diff --git a/contrib/devtools/clang-format-diff.py b/contrib/devtools/clang-format-diff.py index f322b3a880..98eee67f43 100755 --- a/contrib/devtools/clang-format-diff.py +++ b/contrib/devtools/clang-format-diff.py @@ -106,7 +106,7 @@ def main(): filename = None lines_by_file = {} for line in sys.stdin: - match = re.search('^\+\+\+\ (.*?/){%s}(\S*)' % args.p, line) + match = re.search(r'^\+\+\+\ (.*?/){%s}(\S*)' % args.p, line) if match: filename = match.group(2) if filename is None: @@ -119,7 +119,7 @@ def main(): if not re.match('^%s$' % args.iregex, filename, re.IGNORECASE): continue - match = re.search('^@@.*\+(\d+)(,(\d+))?', line) + match = re.search(r'^@@.*\+(\d+)(,(\d+))?', line) if match: start_line = int(match.group(1)) line_count = 1 diff --git a/contrib/devtools/copyright_header.py b/contrib/devtools/copyright_header.py index 827cf871b3..784ec186b5 100755 --- a/contrib/devtools/copyright_header.py +++ b/contrib/devtools/copyright_header.py @@ -41,8 +41,7 @@ def applies_to_file(filename): for excluded_dir in EXCLUDE_DIRS: if filename.startswith(excluded_dir): return False - return ((EXCLUDE_COMPILED.match(filename) is None) and - (INCLUDE_COMPILED.match(filename) is not None)) + return ((EXCLUDE_COMPILED.match(filename) is None) and (INCLUDE_COMPILED.match(filename) is not None)) ################################################################################ # obtain list of files in repo according to INCLUDE and EXCLUDE @@ -71,7 +70,7 @@ def get_filenames_to_examine(base_directory): ################################################################################ -COPYRIGHT_WITH_C = 'Copyright \(c\)' +COPYRIGHT_WITH_C = 'Copyright (c)' COPYRIGHT_WITHOUT_C = 'Copyright' ANY_COPYRIGHT_STYLE = '(%s|%s)' % (COPYRIGHT_WITH_C, COPYRIGHT_WITHOUT_C) @@ -90,8 +89,8 @@ def compile_copyright_regex(copyright_style, year_style, name): EXPECTED_HOLDER_NAMES = [ "Satoshi Nakamoto\n", "The Bitcoin Core developers\n", - "BitPay Inc\.\n", - "University of Illinois at Urbana-Champaign\.\n", + "BitPay Inc.\n", + "University of Illinois at Urbana-Champaign.\n", "Pieter Wuille\n", "Wladimir J. van der Laan\n", "Jeff Garzik\n", @@ -330,7 +329,7 @@ def write_file_lines(filename, file_lines): # update header years execution ################################################################################ -COPYRIGHT = 'Copyright \(c\)' +COPYRIGHT = 'Copyright (c)' YEAR = "20[0-9][0-9]" YEAR_RANGE = '(%s)(-%s)?' % (YEAR, YEAR) HOLDER = 'The Bitcoin Core developers' @@ -369,9 +368,7 @@ def create_updated_copyright_line(line, last_git_change_year): start_year, end_year = parse_year_range(year_range) if end_year == last_git_change_year: return line - return (before_copyright + copyright_splitter + - year_range_to_str(start_year, last_git_change_year) + ' ' + - ' '.join(space_split[1:])) + return (before_copyright + copyright_splitter + year_range_to_str(start_year, last_git_change_year) + ' ' + ' '.join(space_split[1:])) def update_updatable_copyright(filename): file_lines = read_file_lines(filename) diff --git a/contrib/devtools/optimize-pngs.py b/contrib/devtools/optimize-pngs.py index 13aeaa164a..461d46f69c 100755 --- a/contrib/devtools/optimize-pngs.py +++ b/contrib/devtools/optimize-pngs.py @@ -44,8 +44,8 @@ def content_hash(filename): try: subprocess.call([pngcrush, "-brute", "-ow", "-rem", "gAMA", "-rem", "cHRM", "-rem", "iCCP", "-rem", "sRGB", "-rem", "alla", "-rem", "text", file_path], - stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) - except: + stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + except FileNotFoundError: print("pngcrush is not installed, aborting...") sys.exit(0) diff --git a/contrib/devtools/security-check.py b/contrib/devtools/security-check.py index c507a1b660..8e390b20e9 100755 --- a/contrib/devtools/security-check.py +++ b/contrib/devtools/security-check.py @@ -153,7 +153,7 @@ def check_PE_HIGH_ENTROPY_VA(executable): if arch == 'i386:x86-64': reqbits = IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA else: # Unnecessary on 32-bit - assert(arch == 'i386') + assert (arch == 'i386') reqbits = 0 return (bits & reqbits) == reqbits diff --git a/contrib/devtools/symbol-check.py b/contrib/devtools/symbol-check.py index be80e15e44..b0edbb5a27 100755 --- a/contrib/devtools/symbol-check.py +++ b/contrib/devtools/symbol-check.py @@ -141,7 +141,7 @@ def read_libraries(filename): for line in stdout.splitlines(): tokens = line.split() if len(tokens)>2 and tokens[1] == '(NEEDED)': - match = re.match('^Shared library: \[(.*)\]$', ' '.join(tokens[2:])) + match = re.match(r'^Shared library: \[(.*)\]$', ' '.join(tokens[2:])) if match: libraries.append(match.group(1)) else: diff --git a/contrib/linearize/linearize-data.py b/contrib/linearize/linearize-data.py index bd7b49a563..1693a4bd04 100755 --- a/contrib/linearize/linearize-data.py +++ b/contrib/linearize/linearize-data.py @@ -29,8 +29,7 @@ def uint32(x): return x & 0xffffffff def bytereverse(x): - return uint32(( ((x) << 24) | (((x) << 8) & 0x00ff0000) | - (((x) >> 8) & 0x0000ff00) | ((x) >> 24) )) + return uint32(( ((x) << 24) | (((x) << 8) & 0x00ff0000) | (((x) >> 8) & 0x0000ff00) | ((x) >> 24) )) def bufreverse(in_buf): out_words = [] @@ -263,12 +262,12 @@ def run(self): f = open(sys.argv[1], encoding="utf8") for line in f: # skip comment lines - m = re.search('^\s*#', line) + m = re.search(r'^\s*#', line) if m: continue # parse key=value lines - m = re.search('^(\w+)\s*=\s*(\S.*)$', line) + m = re.search(r'^(\w+)\s*=\s*(\S.*)$', line) if m is None: continue settings[m.group(1)] = m.group(2) diff --git a/contrib/linearize/linearize-hashes.py b/contrib/linearize/linearize-hashes.py index 2abf75e8b6..0e5600ca41 100755 --- a/contrib/linearize/linearize-hashes.py +++ b/contrib/linearize/linearize-hashes.py @@ -83,7 +83,7 @@ def get_block_hashes(settings, max_blocks_per_call=10000): if rpc.response_is_error(resp_obj): print('JSON-RPC: error at height', height+x, ': ', resp_obj['error'], file=sys.stderr) sys.exit(1) - assert(resp_obj['id'] == x) # assume replies are in-sequence + assert (resp_obj['id'] == x) # assume replies are in-sequence if settings['rev_hash_bytes'] == 'true': resp_obj['result'] = hex_switchEndian(resp_obj['result']) print(resp_obj['result']) @@ -106,12 +106,12 @@ def get_rpc_cookie(): f = open(sys.argv[1], encoding="utf8") for line in f: # skip comment lines - m = re.search('^\s*#', line) + m = re.search(r'^\s*#', line) if m: continue # parse key=value lines - m = re.search('^(\w+)\s*=\s*(\S.*)$', line) + m = re.search(r'^(\w+)\s*=\s*(\S.*)$', line) if m is None: continue settings[m.group(1)] = m.group(2) diff --git a/contrib/seeds/generate-seeds.py b/contrib/seeds/generate-seeds.py index 2637364c13..53f2a508a3 100755 --- a/contrib/seeds/generate-seeds.py +++ b/contrib/seeds/generate-seeds.py @@ -61,13 +61,13 @@ def name_to_ipv6(addr): if i == 0 or i == (len(addr)-1): # skip empty component at beginning or end continue x += 1 # :: skips to suffix - assert(x < 2) + assert (x < 2) else: # two bytes per component val = int(comp, 16) sub[x].append(val >> 8) sub[x].append(val & 0xff) nullbytes = 16 - len(sub[0]) - len(sub[1]) - assert((x == 0 and nullbytes == 0) or (x == 1 and nullbytes > 0)) + assert ((x == 0 and nullbytes == 0) or (x == 1 and nullbytes > 0)) return bytearray(sub[0] + ([0] * nullbytes) + sub[1]) elif addr.startswith('0x'): # IPv4-in-little-endian return pchIPv4 + bytearray(reversed(a2b_hex(addr[2:]))) @@ -75,7 +75,7 @@ def name_to_ipv6(addr): raise ValueError('Could not parse address %s' % addr) def parse_spec(s, defaultport): - match = re.match('\[([0-9a-fA-F:]+)\](?::([0-9]+))?$', s) + match = re.match(r'\[([0-9a-fA-F:]+)\](?::([0-9]+))?$', s) if match: # ipv6 host = match.group(1) port = match.group(2) diff --git a/contrib/seeds/makeseeds.py b/contrib/seeds/makeseeds.py index 71eead14dc..15aa5d6da6 100755 --- a/contrib/seeds/makeseeds.py +++ b/contrib/seeds/makeseeds.py @@ -139,7 +139,7 @@ def filterbyasn(ips, max_per_asn, max_total): continue asn_count[asn] += 1 result.append(ip) - except: + except ModuleNotFoundError: sys.stderr.write('ERR: Could not resolve ASN for "' + ip['ip'] + '"\n') # Add back Onions diff --git a/contrib/testgen/base58.py b/contrib/testgen/base58.py index 2253cfc31a..12d618f573 100644 --- a/contrib/testgen/base58.py +++ b/contrib/testgen/base58.py @@ -107,7 +107,7 @@ def get_bcaddress_version(strAddress): if __name__ == '__main__': # Test case (from http://gitorious.org/bitcoin/python-base58.git) - assert get_bcaddress_version('15VjRaDX9zpbA8LVnbrCAFzrVzN7ixHNsC') is 0 + assert get_bcaddress_version('15VjRaDX9zpbA8LVnbrCAFzrVzN7ixHNsC') == 0 _ohai = 'o hai'.encode('ascii') _tmp = b58encode(_ohai) assert _tmp == 'DYB3oMS' diff --git a/test/README.md b/test/README.md index 11e39d7cff..fb1a1b5b68 100644 --- a/test/README.md +++ b/test/README.md @@ -6,10 +6,10 @@ etc. This directory contains the following sets of tests: - [functional](/test/functional) which test the functionality of -defid and defi-qt by interacting with them through the RPC and P2P -interfaces. + defid and defi-qt by interacting with them through the RPC and P2P + interfaces. - [util](/test/util) which tests the defi utilities, currently only -defi-tx. + defi-tx. - [lint](/test/lint/) which perform various static analysis checks. The util tests are run as part of `make check` target. The functional @@ -17,8 +17,7 @@ tests and lint scripts can be run as explained in the sections below. # Running tests locally -Before tests can be run locally, DeFi Blockchain must be built. See the [building instructions](/doc#building) for help. - +Before tests can be run locally, DeFi Blockchain must be built. See the [building instructions](/doc#building) for help. ### Functional tests @@ -119,7 +118,6 @@ or pkill -9 defid ``` - ##### Data directory cache A pre-mined blockchain with 200 blocks is generated the first time a diff --git a/test/functional/README.md b/test/functional/README.md index d832a3cd38..a99aeea657 100644 --- a/test/functional/README.md +++ b/test/functional/README.md @@ -23,7 +23,8 @@ don't have test cases for. - The oldest supported Python version is specified in [doc/dependencies.md](/doc/dependencies.md). Consider using [pyenv](https://github.com/pyenv/pyenv), which checks [.python-version](/.python-version), to prevent accidentally introducing modern syntax from an unsupported Python version. - The Travis linter also checks this, but [possibly not in all cases](https://github.com/bitcoin/bitcoin/pull/14884#discussion_r239585126). + The Travis linter also checks this, + but [possibly not in all cases](https://github.com/bitcoin/bitcoin/pull/14884#discussion_r239585126). - See [the python lint script](/test/lint/lint-python.sh) that checks for violations that could lead to bugs and issues in the test code. - Avoid wildcard imports @@ -46,7 +47,8 @@ don't have test cases for. - `tool` for tests for tools, eg `tool_wallet.py` - `wallet` for tests for wallet features, eg `wallet_keypool.py` - use an underscore to separate words - - exception: for tests for specific RPCs or command line options which don't include underscores, name the test after the exact RPC or argument name, eg `rpc_decodescript.py`, not `rpc_decode_script.py` + - exception: for tests for specific RPCs or command line options which don't include underscores, name the test + after the exact RPC or argument name, eg `rpc_decodescript.py`, not `rpc_decode_script.py` - Don't use the redundant word `test` in the name, eg `interface_zmq.py`, not `interface_zmq_test.py` #### General test-writing advice @@ -83,45 +85,53 @@ P2P messages. These can be found in the following source files: #### Using the P2P interface - `messages.py` contains all the definitions for objects that pass -over the network (`CBlock`, `CTransaction`, etc, along with the network-level -wrappers for them, `msg_block`, `msg_tx`, etc). + over the network (`CBlock`, `CTransaction`, etc, along with the network-level + wrappers for them, `msg_block`, `msg_tx`, etc). - P2P tests have two threads. One thread handles all network communication -with the defid(s) being tested in a callback-based event loop; the other -implements the test logic. + with the defid(s) being tested in a callback-based event loop; the other + implements the test logic. - `P2PConnection` is the class used to connect to a defid. `P2PInterface` -contains the higher level logic for processing P2P payloads and connecting to -the DeFi Blockchain node application logic. For custom behaviour, subclass the -P2PInterface object and override the callback methods. + contains the higher level logic for processing P2P payloads and connecting to + the DeFi Blockchain node application logic. For custom behaviour, subclass the + P2PInterface object and override the callback methods. - Can be used to write tests where specific P2P protocol behavior is tested. -Examples tests are `p2p_unrequested_blocks.py`, `p2p_compactblocks.py`. + Examples tests are `p2p_unrequested_blocks.py`, `p2p_compactblocks.py`. ### test-framework modules #### [test_framework/authproxy.py](test_framework/authproxy.py) + Taken from the [python-bitcoinrpc repository](https://github.com/jgarzik/python-bitcoinrpc). #### [test_framework/test_framework.py](test_framework/test_framework.py) + Base class for functional tests. #### [test_framework/util.py](test_framework/util.py) + Generally useful functions. #### [test_framework/mininode.py](test_framework/mininode.py) + Basic code to support P2P connectivity to a defid. #### [test_framework/script.py](test_framework/script.py) + Utilities for manipulating transaction scripts (originally from python-bitcoinlib) #### [test_framework/key.py](test_framework/key.py) + Wrapper around OpenSSL EC_Key (originally from python-bitcoinlib) #### [test_framework/bignum.py](test_framework/bignum.py) + Helpers for script.py #### [test_framework/blocktools.py](test_framework/blocktools.py) + Helper functions for creating blocks and transactions. ### Benchmarking with perf diff --git a/test/functional/combine_logs.py b/test/functional/combine_logs.py index f155570686..9892791ee8 100755 --- a/test/functional/combine_logs.py +++ b/test/functional/combine_logs.py @@ -28,6 +28,7 @@ LogEvent = namedtuple('LogEvent', ['timestamp', 'source', 'event']) + def main(): """Main function. Parses args, reads the log files and renders them as text or html.""" parser = argparse.ArgumentParser( @@ -36,8 +37,10 @@ def main(): 'testdir', nargs='?', default='', help=('temporary test directory to combine logs from. ' 'Defaults to the most recent')) - parser.add_argument('-c', '--color', dest='color', action='store_true', help='outputs the combined log with events colored by source (requires posix terminal colors. Use less -r for viewing)') - parser.add_argument('--html', dest='html', action='store_true', help='outputs the combined log as html. Requires jinja2. pip install jinja2') + parser.add_argument('-c', '--color', dest='color', action='store_true', + help='outputs the combined log with events colored by source (requires posix terminal colors. Use less -r for viewing)') + parser.add_argument('--html', dest='html', action='store_true', + help='outputs the combined log as html. Requires jinja2. pip install jinja2') args = parser.parse_args() if args.html and args.color: @@ -81,7 +84,7 @@ def read_logs(tmp_dir): chain = glob.glob("{}/node0/*/debug.log".format(tmp_dir)) if chain: chain = chain[0] # pick the first one if more than one chain was found (should never happen) - chain = re.search('node0/(.+?)/debug\.log$', chain).group(1) # extract the chain name + chain = re.search(r'node0/(.+?)/debug\.log$', chain).group(1) # extract the chain name else: chain = 'regtest' # fallback to regtest (should only happen when none exists) @@ -125,9 +128,9 @@ def join_tmp(basename): def is_valid_test_tmpdir(basename): fullpath = join_tmp(basename) return ( - os.path.isdir(fullpath) - and basename.startswith(TMPDIR_PREFIX) - and os.access(fullpath, os.R_OK) + os.path.isdir(fullpath) + and basename.startswith(TMPDIR_PREFIX) + and os.access(fullpath, os.R_OK) ) testdir_paths = [ @@ -190,8 +193,8 @@ def print_logs_html(log_events): print("jinja2 not found. Try `pip install jinja2`") sys.exit(1) print(jinja2.Environment(loader=jinja2.FileSystemLoader('./')) - .get_template('combined_log_template.html') - .render(title="Combined Logs from testcase", log_events=[event._asdict() for event in log_events])) + .get_template('combined_log_template.html') + .render(title="Combined Logs from testcase", log_events=[event._asdict() for event in log_events])) if __name__ == '__main__': diff --git a/test/functional/combined_log_template.html b/test/functional/combined_log_template.html index c0b854b080..33c8da2a02 100644 --- a/test/functional/combined_log_template.html +++ b/test/functional/combined_log_template.html @@ -6,25 +6,32 @@ list-style-type: none; font-family: monospace; } + li { border: 1px solid slategray; margin-bottom: 1px; } + li:hover { filter: brightness(85%); } + li.log-test { background-color: cyan; } + li.log-node0 { background-color: lightblue; } + li.log-node1 { background-color: lightgreen; } + li.log-node2 { background-color: lightsalmon; } + li.log-node3 { background-color: lightyellow; } @@ -32,9 +39,9 @@ diff --git a/test/functional/create_cache.py b/test/functional/create_cache.py index 2ca5e85572..e02628c333 100755 --- a/test/functional/create_cache.py +++ b/test/functional/create_cache.py @@ -11,6 +11,7 @@ from test_framework.test_framework import DefiTestFramework + class CreateCache(DefiTestFramework): # Test network and test nodes are not required: @@ -24,5 +25,6 @@ def setup_network(self): def run_test(self): pass + if __name__ == '__main__': CreateCache().main() diff --git a/test/functional/data/rpc_psbt.json b/test/functional/data/rpc_psbt.json index 57f2608ee9..9af3fcc126 100644 --- a/test/functional/data/rpc_psbt.json +++ b/test/functional/data/rpc_psbt.json @@ -1,131 +1,131 @@ { - "invalid" : [ - "AgAAAAEmgXE3Ht/yhek3re6ks3t4AAwFZsuzrWRkFxPKQhcb9gAAAABqRzBEAiBwsiRRI+a/R01gxbUMBD1MaRpdJDXwmjSnZiqdwlF5CgIgATKcqdrPKAvfMHQOwDkEIkIsgctFg5RXrrdvwS7dlbMBIQJlfRGNM1e44PTCzUbbezn22cONmnCry5st5dyNv+TOMf7///8C09/1BQAAAAAZdqkU0MWZA8W6woaHYOkP1SGkZlqnZSCIrADh9QUAAAAAF6kUNUXm4zuDLEcFDyTT7rk8nAOUi8eHsy4TAA==", - "cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAA==", - "cHNidP8BAP0KAQIAAAACqwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QAAAAAakcwRAIgR1lmF5fAGwNrJZKJSGhiGDR9iYZLcZ4ff89X0eURZYcCIFMJ6r9Wqk2Ikf/REf3xM286KdqGbX+EhtdVRs7tr5MZASEDXNxh/HupccC1AaZGoqg7ECy0OIEhfKaC3Ibi1z+ogpL+////qwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QBAAAAAP7///8CYDvqCwAAAAAZdqkUdopAu9dAy+gdmI5x3ipNXHE5ax2IrI4kAAAAAAAAGXapFG9GILVT+glechue4O/p+gOcykWXiKwAAAAAAAABASAA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHhwEEFgAUhdE1N/LiZUBaNNuvqePdoB+4IwgAAAA=", - "cHNidP8AAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAA==", - "cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAQA/AgAAAAH//////////////////////////////////////////wAAAAAA/////wEAAAAAAAAAAANqAQAAAAAAAAAA", - "cHNidP8CAAFVAgAAAAEnmiMjpd+1H8RfIg+liw/BPh4zQnkqhdfjbNYzO1y8OQAAAAAA/////wGgWuoLAAAAABl2qRT/6cAGEJfMO2NvLLBGD6T8Qn0rRYisAAAAAAABASCVXuoLAAAAABepFGNFIA9o0YnhrcDfHE0W6o8UwNvrhyICA7E0HMunaDtq9PEjjNbpfnFn1Wn6xH8eSNR1QYRDVb1GRjBDAiAEJLWO/6qmlOFVnqXJO7/UqJBkIkBVzfBwtncUaUQtBwIfXI6w/qZRbWC4rLM61k7eYOh4W/s6qUuZvfhhUduamgEBBCIAIHcf0YrUWWZt1J89Vk49vEL0yEd042CtoWgWqO1IjVaBAQVHUiEDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUYhA95V0eHayAXj+KWMH7+blMAvPbqv4Sf+/KSZXyb4IIO9Uq4iBgOxNBzLp2g7avTxI4zW6X5xZ9Vp+sR/HkjUdUGEQ1W9RhC0prpnAAAAgAAAAIAEAACAIgYD3lXR4drIBeP4pYwfv5uUwC89uq/hJ/78pJlfJvggg70QtKa6ZwAAAIAAAACABQAAgAAA", - "cHNidP8BAFUCAAAAASeaIyOl37UfxF8iD6WLD8E+HjNCeSqF1+Ns1jM7XLw5AAAAAAD/////AaBa6gsAAAAAGXapFP/pwAYQl8w7Y28ssEYPpPxCfStFiKwAAAAAAAIBACCVXuoLAAAAABepFGNFIA9o0YnhrcDfHE0W6o8UwNvrhyICA7E0HMunaDtq9PEjjNbpfnFn1Wn6xH8eSNR1QYRDVb1GRjBDAiAEJLWO/6qmlOFVnqXJO7/UqJBkIkBVzfBwtncUaUQtBwIfXI6w/qZRbWC4rLM61k7eYOh4W/s6qUuZvfhhUduamgEBBCIAIHcf0YrUWWZt1J89Vk49vEL0yEd042CtoWgWqO1IjVaBAQVHUiEDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUYhA95V0eHayAXj+KWMH7+blMAvPbqv4Sf+/KSZXyb4IIO9Uq4iBgOxNBzLp2g7avTxI4zW6X5xZ9Vp+sR/HkjUdUGEQ1W9RhC0prpnAAAAgAAAAIAEAACAIgYD3lXR4drIBeP4pYwfv5uUwC89uq/hJ/78pJlfJvggg70QtKa6ZwAAAIAAAACABQAAgAAA", - "cHNidP8BAFUCAAAAASeaIyOl37UfxF8iD6WLD8E+HjNCeSqF1+Ns1jM7XLw5AAAAAAD/////AaBa6gsAAAAAGXapFP/pwAYQl8w7Y28ssEYPpPxCfStFiKwAAAAAAAEBIJVe6gsAAAAAF6kUY0UgD2jRieGtwN8cTRbqjxTA2+uHIQIDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUYwQwIgBCS1jv+qppThVZ6lyTu/1KiQZCJAVc3wcLZ3FGlELQcCH1yOsP6mUW1guKyzOtZO3mDoeFv7OqlLmb34YVHbmpoBAQQiACB3H9GK1FlmbdSfPVZOPbxC9MhHdONgraFoFqjtSI1WgQEFR1IhA7E0HMunaDtq9PEjjNbpfnFn1Wn6xH8eSNR1QYRDVb1GIQPeVdHh2sgF4/iljB+/m5TALz26r+En/vykmV8m+CCDvVKuIgYDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUYQtKa6ZwAAAIAAAACABAAAgCIGA95V0eHayAXj+KWMH7+blMAvPbqv4Sf+/KSZXyb4IIO9ELSmumcAAACAAAAAgAUAAIAAAA==", - "cHNidP8BAFUCAAAAASeaIyOl37UfxF8iD6WLD8E+HjNCeSqF1+Ns1jM7XLw5AAAAAAD/////AaBa6gsAAAAAGXapFP/pwAYQl8w7Y28ssEYPpPxCfStFiKwAAAAAAAEBIJVe6gsAAAAAF6kUY0UgD2jRieGtwN8cTRbqjxTA2+uHIgIDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUZGMEMCIAQktY7/qqaU4VWepck7v9SokGQiQFXN8HC2dxRpRC0HAh9cjrD+plFtYLisszrWTt5g6Hhb+zqpS5m9+GFR25qaAQIEACIAIHcf0YrUWWZt1J89Vk49vEL0yEd042CtoWgWqO1IjVaBAQVHUiEDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUYhA95V0eHayAXj+KWMH7+blMAvPbqv4Sf+/KSZXyb4IIO9Uq4iBgOxNBzLp2g7avTxI4zW6X5xZ9Vp+sR/HkjUdUGEQ1W9RhC0prpnAAAAgAAAAIAEAACAIgYD3lXR4drIBeP4pYwfv5uUwC89uq/hJ/78pJlfJvggg70QtKa6ZwAAAIAAAACABQAAgAAA", - "cHNidP8BAFUCAAAAASeaIyOl37UfxF8iD6WLD8E+HjNCeSqF1+Ns1jM7XLw5AAAAAAD/////AaBa6gsAAAAAGXapFP/pwAYQl8w7Y28ssEYPpPxCfStFiKwAAAAAAAEBIJVe6gsAAAAAF6kUY0UgD2jRieGtwN8cTRbqjxTA2+uHIgIDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUZGMEMCIAQktY7/qqaU4VWepck7v9SokGQiQFXN8HC2dxRpRC0HAh9cjrD+plFtYLisszrWTt5g6Hhb+zqpS5m9+GFR25qaAQEEIgAgdx/RitRZZm3Unz1WTj28QvTIR3TjYK2haBao7UiNVoECBQBHUiEDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUYhA95V0eHayAXj+KWMH7+blMAvPbqv4Sf+/KSZXyb4IIO9Uq4iBgOxNBzLp2g7avTxI4zW6X5xZ9Vp+sR/HkjUdUGEQ1W9RhC0prpnAAAAgAAAAIAEAACAIgYD3lXR4drIBeP4pYwfv5uUwC89uq/hJ/78pJlfJvggg70QtKa6ZwAAAIAAAACABQAAgAAA", - "cHNidP8BAFUCAAAAASeaIyOl37UfxF8iD6WLD8E+HjNCeSqF1+Ns1jM7XLw5AAAAAAD/////AaBa6gsAAAAAGXapFP/pwAYQl8w7Y28ssEYPpPxCfStFiKwAAAAAAAEBIJVe6gsAAAAAF6kUY0UgD2jRieGtwN8cTRbqjxTA2+uHIgIDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUZGMEMCIAQktY7/qqaU4VWepck7v9SokGQiQFXN8HC2dxRpRC0HAh9cjrD+plFtYLisszrWTt5g6Hhb+zqpS5m9+GFR25qaAQEEIgAgdx/RitRZZm3Unz1WTj28QvTIR3TjYK2haBao7UiNVoEBBUdSIQOxNBzLp2g7avTxI4zW6X5xZ9Vp+sR/HkjUdUGEQ1W9RiED3lXR4drIBeP4pYwfv5uUwC89uq/hJ/78pJlfJvggg71SriEGA7E0HMunaDtq9PEjjNbpfnFn1Wn6xH8eSNR1QYRDVb0QtKa6ZwAAAIAAAACABAAAgCIGA95V0eHayAXj+KWMH7+blMAvPbqv4Sf+/KSZXyb4IIO9ELSmumcAAACAAAAAgAUAAIAAAA==", - "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAIAALsCAAAAAarXOTEBi9JfhK5AC2iEi+CdtwbqwqwYKYur7nGrZW+LAAAAAEhHMEQCIFj2/HxqM+GzFUjUgcgmwBW9MBNarULNZ3kNq2bSrSQ7AiBKHO0mBMZzW2OT5bQWkd14sA8MWUL7n3UYVvqpOBV9ugH+////AoDw+gIAAAAAF6kUD7lGNCFpa4LIM68kHHjBfdveSTSH0PIKJwEAAAAXqRQpynT4oI+BmZQoGFyXtdhS5AY/YYdlAAAAAQfaAEcwRAIgdAGK1BgAl7hzMjwAFXILNoTMgSOJEEjn282bVa1nnJkCIHPTabdA4+tT3O+jOCPIBwUUylWn3ZVE8VfBZ5EyYRGMAUgwRQIhAPYQOLMI3B2oZaNIUnRvAVdyk0IIxtJEVDk82ZvfIhd3AiAFbmdaZ1ptCgK4WxTl4pB02KJam1dgvqKBb2YZEKAG6gFHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq4AAQEgAMLrCwAAAAAXqRS39fr0Dj1ApaRZsds1NfK3L6kh6IcBByMiACCMI1MXN0O1ld+0oHtyuo5C43l9p06H/n2ddJfjsgKJAwEI2gQARzBEAiBi63pVYQenxz9FrEq1od3fb3B1+xJ1lpp/OD7/94S8sgIgDAXbt0cNvy8IVX3TVscyXB7TCRPpls04QJRdsSIo2l8BRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBR1IhAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcIQI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc1KuACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA=", - "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAACBwDaAEcwRAIgdAGK1BgAl7hzMjwAFXILNoTMgSOJEEjn282bVa1nnJkCIHPTabdA4+tT3O+jOCPIBwUUylWn3ZVE8VfBZ5EyYRGMAUgwRQIhAPYQOLMI3B2oZaNIUnRvAVdyk0IIxtJEVDk82ZvfIhd3AiAFbmdaZ1ptCgK4WxTl4pB02KJam1dgvqKBb2YZEKAG6gFHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq4AAQEgAMLrCwAAAAAXqRS39fr0Dj1ApaRZsds1NfK3L6kh6IcBByMiACCMI1MXN0O1ld+0oHtyuo5C43l9p06H/n2ddJfjsgKJAwEI2gQARzBEAiBi63pVYQenxz9FrEq1od3fb3B1+xJ1lpp/OD7/94S8sgIgDAXbt0cNvy8IVX3TVscyXB7TCRPpls04QJRdsSIo2l8BRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBR1IhAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcIQI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc1KuACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA=", - "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAABB9oARzBEAiB0AYrUGACXuHMyPAAVcgs2hMyBI4kQSOfbzZtVrWecmQIgc9Npt0Dj61Pc76M4I8gHBRTKVafdlUTxV8FnkTJhEYwBSDBFAiEA9hA4swjcHahlo0hSdG8BV3KTQgjG0kRUOTzZm98iF3cCIAVuZ1pnWm0KArhbFOXikHTYolqbV2C+ooFvZhkQoAbqAUdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSrgABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohwEHIyIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAggA2gQARzBEAiBi63pVYQenxz9FrEq1od3fb3B1+xJ1lpp/OD7/94S8sgIgDAXbt0cNvy8IVX3TVscyXB7TCRPpls04QJRdsSIo2l8BRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBR1IhAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcIQI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc1KuACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA=", - "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAABB9oARzBEAiB0AYrUGACXuHMyPAAVcgs2hMyBI4kQSOfbzZtVrWecmQIgc9Npt0Dj61Pc76M4I8gHBRTKVafdlUTxV8FnkTJhEYwBSDBFAiEA9hA4swjcHahlo0hSdG8BV3KTQgjG0kRUOTzZm98iF3cCIAVuZ1pnWm0KArhbFOXikHTYolqbV2C+ooFvZhkQoAbqAUdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSrgABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohwEHIyIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAQjaBABHMEQCIGLrelVhB6fHP0WsSrWh3d9vcHX7EnWWmn84Pv/3hLyyAiAMBdu3Rw2/LwhVfdNWxzJcHtMJE+mWzThAlF2xIijaXwFHMEQCIGX0W6WZi1mif/4ae+0BavHx+Q1Us6qPdFCqX1aiUQO9AiB/ckcDrR7blmgLKEtW1P/LiPf7dZ6rvgiqMPKbhROD0gFHUiEDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwhAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zUq4AIQIDqaTDf1mW06ol26xrVwrwZQOUSSlCRgs1R1PtnuylhxDZDGpPAAAAgAAAAIAEAACAACICAn9jmXV9Lv9VoTatAsaEsYOLZVbl8bazQoKpS2tQBRCWENkMak8AAACAAAAAgAUAAIAA", - "cHNidP8BAHMCAAAAATAa6YblFqHsisW0vGVz0y+DtGXiOtdhZ9aLOOcwtNvbAAAAAAD/////AnR7AQAAAAAAF6kUA6oXrogrXQ1Usl1jEE5P/s57nqKHYEOZOwAAAAAXqRS5IbG6b3IuS/qDtlV6MTmYakLsg4cAAAAAAAEBHwDKmjsAAAAAFgAU0tlLZK4IWH7vyO6xh8YB6Tn5A3wCAwABAAAAAAEAFgAUYunpgv/zTdgjlhAxawkM0qO3R8sAAQAiACCHa62DLx0WgBXtQSMqnqZaGBXZ7xPA74dZ9ktbKyeKZQEBJVEhA7fOI6AcW0vwCmQlN836uzFbZoMyhnR471EwnSvVf4qHUa4A", - "cHNidP8BAHMCAAAAATAa6YblFqHsisW0vGVz0y+DtGXiOtdhZ9aLOOcwtNvbAAAAAAD/////AnR7AQAAAAAAF6kUA6oXrogrXQ1Usl1jEE5P/s57nqKHYEOZOwAAAAAXqRS5IbG6b3IuS/qDtlV6MTmYakLsg4cAAAAAAAEBHwDKmjsAAAAAFgAU0tlLZK4IWH7vyO6xh8YB6Tn5A3wAAgAAFgAUYunpgv/zTdgjlhAxawkM0qO3R8sAAQAiACCHa62DLx0WgBXtQSMqnqZaGBXZ7xPA74dZ9ktbKyeKZQEBJVEhA7fOI6AcW0vwCmQlN836uzFbZoMyhnR471EwnSvVf4qHUa4A", - "cHNidP8BAHMCAAAAATAa6YblFqHsisW0vGVz0y+DtGXiOtdhZ9aLOOcwtNvbAAAAAAD/////AnR7AQAAAAAAF6kUA6oXrogrXQ1Usl1jEE5P/s57nqKHYEOZOwAAAAAXqRS5IbG6b3IuS/qDtlV6MTmYakLsg4cAAAAAAAEBHwDKmjsAAAAAFgAU0tlLZK4IWH7vyO6xh8YB6Tn5A3wAAQAWABRi6emC//NN2COWEDFrCQzSo7dHywABACIAIIdrrYMvHRaAFe1BIyqeploYFdnvE8Dvh1n2S1srJ4plIQEAJVEhA7fOI6AcW0vwCmQlN836uzFbZoMyhnR471EwnSvVf4qHUa4A", - "cHNidP8BAHMCAAAAAbiWoY6pOQepFsEGhUPXaulX9rvye2NH+NrdlAHg+WgpAQAAAAD/////AkBLTAAAAAAAF6kUqWwXCcLM5BN2zoNqMNT5qMlIi7+HQEtMAAAAAAAXqRSVF/in2XNxAlN1OSxkyp0z+Wtg2YcAAAAAAAEBIBNssgAAAAAAF6kUamsvautR8hRlMRY6OKNTx03DK96HAQcXFgAUo8u1LWpHprjt/uENAwBpGZD0UH0BCGsCRzBEAiAONfH3DYiw67ZbylrsxCF/XXpVwyWBRgofyRbPslzvwgIgIKCsWw5sHSIPh1icNvcVLZLHWj6NA7Dk+4Os2pOnMbQBIQPGStfYHPtyhpV7zIWtn0Q4GXv5gK1zy/tnJ+cBXu4iiwABABYAFMwmJQEz+HDpBEEabxJ5PogPsqZRAAEAFgAUyCrGc3h3FYCmiIspbv2pSTKZ5jU" - ], - "valid" : [ - "cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAAAA", - "cHNidP8BAKACAAAAAqsJSaCMWvfEm4IS9Bfi8Vqz9cM9zxU4IagTn4d6W3vkAAAAAAD+////qwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QBAAAAAP7///8CYDvqCwAAAAAZdqkUdopAu9dAy+gdmI5x3ipNXHE5ax2IrI4kAAAAAAAAGXapFG9GILVT+glechue4O/p+gOcykWXiKwAAAAAAAEHakcwRAIgR1lmF5fAGwNrJZKJSGhiGDR9iYZLcZ4ff89X0eURZYcCIFMJ6r9Wqk2Ikf/REf3xM286KdqGbX+EhtdVRs7tr5MZASEDXNxh/HupccC1AaZGoqg7ECy0OIEhfKaC3Ibi1z+ogpIAAQEgAOH1BQAAAAAXqRQ1RebjO4MsRwUPJNPuuTycA5SLx4cBBBYAFIXRNTfy4mVAWjTbr6nj3aAfuCMIAAAA", - "cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAQMEAQAAAAAAAA==", - "cHNidP8BAKACAAAAAqsJSaCMWvfEm4IS9Bfi8Vqz9cM9zxU4IagTn4d6W3vkAAAAAAD+////qwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QBAAAAAP7///8CYDvqCwAAAAAZdqkUdopAu9dAy+gdmI5x3ipNXHE5ax2IrI4kAAAAAAAAGXapFG9GILVT+glechue4O/p+gOcykWXiKwAAAAAAAEA3wIAAAABJoFxNx7f8oXpN63upLN7eAAMBWbLs61kZBcTykIXG/YAAAAAakcwRAIgcLIkUSPmv0dNYMW1DAQ9TGkaXSQ18Jo0p2YqncJReQoCIAEynKnazygL3zB0DsA5BCJCLIHLRYOUV663b8Eu3ZWzASECZX0RjTNXuOD0ws1G23s59tnDjZpwq8ubLeXcjb/kzjH+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQEgAOH1BQAAAAAXqRQ1RebjO4MsRwUPJNPuuTycA5SLx4cBBBYAFIXRNTfy4mVAWjTbr6nj3aAfuCMIACICAurVlmh8qAYEPtw94RbN8p1eklfBls0FXPaYyNAr8k6ZELSmumcAAACAAAAAgAIAAIAAIgIDlPYr6d8ZlSxVh3aK63aYBhrSxKJciU9H2MFitNchPQUQtKa6ZwAAAIABAACAAgAAgAA=", - "cHNidP8BAFUCAAAAASeaIyOl37UfxF8iD6WLD8E+HjNCeSqF1+Ns1jM7XLw5AAAAAAD/////AaBa6gsAAAAAGXapFP/pwAYQl8w7Y28ssEYPpPxCfStFiKwAAAAAAAEBIJVe6gsAAAAAF6kUY0UgD2jRieGtwN8cTRbqjxTA2+uHIgIDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUZGMEMCIAQktY7/qqaU4VWepck7v9SokGQiQFXN8HC2dxRpRC0HAh9cjrD+plFtYLisszrWTt5g6Hhb+zqpS5m9+GFR25qaAQEEIgAgdx/RitRZZm3Unz1WTj28QvTIR3TjYK2haBao7UiNVoEBBUdSIQOxNBzLp2g7avTxI4zW6X5xZ9Vp+sR/HkjUdUGEQ1W9RiED3lXR4drIBeP4pYwfv5uUwC89uq/hJ/78pJlfJvggg71SriIGA7E0HMunaDtq9PEjjNbpfnFn1Wn6xH8eSNR1QYRDVb1GELSmumcAAACAAAAAgAQAAIAiBgPeVdHh2sgF4/iljB+/m5TALz26r+En/vykmV8m+CCDvRC0prpnAAAAgAAAAIAFAACAAAA=", - "cHNidP8BACoCAAAAAAFAQg8AAAAAABepFG6Rty1Vk+fUOR4v9E6R6YXDFkHwhwAAAAAAAA==" - ], - "creator" : [ + "invalid": [ + "AgAAAAEmgXE3Ht/yhek3re6ks3t4AAwFZsuzrWRkFxPKQhcb9gAAAABqRzBEAiBwsiRRI+a/R01gxbUMBD1MaRpdJDXwmjSnZiqdwlF5CgIgATKcqdrPKAvfMHQOwDkEIkIsgctFg5RXrrdvwS7dlbMBIQJlfRGNM1e44PTCzUbbezn22cONmnCry5st5dyNv+TOMf7///8C09/1BQAAAAAZdqkU0MWZA8W6woaHYOkP1SGkZlqnZSCIrADh9QUAAAAAF6kUNUXm4zuDLEcFDyTT7rk8nAOUi8eHsy4TAA==", + "cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAA==", + "cHNidP8BAP0KAQIAAAACqwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QAAAAAakcwRAIgR1lmF5fAGwNrJZKJSGhiGDR9iYZLcZ4ff89X0eURZYcCIFMJ6r9Wqk2Ikf/REf3xM286KdqGbX+EhtdVRs7tr5MZASEDXNxh/HupccC1AaZGoqg7ECy0OIEhfKaC3Ibi1z+ogpL+////qwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QBAAAAAP7///8CYDvqCwAAAAAZdqkUdopAu9dAy+gdmI5x3ipNXHE5ax2IrI4kAAAAAAAAGXapFG9GILVT+glechue4O/p+gOcykWXiKwAAAAAAAABASAA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHhwEEFgAUhdE1N/LiZUBaNNuvqePdoB+4IwgAAAA=", + "cHNidP8AAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAA==", + "cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAQA/AgAAAAH//////////////////////////////////////////wAAAAAA/////wEAAAAAAAAAAANqAQAAAAAAAAAA", + "cHNidP8CAAFVAgAAAAEnmiMjpd+1H8RfIg+liw/BPh4zQnkqhdfjbNYzO1y8OQAAAAAA/////wGgWuoLAAAAABl2qRT/6cAGEJfMO2NvLLBGD6T8Qn0rRYisAAAAAAABASCVXuoLAAAAABepFGNFIA9o0YnhrcDfHE0W6o8UwNvrhyICA7E0HMunaDtq9PEjjNbpfnFn1Wn6xH8eSNR1QYRDVb1GRjBDAiAEJLWO/6qmlOFVnqXJO7/UqJBkIkBVzfBwtncUaUQtBwIfXI6w/qZRbWC4rLM61k7eYOh4W/s6qUuZvfhhUduamgEBBCIAIHcf0YrUWWZt1J89Vk49vEL0yEd042CtoWgWqO1IjVaBAQVHUiEDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUYhA95V0eHayAXj+KWMH7+blMAvPbqv4Sf+/KSZXyb4IIO9Uq4iBgOxNBzLp2g7avTxI4zW6X5xZ9Vp+sR/HkjUdUGEQ1W9RhC0prpnAAAAgAAAAIAEAACAIgYD3lXR4drIBeP4pYwfv5uUwC89uq/hJ/78pJlfJvggg70QtKa6ZwAAAIAAAACABQAAgAAA", + "cHNidP8BAFUCAAAAASeaIyOl37UfxF8iD6WLD8E+HjNCeSqF1+Ns1jM7XLw5AAAAAAD/////AaBa6gsAAAAAGXapFP/pwAYQl8w7Y28ssEYPpPxCfStFiKwAAAAAAAIBACCVXuoLAAAAABepFGNFIA9o0YnhrcDfHE0W6o8UwNvrhyICA7E0HMunaDtq9PEjjNbpfnFn1Wn6xH8eSNR1QYRDVb1GRjBDAiAEJLWO/6qmlOFVnqXJO7/UqJBkIkBVzfBwtncUaUQtBwIfXI6w/qZRbWC4rLM61k7eYOh4W/s6qUuZvfhhUduamgEBBCIAIHcf0YrUWWZt1J89Vk49vEL0yEd042CtoWgWqO1IjVaBAQVHUiEDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUYhA95V0eHayAXj+KWMH7+blMAvPbqv4Sf+/KSZXyb4IIO9Uq4iBgOxNBzLp2g7avTxI4zW6X5xZ9Vp+sR/HkjUdUGEQ1W9RhC0prpnAAAAgAAAAIAEAACAIgYD3lXR4drIBeP4pYwfv5uUwC89uq/hJ/78pJlfJvggg70QtKa6ZwAAAIAAAACABQAAgAAA", + "cHNidP8BAFUCAAAAASeaIyOl37UfxF8iD6WLD8E+HjNCeSqF1+Ns1jM7XLw5AAAAAAD/////AaBa6gsAAAAAGXapFP/pwAYQl8w7Y28ssEYPpPxCfStFiKwAAAAAAAEBIJVe6gsAAAAAF6kUY0UgD2jRieGtwN8cTRbqjxTA2+uHIQIDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUYwQwIgBCS1jv+qppThVZ6lyTu/1KiQZCJAVc3wcLZ3FGlELQcCH1yOsP6mUW1guKyzOtZO3mDoeFv7OqlLmb34YVHbmpoBAQQiACB3H9GK1FlmbdSfPVZOPbxC9MhHdONgraFoFqjtSI1WgQEFR1IhA7E0HMunaDtq9PEjjNbpfnFn1Wn6xH8eSNR1QYRDVb1GIQPeVdHh2sgF4/iljB+/m5TALz26r+En/vykmV8m+CCDvVKuIgYDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUYQtKa6ZwAAAIAAAACABAAAgCIGA95V0eHayAXj+KWMH7+blMAvPbqv4Sf+/KSZXyb4IIO9ELSmumcAAACAAAAAgAUAAIAAAA==", + "cHNidP8BAFUCAAAAASeaIyOl37UfxF8iD6WLD8E+HjNCeSqF1+Ns1jM7XLw5AAAAAAD/////AaBa6gsAAAAAGXapFP/pwAYQl8w7Y28ssEYPpPxCfStFiKwAAAAAAAEBIJVe6gsAAAAAF6kUY0UgD2jRieGtwN8cTRbqjxTA2+uHIgIDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUZGMEMCIAQktY7/qqaU4VWepck7v9SokGQiQFXN8HC2dxRpRC0HAh9cjrD+plFtYLisszrWTt5g6Hhb+zqpS5m9+GFR25qaAQIEACIAIHcf0YrUWWZt1J89Vk49vEL0yEd042CtoWgWqO1IjVaBAQVHUiEDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUYhA95V0eHayAXj+KWMH7+blMAvPbqv4Sf+/KSZXyb4IIO9Uq4iBgOxNBzLp2g7avTxI4zW6X5xZ9Vp+sR/HkjUdUGEQ1W9RhC0prpnAAAAgAAAAIAEAACAIgYD3lXR4drIBeP4pYwfv5uUwC89uq/hJ/78pJlfJvggg70QtKa6ZwAAAIAAAACABQAAgAAA", + "cHNidP8BAFUCAAAAASeaIyOl37UfxF8iD6WLD8E+HjNCeSqF1+Ns1jM7XLw5AAAAAAD/////AaBa6gsAAAAAGXapFP/pwAYQl8w7Y28ssEYPpPxCfStFiKwAAAAAAAEBIJVe6gsAAAAAF6kUY0UgD2jRieGtwN8cTRbqjxTA2+uHIgIDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUZGMEMCIAQktY7/qqaU4VWepck7v9SokGQiQFXN8HC2dxRpRC0HAh9cjrD+plFtYLisszrWTt5g6Hhb+zqpS5m9+GFR25qaAQEEIgAgdx/RitRZZm3Unz1WTj28QvTIR3TjYK2haBao7UiNVoECBQBHUiEDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUYhA95V0eHayAXj+KWMH7+blMAvPbqv4Sf+/KSZXyb4IIO9Uq4iBgOxNBzLp2g7avTxI4zW6X5xZ9Vp+sR/HkjUdUGEQ1W9RhC0prpnAAAAgAAAAIAEAACAIgYD3lXR4drIBeP4pYwfv5uUwC89uq/hJ/78pJlfJvggg70QtKa6ZwAAAIAAAACABQAAgAAA", + "cHNidP8BAFUCAAAAASeaIyOl37UfxF8iD6WLD8E+HjNCeSqF1+Ns1jM7XLw5AAAAAAD/////AaBa6gsAAAAAGXapFP/pwAYQl8w7Y28ssEYPpPxCfStFiKwAAAAAAAEBIJVe6gsAAAAAF6kUY0UgD2jRieGtwN8cTRbqjxTA2+uHIgIDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUZGMEMCIAQktY7/qqaU4VWepck7v9SokGQiQFXN8HC2dxRpRC0HAh9cjrD+plFtYLisszrWTt5g6Hhb+zqpS5m9+GFR25qaAQEEIgAgdx/RitRZZm3Unz1WTj28QvTIR3TjYK2haBao7UiNVoEBBUdSIQOxNBzLp2g7avTxI4zW6X5xZ9Vp+sR/HkjUdUGEQ1W9RiED3lXR4drIBeP4pYwfv5uUwC89uq/hJ/78pJlfJvggg71SriEGA7E0HMunaDtq9PEjjNbpfnFn1Wn6xH8eSNR1QYRDVb0QtKa6ZwAAAIAAAACABAAAgCIGA95V0eHayAXj+KWMH7+blMAvPbqv4Sf+/KSZXyb4IIO9ELSmumcAAACAAAAAgAUAAIAAAA==", + "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAIAALsCAAAAAarXOTEBi9JfhK5AC2iEi+CdtwbqwqwYKYur7nGrZW+LAAAAAEhHMEQCIFj2/HxqM+GzFUjUgcgmwBW9MBNarULNZ3kNq2bSrSQ7AiBKHO0mBMZzW2OT5bQWkd14sA8MWUL7n3UYVvqpOBV9ugH+////AoDw+gIAAAAAF6kUD7lGNCFpa4LIM68kHHjBfdveSTSH0PIKJwEAAAAXqRQpynT4oI+BmZQoGFyXtdhS5AY/YYdlAAAAAQfaAEcwRAIgdAGK1BgAl7hzMjwAFXILNoTMgSOJEEjn282bVa1nnJkCIHPTabdA4+tT3O+jOCPIBwUUylWn3ZVE8VfBZ5EyYRGMAUgwRQIhAPYQOLMI3B2oZaNIUnRvAVdyk0IIxtJEVDk82ZvfIhd3AiAFbmdaZ1ptCgK4WxTl4pB02KJam1dgvqKBb2YZEKAG6gFHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq4AAQEgAMLrCwAAAAAXqRS39fr0Dj1ApaRZsds1NfK3L6kh6IcBByMiACCMI1MXN0O1ld+0oHtyuo5C43l9p06H/n2ddJfjsgKJAwEI2gQARzBEAiBi63pVYQenxz9FrEq1od3fb3B1+xJ1lpp/OD7/94S8sgIgDAXbt0cNvy8IVX3TVscyXB7TCRPpls04QJRdsSIo2l8BRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBR1IhAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcIQI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc1KuACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA=", + "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAACBwDaAEcwRAIgdAGK1BgAl7hzMjwAFXILNoTMgSOJEEjn282bVa1nnJkCIHPTabdA4+tT3O+jOCPIBwUUylWn3ZVE8VfBZ5EyYRGMAUgwRQIhAPYQOLMI3B2oZaNIUnRvAVdyk0IIxtJEVDk82ZvfIhd3AiAFbmdaZ1ptCgK4WxTl4pB02KJam1dgvqKBb2YZEKAG6gFHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq4AAQEgAMLrCwAAAAAXqRS39fr0Dj1ApaRZsds1NfK3L6kh6IcBByMiACCMI1MXN0O1ld+0oHtyuo5C43l9p06H/n2ddJfjsgKJAwEI2gQARzBEAiBi63pVYQenxz9FrEq1od3fb3B1+xJ1lpp/OD7/94S8sgIgDAXbt0cNvy8IVX3TVscyXB7TCRPpls04QJRdsSIo2l8BRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBR1IhAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcIQI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc1KuACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA=", + "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAABB9oARzBEAiB0AYrUGACXuHMyPAAVcgs2hMyBI4kQSOfbzZtVrWecmQIgc9Npt0Dj61Pc76M4I8gHBRTKVafdlUTxV8FnkTJhEYwBSDBFAiEA9hA4swjcHahlo0hSdG8BV3KTQgjG0kRUOTzZm98iF3cCIAVuZ1pnWm0KArhbFOXikHTYolqbV2C+ooFvZhkQoAbqAUdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSrgABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohwEHIyIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAggA2gQARzBEAiBi63pVYQenxz9FrEq1od3fb3B1+xJ1lpp/OD7/94S8sgIgDAXbt0cNvy8IVX3TVscyXB7TCRPpls04QJRdsSIo2l8BRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBR1IhAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcIQI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc1KuACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA=", + "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAABB9oARzBEAiB0AYrUGACXuHMyPAAVcgs2hMyBI4kQSOfbzZtVrWecmQIgc9Npt0Dj61Pc76M4I8gHBRTKVafdlUTxV8FnkTJhEYwBSDBFAiEA9hA4swjcHahlo0hSdG8BV3KTQgjG0kRUOTzZm98iF3cCIAVuZ1pnWm0KArhbFOXikHTYolqbV2C+ooFvZhkQoAbqAUdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSrgABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohwEHIyIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAQjaBABHMEQCIGLrelVhB6fHP0WsSrWh3d9vcHX7EnWWmn84Pv/3hLyyAiAMBdu3Rw2/LwhVfdNWxzJcHtMJE+mWzThAlF2xIijaXwFHMEQCIGX0W6WZi1mif/4ae+0BavHx+Q1Us6qPdFCqX1aiUQO9AiB/ckcDrR7blmgLKEtW1P/LiPf7dZ6rvgiqMPKbhROD0gFHUiEDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwhAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zUq4AIQIDqaTDf1mW06ol26xrVwrwZQOUSSlCRgs1R1PtnuylhxDZDGpPAAAAgAAAAIAEAACAACICAn9jmXV9Lv9VoTatAsaEsYOLZVbl8bazQoKpS2tQBRCWENkMak8AAACAAAAAgAUAAIAA", + "cHNidP8BAHMCAAAAATAa6YblFqHsisW0vGVz0y+DtGXiOtdhZ9aLOOcwtNvbAAAAAAD/////AnR7AQAAAAAAF6kUA6oXrogrXQ1Usl1jEE5P/s57nqKHYEOZOwAAAAAXqRS5IbG6b3IuS/qDtlV6MTmYakLsg4cAAAAAAAEBHwDKmjsAAAAAFgAU0tlLZK4IWH7vyO6xh8YB6Tn5A3wCAwABAAAAAAEAFgAUYunpgv/zTdgjlhAxawkM0qO3R8sAAQAiACCHa62DLx0WgBXtQSMqnqZaGBXZ7xPA74dZ9ktbKyeKZQEBJVEhA7fOI6AcW0vwCmQlN836uzFbZoMyhnR471EwnSvVf4qHUa4A", + "cHNidP8BAHMCAAAAATAa6YblFqHsisW0vGVz0y+DtGXiOtdhZ9aLOOcwtNvbAAAAAAD/////AnR7AQAAAAAAF6kUA6oXrogrXQ1Usl1jEE5P/s57nqKHYEOZOwAAAAAXqRS5IbG6b3IuS/qDtlV6MTmYakLsg4cAAAAAAAEBHwDKmjsAAAAAFgAU0tlLZK4IWH7vyO6xh8YB6Tn5A3wAAgAAFgAUYunpgv/zTdgjlhAxawkM0qO3R8sAAQAiACCHa62DLx0WgBXtQSMqnqZaGBXZ7xPA74dZ9ktbKyeKZQEBJVEhA7fOI6AcW0vwCmQlN836uzFbZoMyhnR471EwnSvVf4qHUa4A", + "cHNidP8BAHMCAAAAATAa6YblFqHsisW0vGVz0y+DtGXiOtdhZ9aLOOcwtNvbAAAAAAD/////AnR7AQAAAAAAF6kUA6oXrogrXQ1Usl1jEE5P/s57nqKHYEOZOwAAAAAXqRS5IbG6b3IuS/qDtlV6MTmYakLsg4cAAAAAAAEBHwDKmjsAAAAAFgAU0tlLZK4IWH7vyO6xh8YB6Tn5A3wAAQAWABRi6emC//NN2COWEDFrCQzSo7dHywABACIAIIdrrYMvHRaAFe1BIyqeploYFdnvE8Dvh1n2S1srJ4plIQEAJVEhA7fOI6AcW0vwCmQlN836uzFbZoMyhnR471EwnSvVf4qHUa4A", + "cHNidP8BAHMCAAAAAbiWoY6pOQepFsEGhUPXaulX9rvye2NH+NrdlAHg+WgpAQAAAAD/////AkBLTAAAAAAAF6kUqWwXCcLM5BN2zoNqMNT5qMlIi7+HQEtMAAAAAAAXqRSVF/in2XNxAlN1OSxkyp0z+Wtg2YcAAAAAAAEBIBNssgAAAAAAF6kUamsvautR8hRlMRY6OKNTx03DK96HAQcXFgAUo8u1LWpHprjt/uENAwBpGZD0UH0BCGsCRzBEAiAONfH3DYiw67ZbylrsxCF/XXpVwyWBRgofyRbPslzvwgIgIKCsWw5sHSIPh1icNvcVLZLHWj6NA7Dk+4Os2pOnMbQBIQPGStfYHPtyhpV7zIWtn0Q4GXv5gK1zy/tnJ+cBXu4iiwABABYAFMwmJQEz+HDpBEEabxJ5PogPsqZRAAEAFgAUyCrGc3h3FYCmiIspbv2pSTKZ5jU" + ], + "valid": [ + "cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAAAA", + "cHNidP8BAKACAAAAAqsJSaCMWvfEm4IS9Bfi8Vqz9cM9zxU4IagTn4d6W3vkAAAAAAD+////qwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QBAAAAAP7///8CYDvqCwAAAAAZdqkUdopAu9dAy+gdmI5x3ipNXHE5ax2IrI4kAAAAAAAAGXapFG9GILVT+glechue4O/p+gOcykWXiKwAAAAAAAEHakcwRAIgR1lmF5fAGwNrJZKJSGhiGDR9iYZLcZ4ff89X0eURZYcCIFMJ6r9Wqk2Ikf/REf3xM286KdqGbX+EhtdVRs7tr5MZASEDXNxh/HupccC1AaZGoqg7ECy0OIEhfKaC3Ibi1z+ogpIAAQEgAOH1BQAAAAAXqRQ1RebjO4MsRwUPJNPuuTycA5SLx4cBBBYAFIXRNTfy4mVAWjTbr6nj3aAfuCMIAAAA", + "cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAQMEAQAAAAAAAA==", + "cHNidP8BAKACAAAAAqsJSaCMWvfEm4IS9Bfi8Vqz9cM9zxU4IagTn4d6W3vkAAAAAAD+////qwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QBAAAAAP7///8CYDvqCwAAAAAZdqkUdopAu9dAy+gdmI5x3ipNXHE5ax2IrI4kAAAAAAAAGXapFG9GILVT+glechue4O/p+gOcykWXiKwAAAAAAAEA3wIAAAABJoFxNx7f8oXpN63upLN7eAAMBWbLs61kZBcTykIXG/YAAAAAakcwRAIgcLIkUSPmv0dNYMW1DAQ9TGkaXSQ18Jo0p2YqncJReQoCIAEynKnazygL3zB0DsA5BCJCLIHLRYOUV663b8Eu3ZWzASECZX0RjTNXuOD0ws1G23s59tnDjZpwq8ubLeXcjb/kzjH+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQEgAOH1BQAAAAAXqRQ1RebjO4MsRwUPJNPuuTycA5SLx4cBBBYAFIXRNTfy4mVAWjTbr6nj3aAfuCMIACICAurVlmh8qAYEPtw94RbN8p1eklfBls0FXPaYyNAr8k6ZELSmumcAAACAAAAAgAIAAIAAIgIDlPYr6d8ZlSxVh3aK63aYBhrSxKJciU9H2MFitNchPQUQtKa6ZwAAAIABAACAAgAAgAA=", + "cHNidP8BAFUCAAAAASeaIyOl37UfxF8iD6WLD8E+HjNCeSqF1+Ns1jM7XLw5AAAAAAD/////AaBa6gsAAAAAGXapFP/pwAYQl8w7Y28ssEYPpPxCfStFiKwAAAAAAAEBIJVe6gsAAAAAF6kUY0UgD2jRieGtwN8cTRbqjxTA2+uHIgIDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUZGMEMCIAQktY7/qqaU4VWepck7v9SokGQiQFXN8HC2dxRpRC0HAh9cjrD+plFtYLisszrWTt5g6Hhb+zqpS5m9+GFR25qaAQEEIgAgdx/RitRZZm3Unz1WTj28QvTIR3TjYK2haBao7UiNVoEBBUdSIQOxNBzLp2g7avTxI4zW6X5xZ9Vp+sR/HkjUdUGEQ1W9RiED3lXR4drIBeP4pYwfv5uUwC89uq/hJ/78pJlfJvggg71SriIGA7E0HMunaDtq9PEjjNbpfnFn1Wn6xH8eSNR1QYRDVb1GELSmumcAAACAAAAAgAQAAIAiBgPeVdHh2sgF4/iljB+/m5TALz26r+En/vykmV8m+CCDvRC0prpnAAAAgAAAAIAFAACAAAA=", + "cHNidP8BACoCAAAAAAFAQg8AAAAAABepFG6Rty1Vk+fUOR4v9E6R6YXDFkHwhwAAAAAAAA==" + ], + "creator": [ + { + "inputs": [ { - "inputs" : [ - { - "txid":"75ddabb27b8845f5247975c8a5ba7c6f336c4570708ebe230caf6db5217ae858", - "vout":0 - }, - { - "txid":"1dea7cd05979072a3578cab271c02244ea8a090bbb46aa680a65ecd027048d83", - "vout":1 - } - ], - "outputs" : [ - { - "bcrt1qmpwzkuwsqc9snjvgdt4czhjsnywa5yjdqpxskv":1.49990000 - }, - { - "bcrt1qqzh2ngh97ru8dfvgma25d6r595wcwqy0cee4cc": 1 - } - ], - "result" : "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAAAAAA=" - } - ], - "signer" : [ - { - "privkeys" : [ - "cP53pDbR5WtAD8dYAW9hhTjuvvTVaEiQBdrz9XPrgLBeRFiyCbQr", - "cR6SXDoyfQrcp4piaiHE97Rsgta9mNhGTen9XeonVgwsh4iSgw6d" - ], - "psbt" : "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAABBEdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSriIGApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/ENkMak8AAACAAAAAgAAAAIAiBgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU21xDZDGpPAAAAgAAAAIABAACAAQMEAQAAAAABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohwEEIgAgjCNTFzdDtZXftKB7crqOQuN5fadOh/59nXSX47ICiQMBBUdSIQMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3CECOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNSriIGAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zENkMak8AAACAAAAAgAMAAIAiBgMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3BDZDGpPAAAAgAAAAIACAACAAQMEAQAAAAAiAgOppMN/WZbTqiXbrGtXCvBlA5RJKUJGCzVHU+2e7KWHcRDZDGpPAAAAgAAAAIAEAACAACICAn9jmXV9Lv9VoTatAsaEsYOLZVbl8bazQoKpS2tQBRCWENkMak8AAACAAAAAgAUAAIAA", - "result" : "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgf0cwRAIgdAGK1BgAl7hzMjwAFXILNoTMgSOJEEjn282bVa1nnJkCIHPTabdA4+tT3O+jOCPIBwUUylWn3ZVE8VfBZ5EyYRGMAQEDBAEAAAABBEdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSriIGApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/ENkMak8AAACAAAAAgAAAAIAiBgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU21xDZDGpPAAAAgAAAAIABAACAAAEBIADC6wsAAAAAF6kUt/X69A49QKWkWbHbNTXyty+pIeiHIgIDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtxHMEQCIGLrelVhB6fHP0WsSrWh3d9vcHX7EnWWmn84Pv/3hLyyAiAMBdu3Rw2/LwhVfdNWxzJcHtMJE+mWzThAlF2xIijaXwEBAwQBAAAAAQQiACCMI1MXN0O1ld+0oHtyuo5C43l9p06H/n2ddJfjsgKJAwEFR1IhAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcIQI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc1KuIgYCOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnMQ2QxqTwAAAIAAAACAAwAAgCIGAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcENkMak8AAACAAAAAgAIAAIAAIgIDqaTDf1mW06ol26xrVwrwZQOUSSlCRgs1R1Ptnuylh3EQ2QxqTwAAAIAAAACABAAAgAAiAgJ/Y5l1fS7/VaE2rQLGhLGDi2VW5fG2s0KCqUtrUAUQlhDZDGpPAAAAgAAAAIAFAACAAA==" - }, - { - "privkeys" : [ - "cT7J9YpCwY3AVRFSjN6ukeEeWY6mhpbJPxRaDaP5QTdygQRxP9Au", - "cNBc3SWUip9PPm1GjRoLEJT6T41iNzCYtD7qro84FMnM5zEqeJsE" - ], - "psbt" : "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAABBEdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSriIGApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/ENkMak8AAACAAAAAgAAAAIAiBgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU21xDZDGpPAAAAgAAAAIABAACAAQMEAQAAAAABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohwEEIgAgjCNTFzdDtZXftKB7crqOQuN5fadOh/59nXSX47ICiQMBBUdSIQMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3CECOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNSriIGAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zENkMak8AAACAAAAAgAMAAIAiBgMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3BDZDGpPAAAAgAAAAIACAACAAQMEAQAAAAAiAgOppMN/WZbTqiXbrGtXCvBlA5RJKUJGCzVHU+2e7KWHcRDZDGpPAAAAgAAAAIAEAACAACICAn9jmXV9Lv9VoTatAsaEsYOLZVbl8bazQoKpS2tQBRCWENkMak8AAACAAAAAgAUAAIAA", - "result" : "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU210cwRAIgYxqYn+c4qSrQGYYCMxLBkhT+KAKznly8GsNniAbGksMCIDnbbDh70mdxbf2z1NjaULjoXSEzJrp8faqkwM5B65IjAQEDBAEAAAABBEdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSriIGApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/ENkMak8AAACAAAAAgAAAAIAiBgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU21xDZDGpPAAAAgAAAAIABAACAAAEBIADC6wsAAAAAF6kUt/X69A49QKWkWbHbNTXyty+pIeiHIgICOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNHMEQCIGX0W6WZi1mif/4ae+0BavHx+Q1Us6qPdFCqX1aiUQO9AiB/ckcDrR7blmgLKEtW1P/LiPf7dZ6rvgiqMPKbhROD0gEBAwQBAAAAAQQiACCMI1MXN0O1ld+0oHtyuo5C43l9p06H/n2ddJfjsgKJAwEFR1IhAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcIQI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc1KuIgYCOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnMQ2QxqTwAAAIAAAACAAwAAgCIGAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcENkMak8AAACAAAAAgAIAAIAAIgIDqaTDf1mW06ol26xrVwrwZQOUSSlCRgs1R1Ptnuylh3EQ2QxqTwAAAIAAAACABAAAgAAiAgJ/Y5l1fS7/VaE2rQLGhLGDi2VW5fG2s0KCqUtrUAUQlhDZDGpPAAAAgAAAAIAFAACAAA==" - }, - { - "privkeys" : [ - "cNBc3SWUip9PPm1GjRoLEJT6T41iNzCYtD7qro84FMnM5zEqeJsE" - ], - "psbt" : "cHNidP8BAKACAAAAAqsJSaCMWvfEm4IS9Bfi8Vqz9cM9zxU4IagTn4d6W3vkAAAAAAD+////qwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QBAAAAAP7///8CYDvqCwAAAAAZdqkUdopAu9dAy+gdmI5x3ipNXHE5ax2IrI4kAAAAAAAAGXapFG9GILVT+glechue4O/p+gOcykWXiKwAAAAAAAEBItPf9QUAAAAAGXapFNSO0xELlAFMsRS9Mtb00GbcdCVriKwAAQEgAOH1BQAAAAAXqRQ1RebjO4MsRwUPJNPuuTycA5SLx4cBBBYAFIXRNTfy4mVAWjTbr6nj3aAfuCMIACICAurVlmh8qAYEPtw94RbN8p1eklfBls0FXPaYyNAr8k6ZELSmumcAAACAAAAAgAIAAIAAIgIDlPYr6d8ZlSxVh3aK63aYBhrSxKJciU9H2MFitNchPQUQtKa6ZwAAAIABAACAAgAAgAA=", - "result" : "cHNidP8BAKACAAAAAqsJSaCMWvfEm4IS9Bfi8Vqz9cM9zxU4IagTn4d6W3vkAAAAAAD+////qwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QBAAAAAP7///8CYDvqCwAAAAAZdqkUdopAu9dAy+gdmI5x3ipNXHE5ax2IrI4kAAAAAAAAGXapFG9GILVT+glechue4O/p+gOcykWXiKwAAAAAAAEBItPf9QUAAAAAGXapFNSO0xELlAFMsRS9Mtb00GbcdCVriKwAAQEgAOH1BQAAAAAXqRQ1RebjO4MsRwUPJNPuuTycA5SLx4cBBBYAFIXRNTfy4mVAWjTbr6nj3aAfuCMIACICAurVlmh8qAYEPtw94RbN8p1eklfBls0FXPaYyNAr8k6ZELSmumcAAACAAAAAgAIAAIAAIgIDlPYr6d8ZlSxVh3aK63aYBhrSxKJciU9H2MFitNchPQUQtKa6ZwAAAIABAACAAgAAgAA=" - }, - { - "privkeys" : [ - "cT7J9YpCwY3AVRFSjN6ukeEeWY6mhpbJPxRaDaP5QTdygQRxP9Au", - "cNBc3SWUip9PPm1GjRoLEJT6T41iNzCYtD7qro84FMnM5zEqeJsE" - ], - "psbt" : "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU210gwRQIhAPYQOLMI3B2oZaNIUnRvAVdyk0IIxtJEVDk82ZvfIhd3AiAFbmdaZ1ptCgK4WxTl4pB02KJam1dgvqKBb2YZEKAG6gEBAwQBAAAAAQRHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq8iBgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfxDZDGpPAAAAgAAAAIAAAACAIgYC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtcQ2QxqTwAAAIAAAACAAQAAgAABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohyICAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBAQMEAQAAAAEEIgAgjCNTFzdDtZXftKB7crqOQuN5fadOh/59nXSX47ICiQMBBUdSIQMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3CECOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNSriIGAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zENkMak8AAACAAAAAgAMAAIAiBgMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3BDZDGpPAAAAgAAAAIACAACAACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA=", - "result" : "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU210gwRQIhAPYQOLMI3B2oZaNIUnRvAVdyk0IIxtJEVDk82ZvfIhd3AiAFbmdaZ1ptCgK4WxTl4pB02KJam1dgvqKBb2YZEKAG6gEBAwQBAAAAAQRHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq8iBgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfxDZDGpPAAAAgAAAAIAAAACAIgYC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtcQ2QxqTwAAAIAAAACAAQAAgAABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohyICAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBAQMEAQAAAAEEIgAgjCNTFzdDtZXftKB7crqOQuN5fadOh/59nXSX47ICiQMBBUdSIQMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3CECOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNSriIGAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zENkMak8AAACAAAAAgAMAAIAiBgMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3BDZDGpPAAAAgAAAAIACAACAACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA=" - }, - { - "privkeys" : [ - "cT7J9YpCwY3AVRFSjN6ukeEeWY6mhpbJPxRaDaP5QTdygQRxP9Au", - "cNBc3SWUip9PPm1GjRoLEJT6T41iNzCYtD7qro84FMnM5zEqeJsE" - ], - "psbt" : "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU210gwRQIhAPYQOLMI3B2oZaNIUnRvAVdyk0IIxtJEVDk82ZvfIhd3AiAFbmdaZ1ptCgK4WxTl4pB02KJam1dgvqKBb2YZEKAG6gEBAwQBAAAAAQRHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq4iBgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfxDZDGpPAAAAgAAAAIAAAACAIgYC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtcQ2QxqTwAAAIAAAACAAQAAgAABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohyICAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBAQMEAQAAAAEEIgAgjCNTFzdDtZXftKB7crqOQuN5fadOh/59nXSX47ICiQABBUdSIQMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3CECOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNSriIGAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zENkMak8AAACAAAAAgAMAAIAiBgMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3BDZDGpPAAAAgAAAAIACAACAACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA=", - "result" : "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU210gwRQIhAPYQOLMI3B2oZaNIUnRvAVdyk0IIxtJEVDk82ZvfIhd3AiAFbmdaZ1ptCgK4WxTl4pB02KJam1dgvqKBb2YZEKAG6gEBAwQBAAAAAQRHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq4iBgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfxDZDGpPAAAAgAAAAIAAAACAIgYC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtcQ2QxqTwAAAIAAAACAAQAAgAABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohyICAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBAQMEAQAAAAEEIgAgjCNTFzdDtZXftKB7crqOQuN5fadOh/59nXSX47ICiQABBUdSIQMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3CECOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNSriIGAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zENkMak8AAACAAAAAgAMAAIAiBgMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3BDZDGpPAAAAgAAAAIACAACAACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA=" + "txid": "75ddabb27b8845f5247975c8a5ba7c6f336c4570708ebe230caf6db5217ae858", + "vout": 0 }, { - "privkeys" : [ - "cT7J9YpCwY3AVRFSjN6ukeEeWY6mhpbJPxRaDaP5QTdygQRxP9Au", - "cNBc3SWUip9PPm1GjRoLEJT6T41iNzCYtD7qro84FMnM5zEqeJsE" - ], - "psbt" : "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU210gwRQIhAPYQOLMI3B2oZaNIUnRvAVdyk0IIxtJEVDk82ZvfIhd3AiAFbmdaZ1ptCgK4WxTl4pB02KJam1dgvqKBb2YZEKAG6gEBAwQBAAAAAQRHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq4iBgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfxDZDGpPAAAAgAAAAIAAAACAIgYC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtcQ2QxqTwAAAIAAAACAAQAAgAABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohyICAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBAQMEAQAAAAEEIgAgjCNTFzdDtZXftKB7crqOQuN5fadOh/59nXSX47ICiQMBBUdSIQMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3CECOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNSrSIGAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zENkMak8AAACAAAAAgAMAAIAiBgMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3BDZDGpPAAAAgAAAAIACAACAACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA=", - "result" : "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU210gwRQIhAPYQOLMI3B2oZaNIUnRvAVdyk0IIxtJEVDk82ZvfIhd3AiAFbmdaZ1ptCgK4WxTl4pB02KJam1dgvqKBb2YZEKAG6gEBAwQBAAAAAQRHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq4iBgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfxDZDGpPAAAAgAAAAIAAAACAIgYC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtcQ2QxqTwAAAIAAAACAAQAAgAABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohyICAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBAQMEAQAAAAEEIgAgjCNTFzdDtZXftKB7crqOQuN5fadOh/59nXSX47ICiQMBBUdSIQMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3CECOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNSrSIGAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zENkMak8AAACAAAAAgAMAAIAiBgMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3BDZDGpPAAAAgAAAAIACAACAACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA=" + "txid": "1dea7cd05979072a3578cab271c02244ea8a090bbb46aa680a65ecd027048d83", + "vout": 1 } - ], - "combiner" : [ + ], + "outputs": [ { - "combine" : [ - "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgf0cwRAIgdAGK1BgAl7hzMjwAFXILNoTMgSOJEEjn282bVa1nnJkCIHPTabdA4+tT3O+jOCPIBwUUylWn3ZVE8VfBZ5EyYRGMAQEDBAEAAAABBEdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSriIGApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/ENkMak8AAACAAAAAgAAAAIAiBgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU21xDZDGpPAAAAgAAAAIABAACAAAEBIADC6wsAAAAAF6kUt/X69A49QKWkWbHbNTXyty+pIeiHIgIDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtxHMEQCIGLrelVhB6fHP0WsSrWh3d9vcHX7EnWWmn84Pv/3hLyyAiAMBdu3Rw2/LwhVfdNWxzJcHtMJE+mWzThAlF2xIijaXwEBAwQBAAAAAQQiACCMI1MXN0O1ld+0oHtyuo5C43l9p06H/n2ddJfjsgKJAwEFR1IhAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcIQI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc1KuIgYCOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnMQ2QxqTwAAAIAAAACAAwAAgCIGAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcENkMak8AAACAAAAAgAIAAIAAIgIDqaTDf1mW06ol26xrVwrwZQOUSSlCRgs1R1Ptnuylh3EQ2QxqTwAAAIAAAACABAAAgAAiAgJ/Y5l1fS7/VaE2rQLGhLGDi2VW5fG2s0KCqUtrUAUQlhDZDGpPAAAAgAAAAIAFAACAAA==", - "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU210cwRAIgYxqYn+c4qSrQGYYCMxLBkhT+KAKznly8GsNniAbGksMCIDnbbDh70mdxbf2z1NjaULjoXSEzJrp8faqkwM5B65IjAQEDBAEAAAABBEdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSriIGApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/ENkMak8AAACAAAAAgAAAAIAiBgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU21xDZDGpPAAAAgAAAAIABAACAAAEBIADC6wsAAAAAF6kUt/X69A49QKWkWbHbNTXyty+pIeiHIgICOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNHMEQCIGX0W6WZi1mif/4ae+0BavHx+Q1Us6qPdFCqX1aiUQO9AiB/ckcDrR7blmgLKEtW1P/LiPf7dZ6rvgiqMPKbhROD0gEBAwQBAAAAAQQiACCMI1MXN0O1ld+0oHtyuo5C43l9p06H/n2ddJfjsgKJAwEFR1IhAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcIQI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc1KuIgYCOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnMQ2QxqTwAAAIAAAACAAwAAgCIGAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcENkMak8AAACAAAAAgAIAAIAAIgIDqaTDf1mW06ol26xrVwrwZQOUSSlCRgs1R1Ptnuylh3EQ2QxqTwAAAIAAAACABAAAgAAiAgJ/Y5l1fS7/VaE2rQLGhLGDi2VW5fG2s0KCqUtrUAUQlhDZDGpPAAAAgAAAAIAFAACAAA==" - ], - "result" : "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgf0cwRAIgdAGK1BgAl7hzMjwAFXILNoTMgSOJEEjn282bVa1nnJkCIHPTabdA4+tT3O+jOCPIBwUUylWn3ZVE8VfBZ5EyYRGMASICAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXRzBEAiBjGpif5zipKtAZhgIzEsGSFP4oArOeXLwaw2eIBsaSwwIgOdtsOHvSZ3Ft/bPU2NpQuOhdITMmunx9qqTAzkHrkiMBAQMEAQAAAAEER1IhApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/IQLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU211KuIgYClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8Q2QxqTwAAAIAAAACAAAAAgCIGAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXENkMak8AAACAAAAAgAEAAIAAAQEgAMLrCwAAAAAXqRS39fr0Dj1ApaRZsds1NfK3L6kh6IciAgMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3EcwRAIgYut6VWEHp8c/RaxKtaHd329wdfsSdZaafzg+//eEvLICIAwF27dHDb8vCFV901bHMlwe0wkT6ZbNOECUXbEiKNpfASICAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBAQMEAQAAAAEEIgAgjCNTFzdDtZXftKB7crqOQuN5fadOh/59nXSX47ICiQMBBUdSIQMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3CECOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNSriIGAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zENkMak8AAACAAAAAgAMAAIAiBgMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3BDZDGpPAAAAgAAAAIACAACAACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA=" + "bcrt1qmpwzkuwsqc9snjvgdt4czhjsnywa5yjdqpxskv": 1.49990000 }, { - "combine" : [ - "cHNidP8BAD8CAAAAAf//////////////////////////////////////////AAAAAAD/////AQAAAAAAAAAAA2oBAAAAAAAKDwECAwQFBgcICQ8BAgMEBQYHCAkKCwwNDg8ACg8BAgMEBQYHCAkPAQIDBAUGBwgJCgsMDQ4PAAoPAQIDBAUGBwgJDwECAwQFBgcICQoLDA0ODwA=", - "cHNidP8BAD8CAAAAAf//////////////////////////////////////////AAAAAAD/////AQAAAAAAAAAAA2oBAAAAAAAKDwECAwQFBgcIEA8BAgMEBQYHCAkKCwwNDg8ACg8BAgMEBQYHCBAPAQIDBAUGBwgJCgsMDQ4PAAoPAQIDBAUGBwgQDwECAwQFBgcICQoLDA0ODwA=" - ], - "result" : "cHNidP8BAD8CAAAAAf//////////////////////////////////////////AAAAAAD/////AQAAAAAAAAAAA2oBAAAAAAAKDwECAwQFBgcICQ8BAgMEBQYHCAkKCwwNDg8KDwECAwQFBgcIEA8BAgMEBQYHCAkKCwwNDg8ACg8BAgMEBQYHCAkPAQIDBAUGBwgJCgsMDQ4PCg8BAgMEBQYHCBAPAQIDBAUGBwgJCgsMDQ4PAAoPAQIDBAUGBwgJDwECAwQFBgcICQoLDA0ODwoPAQIDBAUGBwgQDwECAwQFBgcICQoLDA0ODwA=" - } - ], - "finalizer" : [ - { - "finalize" : "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgf0cwRAIgdAGK1BgAl7hzMjwAFXILNoTMgSOJEEjn282bVa1nnJkCIHPTabdA4+tT3O+jOCPIBwUUylWn3ZVE8VfBZ5EyYRGMASICAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXSDBFAiEA9hA4swjcHahlo0hSdG8BV3KTQgjG0kRUOTzZm98iF3cCIAVuZ1pnWm0KArhbFOXikHTYolqbV2C+ooFvZhkQoAbqAQEDBAEAAAABBEdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSriIGApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/ENkMak8AAACAAAAAgAAAAIAiBgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU21xDZDGpPAAAAgAAAAIABAACAAAEBIADC6wsAAAAAF6kUt/X69A49QKWkWbHbNTXyty+pIeiHIgIDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtxHMEQCIGLrelVhB6fHP0WsSrWh3d9vcHX7EnWWmn84Pv/3hLyyAiAMBdu3Rw2/LwhVfdNWxzJcHtMJE+mWzThAlF2xIijaXwEiAgI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc0cwRAIgZfRbpZmLWaJ//hp77QFq8fH5DVSzqo90UKpfVqJRA70CIH9yRwOtHtuWaAsoS1bU/8uI9/t1nqu+CKow8puFE4PSAQEDBAEAAAABBCIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAQVHUiEDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwhAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zUq4iBgI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8OcxDZDGpPAAAAgAAAAIADAACAIgYDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwQ2QxqTwAAAIAAAACAAgAAgAAiAgOppMN/WZbTqiXbrGtXCvBlA5RJKUJGCzVHU+2e7KWHcRDZDGpPAAAAgAAAAIAEAACAACICAn9jmXV9Lv9VoTatAsaEsYOLZVbl8bazQoKpS2tQBRCWENkMak8AAACAAAAAgAUAAIAA", - "result" : "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAABB9oARzBEAiB0AYrUGACXuHMyPAAVcgs2hMyBI4kQSOfbzZtVrWecmQIgc9Npt0Dj61Pc76M4I8gHBRTKVafdlUTxV8FnkTJhEYwBSDBFAiEA9hA4swjcHahlo0hSdG8BV3KTQgjG0kRUOTzZm98iF3cCIAVuZ1pnWm0KArhbFOXikHTYolqbV2C+ooFvZhkQoAbqAUdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSrgABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohwEHIyIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAQjaBABHMEQCIGLrelVhB6fHP0WsSrWh3d9vcHX7EnWWmn84Pv/3hLyyAiAMBdu3Rw2/LwhVfdNWxzJcHtMJE+mWzThAlF2xIijaXwFHMEQCIGX0W6WZi1mif/4ae+0BavHx+Q1Us6qPdFCqX1aiUQO9AiB/ckcDrR7blmgLKEtW1P/LiPf7dZ6rvgiqMPKbhROD0gFHUiEDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwhAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zUq4AIgIDqaTDf1mW06ol26xrVwrwZQOUSSlCRgs1R1Ptnuylh3EQ2QxqTwAAAIAAAACABAAAgAAiAgJ/Y5l1fS7/VaE2rQLGhLGDi2VW5fG2s0KCqUtrUAUQlhDZDGpPAAAAgAAAAIAFAACAAA==" - } - ], - "extractor" : [ - { - "extract" : "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAABB9oARzBEAiB0AYrUGACXuHMyPAAVcgs2hMyBI4kQSOfbzZtVrWecmQIgc9Npt0Dj61Pc76M4I8gHBRTKVafdlUTxV8FnkTJhEYwBSDBFAiEA9hA4swjcHahlo0hSdG8BV3KTQgjG0kRUOTzZm98iF3cCIAVuZ1pnWm0KArhbFOXikHTYolqbV2C+ooFvZhkQoAbqAUdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSrgABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohwEHIyIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAQjaBABHMEQCIGLrelVhB6fHP0WsSrWh3d9vcHX7EnWWmn84Pv/3hLyyAiAMBdu3Rw2/LwhVfdNWxzJcHtMJE+mWzThAlF2xIijaXwFHMEQCIGX0W6WZi1mif/4ae+0BavHx+Q1Us6qPdFCqX1aiUQO9AiB/ckcDrR7blmgLKEtW1P/LiPf7dZ6rvgiqMPKbhROD0gFHUiEDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwhAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zUq4AIgIDqaTDf1mW06ol26xrVwrwZQOUSSlCRgs1R1Ptnuylh3EQ2QxqTwAAAIAAAACABAAAgAAiAgJ/Y5l1fS7/VaE2rQLGhLGDi2VW5fG2s0KCqUtrUAUQlhDZDGpPAAAAgAAAAIAFAACAAA==", - "result" : "0200000000010258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd7500000000da00473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752aeffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d01000000232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f000400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00000000" + "bcrt1qqzh2ngh97ru8dfvgma25d6r595wcwqy0cee4cc": 1 } - ] + ], + "result": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAAAAAA=" + } + ], + "signer": [ + { + "privkeys": [ + "cP53pDbR5WtAD8dYAW9hhTjuvvTVaEiQBdrz9XPrgLBeRFiyCbQr", + "cR6SXDoyfQrcp4piaiHE97Rsgta9mNhGTen9XeonVgwsh4iSgw6d" + ], + "psbt": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAABBEdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSriIGApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/ENkMak8AAACAAAAAgAAAAIAiBgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU21xDZDGpPAAAAgAAAAIABAACAAQMEAQAAAAABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohwEEIgAgjCNTFzdDtZXftKB7crqOQuN5fadOh/59nXSX47ICiQMBBUdSIQMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3CECOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNSriIGAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zENkMak8AAACAAAAAgAMAAIAiBgMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3BDZDGpPAAAAgAAAAIACAACAAQMEAQAAAAAiAgOppMN/WZbTqiXbrGtXCvBlA5RJKUJGCzVHU+2e7KWHcRDZDGpPAAAAgAAAAIAEAACAACICAn9jmXV9Lv9VoTatAsaEsYOLZVbl8bazQoKpS2tQBRCWENkMak8AAACAAAAAgAUAAIAA", + "result": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgf0cwRAIgdAGK1BgAl7hzMjwAFXILNoTMgSOJEEjn282bVa1nnJkCIHPTabdA4+tT3O+jOCPIBwUUylWn3ZVE8VfBZ5EyYRGMAQEDBAEAAAABBEdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSriIGApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/ENkMak8AAACAAAAAgAAAAIAiBgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU21xDZDGpPAAAAgAAAAIABAACAAAEBIADC6wsAAAAAF6kUt/X69A49QKWkWbHbNTXyty+pIeiHIgIDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtxHMEQCIGLrelVhB6fHP0WsSrWh3d9vcHX7EnWWmn84Pv/3hLyyAiAMBdu3Rw2/LwhVfdNWxzJcHtMJE+mWzThAlF2xIijaXwEBAwQBAAAAAQQiACCMI1MXN0O1ld+0oHtyuo5C43l9p06H/n2ddJfjsgKJAwEFR1IhAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcIQI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc1KuIgYCOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnMQ2QxqTwAAAIAAAACAAwAAgCIGAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcENkMak8AAACAAAAAgAIAAIAAIgIDqaTDf1mW06ol26xrVwrwZQOUSSlCRgs1R1Ptnuylh3EQ2QxqTwAAAIAAAACABAAAgAAiAgJ/Y5l1fS7/VaE2rQLGhLGDi2VW5fG2s0KCqUtrUAUQlhDZDGpPAAAAgAAAAIAFAACAAA==" + }, + { + "privkeys": [ + "cT7J9YpCwY3AVRFSjN6ukeEeWY6mhpbJPxRaDaP5QTdygQRxP9Au", + "cNBc3SWUip9PPm1GjRoLEJT6T41iNzCYtD7qro84FMnM5zEqeJsE" + ], + "psbt": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAABBEdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSriIGApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/ENkMak8AAACAAAAAgAAAAIAiBgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU21xDZDGpPAAAAgAAAAIABAACAAQMEAQAAAAABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohwEEIgAgjCNTFzdDtZXftKB7crqOQuN5fadOh/59nXSX47ICiQMBBUdSIQMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3CECOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNSriIGAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zENkMak8AAACAAAAAgAMAAIAiBgMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3BDZDGpPAAAAgAAAAIACAACAAQMEAQAAAAAiAgOppMN/WZbTqiXbrGtXCvBlA5RJKUJGCzVHU+2e7KWHcRDZDGpPAAAAgAAAAIAEAACAACICAn9jmXV9Lv9VoTatAsaEsYOLZVbl8bazQoKpS2tQBRCWENkMak8AAACAAAAAgAUAAIAA", + "result": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU210cwRAIgYxqYn+c4qSrQGYYCMxLBkhT+KAKznly8GsNniAbGksMCIDnbbDh70mdxbf2z1NjaULjoXSEzJrp8faqkwM5B65IjAQEDBAEAAAABBEdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSriIGApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/ENkMak8AAACAAAAAgAAAAIAiBgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU21xDZDGpPAAAAgAAAAIABAACAAAEBIADC6wsAAAAAF6kUt/X69A49QKWkWbHbNTXyty+pIeiHIgICOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNHMEQCIGX0W6WZi1mif/4ae+0BavHx+Q1Us6qPdFCqX1aiUQO9AiB/ckcDrR7blmgLKEtW1P/LiPf7dZ6rvgiqMPKbhROD0gEBAwQBAAAAAQQiACCMI1MXN0O1ld+0oHtyuo5C43l9p06H/n2ddJfjsgKJAwEFR1IhAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcIQI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc1KuIgYCOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnMQ2QxqTwAAAIAAAACAAwAAgCIGAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcENkMak8AAACAAAAAgAIAAIAAIgIDqaTDf1mW06ol26xrVwrwZQOUSSlCRgs1R1Ptnuylh3EQ2QxqTwAAAIAAAACABAAAgAAiAgJ/Y5l1fS7/VaE2rQLGhLGDi2VW5fG2s0KCqUtrUAUQlhDZDGpPAAAAgAAAAIAFAACAAA==" + }, + { + "privkeys": [ + "cNBc3SWUip9PPm1GjRoLEJT6T41iNzCYtD7qro84FMnM5zEqeJsE" + ], + "psbt": "cHNidP8BAKACAAAAAqsJSaCMWvfEm4IS9Bfi8Vqz9cM9zxU4IagTn4d6W3vkAAAAAAD+////qwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QBAAAAAP7///8CYDvqCwAAAAAZdqkUdopAu9dAy+gdmI5x3ipNXHE5ax2IrI4kAAAAAAAAGXapFG9GILVT+glechue4O/p+gOcykWXiKwAAAAAAAEBItPf9QUAAAAAGXapFNSO0xELlAFMsRS9Mtb00GbcdCVriKwAAQEgAOH1BQAAAAAXqRQ1RebjO4MsRwUPJNPuuTycA5SLx4cBBBYAFIXRNTfy4mVAWjTbr6nj3aAfuCMIACICAurVlmh8qAYEPtw94RbN8p1eklfBls0FXPaYyNAr8k6ZELSmumcAAACAAAAAgAIAAIAAIgIDlPYr6d8ZlSxVh3aK63aYBhrSxKJciU9H2MFitNchPQUQtKa6ZwAAAIABAACAAgAAgAA=", + "result": "cHNidP8BAKACAAAAAqsJSaCMWvfEm4IS9Bfi8Vqz9cM9zxU4IagTn4d6W3vkAAAAAAD+////qwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QBAAAAAP7///8CYDvqCwAAAAAZdqkUdopAu9dAy+gdmI5x3ipNXHE5ax2IrI4kAAAAAAAAGXapFG9GILVT+glechue4O/p+gOcykWXiKwAAAAAAAEBItPf9QUAAAAAGXapFNSO0xELlAFMsRS9Mtb00GbcdCVriKwAAQEgAOH1BQAAAAAXqRQ1RebjO4MsRwUPJNPuuTycA5SLx4cBBBYAFIXRNTfy4mVAWjTbr6nj3aAfuCMIACICAurVlmh8qAYEPtw94RbN8p1eklfBls0FXPaYyNAr8k6ZELSmumcAAACAAAAAgAIAAIAAIgIDlPYr6d8ZlSxVh3aK63aYBhrSxKJciU9H2MFitNchPQUQtKa6ZwAAAIABAACAAgAAgAA=" + }, + { + "privkeys": [ + "cT7J9YpCwY3AVRFSjN6ukeEeWY6mhpbJPxRaDaP5QTdygQRxP9Au", + "cNBc3SWUip9PPm1GjRoLEJT6T41iNzCYtD7qro84FMnM5zEqeJsE" + ], + "psbt": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU210gwRQIhAPYQOLMI3B2oZaNIUnRvAVdyk0IIxtJEVDk82ZvfIhd3AiAFbmdaZ1ptCgK4WxTl4pB02KJam1dgvqKBb2YZEKAG6gEBAwQBAAAAAQRHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq8iBgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfxDZDGpPAAAAgAAAAIAAAACAIgYC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtcQ2QxqTwAAAIAAAACAAQAAgAABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohyICAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBAQMEAQAAAAEEIgAgjCNTFzdDtZXftKB7crqOQuN5fadOh/59nXSX47ICiQMBBUdSIQMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3CECOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNSriIGAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zENkMak8AAACAAAAAgAMAAIAiBgMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3BDZDGpPAAAAgAAAAIACAACAACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA=", + "result": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU210gwRQIhAPYQOLMI3B2oZaNIUnRvAVdyk0IIxtJEVDk82ZvfIhd3AiAFbmdaZ1ptCgK4WxTl4pB02KJam1dgvqKBb2YZEKAG6gEBAwQBAAAAAQRHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq8iBgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfxDZDGpPAAAAgAAAAIAAAACAIgYC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtcQ2QxqTwAAAIAAAACAAQAAgAABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohyICAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBAQMEAQAAAAEEIgAgjCNTFzdDtZXftKB7crqOQuN5fadOh/59nXSX47ICiQMBBUdSIQMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3CECOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNSriIGAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zENkMak8AAACAAAAAgAMAAIAiBgMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3BDZDGpPAAAAgAAAAIACAACAACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA=" + }, + { + "privkeys": [ + "cT7J9YpCwY3AVRFSjN6ukeEeWY6mhpbJPxRaDaP5QTdygQRxP9Au", + "cNBc3SWUip9PPm1GjRoLEJT6T41iNzCYtD7qro84FMnM5zEqeJsE" + ], + "psbt": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU210gwRQIhAPYQOLMI3B2oZaNIUnRvAVdyk0IIxtJEVDk82ZvfIhd3AiAFbmdaZ1ptCgK4WxTl4pB02KJam1dgvqKBb2YZEKAG6gEBAwQBAAAAAQRHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq4iBgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfxDZDGpPAAAAgAAAAIAAAACAIgYC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtcQ2QxqTwAAAIAAAACAAQAAgAABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohyICAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBAQMEAQAAAAEEIgAgjCNTFzdDtZXftKB7crqOQuN5fadOh/59nXSX47ICiQABBUdSIQMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3CECOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNSriIGAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zENkMak8AAACAAAAAgAMAAIAiBgMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3BDZDGpPAAAAgAAAAIACAACAACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA=", + "result": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU210gwRQIhAPYQOLMI3B2oZaNIUnRvAVdyk0IIxtJEVDk82ZvfIhd3AiAFbmdaZ1ptCgK4WxTl4pB02KJam1dgvqKBb2YZEKAG6gEBAwQBAAAAAQRHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq4iBgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfxDZDGpPAAAAgAAAAIAAAACAIgYC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtcQ2QxqTwAAAIAAAACAAQAAgAABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohyICAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBAQMEAQAAAAEEIgAgjCNTFzdDtZXftKB7crqOQuN5fadOh/59nXSX47ICiQABBUdSIQMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3CECOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNSriIGAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zENkMak8AAACAAAAAgAMAAIAiBgMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3BDZDGpPAAAAgAAAAIACAACAACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA=" + }, + { + "privkeys": [ + "cT7J9YpCwY3AVRFSjN6ukeEeWY6mhpbJPxRaDaP5QTdygQRxP9Au", + "cNBc3SWUip9PPm1GjRoLEJT6T41iNzCYtD7qro84FMnM5zEqeJsE" + ], + "psbt": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU210gwRQIhAPYQOLMI3B2oZaNIUnRvAVdyk0IIxtJEVDk82ZvfIhd3AiAFbmdaZ1ptCgK4WxTl4pB02KJam1dgvqKBb2YZEKAG6gEBAwQBAAAAAQRHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq4iBgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfxDZDGpPAAAAgAAAAIAAAACAIgYC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtcQ2QxqTwAAAIAAAACAAQAAgAABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohyICAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBAQMEAQAAAAEEIgAgjCNTFzdDtZXftKB7crqOQuN5fadOh/59nXSX47ICiQMBBUdSIQMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3CECOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNSrSIGAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zENkMak8AAACAAAAAgAMAAIAiBgMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3BDZDGpPAAAAgAAAAIACAACAACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA=", + "result": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU210gwRQIhAPYQOLMI3B2oZaNIUnRvAVdyk0IIxtJEVDk82ZvfIhd3AiAFbmdaZ1ptCgK4WxTl4pB02KJam1dgvqKBb2YZEKAG6gEBAwQBAAAAAQRHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq4iBgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfxDZDGpPAAAAgAAAAIAAAACAIgYC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtcQ2QxqTwAAAIAAAACAAQAAgAABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohyICAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBAQMEAQAAAAEEIgAgjCNTFzdDtZXftKB7crqOQuN5fadOh/59nXSX47ICiQMBBUdSIQMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3CECOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNSrSIGAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zENkMak8AAACAAAAAgAMAAIAiBgMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3BDZDGpPAAAAgAAAAIACAACAACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA=" + } + ], + "combiner": [ + { + "combine": [ + "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgf0cwRAIgdAGK1BgAl7hzMjwAFXILNoTMgSOJEEjn282bVa1nnJkCIHPTabdA4+tT3O+jOCPIBwUUylWn3ZVE8VfBZ5EyYRGMAQEDBAEAAAABBEdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSriIGApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/ENkMak8AAACAAAAAgAAAAIAiBgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU21xDZDGpPAAAAgAAAAIABAACAAAEBIADC6wsAAAAAF6kUt/X69A49QKWkWbHbNTXyty+pIeiHIgIDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtxHMEQCIGLrelVhB6fHP0WsSrWh3d9vcHX7EnWWmn84Pv/3hLyyAiAMBdu3Rw2/LwhVfdNWxzJcHtMJE+mWzThAlF2xIijaXwEBAwQBAAAAAQQiACCMI1MXN0O1ld+0oHtyuo5C43l9p06H/n2ddJfjsgKJAwEFR1IhAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcIQI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc1KuIgYCOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnMQ2QxqTwAAAIAAAACAAwAAgCIGAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcENkMak8AAACAAAAAgAIAAIAAIgIDqaTDf1mW06ol26xrVwrwZQOUSSlCRgs1R1Ptnuylh3EQ2QxqTwAAAIAAAACABAAAgAAiAgJ/Y5l1fS7/VaE2rQLGhLGDi2VW5fG2s0KCqUtrUAUQlhDZDGpPAAAAgAAAAIAFAACAAA==", + "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU210cwRAIgYxqYn+c4qSrQGYYCMxLBkhT+KAKznly8GsNniAbGksMCIDnbbDh70mdxbf2z1NjaULjoXSEzJrp8faqkwM5B65IjAQEDBAEAAAABBEdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSriIGApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/ENkMak8AAACAAAAAgAAAAIAiBgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU21xDZDGpPAAAAgAAAAIABAACAAAEBIADC6wsAAAAAF6kUt/X69A49QKWkWbHbNTXyty+pIeiHIgICOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNHMEQCIGX0W6WZi1mif/4ae+0BavHx+Q1Us6qPdFCqX1aiUQO9AiB/ckcDrR7blmgLKEtW1P/LiPf7dZ6rvgiqMPKbhROD0gEBAwQBAAAAAQQiACCMI1MXN0O1ld+0oHtyuo5C43l9p06H/n2ddJfjsgKJAwEFR1IhAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcIQI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc1KuIgYCOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnMQ2QxqTwAAAIAAAACAAwAAgCIGAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcENkMak8AAACAAAAAgAIAAIAAIgIDqaTDf1mW06ol26xrVwrwZQOUSSlCRgs1R1Ptnuylh3EQ2QxqTwAAAIAAAACABAAAgAAiAgJ/Y5l1fS7/VaE2rQLGhLGDi2VW5fG2s0KCqUtrUAUQlhDZDGpPAAAAgAAAAIAFAACAAA==" + ], + "result": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgf0cwRAIgdAGK1BgAl7hzMjwAFXILNoTMgSOJEEjn282bVa1nnJkCIHPTabdA4+tT3O+jOCPIBwUUylWn3ZVE8VfBZ5EyYRGMASICAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXRzBEAiBjGpif5zipKtAZhgIzEsGSFP4oArOeXLwaw2eIBsaSwwIgOdtsOHvSZ3Ft/bPU2NpQuOhdITMmunx9qqTAzkHrkiMBAQMEAQAAAAEER1IhApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/IQLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU211KuIgYClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8Q2QxqTwAAAIAAAACAAAAAgCIGAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXENkMak8AAACAAAAAgAEAAIAAAQEgAMLrCwAAAAAXqRS39fr0Dj1ApaRZsds1NfK3L6kh6IciAgMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3EcwRAIgYut6VWEHp8c/RaxKtaHd329wdfsSdZaafzg+//eEvLICIAwF27dHDb8vCFV901bHMlwe0wkT6ZbNOECUXbEiKNpfASICAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBAQMEAQAAAAEEIgAgjCNTFzdDtZXftKB7crqOQuN5fadOh/59nXSX47ICiQMBBUdSIQMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3CECOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNSriIGAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zENkMak8AAACAAAAAgAMAAIAiBgMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3BDZDGpPAAAAgAAAAIACAACAACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA=" + }, + { + "combine": [ + "cHNidP8BAD8CAAAAAf//////////////////////////////////////////AAAAAAD/////AQAAAAAAAAAAA2oBAAAAAAAKDwECAwQFBgcICQ8BAgMEBQYHCAkKCwwNDg8ACg8BAgMEBQYHCAkPAQIDBAUGBwgJCgsMDQ4PAAoPAQIDBAUGBwgJDwECAwQFBgcICQoLDA0ODwA=", + "cHNidP8BAD8CAAAAAf//////////////////////////////////////////AAAAAAD/////AQAAAAAAAAAAA2oBAAAAAAAKDwECAwQFBgcIEA8BAgMEBQYHCAkKCwwNDg8ACg8BAgMEBQYHCBAPAQIDBAUGBwgJCgsMDQ4PAAoPAQIDBAUGBwgQDwECAwQFBgcICQoLDA0ODwA=" + ], + "result": "cHNidP8BAD8CAAAAAf//////////////////////////////////////////AAAAAAD/////AQAAAAAAAAAAA2oBAAAAAAAKDwECAwQFBgcICQ8BAgMEBQYHCAkKCwwNDg8KDwECAwQFBgcIEA8BAgMEBQYHCAkKCwwNDg8ACg8BAgMEBQYHCAkPAQIDBAUGBwgJCgsMDQ4PCg8BAgMEBQYHCBAPAQIDBAUGBwgJCgsMDQ4PAAoPAQIDBAUGBwgJDwECAwQFBgcICQoLDA0ODwoPAQIDBAUGBwgQDwECAwQFBgcICQoLDA0ODwA=" + } + ], + "finalizer": [ + { + "finalize": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgf0cwRAIgdAGK1BgAl7hzMjwAFXILNoTMgSOJEEjn282bVa1nnJkCIHPTabdA4+tT3O+jOCPIBwUUylWn3ZVE8VfBZ5EyYRGMASICAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXSDBFAiEA9hA4swjcHahlo0hSdG8BV3KTQgjG0kRUOTzZm98iF3cCIAVuZ1pnWm0KArhbFOXikHTYolqbV2C+ooFvZhkQoAbqAQEDBAEAAAABBEdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSriIGApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/ENkMak8AAACAAAAAgAAAAIAiBgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU21xDZDGpPAAAAgAAAAIABAACAAAEBIADC6wsAAAAAF6kUt/X69A49QKWkWbHbNTXyty+pIeiHIgIDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtxHMEQCIGLrelVhB6fHP0WsSrWh3d9vcHX7EnWWmn84Pv/3hLyyAiAMBdu3Rw2/LwhVfdNWxzJcHtMJE+mWzThAlF2xIijaXwEiAgI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc0cwRAIgZfRbpZmLWaJ//hp77QFq8fH5DVSzqo90UKpfVqJRA70CIH9yRwOtHtuWaAsoS1bU/8uI9/t1nqu+CKow8puFE4PSAQEDBAEAAAABBCIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAQVHUiEDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwhAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zUq4iBgI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8OcxDZDGpPAAAAgAAAAIADAACAIgYDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwQ2QxqTwAAAIAAAACAAgAAgAAiAgOppMN/WZbTqiXbrGtXCvBlA5RJKUJGCzVHU+2e7KWHcRDZDGpPAAAAgAAAAIAEAACAACICAn9jmXV9Lv9VoTatAsaEsYOLZVbl8bazQoKpS2tQBRCWENkMak8AAACAAAAAgAUAAIAA", + "result": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAABB9oARzBEAiB0AYrUGACXuHMyPAAVcgs2hMyBI4kQSOfbzZtVrWecmQIgc9Npt0Dj61Pc76M4I8gHBRTKVafdlUTxV8FnkTJhEYwBSDBFAiEA9hA4swjcHahlo0hSdG8BV3KTQgjG0kRUOTzZm98iF3cCIAVuZ1pnWm0KArhbFOXikHTYolqbV2C+ooFvZhkQoAbqAUdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSrgABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohwEHIyIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAQjaBABHMEQCIGLrelVhB6fHP0WsSrWh3d9vcHX7EnWWmn84Pv/3hLyyAiAMBdu3Rw2/LwhVfdNWxzJcHtMJE+mWzThAlF2xIijaXwFHMEQCIGX0W6WZi1mif/4ae+0BavHx+Q1Us6qPdFCqX1aiUQO9AiB/ckcDrR7blmgLKEtW1P/LiPf7dZ6rvgiqMPKbhROD0gFHUiEDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwhAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zUq4AIgIDqaTDf1mW06ol26xrVwrwZQOUSSlCRgs1R1Ptnuylh3EQ2QxqTwAAAIAAAACABAAAgAAiAgJ/Y5l1fS7/VaE2rQLGhLGDi2VW5fG2s0KCqUtrUAUQlhDZDGpPAAAAgAAAAIAFAACAAA==" + } + ], + "extractor": [ + { + "extract": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAABB9oARzBEAiB0AYrUGACXuHMyPAAVcgs2hMyBI4kQSOfbzZtVrWecmQIgc9Npt0Dj61Pc76M4I8gHBRTKVafdlUTxV8FnkTJhEYwBSDBFAiEA9hA4swjcHahlo0hSdG8BV3KTQgjG0kRUOTzZm98iF3cCIAVuZ1pnWm0KArhbFOXikHTYolqbV2C+ooFvZhkQoAbqAUdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSrgABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohwEHIyIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAQjaBABHMEQCIGLrelVhB6fHP0WsSrWh3d9vcHX7EnWWmn84Pv/3hLyyAiAMBdu3Rw2/LwhVfdNWxzJcHtMJE+mWzThAlF2xIijaXwFHMEQCIGX0W6WZi1mif/4ae+0BavHx+Q1Us6qPdFCqX1aiUQO9AiB/ckcDrR7blmgLKEtW1P/LiPf7dZ6rvgiqMPKbhROD0gFHUiEDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwhAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zUq4AIgIDqaTDf1mW06ol26xrVwrwZQOUSSlCRgs1R1Ptnuylh3EQ2QxqTwAAAIAAAACABAAAgAAiAgJ/Y5l1fS7/VaE2rQLGhLGDi2VW5fG2s0KCqUtrUAUQlhDZDGpPAAAAgAAAAIAFAACAAA==", + "result": "0200000000010258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd7500000000da00473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752aeffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d01000000232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f000400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00000000" + } + ] } \ No newline at end of file diff --git a/test/functional/example_block_hash.py b/test/functional/example_block_hash.py index 7cde114995..567f4415fb 100755 --- a/test/functional/example_block_hash.py +++ b/test/functional/example_block_hash.py @@ -9,7 +9,8 @@ from test_framework.blocktools import add_witness_commitment, create_block, create_coinbase from test_framework.test_framework import DefiTestFramework -class SimpleHashTest (DefiTestFramework): + +class SimpleHashTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True @@ -36,8 +37,9 @@ def run_test(self): # import pprint # pp = pprint.PrettyPrinter(indent=4) # pp.pprint (node.getblockheader(node.getbestblockhash())) - assert(block.hash == node.getbestblockhash()) - assert(height == node.getblockcount()) + assert (block.hash == node.getbestblockhash()) + assert (height == node.getblockcount()) + if __name__ == '__main__': - SimpleHashTest ().main () + SimpleHashTest().main() diff --git a/test/functional/example_test.py b/test/functional/example_test.py index 7df9ece02d..2ae388507b 100755 --- a/test/functional/example_test.py +++ b/test/functional/example_test.py @@ -29,6 +29,7 @@ wait_until, ) + # P2PInterface is a class containing callbacks to be executed when a P2P # message is received from the node-under-test. Subclass P2PInterface and # override the on_*() methods if you need custom behaviour. @@ -59,6 +60,7 @@ def on_inv(self, message): """Override the standard on_inv callback""" pass + def custom_function(): """Do some custom behaviour @@ -170,7 +172,7 @@ def run_test(self): # Use the mininode and blocktools functionality to manually build a block # Calling the generate() rpc is easier, but this allows us to exactly # control the blocks and transactions. - block = create_block(self.tip, create_coinbase(height+1), self.block_time) + block = create_block(self.tip, create_coinbase(height + 1), self.block_time) block.solve() block_message = msg_block(block) # Send message is used to send a P2P message to the node over our P2PInterface @@ -203,7 +205,8 @@ def run_test(self): # wait_until() will loop until a predicate condition is met. Use it to test properties of the # P2PInterface objects. - wait_until(lambda: sorted(blocks) == sorted(list(self.nodes[2].p2p.block_receive_map.keys())), timeout=5, lock=mininode_lock) + wait_until(lambda: sorted(blocks) == sorted(list(self.nodes[2].p2p.block_receive_map.keys())), timeout=5, + lock=mininode_lock) self.log.info("Check that each block was received only once") # The network thread uses a global lock on data access to the P2PConnection objects when sending and receiving @@ -213,5 +216,6 @@ def run_test(self): for block in self.nodes[2].p2p.block_receive_map.values(): assert_equal(block, 1) + if __name__ == '__main__': ExampleTest().main() diff --git a/test/functional/feature_abortnode.py b/test/functional/feature_abortnode.py index 21eca724d9..c13cb4cc2b 100755 --- a/test/functional/feature_abortnode.py +++ b/test/functional/feature_abortnode.py @@ -14,6 +14,7 @@ from test_framework.util import wait_until, get_datadir_path, connect_nodes import os + class AbortNodeTest(DefiTestFramework): def set_test_params(self): @@ -44,5 +45,6 @@ def run_test(self): self.log.info("Node crashed - now verifying restart fails") self.nodes[0].assert_start_raises_init_error() + if __name__ == '__main__': AbortNodeTest().main() diff --git a/test/functional/feature_account_mining.py b/test/functional/feature_account_mining.py index bee7633ff1..65f66b981a 100755 --- a/test/functional/feature_account_mining.py +++ b/test/functional/feature_account_mining.py @@ -13,6 +13,7 @@ ) from decimal import Decimal + class AccountMiningTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 @@ -90,5 +91,6 @@ def run_test(self): # Check the blockchain has extended as expected assert_equal(node.getblockcount(), blockcount + 1) + if __name__ == '__main__': - AccountMiningTest().main () + AccountMiningTest().main() diff --git a/test/functional/feature_accounts_n_utxos.py b/test/functional/feature_accounts_n_utxos.py index ab84d3908d..8160647c2d 100755 --- a/test/functional/feature_accounts_n_utxos.py +++ b/test/functional/feature_accounts_n_utxos.py @@ -14,17 +14,19 @@ from test_framework.util import assert_equal, assert_raises_rpc_error, \ connect_nodes_bi -class AccountsAndUTXOsTest (DefiTestFramework): + +class AccountsAndUTXOsTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 3 # node0: main # node1: secondary tester # node2: revert create (all) self.setup_clean_chain = True - self.extra_args = [['-txnotokens=0', '-amkheight=50'], ['-txnotokens=0', '-amkheight=50'], ['-txnotokens=0', '-amkheight=50']] + self.extra_args = [['-txnotokens=0', '-amkheight=50'], ['-txnotokens=0', '-amkheight=50'], + ['-txnotokens=0', '-amkheight=50']] def run_test(self): - assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI + assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI print("Generating initial chain...") self.setup_tokens() @@ -48,14 +50,14 @@ def run_test(self): toSilver = self.nodes[0].getnewaddress("", "legacy") # accounttoaccount - #======================== + # ======================== # missing from (account) try: self.nodes[0].accounttoaccount(self.nodes[0].getnewaddress("", "legacy"), {toGold: "100@" + symbolGOLD}, []) except JSONRPCException as e: errorString = e.error['message'] - assert("not enough balance" in errorString) + assert ("not enough balance" in errorString) # missing from (account exist, but no tokens) try: @@ -63,7 +65,7 @@ def run_test(self): {toGold: "100@" + symbolSILVER}, []) except JSONRPCException as e: errorString = e.error['message'] - assert("not enough balance" in errorString) + assert ("not enough balance" in errorString) # missing amount try: @@ -71,22 +73,22 @@ def run_test(self): {toGold: ""}, []) except JSONRPCException as e: errorString = e.error['message'] - assert("Invalid amount" in errorString) + assert ("Invalid amount" in errorString) - #invalid UTXOs + # invalid UTXOs try: self.nodes[0].accounttoaccount(accountGold, {toGold: "100@" + symbolGOLD}, [{"": 0}]) except JSONRPCException as e: errorString = e.error['message'] - assert("JSON value is not a string as expected" in errorString) + assert ("JSON value is not a string as expected" in errorString) # missing (account exists, but does not belong) - try: self.nodes[0].accounttoaccount(accountSilver, {accountGold: "100@" + symbolSILVER}, []) except JSONRPCException as e: errorString = e.error['message'] - assert("Incorrect auth" in errorString) + assert ("Incorrect auth" in errorString) # transfer self.nodes[0].accounttoaccount(accountGold, @@ -97,8 +99,10 @@ def run_test(self): assert_equal(self.nodes[0].getaccount(accountGold, {}, True)[idGold], initialGold - 100) assert_equal(self.nodes[0].getaccount(toGold, {}, True)[idGold], 100) - assert_equal(self.nodes[0].getaccount(accountGold, {}, True)[idGold], self.nodes[1].getaccount(accountGold, {}, True)[idGold]) - assert_equal(self.nodes[0].getaccount(toGold, {}, True)[idGold], self.nodes[1].getaccount(toGold, {}, True)[idGold]) + assert_equal(self.nodes[0].getaccount(accountGold, {}, True)[idGold], + self.nodes[1].getaccount(accountGold, {}, True)[idGold]) + assert_equal(self.nodes[0].getaccount(toGold, {}, True)[idGold], + self.nodes[1].getaccount(toGold, {}, True)[idGold]) # transfer between nodes self.nodes[1].accounttoaccount(accountSilver, @@ -109,70 +113,73 @@ def run_test(self): assert_equal(self.nodes[1].getaccount(accountSilver, {}, True)[idSilver], initialSilver - 100) assert_equal(self.nodes[0].getaccount(toSilver, {}, True)[idSilver], 100) - assert_equal(self.nodes[0].getaccount(accountSilver, {}, True)[idSilver], self.nodes[1].getaccount(accountSilver, {}, True)[idSilver]) - assert_equal(self.nodes[0].getaccount(toSilver, {}, True)[idSilver], self.nodes[1].getaccount(toSilver, {}, True)[idSilver]) + assert_equal(self.nodes[0].getaccount(accountSilver, {}, True)[idSilver], + self.nodes[1].getaccount(accountSilver, {}, True)[idSilver]) + assert_equal(self.nodes[0].getaccount(toSilver, {}, True)[idSilver], + self.nodes[1].getaccount(toSilver, {}, True)[idSilver]) # utxostoaccount # Only technically supported for DFI as accounttoutxxos blocks non-DFI transfers - #======================== - assert_raises_rpc_error(-4, "Unexpected token type set for recipient. Only native DFI token type expected.", self.nodes[0].utxostoaccount, {toGold: "100@" + symbolGOLD}) + # ======================== + assert_raises_rpc_error(-4, "Unexpected token type set for recipient. Only native DFI token type expected.", + self.nodes[0].utxostoaccount, {toGold: "100@" + symbolGOLD}) # missing amount try: self.nodes[0].utxostoaccount({toGold: ""}, []) except JSONRPCException as e: errorString = e.error['message'] - assert("Invalid amount" in errorString) + assert ("Invalid amount" in errorString) - #invalid UTXOs + # invalid UTXOs try: self.nodes[0].utxostoaccount({accountGold: "100@DFI"}, [{"": 0}]) except JSONRPCException as e: errorString = e.error['message'] - assert("Invalid amount" in errorString) + assert ("Invalid amount" in errorString) # transfer initialBalance = self.nodes[0].getbalances()['mine']['trusted'] self.nodes[0].utxostoaccount({accountGold: "100@DFI"}, []) self.nodes[0].generate(1) - assert(initialBalance != self.nodes[0].getbalances()['mine']['trusted']) + assert (initialBalance != self.nodes[0].getbalances()['mine']['trusted']) # accounttoutxos - #======================== + # ======================== # missing from (account) try: self.nodes[0].accounttoutxos(self.nodes[0].getnewaddress("", "legacy"), {toGold: "100@DFI"}, []) except JSONRPCException as e: errorString = e.error['message'] - assert("not enough balance" in errorString) + assert ("not enough balance" in errorString) # missing amount try: self.nodes[0].accounttoutxos(accountGold, {accountGold: ""}, []) except JSONRPCException as e: errorString = e.error['message'] - assert("Invalid amount" in errorString) + assert ("Invalid amount" in errorString) - #invalid UTXOs + # invalid UTXOs try: self.nodes[0].accounttoutxos(accountGold, {accountGold: "100@" + symbolGOLD}, [{"": 0}]) except JSONRPCException as e: errorString = e.error['message'] - assert("JSON value is not a string as expected" in errorString) + assert ("JSON value is not a string as expected" in errorString) # missing (account exists, but does not belong) try: self.nodes[0].accounttoutxos(accountSilver, {accountGold: "100@" + symbolSILVER}, []) except JSONRPCException as e: errorString = e.error['message'] - assert("Incorrect auth" in errorString) + assert ("Incorrect auth" in errorString) # missing (account exists, there are tokens, but not token 0) try: self.nodes[0].accounttoutxos(toSilver, {accountGold: "100@DFI"}, []) except JSONRPCException as e: errorString = e.error['message'] - assert("not enough balance" in errorString) + assert ("not enough balance" in errorString) # transfer try: @@ -180,13 +187,14 @@ def run_test(self): self.nodes[0].generate(1) except JSONRPCException as e: errorString = e.error['message'] - assert("only available for DFI transactions" in errorString) + assert ("only available for DFI transactions" in errorString) assert_equal(self.nodes[0].getaccount(accountGold, {}, True)[idGold], initialGold - 100) - assert_equal(self.nodes[0].getaccount(accountGold, {}, True)[idGold], self.nodes[1].getaccount(accountGold, {}, True)[idGold]) + assert_equal(self.nodes[0].getaccount(accountGold, {}, True)[idGold], + self.nodes[1].getaccount(accountGold, {}, True)[idGold]) # gettokenbalances - #======================== + # ======================== # check balances about all accounts belonging to the wallet assert_equal(self.nodes[0].gettokenbalances({}, True)[idGold], initialGold - 100) assert_equal(self.nodes[0].gettokenbalances({}, True)[idSilver], 100) @@ -194,11 +202,11 @@ def run_test(self): # chech work is_mine_only field list_all_acc = len(self.nodes[0].listaccounts({}, False, True, False)) list_mine_acc = len(self.nodes[0].listaccounts({}, False, True, True)) - assert(list_all_acc != list_mine_acc) + assert (list_all_acc != list_mine_acc) # REVERTING: - #======================== - print ("Reverting...") + # ======================== + print("Reverting...") self.start_node(2) self.nodes[2].generate(20) @@ -208,8 +216,8 @@ def run_test(self): assert_equal(self.nodes[0].getaccount(accountGold, {}, True)[idGold], initialGold) assert_equal(self.nodes[0].getaccount(accountSilver, {}, True)[idSilver], initialSilver) - assert_equal(len(self.nodes[0].getrawmempool()), 4) # 4 txs + assert_equal(len(self.nodes[0].getrawmempool()), 4) # 4 txs if __name__ == '__main__': - AccountsAndUTXOsTest ().main () + AccountsAndUTXOsTest().main() diff --git a/test/functional/feature_accounts_validation.py b/test/functional/feature_accounts_validation.py index c3cc12547c..37a09be2f9 100755 --- a/test/functional/feature_accounts_validation.py +++ b/test/functional/feature_accounts_validation.py @@ -8,6 +8,7 @@ from test_framework.test_framework import DefiTestFramework from test_framework.util import assert_equal + class AccountsValidatingTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 @@ -23,7 +24,7 @@ def run_test(self): node.generate(101) self.sync_blocks() - assert_equal(node.getblockcount(), 101) # eunos + assert_equal(node.getblockcount(), 101) # eunos # Get addresses and set up account account = node.getnewaddress() @@ -53,5 +54,6 @@ def run_test(self): # Check the blockchain has extended as expected assert_equal(node1.getblockcount(), blockcount + 1) + if __name__ == '__main__': - AccountsValidatingTest().main () + AccountsValidatingTest().main() diff --git a/test/functional/feature_anchor_rewards.py b/test/functional/feature_anchor_rewards.py index f4d39c5493..7f64a017ed 100755 --- a/test/functional/feature_anchor_rewards.py +++ b/test/functional/feature_anchor_rewards.py @@ -16,20 +16,21 @@ from decimal import Decimal import time -class AnchorRewardsTest (DefiTestFramework): + +class AnchorRewardsTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 3 self.extra_args = [ - [ "-dummypos=1", "-spv=1", '-amkheight=0', "-anchorquorum=2", "-dakotaheight=1", "-fortcanningheight=1"], - [ "-dummypos=1", "-spv=1", '-amkheight=0', "-anchorquorum=2", "-dakotaheight=1", "-fortcanningheight=1"], - [ "-dummypos=1", "-spv=1", '-amkheight=0', "-anchorquorum=2", "-dakotaheight=1", "-fortcanningheight=1"], + ["-dummypos=1", "-spv=1", '-amkheight=0', "-anchorquorum=2", "-dakotaheight=1", "-fortcanningheight=1"], + ["-dummypos=1", "-spv=1", '-amkheight=0', "-anchorquorum=2", "-dakotaheight=1", "-fortcanningheight=1"], + ["-dummypos=1", "-spv=1", '-amkheight=0', "-anchorquorum=2", "-dakotaheight=1", "-fortcanningheight=1"], ] self.setup_clean_chain = True - def mock_time(self, offset_hours, hours = 0): + def mock_time(self, offset_hours, hours=0): for i in range(0, self.num_nodes): self.nodes[i % self.num_nodes].set_mocktime(int((time.time() - offset_hours * 60 * 60) + (hours * 60 * 60))) - self.nodes[i % self.num_nodes].setmocktime(int((time.time() - offset_hours * 60 * 60) + (hours * 60 * 60))) + self.nodes[i % self.num_nodes].setmocktime(int((time.time() - offset_hours * 60 * 60) + (hours * 60 * 60))) # Masternodes have to mint blocks in the last 2 weeks to be valid for # anchor teams, function here mines on all available nodes in turn. @@ -90,7 +91,8 @@ def run_test(self): # Create multiple active MNs self.initmasternodesforanchors(13, 1 * anchorFrequency) - wait_until(lambda: len(self.nodes[0].getanchorteams()['auth']) == 3 and len(self.nodes[0].getanchorteams()['confirm']) == 3, timeout=10) + wait_until(lambda: len(self.nodes[0].getanchorteams()['auth']) == 3 and len( + self.nodes[0].getanchorteams()['confirm']) == 3, timeout=10) # Mo anchors created yet as we need three hours depth in chain assert_equal(len(self.nodes[0].spv_listanchorauths()), 0) @@ -104,7 +106,8 @@ def run_test(self): # Anchor data print(self.nodes[0].spv_listanchorauths()) print(self.nodes[0].getblockcount()) - wait_until(lambda: len(self.nodes[0].spv_listanchorauths()) > 0 and self.nodes[0].spv_listanchorauths()[0]['signers'] == 3, timeout=10) + wait_until(lambda: len(self.nodes[0].spv_listanchorauths()) > 0 and self.nodes[0].spv_listanchorauths()[0][ + 'signers'] == 3, timeout=10) auth = self.nodes[0].spv_listanchorauths() creation_height = auth[0]['creationHeight'] @@ -117,68 +120,68 @@ def run_test(self): # Check the time time_diff = block_creation['time'] - block15['time'] - assert(time_diff > 3 * 60 * 60) + assert (time_diff > 3 * 60 * 60) self.nodes[0].spv_setlastheight(1) self.nodes[1].spv_setlastheight(1) # Check errors assert_raises_rpc_error(None, "Not enough money", self.nodes[1].spv_createanchor, - [{ - 'txid': "a0d5a294be3cde6a8bddab5815b8c4cb1b2ebf2c2b8a4018205d6f8c576e8963", - 'vout': 3, - 'amount': 1000, - 'privkey': "cStbpreCo2P4nbehPXZAAM3gXXY1sAphRfEhj7ADaLx8i2BmxvEP" - }], "mgsE1SqrcfUhvuYuRjqy6rQCKmcCVKNhMu") + [{ + 'txid': "a0d5a294be3cde6a8bddab5815b8c4cb1b2ebf2c2b8a4018205d6f8c576e8963", + 'vout': 3, + 'amount': 1000, + 'privkey': "cStbpreCo2P4nbehPXZAAM3gXXY1sAphRfEhj7ADaLx8i2BmxvEP" + }], "mgsE1SqrcfUhvuYuRjqy6rQCKmcCVKNhMu") # Check some params: assert_raises_rpc_error(None, "Expected type array, got object", self.nodes[1].spv_createanchor, - { - 'txid': "a0d5a294be3cde6a8bddab5815b8c4cb1b2ebf2c2b8a4018205d6f8c576e8963", - 'vout': 3, - 'amount': 2262303, - 'privkey': "cStbpreCo2P4nbehPXZAAM3gXXY1sAphRfEhj7ADaLx8i2BmxvEP" - }, "mgsE1SqrcfUhvuYuRjqy6rQCKmcCVKNhMu") + { + 'txid': "a0d5a294be3cde6a8bddab5815b8c4cb1b2ebf2c2b8a4018205d6f8c576e8963", + 'vout': 3, + 'amount': 2262303, + 'privkey': "cStbpreCo2P4nbehPXZAAM3gXXY1sAphRfEhj7ADaLx8i2BmxvEP" + }, "mgsE1SqrcfUhvuYuRjqy6rQCKmcCVKNhMu") assert_raises_rpc_error(None, "txid must be of length 64", self.nodes[1].spv_createanchor, - [{ - 'txid': "a0d5a294be3cde6a8bddab5815b8c4cb1b2ebf2c2b8a4018205d6f8c576e8963aa", - 'vout': 3, - 'amount': 2262303, - 'privkey': "cStbpreCo2P4nbehPXZAAM3gXXY1sAphRfEhj7ADaLx8i2BmxvEP" - }], "mgsE1SqrcfUhvuYuRjqy6rQCKmcCVKNhMu") + [{ + 'txid': "a0d5a294be3cde6a8bddab5815b8c4cb1b2ebf2c2b8a4018205d6f8c576e8963aa", + 'vout': 3, + 'amount': 2262303, + 'privkey': "cStbpreCo2P4nbehPXZAAM3gXXY1sAphRfEhj7ADaLx8i2BmxvEP" + }], "mgsE1SqrcfUhvuYuRjqy6rQCKmcCVKNhMu") assert_raises_rpc_error(None, "value is not an integer", self.nodes[1].spv_createanchor, - [{ - 'txid': "a0d5a294be3cde6a8bddab5815b8c4cb1b2ebf2c2b8a4018205d6f8c576e8963", - 'vout': "aa", - 'amount': 2262303, - 'privkey': "cStbpreCo2P4nbehPXZAAM3gXXY1sAphRfEhj7ADaLx8i2BmxvEP" - }], "mgsE1SqrcfUhvuYuRjqy6rQCKmcCVKNhMu") + [{ + 'txid': "a0d5a294be3cde6a8bddab5815b8c4cb1b2ebf2c2b8a4018205d6f8c576e8963", + 'vout': "aa", + 'amount': 2262303, + 'privkey': "cStbpreCo2P4nbehPXZAAM3gXXY1sAphRfEhj7ADaLx8i2BmxvEP" + }], "mgsE1SqrcfUhvuYuRjqy6rQCKmcCVKNhMu") assert_raises_rpc_error(None, "Can't parse WIF privkey", self.nodes[1].spv_createanchor, - [{ - 'txid': "a0d5a294be3cde6a8bddab5815b8c4cb1b2ebf2c2b8a4018205d6f8c576e8963", - 'vout': 3, - 'amount': 2262303, - 'privkey': "1_cStbpreCo2P4nbehPXZAAM3gXXY1sAphRfEhj7ADaLx8i2BmxvEP" - }], "mgsE1SqrcfUhvuYuRjqy6rQCKmcCVKNhMu") + [{ + 'txid': "a0d5a294be3cde6a8bddab5815b8c4cb1b2ebf2c2b8a4018205d6f8c576e8963", + 'vout': 3, + 'amount': 2262303, + 'privkey': "1_cStbpreCo2P4nbehPXZAAM3gXXY1sAphRfEhj7ADaLx8i2BmxvEP" + }], "mgsE1SqrcfUhvuYuRjqy6rQCKmcCVKNhMu") assert_raises_rpc_error(None, "does not refer to a P2PKH or P2WPKH address", self.nodes[1].spv_createanchor, - [{ - 'txid': "a0d5a294be3cde6a8bddab5815b8c4cb1b2ebf2c2b8a4018205d6f8c576e8963", - 'vout': 3, - 'amount': 2262303, - 'privkey': "cStbpreCo2P4nbehPXZAAM3gXXY1sAphRfEhj7ADaLx8i2BmxvEP" - }], "__mgsE1SqrcfUhvuYuRjqy6rQCKmcCVKNhMu") + [{ + 'txid': "a0d5a294be3cde6a8bddab5815b8c4cb1b2ebf2c2b8a4018205d6f8c576e8963", + 'vout': 3, + 'amount': 2262303, + 'privkey': "cStbpreCo2P4nbehPXZAAM3gXXY1sAphRfEhj7ADaLx8i2BmxvEP" + }], "__mgsE1SqrcfUhvuYuRjqy6rQCKmcCVKNhMu") assert_raises_rpc_error(None, "does not refer to a P2PKH or P2WPKH address", self.nodes[1].spv_createanchor, - [{ - 'txid': "a0d5a294be3cde6a8bddab5815b8c4cb1b2ebf2c2b8a4018205d6f8c576e8963", - 'vout': 3, - 'amount': 2262303, - 'privkey': "cStbpreCo2P4nbehPXZAAM3gXXY1sAphRfEhj7ADaLx8i2BmxvEP" - }], "") + [{ + 'txid': "a0d5a294be3cde6a8bddab5815b8c4cb1b2ebf2c2b8a4018205d6f8c576e8963", + 'vout': 3, + 'amount': 2262303, + 'privkey': "cStbpreCo2P4nbehPXZAAM3gXXY1sAphRfEhj7ADaLx8i2BmxvEP" + }], "") # Test anchor creations rewardAddress0 = self.nodes[0].getnewaddress("", "legacy") @@ -210,7 +213,7 @@ def run_test(self): assert_equal(pending[1]['rewardAddress'], rewardAddress1) else: assert_equal(pending[0]['rewardAddress'], rewardAddress1) - assert_equal(pending[0]['confirmations'], 1) # Bitcoin confirmations + assert_equal(pending[0]['confirmations'], 1) # Bitcoin confirmations assert_equal(pending[0]['signatures'], 2) assert_equal(pending[0]['anchorCreationHeight'], creation_height) @@ -237,12 +240,12 @@ def run_test(self): assert_equal(anchors[1]['rewardAddress'], rewardAddress1) else: assert_equal(anchors[0]['rewardAddress'], rewardAddress1) - assert_equal(anchors[0]['confirmations'], 1) # Bitcoin confirmations + assert_equal(anchors[0]['confirmations'], 1) # Bitcoin confirmations assert_equal(anchors[0]['signatures'], 2) assert_equal(anchors[0]['anchorCreationHeight'], creation_height) assert_equal(anchors[0]['active'], False) - print ("Confs init:") + print("Confs init:") assert_equal(len(self.nodes[0].spv_listanchorrewardconfirms()), 0) self.nodes[0].spv_setlastheight(5) self.nodes[1].spv_setlastheight(5) @@ -250,7 +253,7 @@ def run_test(self): # Still no active anchor anchors = self.nodes[0].spv_listanchors() - assert_equal(anchors[0]['confirmations'], 5) # Bitcoin confirmations + assert_equal(anchors[0]['confirmations'], 5) # Bitcoin confirmations assert_equal(anchors[0]['active'], False) # important (!) to be synced before disconnection @@ -262,7 +265,7 @@ def run_test(self): anchors = self.nodes[0].spv_listanchors() print(anchors) - assert_equal(anchors[0]['confirmations'], 6) # Bitcoin confirmations + assert_equal(anchors[0]['confirmations'], 6) # Bitcoin confirmations if anchors[0]['active']: activeAnc = anchors[0] else: @@ -280,17 +283,18 @@ def run_test(self): # important to wait here! self.sync_blocks(self.nodes[0:2]) - wait_until(lambda: len(self.nodes[0].spv_listanchorrewardconfirms()) == 1 and self.nodes[0].spv_listanchorrewardconfirms()[0]['signers'] == 2, timeout=10) + wait_until(lambda: len(self.nodes[0].spv_listanchorrewardconfirms()) == 1 and + self.nodes[0].spv_listanchorrewardconfirms()[0]['signers'] == 2, timeout=10) conf0 = self.nodes[0].spv_listanchorrewardconfirms() - print ("Confs created, only active anchor") + print("Confs created, only active anchor") assert_equal(len(conf0), 1) assert_equal(conf0[0]['anchorHeight'], 15) assert_equal(conf0[0]['prevAnchorHeight'], 0) assert_equal(conf0[0]['rewardAddress'], activeAnc['rewardAddress']) assert_equal(conf0[0]['signers'], 2) - print ("Generate reward") + print("Generate reward") assert_equal(len(self.nodes[0].spv_listanchorrewards()), 0) # Reward before @@ -326,20 +330,22 @@ def run_test(self): if anchors[0]['btcAnchorHash'] != btcHash0: assert_equal(anchors[0]['btcAnchorHash'], btcHash1) - print ("Rollback!") + print("Rollback!") self.nodes[2].generate(2) connect_nodes_bi(self.nodes, 1, 2) self.sync_blocks() - wait_until(lambda: len(self.nodes[0].spv_listanchorrewardconfirms()) == 1, timeout=10) # while rollback, it should appear w/o wait + wait_until(lambda: len(self.nodes[0].spv_listanchorrewardconfirms()) == 1, + timeout=10) # while rollback, it should appear w/o wait assert_equal(len(self.nodes[0].spv_listanchorrewards()), 0) - wait_until(lambda: len(self.nodes[2].spv_listanchorrewardconfirms()) == 1, timeout=10) # but wait here + wait_until(lambda: len(self.nodes[2].spv_listanchorrewardconfirms()) == 1, timeout=10) # but wait here assert_equal(len(self.nodes[2].spv_listanchorrewards()), 0) - print ("Reward again") + print("Reward again") # Reward before - assert_equal(self.nodes[0].listcommunitybalances()['AnchorReward'], Decimal('6.30000000')) # 2 more blocks on this chain + assert_equal(self.nodes[0].listcommunitybalances()['AnchorReward'], + Decimal('6.30000000')) # 2 more blocks on this chain self.nodes[1].generate(1) self.sync_blocks() @@ -350,7 +356,7 @@ def run_test(self): wait_until(lambda: len(self.nodes[0].spv_listanchorrewardconfirms()) == 0, timeout=10) assert_equal(len(self.nodes[0].spv_listanchorrewards()), 1) - print ("Generate another reward") + print("Generate another reward") self.setlastheight(6) # Mine forward 6 hours, from 9 hours ago, 5 blocks an hour @@ -384,17 +390,20 @@ def run_test(self): # important to wait here! self.sync_blocks(self.nodes[0:2]) - wait_until(lambda: len(self.nodes[0].spv_listanchorrewardconfirms()) == 1 and self.nodes[0].spv_listanchorrewardconfirms()[0]['signers'] == 2, timeout=10) + wait_until(lambda: len(self.nodes[0].spv_listanchorrewardconfirms()) == 1 and + self.nodes[0].spv_listanchorrewardconfirms()[0]['signers'] == 2, timeout=10) # check confirmations (revoting) after node restart: self.stop_node(0) self.start_node(0, ['-txindex=1', '-amkheight=0', "-dakotaheight=1"]) connect_nodes_bi(self.nodes, 0, 1) self.sync_blocks(self.nodes[0:2]) - wait_until(lambda: len(self.nodes[0].spv_listanchorrewardconfirms()) == 1 and self.nodes[0].spv_listanchorrewardconfirms()[0]['signers'] == 2, timeout=10) + wait_until(lambda: len(self.nodes[0].spv_listanchorrewardconfirms()) == 1 and + self.nodes[0].spv_listanchorrewardconfirms()[0]['signers'] == 2, timeout=10) # Reward before - assert_equal(self.nodes[1].listcommunitybalances()['AnchorReward'], Decimal('7.60000000')) # 2 more blocks on this chain + assert_equal(self.nodes[1].listcommunitybalances()['AnchorReward'], + Decimal('7.60000000')) # 2 more blocks on this chain self.nodes[1].generate(1) @@ -402,7 +411,7 @@ def run_test(self): block_hash = self.nodes[1].getblockhash(block_height) # Reward after - assert_equal(self.nodes[1].listcommunitybalances()['AnchorReward'], Decimal('0.10000000')) # Subsidy halving! + assert_equal(self.nodes[1].listcommunitybalances()['AnchorReward'], Decimal('0.10000000')) # Subsidy halving! self.sync_blocks(self.nodes[0:2]) wait_until(lambda: len(self.nodes[0].spv_listanchorrewardconfirms()) == 0, timeout=10) @@ -417,12 +426,13 @@ def run_test(self): assert_equal(rew2tx['vout'][1]['scriptPubKey']['addresses'][0], rewardAddress2) assert_equal(rew2tx['vout'][1]['value'], Decimal('7.60000000')) - print ("Rollback a rewards") + print("Rollback a rewards") self.nodes[2].generate(3) connect_nodes_bi(self.nodes, 1, 2) self.sync_blocks() wait_until(lambda: len(self.nodes[0].spv_listanchorrewardconfirms()) == 1, timeout=10) assert_equal(len(self.nodes[0].spv_listanchorrewards()), 1) + if __name__ == '__main__': AnchorRewardsTest().main() diff --git a/test/functional/feature_anchorauths_pruning.py b/test/functional/feature_anchorauths_pruning.py index 3c7e30036a..48bc44c044 100755 --- a/test/functional/feature_anchorauths_pruning.py +++ b/test/functional/feature_anchorauths_pruning.py @@ -14,11 +14,12 @@ import time -class AnchorsAuthsPruningTest (DefiTestFramework): + +class AnchorsAuthsPruningTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.extra_args = [ - [ "-dummypos=1", "-spv=1", '-amkheight=0', "-dakotaheight=1", "-fortcanningheight=1"], + ["-dummypos=1", "-spv=1", '-amkheight=0', "-dakotaheight=1", "-fortcanningheight=1"], ] self.setup_clean_chain = True @@ -35,7 +36,7 @@ def run_test(self): assert_equal(len(self.nodes[0].spv_listanchors()), 0) # Checking starting set - assert_equal(len(self.nodes[0].spv_listanchorauths()), 2) # 15,30 + assert_equal(len(self.nodes[0].spv_listanchorauths()), 2) # 15,30 # Setting anchor self.nodes[0].spv_setlastheight(1) @@ -50,22 +51,23 @@ def run_test(self): assert_equal(txinfo['defiHeight'], 30) # Still the same - assert_equal(len(self.nodes[0].spv_listanchorauths()), 2) # 15,30 + assert_equal(len(self.nodes[0].spv_listanchorauths()), 2) # 15,30 self.genmocktime(int(time.time() + (12 * 60 * 60)), 6) # Couple of auths added - assert_equal(len(self.nodes[0].spv_listanchorauths()), 4) # + 45,60 + assert_equal(len(self.nodes[0].spv_listanchorauths()), 4) # + 45,60 # Nothing should change self.nodes[0].spv_setlastheight(5) - assert_equal(len(self.nodes[0].spv_listanchorauths()), 4) # 15,30,45,60 + assert_equal(len(self.nodes[0].spv_listanchorauths()), 4) # 15,30,45,60 # Pruning should occur self.nodes[0].spv_setlastheight(6) - auths = self.nodes[0].spv_listanchorauths() # 45,60 only + auths = self.nodes[0].spv_listanchorauths() # 45,60 only assert_equal(len(auths), 2) assert_equal(auths[0]['blockHeight'], 60) assert_equal(auths[1]['blockHeight'], 45) + if __name__ == '__main__': - AnchorsAuthsPruningTest ().main () + AnchorsAuthsPruningTest().main() diff --git a/test/functional/feature_any_accounts_to_accounts.py b/test/functional/feature_any_accounts_to_accounts.py index 2d2a15662b..c3c670ebb0 100755 --- a/test/functional/feature_any_accounts_to_accounts.py +++ b/test/functional/feature_any_accounts_to_accounts.py @@ -18,7 +18,8 @@ import random -class AnyAccountsToAccountsTest (DefiTestFramework): + +class AnyAccountsToAccountsTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 4 self.setup_clean_chain = True @@ -32,7 +33,7 @@ def set_test_params(self): ] def run_test(self): - assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI + assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI print("Generating initial chain...") tokens = [ @@ -111,7 +112,7 @@ def run_test(self): self.nodes[0].generate(1) for token in tokens: - if i == wallet1_accs_count - 1: # last account + if i == wallet1_accs_count - 1: # last account amount = minterAccountBalances[token["tokenId"]] else: amount = random.randint(0, minterAccountBalances[token["tokenId"]] // 2) @@ -123,8 +124,8 @@ def run_test(self): while repeat: try: token["wallet"].accounttoaccount( - token["collateralAddress"], # from - {node1_wallet[i]["address"]: str(amount) + "@" + token["symbolId"]}) # to + token["collateralAddress"], # from + {node1_wallet[i]["address"]: str(amount) + "@" + token["symbolId"]}) # to repeat = False except JSONRPCException as e: if ("Can't find any UTXO's for owner." in e.error["message"]): @@ -160,14 +161,14 @@ def run_test(self): to = {} to[wallet2_addr1] = ["20@" + tokens[0]["symbolId"], "20@" + tokens[1]["symbolId"]] - to[wallet2_addr2] = ["51@" + tokens[3]["symbolId"]] # we have only 50 + to[wallet2_addr2] = ["51@" + tokens[3]["symbolId"]] # we have only 50 try: self.nodes[1].sendtokenstoaddress({}, to, "forward") except JSONRPCException as e: errorString = e.error['message'] - assert("Not enough balance on wallet accounts" in errorString) + assert ("Not enough balance on wallet accounts" in errorString) # normal transfer from wallet1 to = {} @@ -191,7 +192,8 @@ def run_test(self): # send all remaining tokens to wallet1 change address wallet1_change_addr = self.nodes[1].getnewaddress("", "legacy") to = {} - to[wallet1_change_addr] = ["30@" + tokens[0]["symbolId"], "30@" + tokens[1]["symbolId"], "30@" + tokens[2]["symbolId"], "30@" + tokens[3]["symbolId"]] + to[wallet1_change_addr] = ["30@" + tokens[0]["symbolId"], "30@" + tokens[1]["symbolId"], + "30@" + tokens[2]["symbolId"], "30@" + tokens[3]["symbolId"]] self.nodes[1].sendtokenstoaddress({}, to) @@ -219,7 +221,8 @@ def run_test(self): accsFrom[wallet2_addr1] = ["20@" + tokens[0]["symbolId"], "20@" + tokens[1]["symbolId"]] accsFrom[wallet2_addr2] = ["20@" + tokens[2]["symbolId"], "20@" + tokens[3]["symbolId"]] to = {} - to[wallet1_change_addr] = ["20@" + tokens[0]["symbolId"], "20@" + tokens[1]["symbolId"], "20@" + tokens[2]["symbolId"], "20@" + tokens[3]["symbolId"]] + to[wallet1_change_addr] = ["20@" + tokens[0]["symbolId"], "20@" + tokens[1]["symbolId"], + "20@" + tokens[2]["symbolId"], "20@" + tokens[3]["symbolId"]] self.nodes[2].sendtokenstoaddress(accsFrom, to) @@ -230,8 +233,8 @@ def run_test(self): # check that wallet2 is empty wallet2_addr1_balance = self.nodes[0].getaccount(wallet2_addr1, {}, True) wallet2_addr2_balance = self.nodes[0].getaccount(wallet2_addr2, {}, True) - assert(not wallet2_addr1_balance) - assert(not wallet2_addr2_balance) + assert (not wallet2_addr1_balance) + assert (not wallet2_addr2_balance) # check that wallet1_change_addr has all tokens amount wallet1_change_addr_balance = self.nodes[0].getaccount(wallet1_change_addr, {}, True) @@ -241,7 +244,7 @@ def run_test(self): assert_equal(wallet1_change_addr_balance[tokens[3]["tokenId"]], Decimal(50)) # reverting - print ("Reverting...") + print("Reverting...") blocks = self.nodes[0].getblockcount() - start_block_count + 1 self.start_node(3) self.nodes[3].generate(blocks) @@ -252,14 +255,14 @@ def run_test(self): # check that wallet1 and wallet 2 is empty for node1_acc in node1_wallet: node1_acc_ballance = self.nodes[1].getaccount(node1_acc["address"], {}, True) - assert(not node1_acc_ballance) + assert (not node1_acc_ballance) wallet1_change_addr_balance = self.nodes[1].getaccount(wallet1_change_addr, {}, True) wallet2_addr1_balance = self.nodes[2].getaccount(wallet2_addr1, {}, True) wallet2_addr2_balance = self.nodes[2].getaccount(wallet2_addr2, {}, True) - assert(not wallet1_change_addr_balance) - assert(not wallet2_addr1_balance) - assert(not wallet2_addr2_balance) + assert (not wallet1_change_addr_balance) + assert (not wallet2_addr1_balance) + assert (not wallet2_addr2_balance) minterAccountBalances = self.nodes[0].getaccount(self.nodes[0].get_genesis_keys().ownerAuthAddress, {}, True) @@ -268,5 +271,6 @@ def run_test(self): assert_equal(minterAccountBalances[tokens[2]["tokenId"]], Decimal(50)) assert_equal(minterAccountBalances[tokens[3]["tokenId"]], Decimal(50)) + if __name__ == '__main__': AnyAccountsToAccountsTest().main() diff --git a/test/functional/feature_assumevalid.py b/test/functional/feature_assumevalid.py index dbaae784a8..f66ee7db28 100755 --- a/test/functional/feature_assumevalid.py +++ b/test/functional/feature_assumevalid.py @@ -47,12 +47,14 @@ from test_framework.test_framework import DefiTestFramework from test_framework.util import assert_equal + class BaseNode(P2PInterface): def send_header_for_blocks(self, new_blocks): headers_message = msg_headers() headers_message.headers = [CBlockHeader(b) for b in new_blocks] self.send_message(headers_message) + class AssumeValidTest(DefiTestFramework): def set_test_params(self): self.setup_clean_chain = True @@ -187,5 +189,6 @@ def run_test(self): self.send_blocks_until_disconnected(p2p2) self.assert_blockchain_height(self.nodes[2], 101) + if __name__ == '__main__': AssumeValidTest().main() diff --git a/test/functional/feature_asymmetric_fee.py b/test/functional/feature_asymmetric_fee.py index a36695fd5e..3f8dce50bb 100755 --- a/test/functional/feature_asymmetric_fee.py +++ b/test/functional/feature_asymmetric_fee.py @@ -12,11 +12,15 @@ from decimal import Decimal from math import trunc -class PoolPairAsymmetricTest (DefiTestFramework): + +class PoolPairAsymmetricTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True - self.extra_args = [['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-bayfrontgardensheight=1', '-dakotaheight=1', '-fortcanningheight=1', '-fortcanninghillheight=1', '-fortcanningroadheight=1', '-fortcanningspringheight=150', '-jellyfish_regtest=1']] + self.extra_args = [ + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-bayfrontgardensheight=1', '-dakotaheight=1', + '-fortcanningheight=1', '-fortcanninghillheight=1', '-fortcanningroadheight=1', + '-fortcanningspringheight=150', '-jellyfish_regtest=1']] def run_test(self): @@ -35,7 +39,7 @@ def pool_swaps(self): self.nodes[0].generate(150 - self.nodes[0].getblockcount()) # Set DUSD fee on in only - self.nodes[0].setgov({"ATTRIBUTES":{ + self.nodes[0].setgov({"ATTRIBUTES": { f'v0/poolpairs/{self.idDD}/token_a_fee_pct': '0.05', f'v0/poolpairs/{self.idDD}/token_a_fee_direction': 'in' }}) @@ -45,10 +49,10 @@ def pool_swaps(self): result = self.nodes[0].getpoolpair(self.idDD)[self.idDD] assert_equal(result['dexFeePctTokenA'], Decimal('0.05000000')) assert_equal(result['dexFeeInPctTokenA'], Decimal('0.05000000')) - assert('dexFeeOutPctTokenA' not in result) - assert('dexFeePctTokenB' not in result) - assert('dexFeeInPctTokenB' not in result) - assert('dexFeeOutPctTokenB' not in result) + assert ('dexFeeOutPctTokenA' not in result) + assert ('dexFeePctTokenB' not in result) + assert ('dexFeeInPctTokenB' not in result) + assert ('dexFeeOutPctTokenB' not in result) # Test DFI to DUSD, no fees incurred self.test_swap(self.symbolDFI, self.symbolDUSD, 0, 0) @@ -57,7 +61,7 @@ def pool_swaps(self): self.test_swap(self.symbolDUSD, self.symbolDFI, Decimal('0.05'), 0) # Set DUSD fee on out only - self.nodes[0].setgov({"ATTRIBUTES":{ + self.nodes[0].setgov({"ATTRIBUTES": { f'v0/poolpairs/{self.idDD}/token_a_fee_direction': 'out' }}) self.nodes[0].generate(1) @@ -65,11 +69,11 @@ def pool_swaps(self): # Check poolpair result = self.nodes[0].getpoolpair(self.idDD)[self.idDD] assert_equal(result['dexFeePctTokenA'], Decimal('0.05000000')) - assert('dexFeeInPctTokenA' not in result) + assert ('dexFeeInPctTokenA' not in result) assert_equal(result['dexFeeOutPctTokenA'], Decimal('0.05000000')) - assert('dexFeePctTokenB' not in result) - assert('dexFeeInPctTokenB' not in result) - assert('dexFeeOutPctTokenB' not in result) + assert ('dexFeePctTokenB' not in result) + assert ('dexFeeInPctTokenB' not in result) + assert ('dexFeeOutPctTokenB' not in result) # Test DFI to DUSD, 5% fee on DUSD self.test_swap(self.symbolDFI, self.symbolDUSD, 0, Decimal('0.05')) @@ -78,7 +82,7 @@ def pool_swaps(self): self.test_swap(self.symbolDUSD, self.symbolDFI, 0, 0) # Set DFI fee on in only - self.nodes[0].setgov({"ATTRIBUTES":{ + self.nodes[0].setgov({"ATTRIBUTES": { f'v0/poolpairs/{self.idDD}/token_a_fee_pct': '0', f'v0/poolpairs/{self.idDD}/token_a_fee_direction': 'both', f'v0/poolpairs/{self.idDD}/token_b_fee_pct': '0.05', @@ -88,12 +92,12 @@ def pool_swaps(self): # Check poolpair result = self.nodes[0].getpoolpair(self.idDD)[self.idDD] - assert('dexFeePctTokenA' not in result) - assert('dexFeeInPctTokenA' not in result) - assert('dexFeeOutPctTokenA' not in result) + assert ('dexFeePctTokenA' not in result) + assert ('dexFeeInPctTokenA' not in result) + assert ('dexFeeOutPctTokenA' not in result) assert_equal(result['dexFeePctTokenB'], Decimal('0.05000000')) assert_equal(result['dexFeeInPctTokenB'], Decimal('0.05000000')) - assert('dexFeeOutPctTokenB' not in result) + assert ('dexFeeOutPctTokenB' not in result) # Test DFI to DUSD, 5% fee on DFI self.test_swap(self.symbolDFI, self.symbolDUSD, Decimal('0.05'), 0) @@ -102,18 +106,18 @@ def pool_swaps(self): self.test_swap(self.symbolDUSD, self.symbolDFI, 0, 0) # Set DFI fee on out only - self.nodes[0].setgov({"ATTRIBUTES":{ + self.nodes[0].setgov({"ATTRIBUTES": { f'v0/poolpairs/{self.idDD}/token_b_fee_direction': 'out', }}) self.nodes[0].generate(1) # Check poolpair result = self.nodes[0].getpoolpair(self.idDD)[self.idDD] - assert('dexFeePctTokenA' not in result) - assert('dexFeeInPctTokenA' not in result) - assert('dexFeeOutPctTokenA' not in result) + assert ('dexFeePctTokenA' not in result) + assert ('dexFeeInPctTokenA' not in result) + assert ('dexFeeOutPctTokenA' not in result) assert_equal(result['dexFeePctTokenB'], Decimal('0.05000000')) - assert('dexFeeInPctTokenB' not in result) + assert ('dexFeeInPctTokenB' not in result) assert_equal(result['dexFeeOutPctTokenB'], Decimal('0.05000000')) # Test DFI to DUSD, no fees incurred @@ -123,7 +127,7 @@ def pool_swaps(self): self.test_swap(self.symbolDUSD, self.symbolDFI, 0, Decimal('0.05')) # Set DFI and DUSD fee on in only - self.nodes[0].setgov({"ATTRIBUTES":{ + self.nodes[0].setgov({"ATTRIBUTES": { f'v0/poolpairs/{self.idDD}/token_a_fee_pct': '0.05', f'v0/poolpairs/{self.idDD}/token_a_fee_direction': 'in', f'v0/poolpairs/{self.idDD}/token_b_fee_direction': 'in', @@ -134,10 +138,10 @@ def pool_swaps(self): result = self.nodes[0].getpoolpair(self.idDD)[self.idDD] assert_equal(result['dexFeePctTokenA'], Decimal('0.05000000')) assert_equal(result['dexFeeInPctTokenA'], Decimal('0.05000000')) - assert('dexFeeOutPctTokenA' not in result) + assert ('dexFeeOutPctTokenA' not in result) assert_equal(result['dexFeePctTokenB'], Decimal('0.05000000')) assert_equal(result['dexFeeInPctTokenB'], Decimal('0.05000000')) - assert('dexFeeOutPctTokenB' not in result) + assert ('dexFeeOutPctTokenB' not in result) # Test DFI to DUSD, 5% fee on DFI self.test_swap(self.symbolDFI, self.symbolDUSD, Decimal('0.05'), 0) @@ -146,7 +150,7 @@ def pool_swaps(self): self.test_swap(self.symbolDUSD, self.symbolDFI, Decimal('0.05'), 0) # Set DFI and DUSD fee on out only - self.nodes[0].setgov({"ATTRIBUTES":{ + self.nodes[0].setgov({"ATTRIBUTES": { f'v0/poolpairs/{self.idDD}/token_a_fee_direction': 'out', f'v0/poolpairs/{self.idDD}/token_b_fee_direction': 'out', }}) @@ -155,10 +159,10 @@ def pool_swaps(self): # Check poolpair result = self.nodes[0].getpoolpair(self.idDD)[self.idDD] assert_equal(result['dexFeePctTokenA'], Decimal('0.05000000')) - assert('dexFeeInPctTokenA' not in result) + assert ('dexFeeInPctTokenA' not in result) assert_equal(result['dexFeeOutPctTokenA'], Decimal('0.05000000')) assert_equal(result['dexFeePctTokenB'], Decimal('0.05000000')) - assert('dexFeeInPctTokenB' not in result) + assert ('dexFeeInPctTokenB' not in result) assert_equal(result['dexFeeOutPctTokenB'], Decimal('0.05000000')) # Test DFI to DUSD, 5% fee on DUSD @@ -168,7 +172,7 @@ def pool_swaps(self): self.test_swap(self.symbolDUSD, self.symbolDFI, 0, Decimal('0.05')) # Set DFI and DUSD fee on both, normal behaviour. - self.nodes[0].setgov({"ATTRIBUTES":{ + self.nodes[0].setgov({"ATTRIBUTES": { f'v0/poolpairs/{self.idDD}/token_a_fee_direction': 'both', f'v0/poolpairs/{self.idDD}/token_b_fee_direction': 'both', }}) @@ -232,7 +236,7 @@ def setup_test_pools(self): "commission": Decimal('0'), "status": True, "ownerAddress": self.address, - "symbol" : self.symbolDD + "symbol": self.symbolDD }) self.nodes[0].generate(1) @@ -295,5 +299,6 @@ def test_swap(self, token_from, token_to, fee_in, fee_out): self.nodes[0].invalidateblock(self.nodes[0].getblockhash(self.nodes[0].getblockcount())) self.nodes[0].clearmempool() + if __name__ == '__main__': PoolPairAsymmetricTest().main() diff --git a/test/functional/feature_auth_return_change.py b/test/functional/feature_auth_return_change.py index 529a1c5e44..12da1917ec 100755 --- a/test/functional/feature_auth_return_change.py +++ b/test/functional/feature_auth_return_change.py @@ -10,21 +10,23 @@ from test_framework.util import assert_equal from decimal import Decimal + class TokensAuthChange(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True - self.extra_args = [['-txindex=1', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=50']] + self.extra_args = [ + ['-txindex=1', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=50']] # Move all coins to new address and change address to test auto auth def clear_auth_utxos(self): non_auth_address = self.nodes[0].getnewaddress("", "legacy") balance = self.nodes[0].getbalance() - self.nodes[0].sendtoaddress(non_auth_address, balance - Decimal("0.1")) # 0.1 to cover fee + self.nodes[0].sendtoaddress(non_auth_address, balance - Decimal("0.1")) # 0.1 to cover fee self.nodes[0].generate(1, 1000000, non_auth_address) # Check output/input count and addresses are expected - def check_auto_auth_txs(self, tx, owner, outputs = 2): + def check_auto_auth_txs(self, tx, owner, outputs=2): # Get auto auth TXs final_rawtx = self.nodes[0].getrawtransaction(tx, 1) auth_tx = self.nodes[0].getrawtransaction(final_rawtx['vin'][0]['txid'], 1) @@ -88,7 +90,7 @@ def run_test(self): self.clear_auth_utxos() # Update token - updatetx = self.nodes[0].updatetoken(token_a, {"symbol":"SILVER"}) + updatetx = self.nodes[0].updatetoken(token_a, {"symbol": "SILVER"}) self.nodes[0].generate(1, 1000000, coinbase) # Make sure token updated as expected @@ -158,7 +160,8 @@ def run_test(self): # Change to pool collateral address final_rawtx = self.nodes[0].getrawtransaction(poolpair_tx, 1) - assert_equal(final_rawtx['vout'][1]['scriptPubKey']['addresses'][0], self.nodes[0].PRIV_KEYS[0].ownerAuthAddress) + assert_equal(final_rawtx['vout'][1]['scriptPubKey']['addresses'][0], + self.nodes[0].PRIV_KEYS[0].ownerAuthAddress) # Clear auth UTXOs self.clear_auth_utxos() @@ -177,7 +180,7 @@ def run_test(self): pool_share = self.nodes[0].getnewaddress("", "legacy") liquidity_tx = self.nodes[0].addpoolliquidity({ collateral_a: ['100@' + token_a, '100@' + token_b] - }, pool_share) + }, pool_share) self.nodes[0].generate(1, 1000000, coinbase) # Check auto auth TX @@ -233,7 +236,7 @@ def run_test(self): self.clear_auth_utxos() # Test setgox TX - setgov_tx = self.nodes[0].setgov({ "LP_DAILY_DFI_REWARD": 35}) + setgov_tx = self.nodes[0].setgov({"LP_DAILY_DFI_REWARD": 35}) self.nodes[0].generate(1) # Check auto auth TX @@ -243,7 +246,7 @@ def run_test(self): self.nodes[0].utxostoaccount({collateral_a: "1@0"}) self.nodes[0].generate(1) - tokenstoaddress_tx = self.nodes[0].sendtokenstoaddress({collateral_a:"1@0"}, {collateral_b:"1@0"}) + tokenstoaddress_tx = self.nodes[0].sendtokenstoaddress({collateral_a: "1@0"}, {collateral_b: "1@0"}) self.nodes[0].generate(1) # Check auto auth TX @@ -277,13 +280,14 @@ def run_test(self): # Check auto auth TX final_rawtx = self.nodes[0].getrawtransaction(create_tx, 1) - assert_equal(final_rawtx['vout'][2]['scriptPubKey']['addresses'][0], self.nodes[0].PRIV_KEYS[0].ownerAuthAddress) + assert_equal(final_rawtx['vout'][2]['scriptPubKey']['addresses'][0], + self.nodes[0].PRIV_KEYS[0].ownerAuthAddress) # Clear auth UTXOs self.clear_auth_utxos() # Update DAT token - updatetx = self.nodes[0].updatetoken(token_c, {"symbol":"COPPER"}) + updatetx = self.nodes[0].updatetoken(token_c, {"symbol": "COPPER"}) self.nodes[0].generate(1, 1000000, coinbase) # Make sure token updated as expected @@ -293,5 +297,6 @@ def run_test(self): # Check auto auth TX self.check_auto_auth_txs(updatetx, self.nodes[0].PRIV_KEYS[0].ownerAuthAddress) + if __name__ == '__main__': TokensAuthChange().main() diff --git a/test/functional/feature_autoauth.py b/test/functional/feature_autoauth.py index 3ae48c729d..22fefb0d45 100755 --- a/test/functional/feature_autoauth.py +++ b/test/functional/feature_autoauth.py @@ -13,17 +13,19 @@ from test_framework.util import assert_equal, assert_raises_rpc_error from decimal import Decimal -class TokensAutoAuthTest (DefiTestFramework): + +class TokensAutoAuthTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True - self.extra_args = [['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-regtest-minttoken-simulate-mainnet=1']] + self.extra_args = [ + ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-regtest-minttoken-simulate-mainnet=1']] # Move all coins to new address and change address to test auto auth def clear_auth_utxos(self): non_auth_address = self.nodes[0].getnewaddress("", "legacy") balance = self.nodes[0].getbalance() - self.nodes[0].sendtoaddress(non_auth_address, balance - Decimal("0.1")) # 0.1 to cover fee + self.nodes[0].sendtoaddress(non_auth_address, balance - Decimal("0.1")) # 0.1 to cover fee self.nodes[0].generate(1, 1000000, non_auth_address) def run_test(self): @@ -32,7 +34,7 @@ def run_test(self): coinbase = n0.getnewaddress("", "legacy") n0.generate(102, 1000000, coinbase) - #==== Masternodes auth: + # ==== Masternodes auth: # RPC 'resignmasternode' mnCollateral = n0.getnewaddress("", "legacy") mnId = n0.createmasternode(mnCollateral) @@ -42,7 +44,8 @@ def run_test(self): assert_equal(len(n0.listmasternodes()), 9) assert_equal(len(n0.getrawmempool()), 0) - assert_raises_rpc_error(-32600, "tx must have at least one input from the owner", n0.resignmasternode, mnId, [n0.listunspent()[0]]) + assert_raises_rpc_error(-32600, "tx must have at least one input from the owner", n0.resignmasternode, mnId, + [n0.listunspent()[0]]) n0.resignmasternode(mnId) assert_equal(len(n0.getrawmempool()), 2) @@ -50,8 +53,7 @@ def run_test(self): assert_equal(n0.listmasternodes()[mnId]['state'], 'PRE_RESIGNED') assert_equal(len(n0.getrawmempool()), 0) - - #==== Tokens auth: + # ==== Tokens auth: # RPC 'createtoken' collateralGold = self.nodes[0].getnewaddress("", "legacy") assert_raises_rpc_error(-32600, "tx not from foundation member", n0.createtoken, { @@ -76,11 +78,12 @@ def run_test(self): self.clear_auth_utxos() # RPC 'updatetoken' - assert_raises_rpc_error(-32600, "tx must have at least one input from the owner", n0.updatetoken, "GOLD", {"isDAT": False}, [n0.listunspent()[0]]) + assert_raises_rpc_error(-32600, "tx must have at least one input from the owner", n0.updatetoken, "GOLD", + {"isDAT": False}, [n0.listunspent()[0]]) n0.updatetoken( "GOLD", {"isDAT": False} - ) + ) assert_equal(len(n0.getrawmempool()), 2) n0.generate(1, 1000000, coinbase) assert_equal(n0.listtokens()['1']["isDAT"], False) @@ -104,17 +107,17 @@ def run_test(self): # Clear auth UTXOs self.clear_auth_utxos() - assert_raises_rpc_error(-32600, "tx must have at least one input from token owner", n0.minttokens, ["1000@GOLD#1", "1000@SILVER"], [n0.listunspent()[0]]) + assert_raises_rpc_error(-32600, "tx must have at least one input from token owner", n0.minttokens, + ["1000@GOLD#1", "1000@SILVER"], [n0.listunspent()[0]]) n0.minttokens(["1000@GOLD#1", "5000@SILVER"]) assert_equal(len(n0.getrawmempool()), 2) n0.generate(1, 1000000, coinbase) assert_equal(len(n0.getrawmempool()), 0) - assert_equal(n0.getaccount(collateralGold, {}, True)['1'], 1000) + assert_equal(n0.getaccount(collateralGold, {}, True)['1'], 1000) assert_equal(n0.getaccount(collateralSilver, {}, True)['2'], 5000) - - #==== Liquidity Pools auth: + # ==== Liquidity Pools auth: # RPC 'createpoolpair' poolOwner = n0.getnewaddress("", "legacy") assert_raises_rpc_error(-32600, "tx not from foundation member", n0.createpoolpair, { @@ -153,8 +156,7 @@ def run_test(self): assert_equal(len(n0.getrawmempool()), 2) n0.generate(1, 1000000, coinbase) assert_equal(len(n0.getrawmempool()), 0) - assert(n0.getaccount(poolShare, {}, True)['3'] > 200) # 223.... - + assert (n0.getaccount(poolShare, {}, True)['3'] > 200) # 223.... # RPC 'poolswap' swapped = n0.getnewaddress("", "legacy") @@ -176,24 +178,24 @@ def run_test(self): assert_equal(len(n0.getrawmempool()), 2) n0.generate(1, 1000000, coinbase) assert_equal(len(n0.getrawmempool()), 0) - assert(n0.getaccount(swapped, {}, True)['2'] > 45) + assert (n0.getaccount(swapped, {}, True)['2'] > 45) # Clear auth UTXOs self.clear_auth_utxos() # RPC 'removepoolliquidity' - assert_raises_rpc_error(-32600, "tx must have at least one input from account owner", n0.removepoolliquidity, poolShare, "200@GS", [n0.listunspent()[0]]) + assert_raises_rpc_error(-32600, "tx must have at least one input from account owner", n0.removepoolliquidity, + poolShare, "200@GS", [n0.listunspent()[0]]) n0.removepoolliquidity(poolShare, "200@GS") assert_equal(len(n0.getrawmempool()), 2) n0.generate(1, 1000000, coinbase) assert_equal(len(n0.getrawmempool()), 0) - assert_equal(len(n0.getaccount(poolShare, {}, True)), 3) # so gold and silver appears + assert_equal(len(n0.getaccount(poolShare, {}, True)), 3) # so gold and silver appears # Clear auth UTXOs self.clear_auth_utxos() - # RPC 'updatepoolpair' assert_raises_rpc_error(-32600, "tx not from foundation member", n0.updatepoolpair, { "pool": "GS", @@ -211,20 +213,20 @@ def run_test(self): # Clear auth UTXOs self.clear_auth_utxos() - # RPC 'setgov' - assert_raises_rpc_error(-32600, "tx not from foundation member", n0.setgov, { "LP_DAILY_DFI_REWARD": 35.5 }, [n0.listunspent()[0]]) + assert_raises_rpc_error(-32600, "tx not from foundation member", n0.setgov, {"LP_DAILY_DFI_REWARD": 35.5}, + [n0.listunspent()[0]]) - n0.setgov({ "LP_DAILY_DFI_REWARD": 35.5 }) + n0.setgov({"LP_DAILY_DFI_REWARD": 35.5}) assert_equal(len(n0.getrawmempool()), 2) n0.generate(1, 1000000, coinbase) assert_equal(len(n0.getrawmempool()), 0) - - #==== Transfer auths: + # ==== Transfer auths: # RPC 'accounttoaccount' - assert_raises_rpc_error(-32600, "tx must have at least one input from account owner", n0.accounttoaccount, poolShare, {swapped: "1@GS"}, [n0.listunspent()[0]]) + assert_raises_rpc_error(-32600, "tx must have at least one input from account owner", n0.accounttoaccount, + poolShare, {swapped: "1@GS"}, [n0.listunspent()[0]]) n0.accounttoaccount(poolShare, {swapped: "10@GS"}) assert_equal(len(n0.getrawmempool()), 2) @@ -247,14 +249,15 @@ def run_test(self): # RPC 'accounttoutxos' n0.utxostoaccount({swapped: "1@DFI"}) n0.generate(1, 1000000, coinbase) - assert_raises_rpc_error(-32600, "tx must have at least one input from account owner", n0.accounttoutxos, swapped, {swapped: "0.2"}, [n0.listunspent()[0]]) + assert_raises_rpc_error(-32600, "tx must have at least one input from account owner", n0.accounttoutxos, + swapped, {swapped: "0.2"}, [n0.listunspent()[0]]) n0.accounttoutxos(swapped, {swapped: "0.2"}) assert_equal(len(n0.getrawmempool()), 2) n0.generate(1, 1000000, coinbase) assert_equal(len(n0.getrawmempool()), 0) - assert_equal(n0.listunspent(addresses = [swapped] )[1]['amount'], Decimal('0.2')) + assert_equal(n0.listunspent(addresses=[swapped])[1]['amount'], Decimal('0.2')) if __name__ == '__main__': - TokensAutoAuthTest ().main () + TokensAutoAuthTest().main() diff --git a/test/functional/feature_bip68_sequence.py b/test/functional/feature_bip68_sequence.py index 0f969016cf..c28e58ad9e 100755 --- a/test/functional/feature_bip68_sequence.py +++ b/test/functional/feature_bip68_sequence.py @@ -18,14 +18,15 @@ satoshi_round, ) -SEQUENCE_LOCKTIME_DISABLE_FLAG = (1<<31) -SEQUENCE_LOCKTIME_TYPE_FLAG = (1<<22) # this means use time (0 means height) -SEQUENCE_LOCKTIME_GRANULARITY = 9 # this is a bit-shift +SEQUENCE_LOCKTIME_DISABLE_FLAG = (1 << 31) +SEQUENCE_LOCKTIME_TYPE_FLAG = (1 << 22) # this means use time (0 means height) +SEQUENCE_LOCKTIME_GRANULARITY = 9 # this is a bit-shift SEQUENCE_LOCKTIME_MASK = 0x0000ffff # RPC error for non-BIP68 final transactions NOT_FINAL_ERROR = "non-BIP68-final (code 64)" + class BIP68Test(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 @@ -69,7 +70,7 @@ def run_test(self): def test_disable_flag(self): # Create some unconfirmed inputs new_addr = self.nodes[0].getnewaddress() - self.nodes[0].sendtoaddress(new_addr, 2) # send 2 BTC + self.nodes[0].sendtoaddress(new_addr, 2) # send 2 BTC utxos = self.nodes[0].listunspent(0, 0) assert len(utxos) > 0 @@ -77,7 +78,7 @@ def test_disable_flag(self): utxo = utxos[0] tx1 = CTransaction() - value = int(satoshi_round(utxo["amount"] - self.relayfee)*COIN) + value = int(satoshi_round(utxo["amount"] - self.relayfee) * COIN) # Check that the disable flag disables relative locktime. # If sequence locks were used, this would require 1 block for the @@ -110,7 +111,7 @@ def test_disable_flag(self): # Calculate the median time past of a prior block ("confirmations" before # the current tip). def get_median_time_past(self, confirmations): - block_hash = self.nodes[0].getblockhash(self.nodes[0].getblockcount()-confirmations) + block_hash = self.nodes[0].getblockhash(self.nodes[0].getblockcount() - confirmations) return self.nodes[0].getblockheader(block_hash)["mediantime"] # Test that sequence locks are respected for transactions spending confirmed inputs. @@ -127,7 +128,7 @@ def test_sequence_lock_confirmed_inputs(self): num_outputs = random.randint(1, max_outputs) outputs = {} for i in range(num_outputs): - outputs[addresses[i]] = random.randint(1, 20)*0.01 + outputs[addresses[i]] = random.randint(1, 20) * 0.01 self.nodes[0].sendmany("", outputs) self.nodes[0].generate(1) @@ -153,14 +154,14 @@ def test_sequence_lock_confirmed_inputs(self): tx.nVersion = 2 value = 0 for j in range(num_inputs): - sequence_value = 0xfffffffe # this disables sequence locks + sequence_value = 0xfffffffe # this disables sequence locks # 50% chance we enable sequence locks - if random.randint(0,1): + if random.randint(0, 1): using_sequence_locks = True # 10% of the time, make the input sequence value pass - input_will_pass = (random.randint(1,10) == 1) + input_will_pass = (random.randint(1, 10) == 1) sequence_value = utxos[j]["confirmations"] if not input_will_pass: sequence_value += 1 @@ -171,7 +172,7 @@ def test_sequence_lock_confirmed_inputs(self): # from the tip so that we're looking up MTP of the block # PRIOR to the one the input appears in, as per the BIP68 spec. orig_time = self.get_median_time_past(utxos[j]["confirmations"]) - cur_time = self.get_median_time_past(0) # MTP of the tip + cur_time = self.get_median_time_past(0) # MTP of the tip # can only timelock this input if it's not too old -- otherwise use height can_time_lock = True @@ -179,19 +180,19 @@ def test_sequence_lock_confirmed_inputs(self): can_time_lock = False # if time-lockable, then 50% chance we make this a time lock - if random.randint(0,1) and can_time_lock: + if random.randint(0, 1) and can_time_lock: # Find first time-lock value that fails, or latest one that succeeds time_delta = sequence_value << SEQUENCE_LOCKTIME_GRANULARITY if input_will_pass and time_delta > cur_time - orig_time: sequence_value = ((cur_time - orig_time) >> SEQUENCE_LOCKTIME_GRANULARITY) elif (not input_will_pass and time_delta <= cur_time - orig_time): - sequence_value = ((cur_time - orig_time) >> SEQUENCE_LOCKTIME_GRANULARITY)+1 + sequence_value = ((cur_time - orig_time) >> SEQUENCE_LOCKTIME_GRANULARITY) + 1 sequence_value |= SEQUENCE_LOCKTIME_TYPE_FLAG tx.vin.append(CTxIn(COutPoint(int(utxos[j]["txid"], 16), utxos[j]["vout"]), nSequence=sequence_value)) - value += utxos[j]["amount"]*COIN + value += utxos[j]["amount"] * COIN # Overestimate the size of the tx - signatures should be less than 120 bytes, and leave 50 for the output - tx_size = len(ToHex(tx))//2 + 120*num_inputs + 50 - tx.vout.append(CTxOut(int(value-self.relayfee*tx_size*COIN/1000), CScript([b'a']))) + tx_size = len(ToHex(tx)) // 2 + 120 * num_inputs + 50 + tx.vout.append(CTxOut(int(value - self.relayfee * tx_size * COIN / 1000), CScript([b'a']))) rawtx = self.nodes[0].signrawtransactionwithwallet(ToHex(tx))["hex"] if (using_sequence_locks and not should_pass): @@ -220,7 +221,7 @@ def test_sequence_lock_unconfirmed_inputs(self): tx2 = CTransaction() tx2.nVersion = 2 tx2.vin = [CTxIn(COutPoint(tx1.sha256, 0), nSequence=0)] - tx2.vout = [CTxOut(int(tx1.vout[0].nValue - self.relayfee*COIN), CScript([b'a']))] + tx2.vout = [CTxOut(int(tx1.vout[0].nValue - self.relayfee * COIN), CScript([b'a']))] tx2_raw = self.nodes[0].signrawtransactionwithwallet(ToHex(tx2))["hex"] tx2 = FromHex(tx2, tx2_raw) tx2.rehash() @@ -255,7 +256,7 @@ def test_nonzero_locks(orig_tx, node, relayfee, use_height_lock): # Now mine some blocks, but make sure tx2 doesn't get mined. # Use prioritisetransaction to lower the effective feerate to 0 - self.nodes[0].prioritisetransaction(txid=tx2.hash, fee_delta=int(-self.relayfee*COIN)) + self.nodes[0].prioritisetransaction(txid=tx2.hash, fee_delta=int(-self.relayfee * COIN)) cur_time = int(time.time()) for i in range(10): # self.nodes[0].setmocktime(cur_time + 600) @@ -269,7 +270,7 @@ def test_nonzero_locks(orig_tx, node, relayfee, use_height_lock): test_nonzero_locks(tx2, self.nodes[0], self.relayfee, use_height_lock=False) # Mine tx2, and then try again - self.nodes[0].prioritisetransaction(txid=tx2.hash, fee_delta=int(self.relayfee*COIN)) + self.nodes[0].prioritisetransaction(txid=tx2.hash, fee_delta=int(self.relayfee * COIN)) # Advance the time on the node so that we can test timelocks TestNode.Mocktime = cur_time + 600 @@ -295,7 +296,7 @@ def test_nonzero_locks(orig_tx, node, relayfee, use_height_lock): utxos = self.nodes[0].listunspent() tx5.vin.append(CTxIn(COutPoint(int(utxos[0]["txid"], 16), utxos[0]["vout"]), nSequence=1)) - tx5.vout[0].nValue += int(utxos[0]["amount"]*COIN) + tx5.vout[0].nValue += int(utxos[0]["amount"] * COIN) raw_tx5 = self.nodes[0].signrawtransactionwithwallet(ToHex(tx5))["hex"] assert_raises_rpc_error(-26, NOT_FINAL_ERROR, self.nodes[0].sendrawtransaction, raw_tx5) @@ -317,7 +318,7 @@ def test_nonzero_locks(orig_tx, node, relayfee, use_height_lock): # diagram above). # This would cause tx2 to be added back to the mempool, which in turn causes # tx3 to be removed. - tip = int(self.nodes[0].getblockhash(self.nodes[0].getblockcount()-1), 16) + tip = int(self.nodes[0].getblockhash(self.nodes[0].getblockcount() - 1), 16) height = self.nodes[0].getblockcount() for i in range(2): block = create_block(tip, create_coinbase(height), cur_time) @@ -335,7 +336,7 @@ def test_nonzero_locks(orig_tx, node, relayfee, use_height_lock): # Reset the chain and get rid of the mocktimed-blocks # self.nodes[0].setmocktime(0) # commented cause will be no generation otherwise - self.nodes[0].invalidateblock(self.nodes[0].getblockhash(cur_height+1)) + self.nodes[0].invalidateblock(self.nodes[0].getblockhash(cur_height + 1)) self.nodes[0].generate(10) # Make sure that BIP68 isn't being used to validate blocks prior to @@ -352,7 +353,7 @@ def test_bip68_not_consensus(self): tx2 = CTransaction() tx2.nVersion = 1 tx2.vin = [CTxIn(COutPoint(tx1.sha256, 0), nSequence=0)] - tx2.vout = [CTxOut(int(tx1.vout[0].nValue - self.relayfee*COIN), CScript([b'a']))] + tx2.vout = [CTxOut(int(tx1.vout[0].nValue - self.relayfee * COIN), CScript([b'a']))] # sign tx2 tx2_raw = self.nodes[0].signrawtransactionwithwallet(ToHex(tx2))["hex"] @@ -362,7 +363,7 @@ def test_bip68_not_consensus(self): self.nodes[0].sendrawtransaction(ToHex(tx2)) # Now make an invalid spend of tx2 according to BIP68 - sequence_value = 100 # 100 block relative locktime + sequence_value = 100 # 100 block relative locktime tx3 = CTransaction() tx3.nVersion = 2 @@ -374,7 +375,7 @@ def test_bip68_not_consensus(self): # make a block that violates bip68; ensure that the tip updates tip = int(self.nodes[0].getbestblockhash(), 16) - block = create_block(tip, create_coinbase(self.nodes[0].getblockcount()+1), TestNode.Mocktime) + block = create_block(tip, create_coinbase(self.nodes[0].getblockcount() + 1), TestNode.Mocktime) block.nVersion = 3 block.vtx.extend([tx1, tx2, tx3]) block.hashMerkleRoot = block.calc_merkle_root() @@ -397,8 +398,8 @@ def activateCSV(self): # Use self.nodes[1] to test that version 2 transactions are standard. def test_version2_relay(self): - inputs = [ ] - outputs = { self.nodes[1].getnewaddress() : 1.0 } + inputs = [] + outputs = {self.nodes[1].getnewaddress(): 1.0} rawtx = self.nodes[1].createrawtransaction(inputs, outputs) rawtxfund = self.nodes[1].fundrawtransaction(rawtx)['hex'] tx = FromHex(CTransaction(), rawtxfund) @@ -406,5 +407,6 @@ def test_version2_relay(self): tx_signed = self.nodes[1].signrawtransactionwithwallet(ToHex(tx))["hex"] self.nodes[1].sendrawtransaction(tx_signed) + if __name__ == '__main__': BIP68Test().main() diff --git a/test/functional/feature_bitcoin_htlc.py b/test/functional/feature_bitcoin_htlc.py index 85fd866582..5e2ff7bf78 100755 --- a/test/functional/feature_bitcoin_htlc.py +++ b/test/functional/feature_bitcoin_htlc.py @@ -12,11 +12,12 @@ from decimal import Decimal import os + class BitcoinHTLCTests(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.extra_args = [ - [ "-dummypos=1", "-spv=1"], + ["-dummypos=1", "-spv=1"], ] self.setup_clean_chain = True @@ -36,40 +37,53 @@ def run_test(self): seed_hash = "df95183883789f237977543885e1f82ddc045a3ba90c8f25b43a5b797a35d20e" # Make sure addresses were imported and added to Bitcoin wallet - assert_equal(self.nodes[0].spv_dumpprivkey("bcrt1qs2qsynezncmkzef3qsaaumf5r5uvyeh8ykrg37"), "cSkTV5jWJnKiqMUuuBWo6Sb99UMtddxXerDNQGfU1jJ8WiZoSTRh") - assert_equal(self.nodes[0].spv_dumpprivkey("bcrt1q28ldz0kwh0ltfad95fzpdqmuxu5getf05jlqu7"), "cSumkzL3QT3aGqeQNuswkLeC5n9BMuhBNvWcCST3VEsLpwVasuQR") + assert_equal(self.nodes[0].spv_dumpprivkey("bcrt1qs2qsynezncmkzef3qsaaumf5r5uvyeh8ykrg37"), + "cSkTV5jWJnKiqMUuuBWo6Sb99UMtddxXerDNQGfU1jJ8WiZoSTRh") + assert_equal(self.nodes[0].spv_dumpprivkey("bcrt1q28ldz0kwh0ltfad95fzpdqmuxu5getf05jlqu7"), + "cSumkzL3QT3aGqeQNuswkLeC5n9BMuhBNvWcCST3VEsLpwVasuQR") # Test getpubkey call - assert_equal(self.nodes[0].spv_getaddresspubkey("bcrt1qs2qsynezncmkzef3qsaaumf5r5uvyeh8ykrg37"), "0224e7de2f3a9d4cdc4fdc14601c75176287297c212aae9091404956955f1aea86") - assert_equal(self.nodes[0].spv_getaddresspubkey("bcrt1q28ldz0kwh0ltfad95fzpdqmuxu5getf05jlqu7"), "035fb3eadde611a39036e61d4c8288d1b896f2c94cee49e60a3d1c02236f4be490") + assert_equal(self.nodes[0].spv_getaddresspubkey("bcrt1qs2qsynezncmkzef3qsaaumf5r5uvyeh8ykrg37"), + "0224e7de2f3a9d4cdc4fdc14601c75176287297c212aae9091404956955f1aea86") + assert_equal(self.nodes[0].spv_getaddresspubkey("bcrt1q28ldz0kwh0ltfad95fzpdqmuxu5getf05jlqu7"), + "035fb3eadde611a39036e61d4c8288d1b896f2c94cee49e60a3d1c02236f4be490") # Try annd create a HTLC script with relative time try: - self.nodes[0].spv_createhtlc("0224e7de2f3a9d4cdc4fdc14601c75176287297c212aae9091404956955f1aea86", "035fb3eadde611a39036e61d4c8288d1b896f2c94cee49e60a3d1c02236f4be490", "4194304", seed_hash) + self.nodes[0].spv_createhtlc("0224e7de2f3a9d4cdc4fdc14601c75176287297c212aae9091404956955f1aea86", + "035fb3eadde611a39036e61d4c8288d1b896f2c94cee49e60a3d1c02236f4be490", + "4194304", seed_hash) except JSONRPCException as e: errorString = e.error['message'] - assert("Invalid block denominated relative timeout" in errorString) + assert ("Invalid block denominated relative timeout" in errorString) # Try annd create a HTLC script below min blocks try: - self.nodes[0].spv_createhtlc("0224e7de2f3a9d4cdc4fdc14601c75176287297c212aae9091404956955f1aea86", "035fb3eadde611a39036e61d4c8288d1b896f2c94cee49e60a3d1c02236f4be490", "8", seed_hash) + self.nodes[0].spv_createhtlc("0224e7de2f3a9d4cdc4fdc14601c75176287297c212aae9091404956955f1aea86", + "035fb3eadde611a39036e61d4c8288d1b896f2c94cee49e60a3d1c02236f4be490", "8", + seed_hash) except JSONRPCException as e: errorString = e.error['message'] - assert("Timeout below minimum of" in errorString) + assert ("Timeout below minimum of" in errorString) # Try annd create a HTLC script with incorrect pubkey try: - self.nodes[0].spv_createhtlc("0224e7de2f3a9d4cdc4fdc14601c75176287297c212aae9091404956955f1aea", "035fb3eadde611a39036e61d4c8288d1b896f2c94cee49e60a3d1c02236f4be490", "10", seed_hash) + self.nodes[0].spv_createhtlc("0224e7de2f3a9d4cdc4fdc14601c75176287297c212aae9091404956955f1aea", + "035fb3eadde611a39036e61d4c8288d1b896f2c94cee49e60a3d1c02236f4be490", "10", + seed_hash) except JSONRPCException as e: errorString = e.error['message'] - assert("Invalid public key" in errorString) + assert ("Invalid public key" in errorString) # Create and learn HTLC script - htlc_script = self.nodes[0].spv_createhtlc("0224e7de2f3a9d4cdc4fdc14601c75176287297c212aae9091404956955f1aea86", "035fb3eadde611a39036e61d4c8288d1b896f2c94cee49e60a3d1c02236f4be490", "10", seed_hash) + htlc_script = self.nodes[0].spv_createhtlc("0224e7de2f3a9d4cdc4fdc14601c75176287297c212aae9091404956955f1aea86", + "035fb3eadde611a39036e61d4c8288d1b896f2c94cee49e60a3d1c02236f4be490", + "10", seed_hash) # Make sure address and redeemscript are as expected. assert_equal(htlc_script['address'], "2N1WoHKzHY59uNpXouLQc32h9k5Y3hXK4Ku") - assert_equal(htlc_script['redeemScript'], "63a820df95183883789f237977543885e1f82ddc045a3ba90c8f25b43a5b797a35d20e88210224e7de2f3a9d4cdc4fdc14601c75176287297c212aae9091404956955f1aea86675ab27521035fb3eadde611a39036e61d4c8288d1b896f2c94cee49e60a3d1c02236f4be49068ac") + assert_equal(htlc_script['redeemScript'], + "63a820df95183883789f237977543885e1f82ddc045a3ba90c8f25b43a5b797a35d20e88210224e7de2f3a9d4cdc4fdc14601c75176287297c212aae9091404956955f1aea86675ab27521035fb3eadde611a39036e61d4c8288d1b896f2c94cee49e60a3d1c02236f4be49068ac") # Test script decoding result = self.nodes[0].spv_decodehtlcscript(htlc_script['redeemScript']) @@ -83,7 +97,7 @@ def run_test(self): self.nodes[0].spv_claimhtlc("2N1WoHKzHY59uNpXouLQc32h9k5Y3hXK4Ku", address, seed, 1000) except JSONRPCException as e: errorString = e.error['message'] - assert("No unspent HTLC outputs found" in errorString) + assert ("No unspent HTLC outputs found" in errorString) # Send to contract for seller claim result = self.nodes[0].spv_sendtoaddress(htlc_script['address'], 0.1) @@ -99,14 +113,14 @@ def run_test(self): self.nodes[0].spv_claimhtlc("2N1WoHKzHY59uNpXouLQc32h9k5Y3hXK4Ku", address, "deadbeef", 1000) except JSONRPCException as e: errorString = e.error['message'] - assert("Seed provided does not match seed hash in contract" in errorString) + assert ("Seed provided does not match seed hash in contract" in errorString) # Try and claim with unknown script address try: self.nodes[0].spv_claimhtlc("2NGT3gZvc75NX8DWGqfuEvniHGj5LiY33Ui", address, "deadbeef", 1000) except JSONRPCException as e: errorString = e.error['message'] - assert("Redeem script not found in wallet" in errorString) + assert ("Redeem script not found in wallet" in errorString) # seller claim HTLC result = self.nodes[0].spv_claimhtlc("2N1WoHKzHY59uNpXouLQc32h9k5Y3hXK4Ku", address, seed, 1000) @@ -118,10 +132,12 @@ def run_test(self): # Get raw TX and check secret and redeemscript part of unlock script rawtx = self.nodes[0].spv_getrawtransaction(result["txid"]) - assert(rawtx.find("0120aba5f7e9aecf6ec4372c8a1e49562680d066da4655ee8b4bb01640479fffeaa8514c6e63a820df95183883789f237977543885e1f82ddc045a3ba90c8f25b43a5b797a35d20e88210224e7de2f3a9d4cdc4fdc14601c75176287297c212aae9091404956955f1aea86675ab27521035fb3eadde611a39036e61d4c8288d1b896f2c94cee49e60a3d1c02236f4be49068ac") != -1) + assert (rawtx.find( + "0120aba5f7e9aecf6ec4372c8a1e49562680d066da4655ee8b4bb01640479fffeaa8514c6e63a820df95183883789f237977543885e1f82ddc045a3ba90c8f25b43a5b797a35d20e88210224e7de2f3a9d4cdc4fdc14601c75176287297c212aae9091404956955f1aea86675ab27521035fb3eadde611a39036e61d4c8288d1b896f2c94cee49e60a3d1c02236f4be49068ac") != -1) # Test getting seed from HTLC transaction - assert_equal(self.nodes[0].spv_gethtlcseed("2N1WoHKzHY59uNpXouLQc32h9k5Y3hXK4Ku"), "aba5f7e9aecf6ec4372c8a1e49562680d066da4655ee8b4bb01640479fffeaa8") + assert_equal(self.nodes[0].spv_gethtlcseed("2N1WoHKzHY59uNpXouLQc32h9k5Y3hXK4Ku"), + "aba5f7e9aecf6ec4372c8a1e49562680d066da4655ee8b4bb01640479fffeaa8") # Send to contract for buyer refund result = self.nodes[0].spv_sendtoaddress(htlc_script['address'], 0.1) @@ -138,7 +154,7 @@ def run_test(self): self.nodes[0].spv_refundhtlc("2N1WoHKzHY59uNpXouLQc32h9k5Y3hXK4Ku", address, 1000) except JSONRPCException as e: errorString = e.error['message'] - assert("No unspent HTLC outputs found" in errorString) + assert ("No unspent HTLC outputs found" in errorString) # Move confirtmation count to meet refund requirement self.nodes[0].spv_setlastheight(10) @@ -156,7 +172,8 @@ def run_test(self): # Get raw TX and check redeemscript part of unlock script rawtx = self.nodes[0].spv_getrawtransaction(result["txid"]) - assert(rawtx.find("01004c6e63a820df95183883789f237977543885e1f82ddc045a3ba90c8f25b43a5b797a35d20e88210224e7de2f3a9d4cdc4fdc14601c75176287297c212aae9091404956955f1aea86675ab27521035fb3eadde611a39036e61d4c8288d1b896f2c94cee49e60a3d1c02236f4be49068ac") != -1) + assert (rawtx.find( + "01004c6e63a820df95183883789f237977543885e1f82ddc045a3ba90c8f25b43a5b797a35d20e88210224e7de2f3a9d4cdc4fdc14601c75176287297c212aae9091404956955f1aea86675ab27521035fb3eadde611a39036e61d4c8288d1b896f2c94cee49e60a3d1c02236f4be49068ac") != -1) # Generate all new addresses and seeds and test multiple UTXOs claim in script seller = self.nodes[0].spv_getnewaddress() @@ -232,38 +249,44 @@ def run_test(self): # Incorrect seed length try: - self.nodes[0].spv_decodehtlcscript("63a821df95183883789f237977543885e1f82ddc045a3ba90c8f25b43a5b797a35d20e88210224e7de2f3a9d4cdc4fdc14601c75176287297c212aae9091404956955f1aea86675ab27521035fb3eadde611a39036e61d4c8288d1b896f2c94cee49e60a3d1c02236f4be49068ac") + self.nodes[0].spv_decodehtlcscript( + "63a821df95183883789f237977543885e1f82ddc045a3ba90c8f25b43a5b797a35d20e88210224e7de2f3a9d4cdc4fdc14601c75176287297c212aae9091404956955f1aea86675ab27521035fb3eadde611a39036e61d4c8288d1b896f2c94cee49e60a3d1c02236f4be49068ac") except JSONRPCException as e: errorString = e.error['message'] - assert("Incorrect seed hash length" in errorString) + assert ("Incorrect seed hash length" in errorString) # Incorrect seller pubkey length try: - self.nodes[0].spv_decodehtlcscript("63a820df95183883789f237977543885e1f82ddc045a3ba90c8f25b43a5b797a35d20e88200224e7de2f3a9d4cdc4fdc14601c75176287297c212aae9091404956955f1aea86675ab27521035fb3eadde611a39036e61d4c8288d1b896f2c94cee49e60a3d1c02236f4be49068ac") + self.nodes[0].spv_decodehtlcscript( + "63a820df95183883789f237977543885e1f82ddc045a3ba90c8f25b43a5b797a35d20e88200224e7de2f3a9d4cdc4fdc14601c75176287297c212aae9091404956955f1aea86675ab27521035fb3eadde611a39036e61d4c8288d1b896f2c94cee49e60a3d1c02236f4be49068ac") except JSONRPCException as e: errorString = e.error['message'] - assert("Seller pubkey incorrect pubkey length" in errorString) + assert ("Seller pubkey incorrect pubkey length" in errorString) # Incorrect time length try: - self.nodes[0].spv_decodehtlcscript("63a820df95183883789f237977543885e1f82ddc045a3ba90c8f25b43a5b797a35d20e88210224e7de2f3a9d4cdc4fdc14601c75176287297c212aae9091404956955f1aea866750b27521035fb3eadde611a39036e61d4c8288d1b896f2c94cee49e60a3d1c02236f4be49068") + self.nodes[0].spv_decodehtlcscript( + "63a820df95183883789f237977543885e1f82ddc045a3ba90c8f25b43a5b797a35d20e88210224e7de2f3a9d4cdc4fdc14601c75176287297c212aae9091404956955f1aea866750b27521035fb3eadde611a39036e61d4c8288d1b896f2c94cee49e60a3d1c02236f4be49068") except JSONRPCException as e: errorString = e.error['message'] - assert("Incorrect timeout length" in errorString) + assert ("Incorrect timeout length" in errorString) # Incorrect buyer pubkey length try: - self.nodes[0].spv_decodehtlcscript("63a820df95183883789f237977543885e1f82ddc045a3ba90c8f25b43a5b797a35d20e88210224e7de2f3a9d4cdc4fdc14601c75176287297c212aae9091404956955f1aea86675ab27520035fb3eadde611a39036e61d4c8288d1b896f2c94cee49e60a3d1c02236f4be49068ac") + self.nodes[0].spv_decodehtlcscript( + "63a820df95183883789f237977543885e1f82ddc045a3ba90c8f25b43a5b797a35d20e88210224e7de2f3a9d4cdc4fdc14601c75176287297c212aae9091404956955f1aea86675ab27520035fb3eadde611a39036e61d4c8288d1b896f2c94cee49e60a3d1c02236f4be49068ac") except JSONRPCException as e: errorString = e.error['message'] - assert("Buyer pubkey incorrect pubkey length" in errorString) + assert ("Buyer pubkey incorrect pubkey length" in errorString) # Incorrect redeemscript length try: - self.nodes[0].spv_decodehtlcscript("63a820df95183883789f237977543885e1f82ddc045a3ba90c8f25b43a5b797a35d20e88210224e7de2f3a9d4cdc4fdc14601c75176287297c212aae9091404956955f1aea86675ab27521035fb3eadde611a39036e61d4c8288d1b896f2c94cee49e60a3d1c02236f4be49068") + self.nodes[0].spv_decodehtlcscript( + "63a820df95183883789f237977543885e1f82ddc045a3ba90c8f25b43a5b797a35d20e88210224e7de2f3a9d4cdc4fdc14601c75176287297c212aae9091404956955f1aea86675ab27521035fb3eadde611a39036e61d4c8288d1b896f2c94cee49e60a3d1c02236f4be49068") except JSONRPCException as e: errorString = e.error['message'] - assert("Incorrect redeemscript length" in errorString) + assert ("Incorrect redeemscript length" in errorString) + if __name__ == '__main__': BitcoinHTLCTests().main() diff --git a/test/functional/feature_bitcoin_wallet.py b/test/functional/feature_bitcoin_wallet.py index ee443b55b0..86fc43042c 100755 --- a/test/functional/feature_bitcoin_wallet.py +++ b/test/functional/feature_bitcoin_wallet.py @@ -11,11 +11,12 @@ from test_framework.authproxy import JSONRPCException from decimal import Decimal + class BitcoinSPVTests(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.extra_args = [ - [ "-dummypos=1", "-spv=1"], + ["-dummypos=1", "-spv=1"], ] self.setup_clean_chain = True @@ -44,7 +45,7 @@ def run_test(self): self.nodes[0].spv_sendtoaddress(dummy_address, 0.1) except JSONRPCException as e: errorString = e.error['message'] - assert("Invalid address" in errorString) + assert ("Invalid address" in errorString) # Send to external address dummy_address = "bcrt1qfpnmx6jrn30yvscrw9spudj5aphyrc8es6epva" @@ -53,7 +54,7 @@ def run_test(self): # Make sure tx is present in wallet txs = self.nodes[0].spv_listtransactions() - assert(result['txid'] in txs) + assert (result['txid'] in txs) # Make sure balance reduced balance = self.nodes[0].spv_getbalance() @@ -65,7 +66,7 @@ def run_test(self): # Make sure tx is present in wallet txs = self.nodes[0].spv_listtransactions() - assert(result['txid'] in txs) + assert (result['txid'] in txs) # Make sure balance reduced balance = self.nodes[0].spv_getbalance() @@ -93,5 +94,6 @@ def run_test(self): assert_equal(wallet_priv_key, priv_key) assert_equal(wallet_change_priv_key, change_priv_key) + if __name__ == '__main__': BitcoinSPVTests().main() diff --git a/test/functional/feature_block.py b/test/functional/feature_block.py index 7a421a4df0..bd11b1bf07 100755 --- a/test/functional/feature_block.py +++ b/test/functional/feature_block.py @@ -53,6 +53,7 @@ from test_framework.util import assert_equal from data import invalid_txs + # Use this class for tests that require behavior other than normal "mininode" behavior. # For now, it is used to serialize a bloated varint (b64). class CBrokenBlock(CBlock): @@ -236,7 +237,8 @@ def run_test(self): # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3) # \-> b12 (3) -> b13 (4) -> b14 (5) # \-> b3 (1) -> b4 (2) - self.log.info("Reject a chain where the miner creates too much coinbase reward, even if the chain is longer (on a forked chain)") + self.log.info( + "Reject a chain where the miner creates too much coinbase reward, even if the chain is longer (on a forked chain)") self.move_tip(5) b12 = self.next_block(12, spend=out[3]) self.save_spendable_output() @@ -487,7 +489,7 @@ def run_test(self): tx_new = None tx_last = tx total_size = len(b39.serialize()) - while(total_size < MAX_BLOCK_BASE_SIZE): + while (total_size < MAX_BLOCK_BASE_SIZE): tx_new = self.create_tx(tx_last, 1, 1, p2sh_script) tx_new.vout.append(CTxOut(tx_last.vout[1].nValue - 1, CScript([OP_TRUE]))) tx_new.rehash() @@ -754,7 +756,8 @@ def run_test(self): b57p2 = self.update_block("57p2", [tx, tx1, tx2, tx3, tx4]) # b56p2 - copy b57p2, duplicate two non-consecutive tx's - self.log.info("Reject a block with two duplicate transactions in the Merkle Tree (but with a valid Merkle Root)") + self.log.info( + "Reject a block with two duplicate transactions in the Merkle Tree (but with a valid Merkle Root)") self.move_tip(55) b56p2 = copy.deepcopy(b57p2) self.blocks["b56p2"] = b56p2 @@ -1016,14 +1019,15 @@ def run_test(self): # # b72 is a good block. # b71 is a copy of 72, but re-adds one of its transactions. However, it has the same hash as b72. - self.log.info("Reject a block containing a duplicate transaction but with the same Merkle root (Merkle tree malleability") + self.log.info( + "Reject a block containing a duplicate transaction but with the same Merkle root (Merkle tree malleability") self.move_tip(69) b72 = self.next_block(72) tx1 = self.create_and_sign_transaction(out[21], 2) tx2 = self.create_and_sign_transaction(tx1, 1) b72 = self.update_block(72, [tx1, tx2]) # now tip is 72 b71 = copy.deepcopy(b72) - b71.vtx.append(tx2) # add duplicate tx2 + b71.vtx.append(tx2) # add duplicate tx2 self.block_heights[b71.sha256] = self.block_heights[b69.sha256] + 1 # b71 builds off b69 self.blocks[71] = b71 @@ -1250,7 +1254,7 @@ def run_test(self): self.move_tip(88) LARGE_REORG_SIZE = 1088 blocks = [] - BLOCK_SIZE = 1000000 # old value was MAX_BLOCK_BASE_SIZE, changed due to EXTREMELY big chain and slow operation + BLOCK_SIZE = 1000000 # old value was MAX_BLOCK_BASE_SIZE, changed due to EXTREMELY big chain and slow operation spend = out[32] for i in range(89, LARGE_REORG_SIZE + 89): b = self.next_block(i, spend, version=4) @@ -1288,7 +1292,8 @@ def run_test(self): self.log.info("Reject a block with an invalid block header version") b_v1 = self.next_block('b_v1', version=1) - self.send_blocks([b_v1], success=False, force_send=True, reject_reason='bad-version(0x00000001)', reconnect=True) + self.send_blocks([b_v1], success=False, force_send=True, reject_reason='bad-version(0x00000001)', + reconnect=True) self.move_tip(chain1_tip + 2) b_cb34 = self.next_block('b_cb34', version=4) @@ -1325,7 +1330,8 @@ def create_and_sign_transaction(self, spend_tx, value, script=CScript([OP_TRUE]) tx.rehash() return tx - def next_block(self, number, spend=None, additional_coinbase_value=0, script=CScript([OP_TRUE]), solve=True, *, version=1): + def next_block(self, number, spend=None, additional_coinbase_value=0, script=CScript([OP_TRUE]), solve=True, *, + version=1): if self.tip is None: base_block_hash = self.genesis_hash block_time = int(time.time()) + 1 @@ -1409,7 +1415,8 @@ def send_blocks(self, blocks, success=True, reject_reason=None, force_send=False """Sends blocks to test node. Syncs and verifies that tip has advanced to most recent block. Call with success = False if the tip shouldn't advance to the most recent block.""" - self.nodes[0].p2p.send_blocks_and_test(blocks, self.nodes[0], success=success, reject_reason=reject_reason, force_send=force_send, timeout=timeout, expect_disconnect=reconnect) + self.nodes[0].p2p.send_blocks_and_test(blocks, self.nodes[0], success=success, reject_reason=reject_reason, + force_send=force_send, timeout=timeout, expect_disconnect=reconnect) if reconnect: self.reconnect_p2p(timeout=timeout) diff --git a/test/functional/feature_block_reward.py b/test/functional/feature_block_reward.py index 8f0865061f..6c68b59da4 100755 --- a/test/functional/feature_block_reward.py +++ b/test/functional/feature_block_reward.py @@ -11,21 +11,24 @@ assert_equal ) + class BlockRewardTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True - self.extra_args = [['-txnotokens=0', '-amkheight=50', '-eunosheight=100', '-eunosheight=100', '-fortcanningheight=110', '-subsidytest=1']] + self.extra_args = [ + ['-txnotokens=0', '-amkheight=50', '-eunosheight=100', '-eunosheight=100', '-fortcanningheight=110', + '-subsidytest=1']] def run_test(self): node = self.nodes[0] node.generate(120) newBaseBlockSubsidy = 405.0400 - masternodePortion = 0.3333 # 33.33% + masternodePortion = 0.3333 # 33.33% mingBaseReward = newBaseBlockSubsidy * masternodePortion - result = node.listaccounthistory("mine", {"depth":0}) + result = node.listaccounthistory("mine", {"depth": 0}) assert_equal(result[0]["amounts"][0], f'{mingBaseReward:.8f}@DFI') account = node.getnewaddress() @@ -34,10 +37,11 @@ def run_test(self): node.utxostoaccount({account: "1.3@0"}) node.generate(1) - result = node.listaccounthistory("mine", {"depth":0}) + result = node.listaccounthistory("mine", {"depth": 0}) for subResult in result: if subResult["type"] == "blockReward": assert_greater_than(subResult["amounts"][0], f'{mingBaseReward:.8f}@DFI') + if __name__ == '__main__': - BlockRewardTest().main () + BlockRewardTest().main() diff --git a/test/functional/feature_blocksdir.py b/test/functional/feature_blocksdir.py index 00be05819a..9ca4000724 100755 --- a/test/functional/feature_blocksdir.py +++ b/test/functional/feature_blocksdir.py @@ -24,11 +24,13 @@ def run_test(self): initialize_datadir(self.options.tmpdir, 0, self.chain) self.log.info("Starting with nonexistent blocksdir ...") blocksdir_path = os.path.join(self.options.tmpdir, 'blocksdir') - self.nodes[0].assert_start_raises_init_error(["-blocksdir=" + blocksdir_path], 'Error: Specified blocks directory "{}" does not exist.'.format(blocksdir_path)) + self.nodes[0].assert_start_raises_init_error(["-blocksdir=" + blocksdir_path], + 'Error: Specified blocks directory "{}" does not exist.'.format( + blocksdir_path)) os.mkdir(blocksdir_path) self.log.info("Starting with existing blocksdir ...") self.start_node(0, ["-blocksdir=" + blocksdir_path]) - self.import_deterministic_coinbase_privkeys() # cause initial datadir with predefined wallets was removed + self.import_deterministic_coinbase_privkeys() # cause initial datadir with predefined wallets was removed self.log.info("mining blocks..") self.nodes[0].generate(10) assert os.path.isfile(os.path.join(blocksdir_path, self.chain, "blocks", "blk00000.dat")) diff --git a/test/functional/feature_burn_address.py b/test/functional/feature_burn_address.py index 3d68f1ebd3..44dd49777f 100755 --- a/test/functional/feature_burn_address.py +++ b/test/functional/feature_burn_address.py @@ -12,6 +12,7 @@ from decimal import Decimal + class BurnAddressTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 @@ -33,7 +34,7 @@ def run_test(self): # Check create masternode burn fee result = self.nodes[0].listburnhistory() - assert_equal(result[0]['owner'][4:14], "4466547843") # OP_RETURN data DfTxC + assert_equal(result[0]['owner'][4:14], "4466547843") # OP_RETURN data DfTxC assert_equal(result[0]['txn'], 2) assert_equal(result[0]['type'], 'CreateMasternode') assert_equal(result[0]['amounts'][0], '1.00000000@DFI') @@ -47,7 +48,7 @@ def run_test(self): # Create funded account address funded_address = self.nodes[0].getnewaddress() self.nodes[0].sendtoaddress(funded_address, 1) - self.nodes[0].utxostoaccount({funded_address:"3@0"}) + self.nodes[0].utxostoaccount({funded_address: "3@0"}) self.nodes[0].generate(1) # Test burn token @@ -60,7 +61,8 @@ def run_test(self): # Check token burn fee result = self.nodes[0].listburnhistory() - assert_equal(result[0]['owner'], "6a1f446654785404474f4c440a7368696e7920676f6c6408000000000000000003") # OP_RETURN data + assert_equal(result[0]['owner'], + "6a1f446654785404474f4c440a7368696e7920676f6c6408000000000000000003") # OP_RETURN data assert_equal(result[0]['txn'], 1) assert_equal(result[0]['type'], 'CreateToken') assert_equal(result[0]['amounts'][0], '1.00000000@DFI') @@ -75,7 +77,7 @@ def run_test(self): self.nodes[0].generate(1) # Send tokens to burn address - self.nodes[0].accounttoaccount(funded_address, {burn_address:"100@128"}) + self.nodes[0].accounttoaccount(funded_address, {burn_address: "100@128"}) self.nodes[0].generate(1) # Check burn history @@ -90,7 +92,7 @@ def run_test(self): assert_equal(result['feeburn'], Decimal('2.00000000')) # Track utxostoaccount burn - self.nodes[0].utxostoaccount({burn_address:"1@0"}) + self.nodes[0].utxostoaccount({burn_address: "1@0"}) self.nodes[0].generate(1) # Check burn history @@ -107,13 +109,13 @@ def run_test(self): # Try and spend from burn address account try: - self.nodes[0].accounttoaccount(burn_address, {funded_address:"1@0"}) + self.nodes[0].accounttoaccount(burn_address, {funded_address: "1@0"}) except JSONRPCException as e: errorString = e.error['message'] - assert("burnt-output" in errorString) + assert ("burnt-output" in errorString) # Send to burn address with accounttoaccount - self.nodes[0].accounttoaccount(funded_address, {burn_address:"1@0"}) + self.nodes[0].accounttoaccount(funded_address, {burn_address: "1@0"}) self.nodes[0].generate(1) # Check burn history @@ -132,7 +134,7 @@ def run_test(self): assert_equal(result['feeburn'], Decimal('2.00000000')) # Send to burn address with accounttoutxos - self.nodes[0].accounttoutxos(funded_address, {burn_address:"2@0"}) + self.nodes[0].accounttoutxos(funded_address, {burn_address: "2@0"}) self.nodes[0].generate(1) result = self.nodes[0].listburnhistory() @@ -168,7 +170,7 @@ def run_test(self): if outputs['scriptPubKey']['addresses'][0] == burn_address: vout = outputs['n'] - rawtx = self.nodes[0].createrawtransaction([{"txid":txid,"vout":vout}], [{burn_address:9.9999}]) + rawtx = self.nodes[0].createrawtransaction([{"txid": txid, "vout": vout}], [{burn_address: 9.9999}]) signed_rawtx = self.nodes[0].signrawtransactionwithwallet(rawtx) assert_equal(signed_rawtx['complete'], True) @@ -177,7 +179,7 @@ def run_test(self): self.nodes[0].sendrawtransaction(signed_rawtx['hex']) except JSONRPCException as e: errorString = e.error['message'] - assert("burnt-output" in errorString) + assert ("burnt-output" in errorString) # Test output of getburninfo result = self.nodes[0].getburninfo() @@ -187,30 +189,30 @@ def run_test(self): assert_equal(result['feeburn'], Decimal('2.00000000')) # Filter on tx type None - result = self.nodes[0].listburnhistory({"txtype":'0'}) + result = self.nodes[0].listburnhistory({"txtype": '0'}) assert_equal(len(result), 3) assert_equal(result[0]['type'], 'None') assert_equal(result[1]['type'], 'None') assert_equal(result[2]['type'], 'None') # Filter on tx type UtxosToAccount - result = self.nodes[0].listburnhistory({"txtype":'U'}) + result = self.nodes[0].listburnhistory({"txtype": 'U'}) assert_equal(len(result), 1) assert_equal(result[0]['type'], 'UtxosToAccount') # Filter on tx type AccountToAccount - result = self.nodes[0].listburnhistory({"txtype":'B'}) + result = self.nodes[0].listburnhistory({"txtype": 'B'}) assert_equal(len(result), 2) assert_equal(result[0]['type'], 'AccountToAccount') assert_equal(result[1]['type'], 'AccountToAccount') # Filter on tx type CreateMasternode - result = self.nodes[0].listburnhistory({"txtype":'C'}) + result = self.nodes[0].listburnhistory({"txtype": 'C'}) assert_equal(len(result), 1) assert_equal(result[0]['type'], 'CreateMasternode') # Filter on tx type CreateToken - result = self.nodes[0].listburnhistory({"txtype":'T'}) + result = self.nodes[0].listburnhistory({"txtype": 'T'}) assert_equal(len(result), 1) assert_equal(result[0]['type'], 'CreateToken') @@ -234,5 +236,6 @@ def run_test(self): assert_equal(result['feeburn'], Decimal('0')) assert_equal(result['tokens'], []) + if __name__ == '__main__': BurnAddressTest().main() diff --git a/test/functional/feature_checkpoint.py b/test/functional/feature_checkpoint.py index b499d97e88..af9dd646f6 100755 --- a/test/functional/feature_checkpoint.py +++ b/test/functional/feature_checkpoint.py @@ -11,7 +11,8 @@ assert_equal ) -class CheckpointTest (DefiTestFramework): + +class CheckpointTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 self.setup_clean_chain = True @@ -42,7 +43,7 @@ def run_test(self): headblock = self.nodes[0].getblockcount() # REVERTING: - #======================== + # ======================== self.start_node(1) self.nodes[1].generate(10) @@ -50,5 +51,6 @@ def run_test(self): # reverting prior last checkpoint is forbidden assert_equal(self.nodes[0].getblockcount(), headblock) + if __name__ == '__main__': - CheckpointTest ().main () + CheckpointTest().main() diff --git a/test/functional/feature_cltv.py b/test/functional/feature_cltv.py index 35fe96bf10..e68da1e043 100755 --- a/test/functional/feature_cltv.py +++ b/test/functional/feature_cltv.py @@ -26,6 +26,7 @@ REJECT_INVALID = 16 REJECT_NONSTANDARD = 64 + def cltv_invalidate(tx): '''Modify the signature in vin 0 of the tx to fail CLTV @@ -37,6 +38,7 @@ def cltv_invalidate(tx): tx.vin[0].scriptSig = CScript([OP_1NEGATE, OP_CHECKLOCKTIMEVERIFY, OP_DROP] + list(CScript(tx.vin[0].scriptSig))) + def cltv_validate(node, tx, height): '''Modify the signature in vin 0 of the tx to pass CLTV Prepends CLTV DROP in the scriptSig, and sets @@ -50,7 +52,7 @@ def cltv_validate(node, tx, height): new_tx.deserialize(BytesIO(hex_str_to_bytes(signed_result['hex']))) new_tx.vin[0].scriptSig = CScript([CScriptNum(height), OP_CHECKLOCKTIMEVERIFY, OP_DROP] + - list(CScript(new_tx.vin[0].scriptSig))) + list(CScript(new_tx.vin[0].scriptSig))) return new_tx @@ -78,7 +80,7 @@ def run_test(self): self.log.info("Test that an invalid-according-to-CLTV transaction can still appear in a block") spendtx = create_transaction(self.nodes[0], self.coinbase_txids[0], - self.nodeaddress, amount=1.0) + self.nodeaddress, amount=1.0) cltv_invalidate(spendtx) spendtx.rehash() @@ -109,14 +111,15 @@ def run_test(self): block.nVersion = 4 spendtx = create_transaction(self.nodes[0], self.coinbase_txids[1], - self.nodeaddress, amount=1.0) + self.nodeaddress, amount=1.0) cltv_invalidate(spendtx) spendtx.rehash() # First we show that this tx is valid except for CLTV by getting it # rejected from the mempool for exactly that reason. assert_equal( - [{'txid': spendtx.hash, 'allowed': False, 'reject-reason': '64: non-mandatory-script-verify-flag (Negative locktime)'}], + [{'txid': spendtx.hash, 'allowed': False, + 'reject-reason': '64: non-mandatory-script-verify-flag (Negative locktime)'}], self.nodes[0].testmempoolaccept(rawtxs=[spendtx.serialize().hex()], maxfeerate=0) ) @@ -125,7 +128,9 @@ def run_test(self): block.hashMerkleRoot = block.calc_merkle_root() block.solve() - with self.nodes[0].assert_debug_log(expected_msgs=['CheckInputs on {} failed with non-mandatory-script-verify-flag (Negative locktime)'.format(block.vtx[-1].hash)]): + with self.nodes[0].assert_debug_log(expected_msgs=[ + 'CheckInputs on {} failed with non-mandatory-script-verify-flag (Negative locktime)'.format( + block.vtx[-1].hash)]): self.nodes[0].p2p.send_and_ping(msg_block(block)) assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip) self.nodes[0].p2p.sync_with_ping() diff --git a/test/functional/feature_commission_fix.py b/test/functional/feature_commission_fix.py index 1e5b64f448..e747e60fd9 100644 --- a/test/functional/feature_commission_fix.py +++ b/test/functional/feature_commission_fix.py @@ -11,13 +11,16 @@ from decimal import Decimal import time + class CommissionFixTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True self.grand_central = 200 self.extra_args = [ - ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', '-fortcanningmuseumheight=1', '-fortcanninghillheight=1', '-fortcanningroadheight=1', '-fortcanningcrunchheight=1', f'-grandcentralheight={self.grand_central}', '-subsidytest=1']] + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', + '-fortcanningmuseumheight=1', '-fortcanninghillheight=1', '-fortcanningroadheight=1', + '-fortcanningcrunchheight=1', f'-grandcentralheight={self.grand_central}', '-subsidytest=1']] def run_test(self): # Set up test tokens @@ -108,7 +111,6 @@ def setup_test_tokens(self): self.nodes[0].generate(1) def setup_test_pool(self): - # Create pool pair self.nodes[0].createpoolpair({ "tokenA": self.symbolGOOGL, @@ -124,7 +126,6 @@ def setup_test_pool(self): self.idGD = list(self.nodes[0].gettoken(self.symbolGD).keys())[0] def setup_test_pool_fork(self): - # Create pool pair self.nodes[0].createpoolpair({ "tokenA": self.symbolTSLA, @@ -140,7 +141,6 @@ def setup_test_pool_fork(self): self.idTD = list(self.nodes[0].gettoken(self.symbolTD).keys())[0] def pool_commission(self): - # Set up commission address commission_address = self.nodes[0].getnewaddress("", "legacy") self.nodes[0].sendtoaddress(commission_address, 1) @@ -176,7 +176,7 @@ def pool_commission(self): # Commission missing for result in self.nodes[0].listaccounthistory(commission_address): - assert(result['type'] != 'Commission') + assert (result['type'] != 'Commission') # Show Commission with low depth result = self.nodes[0].listaccounthistory(commission_address, {'depth': 1}) @@ -240,7 +240,6 @@ def pool_commission(self): assert_equal(result[0]['type'], 'Commission') def pool_commission_fork(self): - # Set up commission address commission_address = self.nodes[0].getnewaddress("", "legacy") self.nodes[0].sendtoaddress(commission_address, 1) @@ -276,14 +275,15 @@ def pool_commission_fork(self): assert_equal(result[0]['type'], 'Commission') # Token split - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/oracles/splits/{str(self.nodes[0].getblockcount() + 2)}':f'{self.idTSLA}/2'}}) + self.nodes[0].setgov( + {"ATTRIBUTES": {f'v0/oracles/splits/{str(self.nodes[0].getblockcount() + 2)}': f'{self.idTSLA}/2'}}) self.nodes[0].generate(2) # Swap old for new values self.idTSLA = list(self.nodes[0].gettoken(self.symbolTSLA).keys())[0] # Unlock token - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/locks/token/{self.idTSLA}':'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/locks/token/{self.idTSLA}': 'false'}}) self.nodes[0].generate(1) # Execute pool swap @@ -300,5 +300,6 @@ def pool_commission_fork(self): result = self.nodes[0].listaccounthistory(commission_address) assert_equal(result[0]['type'], 'Commission') + if __name__ == '__main__': CommissionFixTest().main() diff --git a/test/functional/feature_community_development_funds.py b/test/functional/feature_community_development_funds.py index 6e32a72780..c4f4b58812 100755 --- a/test/functional/feature_community_development_funds.py +++ b/test/functional/feature_community_development_funds.py @@ -13,14 +13,24 @@ from decimal import Decimal + class CommunityDevelopmentFunds(DefiTestFramework): def set_test_params(self): self.num_nodes = 3 self.setup_clean_chain = True self.extra_args = [ - ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=60', '-eunosheight=70', '-fortcanningheight=80', '-fortcanninghillheight=90', '-fortcanningroadheight=100', '-fortcanningcrunchheight=110', '-fortcanningspringheight=120', '-fortcanninggreatworldheight=130', '-grandcentralheight=201', '-subsidytest=1'], - ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=60', '-eunosheight=70', '-fortcanningheight=80', '-fortcanninghillheight=90', '-fortcanningroadheight=100', '-fortcanningcrunchheight=110', '-fortcanningspringheight=120', '-fortcanninggreatworldheight=130', '-grandcentralheight=201', '-subsidytest=1'], - ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=60', '-eunosheight=70', '-fortcanningheight=80', '-fortcanninghillheight=90', '-fortcanningroadheight=100', '-fortcanningcrunchheight=110', '-fortcanningspringheight=120', '-fortcanninggreatworldheight=130', '-grandcentralheight=201', '-subsidytest=1'], + ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=60', '-eunosheight=70', + '-fortcanningheight=80', '-fortcanninghillheight=90', '-fortcanningroadheight=100', + '-fortcanningcrunchheight=110', '-fortcanningspringheight=120', '-fortcanninggreatworldheight=130', + '-grandcentralheight=201', '-subsidytest=1'], + ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=60', '-eunosheight=70', + '-fortcanningheight=80', '-fortcanninghillheight=90', '-fortcanningroadheight=100', + '-fortcanningcrunchheight=110', '-fortcanningspringheight=120', '-fortcanninggreatworldheight=130', + '-grandcentralheight=201', '-subsidytest=1'], + ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=60', '-eunosheight=70', + '-fortcanningheight=80', '-fortcanninghillheight=90', '-fortcanningroadheight=100', + '-fortcanningcrunchheight=110', '-fortcanningspringheight=120', '-fortcanninggreatworldheight=130', + '-grandcentralheight=201', '-subsidytest=1'], ] def run_test(self): @@ -54,17 +64,19 @@ def run_test(self): assert_equal(node1.getbalances()['mine']['immature'], foundation['mine']['immature'] - Decimal("19.887464")) # check that funds are not trasfered yet before governance is activated - assert_equal(Decimal(node1.getaccount('2NCWAKfEehP3qibkLKYQjXaWMK23k4EDMVS')[0].split('@')[0]), balanceLessFee + Decimal("19.887464")) + assert_equal(Decimal(node1.getaccount('2NCWAKfEehP3qibkLKYQjXaWMK23k4EDMVS')[0].split('@')[0]), + balanceLessFee + Decimal("19.887464")) assert_equal(node0.listcommunitybalances()['CommunityDevelopmentFunds'], 0) # activate on-chain governance - node0.setgov({"ATTRIBUTES":{'v0/params/feature/gov':'true'}}) + node0.setgov({"ATTRIBUTES": {'v0/params/feature/gov': 'true'}}) node0.generate(1) self.sync_blocks(self.nodes[:2]) # check that funds are not trasfered yet before governance is activated assert_equal(node1.getaccount('2NCWAKfEehP3qibkLKYQjXaWMK23k4EDMVS'), []) - assert_equal(node0.listcommunitybalances()['CommunityDevelopmentFunds'], balanceLessFee + 2*Decimal("19.887464")) + assert_equal(node0.listcommunitybalances()['CommunityDevelopmentFunds'], + balanceLessFee + 2 * Decimal("19.887464")) foundation1 = node1.getbalances() foundationBalance1 = foundation1['mine']['trusted'] @@ -74,19 +86,20 @@ def run_test(self): assert_equal(before_hardfork + Decimal("19.887464"), after_hardfork + foundationBalance) # activate on-chain governance - node0.setgov({"ATTRIBUTES":{'v0/params/feature/gov':'false'}}) + node0.setgov({"ATTRIBUTES": {'v0/params/feature/gov': 'false'}}) node0.generate(1) self.sync_blocks(self.nodes[:2]) # check that funds are not trasfered yet before governance is activated - assert_equal(Decimal(node1.getaccount('2NCWAKfEehP3qibkLKYQjXaWMK23k4EDMVS')[0].split('@')[0]), balanceLessFee + 3*Decimal("19.887464")) + assert_equal(Decimal(node1.getaccount('2NCWAKfEehP3qibkLKYQjXaWMK23k4EDMVS')[0].split('@')[0]), + balanceLessFee + 3 * Decimal("19.887464")) assert_equal(node0.listcommunitybalances()['CommunityDevelopmentFunds'], 0) # foundation coins are locked node0.generate(2) self.sync_blocks(self.nodes[:2]) - print ("Reverting...") + print("Reverting...") self.start_node(2) # GrandCnetral hardfork height @@ -101,14 +114,17 @@ def run_test(self): assert_equal(node1.listcommunitybalances()['CommunityDevelopmentFunds'], 0) assert_equal(node2.listcommunitybalances()['CommunityDevelopmentFunds'], 0) - node0.setgov({"ATTRIBUTES":{'v0/params/feature/gov':'true'}}) + node0.setgov({"ATTRIBUTES": {'v0/params/feature/gov': 'true'}}) node0.generate(1) self.sync_blocks() assert_equal(node1.getaccount('2NCWAKfEehP3qibkLKYQjXaWMK23k4EDMVS'), []) - assert_equal(node0.listcommunitybalances()['CommunityDevelopmentFunds'], balanceLessFee + Decimal('{:.8f}'.format(7 * 19.887464))) - assert_equal(node1.listcommunitybalances()['CommunityDevelopmentFunds'], balanceLessFee + Decimal('{:.8f}'.format(7 * 19.887464))) - assert_equal(node2.listcommunitybalances()['CommunityDevelopmentFunds'], balanceLessFee + Decimal('{:.8f}'.format(7 * 19.887464))) + assert_equal(node0.listcommunitybalances()['CommunityDevelopmentFunds'], + balanceLessFee + Decimal('{:.8f}'.format(7 * 19.887464))) + assert_equal(node1.listcommunitybalances()['CommunityDevelopmentFunds'], + balanceLessFee + Decimal('{:.8f}'.format(7 * 19.887464))) + assert_equal(node2.listcommunitybalances()['CommunityDevelopmentFunds'], + balanceLessFee + Decimal('{:.8f}'.format(7 * 19.887464))) node0.generate(93) self.sync_blocks() @@ -126,12 +142,13 @@ def run_test(self): assert_equal(node0.getaccount('mkzZWPwBVgdnwLSmXKW5SuUFMpm6C5ZPcJ'), []) # Enable unused emission to address - node0.setgov({"ATTRIBUTES":{'v0/params/feature/emission-unused-fund':'true'}}) + node0.setgov({"ATTRIBUTES": {'v0/params/feature/emission-unused-fund': 'true'}}) node0.generate(1) self.sync_blocks(self.nodes[:2]) # Check unused balance now going to emission address assert_equal(node0.getaccount('mkzZWPwBVgdnwLSmXKW5SuUFMpm6C5ZPcJ'), ['46.24546710@DFI']) + if __name__ == '__main__': - CommunityDevelopmentFunds().main () + CommunityDevelopmentFunds().main() diff --git a/test/functional/feature_communitybalance_reorg.py b/test/functional/feature_communitybalance_reorg.py index b983376650..e80cdb3232 100755 --- a/test/functional/feature_communitybalance_reorg.py +++ b/test/functional/feature_communitybalance_reorg.py @@ -11,6 +11,7 @@ from decimal import Decimal + class CommunityBalanceReorg(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 @@ -50,5 +51,6 @@ def run_test(self): assert_equal(self.nodes[0].listcommunitybalances()['AnchorReward'], Decimal('3.10000000')) assert_equal(self.nodes[0].listcommunitybalances()['Burnt'], 310) + if __name__ == '__main__': CommunityBalanceReorg().main() diff --git a/test/functional/feature_config_args.py b/test/functional/feature_config_args.py index a791db22ce..198f3259db 100755 --- a/test/functional/feature_config_args.py +++ b/test/functional/feature_config_args.py @@ -33,33 +33,40 @@ def test_config_file_parser(self): with open(inc_conf_file_path, 'w', encoding='utf-8') as conf: conf.write('-dash=1\n') - self.nodes[0].assert_start_raises_init_error(expected_msg='Error: Error reading configuration file: parse error on line 1: -dash=1, options in configuration file must be specified without leading -') + self.nodes[0].assert_start_raises_init_error( + expected_msg='Error: Error reading configuration file: parse error on line 1: -dash=1, options in configuration file must be specified without leading -') if self.is_wallet_compiled(): with open(inc_conf_file_path, 'w', encoding='utf8') as conf: conf.write("wallet=foo\n") - self.nodes[0].assert_start_raises_init_error(expected_msg='Error: Config setting for -wallet only applied on regtest network when in [regtest] section.') + self.nodes[0].assert_start_raises_init_error( + expected_msg='Error: Config setting for -wallet only applied on regtest network when in [regtest] section.') with open(inc_conf_file_path, 'w', encoding='utf-8') as conf: - conf.write('regtest=0\n') # mainnet + conf.write('regtest=0\n') # mainnet conf.write('acceptnonstdtxn=1\n') - self.nodes[0].assert_start_raises_init_error(expected_msg='Error: acceptnonstdtxn is not currently supported for main chain') + self.nodes[0].assert_start_raises_init_error( + expected_msg='Error: acceptnonstdtxn is not currently supported for main chain') with open(inc_conf_file_path, 'w', encoding='utf-8') as conf: conf.write('nono\n') - self.nodes[0].assert_start_raises_init_error(expected_msg='Error: Error reading configuration file: parse error on line 1: nono, if you intended to specify a negated option, use nono=1 instead') + self.nodes[0].assert_start_raises_init_error( + expected_msg='Error: Error reading configuration file: parse error on line 1: nono, if you intended to specify a negated option, use nono=1 instead') with open(inc_conf_file_path, 'w', encoding='utf-8') as conf: conf.write('server=1\nrpcuser=someuser\nrpcpassword=some#pass') - self.nodes[0].assert_start_raises_init_error(expected_msg='Error: Error reading configuration file: parse error on line 3, using # in rpcpassword can be ambiguous and should be avoided') + self.nodes[0].assert_start_raises_init_error( + expected_msg='Error: Error reading configuration file: parse error on line 3, using # in rpcpassword can be ambiguous and should be avoided') with open(inc_conf_file_path, 'w', encoding='utf-8') as conf: conf.write('server=1\nrpcuser=someuser\nmain.rpcpassword=some#pass') - self.nodes[0].assert_start_raises_init_error(expected_msg='Error: Error reading configuration file: parse error on line 3, using # in rpcpassword can be ambiguous and should be avoided') + self.nodes[0].assert_start_raises_init_error( + expected_msg='Error: Error reading configuration file: parse error on line 3, using # in rpcpassword can be ambiguous and should be avoided') with open(inc_conf_file_path, 'w', encoding='utf-8') as conf: conf.write('server=1\nrpcuser=someuser\n[main]\nrpcpassword=some#pass') - self.nodes[0].assert_start_raises_init_error(expected_msg='Error: Error reading configuration file: parse error on line 4, using # in rpcpassword can be ambiguous and should be avoided') + self.nodes[0].assert_start_raises_init_error( + expected_msg='Error: Error reading configuration file: parse error on line 4, using # in rpcpassword can be ambiguous and should be avoided') inc_conf_file2_path = os.path.join(self.nodes[0].datadir, 'include2.conf') with open(os.path.join(self.nodes[0].datadir, 'defi.conf'), 'a', encoding='utf-8') as conf: @@ -70,7 +77,8 @@ def test_config_file_parser(self): with open(inc_conf_file2_path, 'w', encoding='utf-8') as conf: conf.write('[testnet]\n') self.restart_node(0) - self.nodes[0].stop_node(expected_stderr='Warning: ' + inc_conf_file_path + ':1 Section [testnot] is not recognized.' + os.linesep + 'Warning: ' + inc_conf_file2_path + ':1 Section [testnet] is not recognized.') + self.nodes[0].stop_node( + expected_stderr='Warning: ' + inc_conf_file_path + ':1 Section [testnot] is not recognized.' + os.linesep + 'Warning: ' + inc_conf_file2_path + ':1 Section [testnet] is not recognized.') with open(inc_conf_file_path, 'w', encoding='utf-8') as conf: conf.write('') # clear @@ -78,7 +86,8 @@ def test_config_file_parser(self): conf.write('') # clear def test_log_buffer(self): - with self.nodes[0].assert_debug_log(expected_msgs=['Warning: parsed potentially confusing double-negative -connect=0']): + with self.nodes[0].assert_debug_log( + expected_msgs=['Warning: parsed potentially confusing double-negative -connect=0']): self.start_node(0, extra_args=['-noconnect=0']) self.stop_node(0) @@ -98,7 +107,8 @@ def run_test(self): # Check that using -datadir argument on non-existent directory fails self.nodes[0].datadir = new_data_dir - self.nodes[0].assert_start_raises_init_error(['-datadir=' + new_data_dir], 'Error: Specified data directory "' + new_data_dir + '" does not exist.') + self.nodes[0].assert_start_raises_init_error(['-datadir=' + new_data_dir], + 'Error: Specified data directory "' + new_data_dir + '" does not exist.') # Check that using non-existent datadir in conf file fails conf_file = os.path.join(default_data_dir, "defi.conf") @@ -109,11 +119,12 @@ def run_test(self): f.write("datadir=" + new_data_dir + "\n") f.write(conf_file_contents) - self.nodes[0].assert_start_raises_init_error(['-conf=' + conf_file], 'Error: Error reading configuration file: specified data directory "' + new_data_dir + '" does not exist.') + self.nodes[0].assert_start_raises_init_error(['-conf=' + conf_file], + 'Error: Error reading configuration file: specified data directory "' + new_data_dir + '" does not exist.') # Create the directory and ensure the config file now works os.mkdir(new_data_dir) - self.start_node(0, ['-conf='+conf_file, '-wallet=w1']) + self.start_node(0, ['-conf=' + conf_file, '-wallet=w1']) self.stop_node(0) assert os.path.exists(os.path.join(new_data_dir, 'regtest', 'blocks')) if self.is_wallet_compiled(): @@ -122,7 +133,7 @@ def run_test(self): # Ensure command line argument overrides datadir in conf os.mkdir(new_data_dir_2) self.nodes[0].datadir = new_data_dir_2 - self.start_node(0, ['-datadir='+new_data_dir_2, '-conf='+conf_file, '-wallet=w2']) + self.start_node(0, ['-datadir=' + new_data_dir_2, '-conf=' + conf_file, '-wallet=w2']) assert os.path.exists(os.path.join(new_data_dir_2, 'regtest', 'blocks')) if self.is_wallet_compiled(): assert os.path.exists(os.path.join(new_data_dir_2, 'regtest', 'wallets', 'w2')) diff --git a/test/functional/feature_consortium.py b/test/functional/feature_consortium.py index 4160433aa1..7cf7bb8420 100755 --- a/test/functional/feature_consortium.py +++ b/test/functional/feature_consortium.py @@ -10,18 +10,34 @@ from decimal import Decimal import time -class ConsortiumTest (DefiTestFramework): + +class ConsortiumTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 4 self.setup_clean_chain = True self.extra_args = [ - ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=1', '-fortcanningheight=50', '-eunosheight=50', '-fortcanninghillheight=50', '-fortcanningparkheight=50', '-fortcanningroadheight=50', '-fortcanningcrunchheight=50', '-fortcanningspringheight=50', '-fortcanninggreatworldheight=250', '-grandcentralheight=254', '-grandcentralepilogueheight=350', '-regtest-minttoken-simulate-mainnet=1', '-txindex=1'], - ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=1', '-fortcanningheight=50', '-eunosheight=50', '-fortcanninghillheight=50', '-fortcanningparkheight=50', '-fortcanningroadheight=50', '-fortcanningcrunchheight=50', '-fortcanningspringheight=50', '-fortcanninggreatworldheight=250', '-grandcentralheight=254', '-grandcentralepilogueheight=350', '-regtest-minttoken-simulate-mainnet=1', '-txindex=1'], - ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=1', '-fortcanningheight=50', '-eunosheight=50', '-fortcanninghillheight=50', '-fortcanningparkheight=50', '-fortcanningroadheight=50', '-fortcanningcrunchheight=50', '-fortcanningspringheight=50', '-fortcanninggreatworldheight=250', '-grandcentralheight=254', '-grandcentralepilogueheight=350', '-regtest-minttoken-simulate-mainnet=1', '-txindex=1'], - ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=1', '-fortcanningheight=50', '-eunosheight=50', '-fortcanninghillheight=50', '-fortcanningparkheight=50', '-fortcanningroadheight=50', '-fortcanningcrunchheight=50', '-fortcanningspringheight=50', '-fortcanninggreatworldheight=250', '-grandcentralheight=254', '-grandcentralepilogueheight=350', '-regtest-minttoken-simulate-mainnet=1', '-txindex=1']] + ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=1', + '-fortcanningheight=50', '-eunosheight=50', '-fortcanninghillheight=50', '-fortcanningparkheight=50', + '-fortcanningroadheight=50', '-fortcanningcrunchheight=50', '-fortcanningspringheight=50', + '-fortcanninggreatworldheight=250', '-grandcentralheight=254', '-grandcentralepilogueheight=350', + '-regtest-minttoken-simulate-mainnet=1', '-txindex=1'], + ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=1', + '-fortcanningheight=50', '-eunosheight=50', '-fortcanninghillheight=50', '-fortcanningparkheight=50', + '-fortcanningroadheight=50', '-fortcanningcrunchheight=50', '-fortcanningspringheight=50', + '-fortcanninggreatworldheight=250', '-grandcentralheight=254', '-grandcentralepilogueheight=350', + '-regtest-minttoken-simulate-mainnet=1', '-txindex=1'], + ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=1', + '-fortcanningheight=50', '-eunosheight=50', '-fortcanninghillheight=50', '-fortcanningparkheight=50', + '-fortcanningroadheight=50', '-fortcanningcrunchheight=50', '-fortcanningspringheight=50', + '-fortcanninggreatworldheight=250', '-grandcentralheight=254', '-grandcentralepilogueheight=350', + '-regtest-minttoken-simulate-mainnet=1', '-txindex=1'], + ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=1', + '-fortcanningheight=50', '-eunosheight=50', '-fortcanninghillheight=50', '-fortcanningparkheight=50', + '-fortcanningroadheight=50', '-fortcanningcrunchheight=50', '-fortcanningspringheight=50', + '-fortcanninggreatworldheight=250', '-grandcentralheight=254', '-grandcentralepilogueheight=350', + '-regtest-minttoken-simulate-mainnet=1', '-txindex=1']] def run_test(self): - print("Generating initial chain...") self.nodes[0].generate(100) self.sync_blocks() @@ -83,18 +99,24 @@ def run_test(self): self.nodes[3].generate(1) self.sync_blocks() - assert_raises_rpc_error(-32600, "You are not a foundation member or token owner and cannot mint this token", self.nodes[2].minttokens, ["1@" + symbolBTC]) - assert_raises_rpc_error(-32600, "You are not a foundation member or token owner and cannot mint this token", self.nodes[2].minttokens, ["1@" + symbolDOGE]) - assert_raises_rpc_error(-32600, "You are not a foundation member or token owner and cannot mint this token", self.nodes[3].minttokens, ["1@" + symbolBTC]) + assert_raises_rpc_error(-32600, "You are not a foundation member or token owner and cannot mint this token", + self.nodes[2].minttokens, ["1@" + symbolBTC]) + assert_raises_rpc_error(-32600, "You are not a foundation member or token owner and cannot mint this token", + self.nodes[2].minttokens, ["1@" + symbolDOGE]) + assert_raises_rpc_error(-32600, "You are not a foundation member or token owner and cannot mint this token", + self.nodes[3].minttokens, ["1@" + symbolBTC]) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/feature/consortium' : 'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/feature/consortium': 'true'}}) self.nodes[0].generate(1) self.sync_blocks() - assert_raises_rpc_error(-32600, "You are not a foundation member or token owner and cannot mint this token", self.nodes[2].minttokens, ["1@" + symbolBTC]) - assert_raises_rpc_error(-32600, "You are not a foundation member or token owner and cannot mint this token", self.nodes[2].minttokens, ["1@" + symbolDOGE]) - assert_raises_rpc_error(-32600, "You are not a foundation member or token owner and cannot mint this token", self.nodes[3].minttokens, ["1@" + symbolBTC]) + assert_raises_rpc_error(-32600, "You are not a foundation member or token owner and cannot mint this token", + self.nodes[2].minttokens, ["1@" + symbolBTC]) + assert_raises_rpc_error(-32600, "You are not a foundation member or token owner and cannot mint this token", + self.nodes[2].minttokens, ["1@" + symbolDOGE]) + assert_raises_rpc_error(-32600, "You are not a foundation member or token owner and cannot mint this token", + self.nodes[3].minttokens, ["1@" + symbolBTC]) # Set global mint limits self.nodes[0].setgov({"ATTRIBUTES": {'v0/consortium/' + idBTC + '/mint_limit': '0', @@ -107,8 +129,8 @@ def run_test(self): assert_equal(attributes['v0/consortium/' + idBTC + '/mint_limit_daily'], '0') # Set global mint limits - self.nodes[0].setgov({"ATTRIBUTES":{'v0/consortium/' + idBTC + '/mint_limit' : '10', - 'v0/consortium/' + idBTC + '/mint_limit_daily' : '10'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/consortium/' + idBTC + '/mint_limit': '10', + 'v0/consortium/' + idBTC + '/mint_limit_daily': '10'}}) self.nodes[0].generate(1) self.sync_blocks() @@ -118,44 +140,55 @@ def run_test(self): assert_equal(attributes['v0/consortium/' + idBTC + '/mint_limit_daily'], '10') # Test setting member mint limit hight than global mint - assert_raises_rpc_error(-32600, "Mint limit higher than global mint limit", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/consortium/' + idBTC + '/members' : {"01":{"name":"account2BTC", - "ownerAddress": account2, - "backingId":"ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf", - "mintLimitDaily":10.00000000, - "mintLimit":11.00000000}}}}) + assert_raises_rpc_error(-32600, "Mint limit higher than global mint limit", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/consortium/' + idBTC + '/members': {"01": {"name": "account2BTC", + "ownerAddress": account2, + "backingId": "ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf", + "mintLimitDaily": 10.00000000, + "mintLimit": 11.00000000}}}}) # Test setting member mint limit hight than global mint - assert_raises_rpc_error(-32600, "Daily mint limit higher than daily global mint limit", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/consortium/' + idBTC + '/members' : {"01":{"name":"account2BTC", - "ownerAddress": account2, - "backingId":"ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf", - "mintLimitDaily":11.00000000, - "mintLimit":10.00000000}}}}) + assert_raises_rpc_error(-32600, "Daily mint limit higher than daily global mint limit", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/consortium/' + idBTC + '/members': {"01": {"name": "account2BTC", + "ownerAddress": account2, + "backingId": "ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf", + "mintLimitDaily": 11.00000000, + "mintLimit": 10.00000000}}}}) # Set consortium members - self.nodes[0].setgov({"ATTRIBUTES":{'v0/consortium/' + idBTC + '/members' : {"01":{"name":"account2BTC", + self.nodes[0].setgov({"ATTRIBUTES": {'v0/consortium/' + idBTC + '/members': {"01": {"name": "account2BTC", "ownerAddress": account2, - "backingId":"ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf", - "mintLimitDaily":10.00000000, - "mintLimit":10.00000000}, - "02":{"name":"account3BTC", + "backingId": "ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf", + "mintLimitDaily": 10.00000000, + "mintLimit": 10.00000000}, + "02": {"name": "account3BTC", "ownerAddress": account3, - "backingId":"6c67fe93cad3d6a4982469a9b6708cdde2364f183d3698d3745f86eeb8ba99d5", - "mintLimitDaily":4.00000000, - "mintLimit":4.00000000}}}}) + "backingId": "6c67fe93cad3d6a4982469a9b6708cdde2364f183d3698d3745f86eeb8ba99d5", + "mintLimitDaily": 4.00000000, + "mintLimit": 4.00000000}}}}) self.nodes[0].generate(1) self.sync_blocks() - assert_raises_rpc_error(-32600, "Cannot add a member with an owner address of a existing consortium member", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/consortium/' + idBTC + '/members' : {"03":{"name":"test", - "ownerAddress": account2, - "backingId":"7cb2f6954291d81d2270c9a6a52442b3f8c637b1ec793c731cb5f5a8f7fb9b9d", - "mintLimitDaily":10.00000000, - "mintLimit":10.00000000}}}}) + assert_raises_rpc_error(-32600, "Cannot add a member with an owner address of a existing consortium member", + self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/consortium/' + idBTC + '/members': {"03": {"name": "test", + "ownerAddress": account2, + "backingId": "7cb2f6954291d81d2270c9a6a52442b3f8c637b1ec793c731cb5f5a8f7fb9b9d", + "mintLimitDaily": 10.00000000, + "mintLimit": 10.00000000}}}}) attribs = self.nodes[2].getgov('ATTRIBUTES')['ATTRIBUTES'] - assert_equal(attribs['v0/consortium/' + idBTC + '/members'], {"01":{"name":"account2BTC","ownerAddress": account2,"backingId":"ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf","mintLimit": Decimal('10.00000000'),"mintLimitDaily":Decimal('10.00000000'),"status":0},"02":{"name":"account3BTC","ownerAddress": account3,"backingId":"6c67fe93cad3d6a4982469a9b6708cdde2364f183d3698d3745f86eeb8ba99d5","mintLimit":Decimal('4.00000000'),"mintLimitDaily":Decimal('4.00000000'),"status":0}}) + assert_equal(attribs['v0/consortium/' + idBTC + '/members'], { + "01": {"name": "account2BTC", "ownerAddress": account2, + "backingId": "ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf", + "mintLimit": Decimal('10.00000000'), "mintLimitDaily": Decimal('10.00000000'), "status": 0}, + "02": {"name": "account3BTC", "ownerAddress": account3, + "backingId": "6c67fe93cad3d6a4982469a9b6708cdde2364f183d3698d3745f86eeb8ba99d5", + "mintLimit": Decimal('4.00000000'), "mintLimitDaily": Decimal('4.00000000'), "status": 0}}) assert_equal(attribs['v0/consortium/' + idBTC + '/mint_limit'], '10') - assert_raises_rpc_error(-32600, "You are not a foundation member or token owner and cannot mint this token", self.nodes[2].minttokens, ["1@" + symbolDOGE]) + assert_raises_rpc_error(-32600, "You are not a foundation member or token owner and cannot mint this token", + self.nodes[2].minttokens, ["1@" + symbolDOGE]) self.nodes[2].minttokens(["1@" + symbolBTC]) self.nodes[2].generate(1) @@ -168,34 +201,49 @@ def run_test(self): assert_equal(attribs['v0/live/economy/consortium/1/supply'], Decimal('1.00000000')) # Set global mint limits - self.nodes[0].setgov({"ATTRIBUTES":{'v0/consortium/' + idDOGE + '/mint_limit' : '6', 'v0/consortium/' + idDOGE + '/mint_limit_daily' : '6'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/consortium/' + idDOGE + '/mint_limit': '6', + 'v0/consortium/' + idDOGE + '/mint_limit_daily': '6'}}) self.nodes[0].generate(1) self.sync_blocks() # Create consortium members - self.nodes[0].setgov({"ATTRIBUTES":{'v0/consortium/' + idDOGE + '/members' : {"01":{"name":"account2DOGE", - "ownerAddress": account2, - "backingId":"ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf", - "mintLimitDaily":5.00000000, - "mintLimit":5.00000000}}}}) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/consortium/' + idDOGE + '/members' : {"02":{"name":"account1DOGE", - "ownerAddress": account1, - "backingId":"ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf", - "mintLimitDaily":5.00000000, - "mintLimit":5.00000000}}}}) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/consortium/' + idDOGE + '/mint_limit' : '6', 'v0/consortium/' + idDOGE + '/mint_limit_daily' : '6'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/consortium/' + idDOGE + '/members': {"01": {"name": "account2DOGE", + "ownerAddress": account2, + "backingId": "ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf", + "mintLimitDaily": 5.00000000, + "mintLimit": 5.00000000}}}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/consortium/' + idDOGE + '/members': {"02": {"name": "account1DOGE", + "ownerAddress": account1, + "backingId": "ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf", + "mintLimitDaily": 5.00000000, + "mintLimit": 5.00000000}}}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/consortium/' + idDOGE + '/mint_limit': '6', + 'v0/consortium/' + idDOGE + '/mint_limit_daily': '6'}}) self.nodes[0].generate(1) self.sync_blocks() attribs = self.nodes[2].getgov('ATTRIBUTES')['ATTRIBUTES'] - assert_equal(attribs['v0/consortium/' + idBTC + '/members'], {"01":{"name":"account2BTC","ownerAddress": account2,"backingId":"ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf","mintLimit":Decimal('10.00000000'),"mintLimitDaily":Decimal('10.00000000'),"status":0},"02":{"name":"account3BTC","ownerAddress": account3,"backingId":"6c67fe93cad3d6a4982469a9b6708cdde2364f183d3698d3745f86eeb8ba99d5","mintLimit":Decimal('4.00000000'),"mintLimitDaily":Decimal('4.00000000'),"status":0}}) + assert_equal(attribs['v0/consortium/' + idBTC + '/members'], { + "01": {"name": "account2BTC", "ownerAddress": account2, + "backingId": "ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf", + "mintLimit": Decimal('10.00000000'), "mintLimitDaily": Decimal('10.00000000'), "status": 0}, + "02": {"name": "account3BTC", "ownerAddress": account3, + "backingId": "6c67fe93cad3d6a4982469a9b6708cdde2364f183d3698d3745f86eeb8ba99d5", + "mintLimit": Decimal('4.00000000'), "mintLimitDaily": Decimal('4.00000000'), "status": 0}}) assert_equal(attribs['v0/consortium/' + idBTC + '/mint_limit'], '10') - assert_equal(attribs['v0/consortium/' + idDOGE + '/members'], {"01":{"name":"account2DOGE","ownerAddress": account2,"backingId":"ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf","mintLimit":Decimal('5.00000000'),"mintLimitDaily":Decimal('5.00000000'),"status":0},"02":{"name":"account1DOGE","ownerAddress": account1,"backingId":"ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf","mintLimit":Decimal('5.00000000'),"mintLimitDaily":Decimal('5.00000000'),"status":0}}) + assert_equal(attribs['v0/consortium/' + idDOGE + '/members'], { + "01": {"name": "account2DOGE", "ownerAddress": account2, + "backingId": "ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf", + "mintLimit": Decimal('5.00000000'), "mintLimitDaily": Decimal('5.00000000'), "status": 0}, + "02": {"name": "account1DOGE", "ownerAddress": account1, + "backingId": "ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf", + "mintLimit": Decimal('5.00000000'), "mintLimitDaily": Decimal('5.00000000'), "status": 0}}) assert_equal(attribs['v0/consortium/' + idDOGE + '/mint_limit'], '6') assert_equal(attribs['v0/consortium/' + idDOGE + '/mint_limit_daily'], '6') - assert_raises_rpc_error(-32600, "You are not a foundation or consortium member and cannot mint this token", self.nodes[3].minttokens, ["1@" + symbolDOGE]) + assert_raises_rpc_error(-32600, "You are not a foundation or consortium member and cannot mint this token", + self.nodes[3].minttokens, ["1@" + symbolDOGE]) self.nodes[2].minttokens(["2@" + symbolDOGE]) self.nodes[2].generate(1) @@ -219,8 +267,12 @@ def run_test(self): assert_equal(attribs['v0/live/economy/consortium_members/2/01/burnt'], Decimal('0.00000000')) assert_equal(attribs['v0/live/economy/consortium_members/2/01/supply'], Decimal('2.00000000')) - assert_raises_rpc_error(-32600, "You will exceed your maximum mint limit for " + symbolDOGE + " token by minting this amount!", self.nodes[2].minttokens, ["3.00000001@" + symbolDOGE]) - assert_raises_rpc_error(-8, "No valid addresses could be found, use the \"from\" argument to set address to burn from", self.nodes[0].burntokens, {'amounts': "1.00000000@" + symbolBTC}) + assert_raises_rpc_error(-32600, + "You will exceed your maximum mint limit for " + symbolDOGE + " token by minting this amount!", + self.nodes[2].minttokens, ["3.00000001@" + symbolDOGE]) + assert_raises_rpc_error(-8, + "No valid addresses could be found, use the \"from\" argument to set address to burn from", + self.nodes[0].burntokens, {'amounts': "1.00000000@" + symbolBTC}) self.nodes[0].burntokens({ 'amounts': "2@" + symbolBTC, @@ -311,20 +363,32 @@ def run_test(self): assert_equal(attribs['v0/live/economy/consortium_members/2/01/burnt'], Decimal('1.50000000')) assert_equal(attribs['v0/live/economy/consortium_members/2/01/supply'], Decimal('0.50000000')) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/consortium/' + idDOGE + '/members' : {"01":{"name":"account2DOGE", - "ownerAddress": account2, - "backingId":"ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf", - "mintLimit":5.00000000, - "mintLimitDaily":5.00000000, - "status":1}}}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/consortium/' + idDOGE + '/members': {"01": {"name": "account2DOGE", + "ownerAddress": account2, + "backingId": "ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf", + "mintLimit": 5.00000000, + "mintLimitDaily": 5.00000000, + "status": 1}}}}) self.nodes[0].generate(1) self.sync_blocks() attribs = self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'] - assert_equal(attribs['v0/consortium/' + idDOGE + '/members'], {"01":{"name":"account2DOGE","ownerAddress": account2,"backingId":"ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf","mintLimit":Decimal('5.00000000'),"mintLimitDaily":Decimal('5.00000000'),"status":1},"02":{"name":"account1DOGE","ownerAddress": account1,"backingId":"ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf","mintLimit":Decimal('5.00000000'),"mintLimitDaily":Decimal('5.00000000'),"status":0}}) - assert_equal(self.nodes[0].getburninfo(), {'address': 'mfburnZSAM7Gs1hpDeNaMotJXSGA7edosG', 'amount': Decimal('0E-8'), 'tokens': ['2.00000000@BTC', '0.50000000@DOGE'], 'consortiumtokens': ['1.50000000@DOGE'], 'feeburn': Decimal('2.00000000'), 'auctionburn': Decimal('0E-8'), 'paybackburn': [], 'dexfeetokens': [], 'dfipaybackfee': Decimal('0E-8'), 'dfipaybacktokens': [], 'paybackfees': [], 'paybacktokens': [], 'emissionburn': Decimal('4923.76500000'), 'dfip2203': [], 'dfip2206f': []}) - - assert_raises_rpc_error(-32600, "Cannot mint token, not an active member of consortium for DOGE!", self.nodes[2].minttokens, ["1@" + symbolDOGE]) + assert_equal(attribs['v0/consortium/' + idDOGE + '/members'], { + "01": {"name": "account2DOGE", "ownerAddress": account2, + "backingId": "ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf", + "mintLimit": Decimal('5.00000000'), "mintLimitDaily": Decimal('5.00000000'), "status": 1}, + "02": {"name": "account1DOGE", "ownerAddress": account1, + "backingId": "ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf", + "mintLimit": Decimal('5.00000000'), "mintLimitDaily": Decimal('5.00000000'), "status": 0}}) + assert_equal(self.nodes[0].getburninfo(), + {'address': 'mfburnZSAM7Gs1hpDeNaMotJXSGA7edosG', 'amount': Decimal('0E-8'), + 'tokens': ['2.00000000@BTC', '0.50000000@DOGE'], 'consortiumtokens': ['1.50000000@DOGE'], + 'feeburn': Decimal('2.00000000'), 'auctionburn': Decimal('0E-8'), 'paybackburn': [], + 'dexfeetokens': [], 'dfipaybackfee': Decimal('0E-8'), 'dfipaybacktokens': [], 'paybackfees': [], + 'paybacktokens': [], 'emissionburn': Decimal('4923.76500000'), 'dfip2203': [], 'dfip2206f': []}) + + assert_raises_rpc_error(-32600, "Cannot mint token, not an active member of consortium for DOGE!", + self.nodes[2].minttokens, ["1@" + symbolDOGE]) # can mint because it is a founder self.nodes[0].minttokens(["1@" + symbolBTC]) @@ -366,23 +430,29 @@ def run_test(self): assert_equal(attribs['v0/live/economy/consortium_members/1/02/burnt'], Decimal('0.00000000')) assert_equal(attribs['v0/live/economy/consortium_members/1/02/supply'], Decimal('2.00000000')) - assert_raises_rpc_error(-32600, "You will exceed your maximum mint limit for " + symbolBTC + " token by minting this amount!", self.nodes[3].minttokens, ["2.00000001@" + symbolBTC]) - assert_raises_rpc_error(-32600, "You will exceed global maximum consortium mint limit for " + symbolBTC + " token by minting this amount!", self.nodes[3].minttokens, ["1.00000001@" + symbolBTC]) + assert_raises_rpc_error(-32600, + "You will exceed your maximum mint limit for " + symbolBTC + " token by minting this amount!", + self.nodes[3].minttokens, ["2.00000001@" + symbolBTC]) + assert_raises_rpc_error(-32600, + "You will exceed global maximum consortium mint limit for " + symbolBTC + " token by minting this amount!", + self.nodes[3].minttokens, ["1.00000001@" + symbolBTC]) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/consortium/' + idBTC + '/members' : {"02":{"name":"account3BTC", - "ownerAddress": account3, - "backingId":"6c67fe93cad3d6a4982469a9b6708cdde2364f183d3698d3745f86eeb8ba99d5", - "mintLimitDaily":4.00000000, - "mintLimit":6.00000000}}}}) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/consortium/' + idBTC + '/mint_limit' : '20'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/consortium/' + idBTC + '/members': {"02": {"name": "account3BTC", + "ownerAddress": account3, + "backingId": "6c67fe93cad3d6a4982469a9b6708cdde2364f183d3698d3745f86eeb8ba99d5", + "mintLimitDaily": 4.00000000, + "mintLimit": 6.00000000}}}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/consortium/' + idBTC + '/mint_limit': '20'}}) self.nodes[0].generate(1) self.sync_blocks() # Test global daily limit - assert_raises_rpc_error(-32600, "You will exceed global daily maximum consortium mint limit for " + symbolBTC + " token by minting this amount.", self.nodes[3].minttokens, ["2@" + symbolBTC]) + assert_raises_rpc_error(-32600, + "You will exceed global daily maximum consortium mint limit for " + symbolBTC + " token by minting this amount.", + self.nodes[3].minttokens, ["2@" + symbolBTC]) # Increase global daily limit - self.nodes[0].setgov({"ATTRIBUTES":{'v0/consortium/' + idBTC + '/mint_limit_daily' : '12'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/consortium/' + idBTC + '/mint_limit_daily': '12'}}) self.nodes[0].generate(1) self.sync_blocks() @@ -396,7 +466,9 @@ def run_test(self): assert_equal(attribs['v0/live/economy/consortium_members/1/02/daily_minted'], '144/4.00000000') # Test daily limit - assert_raises_rpc_error(-32600, "You will exceed your daily mint limit for " + symbolBTC + " token by minting this amount", self.nodes[3].minttokens, ["2@" + symbolBTC]) + assert_raises_rpc_error(-32600, + "You will exceed your daily mint limit for " + symbolBTC + " token by minting this amount", + self.nodes[3].minttokens, ["2@" + symbolBTC]) # Move to next day, day is 144 blocks on regtest. self.nodes[0].generate(288 - self.nodes[0].getblockcount()) @@ -412,20 +484,24 @@ def run_test(self): assert_equal(attribs['v0/live/economy/consortium_members/1/02/minted'], Decimal('6.00000000')) assert_equal(attribs['v0/live/economy/consortium_members/1/02/daily_minted'], '288/2.00000000') - self.nodes[0].setgov({"ATTRIBUTES":{'v0/consortium/' + idBTC + '/members' : {"02":{"name":"account3BTC", + self.nodes[0].setgov({"ATTRIBUTES": {'v0/consortium/' + idBTC + '/members': {"02": {"name": "account3BTC", "ownerAddress": account3, - "backingId":"6c67fe93cad3d6a4982469a9b6708cdde2364f183d3698d3745f86eeb8ba99d5", - "mintLimitDaily":2.00000000, - "mintLimit":8.00000000}}}}) + "backingId": "6c67fe93cad3d6a4982469a9b6708cdde2364f183d3698d3745f86eeb8ba99d5", + "mintLimitDaily": 2.00000000, + "mintLimit": 8.00000000}}}}) self.nodes[0].generate(1) self.sync_blocks() # Test new daily limit - assert_raises_rpc_error(-32600, "You will exceed your daily mint limit for " + symbolBTC + " token by minting this amount", self.nodes[3].minttokens, ["1@" + symbolBTC]) + assert_raises_rpc_error(-32600, + "You will exceed your daily mint limit for " + symbolBTC + " token by minting this amount", + self.nodes[3].minttokens, ["1@" + symbolBTC]) # burn to check that burning from address of a member for different token does not get counted when burning other tokens - assert_raises_rpc_error(-8, "No valid addresses could be found, use the \"from\" argument to set address to burn from", self.nodes[1].burntokens, {'amounts': "0.10000000@" + symbolBTC}) + assert_raises_rpc_error(-8, + "No valid addresses could be found, use the \"from\" argument to set address to burn from", + self.nodes[1].burntokens, {'amounts': "0.10000000@" + symbolBTC}) self.nodes[1].burntokens({ 'amounts': "0.1@" + symbolBTC, 'from': account1, @@ -482,14 +558,17 @@ def run_test(self): assert_equal(attribs['v0/live/economy/consortium_members/1/02/burnt'], Decimal('0.00000000')) assert_equal(attribs['v0/live/economy/consortium_members/1/02/supply'], Decimal('6.00000000')) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/feature/consortium' : 'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/feature/consortium': 'false'}}) self.nodes[0].generate(1) self.sync_blocks() - assert_raises_rpc_error(-32600, "You are not a foundation member or token owner and cannot mint this token", self.nodes[2].minttokens, ["1@" + symbolBTC]) - assert_raises_rpc_error(-32600, "You are not a foundation member or token owner and cannot mint this token", self.nodes[2].minttokens, ["1@" + symbolDOGE]) - assert_raises_rpc_error(-32600, "You are not a foundation member or token owner and cannot mint this token", self.nodes[3].minttokens, ["1@" + symbolBTC]) + assert_raises_rpc_error(-32600, "You are not a foundation member or token owner and cannot mint this token", + self.nodes[2].minttokens, ["1@" + symbolBTC]) + assert_raises_rpc_error(-32600, "You are not a foundation member or token owner and cannot mint this token", + self.nodes[2].minttokens, ["1@" + symbolDOGE]) + assert_raises_rpc_error(-32600, "You are not a foundation member or token owner and cannot mint this token", + self.nodes[3].minttokens, ["1@" + symbolBTC]) # DAT owner can mint again self.nodes[3].minttokens(["1@" + symbolDOGE]) @@ -497,7 +576,8 @@ def run_test(self): self.sync_blocks() # Test unlimited limit - self.nodes[0].setgov({"ATTRIBUTES": {'v0/consortium/' + idBTC + '/mint_limit': '-1', 'v0/consortium/' + idBTC + '/mint_limit_daily': '-1'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/consortium/' + idBTC + '/mint_limit': '-1', + 'v0/consortium/' + idBTC + '/mint_limit_daily': '-1'}}) self.nodes[0].generate(1) self.sync_blocks() @@ -505,36 +585,42 @@ def run_test(self): self.nodes[0].generate(1) # Increase limit - self.nodes[0].setgov({"ATTRIBUTES": {'v0/consortium/' + idBTC + '/members': {"01":{"name":"account2BTC", + self.nodes[0].setgov({"ATTRIBUTES": {'v0/consortium/' + idBTC + '/members': {"01": {"name": "account2BTC", "ownerAddress": account2, - "backingId":"ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf", - "mintLimitDaily":100000.00000000, - "mintLimit":100000.00000000}, - "02":{"name":"account3BTC", + "backingId": "ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf", + "mintLimitDaily": 100000.00000000, + "mintLimit": 100000.00000000}, + "02": {"name": "account3BTC", "ownerAddress": account3, - "backingId":"6c67fe93cad3d6a4982469a9b6708cdde2364f183d3698d3745f86eeb8ba99d5", - "mintLimitDaily":400000.00000000, - "mintLimit":400000.00000000}}}}) + "backingId": "6c67fe93cad3d6a4982469a9b6708cdde2364f183d3698d3745f86eeb8ba99d5", + "mintLimitDaily": 400000.00000000, + "mintLimit": 400000.00000000}}}}) self.nodes[0].generate(1) # Decrease limit - self.nodes[0].setgov({"ATTRIBUTES": {'v0/consortium/' + idBTC + '/members': {"01":{"name":"account2BTC", + self.nodes[0].setgov({"ATTRIBUTES": {'v0/consortium/' + idBTC + '/members': {"01": {"name": "account2BTC", "ownerAddress": account2, - "backingId":"ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf", - "mintLimitDaily":1.00000000, - "mintLimit":1.00000000}, - "02":{"name":"account3BTC", + "backingId": "ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf", + "mintLimitDaily": 1.00000000, + "mintLimit": 1.00000000}, + "02": {"name": "account3BTC", "ownerAddress": account3, - "backingId":"6c67fe93cad3d6a4982469a9b6708cdde2364f183d3698d3745f86eeb8ba99d5", - "mintLimitDaily":1.00000000, - "mintLimit":1.00000000}}}}) + "backingId": "6c67fe93cad3d6a4982469a9b6708cdde2364f183d3698d3745f86eeb8ba99d5", + "mintLimitDaily": 1.00000000, + "mintLimit": 1.00000000}}}}) self.nodes[0].generate(1) # Throw error for invalid values assert_raises_rpc_error(-5, "Amount must be positive or -1", self.nodes[0].setgov, { "ATTRIBUTES": {'v0/consortium/' + idBTC + '/mint_limit': '-2'}}) - assert_equal(self.nodes[0].getburninfo(), {'address': 'mfburnZSAM7Gs1hpDeNaMotJXSGA7edosG', 'amount': Decimal('0E-8'), 'tokens': ['2.10000000@BTC', '0.50000000@DOGE'], 'consortiumtokens': ['6.10000000@BTC', '1.50000000@DOGE'], 'feeburn': Decimal('2.00000000'), 'auctionburn': Decimal('0E-8'), 'paybackburn': [], 'dexfeetokens': [], 'dfipaybackfee': Decimal('0E-8'), 'dfipaybacktokens': [], 'paybackfees': [], 'paybacktokens': [], 'emissionburn': Decimal('5386.81500000'), 'dfip2203': [], 'dfip2206f': []}) + assert_equal(self.nodes[0].getburninfo(), + {'address': 'mfburnZSAM7Gs1hpDeNaMotJXSGA7edosG', 'amount': Decimal('0E-8'), + 'tokens': ['2.10000000@BTC', '0.50000000@DOGE'], + 'consortiumtokens': ['6.10000000@BTC', '1.50000000@DOGE'], 'feeburn': Decimal('2.00000000'), + 'auctionburn': Decimal('0E-8'), 'paybackburn': [], 'dexfeetokens': [], + 'dfipaybackfee': Decimal('0E-8'), 'dfipaybacktokens': [], 'paybackfees': [], 'paybacktokens': [], + 'emissionburn': Decimal('5386.81500000'), 'dfip2203': [], 'dfip2206f': []}) # Price feeds price_feed = [ @@ -567,37 +653,48 @@ def run_test(self): idTSLA = list(self.nodes[0].gettoken("TSLA").keys())[0] # Try and set consortium value for DFI and loan token - assert_raises_rpc_error(-32600, "Cannot set consortium on DFI, loan tokens and non-DAT tokens", self.nodes[0].setgov, { - "ATTRIBUTES": {'v0/consortium/' + idTSLA + '/mint_limit': '10'}}) - assert_raises_rpc_error(-32600, "Cannot set consortium on DFI, loan tokens and non-DAT tokens", self.nodes[0].setgov, { - "ATTRIBUTES": {'v0/consortium/' + idTSLA + '/mint_limit_daily': '10'}}) - assert_raises_rpc_error(-32600, "Cannot set consortium on DFI, loan tokens and non-DAT tokens", self.nodes[0].setgov, { - "ATTRIBUTES": {'v0/consortium/0/mint_limit': '10'}}) - assert_raises_rpc_error(-32600, "Cannot set consortium on DFI, loan tokens and non-DAT tokens", self.nodes[0].setgov, { - "ATTRIBUTES": {'v0/consortium/0/mint_limit_daily': '10'}}) - assert_raises_rpc_error(-32600, "Cannot set consortium on DFI, loan tokens and non-DAT tokens", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/consortium/' + idTSLA + '/members' : {"01":{"name":"account2BTC", - "ownerAddress": account2, - "backingId":"ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf", - "mintLimitDaily":1.00000000, - "mintLimit":1.00000000}}}}) - assert_raises_rpc_error(-32600, "Cannot set consortium on DFI, loan tokens and non-DAT tokens", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/consortium/0/members' : {"01":{"name":"account2BTC", - "ownerAddress": account2, - "backingId":"ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf", - "mintLimitDaily":1.00000000, - "mintLimit":1.00000000}}}}) + assert_raises_rpc_error(-32600, "Cannot set consortium on DFI, loan tokens and non-DAT tokens", + self.nodes[0].setgov, { + "ATTRIBUTES": {'v0/consortium/' + idTSLA + '/mint_limit': '10'}}) + assert_raises_rpc_error(-32600, "Cannot set consortium on DFI, loan tokens and non-DAT tokens", + self.nodes[0].setgov, { + "ATTRIBUTES": {'v0/consortium/' + idTSLA + '/mint_limit_daily': '10'}}) + assert_raises_rpc_error(-32600, "Cannot set consortium on DFI, loan tokens and non-DAT tokens", + self.nodes[0].setgov, { + "ATTRIBUTES": {'v0/consortium/0/mint_limit': '10'}}) + assert_raises_rpc_error(-32600, "Cannot set consortium on DFI, loan tokens and non-DAT tokens", + self.nodes[0].setgov, { + "ATTRIBUTES": {'v0/consortium/0/mint_limit_daily': '10'}}) + assert_raises_rpc_error(-32600, "Cannot set consortium on DFI, loan tokens and non-DAT tokens", + self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/consortium/' + idTSLA + '/members': {"01": {"name": "account2BTC", + "ownerAddress": account2, + "backingId": "ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf", + "mintLimitDaily": 1.00000000, + "mintLimit": 1.00000000}}}}) + assert_raises_rpc_error(-32600, "Cannot set consortium on DFI, loan tokens and non-DAT tokens", + self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/consortium/0/members': {"01": {"name": "account2BTC", + "ownerAddress": account2, + "backingId": "ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf", + "mintLimitDaily": 1.00000000, + "mintLimit": 1.00000000}}}}) # Test setting before fork - assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set before GrandCentralEpilogueHeight", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/feature/mint-tokens-to-address':'true'}}) + assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set before GrandCentralEpilogueHeight", + self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/feature/mint-tokens-to-address': 'true'}}) # Move to fork self.nodes[0].generate(350 - self.nodes[0].getblockcount()) # Try and mint to an address before feature enabled newAddress = self.nodes[0].getnewaddress("", "bech32") - assert_raises_rpc_error(-32600, "Mint tokens to address is not enabled", self.nodes[0].minttokens, {"amounts": ["2@" + symbolBTC], "to": newAddress}) + assert_raises_rpc_error(-32600, "Mint tokens to address is not enabled", self.nodes[0].minttokens, + {"amounts": ["2@" + symbolBTC], "to": newAddress}) # Enable mint tokens to an address - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/feature/mint-tokens-to-address':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/feature/mint-tokens-to-address': 'true'}}) self.nodes[0].generate(1) # Mint tokens to an address @@ -618,7 +715,8 @@ def run_test(self): newAddress = self.nodes[0].getnewaddress("", "legacy") self.nodes[0].minttokens({"amounts": ["2@" + symbolBTC, "2@" + symbolDOGE, '2@' + symbolLTC], "to": newAddress}) self.nodes[0].generate(1) - assert_equal(self.nodes[0].getaccount(newAddress), ['2.00000000@' + symbolBTC, '2.00000000@' + symbolDOGE, '2.00000000@' + symbolLTC]) + assert_equal(self.nodes[0].getaccount(newAddress), + ['2.00000000@' + symbolBTC, '2.00000000@' + symbolDOGE, '2.00000000@' + symbolLTC]) assert_raises_rpc_error(-5, "recipient (NOTANADDRESS) does not refer to any valid address", self.nodes[0].minttokens, {"amounts": ["2@" + symbolBTC], "to": "NOTANADDRESS"}) @@ -633,10 +731,14 @@ def run_test(self): self.nodes[0].generate(1) idnotDAT = list(self.nodes[0].gettoken(token).keys())[0] - assert_raises_rpc_error(-32600, "Cannot set consortium on DFI, loan tokens and non-DAT tokens", self.nodes[0].setgov, { - "ATTRIBUTES": {'v0/consortium/' + idnotDAT + '/mint_limit': '10'}}) - assert_raises_rpc_error(-32600, "Cannot set consortium on DFI, loan tokens and non-DAT tokens", self.nodes[0].setgovheight, { - "ATTRIBUTES": {'v0/consortium/' + idnotDAT + '/mint_limit': '10'}}, self.nodes[0].getblockcount() + 10) + assert_raises_rpc_error(-32600, "Cannot set consortium on DFI, loan tokens and non-DAT tokens", + self.nodes[0].setgov, { + "ATTRIBUTES": {'v0/consortium/' + idnotDAT + '/mint_limit': '10'}}) + assert_raises_rpc_error(-32600, "Cannot set consortium on DFI, loan tokens and non-DAT tokens", + self.nodes[0].setgovheight, { + "ATTRIBUTES": {'v0/consortium/' + idnotDAT + '/mint_limit': '10'}}, + self.nodes[0].getblockcount() + 10) + if __name__ == '__main__': ConsortiumTest().main() diff --git a/test/functional/feature_csv_activation.py b/test/functional/feature_csv_activation.py index 4d0c11cd7d..270f229179 100755 --- a/test/functional/feature_csv_activation.py +++ b/test/functional/feature_csv_activation.py @@ -63,6 +63,7 @@ SEQ_TYPE_FLAG = 1 << 22 SEQ_RANDOM_LOW_BIT = 1 << 18 + def relative_locktime(sdf, srhb, stf, srlb): """Returns a locktime with certain bits set.""" @@ -77,9 +78,11 @@ def relative_locktime(sdf, srhb, stf, srlb): locktime |= SEQ_RANDOM_LOW_BIT return locktime + def all_rlt_txs(txs): return [tx['tx'] for tx in txs] + def sign_transaction(node, unsignedtx): rawtx = ToHex(unsignedtx) signresult = node.signrawtransactionwithwallet(rawtx) @@ -88,6 +91,7 @@ def sign_transaction(node, unsignedtx): tx.deserialize(f) return tx + def create_bip112special(node, input, txversion, address): tx = create_transaction(node, input, address, amount=Decimal("49.98")) tx.nVersion = txversion @@ -95,8 +99,13 @@ def create_bip112special(node, input, txversion, address): signtx.vin[0].scriptSig = CScript([-1, OP_CHECKSEQUENCEVERIFY, OP_DROP] + list(CScript(signtx.vin[0].scriptSig))) return signtx + def send_generic_input_tx(node, coinbases, address): - return node.sendrawtransaction(ToHex(sign_transaction(node, create_transaction(node, node.getblock(coinbases.pop())['tx'][0], address, amount=Decimal("49.99"))))) + return node.sendrawtransaction(ToHex(sign_transaction(node, create_transaction(node, + node.getblock(coinbases.pop())['tx'][ + 0], address, + amount=Decimal("49.99"))))) + def create_bip68txs(node, bip68inputs, txversion, address, locktime_delta=0): """Returns a list of bip68 transactions with different bits set.""" @@ -113,6 +122,7 @@ def create_bip68txs(node, bip68inputs, txversion, address, locktime_delta=0): return txs + def create_bip112txs(node, bip112inputs, varyOP_CSV, txversion, address, locktime_delta=0): """Returns a list of bip68 transactions with different bits set.""" txs = [] @@ -127,13 +137,16 @@ def create_bip112txs(node, bip112inputs, varyOP_CSV, txversion, address, locktim tx.nVersion = txversion signtx = sign_transaction(node, tx) if (varyOP_CSV): - signtx.vin[0].scriptSig = CScript([locktime, OP_CHECKSEQUENCEVERIFY, OP_DROP] + list(CScript(signtx.vin[0].scriptSig))) + signtx.vin[0].scriptSig = CScript( + [locktime, OP_CHECKSEQUENCEVERIFY, OP_DROP] + list(CScript(signtx.vin[0].scriptSig))) else: - signtx.vin[0].scriptSig = CScript([BASE_RELATIVE_LOCKTIME, OP_CHECKSEQUENCEVERIFY, OP_DROP] + list(CScript(signtx.vin[0].scriptSig))) + signtx.vin[0].scriptSig = CScript( + [BASE_RELATIVE_LOCKTIME, OP_CHECKSEQUENCEVERIFY, OP_DROP] + list(CScript(signtx.vin[0].scriptSig))) tx.rehash() txs.append({'tx': signtx, 'sdf': sdf, 'stf': stf}) return txs + class BIP68_112_113Test(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 @@ -172,11 +185,13 @@ def run_test(self): self.nodes[0].add_p2p_connection(P2PDataStore()) self.log.info("Generate blocks in the past for coinbase outputs.") - long_past_time = int(time.time()) - 600 * 1000 # enough to build up to 1000 blocks 10 minutes apart without worrying about getting into the future + long_past_time = int( + time.time()) - 600 * 1000 # enough to build up to 1000 blocks 10 minutes apart without worrying about getting into the future # self.nodes[0].setmocktime(long_past_time - 100) # enough so that the generated blocks will still all be before long_past_time TestNode.Mocktime = long_past_time - 100 self.coinbase_blocks = self.nodes[0].generate(1 + 16 + 2 * 32 + 1) # 82 blocks generated for inputs - self.nodes[0].setmocktime(0) # set time back to present so yielded blocks aren't in the future as we advance last_block_time + self.nodes[0].setmocktime( + 0) # set time back to present so yielded blocks aren't in the future as we advance last_block_time self.tipheight = 82 # height of the next block to build self.last_block_time = long_past_time self.tip = int(self.nodes[0].getbestblockhash(), 16) @@ -231,7 +246,9 @@ def run_test(self): self.send_blocks(test_blocks) assert_equal(self.tipheight, CSV_ACTIVATION_HEIGHT - 2) - self.log.info("Height = {}, CSV not yet active (will activate for block {}, not {})".format(self.tipheight, CSV_ACTIVATION_HEIGHT, CSV_ACTIVATION_HEIGHT - 1)) + self.log.info("Height = {}, CSV not yet active (will activate for block {}, not {})".format(self.tipheight, + CSV_ACTIVATION_HEIGHT, + CSV_ACTIVATION_HEIGHT - 1)) # Test both version 1 and version 2 transactions for all tests # BIP113 test transaction will be modified before each use to put in appropriate block time @@ -251,14 +268,18 @@ def run_test(self): bip112txs_vary_nSequence_v1 = create_bip112txs(self.nodes[0], bip112basicinputs[0], False, 1, self.nodeaddress) bip112txs_vary_nSequence_v2 = create_bip112txs(self.nodes[0], bip112basicinputs[0], False, 2, self.nodeaddress) # 16 relative sequence locktimes of 9 against 10 OP_CSV OP_DROP inputs - bip112txs_vary_nSequence_9_v1 = create_bip112txs(self.nodes[0], bip112basicinputs[1], False, 1, self.nodeaddress, -1) - bip112txs_vary_nSequence_9_v2 = create_bip112txs(self.nodes[0], bip112basicinputs[1], False, 2, self.nodeaddress, -1) + bip112txs_vary_nSequence_9_v1 = create_bip112txs(self.nodes[0], bip112basicinputs[1], False, 1, + self.nodeaddress, -1) + bip112txs_vary_nSequence_9_v2 = create_bip112txs(self.nodes[0], bip112basicinputs[1], False, 2, + self.nodeaddress, -1) # sequence lock time of 10 against 16 (relative_lock_time) OP_CSV OP_DROP inputs bip112txs_vary_OP_CSV_v1 = create_bip112txs(self.nodes[0], bip112diverseinputs[0], True, 1, self.nodeaddress) bip112txs_vary_OP_CSV_v2 = create_bip112txs(self.nodes[0], bip112diverseinputs[0], True, 2, self.nodeaddress) # sequence lock time of 9 against 16 (relative_lock_time) OP_CSV OP_DROP inputs - bip112txs_vary_OP_CSV_9_v1 = create_bip112txs(self.nodes[0], bip112diverseinputs[1], True, 1, self.nodeaddress, -1) - bip112txs_vary_OP_CSV_9_v2 = create_bip112txs(self.nodes[0], bip112diverseinputs[1], True, 2, self.nodeaddress, -1) + bip112txs_vary_OP_CSV_9_v1 = create_bip112txs(self.nodes[0], bip112diverseinputs[1], True, 1, self.nodeaddress, + -1) + bip112txs_vary_OP_CSV_9_v2 = create_bip112txs(self.nodes[0], bip112diverseinputs[1], True, 2, self.nodeaddress, + -1) # -1 OP_CSV OP_DROP input bip112tx_special_v1 = create_bip112special(self.nodes[0], bip112specialinput, 1, self.nodeaddress) bip112tx_special_v2 = create_bip112special(self.nodes[0], bip112specialinput, 2, self.nodeaddress) @@ -444,5 +465,6 @@ def run_test(self): # TODO: Test empty stack fails + if __name__ == '__main__': BIP68_112_113Test().main() diff --git a/test/functional/feature_custom_poolreward.py b/test/functional/feature_custom_poolreward.py index 5aa5fe696b..d563db2a80 100755 --- a/test/functional/feature_custom_poolreward.py +++ b/test/functional/feature_custom_poolreward.py @@ -10,12 +10,15 @@ from test_framework.util import assert_equal from test_framework.authproxy import JSONRPCException + class TokensCustomPoolReward(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 self.setup_clean_chain = True - self.extra_args = [['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=50', '-clarkequayheight=50'], - ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=50', '-clarkequayheight=50']] + self.extra_args = [['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=50', + '-clarkequayheight=50'], + ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=50', + '-clarkequayheight=50']] def run_test(self): self.nodes[0].generate(102) @@ -66,33 +69,33 @@ def run_test(self): # Fail on zero amount token reward try: self.nodes[0].createpoolpair({ - "tokenA": "GOLD#" + token_a, - "tokenB": "SILVER#" + token_b, - "commission": 0.001, - "status": True, - "ownerAddress": pool_collateral, - "pairSymbol": "SILVGOLD", - "customRewards": ["0@" + token_a] - }) + "tokenA": "GOLD#" + token_a, + "tokenB": "SILVER#" + token_b, + "commission": 0.001, + "status": True, + "ownerAddress": pool_collateral, + "pairSymbol": "SILVGOLD", + "customRewards": ["0@" + token_a] + }) except JSONRPCException as e: errorString = e.error['message'] - assert("Amount out of range" in errorString) + assert ("Amount out of range" in errorString) errorString = "" # Fail on token that does not exist try: self.nodes[0].createpoolpair({ - "tokenA": "GOLD#" + token_a, - "tokenB": "SILVER#" + token_b, - "commission": 0.001, - "status": True, - "ownerAddress": pool_collateral, - "pairSymbol": "SILVGOLD", - "customRewards": ["1@100"] - }) + "tokenA": "GOLD#" + token_a, + "tokenB": "SILVER#" + token_b, + "commission": 0.001, + "status": True, + "ownerAddress": pool_collateral, + "pairSymbol": "SILVGOLD", + "customRewards": ["1@100"] + }) except JSONRPCException as e: errorString = e.error['message'] - assert("reward token 100 does not exist" in errorString) + assert ("reward token 100 does not exist" in errorString) errorString = "" # Create pool with token rewards @@ -113,7 +116,7 @@ def run_test(self): assert_equal(result['results']['customRewards'], ["1.00000000@" + token_a, "1.00000000@" + token_b]) # custom rewards should not show up yet without balance - assert('customRewards' not in self.nodes[0].getpoolpair(1)['1']) + assert ('customRewards' not in self.nodes[0].getpoolpair(1)['1']) # Create and fund liquidity provider provider = self.nodes[1].getnewaddress("", "legacy") @@ -147,7 +150,8 @@ def run_test(self): self.sync_blocks() # token b reward should be added to provider but token a same as before - assert_equal(self.nodes[1].getaccount(provider), ['0.99999000@SILVGOLD', '0.99999000@GOLD#128', '0.99999000@SILVER#129']) + assert_equal(self.nodes[1].getaccount(provider), + ['0.99999000@SILVGOLD', '0.99999000@GOLD#128', '0.99999000@SILVER#129']) # Make sure amount reduced from token a assert_equal(self.nodes[1].getaccount(pool_collateral), ['0.00001000@GOLD#128', '0.00001000@SILVER#129']) @@ -155,7 +159,8 @@ def run_test(self): self.sync_blocks() # token a and b amount should be static as not enough funds to pay - assert_equal(self.nodes[1].getaccount(provider), ['0.99999000@SILVGOLD', '0.99999000@GOLD#128', '0.99999000@SILVER#129']) + assert_equal(self.nodes[1].getaccount(provider), + ['0.99999000@SILVGOLD', '0.99999000@GOLD#128', '0.99999000@SILVER#129']) # Fund addresses to avoid auto auth to send raw via node 1 easily self.nodes[0].sendtoaddress(collateral_a, 1) @@ -185,13 +190,14 @@ def run_test(self): self.sync_blocks() # token a and b rewards should be added to provider - assert_equal(self.nodes[1].getaccount(provider), ['0.99999000@SILVGOLD', '10.99989000@GOLD#128', '10.99989000@SILVER#129']) + assert_equal(self.nodes[1].getaccount(provider), + ['0.99999000@SILVGOLD', '10.99989000@GOLD#128', '10.99989000@SILVER#129']) # Make sure amount reduced from token a assert_equal(self.nodes[1].getaccount(pool_collateral), ['0.00011000@GOLD#128', '0.00011000@SILVER#129']) # custom rewards should not show up yet without balance - assert('customRewards' not in self.nodes[0].getpoolpair(1)['1']) + assert ('customRewards' not in self.nodes[0].getpoolpair(1)['1']) # Top up of token a to test poolpair output self.nodes[0].accounttoaccount(collateral_a, {pool_collateral: "10@" + token_a}) @@ -206,7 +212,7 @@ def run_test(self): self.sync_blocks() # custom rewards should not show up yet without balance - assert('customRewards' not in self.nodes[0].getpoolpair(1)['1']) + assert ('customRewards' not in self.nodes[0].getpoolpair(1)['1']) # Top up of token b to test poolpair output self.nodes[0].accounttoaccount(collateral_b, {pool_collateral: "10@" + token_b}) @@ -221,7 +227,7 @@ def run_test(self): self.sync_blocks() # custom rewards should not show up yet without balance - assert('customRewards' not in self.nodes[0].getpoolpair(1)['1']) + assert ('customRewards' not in self.nodes[0].getpoolpair(1)['1']) # Create new token for reward num_tokens = len(self.nodes[0].listtokens()) @@ -258,7 +264,7 @@ def run_test(self): self.nodes[0].updatepoolpair({"pool": "1", "customRewards": ["0@" + token_c]}) except JSONRPCException as e: errorString = e.error['message'] - assert("Amount out of range" in errorString) + assert ("Amount out of range" in errorString) errorString = "" # Update poolpair with invalid reward token @@ -266,7 +272,7 @@ def run_test(self): self.nodes[0].updatepoolpair({"pool": "1", "customRewards": ["1@100"]}) except JSONRPCException as e: errorString = e.error['message'] - assert("reward token 100 does not exist" in errorString) + assert ("reward token 100 does not exist" in errorString) errorString = "" # Replace tokens with token c @@ -280,8 +286,10 @@ def run_test(self): # Check for new block reward and payout assert_equal(self.nodes[1].getpoolpair(1)['1']['customRewards'], ['1.00000000@130']) - assert_equal(self.nodes[1].getaccount(provider), ['0.99999000@SILVGOLD', '20.99979000@GOLD#128', '20.99979000@SILVER#129', '0.99999000@BRONZE#130']) - assert_equal(self.nodes[1].getaccount(pool_collateral), ['0.00021000@GOLD#128', '0.00021000@SILVER#129', '9.00001000@BRONZE#130']) + assert_equal(self.nodes[1].getaccount(provider), + ['0.99999000@SILVGOLD', '20.99979000@GOLD#128', '20.99979000@SILVER#129', '0.99999000@BRONZE#130']) + assert_equal(self.nodes[1].getaccount(pool_collateral), + ['0.00021000@GOLD#128', '0.00021000@SILVER#129', '9.00001000@BRONZE#130']) # Provide pool reward for token a, should not show as it wasd removed self.nodes[0].accounttoaccount(collateral_a, {pool_collateral: "10@" + token_a}) @@ -290,11 +298,14 @@ def run_test(self): # Check for new block reward and payout assert_equal(self.nodes[1].getpoolpair(1)['1']['customRewards'], ['1.00000000@130']) - assert_equal(self.nodes[1].getaccount(provider), ['0.99999000@SILVGOLD', '20.99979000@GOLD#128', '20.99979000@SILVER#129', '1.99998000@BRONZE#130']) - assert_equal(self.nodes[1].getaccount(pool_collateral), ['10.00021000@GOLD#128', '0.00021000@SILVER#129', '8.00002000@BRONZE#130']) + assert_equal(self.nodes[1].getaccount(provider), + ['0.99999000@SILVGOLD', '20.99979000@GOLD#128', '20.99979000@SILVER#129', '1.99998000@BRONZE#130']) + assert_equal(self.nodes[1].getaccount(pool_collateral), + ['10.00021000@GOLD#128', '0.00021000@SILVER#129', '8.00002000@BRONZE#130']) # Add back token a - updatepoolpair_tx = self.nodes[0].updatepoolpair({"pool": "1", "customRewards": ["1@" + token_a, "1@" + token_c]}) + updatepoolpair_tx = self.nodes[0].updatepoolpair( + {"pool": "1", "customRewards": ["1@" + token_a, "1@" + token_c]}) self.nodes[0].generate(1) self.sync_blocks() @@ -304,8 +315,10 @@ def run_test(self): # Check for new block reward and payout for token a and c assert_equal(self.nodes[1].getpoolpair(1)['1']['customRewards'], ['1.00000000@128', '1.00000000@130']) - assert_equal(self.nodes[1].getaccount(provider), ['0.99999000@SILVGOLD', '21.99978000@GOLD#128', '20.99979000@SILVER#129', '2.99997000@BRONZE#130']) - assert_equal(self.nodes[1].getaccount(pool_collateral), ['9.00022000@GOLD#128', '0.00021000@SILVER#129', '7.00003000@BRONZE#130']) + assert_equal(self.nodes[1].getaccount(provider), + ['0.99999000@SILVGOLD', '21.99978000@GOLD#128', '20.99979000@SILVER#129', '2.99997000@BRONZE#130']) + assert_equal(self.nodes[1].getaccount(pool_collateral), + ['9.00022000@GOLD#128', '0.00021000@SILVER#129', '7.00003000@BRONZE#130']) # Provide pool reward for token b, should not show as it was removed self.nodes[0].accounttoaccount(collateral_b, {pool_collateral: "10@" + token_b}) @@ -314,22 +327,29 @@ def run_test(self): # Check for new block reward and payout assert_equal(self.nodes[1].getpoolpair(1)['1']['customRewards'], ['1.00000000@128', '1.00000000@130']) - assert_equal(self.nodes[1].getaccount(provider), ['0.99999000@SILVGOLD', '22.99977000@GOLD#128', '20.99979000@SILVER#129', '3.99996000@BRONZE#130']) - assert_equal(self.nodes[1].getaccount(pool_collateral), ['8.00023000@GOLD#128', '10.00021000@SILVER#129', '6.00004000@BRONZE#130']) + assert_equal(self.nodes[1].getaccount(provider), + ['0.99999000@SILVGOLD', '22.99977000@GOLD#128', '20.99979000@SILVER#129', '3.99996000@BRONZE#130']) + assert_equal(self.nodes[1].getaccount(pool_collateral), + ['8.00023000@GOLD#128', '10.00021000@SILVER#129', '6.00004000@BRONZE#130']) # Add back token b - updatepoolpair_tx = self.nodes[0].updatepoolpair({"pool": "1", "customRewards": ["1@" + token_a, "1@" + token_b, "1@" + token_c]}) + updatepoolpair_tx = self.nodes[0].updatepoolpair( + {"pool": "1", "customRewards": ["1@" + token_a, "1@" + token_b, "1@" + token_c]}) self.nodes[0].generate(1) self.sync_blocks() # Check that customReards shows up in getcustomtx result = self.nodes[0].getcustomtx(updatepoolpair_tx) - assert_equal(result['results']['customRewards'], ["1.00000000@" + token_a, "1.00000000@" + token_b, "1.00000000@" + token_c]) + assert_equal(result['results']['customRewards'], + ["1.00000000@" + token_a, "1.00000000@" + token_b, "1.00000000@" + token_c]) # Check for new block reward and payout for token a, b and c - assert_equal(self.nodes[1].getpoolpair(1)['1']['customRewards'], ['1.00000000@128', '1.00000000@129', '1.00000000@130']) - assert_equal(self.nodes[1].getaccount(provider), ['0.99999000@SILVGOLD', '23.99976000@GOLD#128', '21.99978000@SILVER#129', '4.99995000@BRONZE#130']) - assert_equal(self.nodes[1].getaccount(pool_collateral), ['7.00024000@GOLD#128', '9.00022000@SILVER#129', '5.00005000@BRONZE#130']) + assert_equal(self.nodes[1].getpoolpair(1)['1']['customRewards'], + ['1.00000000@128', '1.00000000@129', '1.00000000@130']) + assert_equal(self.nodes[1].getaccount(provider), + ['0.99999000@SILVGOLD', '23.99976000@GOLD#128', '21.99978000@SILVER#129', '4.99995000@BRONZE#130']) + assert_equal(self.nodes[1].getaccount(pool_collateral), + ['7.00024000@GOLD#128', '9.00022000@SILVER#129', '5.00005000@BRONZE#130']) # Do nothing updatepoolpair_tx = self.nodes[0].updatepoolpair({"pool": "1"}) @@ -338,12 +358,15 @@ def run_test(self): # Check that customReards shows up in getcustomtx result = self.nodes[0].getcustomtx(updatepoolpair_tx) - assert('customRewards' not in result['results']) + assert ('customRewards' not in result['results']) # Check for new block reward and payout for token a, b and c - assert_equal(self.nodes[1].getpoolpair(1)['1']['customRewards'], ['1.00000000@128', '1.00000000@129', '1.00000000@130']) - assert_equal(self.nodes[1].getaccount(provider), ['0.99999000@SILVGOLD', '24.99975000@GOLD#128', '22.99977000@SILVER#129', '5.99994000@BRONZE#130']) - assert_equal(self.nodes[1].getaccount(pool_collateral), ['6.00025000@GOLD#128', '8.00023000@SILVER#129', '4.00006000@BRONZE#130']) + assert_equal(self.nodes[1].getpoolpair(1)['1']['customRewards'], + ['1.00000000@128', '1.00000000@129', '1.00000000@130']) + assert_equal(self.nodes[1].getaccount(provider), + ['0.99999000@SILVGOLD', '24.99975000@GOLD#128', '22.99977000@SILVER#129', '5.99994000@BRONZE#130']) + assert_equal(self.nodes[1].getaccount(pool_collateral), + ['6.00025000@GOLD#128', '8.00023000@SILVER#129', '4.00006000@BRONZE#130']) # Wipe all rewards updatepoolpair_tx = self.nodes[0].updatepoolpair({"pool": "1", "customRewards": []}) @@ -353,8 +376,11 @@ def run_test(self): # Check TX shows rewards present and empty and balances should be unchanged result = self.nodes[0].getcustomtx(updatepoolpair_tx) assert_equal(result['results']['customRewards'], []) - assert_equal(self.nodes[1].getaccount(provider), ['0.99999000@SILVGOLD', '24.99975000@GOLD#128', '22.99977000@SILVER#129', '5.99994000@BRONZE#130']) - assert_equal(self.nodes[1].getaccount(pool_collateral), ['6.00025000@GOLD#128', '8.00023000@SILVER#129', '4.00006000@BRONZE#130']) + assert_equal(self.nodes[1].getaccount(provider), + ['0.99999000@SILVGOLD', '24.99975000@GOLD#128', '22.99977000@SILVER#129', '5.99994000@BRONZE#130']) + assert_equal(self.nodes[1].getaccount(pool_collateral), + ['6.00025000@GOLD#128', '8.00023000@SILVER#129', '4.00006000@BRONZE#130']) + if __name__ == '__main__': TokensCustomPoolReward().main() diff --git a/test/functional/feature_dbcrash.py b/test/functional/feature_dbcrash.py index 3a4051cb40..ab3373dd3c 100755 --- a/test/functional/feature_dbcrash.py +++ b/test/functional/feature_dbcrash.py @@ -91,7 +91,7 @@ def restart_node(self, node_index, expected_tip): self.nodes[node_index].waitforblock(expected_tip) utxo_hash = self.nodes[node_index].gettxoutsetinfo()['hash_serialized_2'] return utxo_hash - except: + except Exception: # An exception here should mean the node is about to crash. # If defid exits, then try again. wait_for_node_exit() # should raise an exception if defid doesn't exit. @@ -215,7 +215,7 @@ def generate_small_transactions(self, node, count, utxo_list): def run_test(self): # Track test coverage statistics self.restart_counts = [0, 0, 0] # Track the restarts for nodes 0-2 - self.crashed_on_restart = 0 # Track count of crashes during recovery + self.crashed_on_restart = 0 # Track count of crashes during recovery # Start by creating a lot of utxos on node3 initial_height = self.nodes[3].getblockcount() @@ -280,5 +280,6 @@ def run_test(self): if self.restart_counts[i] == 0: self.log.warning("Node %d never crashed during utxo flush!", i) + if __name__ == "__main__": ChainstateWriteCrashTest().main() diff --git a/test/functional/feature_dersig.py b/test/functional/feature_dersig.py index 4903bdcec2..fcb2f8d08f 100755 --- a/test/functional/feature_dersig.py +++ b/test/functional/feature_dersig.py @@ -23,6 +23,7 @@ REJECT_INVALID = 16 REJECT_NONSTANDARD = 64 + # A canonical signature consists of: # <30> <02> <02> def unDERify(tx): @@ -40,11 +41,11 @@ def unDERify(tx): tx.vin[0].scriptSig = CScript(newscript) - class BIP66Test(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 - self.extra_args = [['-whitelist=127.0.0.1', '-par=1', '-enablebip61']] # Use only one script thread to get the exact reject reason for testing + self.extra_args = [['-whitelist=127.0.0.1', '-par=1', + '-enablebip61']] # Use only one script thread to get the exact reject reason for testing self.setup_clean_chain = True self.rpc_timeout = 120 @@ -61,7 +62,7 @@ def run_test(self): self.log.info("Test that a transaction with non-DER signature can still appear in a block") spendtx = create_transaction(self.nodes[0], self.coinbase_txids[0], - self.nodeaddress, amount=1.0) + self.nodeaddress, amount=1.0) unDERify(spendtx) spendtx.rehash() @@ -94,14 +95,15 @@ def run_test(self): block.nVersion = 3 spendtx = create_transaction(self.nodes[0], self.coinbase_txids[1], - self.nodeaddress, amount=1.0) + self.nodeaddress, amount=1.0) unDERify(spendtx) spendtx.rehash() # First we show that this tx is valid except for DERSIG by getting it # rejected from the mempool for exactly that reason. assert_equal( - [{'txid': spendtx.hash, 'allowed': False, 'reject-reason': '64: non-mandatory-script-verify-flag (Non-canonical DER signature)'}], + [{'txid': spendtx.hash, 'allowed': False, + 'reject-reason': '64: non-mandatory-script-verify-flag (Non-canonical DER signature)'}], self.nodes[0].testmempoolaccept(rawtxs=[spendtx.serialize().hex()], maxfeerate=0) ) @@ -111,7 +113,9 @@ def run_test(self): block.rehash() block.solve() - with self.nodes[0].assert_debug_log(expected_msgs=['CheckInputs on {} failed with non-mandatory-script-verify-flag (Non-canonical DER signature)'.format(block.vtx[-1].hash)]): + with self.nodes[0].assert_debug_log(expected_msgs=[ + 'CheckInputs on {} failed with non-mandatory-script-verify-flag (Non-canonical DER signature)'.format( + block.vtx[-1].hash)]): self.nodes[0].p2p.send_and_ping(msg_block(block)) assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip) self.nodes[0].p2p.sync_with_ping() diff --git a/test/functional/feature_dfip8_communitybalances.py b/test/functional/feature_dfip8_communitybalances.py index 64532ebe6c..9e94cf3b7f 100755 --- a/test/functional/feature_dfip8_communitybalances.py +++ b/test/functional/feature_dfip8_communitybalances.py @@ -10,6 +10,7 @@ from test_framework.util import assert_equal from decimal import Decimal + class Dfip8Test(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 @@ -79,7 +80,7 @@ def run_test(self): assert_equal(getblock['nonutxo'][0]['AnchorReward'], Decimal('0.07966488')) assert_equal(getblock['nonutxo'][0]['Burnt'], Decimal('245.92550726')) - #Go forward again to first reduction + # Go forward again to first reduction self.nodes[0].generate(1) result = self.nodes[0].listcommunitybalances() @@ -105,5 +106,6 @@ def run_test(self): assert_equal(getblock['nonutxo'][0]['AnchorReward'], Decimal('0.06853592')) assert_equal(getblock['nonutxo'][0]['Burnt'], Decimal('211.57039811')) + if __name__ == '__main__': Dfip8Test().main() diff --git a/test/functional/feature_dip1.py b/test/functional/feature_dip1.py index df211c41a3..35dbb60feb 100755 --- a/test/functional/feature_dip1.py +++ b/test/functional/feature_dip1.py @@ -16,7 +16,8 @@ from decimal import Decimal import time -class Dip1Test (DefiTestFramework): + +class Dip1Test(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 # node0: main @@ -37,8 +38,8 @@ def run_test(self): assert_equal(self.nodes[0].getbalances()['mine']['immature'], 50) assert_equal(self.nodes[0].listcommunitybalances()['AnchorReward'], 0) assert_equal(self.nodes[0].listcommunitybalances()['Burnt'], 0) - assert_equal(self.nodes[0].getblockchaininfo()['softforks']['amk']['active'], True) # not active IRL, so getblockchaininfo works like "height+1" - + assert_equal(self.nodes[0].getblockchaininfo()['softforks']['amk']['active'], + True) # not active IRL, so getblockchaininfo works like "height+1" # BLOCK#2 - AMK activated self.nodes[0].generate(1) @@ -50,7 +51,8 @@ def run_test(self): assert_equal(self.nodes[0].getbalances()['mine']['immature'], 88) # import foundation address, so we can check foundation share (due to listunspent doesn't show immatured coinbases) - self.nodes[0].importprivkey('cMv1JaaZ9Mbb3M3oNmcFvko8p7EcHJ8XD7RCQjzNaMs7BWRVZTyR') # foundationAddress (2NCWAKfEehP3qibkLKYQjXaWMK23k4EDMVS) privkey + self.nodes[0].importprivkey( + 'cMv1JaaZ9Mbb3M3oNmcFvko8p7EcHJ8XD7RCQjzNaMs7BWRVZTyR') # foundationAddress (2NCWAKfEehP3qibkLKYQjXaWMK23k4EDMVS) privkey assert_equal(self.nodes[0].getbalances()['mine']['immature'], Decimal('89.9')) assert_equal(self.nodes[0].listcommunitybalances()['AnchorReward'], Decimal('0.1')) @@ -62,12 +64,11 @@ def run_test(self): assert_equal(self.nodes[1].listcommunitybalances()['AnchorReward'], 0) assert_equal(self.nodes[1].listcommunitybalances()['Burnt'], 0) - # BLOCK#3 by node1 (rejected by node0) self.nodes[1].generate(1) - time.sleep(2) # can't sync here + time.sleep(2) # can't sync here assert_equal(self.nodes[1].getblockcount(), 3) - assert_equal(self.nodes[0].getblockcount(), 2) # block rejected by "new" node! + assert_equal(self.nodes[0].getblockcount(), 2) # block rejected by "new" node! # restart node1 with activated fork self.stop_node(1) @@ -94,4 +95,4 @@ def run_test(self): if __name__ == '__main__': - Dip1Test ().main () + Dip1Test().main() diff --git a/test/functional/feature_dusd_loans.py b/test/functional/feature_dusd_loans.py index 65c47cfd0d..ee5dfe6161 100755 --- a/test/functional/feature_dusd_loans.py +++ b/test/functional/feature_dusd_loans.py @@ -11,19 +11,23 @@ import time from decimal import Decimal + def get_decimal_amount(amount): account_tmp = amount.split('@')[0] return Decimal(account_tmp) + def token_index_in_account(accounts, symbol): for id in range(len(accounts)): if symbol in accounts[id]: return id return -1 + ERR_STRING_MIN_COLLATERAL_DFI_PCT = "At least 50% of the minimum required collateral must be in DFI" ERR_STRING_MIN_COLLATERAL_DFI_DUSD_PCT = "At least 50% of the minimum required collateral must be in DFI or DUSD" + class DUSDLoanTests(DefiTestFramework): def set_test_params(self): @@ -35,17 +39,17 @@ def set_test_params(self): self.fortcanningepilogueheight = 4000 self.extra_args = [ ['-txnotokens=0', - '-amkheight=1', - '-bayfrontheight=1', - '-eunosheight=1', - '-fortcanningheight=1', - '-fortcanningmuseumheight=1', - '-fortcanningparkheight=1', - f'-fortcanninghillheight={self.fortcanninghillheight}', - f'-fortcanningroadheight={self.fortcanningroadheight}', - f'-fortcanninggreatworldheight={self.fortcanninggreatworldheight}', - f'-fortcanningepilogueheight={self.fortcanningepilogueheight}', - '-jellyfish_regtest=1', '-txindex=1', '-simulatemainnet=1'] + '-amkheight=1', + '-bayfrontheight=1', + '-eunosheight=1', + '-fortcanningheight=1', + '-fortcanningmuseumheight=1', + '-fortcanningparkheight=1', + f'-fortcanninghillheight={self.fortcanninghillheight}', + f'-fortcanningroadheight={self.fortcanningroadheight}', + f'-fortcanninggreatworldheight={self.fortcanninggreatworldheight}', + f'-fortcanningepilogueheight={self.fortcanningepilogueheight}', + '-jellyfish_regtest=1', '-txindex=1', '-simulatemainnet=1'] ] def takeloan_withdraw(self, vaultId, amount, type='takeloan'): @@ -72,7 +76,7 @@ def takeloan_withdraw(self, vaultId, amount, type='takeloan'): # Utils - def new_vault(self, loan_scheme, amounts = None): + def new_vault(self, loan_scheme, amounts=None): if amounts is None: amounts = [] vaultId = self.nodes[0].createvault(self.account0, loan_scheme) @@ -112,7 +116,6 @@ def goto_fce_height(self): blockchainInfo = self.nodes[0].getblockchaininfo() assert_equal(blockchainInfo["softforks"]["fortcanningepilogue"]["active"], True) - def create_tokens(self): self.symbolDFI = "DFI" self.symboldUSD = "DUSD" @@ -210,7 +213,7 @@ def update_oracle_price(self, add_time=3000): {"currency": "USD", "tokenAmount": "1@BTC"}, {"currency": "USD", "tokenAmount": "10@DFI"}] - mock_time = int(time.time()+add_time) + mock_time = int(time.time() + add_time) self.nodes[0].setmocktime(mock_time) self.nodes[0].setoracledata(self.oracle_id1, mock_time, oracle_prices) self.nodes[0].generate(120) @@ -261,7 +264,7 @@ def setup(self): self.nodes[0].generate(10) self.setup_height = self.nodes[0].getblockcount() - def rollback_checks(self, vaults = None): + def rollback_checks(self, vaults=None): if vaults is None: vaults = [] for vault in vaults: @@ -269,7 +272,7 @@ def rollback_checks(self, vaults = None): self.nodes[0].getvault(vault) except JSONRPCException as e: errorString = e.error['message'] - assert(f"Vault <{vault}> not found" in errorString) + assert (f"Vault <{vault}> not found" in errorString) # TESTS def pre_FCH_DFI_minimum_check_withdraw(self): @@ -332,7 +335,7 @@ def post_FCR_DFI_minimum_check_withdraw(self): ERR_STRING_MIN_COLLATERAL_DFI_DUSD_PCT, self.takeloan_withdraw, vault_id, "0.50000000@DFI", 'withdraw') - vault_id_1 = self.new_vault('LOAN1', ["200.00000000@BTC","30.00000000@DUSD"]) + vault_id_1 = self.new_vault('LOAN1', ["200.00000000@BTC", "30.00000000@DUSD"]) self.takeloan_withdraw(vault_id_1, "1.00000000@TSLA", 'takeloan') self.takeloan_withdraw(vault_id_1, "20.00000000@DUSD", 'withdraw') assert_raises_rpc_error(-32600, @@ -445,7 +448,6 @@ def pre_FCR_DFI_minimum_check_takeloan(self): self.rollback_to(block_height) self.rollback_checks([vault_id, vault_id_1]) - def post_FCR_DFI_minimum_check_takeloan(self): block_height = self.nodes[0].getblockcount() @@ -508,8 +510,6 @@ def post_FCE_DFI_minimum_check_takeloan(self): self.rollback_to(block_height) self.rollback_checks([vault_id, vault_id_1]) - - def run_test(self): # Initial set up self.setup() @@ -535,5 +535,6 @@ def run_test(self): # File "/Users/diegodelcorral/workspace/fce-no-dusd-loop/test/functional/test_framework/test_framework.py", line 414, in _rollback_to # node.invalidateblock(blockhash) + if __name__ == '__main__': DUSDLoanTests().main() diff --git a/test/functional/feature_eunos_balances.py b/test/functional/feature_eunos_balances.py index 6432550820..85d5f7985a 100755 --- a/test/functional/feature_eunos_balances.py +++ b/test/functional/feature_eunos_balances.py @@ -11,6 +11,7 @@ from decimal import Decimal + class TransferBurnTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 @@ -18,7 +19,6 @@ def set_test_params(self): self.extra_args = [['-txnotokens=0', '-amkheight=1', '-eunosheight=200', '-dakotaheight=1']] def run_test(self): - # Burn address old_burn_address = "mfdefichainDSTBurnAddressXXXZcE1vs" burn_address = "mfburnZSAM7Gs1hpDeNaMotJXSGA7edosG" @@ -48,7 +48,8 @@ def run_test(self): # Check token burn fee result = self.nodes[0].listburnhistory() - assert_equal(result[0]['owner'], "6a1f446654785404474f4c440a7368696e7920676f6c6408000000000000000003") # OP_RETURN data + assert_equal(result[0]['owner'], + "6a1f446654785404474f4c440a7368696e7920676f6c6408000000000000000003") # OP_RETURN data assert_equal(result[0]['txn'], 1) assert_equal(result[0]['type'], 'CreateToken') assert_equal(result[0]['amounts'][0], '1.00000000@DFI') @@ -62,7 +63,8 @@ def run_test(self): # Check token burn fee result = self.nodes[0].listburnhistory() - assert_equal(result[0]['owner'], "6a2344665478540653494c5645520c7368696e792073696c76657208000000000000000003") # OP_RETURN data + assert_equal(result[0]['owner'], + "6a2344665478540653494c5645520c7368696e792073696c76657208000000000000000003") # OP_RETURN data assert_equal(result[0]['txn'], 1) assert_equal(result[0]['type'], 'CreateToken') assert_equal(result[0]['amounts'][0], '1.00000000@DFI') @@ -75,10 +77,10 @@ def run_test(self): self.nodes[0].generate(1) # Send tokens to burn address - self.nodes[0].accounttoaccount(address, {old_burn_address:"100@128"}) + self.nodes[0].accounttoaccount(address, {old_burn_address: "100@128"}) self.nodes[0].generate(1) - self.nodes[0].accounttoaccount(address, {old_burn_address:"100@129"}) + self.nodes[0].accounttoaccount(address, {old_burn_address: "100@129"}) self.nodes[0].generate(1) # Check balance @@ -87,9 +89,9 @@ def run_test(self): assert_equal(result[1], "100.00000000@SILVER#129") # Send funds to destruction addresses - self.nodes[0].utxostoaccount({destruction_one:"5@0"}) - self.nodes[0].utxostoaccount({destruction_one:"5@0"}) - self.nodes[0].utxostoaccount({destruction_two:"20@0"}) + self.nodes[0].utxostoaccount({destruction_one: "5@0"}) + self.nodes[0].utxostoaccount({destruction_one: "5@0"}) + self.nodes[0].utxostoaccount({destruction_two: "20@0"}) self.nodes[0].generate(1) # Check destruction balance @@ -138,7 +140,7 @@ def run_test(self): assert_equal(result[0], "100.00000000@GOLD#128") assert_equal(result[1], "100.00000000@SILVER#129") - assert_equal(len(self.nodes[0].listburnhistory()), 2) # Creation fee burns still present + assert_equal(len(self.nodes[0].listburnhistory()), 2) # Creation fee burns still present result = self.nodes[0].getburninfo() assert_equal(result['address'], burn_address) @@ -181,5 +183,6 @@ def run_test(self): result = self.nodes[0].getaccount(destruction_two) assert_equal(len(result), 0) + if __name__ == '__main__': TransferBurnTest().main() diff --git a/test/functional/feature_filelock.py b/test/functional/feature_filelock.py index fdff409386..8cf8a4a9df 100755 --- a/test/functional/feature_filelock.py +++ b/test/functional/feature_filelock.py @@ -8,6 +8,7 @@ from test_framework.test_framework import DefiTestFramework from test_framework.test_node import ErrorMatch + class FilelockTest(DefiTestFramework): def set_test_params(self): self.setup_clean_chain = True @@ -23,14 +24,18 @@ def run_test(self): self.log.info("Using datadir {}".format(datadir)) self.log.info("Check that we can't start a second defid instance using the same datadir") - expected_msg = "Error: Cannot obtain a lock on data directory {0}. {1} is probably already running.".format(datadir, self.config['environment']['PACKAGE_NAME']) - self.nodes[1].assert_start_raises_init_error(extra_args=['-datadir={}'.format(self.nodes[0].datadir), '-noserver'], expected_msg=expected_msg) + expected_msg = "Error: Cannot obtain a lock on data directory {0}. {1} is probably already running.".format( + datadir, self.config['environment']['PACKAGE_NAME']) + self.nodes[1].assert_start_raises_init_error( + extra_args=['-datadir={}'.format(self.nodes[0].datadir), '-noserver'], expected_msg=expected_msg) if self.is_wallet_compiled(): wallet_dir = os.path.join(datadir, 'wallets') self.log.info("Check that we can't start a second defid instance using the same wallet") expected_msg = "Error: Error initializing wallet database environment" - self.nodes[1].assert_start_raises_init_error(extra_args=['-walletdir={}'.format(wallet_dir), '-noserver'], expected_msg=expected_msg, match=ErrorMatch.PARTIAL_REGEX) + self.nodes[1].assert_start_raises_init_error(extra_args=['-walletdir={}'.format(wallet_dir), '-noserver'], + expected_msg=expected_msg, match=ErrorMatch.PARTIAL_REGEX) + if __name__ == '__main__': FilelockTest().main() diff --git a/test/functional/feature_foundation_migration.py b/test/functional/feature_foundation_migration.py index 54fe845424..39396ad1eb 100755 --- a/test/functional/feature_foundation_migration.py +++ b/test/functional/feature_foundation_migration.py @@ -9,18 +9,22 @@ from test_framework.util import assert_equal, assert_raises_rpc_error + class FoundationMemberTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 self.setup_clean_chain = True self.grand_central = 202 self.extra_args = [ - ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', '-fortcanningmuseumheight=1', '-fortcanninghillheight=1', '-fortcanningroadheight=1', '-fortcanningcrunchheight=1', f'-grandcentralheight={self.grand_central}', '-subsidytest=1'], - ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', '-fortcanningmuseumheight=1', '-fortcanninghillheight=1', '-fortcanningroadheight=1', '-fortcanningcrunchheight=1', f'-grandcentralheight={self.grand_central}', '-subsidytest=1'] + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', + '-fortcanningmuseumheight=1', '-fortcanninghillheight=1', '-fortcanningroadheight=1', + '-fortcanningcrunchheight=1', f'-grandcentralheight={self.grand_central}', '-subsidytest=1'], + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', + '-fortcanningmuseumheight=1', '-fortcanninghillheight=1', '-fortcanningroadheight=1', + '-fortcanningcrunchheight=1', f'-grandcentralheight={self.grand_central}', '-subsidytest=1'] ] def run_test(self): - # Define node 0 foundation address address = self.nodes[0].get_genesis_keys().ownerAuthAddress @@ -29,90 +33,116 @@ def run_test(self): self.sync_blocks() # Change address before fork - assert_raises_rpc_error(-32600, "Cannot be set before GrandCentralHeight", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/foundation/members':[address]}}) - assert_raises_rpc_error(-32600, "Cannot be set before GrandCentralHeight", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/feature/gov-foundation':'true'}}) + assert_raises_rpc_error(-32600, "Cannot be set before GrandCentralHeight", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/foundation/members': [address]}}) + assert_raises_rpc_error(-32600, "Cannot be set before GrandCentralHeight", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/feature/gov-foundation': 'true'}}) # Generate blocks on other node so both nodes have available UTXOs self.nodes[1].generate(self.grand_central - self.nodes[0].getblockcount()) self.sync_blocks() # Check addresses now in DB - assert_equal(self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES']['v0/params/foundation/members'], ["bcrt1qyrfrpadwgw7p5eh3e9h3jmu4kwlz4prx73cqny","bcrt1qyeuu9rvq8a67j86pzvh5897afdmdjpyankp4mu","msER9bmJjyEemRpQoS8YYVL21VyZZrSgQ7","mwsZw8nF7pKxWH8eoKL9tPxTpaFkz7QeLU"]) + assert_equal(self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES']['v0/params/foundation/members'], + ["bcrt1qyrfrpadwgw7p5eh3e9h3jmu4kwlz4prx73cqny", "bcrt1qyeuu9rvq8a67j86pzvh5897afdmdjpyankp4mu", + "msER9bmJjyEemRpQoS8YYVL21VyZZrSgQ7", "mwsZw8nF7pKxWH8eoKL9tPxTpaFkz7QeLU"]) # Add already existant address - assert_raises_rpc_error(-32600, "Member to add already present", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/foundation/members':[address]}}) + assert_raises_rpc_error(-32600, "Member to add already present", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/foundation/members': [address]}}) # Remove an address that is not present - assert_raises_rpc_error(-32600, "Member to remove not present", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/foundation/members':[f"-{self.nodes[0].getnewaddress()}"]}}) + assert_raises_rpc_error(-32600, "Member to remove not present", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/foundation/members': [f"-{self.nodes[0].getnewaddress()}"]}}) # Add nonsense address - assert_raises_rpc_error(-5, "Invalid address provided", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/foundation/members':["NOTANADDRESS"]}}) + assert_raises_rpc_error(-5, "Invalid address provided", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/foundation/members': ["NOTANADDRESS"]}}) # Enable foundation address in attributes - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/feature/gov-foundation':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/feature/gov-foundation': 'true'}}) self.nodes[0].generate(1) # Remove address - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/foundation/members':[f"-{address}"]}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/foundation/members': [f"-{address}"]}}) self.nodes[0].generate(1) # Check address no longer present - assert_equal(self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES']['v0/params/foundation/members'], ["bcrt1qyrfrpadwgw7p5eh3e9h3jmu4kwlz4prx73cqny","bcrt1qyeuu9rvq8a67j86pzvh5897afdmdjpyankp4mu","msER9bmJjyEemRpQoS8YYVL21VyZZrSgQ7"]) + assert_equal(self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES']['v0/params/foundation/members'], + ["bcrt1qyrfrpadwgw7p5eh3e9h3jmu4kwlz4prx73cqny", "bcrt1qyeuu9rvq8a67j86pzvh5897afdmdjpyankp4mu", + "msER9bmJjyEemRpQoS8YYVL21VyZZrSgQ7"]) # Try and add self back in without foundation auth - assert_raises_rpc_error(-32600, "tx not from foundation member", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/foundation/members':[address]}}) + assert_raises_rpc_error(-32600, "tx not from foundation member", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/foundation/members': [address]}}) # Add address in from another node self.sync_blocks() - self.nodes[1].setgov({"ATTRIBUTES":{'v0/params/foundation/members':[address]}}) + self.nodes[1].setgov({"ATTRIBUTES": {'v0/params/foundation/members': [address]}}) self.nodes[1].generate(1) self.sync_blocks() # Check address present again - assert_equal(self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES']['v0/params/foundation/members'], ["bcrt1qyrfrpadwgw7p5eh3e9h3jmu4kwlz4prx73cqny","bcrt1qyeuu9rvq8a67j86pzvh5897afdmdjpyankp4mu","msER9bmJjyEemRpQoS8YYVL21VyZZrSgQ7","mwsZw8nF7pKxWH8eoKL9tPxTpaFkz7QeLU"]) + assert_equal(self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES']['v0/params/foundation/members'], + ["bcrt1qyrfrpadwgw7p5eh3e9h3jmu4kwlz4prx73cqny", "bcrt1qyeuu9rvq8a67j86pzvh5897afdmdjpyankp4mu", + "msER9bmJjyEemRpQoS8YYVL21VyZZrSgQ7", "mwsZw8nF7pKxWH8eoKL9tPxTpaFkz7QeLU"]) # Removing address again, add new address and set another variable - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/foundation/members':[f"-{address}","+2MwHamtynMqvstggG5XsVPVoAKroa4CgwFs"],'v0/params/dfip2201/active':'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": { + 'v0/params/foundation/members': [f"-{address}", "+2MwHamtynMqvstggG5XsVPVoAKroa4CgwFs"], + 'v0/params/dfip2201/active': 'false'}}) self.nodes[0].generate(1) self.sync_blocks() # Check address no longer present attributes = self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'] - assert_equal(attributes['v0/params/foundation/members'], ["bcrt1qyrfrpadwgw7p5eh3e9h3jmu4kwlz4prx73cqny","bcrt1qyeuu9rvq8a67j86pzvh5897afdmdjpyankp4mu","2MwHamtynMqvstggG5XsVPVoAKroa4CgwFs","msER9bmJjyEemRpQoS8YYVL21VyZZrSgQ7"]) + assert_equal(attributes['v0/params/foundation/members'], + ["bcrt1qyrfrpadwgw7p5eh3e9h3jmu4kwlz4prx73cqny", "bcrt1qyeuu9rvq8a67j86pzvh5897afdmdjpyankp4mu", + "2MwHamtynMqvstggG5XsVPVoAKroa4CgwFs", "msER9bmJjyEemRpQoS8YYVL21VyZZrSgQ7"]) assert_equal(attributes['v0/params/dfip2201/active'], 'false') # Set stored lock activation_height = self.nodes[1].getblockcount() + 5 - self.nodes[1].setgovheight({"ATTRIBUTES":{'v0/params/foundation/members':["-2MwHamtynMqvstggG5XsVPVoAKroa4CgwFs","2N3kCSytvetmJybdZbqV5wK3Zzekg9SiSe2"],'v0/params/dfip2203/active':'false'}}, activation_height) + self.nodes[1].setgovheight({"ATTRIBUTES": { + 'v0/params/foundation/members': ["-2MwHamtynMqvstggG5XsVPVoAKroa4CgwFs", + "2N3kCSytvetmJybdZbqV5wK3Zzekg9SiSe2"], + 'v0/params/dfip2203/active': 'false'}}, activation_height) self.nodes[1].generate(1) # Check pending changes show as expected attributes = self.nodes[1].listgovs()[8] - assert_equal(attributes[1][str(activation_height)]['v0/params/foundation/members'], ["-2MwHamtynMqvstggG5XsVPVoAKroa4CgwFs","2N3kCSytvetmJybdZbqV5wK3Zzekg9SiSe2"]) + assert_equal(attributes[1][str(activation_height)]['v0/params/foundation/members'], + ["-2MwHamtynMqvstggG5XsVPVoAKroa4CgwFs", "2N3kCSytvetmJybdZbqV5wK3Zzekg9SiSe2"]) assert_equal(attributes[1][str(activation_height)]['v0/params/dfip2203/active'], 'false') # Move to fork height and check changes self.nodes[1].generate(5) self.sync_blocks() attributes = self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'] - assert_equal(attributes['v0/params/foundation/members'], ["bcrt1qyrfrpadwgw7p5eh3e9h3jmu4kwlz4prx73cqny","bcrt1qyeuu9rvq8a67j86pzvh5897afdmdjpyankp4mu","2N3kCSytvetmJybdZbqV5wK3Zzekg9SiSe2","msER9bmJjyEemRpQoS8YYVL21VyZZrSgQ7"]) + assert_equal(attributes['v0/params/foundation/members'], + ["bcrt1qyrfrpadwgw7p5eh3e9h3jmu4kwlz4prx73cqny", "bcrt1qyeuu9rvq8a67j86pzvh5897afdmdjpyankp4mu", + "2N3kCSytvetmJybdZbqV5wK3Zzekg9SiSe2", "msER9bmJjyEemRpQoS8YYVL21VyZZrSgQ7"]) assert_equal(attributes['v0/params/dfip2203/active'], 'false') # Check disabling feature restores original usage. Node 0 fails here. - assert_raises_rpc_error(-32600, "tx not from foundation member", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/foundation/members':[address]}}) - self.nodes[1].setgov({"ATTRIBUTES":{'v0/params/feature/gov-foundation':'false'}}) + assert_raises_rpc_error(-32600, "tx not from foundation member", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/foundation/members': [address]}}) + self.nodes[1].setgov({"ATTRIBUTES": {'v0/params/feature/gov-foundation': 'false'}}) self.nodes[1].generate(1) self.sync_blocks() # Can now add to Gov attributes again. Adding removing address allowed # while feature disabled,but addresses will not be used for auth. - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/foundation/members':[address]}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/foundation/members': [address]}}) self.nodes[0].generate(1) # Check address still present attributes = self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'] - assert_equal(attributes['v0/params/foundation/members'], ["bcrt1qyrfrpadwgw7p5eh3e9h3jmu4kwlz4prx73cqny","bcrt1qyeuu9rvq8a67j86pzvh5897afdmdjpyankp4mu","2N3kCSytvetmJybdZbqV5wK3Zzekg9SiSe2","msER9bmJjyEemRpQoS8YYVL21VyZZrSgQ7","mwsZw8nF7pKxWH8eoKL9tPxTpaFkz7QeLU"]) + assert_equal(attributes['v0/params/foundation/members'], + ["bcrt1qyrfrpadwgw7p5eh3e9h3jmu4kwlz4prx73cqny", "bcrt1qyeuu9rvq8a67j86pzvh5897afdmdjpyankp4mu", + "2N3kCSytvetmJybdZbqV5wK3Zzekg9SiSe2", "msER9bmJjyEemRpQoS8YYVL21VyZZrSgQ7", + "mwsZw8nF7pKxWH8eoKL9tPxTpaFkz7QeLU"]) + if __name__ == '__main__': FoundationMemberTest().main() - diff --git a/test/functional/feature_framework_rollback.py b/test/functional/feature_framework_rollback.py index 40b26c6543..15595daf5c 100755 --- a/test/functional/feature_framework_rollback.py +++ b/test/functional/feature_framework_rollback.py @@ -8,16 +8,32 @@ from test_framework.test_framework import DefiTestFramework from test_framework.util import assert_equal, assert_raises_rpc_error -class RollbackFrameworkTest (DefiTestFramework): + +class RollbackFrameworkTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 4 self.setup_clean_chain = True self.extra_args = [ - ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=1', '-fortcanningheight=50', '-eunosheight=50', '-fortcanninghillheight=50', '-fortcanningparkheight=50', '-fortcanningroadheight=50', '-fortcanningcrunchheight=50', '-fortcanningspringheight=50', '-fortcanninggreatworldheight=250', '-grandcentralheight=254', '-grandcentralepilogueheight=350', '-regtest-minttoken-simulate-mainnet=1', '-txindex=1'], - ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=1', '-fortcanningheight=50', '-eunosheight=50', '-fortcanninghillheight=50', '-fortcanningparkheight=50', '-fortcanningroadheight=50', '-fortcanningcrunchheight=50', '-fortcanningspringheight=50', '-fortcanninggreatworldheight=250', '-grandcentralheight=254', '-grandcentralepilogueheight=350', '-regtest-minttoken-simulate-mainnet=1', '-txindex=1'], - ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=1', '-fortcanningheight=50', '-eunosheight=50', '-fortcanninghillheight=50', '-fortcanningparkheight=50', '-fortcanningroadheight=50', '-fortcanningcrunchheight=50', '-fortcanningspringheight=50', '-fortcanninggreatworldheight=250', '-grandcentralheight=254', '-grandcentralepilogueheight=350', '-regtest-minttoken-simulate-mainnet=1', '-txindex=1'], - ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=1', '-fortcanningheight=50', '-eunosheight=50', '-fortcanninghillheight=50', '-fortcanningparkheight=50', '-fortcanningroadheight=50', '-fortcanningcrunchheight=50', '-fortcanningspringheight=50', '-fortcanninggreatworldheight=250', '-grandcentralheight=254', '-grandcentralepilogueheight=350', '-regtest-minttoken-simulate-mainnet=1', '-txindex=1']] - + ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=1', + '-fortcanningheight=50', '-eunosheight=50', '-fortcanninghillheight=50', '-fortcanningparkheight=50', + '-fortcanningroadheight=50', '-fortcanningcrunchheight=50', '-fortcanningspringheight=50', + '-fortcanninggreatworldheight=250', '-grandcentralheight=254', '-grandcentralepilogueheight=350', + '-regtest-minttoken-simulate-mainnet=1', '-txindex=1'], + ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=1', + '-fortcanningheight=50', '-eunosheight=50', '-fortcanninghillheight=50', '-fortcanningparkheight=50', + '-fortcanningroadheight=50', '-fortcanningcrunchheight=50', '-fortcanningspringheight=50', + '-fortcanninggreatworldheight=250', '-grandcentralheight=254', '-grandcentralepilogueheight=350', + '-regtest-minttoken-simulate-mainnet=1', '-txindex=1'], + ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=1', + '-fortcanningheight=50', '-eunosheight=50', '-fortcanninghillheight=50', '-fortcanningparkheight=50', + '-fortcanningroadheight=50', '-fortcanningcrunchheight=50', '-fortcanningspringheight=50', + '-fortcanninggreatworldheight=250', '-grandcentralheight=254', '-grandcentralepilogueheight=350', + '-regtest-minttoken-simulate-mainnet=1', '-txindex=1'], + ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=1', + '-fortcanningheight=50', '-eunosheight=50', '-fortcanninghillheight=50', '-fortcanningparkheight=50', + '-fortcanningroadheight=50', '-fortcanningcrunchheight=50', '-fortcanningspringheight=50', + '-fortcanninggreatworldheight=250', '-grandcentralheight=254', '-grandcentralepilogueheight=350', + '-regtest-minttoken-simulate-mainnet=1', '-txindex=1']] def init_chain(self): print("Generating initial chain...") @@ -42,7 +58,6 @@ def set_accounts(self, rollback=True): def set_accounts_with_rollback(self): self.set_accounts() - def create_tokens(self, rollback=None): self.symbolBTC = "BTC" self.symbolDOGE = "DOGE" @@ -99,9 +114,8 @@ def mint_extra_with_rollback(self): self.mint_extra() def run_test(self): - self.init_chain() - height = self.nodes[0].getblockcount() # block 100 + height = self.nodes[0].getblockcount() # block 100 # rollback self.set_accounts_with_rollback() @@ -111,7 +125,7 @@ def run_test(self): # no rollback self.set_accounts(rollback=False) height2 = self.nodes[3].getblockcount() - assert(height != height2) + assert (height != height2) # rollback self.create_tokens_with_rollback() @@ -121,7 +135,7 @@ def run_test(self): # no rollback self.create_tokens() height4 = self.nodes[0].getblockcount() - assert(height3 != height4) + assert (height3 != height4) # rollback self.mint_extra_with_rollback() @@ -131,7 +145,8 @@ def run_test(self): # no rollback self.mint_extra() height6 = self.nodes[0].getblockcount() - assert(height6 != height5) + assert (height6 != height5) + if __name__ == '__main__': RollbackFrameworkTest().main() diff --git a/test/functional/feature_futures.py b/test/functional/feature_futures.py index f9cb2805b4..2a8038b65e 100755 --- a/test/functional/feature_futures.py +++ b/test/functional/feature_futures.py @@ -11,14 +11,19 @@ from decimal import Decimal import time + def sort_history(e): return e['txn'] + class FuturesTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True - self.extra_args = [['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', '-fortcanninghillheight=1', '-fortcanningcrunchheight=150', '-fortcanningroadheight=150', '-fortcanningspringheight=500', '-subsidytest=1']] + self.extra_args = [ + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', + '-fortcanninghillheight=1', '-fortcanningcrunchheight=150', '-fortcanningroadheight=150', + '-fortcanningspringheight=500', '-subsidytest=1']] def run_test(self): self.nodes[0].generate(101) @@ -82,13 +87,13 @@ def setup_test(self): self.list_history = [] # Set token symbols - self.symbolDFI = 'DFI' - self.symbolDUSD = 'DUSD' - self.symbolTSLA = 'TSLA' + self.symbolDFI = 'DFI' + self.symbolDUSD = 'DUSD' + self.symbolTSLA = 'TSLA' self.symbolGOOGL = 'GOOGL' - self.symbolTWTR = 'TWTR' - self.symbolMSFT = 'MSFT' - self.symbolBTC = 'BTC' + self.symbolTWTR = 'TWTR' + self.symbolMSFT = 'MSFT' + self.symbolBTC = 'BTC' # Setup oracle oracle_address = self.nodes[0].getnewaddress("", "legacy") @@ -190,13 +195,13 @@ def setup_test(self): self.nodes[0].generate(1) # Set token ids - self.idDFI = list(self.nodes[0].gettoken(self.symbolDFI).keys())[0] - self.idDUSD = list(self.nodes[0].gettoken(self.symbolDUSD).keys())[0] - self.idTSLA = list(self.nodes[0].gettoken(self.symbolTSLA).keys())[0] + self.idDFI = list(self.nodes[0].gettoken(self.symbolDFI).keys())[0] + self.idDUSD = list(self.nodes[0].gettoken(self.symbolDUSD).keys())[0] + self.idTSLA = list(self.nodes[0].gettoken(self.symbolTSLA).keys())[0] self.idGOOGL = list(self.nodes[0].gettoken(self.symbolGOOGL).keys())[0] - self.idTWTR = list(self.nodes[0].gettoken(self.symbolTWTR).keys())[0] - self.idMSFT = list(self.nodes[0].gettoken(self.symbolMSFT).keys())[0] - self.idBTC = list(self.nodes[0].gettoken(self.symbolBTC).keys())[0] + self.idTWTR = list(self.nodes[0].gettoken(self.symbolTWTR).keys())[0] + self.idMSFT = list(self.nodes[0].gettoken(self.symbolMSFT).keys())[0] + self.idBTC = list(self.nodes[0].gettoken(self.symbolBTC).keys())[0] # Mint tokens for swapping self.nodes[0].minttokens([f'100000@{self.idDUSD}']) @@ -215,28 +220,34 @@ def futures_setup(self): address = self.nodes[0].getnewaddress("", "legacy") # Set DFI/DUSD fixed price interval - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDFI}/fixed_interval_price_id':f'{self.symbolDFI}/USD'}}) + self.nodes[0].setgov( + {"ATTRIBUTES": {f'v0/token/{self.idDFI}/fixed_interval_price_id': f'{self.symbolDFI}/USD'}}) self.nodes[0].generate(1) # Try futureswap before feature is active - assert_raises_rpc_error(-32600, "DFIP2203 not currently active", self.nodes[0].futureswap, address, f'1@{self.symbolTWTR}') + assert_raises_rpc_error(-32600, "DFIP2203 not currently active", self.nodes[0].futureswap, address, + f'1@{self.symbolTWTR}') # Set partial futures attributes - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/dfip2203/active':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/dfip2203/active': 'true'}}) self.nodes[0].generate(1) # Try futureswap before feature is fully active - assert_raises_rpc_error(-32600, "DFIP2203 not currently active", self.nodes[0].futureswap, address, f'1@{self.symbolTWTR}') + assert_raises_rpc_error(-32600, "DFIP2203 not currently active", self.nodes[0].futureswap, address, + f'1@{self.symbolTWTR}') # Set all futures attributes but set active to false - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/dfip2203/active':'false','v0/params/dfip2203/reward_pct':'0.05','v0/params/dfip2203/block_period':f'{self.futures_interval}'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/dfip2203/active': 'false', + 'v0/params/dfip2203/reward_pct': '0.05', + 'v0/params/dfip2203/block_period': f'{self.futures_interval}'}}) self.nodes[0].generate(1) # Try futureswap with DFIP2203 active set to false - assert_raises_rpc_error(-32600, "DFIP2203 not currently active", self.nodes[0].futureswap, address, f'1@{self.symbolTWTR}') + assert_raises_rpc_error(-32600, "DFIP2203 not currently active", self.nodes[0].futureswap, address, + f'1@{self.symbolTWTR}') # Fully enable DFIP2203 - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/dfip2203/active':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/dfip2203/active': 'true'}}) self.nodes[0].generate(1) # Verify Gov vars @@ -247,7 +258,7 @@ def futures_setup(self): assert_equal(result['v0/params/dfip2203/block_period'], str(self.futures_interval)) # Disable DUSD - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{str(self.idDUSD)}/dfip2203':'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{str(self.idDUSD)}/dfip2203': 'false'}}) self.nodes[0].generate(1) # Verify Gov vars @@ -255,7 +266,8 @@ def futures_setup(self): assert_equal(result[f'v0/token/{self.idDUSD}/dfip2203'], 'false') # Check futures block - next_futures_block = self.nodes[0].getblockcount() + (self.futures_interval - (self.nodes[0].getblockcount() % self.futures_interval)) + next_futures_block = self.nodes[0].getblockcount() + ( + self.futures_interval - (self.nodes[0].getblockcount() % self.futures_interval)) assert_equal(next_futures_block, self.nodes[0].getfutureswapblock()) def test_dtoken_to_dusd(self): @@ -274,11 +286,16 @@ def test_dtoken_to_dusd(self): self.nodes[0].generate(1) # Test futureswap failures - assert_raises_rpc_error(-32600, f'Could not get source loan token {self.idBTC}', self.nodes[0].futureswap, self.address, f'1@{self.symbolBTC}') - assert_raises_rpc_error(-32600, f'DFIP2203 currently disabled for token {self.idDUSD}', self.nodes[0].futureswap, self.address, f'1@{self.symbolDUSD}', int(self.idDUSD)) - assert_raises_rpc_error(-32600, f'Could not get destination loan token {self.idBTC}. Set valid destination.', self.nodes[0].futureswap, self.address, f'1@{self.symbolDUSD}', int(self.idBTC)) - assert_raises_rpc_error(-32600, 'Destination should not be set when source amount is dToken or DFI', self.nodes[0].futureswap, self.address, f'1@{self.symbolTSLA}', int(self.idBTC)) - assert_raises_rpc_error(-32600, 'amount 0.00000000 is less than 1.00000000', self.nodes[0].futureswap, address_twtr, f'1@{self.symbolTSLA}') + assert_raises_rpc_error(-32600, f'Could not get source loan token {self.idBTC}', self.nodes[0].futureswap, + self.address, f'1@{self.symbolBTC}') + assert_raises_rpc_error(-32600, f'DFIP2203 currently disabled for token {self.idDUSD}', + self.nodes[0].futureswap, self.address, f'1@{self.symbolDUSD}', int(self.idDUSD)) + assert_raises_rpc_error(-32600, f'Could not get destination loan token {self.idBTC}. Set valid destination.', + self.nodes[0].futureswap, self.address, f'1@{self.symbolDUSD}', int(self.idBTC)) + assert_raises_rpc_error(-32600, 'Destination should not be set when source amount is dToken or DFI', + self.nodes[0].futureswap, self.address, f'1@{self.symbolTSLA}', int(self.idBTC)) + assert_raises_rpc_error(-32600, 'amount 0.00000000 is less than 1.00000000', self.nodes[0].futureswap, + address_twtr, f'1@{self.symbolTSLA}') # Create user futures contracts self.nodes[0].futureswap(address_twtr, f'1@{self.symbolTWTR}') @@ -331,25 +348,30 @@ def test_dtoken_to_dusd(self): # Check DFI2203 address on listgovs, current shows pending, burn should be empty. result = self.nodes[0].listgovs()[8][0]['ATTRIBUTES'] - assert_equal(result['v0/live/economy/dfip2203_current'], [f'1.00000000@{self.symbolTSLA}', f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', f'1.00000000@{self.symbolMSFT}']) - assert('v0/live/economy/dfip2203_burned' not in result) - assert('v0/live/economy/dfip2203_minted' not in result) + assert_equal(result['v0/live/economy/dfip2203_current'], + [f'1.00000000@{self.symbolTSLA}', f'1.00000000@{self.symbolGOOGL}', + f'1.00000000@{self.symbolTWTR}', f'1.00000000@{self.symbolMSFT}']) + assert ('v0/live/economy/dfip2203_burned' not in result) + assert ('v0/live/economy/dfip2203_minted' not in result) # Get token total minted before future swap total_dusd = Decimal(self.nodes[0].gettoken(self.idDUSD)[self.idDUSD]['minted']) # Move to next futures block - next_futures_block = self.nodes[0].getblockcount() + (self.futures_interval - (self.nodes[0].getblockcount() % self.futures_interval)) + next_futures_block = self.nodes[0].getblockcount() + ( + self.futures_interval - (self.nodes[0].getblockcount() % self.futures_interval)) self.nodes[0].generate(next_futures_block - self.nodes[0].getblockcount()) # Check total minted incremented as expected new_total_dusd = Decimal(self.nodes[0].gettoken(self.idDUSD)[self.idDUSD]['minted']) - assert_equal(total_dusd + self.prices[0]["discountPrice"] + self.prices[1]["discountPrice"] + self.prices[2]["discountPrice"] + self.prices[3]["discountPrice"], new_total_dusd) + assert_equal(total_dusd + self.prices[0]["discountPrice"] + self.prices[1]["discountPrice"] + self.prices[2][ + "discountPrice"] + self.prices[3]["discountPrice"], new_total_dusd) # Check TXN ordering txn_first = 4294967295 - result = self.nodes[0].listaccounthistory('all', {"maxBlockHeight":self.nodes[0].getblockcount(), 'depth':0, 'txtype':'q'}) - result.sort(key = sort_history, reverse = True) + result = self.nodes[0].listaccounthistory('all', {"maxBlockHeight": self.nodes[0].getblockcount(), 'depth': 0, + 'txtype': 'q'}) + result.sort(key=sort_history, reverse=True) for result_entry in result: assert_equal(result_entry['txn'], txn_first) txn_first -= 1 @@ -368,15 +390,19 @@ def test_dtoken_to_dusd(self): # Check contract address result = self.nodes[0].getaccount(self.contract_address) - assert_equal(result, [f'1.00000000@{self.symbolTSLA}', f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', f'1.00000000@{self.symbolMSFT}']) + assert_equal(result, [f'1.00000000@{self.symbolTSLA}', f'1.00000000@{self.symbolGOOGL}', + f'1.00000000@{self.symbolTWTR}', f'1.00000000@{self.symbolMSFT}']) # Check DFI2203 address on listgovs result = self.nodes[0].listgovs()[8][0]['ATTRIBUTES'] - assert_equal(result['v0/live/economy/dfip2203_current'], [f'1.00000000@{self.symbolTSLA}', f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', f'1.00000000@{self.symbolMSFT}']) + assert_equal(result['v0/live/economy/dfip2203_current'], + [f'1.00000000@{self.symbolTSLA}', f'1.00000000@{self.symbolGOOGL}', + f'1.00000000@{self.symbolTWTR}', f'1.00000000@{self.symbolMSFT}']) # Check DFI2203 address on getburninfo result = self.nodes[0].getburninfo() - assert_equal(result['dfip2203'], [f'1.00000000@{self.symbolTSLA}', f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', f'1.00000000@{self.symbolMSFT}']) + assert_equal(result['dfip2203'], [f'1.00000000@{self.symbolTSLA}', f'1.00000000@{self.symbolGOOGL}', + f'1.00000000@{self.symbolTWTR}', f'1.00000000@{self.symbolMSFT}']) # Check that futures have been executed result = self.nodes[0].getaccount(address_msft) @@ -405,10 +431,14 @@ def test_dusd_to_dtoken(self): address_msft = self.nodes[0].getnewaddress("", "legacy") # Fund addresses - self.nodes[0].accounttoaccount(self.address, {address_tsla: f'{self.prices[0]["premiumPrice"]}@{self.symbolDUSD}'}) - self.nodes[0].accounttoaccount(self.address, {address_googl: f'{self.prices[1]["premiumPrice"]}@{self.symbolDUSD}'}) - self.nodes[0].accounttoaccount(self.address, {address_twtr: f'{self.prices[2]["premiumPrice"]}@{self.symbolDUSD}'}) - self.nodes[0].accounttoaccount(self.address, {address_msft: f'{self.prices[3]["premiumPrice"]}@{self.symbolDUSD}'}) + self.nodes[0].accounttoaccount(self.address, + {address_tsla: f'{self.prices[0]["premiumPrice"]}@{self.symbolDUSD}'}) + self.nodes[0].accounttoaccount(self.address, + {address_googl: f'{self.prices[1]["premiumPrice"]}@{self.symbolDUSD}'}) + self.nodes[0].accounttoaccount(self.address, + {address_twtr: f'{self.prices[2]["premiumPrice"]}@{self.symbolDUSD}'}) + self.nodes[0].accounttoaccount(self.address, + {address_msft: f'{self.prices[3]["premiumPrice"]}@{self.symbolDUSD}'}) self.nodes[0].generate(1) # Create user futures contracts @@ -458,14 +488,21 @@ def test_dusd_to_dtoken(self): # Check new DFI2203 amounts do not show up as burns yet result = self.nodes[0].getburninfo() - assert_equal(result['dfip2203'], [f'1.00000000@{self.symbolTSLA}', f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', f'1.00000000@{self.symbolMSFT}']) + assert_equal(result['dfip2203'], [f'1.00000000@{self.symbolTSLA}', f'1.00000000@{self.symbolGOOGL}', + f'1.00000000@{self.symbolTWTR}', f'1.00000000@{self.symbolMSFT}']) # Check DFI2203 address on listgovs, current shows pending if any, burned shows # deposits from executed swaps and minted shows output from executed swaps. result = self.nodes[0].listgovs()[8][0]['ATTRIBUTES'] - assert_equal(result['v0/live/economy/dfip2203_current'], [f'3992.10000000@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', f'1.00000000@{self.symbolMSFT}']) - assert_equal(result['v0/live/economy/dfip2203_burned'], [f'1.00000000@{self.symbolTSLA}', f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', f'1.00000000@{self.symbolMSFT}']) - assert_equal(result['v0/live/economy/dfip2203_minted'], [f'{self.prices[0]["discountPrice"] + self.prices[1]["discountPrice"] + self.prices[2]["discountPrice"] + self.prices[3]["discountPrice"]}@{self.symbolDUSD}']) + assert_equal(result['v0/live/economy/dfip2203_current'], + [f'3992.10000000@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', + f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', + f'1.00000000@{self.symbolMSFT}']) + assert_equal(result['v0/live/economy/dfip2203_burned'], + [f'1.00000000@{self.symbolTSLA}', f'1.00000000@{self.symbolGOOGL}', + f'1.00000000@{self.symbolTWTR}', f'1.00000000@{self.symbolMSFT}']) + assert_equal(result['v0/live/economy/dfip2203_minted'], [ + f'{self.prices[0]["discountPrice"] + self.prices[1]["discountPrice"] + self.prices[2]["discountPrice"] + self.prices[3]["discountPrice"]}@{self.symbolDUSD}']) # Get token total minted before future swap total_tsla = Decimal(self.nodes[0].gettoken(self.idTSLA)[self.idTSLA]['minted']) @@ -474,7 +511,8 @@ def test_dusd_to_dtoken(self): total_msft = Decimal(self.nodes[0].gettoken(self.idMSFT)[self.idMSFT]['minted']) # Move to next futures block - next_futures_block = self.nodes[0].getblockcount() + (self.futures_interval - (self.nodes[0].getblockcount() % self.futures_interval)) + next_futures_block = self.nodes[0].getblockcount() + ( + self.futures_interval - (self.nodes[0].getblockcount() % self.futures_interval)) self.nodes[0].generate(next_futures_block - self.nodes[0].getblockcount()) # Check minted totals incremented as expected @@ -501,15 +539,22 @@ def test_dusd_to_dtoken(self): # Check contract address result = self.nodes[0].getaccount(self.contract_address) - assert_equal(result, [f'3992.10000000@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', f'1.00000000@{self.symbolMSFT}']) + assert_equal(result, [f'3992.10000000@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', + f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', + f'1.00000000@{self.symbolMSFT}']) # Check DFI2203 address on listgovs result = self.nodes[0].listgovs()[8][0]['ATTRIBUTES'] - assert_equal(result['v0/live/economy/dfip2203_current'], [f'3992.10000000@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', f'1.00000000@{self.symbolMSFT}']) + assert_equal(result['v0/live/economy/dfip2203_current'], + [f'3992.10000000@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', + f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', + f'1.00000000@{self.symbolMSFT}']) # Check DFI2203 address on getburninfo result = self.nodes[0].getburninfo() - assert_equal(result['dfip2203'], [f'3992.10000000@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', f'1.00000000@{self.symbolMSFT}']) + assert_equal(result['dfip2203'], [f'3992.10000000@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', + f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', + f'1.00000000@{self.symbolMSFT}']) # Check that futures have been executed result = self.nodes[0].getaccount(address_msft) @@ -535,11 +580,13 @@ def check_swap_block_range(self): address = self.nodes[0].getnewaddress("", "legacy") # Fund addresses - self.nodes[0].accounttoaccount(self.address, {address: f'{self.prices[0]["premiumPrice"] * 2}@{self.symbolDUSD}'}) + self.nodes[0].accounttoaccount(self.address, + {address: f'{self.prices[0]["premiumPrice"] * 2}@{self.symbolDUSD}'}) self.nodes[0].generate(1) # Move to just before futures block - next_futures_block = self.nodes[0].getblockcount() + (self.futures_interval - (self.nodes[0].getblockcount() % self.futures_interval)) + next_futures_block = self.nodes[0].getblockcount() + ( + self.futures_interval - (self.nodes[0].getblockcount() % self.futures_interval)) self.nodes[0].generate(next_futures_block - self.nodes[0].getblockcount() - 1) # Create user futures contracts on futures block @@ -559,7 +606,8 @@ def check_swap_block_range(self): assert_equal(len(result['values']), 0) # Try and withdraw smallest amount now contract has been paid - assert_raises_rpc_error(-32600, 'amount 0.00000000 is less than 0.00000001', self.nodes[0].withdrawfutureswap, address, f'{Decimal("0.00000001")}@{self.symbolDUSD}', int(self.idTSLA)) + assert_raises_rpc_error(-32600, 'amount 0.00000000 is less than 0.00000001', self.nodes[0].withdrawfutureswap, + address, f'{Decimal("0.00000001")}@{self.symbolDUSD}', int(self.idTSLA)) # Populate RPC check self.list_history.append({'height': self.nodes[0].getblockcount(), 'swaps': [ @@ -567,7 +615,8 @@ def check_swap_block_range(self): ]}) # Move to next futures block - next_futures_block = self.nodes[0].getblockcount() + (self.futures_interval - (self.nodes[0].getblockcount() % self.futures_interval)) + next_futures_block = self.nodes[0].getblockcount() + ( + self.futures_interval - (self.nodes[0].getblockcount() % self.futures_interval)) self.nodes[0].generate(next_futures_block - self.nodes[0].getblockcount()) # Check that futures has not been executed again @@ -576,7 +625,9 @@ def check_swap_block_range(self): # Check contract address result = self.nodes[0].getaccount(self.contract_address) - assert_equal(result, [f'4905.60000000@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', f'1.00000000@{self.symbolMSFT}']) + assert_equal(result, [f'4905.60000000@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', + f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', + f'1.00000000@{self.symbolMSFT}']) def check_multiple_swaps(self): @@ -585,8 +636,10 @@ def check_multiple_swaps(self): address_twtr = self.nodes[0].getnewaddress("", "legacy") # Fund addresses - self.nodes[0].accounttoaccount(self.address, {address_tsla: f'{self.prices[0]["premiumPrice"] * 2}@{self.symbolDUSD}'}) - self.nodes[0].accounttoaccount(self.address, {address_twtr: f'{self.prices[2]["premiumPrice"] * 2}@{self.symbolDUSD}'}) + self.nodes[0].accounttoaccount(self.address, + {address_tsla: f'{self.prices[0]["premiumPrice"] * 2}@{self.symbolDUSD}'}) + self.nodes[0].accounttoaccount(self.address, + {address_twtr: f'{self.prices[2]["premiumPrice"] * 2}@{self.symbolDUSD}'}) self.nodes[0].generate(1) # Create two user futures contracts @@ -611,7 +664,8 @@ def check_multiple_swaps(self): assert_equal(result['values'][0]['destination'], self.symbolTWTR) # Move to next futures block - next_futures_block = self.nodes[0].getblockcount() + (self.futures_interval - (self.nodes[0].getblockcount() % self.futures_interval)) + next_futures_block = self.nodes[0].getblockcount() + ( + self.futures_interval - (self.nodes[0].getblockcount() % self.futures_interval)) self.nodes[0].generate(next_futures_block - self.nodes[0].getblockcount()) # Check that futures have been executed @@ -622,7 +676,9 @@ def check_multiple_swaps(self): # Check contract address result = self.nodes[0].getaccount(self.contract_address) - assert_equal(result, [f'6810.30000000@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', f'1.00000000@{self.symbolMSFT}']) + assert_equal(result, [f'6810.30000000@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', + f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', + f'1.00000000@{self.symbolMSFT}']) def check_withdrawals(self): @@ -633,10 +689,14 @@ def check_withdrawals(self): address_msft = self.nodes[0].getnewaddress("", "legacy") # Fund addresses - self.nodes[0].accounttoaccount(self.address, {address_tsla: f'{self.prices[0]["premiumPrice"] * 2}@{self.symbolDUSD}'}) - self.nodes[0].accounttoaccount(self.address, {address_googl: f'{self.prices[1]["premiumPrice"] * 2}@{self.symbolDUSD}'}) - self.nodes[0].accounttoaccount(self.address, {address_twtr: f'{self.prices[2]["premiumPrice"] * 2}@{self.symbolDUSD}'}) - self.nodes[0].accounttoaccount(self.address, {address_msft: f'{self.prices[3]["premiumPrice"] * 2}@{self.symbolDUSD}'}) + self.nodes[0].accounttoaccount(self.address, + {address_tsla: f'{self.prices[0]["premiumPrice"] * 2}@{self.symbolDUSD}'}) + self.nodes[0].accounttoaccount(self.address, + {address_googl: f'{self.prices[1]["premiumPrice"] * 2}@{self.symbolDUSD}'}) + self.nodes[0].accounttoaccount(self.address, + {address_twtr: f'{self.prices[2]["premiumPrice"] * 2}@{self.symbolDUSD}'}) + self.nodes[0].accounttoaccount(self.address, + {address_msft: f'{self.prices[3]["premiumPrice"] * 2}@{self.symbolDUSD}'}) self.nodes[0].generate(1) # Create user futures contracts @@ -644,8 +704,10 @@ def check_withdrawals(self): self.nodes[0].futureswap(address_msft, f'{self.prices[3]["premiumPrice"]}@{self.symbolDUSD}', int(self.idMSFT)) self.nodes[0].futureswap(address_twtr, f'{self.prices[2]["premiumPrice"]}@{self.symbolDUSD}', int(self.idTWTR)) self.nodes[0].futureswap(address_twtr, f'{self.prices[2]["premiumPrice"]}@{self.symbolDUSD}', int(self.idTWTR)) - self.nodes[0].futureswap(address_googl, f'{self.prices[1]["premiumPrice"]}@{self.symbolDUSD}', int(self.idGOOGL)) - self.nodes[0].futureswap(address_googl, f'{self.prices[1]["premiumPrice"]}@{self.symbolDUSD}', int(self.idGOOGL)) + self.nodes[0].futureswap(address_googl, f'{self.prices[1]["premiumPrice"]}@{self.symbolDUSD}', + int(self.idGOOGL)) + self.nodes[0].futureswap(address_googl, f'{self.prices[1]["premiumPrice"]}@{self.symbolDUSD}', + int(self.idGOOGL)) self.nodes[0].futureswap(address_tsla, f'{self.prices[0]["premiumPrice"]}@{self.symbolDUSD}', int(self.idTSLA)) self.nodes[0].futureswap(address_tsla, f'{self.prices[0]["premiumPrice"]}@{self.symbolDUSD}', int(self.idTSLA)) self.nodes[0].generate(1) @@ -679,11 +741,18 @@ def check_withdrawals(self): assert_equal(result['values'][1]['destination'], self.symbolMSFT) # Check withdrawal failures - assert_raises_rpc_error(-32600, f'amount 0.00000000 is less than {self.prices[2]["premiumPrice"] * 2}', self.nodes[0].withdrawfutureswap, address_tsla, f'{self.prices[2]["premiumPrice"] * 2}@{self.symbolDUSD}', int(self.idTWTR)) - assert_raises_rpc_error(-32600, f'amount {self.prices[0]["premiumPrice"] * 2} is less than {(self.prices[0]["premiumPrice"] * 2) + Decimal("0.00000001")}', self.nodes[0].withdrawfutureswap, address_tsla, f'{(self.prices[0]["premiumPrice"] * 2) + Decimal("0.00000001")}@{self.symbolDUSD}', int(self.idTSLA)) + assert_raises_rpc_error(-32600, f'amount 0.00000000 is less than {self.prices[2]["premiumPrice"] * 2}', + self.nodes[0].withdrawfutureswap, address_tsla, + f'{self.prices[2]["premiumPrice"] * 2}@{self.symbolDUSD}', int(self.idTWTR)) + assert_raises_rpc_error(-32600, + f'amount {self.prices[0]["premiumPrice"] * 2} is less than {(self.prices[0]["premiumPrice"] * 2) + Decimal("0.00000001")}', + self.nodes[0].withdrawfutureswap, address_tsla, + f'{(self.prices[0]["premiumPrice"] * 2) + Decimal("0.00000001")}@{self.symbolDUSD}', + int(self.idTSLA)) # Withdraw both TSLA contracts - self.nodes[0].withdrawfutureswap(address_tsla, f'{self.prices[0]["premiumPrice"] * 2}@{self.symbolDUSD}', int(self.idTSLA)) + self.nodes[0].withdrawfutureswap(address_tsla, f'{self.prices[0]["premiumPrice"] * 2}@{self.symbolDUSD}', + int(self.idTSLA)) self.nodes[0].generate(1) # Check user pending swap is empty @@ -691,10 +760,13 @@ def check_withdrawals(self): assert_equal(len(result['values']), 0) # Try and withdraw smallest amount now contract empty - assert_raises_rpc_error(-32600, 'amount 0.00000000 is less than 0.00000001', self.nodes[0].withdrawfutureswap, address_tsla, f'{Decimal("0.00000001")}@{self.symbolDUSD}', int(self.idTSLA)) + assert_raises_rpc_error(-32600, 'amount 0.00000000 is less than 0.00000001', self.nodes[0].withdrawfutureswap, + address_tsla, f'{Decimal("0.00000001")}@{self.symbolDUSD}', int(self.idTSLA)) # Withdraw frm GOOGL everything but one Sat - self.nodes[0].withdrawfutureswap(address_googl, f'{(self.prices[1]["premiumPrice"] * 2) - Decimal("0.00000001")}@{self.symbolDUSD}', int(self.idGOOGL)) + self.nodes[0].withdrawfutureswap(address_googl, + f'{(self.prices[1]["premiumPrice"] * 2) - Decimal("0.00000001")}@{self.symbolDUSD}', + int(self.idGOOGL)) self.nodes[0].generate(1) # Check user pending swap @@ -703,12 +775,15 @@ def check_withdrawals(self): assert_equal(result['values'][0]['destination'], self.symbolGOOGL) # Withdraw one TWTR contract plus 1 Sat of the second one - self.nodes[0].withdrawfutureswap(address_twtr, f'{self.prices[2]["premiumPrice"] + Decimal("0.00000001")}@{self.symbolDUSD}', int(self.idTWTR)) + self.nodes[0].withdrawfutureswap(address_twtr, + f'{self.prices[2]["premiumPrice"] + Decimal("0.00000001")}@{self.symbolDUSD}', + int(self.idTWTR)) self.nodes[0].generate(1) # Check user pending swap result = self.nodes[0].getpendingfutureswaps(address_twtr) - assert_equal(result['values'][0]['source'], f'{self.prices[2]["premiumPrice"] - Decimal("0.00000001")}@{self.symbolDUSD}') + assert_equal(result['values'][0]['source'], + f'{self.prices[2]["premiumPrice"] - Decimal("0.00000001")}@{self.symbolDUSD}') assert_equal(result['values'][0]['destination'], self.symbolTWTR) # Withdraw one Sat @@ -717,18 +792,21 @@ def check_withdrawals(self): # Check user pending swap result = self.nodes[0].getpendingfutureswaps(address_msft) - assert_equal(result['values'][0]['source'], f'{(self.prices[3]["premiumPrice"] * 2) - Decimal("0.00000001")}@{self.symbolDUSD}') + assert_equal(result['values'][0]['source'], + f'{(self.prices[3]["premiumPrice"] * 2) - Decimal("0.00000001")}@{self.symbolDUSD}') assert_equal(result['values'][0]['destination'], self.symbolMSFT) # Move to next futures block - next_futures_block = self.nodes[0].getblockcount() + (self.futures_interval - (self.nodes[0].getblockcount() % self.futures_interval)) + next_futures_block = self.nodes[0].getblockcount() + ( + self.futures_interval - (self.nodes[0].getblockcount() % self.futures_interval)) self.nodes[0].generate(next_futures_block - self.nodes[0].getblockcount()) # Check final balances result = self.nodes[0].getaccount(address_tsla) assert_equal(result, [f'{self.prices[0]["premiumPrice"] * 2}@{self.symbolDUSD}']) result = self.nodes[0].getaccount(address_twtr) - assert_equal(result, [f'{self.prices[2]["premiumPrice"] + Decimal("0.00000001")}@{self.symbolDUSD}', f'0.99999999@{self.symbolTWTR}']) + assert_equal(result, [f'{self.prices[2]["premiumPrice"] + Decimal("0.00000001")}@{self.symbolDUSD}', + f'0.99999999@{self.symbolTWTR}']) result = self.nodes[0].getaccount(address_googl) assert_equal(result, [f'{(self.prices[1]["premiumPrice"] * 2) - Decimal("0.00000001")}@{self.symbolDUSD}']) result = self.nodes[0].getaccount(address_msft) @@ -736,15 +814,22 @@ def check_withdrawals(self): # Check contract address result = self.nodes[0].getaccount(self.contract_address) - assert_equal(result, [f'7468.64999999@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', f'1.00000000@{self.symbolMSFT}']) + assert_equal(result, [f'7468.64999999@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', + f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', + f'1.00000000@{self.symbolMSFT}']) # Check DFI2203 address on listgovs result = self.nodes[0].listgovs()[8][0]['ATTRIBUTES'] - assert_equal(result['v0/live/economy/dfip2203_current'], [f'7468.64999999@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', f'1.00000000@{self.symbolMSFT}']) + assert_equal(result['v0/live/economy/dfip2203_current'], + [f'7468.64999999@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', + f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', + f'1.00000000@{self.symbolMSFT}']) # Check DFI2203 address on getburninfo result = self.nodes[0].getburninfo() - assert_equal(result['dfip2203'], [f'7468.64999999@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', f'1.00000000@{self.symbolMSFT}']) + assert_equal(result['dfip2203'], [f'7468.64999999@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', + f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', + f'1.00000000@{self.symbolMSFT}']) def check_minimum_swaps(self): @@ -760,7 +845,8 @@ def check_minimum_swaps(self): self.nodes[0].generate(1) # Move to next futures block - next_futures_block = self.nodes[0].getblockcount() + (self.futures_interval - (self.nodes[0].getblockcount() % self.futures_interval)) + next_futures_block = self.nodes[0].getblockcount() + ( + self.futures_interval - (self.nodes[0].getblockcount() % self.futures_interval)) self.nodes[0].generate(next_futures_block - self.nodes[0].getblockcount()) # Check one Satoshi swap yields no TSLA @@ -769,7 +855,9 @@ def check_minimum_swaps(self): # Check contract address result = self.nodes[0].getaccount(self.contract_address) - assert_equal(result, [f'7468.65000000@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', f'1.00000000@{self.symbolMSFT}']) + assert_equal(result, [f'7468.65000000@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', + f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', + f'1.00000000@{self.symbolMSFT}']) # Create user futures contract to purchase one Satoshi of TSLA min_purchase = round(self.prices[0]["premiumPrice"] / 100000000, 8) @@ -777,16 +865,21 @@ def check_minimum_swaps(self): self.nodes[0].generate(1) # Move to next futures block - next_futures_block = self.nodes[0].getblockcount() + (self.futures_interval - (self.nodes[0].getblockcount() % self.futures_interval)) + next_futures_block = self.nodes[0].getblockcount() + ( + self.futures_interval - (self.nodes[0].getblockcount() % self.futures_interval)) self.nodes[0].generate(next_futures_block - self.nodes[0].getblockcount()) # Check one Satoshi swap yields one TSLA Satoshi result = self.nodes[0].getaccount(address) - assert_equal(result, [f'{self.prices[0]["premiumPrice"] - Decimal("0.00000001") - Decimal(min_purchase)}@{self.symbolDUSD}', f'0.00000001@{self.symbolTSLA}']) + assert_equal(result, [ + f'{self.prices[0]["premiumPrice"] - Decimal("0.00000001") - Decimal(min_purchase)}@{self.symbolDUSD}', + f'0.00000001@{self.symbolTSLA}']) # Check contract address result = self.nodes[0].getaccount(self.contract_address) - assert_equal(result, [f'7468.65000914@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', f'1.00000000@{self.symbolMSFT}']) + assert_equal(result, [f'7468.65000914@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', + f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', + f'1.00000000@{self.symbolMSFT}']) def check_gov_var_change(self): @@ -798,7 +891,8 @@ def check_gov_var_change(self): self.nodes[0].generate(1) # Move to before next futures block - next_futures_block = self.nodes[0].getblockcount() + (self.futures_interval - (self.nodes[0].getblockcount() % self.futures_interval)) - 1 + next_futures_block = self.nodes[0].getblockcount() + ( + self.futures_interval - (self.nodes[0].getblockcount() % self.futures_interval)) - 1 self.nodes[0].generate(next_futures_block - self.nodes[0].getblockcount()) # Create user futures contract with 1 Satoshi to invalidate block period change @@ -807,29 +901,35 @@ def check_gov_var_change(self): # Check contract address has updated result = self.nodes[0].getaccount(self.contract_address) - assert_equal(result, [f'7468.65000915@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', f'1.00000000@{self.symbolMSFT}']) + assert_equal(result, [f'7468.65000915@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', + f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', + f'1.00000000@{self.symbolMSFT}']) # Test changing block period while DFIP2203 still active - assert_raises_rpc_error(-32600, 'Cannot set block period while DFIP2203 is active', self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2203/block_period':f'{self.futures_interval}'}}) + assert_raises_rpc_error(-32600, 'Cannot set block period while DFIP2203 is active', self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2203/block_period': f'{self.futures_interval}'}}) # Disable DFIP2203 to be able to change block period - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/dfip2203/active':'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/dfip2203/active': 'false'}}) self.nodes[0].generate(1) # Check contract address has not changed, no refund on disabling DFIP2203. result = self.nodes[0].getaccount(self.contract_address) - assert_equal(result, [f'7468.65000915@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', f'1.00000000@{self.symbolMSFT}']) + assert_equal(result, [f'7468.65000915@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', + f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', + f'1.00000000@{self.symbolMSFT}']) # Move to next futures block - next_futures_block = self.nodes[0].getblockcount() + (self.futures_interval - (self.nodes[0].getblockcount() % self.futures_interval)) + next_futures_block = self.nodes[0].getblockcount() + ( + self.futures_interval - (self.nodes[0].getblockcount() % self.futures_interval)) self.nodes[0].generate(next_futures_block - self.nodes[0].getblockcount()) # Now set the new block period - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/dfip2203/block_period':f'{self.futures_interval}'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/dfip2203/block_period': f'{self.futures_interval}'}}) self.nodes[0].generate(1) # Enable DFIP2203 - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/dfip2203/active':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/dfip2203/active': 'true'}}) self.nodes[0].generate(1) # Create addresses @@ -837,23 +937,27 @@ def check_gov_var_change(self): address_googl = self.nodes[0].getnewaddress("", "legacy") # Fund addresses - self.nodes[0].accounttoaccount(self.address, {address_tsla: f'{self.prices[0]["premiumPrice"]}@{self.symbolDUSD}'}) - self.nodes[0].accounttoaccount(self.address, {address_googl: f'{self.prices[1]["premiumPrice"]}@{self.symbolDUSD}'}) + self.nodes[0].accounttoaccount(self.address, + {address_tsla: f'{self.prices[0]["premiumPrice"]}@{self.symbolDUSD}'}) + self.nodes[0].accounttoaccount(self.address, + {address_googl: f'{self.prices[1]["premiumPrice"]}@{self.symbolDUSD}'}) self.nodes[0].generate(1) # Create user futures contracts - self.nodes[0].futureswap(address_googl, f'{self.prices[1]["premiumPrice"]}@{self.symbolDUSD}', int(self.idGOOGL)) + self.nodes[0].futureswap(address_googl, f'{self.prices[1]["premiumPrice"]}@{self.symbolDUSD}', + int(self.idGOOGL)) self.nodes[0].futureswap(address_tsla, f'{self.prices[0]["premiumPrice"]}@{self.symbolDUSD}', int(self.idTSLA)) self.nodes[0].generate(1) # Disable DFIP2203 - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/dfip2203/active':'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/dfip2203/active': 'false'}}) self.nodes[0].generate(1) # Check TXN ordering on Gov var refunds txn_first = 4294967295 - result = self.nodes[0].listaccounthistory('all', {"maxBlockHeight":self.nodes[0].getblockcount(), 'depth':0, 'txtype':'w'}) - result.sort(key = sort_history, reverse = True) + result = self.nodes[0].listaccounthistory('all', {"maxBlockHeight": self.nodes[0].getblockcount(), 'depth': 0, + 'txtype': 'w'}) + result.sort(key=sort_history, reverse=True) assert_equal(len(result), 4) for result_entry in result: assert_equal(result_entry['blockHeight'], self.nodes[0].getblockcount()) @@ -887,19 +991,22 @@ def check_gov_var_change(self): # Check contract address remains the same result = self.nodes[0].getaccount(self.contract_address) - assert_equal(result, [f'7468.65000915@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', f'1.00000000@{self.symbolMSFT}']) + assert_equal(result, [f'7468.65000915@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', + f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', + f'1.00000000@{self.symbolMSFT}']) # Enable DFIP2203 - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/dfip2203/active':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/dfip2203/active': 'true'}}) self.nodes[0].generate(1) # Create user futures contracts - self.nodes[0].futureswap(address_googl, f'{self.prices[1]["premiumPrice"]}@{self.symbolDUSD}', int(self.idGOOGL)) + self.nodes[0].futureswap(address_googl, f'{self.prices[1]["premiumPrice"]}@{self.symbolDUSD}', + int(self.idGOOGL)) self.nodes[0].futureswap(address_tsla, f'{self.prices[0]["premiumPrice"]}@{self.symbolDUSD}', int(self.idTSLA)) self.nodes[0].generate(1) # Disable GOOGL - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{str(self.idGOOGL)}/dfip2203':'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{str(self.idGOOGL)}/dfip2203': 'false'}}) self.nodes[0].generate(1) # Only TSLA contract should remain @@ -918,11 +1025,12 @@ def check_gov_var_change(self): assert_equal(result, []) # Enable GOOGL - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{str(self.idGOOGL)}/dfip2203':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{str(self.idGOOGL)}/dfip2203': 'true'}}) self.nodes[0].generate(1) # Create user futures contracts - self.nodes[0].futureswap(address_googl, f'{self.prices[1]["premiumPrice"]}@{self.symbolDUSD}', int(self.idGOOGL)) + self.nodes[0].futureswap(address_googl, f'{self.prices[1]["premiumPrice"]}@{self.symbolDUSD}', + int(self.idGOOGL)) self.nodes[0].generate(1) # GOOGL balance should be empty @@ -930,7 +1038,7 @@ def check_gov_var_change(self): assert_equal(result, []) # Disable GOOGL - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{str(self.idGOOGL)}/dfip2203':'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{str(self.idGOOGL)}/dfip2203': 'false'}}) self.nodes[0].generate(1) # Balance should be restored @@ -938,7 +1046,8 @@ def check_gov_var_change(self): assert_equal(result, [f'{self.prices[1]["premiumPrice"]}@{self.symbolDUSD}']) # Move to next futures block - next_futures_block = self.nodes[0].getblockcount() + (self.futures_interval - (self.nodes[0].getblockcount() % self.futures_interval)) + next_futures_block = self.nodes[0].getblockcount() + ( + self.futures_interval - (self.nodes[0].getblockcount() % self.futures_interval)) self.nodes[0].generate(next_futures_block - self.nodes[0].getblockcount()) # Check all balances @@ -949,15 +1058,22 @@ def check_gov_var_change(self): # Check contract address result = self.nodes[0].getaccount(self.contract_address) - assert_equal(result, [f'8382.15000915@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', f'1.00000000@{self.symbolMSFT}']) + assert_equal(result, [f'8382.15000915@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', + f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', + f'1.00000000@{self.symbolMSFT}']) # Check DFI2203 address on listgovs result = self.nodes[0].listgovs()[8][0]['ATTRIBUTES'] - assert_equal(result['v0/live/economy/dfip2203_current'], [f'8382.15000915@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', f'1.00000000@{self.symbolMSFT}']) + assert_equal(result['v0/live/economy/dfip2203_current'], + [f'8382.15000915@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', + f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', + f'1.00000000@{self.symbolMSFT}']) # Check DFI2203 address on getburninfo result = self.nodes[0].getburninfo() - assert_equal(result['dfip2203'], [f'8382.15000915@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', f'1.00000000@{self.symbolMSFT}']) + assert_equal(result['dfip2203'], [f'8382.15000915@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', + f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', + f'1.00000000@{self.symbolMSFT}']) def unpaid_contract(self): @@ -965,7 +1081,8 @@ def unpaid_contract(self): address = self.nodes[0].getnewaddress("", "legacy") # Fund addresses - self.nodes[0].accounttoaccount(self.address, {address: f'{self.prices[0]["premiumPrice"] * 2}@{self.symbolDUSD}'}) + self.nodes[0].accounttoaccount(self.address, + {address: f'{self.prices[0]["premiumPrice"] * 2}@{self.symbolDUSD}'}) self.nodes[0].generate(1) # Create user futures contract @@ -978,12 +1095,14 @@ def unpaid_contract(self): self.nodes[0].generate(1) # Move to next futures block - next_futures_block = self.nodes[0].getblockcount() + (self.futures_interval - (self.nodes[0].getblockcount() % self.futures_interval)) + next_futures_block = self.nodes[0].getblockcount() + ( + self.futures_interval - (self.nodes[0].getblockcount() % self.futures_interval)) self.nodes[0].generate(next_futures_block - self.nodes[0].getblockcount()) # Check refund in history - result = self.nodes[0].listaccounthistory('all', {"maxBlockHeight":self.nodes[0].getblockcount(), 'depth':0, 'txtype':'w'}) - result.sort(key = sort_history, reverse = True) + result = self.nodes[0].listaccounthistory('all', {"maxBlockHeight": self.nodes[0].getblockcount(), 'depth': 0, + 'txtype': 'w'}) + result.sort(key=sort_history, reverse=True) assert_equal(result[0]['owner'], self.contract_address) assert_equal(result[0]['type'], 'FutureSwapRefund') assert_equal(result[0]['amounts'], [f'{-self.prices[0]["premiumPrice"]}@{self.symbolDUSD}']) @@ -1003,21 +1122,29 @@ def unpaid_contract(self): # Check contract address result = self.nodes[0].getaccount(self.contract_address) - assert_equal(result, [f'8382.15000915@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', f'1.00000000@{self.symbolMSFT}']) + assert_equal(result, [f'8382.15000915@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', + f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', + f'1.00000000@{self.symbolMSFT}']) # Check DFI2203 address on listgovs result = self.nodes[0].listgovs()[8][0]['ATTRIBUTES'] - assert_equal(result['v0/live/economy/dfip2203_current'], [f'8382.15000915@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', f'1.00000000@{self.symbolMSFT}']) + assert_equal(result['v0/live/economy/dfip2203_current'], + [f'8382.15000915@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', + f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', + f'1.00000000@{self.symbolMSFT}']) # Check DFI2203 address on getburninfo result = self.nodes[0].getburninfo() - assert_equal(result['dfip2203'], [f'8382.15000915@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', f'1.00000000@{self.symbolMSFT}']) + assert_equal(result['dfip2203'], [f'8382.15000915@{self.symbolDUSD}', f'1.00000000@{self.symbolTSLA}', + f'1.00000000@{self.symbolGOOGL}', f'1.00000000@{self.symbolTWTR}', + f'1.00000000@{self.symbolMSFT}']) def rpc_history(self): # Check some historical swaps for history in self.list_history: - result = self.nodes[0].listaccounthistory('all', {"maxBlockHeight":history['height'], 'depth':0, 'txtype':'q'}) + result = self.nodes[0].listaccounthistory('all', + {"maxBlockHeight": history['height'], 'depth': 0, 'txtype': 'q'}) for history_entry in history['swaps']: found = False for result_entry in result: @@ -1027,18 +1154,18 @@ def rpc_history(self): assert_equal(result_entry['type'], 'FutureSwapExecution') assert_equal(result_entry['amounts'], [history_entry['destination']]) found = True - assert(found) + assert (found) # Check all swaps present - result = self.nodes[0].listaccounthistory('all', {'txtype':'q'}) + result = self.nodes[0].listaccounthistory('all', {'txtype': 'q'}) assert_equal(len(result), 17) # Check all swap refunds present - result = self.nodes[0].listaccounthistory('all', {'txtype':'w'}) + result = self.nodes[0].listaccounthistory('all', {'txtype': 'w'}) assert_equal(len(result), 12) # Check swap by specific address - result = self.nodes[0].listaccounthistory(self.list_history[0]['swaps'][0]['address'], {'txtype':'q'}) + result = self.nodes[0].listaccounthistory(self.list_history[0]['swaps'][0]['address'], {'txtype': 'q'}) assert_equal(len(result), 1) assert_equal(result[0]['blockHeight'], self.list_history[0]['height']) assert_equal(result[0]['owner'], self.list_history[0]['swaps'][0]['address']) @@ -1064,26 +1191,29 @@ def start_block(self): self.nodes[0].generate(500 - self.nodes[0].getblockcount()) # Test setting start block while DFIP2203 still active - assert_raises_rpc_error(-32600, 'Cannot set block period while DFIP2203 is active', self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2203/start_block':f'{self.nodes[0].getblockcount() + 1}'}}) + assert_raises_rpc_error(-32600, 'Cannot set block period while DFIP2203 is active', self.nodes[0].setgov, { + "ATTRIBUTES": {'v0/params/dfip2203/start_block': f'{self.nodes[0].getblockcount() + 1}'}}) # Disable DFIP2203 - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/dfip2203/active':'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/dfip2203/active': 'false'}}) self.nodes[0].generate(1) # Set start block height self.start_block = self.nodes[0].getblockcount() + 10 - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/dfip2203/start_block':f'{self.start_block}'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/dfip2203/start_block': f'{self.start_block}'}}) self.nodes[0].generate(1) # Enable DFIP2203 - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/dfip2203/active':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/dfip2203/active': 'true'}}) self.nodes[0].generate(1) # Test cannot create a future swap until active - assert_raises_rpc_error(-32600, f'DFIP2203 not active until block {self.start_block}', self.nodes[0].futureswap, address, f'{self.prices[0]["premiumPrice"]}@{self.symbolDUSD}', int(self.idTSLA)) + assert_raises_rpc_error(-32600, f'DFIP2203 not active until block {self.start_block}', self.nodes[0].futureswap, + address, f'{self.prices[0]["premiumPrice"]}@{self.symbolDUSD}', int(self.idTSLA)) # Check next future swap block reported correctly via RPC - next_futures_block = self.nodes[0].getblockcount() + (self.futures_interval - ((self.nodes[0].getblockcount() - self.start_block) % self.futures_interval)) + self.futures_interval + next_futures_block = self.nodes[0].getblockcount() + (self.futures_interval - ( + (self.nodes[0].getblockcount() - self.start_block) % self.futures_interval)) + self.futures_interval assert_equal(next_futures_block, self.nodes[0].getfutureswapblock()) # Move to futures start height @@ -1094,7 +1224,8 @@ def start_block(self): self.nodes[0].generate(1) # Move to one before next future swap block - next_futures_block = self.nodes[0].getblockcount() + (self.futures_interval - ((self.nodes[0].getblockcount() - self.start_block) % self.futures_interval)) + next_futures_block = self.nodes[0].getblockcount() + (self.futures_interval - ( + (self.nodes[0].getblockcount() - self.start_block) % self.futures_interval)) self.nodes[0].generate(next_futures_block - self.nodes[0].getblockcount() - 1) # Check calculation is correct for second swap height after setting start block @@ -1121,14 +1252,15 @@ def dfi_to_dusd(self): self.nodes[0].generate(1) # Test swap before DFIP2206F defined - assert_raises_rpc_error(-32600, f'DFIP2206F not currently active', self.nodes[0].futureswap, address, f'1@{self.symbolDFI}') + assert_raises_rpc_error(-32600, f'DFIP2206F not currently active', self.nodes[0].futureswap, address, + f'1@{self.symbolDFI}') # Define DFI-to-DUSD swap period and start block self.futures_interval_dusd = 10 self.start_block_dusd = self.nodes[0].getblockcount() + 10 # Set DFI-to-DUSD Gov vars - self.nodes[0].setgov({"ATTRIBUTES":{ + self.nodes[0].setgov({"ATTRIBUTES": { 'v0/params/dfip2206f/reward_pct': '0.01', 'v0/params/dfip2206f/block_period': f'{self.futures_interval_dusd}', 'v0/params/dfip2206f/start_block': f'{self.start_block_dusd}' @@ -1136,7 +1268,7 @@ def dfi_to_dusd(self): self.nodes[0].generate(1) # Enable DFIP2206F - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/dfip2206f/active':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/dfip2206f/active': 'true'}}) self.nodes[0].generate(1) # Verify Gov vars @@ -1148,18 +1280,24 @@ def dfi_to_dusd(self): assert_equal(result['v0/params/dfip2206f/start_block'], f'{self.start_block_dusd}') # Test cannot create a future swap until active - assert_raises_rpc_error(-32600, f'DFIP2206F not active until block {self.start_block_dusd}', self.nodes[0].futureswap, address, f'1@{self.symbolDFI}', f'{self.symbolDUSD}') + assert_raises_rpc_error(-32600, f'DFIP2206F not active until block {self.start_block_dusd}', + self.nodes[0].futureswap, address, f'1@{self.symbolDFI}', f'{self.symbolDUSD}') # Check next future swap block reported correctly via RPC - next_futures_block = self.nodes[0].getblockcount() + (self.futures_interval_dusd - ((self.nodes[0].getblockcount() - self.start_block_dusd) % self.futures_interval_dusd)) + self.futures_interval_dusd + next_futures_block = self.nodes[0].getblockcount() + (self.futures_interval_dusd - ((self.nodes[ + 0].getblockcount() - self.start_block_dusd) % self.futures_interval_dusd)) + self.futures_interval_dusd assert_equal(next_futures_block, self.nodes[0].getdusdswapblock()) # Move to futures start height self.nodes[0].generate(next_futures_block - self.nodes[0].getblockcount()) # Check error when DUSD destination not set or incorrect - assert_raises_rpc_error(-32600, f'Incorrect destination defined for DFI swap, DUSD destination expected id: {self.idDUSD}', self.nodes[0].futureswap, address, f'1@{self.symbolDFI}') - assert_raises_rpc_error(-32600, f'Incorrect destination defined for DFI swap, DUSD destination expected id: {self.idDUSD}', self.nodes[0].futureswap, address, f'1@{self.symbolDFI}', f'{self.symbolGOOGL}') + assert_raises_rpc_error(-32600, + f'Incorrect destination defined for DFI swap, DUSD destination expected id: {self.idDUSD}', + self.nodes[0].futureswap, address, f'1@{self.symbolDFI}') + assert_raises_rpc_error(-32600, + f'Incorrect destination defined for DFI swap, DUSD destination expected id: {self.idDUSD}', + self.nodes[0].futureswap, address, f'1@{self.symbolDFI}', f'{self.symbolGOOGL}') # Test swap of DFI to DUSD self.nodes[0].futureswap(address, f'1@{self.symbolDFI}', f'{self.symbolDUSD}') @@ -1177,11 +1315,13 @@ def dfi_to_dusd(self): assert_equal(result['amount'], Decimal('1.00000000')) # Move to swap height - next_futures_block = self.nodes[0].getblockcount() + (self.futures_interval_dusd - ((self.nodes[0].getblockcount() - self.start_block_dusd) % self.futures_interval_dusd)) + next_futures_block = self.nodes[0].getblockcount() + (self.futures_interval_dusd - ( + (self.nodes[0].getblockcount() - self.start_block_dusd) % self.futures_interval_dusd)) self.nodes[0].generate(next_futures_block - self.nodes[0].getblockcount()) # Check swap in history - result = self.nodes[0].listaccounthistory('all', {"maxBlockHeight":self.nodes[0].getblockcount(), 'depth':1, 'txtype':'q'}) + result = self.nodes[0].listaccounthistory('all', {"maxBlockHeight": self.nodes[0].getblockcount(), 'depth': 1, + 'txtype': 'q'}) assert_equal(result[0]['owner'], address) assert_equal(result[0]['type'], 'FutureSwapExecution') assert_equal(result[0]['amounts'], [f'0.99000000@{self.symbolDUSD}']) @@ -1197,7 +1337,7 @@ def dfi_to_dusd(self): assert_equal(get, {}) # Test swap when DFIP2203 disabled - self.nodes[0].setgov({"ATTRIBUTES":{ + self.nodes[0].setgov({"ATTRIBUTES": { 'v0/params/dfip2203/active': 'false', }}) self.nodes[0].generate(1) @@ -1207,7 +1347,8 @@ def dfi_to_dusd(self): self.nodes[0].generate(1) # Move to swap height - next_futures_block = self.nodes[0].getblockcount() + (self.futures_interval_dusd - ((self.nodes[0].getblockcount() - self.start_block_dusd) % self.futures_interval_dusd)) + next_futures_block = self.nodes[0].getblockcount() + (self.futures_interval_dusd - ( + (self.nodes[0].getblockcount() - self.start_block_dusd) % self.futures_interval_dusd)) self.nodes[0].generate(next_futures_block - self.nodes[0].getblockcount()) # Check result @@ -1243,7 +1384,8 @@ def check_withdrawals_dusd(self): self.nodes[0].generate(1) # Check withdrawal failures - assert_raises_rpc_error(-32600, 'amount 2.00000000 is less than 2.00000001', self.nodes[0].withdrawfutureswap, address, f'2.00000001@{self.symbolDFI}', self.symbolDUSD) + assert_raises_rpc_error(-32600, 'amount 2.00000000 is less than 2.00000001', self.nodes[0].withdrawfutureswap, + address, f'2.00000001@{self.symbolDFI}', self.symbolDUSD) # Withdraw both contracts self.nodes[0].withdrawfutureswap(address, f'2.00000000@{self.symbolDFI}', self.symbolDUSD) @@ -1254,7 +1396,8 @@ def check_withdrawals_dusd(self): assert_equal(result, {}) # Try and withdraw smallest amount now contract empty - assert_raises_rpc_error(-32600, 'amount 0.00000000 is less than 0.00000001', self.nodes[0].withdrawfutureswap, address, f'0.00000001@{self.symbolDFI}', self.symbolDUSD) + assert_raises_rpc_error(-32600, 'amount 0.00000000 is less than 0.00000001', self.nodes[0].withdrawfutureswap, + address, f'0.00000001@{self.symbolDFI}', self.symbolDUSD) # Create new future swap self.nodes[0].futureswap(address, f'1@{self.symbolDFI}', f'{self.symbolDUSD}') @@ -1270,7 +1413,8 @@ def check_withdrawals_dusd(self): assert_equal(result['amount'], Decimal('0.00000001')) # Move to swap height - next_futures_block = self.nodes[0].getblockcount() + (self.futures_interval_dusd - ((self.nodes[0].getblockcount() - self.start_block_dusd) % self.futures_interval_dusd)) + next_futures_block = self.nodes[0].getblockcount() + (self.futures_interval_dusd - ( + (self.nodes[0].getblockcount() - self.start_block_dusd) % self.futures_interval_dusd)) self.nodes[0].generate(next_futures_block - self.nodes[0].getblockcount()) # Check result, should just be DFI @@ -1310,7 +1454,8 @@ def check_withdrawals_dusd(self): assert_equal(result['amount'], Decimal('0.00000002')) # Move to swap height - next_futures_block = self.nodes[0].getblockcount() + (self.futures_interval_dusd - ((self.nodes[0].getblockcount() - self.start_block_dusd) % self.futures_interval_dusd)) + next_futures_block = self.nodes[0].getblockcount() + (self.futures_interval_dusd - ( + (self.nodes[0].getblockcount() - self.start_block_dusd) % self.futures_interval_dusd)) self.nodes[0].generate(next_futures_block - self.nodes[0].getblockcount()) # Check result. @@ -1325,7 +1470,8 @@ def check_withdrawals_dusd(self): result = self.nodes[0].listgovs()[8][0]['ATTRIBUTES'] assert_equal(result['v0/live/economy/dfip2206f_current'], [f'2.00000003@{self.symbolDFI}']) assert_equal(result['v0/live/economy/dfip2206f_burned'], [f'2.00000003@{self.symbolDFI}']) - assert_equal(result['v0/live/economy/dfip2206f_minted'], [f'{Decimal("0.99000000") * 2 + Decimal("0.00000001")}@{self.symbolDUSD}']) + assert_equal(result['v0/live/economy/dfip2206f_minted'], + [f'{Decimal("0.99000000") * 2 + Decimal("0.00000001")}@{self.symbolDUSD}']) # Check burn info result = self.nodes[0].getburninfo() @@ -1353,7 +1499,8 @@ def unpaid_contract_dusd(self): assert_equal(result, []) # Move to next futures block - next_futures_block = self.nodes[0].getblockcount() + (self.futures_interval_dusd - ((self.nodes[0].getblockcount() - self.start_block_dusd) % self.futures_interval_dusd)) + next_futures_block = self.nodes[0].getblockcount() + (self.futures_interval_dusd - ( + (self.nodes[0].getblockcount() - self.start_block_dusd) % self.futures_interval_dusd)) self.nodes[0].generate(next_futures_block - self.nodes[0].getblockcount()) # Check user has been refunded @@ -1361,8 +1508,9 @@ def unpaid_contract_dusd(self): assert_equal(result, [f'1.00000000@{self.symbolDFI}']) # Check refund in history - result = self.nodes[0].listaccounthistory('all', {"maxBlockHeight":self.nodes[0].getblockcount(), 'depth':1, 'txtype':'w'}) - result.sort(key = sort_history, reverse = True) + result = self.nodes[0].listaccounthistory('all', {"maxBlockHeight": self.nodes[0].getblockcount(), 'depth': 1, + 'txtype': 'w'}) + result.sort(key=sort_history, reverse=True) assert_equal(result[0]['owner'], self.contract_address_dusd) assert_equal(result[0]['type'], 'FutureSwapRefund') assert_equal(result[0]['amounts'], [f'-1.00000000@{self.symbolDFI}']) @@ -1378,11 +1526,13 @@ def unpaid_contract_dusd(self): result = self.nodes[0].listgovs()[8][0]['ATTRIBUTES'] assert_equal(result['v0/live/economy/dfip2206f_current'], [f'2.00000003@{self.symbolDFI}']) assert_equal(result['v0/live/economy/dfip2206f_burned'], [f'2.00000003@{self.symbolDFI}']) - assert_equal(result['v0/live/economy/dfip2206f_minted'], [f'{Decimal("0.99000000") * 2 + Decimal("0.00000001")}@{self.symbolDUSD}']) + assert_equal(result['v0/live/economy/dfip2206f_minted'], + [f'{Decimal("0.99000000") * 2 + Decimal("0.00000001")}@{self.symbolDUSD}']) # Check burn info result = self.nodes[0].getburninfo() assert_equal(result['dfip2206f'], [f'2.00000003@{self.symbolDFI}']) + if __name__ == '__main__': FuturesTest().main() diff --git a/test/functional/feature_help.py b/test/functional/feature_help.py index 52f2ad4951..e61654a73a 100755 --- a/test/functional/feature_help.py +++ b/test/functional/feature_help.py @@ -7,6 +7,7 @@ from test_framework.test_framework import DefiTestFramework from test_framework.util import assert_equal + class HelpTest(DefiTestFramework): def set_test_params(self): self.setup_clean_chain = True diff --git a/test/functional/feature_higher_collateral_factor.py b/test/functional/feature_higher_collateral_factor.py index 8fa8b56582..309f16ec23 100755 --- a/test/functional/feature_higher_collateral_factor.py +++ b/test/functional/feature_higher_collateral_factor.py @@ -11,11 +11,16 @@ from decimal import Decimal import time + class DUSDCollateralFactorTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True - self.extra_args = [['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-bayfrontgardensheight=1', '-eunosheight=1', '-txindex=1', '-fortcanningheight=1', '-fortcanningroadheight=1', '-fortcanninghillheight=1', '-fortcanningcrunchheight=1', '-fortcanninggreatworldheight=1', '-fortcanningepilogueheight=200', '-jellyfish_regtest=1']] + self.extra_args = [ + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-bayfrontgardensheight=1', '-eunosheight=1', + '-txindex=1', '-fortcanningheight=1', '-fortcanningroadheight=1', '-fortcanninghillheight=1', + '-fortcanningcrunchheight=1', '-fortcanninggreatworldheight=1', '-fortcanningepilogueheight=200', + '-jellyfish_regtest=1']] def run_test(self): # Setup @@ -109,9 +114,9 @@ def setup(self): self.nodes[0].generate(1) def set_collateral_factor(self): - # Test setting new token factor before fork - assert_raises_rpc_error(-32600, "Percentage exceeds 100%", self.nodes[0].setgov, {"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_collateral_factor': '1.49'}}) + assert_raises_rpc_error(-32600, "Percentage exceeds 100%", self.nodes[0].setgov, + {"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_collateral_factor': '1.49'}}) # Move to fork self.nodes[0].generate(200 - self.nodes[0].getblockcount()) @@ -121,10 +126,12 @@ def set_collateral_factor(self): self.nodes[0].generate(1) # Test setting higher than the lowest scheme rate - assert_raises_rpc_error(-32600, "Factor cannot be more than or equal to the lowest scheme rate of 1.50000000", self.nodes[0].setgov, {"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_collateral_factor': '1.50'}}) + assert_raises_rpc_error(-32600, "Factor cannot be more than or equal to the lowest scheme rate of 1.50000000", + self.nodes[0].setgov, + {"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_collateral_factor': '1.50'}}) # Now set new token factor - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_collateral_factor': '1.49'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_collateral_factor': '1.49'}}) self.nodes[0].generate(1) # Check results @@ -132,7 +139,6 @@ def set_collateral_factor(self): assert_equal(attributes['v0/token/1/loan_collateral_factor'], '1.49') def take_dusd_loan(self): - # Create vault vault_address = self.nodes[0].getnewaddress('', 'legacy') vault_id = self.nodes[0].createvault(vault_address, 'LOAN001') @@ -145,7 +151,7 @@ def take_dusd_loan(self): self.nodes[0].generate(1) # Take DUSD loan greater than collateral amount - self.nodes[0].takeloan({ "vaultId": vault_id, "amounts": f"2.98@{self.symbolDUSD}"}) + self.nodes[0].takeloan({"vaultId": vault_id, "amounts": f"2.98@{self.symbolDUSD}"}) self.nodes[0].generate(1) # Check that we are on 150% collateral ratio @@ -156,7 +162,6 @@ def take_dusd_loan(self): assert_equal(vault['loanValue'], Decimal('2.98000000')) def take_multiple_loans(self): - # Create vault vault_address = self.nodes[0].getnewaddress('', 'legacy') vault_id = self.nodes[0].createvault(vault_address, 'LOAN001') @@ -169,7 +174,7 @@ def take_multiple_loans(self): self.nodes[0].generate(1) # Take TSLA loan for half the available ratio - self.nodes[0].takeloan({ "vaultId": vault_id, "amounts": f"1@{self.symbolTSLA}"}) + self.nodes[0].takeloan({"vaultId": vault_id, "amounts": f"1@{self.symbolTSLA}"}) self.nodes[0].generate(1) # Check that we are on 300% collateral ratio @@ -180,7 +185,7 @@ def take_multiple_loans(self): assert_equal(vault['loanValue'], Decimal('1.00000000')) # Take a DUSD loan - self.nodes[0].takeloan({ "vaultId": vault_id, "amounts": f"1@{self.symbolDUSD}"}) + self.nodes[0].takeloan({"vaultId": vault_id, "amounts": f"1@{self.symbolDUSD}"}) self.nodes[0].generate(1) # Check that vault still has capacity to take more loans @@ -190,6 +195,6 @@ def take_multiple_loans(self): assert_equal(vault['informativeRatio'], Decimal('186.75000000')) assert_equal(vault['collateralRatio'], 187) + if __name__ == '__main__': DUSDCollateralFactorTest().main() - diff --git a/test/functional/feature_icx_orderbook.py b/test/functional/feature_icx_orderbook.py index 3998b51782..e8001fc9b9 100755 --- a/test/functional/feature_icx_orderbook.py +++ b/test/functional/feature_icx_orderbook.py @@ -11,16 +11,19 @@ from decimal import Decimal -class ICXOrderbookTest (DefiTestFramework): + +class ICXOrderbookTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 self.setup_clean_chain = True self.extra_args = [ - ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-eunosheight=50', '-eunospayaheight=50', '-txindex=1'], - ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-eunosheight=50', '-eunospayaheight=50', '-txindex=1']] + ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-eunosheight=50', '-eunospayaheight=50', + '-txindex=1'], + ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-eunosheight=50', '-eunospayaheight=50', + '-txindex=1']] def run_test(self): - assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI + assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI # Burn address burn_address = "mfburnZSAM7Gs1hpDeNaMotJXSGA7edosG" @@ -85,8 +88,8 @@ def run_test(self): # check tokens id pool = self.nodes[0].getpoolpair("BTC-DFI") idDFIBTC = list(self.nodes[0].gettoken("BTC-DFI").keys())[0] - assert(pool[idDFIBTC]['idTokenA'] == idBTC) - assert(pool[idDFIBTC]['idTokenB'] == idDFI) + assert (pool[idDFIBTC]['idTokenA'] == idBTC) + assert (pool[idDFIBTC]['idTokenB'] == idDFI) # transfer self.nodes[0].addpoolliquidity({ @@ -96,7 +99,7 @@ def run_test(self): assert_equal(len(self.nodes[0].getaccount(accountDFI, {}, True)), 2) - self.nodes[0].setgov({"ICX_TAKERFEE_PER_BTC":Decimal('0.001')}) + self.nodes[0].setgov({"ICX_TAKERFEE_PER_BTC": Decimal('0.001')}) self.nodes[0].generate(1) @@ -106,12 +109,12 @@ def run_test(self): # DFI/BTC Open and close an order orderTx = self.nodes[0].icx_createorder({ - 'tokenFrom': idDFI, - 'chainTo': "BTC", - 'ownerAddress': accountDFI, - 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941', - 'amountFrom': 15, - 'orderPrice':0.01})["txid"] + 'tokenFrom': idDFI, + 'chainTo': "BTC", + 'ownerAddress': accountDFI, + 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941', + 'amountFrom': 15, + 'orderPrice': 0.01})["txid"] self.nodes[0].generate(1) self.sync_blocks() @@ -123,7 +126,8 @@ def run_test(self): assert_equal(order[orderTx]["tokenFrom"], symbolDFI) assert_equal(order[orderTx]["chainTo"], "BTC") assert_equal(order[orderTx]["ownerAddress"], accountDFI) - assert_equal(order[orderTx]["receivePubkey"], '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941') + assert_equal(order[orderTx]["receivePubkey"], + '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941') assert_equal(order[orderTx]["amountFrom"], Decimal('15')) assert_equal(order[orderTx]["amountToFill"], Decimal('15')) assert_equal(order[orderTx]["orderPrice"], Decimal('0.01000000')) @@ -133,9 +137,9 @@ def run_test(self): beforeOffer = self.nodes[1].getaccount(accountBTC, {}, True)[idDFI] offerTx = self.nodes[1].icx_makeoffer({ - 'orderTx': orderTx, - 'amount': 0.10, - 'ownerAddress': accountBTC})["txid"] + 'orderTx': orderTx, + 'amount': 0.10, + 'ownerAddress': accountBTC})["txid"] self.nodes[1].generate(1) self.sync_blocks() @@ -158,7 +162,7 @@ def run_test(self): for vout in authTx['vout']: if 'addresses' in vout['scriptPubKey'] and vout['scriptPubKey']['addresses'][0] == accountBTC: found = True - assert(found) + assert (found) self.nodes[1].generate(1) self.sync_blocks() @@ -185,7 +189,7 @@ def run_test(self): for vout in authTx['vout']: if 'addresses' in vout['scriptPubKey'] and vout['scriptPubKey']['addresses'][0] == accountDFI: found = True - assert(found) + assert (found) self.nodes[0].generate(1) self.sync_blocks() @@ -201,11 +205,11 @@ def run_test(self): # BTC/DFI Open and close an order orderTx = self.nodes[0].icx_createorder({ - 'chainFrom': "BTC", - 'tokenTo': idDFI, - 'ownerAddress': accountDFI, - 'amountFrom': 2, - 'orderPrice':100})["txid"] + 'chainFrom': "BTC", + 'tokenTo': idDFI, + 'ownerAddress': accountDFI, + 'amountFrom': 2, + 'orderPrice': 100})["txid"] self.nodes[0].generate(1) self.sync_blocks() @@ -213,10 +217,10 @@ def run_test(self): beforeOffer = self.nodes[1].getaccount(accountBTC, {}, True)[idDFI] offerTx = self.nodes[1].icx_makeoffer({ - 'orderTx': orderTx, - 'amount': 10, - 'ownerAddress': accountBTC, - 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941'})["txid"] + 'orderTx': orderTx, + 'amount': 10, + 'ownerAddress': accountBTC, + 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941'})["txid"] self.nodes[1].generate(1) self.sync_blocks() @@ -235,7 +239,7 @@ def run_test(self): for vout in authTx['vout']: if 'addresses' in vout['scriptPubKey'] and vout['scriptPubKey']['addresses'][0] == accountBTC: found = True - assert(found) + assert (found) self.nodes[1].generate(1) self.sync_blocks() @@ -258,7 +262,7 @@ def run_test(self): for vout in authTx['vout']: if 'addresses' in vout['scriptPubKey'] and vout['scriptPubKey']['addresses'][0] == accountDFI: found = True - assert(found) + assert (found) self.nodes[0].generate(1) self.sync_blocks() @@ -267,19 +271,18 @@ def run_test(self): assert_equal(len(order), 1) - # DFI/BTC scenario # Open an order beforeOrder = self.nodes[0].getaccount(accountDFI, {}, True)[idDFI] orderTx = self.nodes[0].icx_createorder({ - 'tokenFrom': idDFI, - 'chainTo': "BTC", - 'ownerAddress': accountDFI, - 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941', - 'amountFrom': 15, - 'orderPrice':0.01})["txid"] + 'tokenFrom': idDFI, + 'chainTo': "BTC", + 'ownerAddress': accountDFI, + 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941', + 'amountFrom': 15, + 'orderPrice': 0.01})["txid"] self.nodes[0].generate(1) self.sync_blocks() @@ -292,7 +295,8 @@ def run_test(self): assert_equal(order[orderTx]["tokenFrom"], symbolDFI) assert_equal(order[orderTx]["chainTo"], "BTC") assert_equal(order[orderTx]["ownerAddress"], accountDFI) - assert_equal(order[orderTx]["receivePubkey"], '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941') + assert_equal(order[orderTx]["receivePubkey"], + '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941') assert_equal(order[orderTx]["amountFrom"], Decimal('15')) assert_equal(order[orderTx]["amountToFill"], Decimal('15')) assert_equal(order[orderTx]["orderPrice"], Decimal('0.01000000')) @@ -302,9 +306,9 @@ def run_test(self): beforeOffer = self.nodes[1].getaccount(accountBTC, {}, True)[idDFI] offerTx = self.nodes[1].icx_makeoffer({ - 'orderTx': orderTx, - 'amount': 0.10, - 'ownerAddress': accountBTC})["txid"] + 'orderTx': orderTx, + 'amount': 0.10, + 'ownerAddress': accountBTC})["txid"] self.nodes[1].generate(1) self.sync_blocks() @@ -323,9 +327,9 @@ def run_test(self): beforeDFCHTLC = self.nodes[0].getaccount(accountDFI, {}, True)[idDFI] dfchtlcTx = self.nodes[0].icx_submitdfchtlc({ - 'offerTx': offerTx, - 'amount': 10, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220'})["txid"] + 'offerTx': offerTx, + 'amount': 10, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220'})["txid"] self.nodes[0].generate(1) self.sync_blocks() @@ -351,12 +355,12 @@ def run_test(self): assert_equal(htlcs[dfchtlcTx]["timeout"], 1440) exthtlcTx = self.nodes[1].icx_submitexthtlc({ - 'offerTx': offerTx, - 'amount': 0.10, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', - 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', - 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', - 'timeout': 24})["txid"] + 'offerTx': offerTx, + 'amount': 0.10, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', + 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', + 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', + 'timeout': 24})["txid"] self.nodes[1].generate(1) self.sync_blocks() @@ -371,22 +375,23 @@ def run_test(self): assert_equal(htlcs[exthtlcTx]["amountInDFCAsset"], Decimal('10.00000000')) assert_equal(htlcs[exthtlcTx]["hash"], '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220') assert_equal(htlcs[exthtlcTx]["htlcScriptAddress"], '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N') - assert_equal(htlcs[exthtlcTx]["ownerPubkey"], '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252') + assert_equal(htlcs[exthtlcTx]["ownerPubkey"], + '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252') assert_equal(htlcs[exthtlcTx]["timeout"], 24) beforeClaim0 = self.nodes[0].getaccount(accountDFI, {}, True)[idDFI] beforeClaim1 = self.nodes[1].getaccount(accountBTC, {}, True)[idDFI] claimTx = self.nodes[1].icx_claimdfchtlc({ - 'dfchtlcTx': dfchtlcTx, - 'seed': 'f75a61ad8f7a6e0ab701d5be1f5d4523a9b534571e4e92e0c4610c6a6784ccef'})["txid"] + 'dfchtlcTx': dfchtlcTx, + 'seed': 'f75a61ad8f7a6e0ab701d5be1f5d4523a9b534571e4e92e0c4610c6a6784ccef'})["txid"] self.nodes[1].generate(1) self.sync_blocks() htlcs = self.nodes[0].icx_listhtlcs({ - "offerTx": offerTx, - "closed": True}) + "offerTx": offerTx, + "closed": True}) assert_equal(len(htlcs), 4) assert_equal(htlcs[claimTx]["type"], 'CLAIM DFC') @@ -416,18 +421,18 @@ def run_test(self): assert_equal(order[orderTx]["tokenFrom"], symbolDFI) assert_equal(order[orderTx]["chainTo"], "BTC") assert_equal(order[orderTx]["ownerAddress"], accountDFI) - assert_equal(order[orderTx]["receivePubkey"], '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941') + assert_equal(order[orderTx]["receivePubkey"], + '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941') assert_equal(order[orderTx]["amountFrom"], Decimal('15')) assert_equal(order[orderTx]["amountToFill"], Decimal('5')) assert_equal(order[orderTx]["orderPrice"], Decimal('0.01000000')) assert_equal(order[orderTx]["amountToFillInToAsset"], Decimal('0.0500000')) - # Make offer for more than is available to test partial fill offerTx = self.nodes[1].icx_makeoffer({ - 'orderTx': orderTx, - 'amount': 0.10, - 'ownerAddress': accountBTC})["txid"] + 'orderTx': orderTx, + 'amount': 0.10, + 'ownerAddress': accountBTC})["txid"] self.nodes[1].generate(1) self.sync_blocks() @@ -440,11 +445,10 @@ def run_test(self): assert_equal(offer[offerTx]["takerFee"], Decimal('0.01000000')) assert_equal(offer[offerTx]["expireHeight"], self.nodes[0].getblockchaininfo()["blocks"] + 20) - dfchtlcTx = self.nodes[0].icx_submitdfchtlc({ - 'offerTx': offerTx, - 'amount': 5, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220'})["txid"] + 'offerTx': offerTx, + 'amount': 5, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220'})["txid"] self.nodes[0].generate(1) self.sync_blocks() @@ -468,12 +472,12 @@ def run_test(self): assert_equal(htlcs[dfchtlcTx]["timeout"], 1440) exthtlcTx = self.nodes[1].icx_submitexthtlc({ - 'offerTx': offerTx, - 'amount': 0.05, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', - 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', - 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', - 'timeout': 24})["txid"] + 'offerTx': offerTx, + 'amount': 0.05, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', + 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', + 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', + 'timeout': 24})["txid"] self.nodes[1].generate(1) self.sync_blocks() @@ -488,22 +492,23 @@ def run_test(self): assert_equal(htlcs[exthtlcTx]["amountInDFCAsset"], Decimal('5.00000000')) assert_equal(htlcs[exthtlcTx]["hash"], '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220') assert_equal(htlcs[exthtlcTx]["htlcScriptAddress"], '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N') - assert_equal(htlcs[exthtlcTx]["ownerPubkey"], '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252') + assert_equal(htlcs[exthtlcTx]["ownerPubkey"], + '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252') assert_equal(htlcs[exthtlcTx]["timeout"], 24) beforeClaim0 = self.nodes[0].getaccount(accountDFI, {}, True)[idDFI] beforeClaim1 = self.nodes[1].getaccount(accountBTC, {}, True)[idDFI] claimTx = self.nodes[1].icx_claimdfchtlc({ - 'dfchtlcTx': dfchtlcTx, - 'seed': 'f75a61ad8f7a6e0ab701d5be1f5d4523a9b534571e4e92e0c4610c6a6784ccef'})["txid"] + 'dfchtlcTx': dfchtlcTx, + 'seed': 'f75a61ad8f7a6e0ab701d5be1f5d4523a9b534571e4e92e0c4610c6a6784ccef'})["txid"] self.nodes[1].generate(1) self.sync_blocks() htlcs = self.nodes[0].icx_listhtlcs({ - "offerTx": offerTx, - "closed": True}) + "offerTx": offerTx, + "closed": True}) assert_equal(len(htlcs), 4) assert_equal(htlcs[claimTx]["type"], 'CLAIM DFC') @@ -533,11 +538,11 @@ def run_test(self): # Open an order orderTx = self.nodes[0].icx_createorder({ - 'chainFrom': "BTC", - 'tokenTo': idDFI, - 'ownerAddress': accountDFI, - 'amountFrom': 2, - 'orderPrice':1000})["txid"] + 'chainFrom': "BTC", + 'tokenTo': idDFI, + 'ownerAddress': accountDFI, + 'amountFrom': 2, + 'orderPrice': 1000})["txid"] self.nodes[0].generate(1) self.sync_blocks() @@ -557,10 +562,10 @@ def run_test(self): beforeOffer = self.nodes[1].getaccount(accountBTC, {}, True)[idDFI] offerTx = self.nodes[1].icx_makeoffer({ - 'orderTx': orderTx, - 'amount': 3000, - 'ownerAddress': accountBTC, - 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941'})["txid"] + 'orderTx': orderTx, + 'amount': 3000, + 'ownerAddress': accountBTC, + 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941'})["txid"] self.nodes[1].generate(1) self.sync_blocks() @@ -573,18 +578,18 @@ def run_test(self): assert_equal(offer[offerTx]["orderTx"], orderTx) assert_equal(offer[offerTx]["amount"], Decimal('3000.00000000')) assert_equal(offer[offerTx]["ownerAddress"], accountBTC) - assert_equal(offer[offerTx]["receivePubkey"], '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941') + assert_equal(offer[offerTx]["receivePubkey"], + '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941') assert_equal(offer[offerTx]["takerFee"], Decimal('0.30000000')) assert_equal(offer[offerTx]["expireHeight"], self.nodes[0].getblockchaininfo()["blocks"] + 20) - exthtlcTx = self.nodes[0].icx_submitexthtlc({ - 'offerTx': offerTx, - 'amount': 2, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', - 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', - 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', - 'timeout': 72})["txid"] + 'offerTx': offerTx, + 'amount': 2, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', + 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', + 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', + 'timeout': 72})["txid"] self.nodes[0].generate(1) self.sync_blocks() @@ -608,13 +613,14 @@ def run_test(self): assert_equal(htlcs[exthtlcTx]["amountInDFCAsset"], Decimal('2000.00000000')) assert_equal(htlcs[exthtlcTx]["hash"], '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220') assert_equal(htlcs[exthtlcTx]["htlcScriptAddress"], '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N') - assert_equal(htlcs[exthtlcTx]["ownerPubkey"], '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252') + assert_equal(htlcs[exthtlcTx]["ownerPubkey"], + '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252') assert_equal(htlcs[exthtlcTx]["timeout"], 72) dfchtlcTx = self.nodes[1].icx_submitdfchtlc({ - 'offerTx': offerTx, - 'amount': 2000, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220'})["txid"] + 'offerTx': offerTx, + 'amount': 2000, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220'})["txid"] self.nodes[1].generate(1) self.sync_blocks() @@ -630,18 +636,17 @@ def run_test(self): assert_equal(htlcs[dfchtlcTx]["hash"], '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220') assert_equal(htlcs[dfchtlcTx]["timeout"], 480) - beforeClaim = self.nodes[0].getaccount(accountDFI, {}, True)[idDFI] claimTx = self.nodes[0].icx_claimdfchtlc({ - 'dfchtlcTx': dfchtlcTx, - 'seed': 'f75a61ad8f7a6e0ab701d5be1f5d4523a9b534571e4e92e0c4610c6a6784ccef'})["txid"] + 'dfchtlcTx': dfchtlcTx, + 'seed': 'f75a61ad8f7a6e0ab701d5be1f5d4523a9b534571e4e92e0c4610c6a6784ccef'})["txid"] self.nodes[0].generate(1) self.sync_blocks() htlcs = self.nodes[0].icx_listhtlcs({ - "offerTx": offerTx, - "closed": True}) + "offerTx": offerTx, + "closed": True}) assert_equal(len(htlcs), 4) assert_equal(htlcs[claimTx]["type"], 'CLAIM DFC') @@ -651,7 +656,8 @@ def run_test(self): assert_equal(htlcs[dfchtlcTx]["status"], 'CLAIMED') # claimed DFI + refunded makerDeposit + makerIncentive on maker address - assert_equal(self.nodes[0].getaccount(accountDFI, {}, True)[idDFI], beforeClaim + Decimal('2000.00000000') + Decimal('0.25000000')) + assert_equal(self.nodes[0].getaccount(accountDFI, {}, True)[idDFI], + beforeClaim + Decimal('2000.00000000') + Decimal('0.25000000')) # Make sure offer and order are now closed offer = self.nodes[0].icx_listorders({"orderTx": orderTx}) @@ -661,15 +667,14 @@ def run_test(self): order = self.nodes[0].icx_listorders({"closed": True}) assert_equal(order[orderTx]["status"], 'FILLED') - # DFI/BTC partial offer acceptance orderTx = self.nodes[0].icx_createorder({ - 'tokenFrom': idDFI, - 'chainTo': "BTC", - 'ownerAddress': accountDFI, - 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941', - 'amountFrom': 15, - 'orderPrice':0.01})["txid"] + 'tokenFrom': idDFI, + 'chainTo': "BTC", + 'ownerAddress': accountDFI, + 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941', + 'amountFrom': 15, + 'orderPrice': 0.01})["txid"] self.nodes[0].generate(1) self.sync_blocks() @@ -677,9 +682,9 @@ def run_test(self): beforeOffer = self.nodes[1].getaccount(accountBTC, {}, True)[idDFI] offerTx = self.nodes[1].icx_makeoffer({ - 'orderTx': orderTx, - 'amount': 1, - 'ownerAddress': accountBTC})["txid"] + 'orderTx': orderTx, + 'amount': 1, + 'ownerAddress': accountBTC})["txid"] self.nodes[1].generate(1) self.sync_blocks() @@ -694,9 +699,9 @@ def run_test(self): assert_equal(offer[offerTx]["takerFee"], Decimal('0.10000000')) dfchtlcTx = self.nodes[0].icx_submitdfchtlc({ - 'offerTx': offerTx, - 'amount': 15, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220'})["txid"] + 'offerTx': offerTx, + 'amount': 15, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220'})["txid"] self.nodes[0].generate(1) self.sync_blocks() @@ -713,21 +718,20 @@ def run_test(self): offer = self.nodes[0].icx_listorders({"orderTx": orderTx}) assert_equal(offer[offerTx]["takerFee"], Decimal('0.01500000')) - exthtlcTx = self.nodes[1].icx_submitexthtlc({ - 'offerTx': offerTx, - 'amount': 0.15, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', - 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', - 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', - 'timeout': 24})["txid"] + 'offerTx': offerTx, + 'amount': 0.15, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', + 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', + 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', + 'timeout': 24})["txid"] self.nodes[1].generate(1) self.sync_blocks() claimTx = self.nodes[1].icx_claimdfchtlc({ - 'dfchtlcTx': dfchtlcTx, - 'seed': 'f75a61ad8f7a6e0ab701d5be1f5d4523a9b534571e4e92e0c4610c6a6784ccef'})["txid"] + 'dfchtlcTx': dfchtlcTx, + 'seed': 'f75a61ad8f7a6e0ab701d5be1f5d4523a9b534571e4e92e0c4610c6a6784ccef'})["txid"] self.nodes[1].generate(1) self.sync_blocks() @@ -747,12 +751,12 @@ def run_test(self): beforeOrderDFI1 = self.nodes[1].getaccount(accountBTC, {}, True)[idDFI] orderTxDFI = self.nodes[0].icx_createorder({ - 'tokenFrom': idDFI, - 'chainTo': "BTC", - 'ownerAddress': accountDFI, - 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941', - 'amountFrom': 15, - 'orderPrice':0.01})["txid"] + 'tokenFrom': idDFI, + 'chainTo': "BTC", + 'ownerAddress': accountDFI, + 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941', + 'amountFrom': 15, + 'orderPrice': 0.01})["txid"] self.nodes[0].generate(1) self.sync_blocks() @@ -760,9 +764,9 @@ def run_test(self): beforeOffer = self.nodes[1].getaccount(accountBTC, {}, True)[idDFI] offerTx = self.nodes[1].icx_makeoffer({ - 'orderTx': orderTxDFI, - 'amount': 0.1, - 'ownerAddress': accountBTC})["txid"] + 'orderTx': orderTxDFI, + 'amount': 0.1, + 'ownerAddress': accountBTC})["txid"] self.nodes[1].generate(1) self.sync_blocks() @@ -781,9 +785,9 @@ def run_test(self): assert_equal(len(offer), 1) offerTx = self.nodes[1].icx_makeoffer({ - 'orderTx': orderTxDFI, - 'amount': 0.1, - 'ownerAddress': accountBTC})["txid"] + 'orderTx': orderTxDFI, + 'amount': 0.1, + 'ownerAddress': accountBTC})["txid"] self.nodes[1].generate(1) self.sync_blocks() @@ -791,25 +795,24 @@ def run_test(self): beforeDFCHTLC = self.nodes[0].getaccount(accountDFI, {}, True)[idDFI] dfchtlcTx = self.nodes[0].icx_submitdfchtlc({ - 'offerTx': offerTx, - 'amount': 10, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220'})["txid"] + 'offerTx': offerTx, + 'amount': 10, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220'})["txid"] self.nodes[0].generate(1) assert_equal(self.nodes[0].getaccount(accountDFI, {}, True)[idDFI], beforeDFCHTLC - Decimal('0.01000000')) - self.nodes[0].generate(100) self.sync_blocks() assert_equal(self.nodes[0].getaccount(accountDFI, {}, True)[idDFI], beforeDFCHTLC) htlcs = self.nodes[0].icx_listhtlcs({ - "offerTx": offerTx, - "closed": True}) + "offerTx": offerTx, + "closed": True}) offer = self.nodes[0].icx_listorders({ - "orderTx": orderTxDFI, - "closed": True}) + "orderTx": orderTxDFI, + "closed": True}) assert_equal(len(htlcs), 2) assert_equal(htlcs[dfchtlcTx]["status"], 'EXPIRED') @@ -818,11 +821,11 @@ def run_test(self): # BTC/DFI scenario expiration test # Open an order orderTxBTC = self.nodes[0].icx_createorder({ - 'chainFrom': "BTC", - 'tokenTo': idDFI, - 'ownerAddress': accountDFI, - 'amountFrom': 1, - 'orderPrice':10})["txid"] + 'chainFrom': "BTC", + 'tokenTo': idDFI, + 'ownerAddress': accountDFI, + 'amountFrom': 1, + 'orderPrice': 10})["txid"] self.nodes[0].generate(1) self.sync_blocks() @@ -830,18 +833,16 @@ def run_test(self): beforeOffer = self.nodes[1].getaccount(accountBTC, {}, True)[idDFI] offerTx = self.nodes[1].icx_makeoffer({ - 'orderTx': orderTxBTC, - 'amount': 10, - 'ownerAddress': accountBTC, - 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941'})["txid"] - + 'orderTx': orderTxBTC, + 'amount': 10, + 'ownerAddress': accountBTC, + 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941'})["txid"] self.nodes[1].generate(1) self.sync_blocks() assert_equal(self.nodes[1].getaccount(accountBTC, {}, True)[idDFI], beforeOffer - Decimal('0.10000000')) - offer = self.nodes[0].icx_listorders({"orderTx": orderTxBTC}) assert_equal(len(offer), 2) @@ -850,16 +851,14 @@ def run_test(self): assert_equal(self.nodes[1].getaccount(accountBTC, {}, True)[idDFI], beforeOffer) - offer = self.nodes[0].icx_listorders({"orderTx": orderTxBTC}) assert_equal(len(offer), 1) - offerTx = self.nodes[1].icx_makeoffer({ - 'orderTx': orderTxBTC, - 'amount': 10, - 'ownerAddress': accountBTC, - 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941'})["txid"] + 'orderTx': orderTxBTC, + 'amount': 10, + 'ownerAddress': accountBTC, + 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941'})["txid"] self.nodes[1].generate(1) self.sync_blocks() @@ -867,70 +866,68 @@ def run_test(self): beforeEXTHTLC = self.nodes[0].getaccount(accountDFI, {}, True)[idDFI] exthtlcTx = self.nodes[0].icx_submitexthtlc({ - 'offerTx': offerTx, - 'amount': 1, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', - 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', - 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', - 'timeout': 72})["txid"] + 'offerTx': offerTx, + 'amount': 1, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', + 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', + 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', + 'timeout': 72})["txid"] self.nodes[0].generate(1) htlcs = self.nodes[0].icx_listhtlcs({ - "offerTx": offerTx}) + "offerTx": offerTx}) assert_equal(self.nodes[0].getaccount(accountDFI, {}, True)[idDFI], beforeEXTHTLC - Decimal('0.10000000')) - self.nodes[0].generate(100) self.sync_blocks() assert_equal(self.nodes[0].getaccount(accountDFI, {}, True)[idDFI], beforeEXTHTLC) htlcs = self.nodes[0].icx_listhtlcs({ - "offerTx": offerTx, - "closed": True}) + "offerTx": offerTx, + "closed": True}) offer = self.nodes[0].icx_listorders({ - "orderTx": orderTxBTC, - "closed": True}) + "orderTx": orderTxBTC, + "closed": True}) assert_equal(len(htlcs), 2) assert_equal(htlcs[exthtlcTx]["status"], 'EXPIRED') assert_equal(offer[offerTx]["status"], 'EXPIRED') - orderTx = self.nodes[0].icx_createorder({ - 'tokenFrom': idDFI, - 'chainTo': "BTC", - 'ownerAddress': accountDFI, - 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941', - 'amountFrom': 15, - 'orderPrice':0.01})["txid"] + 'tokenFrom': idDFI, + 'chainTo': "BTC", + 'ownerAddress': accountDFI, + 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941', + 'amountFrom': 15, + 'orderPrice': 0.01})["txid"] self.nodes[0].generate(1) self.sync_blocks() offerTx = self.nodes[1].icx_makeoffer({ - 'orderTx': orderTx, - 'amount': 0.1, - 'ownerAddress': accountBTC})["txid"] + 'orderTx': orderTx, + 'amount': 0.1, + 'ownerAddress': accountBTC})["txid"] self.nodes[1].generate(1) self.sync_blocks() dfchtlcTx = self.nodes[0].icx_submitdfchtlc({ - 'offerTx': offerTx, - 'amount': 10, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220'})["txid"] + 'offerTx': offerTx, + 'amount': 10, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220'})["txid"] self.nodes[0].generate(1) self.sync_blocks() exthtlcTx = self.nodes[1].icx_submitexthtlc({ - 'offerTx': offerTx, - 'amount': 0.1, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', - 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', - 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', - 'timeout': 24})["txid"] + 'offerTx': offerTx, + 'amount': 0.1, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', + 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', + 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', + 'timeout': 24})["txid"] self.nodes[1].generate(1) self.sync_blocks() @@ -950,11 +947,10 @@ def run_test(self): assert_equal(order[orderTx]["status"], 'EXPIRED') htlcs = self.nodes[0].icx_listhtlcs({ - "offerTx": offerTx, - "closed": True}) + "offerTx": offerTx, + "closed": True}) assert_equal(htlcs[dfchtlcTx]["status"], 'REFUNDED') - # dBTC/BTC Scenario, tests 75% taker fee refund # both accounts have >=1BTC self.nodes[1].accounttoaccount(accountBTC, {accountDFI: "1@" + symbolBTC}) @@ -964,12 +960,12 @@ def run_test(self): beforeOrder = self.nodes[0].getaccount(accountDFI, {}, True)[idBTC] orderTx = self.nodes[0].icx_createorder({ - 'tokenFrom': idBTC, - 'chainTo': "BTC", - 'ownerAddress': accountDFI, - 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941', - 'amountFrom': 0.5, - 'orderPrice': 1})["txid"] + 'tokenFrom': idBTC, + 'chainTo': "BTC", + 'ownerAddress': accountDFI, + 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941', + 'amountFrom': 0.5, + 'orderPrice': 1})["txid"] self.nodes[0].generate(1) self.sync_blocks() @@ -982,7 +978,8 @@ def run_test(self): assert_equal(order[orderTx]["tokenFrom"], symbolBTC) assert_equal(order[orderTx]["chainTo"], "BTC") assert_equal(order[orderTx]["ownerAddress"], accountDFI) - assert_equal(order[orderTx]["receivePubkey"], '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941') + assert_equal(order[orderTx]["receivePubkey"], + '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941') assert_equal(order[orderTx]["amountFrom"], Decimal('0.5')) assert_equal(order[orderTx]["amountToFill"], Decimal('0.5')) assert_equal(order[orderTx]["orderPrice"], Decimal('1')) @@ -992,15 +989,16 @@ def run_test(self): beforeOffer = self.nodes[1].getaccount(accountBTC, {}, True)[idDFI] offerTx = self.nodes[1].icx_makeoffer({ - 'orderTx': orderTx, - 'amount': 0.5, - 'ownerAddress': accountBTC})["txid"] + 'orderTx': orderTx, + 'amount': 0.5, + 'ownerAddress': accountBTC})["txid"] self.nodes[1].generate(1) self.sync_blocks() # taker fee - assert_equal(self.nodes[1].getaccount(accountBTC, {}, True)[idDFI], beforeOffer - Decimal('0.05')) # why 0.05 DFI? 0.5 * 0.001 * 100 (order amount * fee per btc * DFI price in BTC) + assert_equal(self.nodes[1].getaccount(accountBTC, {}, True)[idDFI], beforeOffer - Decimal( + '0.05')) # why 0.05 DFI? 0.5 * 0.001 * 100 (order amount * fee per btc * DFI price in BTC) offer = self.nodes[0].icx_listorders({"orderTx": orderTx}) @@ -1014,9 +1012,9 @@ def run_test(self): beforeDFCHTLC = self.nodes[0].getaccount(accountDFI, {}, True)[idDFI] dfchtlcTx = self.nodes[0].icx_submitdfchtlc({ - 'offerTx': offerTx, - 'amount': 0.5, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220'})["txid"] + 'offerTx': offerTx, + 'amount': 0.5, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220'})["txid"] self.nodes[0].generate(1) self.sync_blocks() @@ -1024,7 +1022,8 @@ def run_test(self): assert_equal(self.nodes[0].getaccount(accountDFI, {}, True)[idDFI], beforeDFCHTLC - Decimal('0.05000000')) # Check burn - assert_equal(self.nodes[0].getburninfo()['tokens'][0], "0.80000000@DFI") # 0.7 from previous, 0.1 for this order + assert_equal(self.nodes[0].getburninfo()['tokens'][0], + "0.80000000@DFI") # 0.7 from previous, 0.1 for this order result = self.nodes[0].listburnhistory() assert_equal(result[0]['owner'], burn_address) assert_equal(result[0]['type'], 'ICXSubmitDFCHTLC') @@ -1042,12 +1041,12 @@ def run_test(self): assert_equal(htlcs[dfchtlcTx]["timeout"], 1440) exthtlcTx = self.nodes[1].icx_submitexthtlc({ - 'offerTx': offerTx, - 'amount': 0.5, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', - 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', - 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', - 'timeout': 24})["txid"] + 'offerTx': offerTx, + 'amount': 0.5, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', + 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', + 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', + 'timeout': 24})["txid"] self.nodes[1].generate(1) self.sync_blocks() @@ -1062,21 +1061,23 @@ def run_test(self): assert_equal(htlcs[exthtlcTx]["amountInDFCAsset"], Decimal('0.5')) assert_equal(htlcs[exthtlcTx]["hash"], '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220') assert_equal(htlcs[exthtlcTx]["htlcScriptAddress"], '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N') - assert_equal(htlcs[exthtlcTx]["ownerPubkey"], '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252') + assert_equal(htlcs[exthtlcTx]["ownerPubkey"], + '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252') assert_equal(htlcs[exthtlcTx]["timeout"], 24) beforeClaim0 = self.nodes[0].getaccount(accountDFI, {}, True)[idDFI] beforeClaim1 = self.nodes[1].getaccount(accountBTC, {}, True)[idDFI] claimTx = self.nodes[1].icx_claimdfchtlc({ - 'dfchtlcTx': dfchtlcTx, - 'seed': 'f75a61ad8f7a6e0ab701d5be1f5d4523a9b534571e4e92e0c4610c6a6784ccef'})["txid"] + 'dfchtlcTx': dfchtlcTx, + 'seed': 'f75a61ad8f7a6e0ab701d5be1f5d4523a9b534571e4e92e0c4610c6a6784ccef'})["txid"] self.nodes[1].generate(1) self.sync_blocks() - assert_equal(self.nodes[0].getaccount(accountDFI, {}, True)[idDFI], beforeClaim0 + Decimal("0.05") + Decimal("0.0375")) # 0.05 lock refund + 0.75 * 0.05 taker fee refund - assert_equal(self.nodes[1].getaccount(accountBTC, {}, True)[idDFI], beforeClaim1) # no refunds for taker + assert_equal(self.nodes[0].getaccount(accountDFI, {}, True)[idDFI], beforeClaim0 + Decimal("0.05") + Decimal( + "0.0375")) # 0.05 lock refund + 0.75 * 0.05 taker fee refund + assert_equal(self.nodes[1].getaccount(accountBTC, {}, True)[idDFI], beforeClaim1) # no refunds for taker # dBTC/BTC Scenario, tests 25% taker fee refund # both accounts have >=1BTC @@ -1087,12 +1088,12 @@ def run_test(self): beforeOrder = self.nodes[0].getaccount(accountDFI, {}, True)[idBTC] orderTx = self.nodes[0].icx_createorder({ - 'tokenFrom': idBTC, - 'chainTo': "BTC", - 'ownerAddress': accountDFI, - 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941', - 'amountFrom': 0.5, - 'orderPrice': 0.9})["txid"] + 'tokenFrom': idBTC, + 'chainTo': "BTC", + 'ownerAddress': accountDFI, + 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941', + 'amountFrom': 0.5, + 'orderPrice': 0.9})["txid"] self.nodes[0].generate(1) self.sync_blocks() @@ -1105,7 +1106,8 @@ def run_test(self): assert_equal(order[orderTx]["tokenFrom"], symbolBTC) assert_equal(order[orderTx]["chainTo"], "BTC") assert_equal(order[orderTx]["ownerAddress"], accountDFI) - assert_equal(order[orderTx]["receivePubkey"], '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941') + assert_equal(order[orderTx]["receivePubkey"], + '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941') assert_equal(order[orderTx]["amountFrom"], Decimal('0.5')) assert_equal(order[orderTx]["amountToFill"], Decimal('0.5')) assert_equal(order[orderTx]["orderPrice"], Decimal('0.9')) @@ -1115,15 +1117,16 @@ def run_test(self): beforeOffer = self.nodes[1].getaccount(accountBTC, {}, True)[idDFI] offerTx = self.nodes[1].icx_makeoffer({ - 'orderTx': orderTx, - 'amount': 0.5, - 'ownerAddress': accountBTC})["txid"] + 'orderTx': orderTx, + 'amount': 0.5, + 'ownerAddress': accountBTC})["txid"] self.nodes[1].generate(1) self.sync_blocks() # taker fee - assert_equal(self.nodes[1].getaccount(accountBTC, {}, True)[idDFI], beforeOffer - Decimal('0.05')) # why 0.05 DFI? 0.5 * 0.001 * 100 (order amount * fee per btc * DFI price in BTC) + assert_equal(self.nodes[1].getaccount(accountBTC, {}, True)[idDFI], beforeOffer - Decimal( + '0.05')) # why 0.05 DFI? 0.5 * 0.001 * 100 (order amount * fee per btc * DFI price in BTC) offer = self.nodes[0].icx_listorders({"orderTx": orderTx}) @@ -1137,9 +1140,9 @@ def run_test(self): beforeDFCHTLC = self.nodes[0].getaccount(accountDFI, {}, True)[idDFI] dfchtlcTx = self.nodes[0].icx_submitdfchtlc({ - 'offerTx': offerTx, - 'amount': 0.5, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220'})["txid"] + 'offerTx': offerTx, + 'amount': 0.5, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220'})["txid"] self.nodes[0].generate(1) self.sync_blocks() @@ -1147,7 +1150,8 @@ def run_test(self): assert_equal(self.nodes[0].getaccount(accountDFI, {}, True)[idDFI], beforeDFCHTLC - Decimal('0.04500000')) # Check burn - assert_equal(self.nodes[0].getburninfo()['tokens'][0], "0.89000000@DFI") # 0.8 from previous, 0.09 for this order + assert_equal(self.nodes[0].getburninfo()['tokens'][0], + "0.89000000@DFI") # 0.8 from previous, 0.09 for this order result = self.nodes[0].listburnhistory() assert_equal(result[0]['owner'], burn_address) assert_equal(result[0]['type'], 'ICXSubmitDFCHTLC') @@ -1165,12 +1169,12 @@ def run_test(self): assert_equal(htlcs[dfchtlcTx]["timeout"], 1440) exthtlcTx = self.nodes[1].icx_submitexthtlc({ - 'offerTx': offerTx, - 'amount': 0.45, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', - 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', - 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', - 'timeout': 24})["txid"] + 'offerTx': offerTx, + 'amount': 0.45, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', + 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', + 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', + 'timeout': 24})["txid"] self.nodes[1].generate(1) self.sync_blocks() @@ -1185,21 +1189,24 @@ def run_test(self): assert_equal(htlcs[exthtlcTx]["amountInDFCAsset"], Decimal('0.5')) assert_equal(htlcs[exthtlcTx]["hash"], '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220') assert_equal(htlcs[exthtlcTx]["htlcScriptAddress"], '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N') - assert_equal(htlcs[exthtlcTx]["ownerPubkey"], '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252') + assert_equal(htlcs[exthtlcTx]["ownerPubkey"], + '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252') assert_equal(htlcs[exthtlcTx]["timeout"], 24) beforeClaim0 = self.nodes[0].getaccount(accountDFI, {}, True)[idDFI] beforeClaim1 = self.nodes[1].getaccount(accountBTC, {}, True)[idDFI] claimTx = self.nodes[1].icx_claimdfchtlc({ - 'dfchtlcTx': dfchtlcTx, - 'seed': 'f75a61ad8f7a6e0ab701d5be1f5d4523a9b534571e4e92e0c4610c6a6784ccef'})["txid"] + 'dfchtlcTx': dfchtlcTx, + 'seed': 'f75a61ad8f7a6e0ab701d5be1f5d4523a9b534571e4e92e0c4610c6a6784ccef'})["txid"] self.nodes[1].generate(1) self.sync_blocks() - assert_equal(self.nodes[0].getaccount(accountDFI, {}, True)[idDFI], beforeClaim0 + Decimal("0.045") + Decimal("0.01125")) # 0.045 lock refund + 0.25 * 0.045 taker fee refund - assert_equal(self.nodes[1].getaccount(accountBTC, {}, True)[idDFI], beforeClaim1) # no refunds for taker + assert_equal(self.nodes[0].getaccount(accountDFI, {}, True)[idDFI], beforeClaim0 + Decimal("0.045") + Decimal( + "0.01125")) # 0.045 lock refund + 0.25 * 0.045 taker fee refund + assert_equal(self.nodes[1].getaccount(accountBTC, {}, True)[idDFI], beforeClaim1) # no refunds for taker + if __name__ == '__main__': ICXOrderbookTest().main() diff --git a/test/functional/feature_icx_orderbook_errors.py b/test/functional/feature_icx_orderbook_errors.py index 1a580a67ca..51df65bd77 100755 --- a/test/functional/feature_icx_orderbook_errors.py +++ b/test/functional/feature_icx_orderbook_errors.py @@ -13,16 +13,18 @@ from decimal import Decimal -class ICXOrderbookErrorTest (DefiTestFramework): +class ICXOrderbookErrorTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 self.setup_clean_chain = True self.extra_args = [ - ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-eunosheight=50', '-eunospayaheight=50', '-txindex=1'], - ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-eunosheight=50', '-eunospayaheight=50', '-txindex=1']] + ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-eunosheight=50', '-eunospayaheight=50', + '-txindex=1'], + ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-eunosheight=50', '-eunospayaheight=50', + '-txindex=1']] def run_test(self): - assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI + assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI print("Generating initial chain...") self.nodes[0].generate(25) @@ -83,8 +85,8 @@ def run_test(self): # check tokens id pool = self.nodes[0].getpoolpair("DFIBTC") idDFIBTC = list(self.nodes[0].gettoken("DFIBTC").keys())[0] - assert(pool[idDFIBTC]['idTokenA'] == idDFI) - assert(pool[idDFIBTC]['idTokenB'] == idBTC) + assert (pool[idDFIBTC]['idTokenA'] == idDFI) + assert (pool[idDFIBTC]['idTokenB'] == idBTC) # transfer self.nodes[0].addpoolliquidity({ @@ -92,7 +94,7 @@ def run_test(self): }, accountDFI, []) self.nodes[0].generate(1) - self.nodes[0].setgov({"ICX_TAKERFEE_PER_BTC":Decimal('0.001')}) + self.nodes[0].setgov({"ICX_TAKERFEE_PER_BTC": Decimal('0.001')}) self.nodes[0].generate(1) @@ -104,75 +106,75 @@ def run_test(self): # unexistant token for create order try: self.nodes[0].icx_createorder({ - 'tokenFrom': "DOGE", - 'chainTo': "BTC", - 'ownerAddress': accountDFI, - 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941', - 'amountFrom': 1, - 'orderPrice':0.01}) + 'tokenFrom': "DOGE", + 'chainTo': "BTC", + 'ownerAddress': accountDFI, + 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941', + 'amountFrom': 1, + 'orderPrice': 0.01}) except JSONRPCException as e: errorString = e.error['message'] - assert("Token DOGE does not exist!" in errorString) + assert ("Token DOGE does not exist!" in errorString) # wrong chain for create order try: self.nodes[0].icx_createorder({ - 'tokenFrom': idDFI, - 'chainTo': "LTC", - 'ownerAddress': accountDFI, - 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941', - 'amountFrom': 1, - 'orderPrice':0.01}) + 'tokenFrom': idDFI, + 'chainTo': "LTC", + 'ownerAddress': accountDFI, + 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941', + 'amountFrom': 1, + 'orderPrice': 0.01}) except JSONRPCException as e: errorString = e.error['message'] - assert("Invalid parameters, argument \"chainTo\" must be \"BTC\" if \"tokenFrom\" specified" in errorString) + assert ("Invalid parameters, argument \"chainTo\" must be \"BTC\" if \"tokenFrom\" specified" in errorString) # wrong address for DFI for create order try: self.nodes[0].icx_createorder({ - 'tokenFrom': idDFI, - 'chainTo': "BTC", - 'ownerAddress': accountBTC, - 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941', - 'amountFrom': 1, - 'orderPrice':0.01}) + 'tokenFrom': idDFI, + 'chainTo': "BTC", + 'ownerAddress': accountBTC, + 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941', + 'amountFrom': 1, + 'orderPrice': 0.01}) except JSONRPCException as e: errorString = e.error['message'] - assert("Address ("+accountBTC+") is not owned by the wallet" in errorString) + assert ("Address (" + accountBTC + ") is not owned by the wallet" in errorString) # invalid receivePubkey for create order try: self.nodes[0].icx_createorder({ - 'tokenFrom': idDFI, - 'chainTo': "BTC", - 'ownerAddress': accountDFI, - 'receivePubkey': '000000000000000000000000000000000000000000000000000000000000000000', - 'amountFrom': 1, - 'orderPrice':0.01}) + 'tokenFrom': idDFI, + 'chainTo': "BTC", + 'ownerAddress': accountDFI, + 'receivePubkey': '000000000000000000000000000000000000000000000000000000000000000000', + 'amountFrom': 1, + 'orderPrice': 0.01}) except JSONRPCException as e: errorString = e.error['message'] - assert("Invalid public key:" in errorString) + assert ("Invalid public key:" in errorString) # not enough balance od DFI for create order try: self.nodes[0].icx_createorder({ - 'tokenFrom': idDFI, - 'chainTo': "BTC", - 'ownerAddress': accountDFI, - 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941', - 'amountFrom': 1500, - 'orderPrice':0.01}) + 'tokenFrom': idDFI, + 'chainTo': "BTC", + 'ownerAddress': accountDFI, + 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941', + 'amountFrom': 1500, + 'orderPrice': 0.01}) except JSONRPCException as e: errorString = e.error['message'] - assert("Not enough balance for Token DFI on address "+accountDFI in errorString) + assert ("Not enough balance for Token DFI on address " + accountDFI in errorString) orderTx = self.nodes[0].icx_createorder({ - 'tokenFrom': idDFI, - 'chainTo': "BTC", - 'ownerAddress': accountDFI, - 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941', - 'amountFrom': 1, - 'orderPrice':0.01})["txid"] + 'tokenFrom': idDFI, + 'chainTo': "BTC", + 'ownerAddress': accountDFI, + 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941', + 'amountFrom': 1, + 'orderPrice': 0.01})["txid"] self.nodes[0].generate(1) self.sync_blocks() @@ -180,40 +182,41 @@ def run_test(self): # unexistent orderTx try: self.nodes[1].icx_makeoffer({ - 'orderTx': "76432beb2a667efe4858b4e1ec93979b621c51c76abaab2434892655dd152e3d", - 'amount': 0.10, - 'ownerAddress': accountBTC}) + 'orderTx': "76432beb2a667efe4858b4e1ec93979b621c51c76abaab2434892655dd152e3d", + 'amount': 0.10, + 'ownerAddress': accountBTC}) except JSONRPCException as e: errorString = e.error['message'] - assert("orderTx (76432beb2a667efe4858b4e1ec93979b621c51c76abaab2434892655dd152e3d) does not exist" in errorString) + assert ( + "orderTx (76432beb2a667efe4858b4e1ec93979b621c51c76abaab2434892655dd152e3d) does not exist" in errorString) # invalid ownerAddress try: self.nodes[1].icx_makeoffer({ - 'orderTx': orderTx, - 'amount': 0.01, - 'ownerAddress': accountDFI}) + 'orderTx': orderTx, + 'amount': 0.01, + 'ownerAddress': accountDFI}) except JSONRPCException as e: errorString = e.error['message'] - assert("Address ("+accountDFI+") is not owned by the wallet" in errorString) + assert ("Address (" + accountDFI + ") is not owned by the wallet" in errorString) # not enough DFI for takerFee try: self.nodes[1].icx_makeoffer({ - 'orderTx': orderTx, - 'amount': 0.01, - 'ownerAddress': accountBTC}) + 'orderTx': orderTx, + 'amount': 0.01, + 'ownerAddress': accountBTC}) except JSONRPCException as e: errorString = e.error['message'] - assert("amount 0.00000000 is less than 0.00100000" in errorString) + assert ("amount 0.00000000 is less than 0.00100000" in errorString) self.nodes[1].utxostoaccount({accountBTC: "0.001@" + symbolDFI}) self.nodes[1].generate(1) offerTx = self.nodes[1].icx_makeoffer({ - 'orderTx': orderTx, - 'amount': 0.01, - 'ownerAddress': accountBTC})["txid"] + 'orderTx': orderTx, + 'amount': 0.01, + 'ownerAddress': accountBTC})["txid"] self.nodes[1].generate(1) self.sync_blocks() @@ -221,25 +224,25 @@ def run_test(self): # ext htlc cannot be first htlc try: self.nodes[1].icx_submitexthtlc({ - 'offerTx': offerTx, - 'amount': 0.01, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', - 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', - 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', - 'timeout': 24}) + 'offerTx': offerTx, + 'amount': 0.01, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', + 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', + 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', + 'timeout': 24}) except JSONRPCException as e: errorString = e.error['message'] - assert("offer ("+ offerTx + ") needs to have dfc htlc submitted first, but no dfc htlc found!" in errorString) + assert ("offer (" + offerTx + ") needs to have dfc htlc submitted first, but no dfc htlc found!" in errorString) # not enough DFI for takerFee try: self.nodes[0].icx_submitdfchtlc({ - 'offerTx': offerTx, - 'amount': 1, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220'}) + 'offerTx': offerTx, + 'amount': 1, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220'}) except JSONRPCException as e: errorString = e.error['message'] - assert("amount 0.00000000 is less than 0.00100000" in errorString) + assert ("amount 0.00000000 is less than 0.00100000" in errorString) self.nodes[0].utxostoaccount({accountDFI: "0.001@" + symbolDFI}) self.nodes[0].generate(1) @@ -247,28 +250,28 @@ def run_test(self): # wrong amount try: self.nodes[0].icx_submitdfchtlc({ - 'offerTx': offerTx, - 'amount': 2, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220'}) + 'offerTx': offerTx, + 'amount': 2, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220'}) except JSONRPCException as e: errorString = e.error['message'] - assert("amount must be lower or equal the offer one" in errorString) + assert ("amount must be lower or equal the offer one" in errorString) # timeout less than minimum try: self.nodes[0].icx_submitdfchtlc({ - 'offerTx': offerTx, - 'amount': 1, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', - 'timeout': 1439}) + 'offerTx': offerTx, + 'amount': 1, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', + 'timeout': 1439}) except JSONRPCException as e: errorString = e.error['message'] - assert("timeout must be greater than 1439" in errorString) + assert ("timeout must be greater than 1439" in errorString) dfchtlcTx = self.nodes[0].icx_submitdfchtlc({ - 'offerTx': offerTx, - 'amount': 1, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220'})["txid"] + 'offerTx': offerTx, + 'amount': 1, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220'})["txid"] self.nodes[0].generate(1) self.sync_blocks() @@ -276,86 +279,85 @@ def run_test(self): # dfc htlc already submitted try: self.nodes[0].icx_submitdfchtlc({ - 'offerTx': offerTx, - 'amount': 1, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220'}) + 'offerTx': offerTx, + 'amount': 1, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220'}) except JSONRPCException as e: errorString = e.error['message'] - assert("dfc htlc already submitted" in errorString) - + assert ("dfc htlc already submitted" in errorString) # less amount try: self.nodes[1].icx_submitexthtlc({ - 'offerTx': offerTx, - 'amount': 0.001, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', - 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', - 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', - 'timeout': 24}) + 'offerTx': offerTx, + 'amount': 0.001, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', + 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', + 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', + 'timeout': 24}) except JSONRPCException as e: errorString = e.error['message'] - assert("amount must be equal to calculated dfchtlc amount" in errorString) + assert ("amount must be equal to calculated dfchtlc amount" in errorString) # more amount try: self.nodes[1].icx_submitexthtlc({ - 'offerTx': offerTx, - 'amount': 0.1, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', - 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', - 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', - 'timeout': 24}) + 'offerTx': offerTx, + 'amount': 0.1, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', + 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', + 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', + 'timeout': 24}) except JSONRPCException as e: errorString = e.error['message'] - assert("amount must be equal to calculated dfchtlc amount" in errorString) + assert ("amount must be equal to calculated dfchtlc amount" in errorString) # different hash try: self.nodes[1].icx_submitexthtlc({ - 'offerTx': offerTx, - 'amount': 0.01, - 'hash': '957fc0fd643f605b2938e0000000029fd70bd35b2162a21d978c41e5241a5220', - 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', - 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', - 'timeout': 24}) + 'offerTx': offerTx, + 'amount': 0.01, + 'hash': '957fc0fd643f605b2938e0000000029fd70bd35b2162a21d978c41e5241a5220', + 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', + 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', + 'timeout': 24}) except JSONRPCException as e: errorString = e.error['message'] - assert("Invalid hash, external htlc hash is different than dfc htlc hash" in errorString) + assert ("Invalid hash, external htlc hash is different than dfc htlc hash" in errorString) # timeout less than minimum try: self.nodes[1].icx_submitexthtlc({ - 'offerTx': offerTx, - 'amount': 0.01, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', - 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', - 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', - 'timeout': 23}) + 'offerTx': offerTx, + 'amount': 0.01, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', + 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', + 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', + 'timeout': 23}) except JSONRPCException as e: errorString = e.error['message'] - assert("timeout must be greater than 23" in errorString) + assert ("timeout must be greater than 23" in errorString) # timeout more than expiration of dfc htlc try: self.nodes[1].icx_submitexthtlc({ - 'offerTx': offerTx, - 'amount': 0.01, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', - 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', - 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', - 'timeout': 73}) + 'offerTx': offerTx, + 'amount': 0.01, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', + 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', + 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', + 'timeout': 73}) except JSONRPCException as e: errorString = e.error['message'] - assert("timeout must be less than expiration period of 1st htlc in DFC blocks" in errorString) + assert ("timeout must be less than expiration period of 1st htlc in DFC blocks" in errorString) self.nodes[1].icx_submitexthtlc({ - 'offerTx': offerTx, - 'amount': 0.01, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', - 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', - 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', - 'timeout': 24})["txid"] + 'offerTx': offerTx, + 'amount': 0.01, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', + 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', + 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', + 'timeout': 24})["txid"] self.nodes[1].generate(1) self.sync_blocks() @@ -363,24 +365,25 @@ def run_test(self): # wrong dfchtlcTx try: self.nodes[1].icx_claimdfchtlc({ - 'dfchtlcTx': "76432beb2a667efe4858b4e1ec93979b621c51c76abaab2434892655dd152e3d", - 'seed': 'f75a61ad8f7a6e0ab701d5be1f5d4523a9b534571e4e92e0c4610c6a6784ccef'}) + 'dfchtlcTx': "76432beb2a667efe4858b4e1ec93979b621c51c76abaab2434892655dd152e3d", + 'seed': 'f75a61ad8f7a6e0ab701d5be1f5d4523a9b534571e4e92e0c4610c6a6784ccef'}) except JSONRPCException as e: errorString = e.error['message'] - assert("dfc htlc with creation tx 76432beb2a667efe4858b4e1ec93979b621c51c76abaab2434892655dd152e3d does not exists" in errorString) + assert ( + "dfc htlc with creation tx 76432beb2a667efe4858b4e1ec93979b621c51c76abaab2434892655dd152e3d does not exists" in errorString) # wrong seed try: self.nodes[1].icx_claimdfchtlc({ - 'dfchtlcTx': dfchtlcTx, - 'seed': 'f75a61ad8f7a6e0ab7000000000d4523a9b534571e4e92e0c4610c6a6784ccef'}) + 'dfchtlcTx': dfchtlcTx, + 'seed': 'f75a61ad8f7a6e0ab7000000000d4523a9b534571e4e92e0c4610c6a6784ccef'}) except JSONRPCException as e: errorString = e.error['message'] - assert("hash generated from given seed is different than in dfc htlc" in errorString) + assert ("hash generated from given seed is different than in dfc htlc" in errorString) self.nodes[1].icx_claimdfchtlc({ - 'dfchtlcTx': dfchtlcTx, - 'seed': 'f75a61ad8f7a6e0ab701d5be1f5d4523a9b534571e4e92e0c4610c6a6784ccef'})["txid"] + 'dfchtlcTx': dfchtlcTx, + 'seed': 'f75a61ad8f7a6e0ab701d5be1f5d4523a9b534571e4e92e0c4610c6a6784ccef'})["txid"] self.nodes[1].generate(1) self.sync_blocks() @@ -398,45 +401,45 @@ def run_test(self): # unexistant token for create order try: self.nodes[0].icx_createorder({ - 'chainFrom': "BTC", - 'tokenTo': "DOGE", - 'ownerAddress': accountDFI, - 'amountFrom': 0.01, - 'orderPrice': 100}) + 'chainFrom': "BTC", + 'tokenTo': "DOGE", + 'ownerAddress': accountDFI, + 'amountFrom': 0.01, + 'orderPrice': 100}) except JSONRPCException as e: errorString = e.error['message'] - assert("Token DOGE does not exist!" in errorString) + assert ("Token DOGE does not exist!" in errorString) # wrong chain for create order try: self.nodes[0].icx_createorder({ - 'chainFrom': "LTC", - 'tokenTo': idDFI, - 'ownerAddress': accountDFI, - 'amountFrom': 0.01, - 'orderPrice': 100}) + 'chainFrom': "LTC", + 'tokenTo': idDFI, + 'ownerAddress': accountDFI, + 'amountFrom': 0.01, + 'orderPrice': 100}) except JSONRPCException as e: errorString = e.error['message'] - assert("Invalid parameters, argument \"chainFrom\" must be \"BTC\" if \"tokenTo\" specified" in errorString) + assert ("Invalid parameters, argument \"chainFrom\" must be \"BTC\" if \"tokenTo\" specified" in errorString) # wrong address for DFI for create order try: self.nodes[0].icx_createorder({ - 'chainFrom': "BTC", - 'tokenTo': idDFI, - 'ownerAddress': accountBTC, - 'amountFrom': 0.01, - 'orderPrice': 100}) + 'chainFrom': "BTC", + 'tokenTo': idDFI, + 'ownerAddress': accountBTC, + 'amountFrom': 0.01, + 'orderPrice': 100}) except JSONRPCException as e: errorString = e.error['message'] - assert("Address ("+accountBTC+") is not owned by the wallet" in errorString) + assert ("Address (" + accountBTC + ") is not owned by the wallet" in errorString) orderTx = self.nodes[0].icx_createorder({ - 'chainFrom': "BTC", - 'tokenTo': idDFI, - 'ownerAddress': accountDFI, - 'amountFrom': 0.01, - 'orderPrice': 100})["txid"] + 'chainFrom': "BTC", + 'tokenTo': idDFI, + 'ownerAddress': accountDFI, + 'amountFrom': 0.01, + 'orderPrice': 100})["txid"] self.nodes[0].generate(1) self.sync_blocks() @@ -444,41 +447,42 @@ def run_test(self): # unexistent orderTx try: self.nodes[1].icx_makeoffer({ - 'orderTx': "76432beb2a667efe4858b4e1ec93979b621c51c76abaab2434892655dd152e3d", - 'amount': 1, - 'ownerAddress': accountBTC, - 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941'}) + 'orderTx': "76432beb2a667efe4858b4e1ec93979b621c51c76abaab2434892655dd152e3d", + 'amount': 1, + 'ownerAddress': accountBTC, + 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941'}) except JSONRPCException as e: errorString = e.error['message'] - assert("orderTx (76432beb2a667efe4858b4e1ec93979b621c51c76abaab2434892655dd152e3d) does not exist" in errorString) + assert ( + "orderTx (76432beb2a667efe4858b4e1ec93979b621c51c76abaab2434892655dd152e3d) does not exist" in errorString) # invalid ownerAddress try: self.nodes[1].icx_makeoffer({ - 'orderTx': orderTx, - 'amount': 1, - 'ownerAddress': accountDFI, - 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941'}) + 'orderTx': orderTx, + 'amount': 1, + 'ownerAddress': accountDFI, + 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941'}) except JSONRPCException as e: errorString = e.error['message'] - assert("Address ("+accountDFI+") is not owned by the wallet" in errorString) + assert ("Address (" + accountDFI + ") is not owned by the wallet" in errorString) # invalid receivePublikey try: self.nodes[1].icx_makeoffer({ - 'orderTx': orderTx, - 'amount': 1, - 'ownerAddress': accountBTC, - 'receivePubkey': '000000000000000000000000000000000000000000000000000000000000000000'}) + 'orderTx': orderTx, + 'amount': 1, + 'ownerAddress': accountBTC, + 'receivePubkey': '000000000000000000000000000000000000000000000000000000000000000000'}) except JSONRPCException as e: errorString = e.error['message'] - assert("Invalid public key" in errorString) + assert ("Invalid public key" in errorString) offerTx = self.nodes[1].icx_makeoffer({ - 'orderTx': orderTx, - 'amount': 1, - 'ownerAddress': accountBTC, - 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941'})["txid"] + 'orderTx': orderTx, + 'amount': 1, + 'ownerAddress': accountBTC, + 'receivePubkey': '037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941'})["txid"] self.nodes[1].utxostoaccount({accountBTC: "1@" + symbolDFI}) self.nodes[1].generate(1) @@ -487,46 +491,47 @@ def run_test(self): # dfc htlc cannot be first htlc try: self.nodes[1].icx_submitdfchtlc({ - 'offerTx': offerTx, - 'amount': 1, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220'}) + 'offerTx': offerTx, + 'amount': 1, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220'}) except JSONRPCException as e: errorString = e.error['message'] - assert("offer ("+ offerTx + ") needs to have ext htlc submitted first, but no external htlc found" in errorString) + assert ( + "offer (" + offerTx + ") needs to have ext htlc submitted first, but no external htlc found" in errorString) # more amount try: self.nodes[0].icx_submitexthtlc({ - 'offerTx': offerTx, - 'amount': 0.1, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', - 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', - 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', - 'timeout': 72}) + 'offerTx': offerTx, + 'amount': 0.1, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', + 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', + 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', + 'timeout': 72}) except JSONRPCException as e: errorString = e.error['message'] - assert("amount must be lower or equal the offer one" in errorString) + assert ("amount must be lower or equal the offer one" in errorString) # timeout less than minimum try: self.nodes[0].icx_submitexthtlc({ - 'offerTx': offerTx, - 'amount': 0.01, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', - 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', - 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', - 'timeout': 71}) + 'offerTx': offerTx, + 'amount': 0.01, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', + 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', + 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', + 'timeout': 71}) except JSONRPCException as e: errorString = e.error['message'] - assert("timeout must be greater than 71" in errorString) + assert ("timeout must be greater than 71" in errorString) self.nodes[0].icx_submitexthtlc({ - 'offerTx': offerTx, - 'amount': 0.01, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', - 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', - 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', - 'timeout': 72})["txid"] + 'offerTx': offerTx, + 'amount': 0.01, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', + 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', + 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', + 'timeout': 72})["txid"] self.nodes[0].generate(1) self.sync_blocks() @@ -534,62 +539,62 @@ def run_test(self): # ext htlc already submitted try: self.nodes[0].icx_submitexthtlc({ - 'offerTx': offerTx, - 'amount': 0.01, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', - 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', - 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', - 'timeout': 72}) + 'offerTx': offerTx, + 'amount': 0.01, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', + 'htlcScriptAddress': '13sJQ9wBWh8ssihHUgAaCmNWJbBAG5Hr9N', + 'ownerPubkey': '036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252', + 'timeout': 72}) except JSONRPCException as e: errorString = e.error['message'] - assert("ext htlc already submitted" in errorString) + assert ("ext htlc already submitted" in errorString) # less amount try: self.nodes[1].icx_submitdfchtlc({ - 'offerTx': offerTx, - 'amount': 0.5, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220'}) + 'offerTx': offerTx, + 'amount': 0.5, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220'}) except JSONRPCException as e: errorString = e.error['message'] - assert("amount must be equal to calculated exthtlc amount" in errorString) + assert ("amount must be equal to calculated exthtlc amount" in errorString) # more amount try: self.nodes[1].icx_submitdfchtlc({ - 'offerTx': offerTx, - 'amount': 2, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220'}) + 'offerTx': offerTx, + 'amount': 2, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220'}) except JSONRPCException as e: errorString = e.error['message'] - assert("amount must be equal to calculated exthtlc amount" in errorString) + assert ("amount must be equal to calculated exthtlc amount" in errorString) # timeout less than minimum try: self.nodes[1].icx_submitdfchtlc({ - 'offerTx': offerTx, - 'amount': 1, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', - 'timeout': 479}) + 'offerTx': offerTx, + 'amount': 1, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', + 'timeout': 479}) except JSONRPCException as e: errorString = e.error['message'] - assert("timeout must be greater than 479" in errorString) + assert ("timeout must be greater than 479" in errorString) # timeout more than expiration of ext htlc try: self.nodes[1].icx_submitdfchtlc({ - 'offerTx': offerTx, - 'amount': 1, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', - 'timeout': 1441}) + 'offerTx': offerTx, + 'amount': 1, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220', + 'timeout': 1441}) except JSONRPCException as e: errorString = e.error['message'] - assert("timeout must be less than expiration period of 1st htlc in DFI blocks" in errorString) + assert ("timeout must be less than expiration period of 1st htlc in DFI blocks" in errorString) dfchtlcTx = self.nodes[1].icx_submitdfchtlc({ - 'offerTx': offerTx, - 'amount': 1, - 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220'})["txid"] + 'offerTx': offerTx, + 'amount': 1, + 'hash': '957fc0fd643f605b2938e0631a61529fd70bd35b2162a21d978c41e5241a5220'})["txid"] self.nodes[1].generate(1) self.sync_blocks() @@ -597,24 +602,25 @@ def run_test(self): # wrong dfchtlcTx try: self.nodes[0].icx_claimdfchtlc({ - 'dfchtlcTx': "76432beb2a667efe4858b4e1ec93979b621c51c76abaab2434892655dd152e3d", - 'seed': 'f75a61ad8f7a6e0ab701d5be1f5d4523a9b534571e4e92e0c4610c6a6784ccef'}) + 'dfchtlcTx': "76432beb2a667efe4858b4e1ec93979b621c51c76abaab2434892655dd152e3d", + 'seed': 'f75a61ad8f7a6e0ab701d5be1f5d4523a9b534571e4e92e0c4610c6a6784ccef'}) except JSONRPCException as e: errorString = e.error['message'] - assert("dfc htlc with creation tx 76432beb2a667efe4858b4e1ec93979b621c51c76abaab2434892655dd152e3d does not exists" in errorString) + assert ( + "dfc htlc with creation tx 76432beb2a667efe4858b4e1ec93979b621c51c76abaab2434892655dd152e3d does not exists" in errorString) # wrong seed try: self.nodes[0].icx_claimdfchtlc({ - 'dfchtlcTx': dfchtlcTx, - 'seed': 'f75a61ad8f7a6e0ab7000000000d4523a9b534571e4e92e0c4610c6a6784ccef'}) + 'dfchtlcTx': dfchtlcTx, + 'seed': 'f75a61ad8f7a6e0ab7000000000d4523a9b534571e4e92e0c4610c6a6784ccef'}) except JSONRPCException as e: errorString = e.error['message'] - assert("hash generated from given seed is different than in dfc htlc" in errorString) + assert ("hash generated from given seed is different than in dfc htlc" in errorString) self.nodes[0].icx_claimdfchtlc({ - 'dfchtlcTx': dfchtlcTx, - 'seed': 'f75a61ad8f7a6e0ab701d5be1f5d4523a9b534571e4e92e0c4610c6a6784ccef'})["txid"] + 'dfchtlcTx': dfchtlcTx, + 'seed': 'f75a61ad8f7a6e0ab701d5be1f5d4523a9b534571e4e92e0c4610c6a6784ccef'})["txid"] self.nodes[0].generate(1) self.sync_blocks() @@ -628,5 +634,6 @@ def run_test(self): assert_equal(len(order), 3) assert_equal(order[orderTx]["status"], 'FILLED') + if __name__ == '__main__': ICXOrderbookErrorTest().main() diff --git a/test/functional/feature_includeconf.py b/test/functional/feature_includeconf.py index 427141bbc4..0252f74e37 100755 --- a/test/functional/feature_includeconf.py +++ b/test/functional/feature_includeconf.py @@ -18,6 +18,7 @@ from test_framework.test_framework import DefiTestFramework + class IncludeConfTest(DefiTestFramework): def set_test_params(self): self.setup_clean_chain = False @@ -43,7 +44,8 @@ def run_test(self): self.log.info("-includeconf cannot be used as command-line arg") self.stop_node(0) - self.nodes[0].assert_start_raises_init_error(extra_args=["-includeconf=relative2.conf"], expected_msg="Error: Error parsing command line arguments: -includeconf cannot be used from commandline; -includeconf=relative2.conf") + self.nodes[0].assert_start_raises_init_error(extra_args=["-includeconf=relative2.conf"], + expected_msg="Error: Error parsing command line arguments: -includeconf cannot be used from commandline; -includeconf=relative2.conf") self.log.info("-includeconf cannot be used recursively. subversion should end with 'main; relative)/'") with open(os.path.join(self.options.tmpdir, "node0", "relative.conf"), "a", encoding="utf8") as f: @@ -52,20 +54,23 @@ def run_test(self): subversion = self.nodes[0].getnetworkinfo()["subversion"] assert subversion.endswith("main; relative)/") - self.stop_node(0, expected_stderr="warning: -includeconf cannot be used from included files; ignoring -includeconf=relative2.conf") + self.stop_node(0, + expected_stderr="warning: -includeconf cannot be used from included files; ignoring -includeconf=relative2.conf") self.log.info("-includeconf cannot contain invalid arg") # Commented out as long as we ignore invalid arguments in configuration files - #with open(os.path.join(self.options.tmpdir, "node0", "relative.conf"), "w", encoding="utf8") as f: + # with open(os.path.join(self.options.tmpdir, "node0", "relative.conf"), "w", encoding="utf8") as f: # f.write("foo=bar\n") - #self.nodes[0].assert_start_raises_init_error(expected_msg="Error: Error reading configuration file: Invalid configuration value foo") + # self.nodes[0].assert_start_raises_init_error(expected_msg="Error: Error reading configuration file: Invalid configuration value foo") self.log.info("-includeconf cannot be invalid path") os.remove(os.path.join(self.options.tmpdir, "node0", "relative.conf")) - self.nodes[0].assert_start_raises_init_error(expected_msg="Error: Error reading configuration file: Failed to include configuration file relative.conf") + self.nodes[0].assert_start_raises_init_error( + expected_msg="Error: Error reading configuration file: Failed to include configuration file relative.conf") - self.log.info("multiple -includeconf args can be used from the base config file. subversion should end with 'main; relative; relative2)/'") + self.log.info( + "multiple -includeconf args can be used from the base config file. subversion should end with 'main; relative; relative2)/'") with open(os.path.join(self.options.tmpdir, "node0", "relative.conf"), "w", encoding="utf8") as f: # Restore initial file contents f.write("uacomment=relative\n") @@ -78,5 +83,6 @@ def run_test(self): subversion = self.nodes[0].getnetworkinfo()["subversion"] assert subversion.endswith("main; relative; relative2)/") + if __name__ == '__main__': IncludeConfTest().main() diff --git a/test/functional/feature_initdist.py b/test/functional/feature_initdist.py index 2a8593bf4e..1685f3135b 100755 --- a/test/functional/feature_initdist.py +++ b/test/functional/feature_initdist.py @@ -8,19 +8,19 @@ - verify that initdist coins is spendable """ - from test_framework.test_framework import DefiTestFramework from test_framework.util import connect_nodes_bi -class InitDistTest (DefiTestFramework): + +class InitDistTest(DefiTestFramework): def set_test_params(self): # 3 nodes used just for "clean" balanses for 0&1. node#2 used for generation self.num_nodes = 3 self.extra_args = [ - [ "-dummypos=1", "-spv=0" ], - [ "-dummypos=1", "-spv=0" ], - [ "-dummypos=1", "-spv=0" ], + ["-dummypos=1", "-spv=0"], + ["-dummypos=1", "-spv=0"], + ["-dummypos=1", "-spv=0"], ] self.setup_clean_chain = True @@ -32,19 +32,18 @@ def setup_network(self): self.sync_blocks() def run_test(self): - self.nodes[0].importprivkey(privkey=self.nodes[0].PRIV_KEYS[5].ownerPrivKey, label='initdist') - assert(self.nodes[0].getbalance() == 0) - assert(self.nodes[1].getbalance() == 0) + assert (self.nodes[0].getbalance() == 0) + assert (self.nodes[1].getbalance() == 0) self.nodes[2].generate(100) self.sync_blocks() - assert(self.nodes[0].getbalance() == 50) + assert (self.nodes[0].getbalance() == 50) utxo0 = self.nodes[0].listunspent() - assert(utxo0[0]['address'] == 'mud4VMfbBqXNpbt8ur33KHKx8pk3npSq8c') - assert(utxo0[0]['amount'] == 50.0) - assert(utxo0[0]['spendable'] == True) + assert (utxo0[0]['address'] == 'mud4VMfbBqXNpbt8ur33KHKx8pk3npSq8c') + assert (utxo0[0]['amount'] == 50.0) + assert (utxo0[0]['spendable'] == True) addr = self.nodes[1].getnewaddress("", "legacy") self.nodes[0].sendtoaddress(addr, 42) @@ -52,9 +51,9 @@ def run_test(self): self.nodes[2].generate(1) self.sync_blocks() - assert(self.nodes[0].getbalance() >= 7.99) - assert(self.nodes[1].getbalance() == 42) + assert (self.nodes[0].getbalance() >= 7.99) + assert (self.nodes[1].getbalance() == 42) if __name__ == '__main__': - InitDistTest ().main () + InitDistTest().main() diff --git a/test/functional/feature_jellyfish_initial_funds.py b/test/functional/feature_jellyfish_initial_funds.py index 5611a134a9..cfb5085599 100755 --- a/test/functional/feature_jellyfish_initial_funds.py +++ b/test/functional/feature_jellyfish_initial_funds.py @@ -11,7 +11,8 @@ assert_equal, ) -class JellyfishInitialFundsTest (DefiTestFramework): + +class JellyfishInitialFundsTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True @@ -23,10 +24,11 @@ def run_test(self): # generate one block node.generate(1) - #check balances. should have 200000100 DFI immature balance + # check balances. should have 200000100 DFI immature balance walletinfo = node.getwalletinfo() assert_equal(walletinfo['immature_balance'], 200000100) assert_equal(walletinfo['balance'], 0) + if __name__ == '__main__': - JellyfishInitialFundsTest ().main () + JellyfishInitialFundsTest().main() diff --git a/test/functional/feature_listaccounts_pagination.py b/test/functional/feature_listaccounts_pagination.py index dfdad8b4f2..f33c5cd559 100755 --- a/test/functional/feature_listaccounts_pagination.py +++ b/test/functional/feature_listaccounts_pagination.py @@ -8,6 +8,7 @@ from test_framework.test_framework import DefiTestFramework from test_framework.util import assert_equal + class AccountsValidatingTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 @@ -16,64 +17,65 @@ def set_test_params(self): ['-txnotokens=0', '-amkheight=50', '-eunosheight=101'], ['-txnotokens=0', '-amkheight=50', '-eunosheight=101'], ] + def run_test(self): node = self.nodes[0] node1 = self.nodes[1] node.generate(101) self.sync_blocks() - assert_equal(node.getblockcount(), 101) # eunos + assert_equal(node.getblockcount(), 101) # eunos # Get addresses and set up account account = node.getnewaddress() node.utxostoaccount({account: "10@0"}) node.generate(1) self.sync_blocks() addressInfo = node.getaddressinfo(account) - accountkey1 = addressInfo["scriptPubKey"] + "@0" #key of the first account + accountkey1 = addressInfo["scriptPubKey"] + "@0" # key of the first account accounts = node1.listaccounts() - #make sure one account in the system + # make sure one account in the system assert_equal(len(accounts), 1) assert_equal(accounts[0]["key"], accountkey1) pagination = { - "start": accounts[len(accounts) - 1]["key"], - "including_start": True - } + "start": accounts[len(accounts) - 1]["key"], + "including_start": True + } result2 = node1.listaccounts(pagination) - #check the result has accountkey1 + # check the result has accountkey1 assert_equal(len(result2), 1) assert_equal(result2[0]["key"], accountkey1) ########################################################################################### - #test with two accounts - #add another account + # test with two accounts + # add another account account2 = node.getnewaddress() node.utxostoaccount({account2: "10@0"}) node.generate(1) self.sync_blocks() addressInfo = node.getaddressinfo(account2) - accountkey2 = addressInfo["scriptPubKey"] + "@0" #key of the second account + accountkey2 = addressInfo["scriptPubKey"] + "@0" # key of the second account accounts = node1.listaccounts() - #make sure we have two account in the system + # make sure we have two account in the system assert_equal(len(accounts), 2) # results are in lexograpic order. perform the checks accordingly - if accountkey1 < accountkey2 : + if accountkey1 < accountkey2: assert_equal(accounts[0]["key"], accountkey1) assert_equal(accounts[1]["key"], accountkey2) - else : + else: assert_equal(accounts[0]["key"], accountkey2) assert_equal(accounts[1]["key"], accountkey1) pagination = { - "start": accounts[len(accounts) - 1]["key"],#giving the last element of accounts[] as start - "including_start": True - } + "start": accounts[len(accounts) - 1]["key"], # giving the last element of accounts[] as start + "including_start": True + } result2 = node1.listaccounts(pagination) - #check for length + # check for length assert_equal(len(result2), 1) # results are in lexograpic order. perform the checks accordingly - if accountkey1 < accountkey2 : + if accountkey1 < accountkey2: assert_equal(result2[0]["key"], accountkey2) - else : + else: assert_equal(result2[0]["key"], accountkey1) ########################################################################################### - #Add another account from other node + # Add another account from other node account3 = node1.getnewaddress() node.sendtoaddress(account3, 50) node.generate(1) @@ -83,15 +85,16 @@ def run_test(self): self.sync_blocks() addressInfo = node1.getaddressinfo(account3) accounts = node.listaccounts() - #make sure we have three account in the system + # make sure we have three account in the system assert_equal(len(accounts), 3) pagination = { - "start": accounts[0]["key"], #pass the first key in the accounts list - "including_start": False - } + "start": accounts[0]["key"], # pass the first key in the accounts list + "including_start": False + } result2 = node1.listaccounts(pagination) - #check for length, we should get 2 entries since listaccounts RPC should return all accounts even with pagination. + # check for length, we should get 2 entries since listaccounts RPC should return all accounts even with pagination. assert_equal(len(result2), 2) + if __name__ == '__main__': - AccountsValidatingTest().main () + AccountsValidatingTest().main() diff --git a/test/functional/feature_loan.py b/test/functional/feature_loan.py index aa689026c9..55b5c7f3ac 100755 --- a/test/functional/feature_loan.py +++ b/test/functional/feature_loan.py @@ -14,14 +14,17 @@ import time from decimal import Decimal -class LoanTest (DefiTestFramework): + +class LoanTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 self.setup_clean_chain = True self.extra_args = [ - ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-bayfrontgardensheight=1', '-eunosheight=1', '-txindex=1', '-fortcanningheight=1'], - ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-bayfrontgardensheight=1', '-eunosheight=1', '-txindex=1', '-fortcanningheight=1'] - ] + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-bayfrontgardensheight=1', '-eunosheight=1', + '-txindex=1', '-fortcanningheight=1'], + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-bayfrontgardensheight=1', '-eunosheight=1', + '-txindex=1', '-fortcanningheight=1'] + ] def run_test(self): self.nodes[0].generate(300) @@ -52,7 +55,8 @@ def run_test(self): # setup oracle oracle_address1 = self.nodes[0].getnewaddress("", "legacy") - price_feeds = [{"currency": "USD", "token": "DFI"}, {"currency": "USD", "token": "BTC"}, {"currency": "USD", "token": "TSLA"}] + price_feeds = [{"currency": "USD", "token": "DFI"}, {"currency": "USD", "token": "BTC"}, + {"currency": "USD", "token": "TSLA"}] oracle_id1 = self.nodes[0].appointoracle(oracle_address1, price_feeds, 10) self.nodes[0].generate(1) oracle_address2 = self.nodes[0].getnewaddress("", "legacy") @@ -60,25 +64,27 @@ def run_test(self): self.nodes[0].generate(1) # feed oracle - oracle1_prices = [{"currency": "USD", "tokenAmount": "10@TSLA"}, {"currency": "USD", "tokenAmount": "10@DFI"}, {"currency": "USD", "tokenAmount": "10@BTC"}] + oracle1_prices = [{"currency": "USD", "tokenAmount": "10@TSLA"}, {"currency": "USD", "tokenAmount": "10@DFI"}, + {"currency": "USD", "tokenAmount": "10@BTC"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(oracle_id1, timestamp, oracle1_prices) self.nodes[0].generate(1) - oracle2_prices = [{"currency": "USD", "tokenAmount": "15@TSLA"}, {"currency": "USD", "tokenAmount": "15@DFI"}, {"currency": "USD", "tokenAmount": "15@BTC"}] + oracle2_prices = [{"currency": "USD", "tokenAmount": "15@TSLA"}, {"currency": "USD", "tokenAmount": "15@DFI"}, + {"currency": "USD", "tokenAmount": "15@BTC"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(oracle_id2, timestamp, oracle2_prices) self.nodes[0].generate(1) # set DFI an BTC as collateral tokens self.nodes[0].setcollateraltoken({ - 'token': "DFI", - 'factor': 1, - 'fixedIntervalPriceId': "DFI/USD"}) + 'token': "DFI", + 'factor': 1, + 'fixedIntervalPriceId': "DFI/USD"}) self.nodes[0].generate(1) self.nodes[0].setcollateraltoken({ - 'token': "BTC", - 'factor': 1, - 'fixedIntervalPriceId': "BTC/USD"}) + 'token': "BTC", + 'factor': 1, + 'fixedIntervalPriceId': "BTC/USD"}) self.nodes[0].generate(1) # Create loan schemes @@ -88,7 +94,7 @@ def run_test(self): self.nodes[0].generate(1) # Create vault - vaultId1 = self.nodes[0].createvault(account, '') # default loan scheme + vaultId1 = self.nodes[0].createvault(account, '') # default loan scheme self.nodes[0].generate(5) # deposit DFI and BTC to vault1 @@ -99,27 +105,27 @@ def run_test(self): # set TSLA as loan token self.nodes[0].setloantoken({ - 'symbol': "TSLA", - 'name': "Tesla Token", - 'fixedIntervalPriceId': "TSLA/USD", - 'mintable': True, - 'interest': 1}) + 'symbol': "TSLA", + 'name': "Tesla Token", + 'fixedIntervalPriceId': "TSLA/USD", + 'mintable': True, + 'interest': 1}) self.nodes[0].generate(6) # take loan self.nodes[0].takeloan({ - 'vaultId': vaultId1, - 'amounts': "1000@TSLA"}) + 'vaultId': vaultId1, + 'amounts': "1000@TSLA"}) self.nodes[0].generate(1) accountBal = self.nodes[0].getaccount(account) assert_equal(accountBal, ['1000.00000000@DFI', '1000.00000000@BTC', '1000.00000000@TSLA']) - self.nodes[0].generate(60) # ~10 hours + self.nodes[0].generate(60) # ~10 hours vault1 = self.nodes[0].getvault(vaultId1) interests = self.nodes[0].getinterest( vault1['loanSchemeId'], 'TSLA' ) - totalLoanAmount = (1000+interests[0]['totalInterest']) # Initial loan taken + totalLoanAmount = (1000 + interests[0]['totalInterest']) # Initial loan taken assert_equal(Decimal(vault1['loanAmounts'][0].split("@")[0]), totalLoanAmount) # Trigger liquidation updating price in oracle @@ -143,7 +149,7 @@ def run_test(self): self.nodes[0].placeauctionbid(vaultId1, 0, account, "410@TSLA") except JSONRPCException as e: errorString = e.error['message'] - assert("First bid should include liquidation penalty of 5%" in errorString) + assert ("First bid should include liquidation penalty of 5%" in errorString) self.nodes[0].minttokens("1000@TSLA") self.nodes[0].generate(1) @@ -161,17 +167,17 @@ def run_test(self): # new account for new bidder self.nodes[0].generate(1) account2 = self.nodes[0].getnewaddress() - self.nodes[0].accounttoaccount(account, {account2: "1000@TSLA"} ) + self.nodes[0].accounttoaccount(account, {account2: "1000@TSLA"}) self.nodes[0].generate(1) # Fail auction bid less that 1% higher try: - self.nodes[0].placeauctionbid(vaultId1, 0, account2, "555@TSLA") # just under 1% + self.nodes[0].placeauctionbid(vaultId1, 0, account2, "555@TSLA") # just under 1% except JSONRPCException as e: errorString = e.error['message'] - assert("Bid override should be at least 1% higher than current one" in errorString) + assert ("Bid override should be at least 1% higher than current one" in errorString) - self.nodes[0].placeauctionbid(vaultId1, 0, account2, "555.5@TSLA") # above 1% + self.nodes[0].placeauctionbid(vaultId1, 0, account2, "555.5@TSLA") # above 1% self.nodes[0].generate(1) # check balances are right after greater bid @@ -205,8 +211,9 @@ def run_test(self): auctionlist = self.nodes[0].listauctions() assert_equal(len(auctionlist[0]['batches']), 2) - self.nodes[0].placeauctionbid(vaultId1, 0, account, "515@TSLA") # above 5% and leave vault with some loan to exit liquidation state - self.nodes[0].generate(40) # let auction end + self.nodes[0].placeauctionbid(vaultId1, 0, account, + "515@TSLA") # above 5% and leave vault with some loan to exit liquidation state + self.nodes[0].generate(40) # let auction end auction = self.nodes[0].listauctionhistory(account)[0] assert_equal(auction['winner'], account) @@ -217,7 +224,7 @@ def run_test(self): assert_equal(auction['auctionWon'].sort(), ['399.99999600@DFI', '399.99999600@DFI'].sort()) self.nodes[0].placeauctionbid(vaultId1, 0, account, "259@TSLA") - self.nodes[0].generate(40) # let auction end + self.nodes[0].generate(40) # let auction end auctions = self.nodes[0].listauctionhistory() assert_equal(len(auctions), 3) @@ -241,7 +248,6 @@ def run_test(self): assert_equal(vault1['state'], "active") assert_equal(accountBal, ['1600.00000000@DFI', '1600.00000000@BTC', '226.00000000@TSLA']) - self.nodes[0].deposittovault(vaultId1, account, '600@DFI') self.nodes[0].generate(1) vault1 = self.nodes[0].getvault(vaultId1) @@ -275,14 +281,16 @@ def run_test(self): self.nodes[0].placeauctionbid(vaultId1, 0, "*", "1600@TSLA") except JSONRPCException as e: errorString = e.error['message'] - assert("Not enough tokens on account, call sendtokenstoaddress to increase it." in errorString) + assert ("Not enough tokens on account, call sendtokenstoaddress to increase it." in errorString) newAddress = self.nodes[0].getnewaddress("") - self.nodes[0].sendtokenstoaddress({}, {newAddress: "1600@TSLA"}) # newAddress has now the highest amount of TSLA token + self.nodes[0].sendtokenstoaddress({}, { + newAddress: "1600@TSLA"}) # newAddress has now the highest amount of TSLA token self.nodes[0].generate(1) - self.nodes[0].placeauctionbid(vaultId1, 0, "*", "1600@TSLA") # Autoselect address with highest amount of TSLA token - self.nodes[0].generate(40) # let auction end + self.nodes[0].placeauctionbid(vaultId1, 0, "*", + "1600@TSLA") # Autoselect address with highest amount of TSLA token + self.nodes[0].generate(40) # let auction end auction = self.nodes[0].listauctionhistory(newAddress)[0] assert_equal(auction['winner'], newAddress) @@ -291,6 +299,6 @@ def run_test(self): assert_equal(auction['batchIndex'], 0) assert_equal(auction['auctionBid'], "1600.00000000@TSLA") + if __name__ == '__main__': LoanTest().main() - diff --git a/test/functional/feature_loan_auctions.py b/test/functional/feature_loan_auctions.py index 035dbf0c78..79b68ffeb5 100755 --- a/test/functional/feature_loan_auctions.py +++ b/test/functional/feature_loan_auctions.py @@ -13,13 +13,15 @@ import calendar import time -class AuctionsTest (DefiTestFramework): + +class AuctionsTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True self.extra_args = [ - ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-txindex=1', '-fortcanningheight=1'] - ] + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-txindex=1', + '-fortcanningheight=1'] + ] def run_test(self): self.nodes[0].generate(500) @@ -56,50 +58,56 @@ def run_test(self): # setup oracle oracle_address1 = self.nodes[0].getnewaddress("", "legacy") - price_feeds1 = [{"currency": "USD", "token": "DFI"}, {"currency": "USD", "token": "BTC"}, {"currency": "USD", "token": "TSLA"}, {"currency": "USD", "token": "GOOGL"}, {"currency": "USD", "token": "TWTR"}, {"currency": "USD", "token": "MSFT"}] + price_feeds1 = [{"currency": "USD", "token": "DFI"}, {"currency": "USD", "token": "BTC"}, + {"currency": "USD", "token": "TSLA"}, {"currency": "USD", "token": "GOOGL"}, + {"currency": "USD", "token": "TWTR"}, {"currency": "USD", "token": "MSFT"}] oracle_id1 = self.nodes[0].appointoracle(oracle_address1, price_feeds1, 10) self.nodes[0].generate(1) # feed oracle - oracle1_prices = [{"currency": "USD", "tokenAmount": "100@TSLA"}, {"currency": "USD", "tokenAmount": "100@GOOGL"}, {"currency": "USD", "tokenAmount": "100@TWTR"}, {"currency": "USD", "tokenAmount": "100@MSFT"}, {"currency": "USD", "tokenAmount": "100@DFI"}, {"currency": "USD", "tokenAmount": "100@BTC"}] + oracle1_prices = [{"currency": "USD", "tokenAmount": "100@TSLA"}, + {"currency": "USD", "tokenAmount": "100@GOOGL"}, + {"currency": "USD", "tokenAmount": "100@TWTR"}, + {"currency": "USD", "tokenAmount": "100@MSFT"}, {"currency": "USD", "tokenAmount": "100@DFI"}, + {"currency": "USD", "tokenAmount": "100@BTC"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(oracle_id1, timestamp, oracle1_prices) self.nodes[0].generate(6) # set DFI an BTC as collateral tokens self.nodes[0].setcollateraltoken({ - 'token': "DFI", - 'factor': 1, - 'fixedIntervalPriceId': "DFI/USD"}) + 'token': "DFI", + 'factor': 1, + 'fixedIntervalPriceId': "DFI/USD"}) self.nodes[0].setcollateraltoken({ - 'token': "BTC", - 'factor': 1, - 'fixedIntervalPriceId': "BTC/USD"}) + 'token': "BTC", + 'factor': 1, + 'fixedIntervalPriceId': "BTC/USD"}) self.nodes[0].setloantoken({ - 'symbol': "TSLA", - 'name': "Tesla Token", - 'fixedIntervalPriceId': "TSLA/USD", - 'mintable': True, - 'interest': 1}) + 'symbol': "TSLA", + 'name': "Tesla Token", + 'fixedIntervalPriceId': "TSLA/USD", + 'mintable': True, + 'interest': 1}) self.nodes[0].setloantoken({ - 'symbol': "GOOGL", - 'name': "Google", - 'fixedIntervalPriceId': "GOOGL/USD", - 'mintable': True, - 'interest': 1}) + 'symbol': "GOOGL", + 'name': "Google", + 'fixedIntervalPriceId': "GOOGL/USD", + 'mintable': True, + 'interest': 1}) self.nodes[0].setloantoken({ - 'symbol': "TWTR", - 'name': "Twitter", - 'fixedIntervalPriceId': "TWTR/USD", - 'mintable': True, - 'interest': 1}) + 'symbol': "TWTR", + 'name': "Twitter", + 'fixedIntervalPriceId': "TWTR/USD", + 'mintable': True, + 'interest': 1}) self.nodes[0].setloantoken({ - 'symbol': "MSFT", - 'name': "Microsoft", - 'fixedIntervalPriceId': "MSFT/USD", - 'mintable': True, - 'interest': 1}) - self.nodes[0].generate(6) # let active price update + 'symbol': "MSFT", + 'name': "Microsoft", + 'fixedIntervalPriceId': "MSFT/USD", + 'mintable': True, + 'interest': 1}) + self.nodes[0].generate(6) # let active price update idDFI = list(self.nodes[0].gettoken("DFI").keys())[0] iddUSD = list(self.nodes[0].gettoken("DUSD").keys())[0] @@ -211,30 +219,32 @@ def run_test(self): self.nodes[0].generate(1) self.nodes[0].takeloan({ - 'vaultId': vaultId1, - 'amounts': "5@TSLA"}) + 'vaultId': vaultId1, + 'amounts': "5@TSLA"}) self.nodes[0].generate(1) # trigger liquidation - oracle1_prices = [{"currency": "USD", "tokenAmount": "101@TSLA"}, {"currency": "USD", "tokenAmount": "100@DFI"}, {"currency": "USD", "tokenAmount": "100@BTC"}] + oracle1_prices = [{"currency": "USD", "tokenAmount": "101@TSLA"}, {"currency": "USD", "tokenAmount": "100@DFI"}, + {"currency": "USD", "tokenAmount": "100@BTC"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(oracle_id1, timestamp, oracle1_prices) - self.nodes[0].generate(12) # let price update and trigger liquidation of vault + self.nodes[0].generate(12) # let price update and trigger liquidation of vault auctionlist = self.nodes[0].listauctions() assert_equal(len(auctionlist), 1) assert_equal(auctionlist[0]["liquidationHeight"], 570) - self.nodes[0].generate(36) # let auction end without bids + self.nodes[0].generate(36) # let auction end without bids auctionlist = self.nodes[0].listauctions() assert_equal(len(auctionlist), 1) assert_equal(auctionlist[0]["liquidationHeight"], 607) # Case 2 # reset prices - oracle1_prices = [{"currency": "USD", "tokenAmount": "100@TSLA"}, {"currency": "USD", "tokenAmount": "100@DFI"}, {"currency": "USD", "tokenAmount": "100@BTC"}] + oracle1_prices = [{"currency": "USD", "tokenAmount": "100@TSLA"}, {"currency": "USD", "tokenAmount": "100@DFI"}, + {"currency": "USD", "tokenAmount": "100@BTC"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(oracle_id1, timestamp, oracle1_prices) - self.nodes[0].generate(12) # let price update and trigger liquidation of vault + self.nodes[0].generate(12) # let price update and trigger liquidation of vault vaultId2 = self.nodes[0].createvault(account, 'LOAN200') self.nodes[0].generate(1) @@ -245,14 +255,15 @@ def run_test(self): self.nodes[0].generate(1) self.nodes[0].takeloan({ - 'vaultId': vaultId2, - 'amounts': "60@TSLA"}) + 'vaultId': vaultId2, + 'amounts': "60@TSLA"}) self.nodes[0].generate(1) - oracle1_prices = [{"currency": "USD", "tokenAmount": "101@TSLA"}, {"currency": "USD", "tokenAmount": "100@DFI"}, {"currency": "USD", "tokenAmount": "100@BTC"}] + oracle1_prices = [{"currency": "USD", "tokenAmount": "101@TSLA"}, {"currency": "USD", "tokenAmount": "100@DFI"}, + {"currency": "USD", "tokenAmount": "100@BTC"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(oracle_id1, timestamp, oracle1_prices) - self.nodes[0].generate(12) # let price update and trigger liquidation of vault + self.nodes[0].generate(12) # let price update and trigger liquidation of vault vault2 = self.nodes[0].getvault(vaultId2) assert_equal(vault2["state"], "inLiquidation") assert_equal(vault2["batches"][0]["collaterals"], ['49.99999980@DFI', '49.99999980@BTC']) @@ -260,7 +271,7 @@ def run_test(self): self.nodes[0].placeauctionbid(vaultId2, 0, account, "59.41@TSLA") - self.nodes[0].generate(35) # let auction end + self.nodes[0].generate(35) # let auction end interest = self.nodes[0].getinterest('LOAN200', "TSLA") vault2 = self.nodes[0].getvault(vaultId2) @@ -269,18 +280,19 @@ def run_test(self): assert_greater_than(Decimal(vault2["collateralAmounts"][0].split('@')[0]), Decimal(10.00000020)) assert_equal(vault2["informativeRatio"], Decimal("264.70081509")) self.nodes[0].paybackloan({ - 'vaultId': vaultId2, - 'from': account, - 'amounts': vault2["loanAmounts"]}) + 'vaultId': vaultId2, + 'from': account, + 'amounts': vault2["loanAmounts"]}) self.nodes[0].generate(1) self.nodes[0].closevault(vaultId2, account) # Case 3 # reset prices - oracle1_prices = [{"currency": "USD", "tokenAmount": "100@TSLA"}, {"currency": "USD", "tokenAmount": "100@DFI"}, {"currency": "USD", "tokenAmount": "100@BTC"}] + oracle1_prices = [{"currency": "USD", "tokenAmount": "100@TSLA"}, {"currency": "USD", "tokenAmount": "100@DFI"}, + {"currency": "USD", "tokenAmount": "100@BTC"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(oracle_id1, timestamp, oracle1_prices) - self.nodes[0].generate(12) # let price update + self.nodes[0].generate(12) # let price update vaultId3 = self.nodes[0].createvault(account, 'LOAN200') self.nodes[0].generate(1) @@ -292,17 +304,18 @@ def run_test(self): vault3 = self.nodes[0].getvault(vaultId3) self.nodes[0].takeloan({ - 'vaultId': vaultId3, - 'amounts': "60@TSLA"}) + 'vaultId': vaultId3, + 'amounts': "60@TSLA"}) self.nodes[0].generate(1) - oracle1_prices = [{"currency": "USD", "tokenAmount": "101@TSLA"}, {"currency": "USD", "tokenAmount": "100@DFI"}, {"currency": "USD", "tokenAmount": "100@BTC"}] + oracle1_prices = [{"currency": "USD", "tokenAmount": "101@TSLA"}, {"currency": "USD", "tokenAmount": "100@DFI"}, + {"currency": "USD", "tokenAmount": "100@BTC"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(oracle_id1, timestamp, oracle1_prices) - self.nodes[0].generate(12) # let price update and trigger liquidation of vault + self.nodes[0].generate(12) # let price update and trigger liquidation of vault self.nodes[0].placeauctionbid(vaultId3, 0, account, "54.46@TSLA") - self.nodes[0].generate(31) # let auction end + self.nodes[0].generate(31) # let auction end vault3 = self.nodes[0].getvault(vaultId3) assert_equal(vault3["state"], "active") auctionlist = self.nodes[0].listauctions() @@ -310,18 +323,19 @@ def run_test(self): assert_greater_than(Decimal(vault3["collateralAmounts"][0].split('@')[0]), Decimal(10.00000020)) self.nodes[0].paybackloan({ - 'vaultId': vaultId3, - 'from': account, - 'amounts': vault3["loanAmounts"]}) + 'vaultId': vaultId3, + 'from': account, + 'amounts': vault3["loanAmounts"]}) self.nodes[0].generate(1) self.nodes[0].closevault(vaultId3, account) # Case 4 # reset prices - oracle1_prices = [{"currency": "USD", "tokenAmount": "100@TSLA"}, {"currency": "USD", "tokenAmount": "100@DFI"}, {"currency": "USD", "tokenAmount": "100@BTC"}] + oracle1_prices = [{"currency": "USD", "tokenAmount": "100@TSLA"}, {"currency": "USD", "tokenAmount": "100@DFI"}, + {"currency": "USD", "tokenAmount": "100@BTC"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(oracle_id1, timestamp, oracle1_prices) - self.nodes[0].generate(12) # let price update + self.nodes[0].generate(12) # let price update vaultId4 = self.nodes[0].createvault(account, 'LOAN200') self.nodes[0].generate(1) @@ -331,16 +345,17 @@ def run_test(self): self.nodes[0].deposittovault(vaultId4, account, '5@BTC') self.nodes[0].generate(1) self.nodes[0].takeloan({ - 'vaultId': vaultId4, - 'amounts': "5@TSLA"}) + 'vaultId': vaultId4, + 'amounts': "5@TSLA"}) self.nodes[0].generate(1) - oracle1_prices = [{"currency": "USD", "tokenAmount": "101@TSLA"}, {"currency": "USD", "tokenAmount": "100@DFI"}, {"currency": "USD", "tokenAmount": "100@BTC"}] + oracle1_prices = [{"currency": "USD", "tokenAmount": "101@TSLA"}, {"currency": "USD", "tokenAmount": "100@DFI"}, + {"currency": "USD", "tokenAmount": "100@BTC"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(oracle_id1, timestamp, oracle1_prices) - self.nodes[0].generate(12) # let price update and trigger liquidation of vault + self.nodes[0].generate(12) # let price update and trigger liquidation of vault self.nodes[0].placeauctionbid(vaultId4, 0, account, "7.92@TSLA") - self.nodes[0].generate(31) # let auction end + self.nodes[0].generate(31) # let auction end vault4 = self.nodes[0].getvault(vaultId4) assert_equal(len(vault4["loanAmounts"]), 0) @@ -352,7 +367,7 @@ def run_test(self): self.nodes[0].withdrawfromvault(vaultId4, account, "2.50710426@DFI") self.nodes[0].generate(1) - assert_equal(Decimal(self.nodes[0].getaccount(account)[0].split("@")[0]), collateralAmount+accountDFIBalance) + assert_equal(Decimal(self.nodes[0].getaccount(account)[0].split("@")[0]), collateralAmount + accountDFIBalance) vault4 = self.nodes[0].getvault(vaultId4) assert_equal(len(vault4["collateralAmounts"]), 0) @@ -360,14 +375,16 @@ def run_test(self): self.nodes[0].closevault(vaultId4, account) self.nodes[0].generate(1) - assert_equal(Decimal(self.nodes[0].getaccount(account)[0].split("@")[0]), Decimal(0.5) + collateralAmount + accountDFIBalance) + assert_equal(Decimal(self.nodes[0].getaccount(account)[0].split("@")[0]), + Decimal(0.5) + collateralAmount + accountDFIBalance) # Case 5 # reset prices - oracle1_prices = [{"currency": "USD", "tokenAmount": "100@TSLA"}, {"currency": "USD", "tokenAmount": "100@DFI"}, {"currency": "USD", "tokenAmount": "100@BTC"}] + oracle1_prices = [{"currency": "USD", "tokenAmount": "100@TSLA"}, {"currency": "USD", "tokenAmount": "100@DFI"}, + {"currency": "USD", "tokenAmount": "100@BTC"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(oracle_id1, timestamp, oracle1_prices) - self.nodes[0].generate(12) # let price update + self.nodes[0].generate(12) # let price update vaultId5 = self.nodes[0].createvault(account, 'LOAN200') self.nodes[0].generate(1) @@ -377,13 +394,14 @@ def run_test(self): self.nodes[0].deposittovault(vaultId5, account, '100@BTC') self.nodes[0].generate(1) self.nodes[0].takeloan({ - 'vaultId': vaultId5, - 'amounts': "100@TSLA"}) + 'vaultId': vaultId5, + 'amounts': "100@TSLA"}) self.nodes[0].generate(1) - oracle1_prices = [{"currency": "USD", "tokenAmount": "330@TSLA"}, {"currency": "USD", "tokenAmount": "220@DFI"}, {"currency": "USD", "tokenAmount": "220@BTC"}] + oracle1_prices = [{"currency": "USD", "tokenAmount": "330@TSLA"}, {"currency": "USD", "tokenAmount": "220@DFI"}, + {"currency": "USD", "tokenAmount": "220@BTC"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(oracle_id1, timestamp, oracle1_prices) - self.nodes[0].generate(12) # let price update and trigger liquidation of vault + self.nodes[0].generate(12) # let price update and trigger liquidation of vault vault5 = self.nodes[0].getvault(vaultId5) assert_equal(len(vault5["batches"]), 5) @@ -392,17 +410,19 @@ def run_test(self): self.nodes[0].placeauctionbid(vaultId5, 4, account, "10@TSLA") self.nodes[0].generate(1) - self.nodes[0].generate(32) # let auction end + self.nodes[0].generate(32) # let auction end vault5 = self.nodes[0].getvault(vaultId5) assert_equal(len(vault5["batches"]), 4) # Case 6 Test two loan token # Reset prices - oracle1_prices = [{"currency": "USD", "tokenAmount": "100@TSLA"}, {"currency": "USD", "tokenAmount": "100@GOOGL"}, {"currency": "USD", "tokenAmount": "100@DFI"}, {"currency": "USD", "tokenAmount": "100@BTC"}] + oracle1_prices = [{"currency": "USD", "tokenAmount": "100@TSLA"}, + {"currency": "USD", "tokenAmount": "100@GOOGL"}, + {"currency": "USD", "tokenAmount": "100@DFI"}, {"currency": "USD", "tokenAmount": "100@BTC"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(oracle_id1, timestamp, oracle1_prices) - self.nodes[0].generate(12) # let price update + self.nodes[0].generate(12) # let price update vaultId6 = self.nodes[0].createvault(account, 'LOAN200') self.nodes[0].generate(1) @@ -413,19 +433,21 @@ def run_test(self): # Take TSLA loan self.nodes[0].takeloan({ - 'vaultId': vaultId6, - 'amounts': "172@TSLA"}) + 'vaultId': vaultId6, + 'amounts': "172@TSLA"}) # Take GOOGL loan self.nodes[0].takeloan({ - 'vaultId': vaultId6, - 'amounts': "18@GOOGL"}) + 'vaultId': vaultId6, + 'amounts': "18@GOOGL"}) self.nodes[0].generate(1) - oracle1_prices = [{"currency": "USD", "tokenAmount": "330@TSLA"}, {"currency": "USD", "tokenAmount": "330@GOOGL"}, {"currency": "USD", "tokenAmount": "220@DFI"}, {"currency": "USD", "tokenAmount": "220@BTC"}] + oracle1_prices = [{"currency": "USD", "tokenAmount": "330@TSLA"}, + {"currency": "USD", "tokenAmount": "330@GOOGL"}, + {"currency": "USD", "tokenAmount": "220@DFI"}, {"currency": "USD", "tokenAmount": "220@BTC"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(oracle_id1, timestamp, oracle1_prices) - self.nodes[0].generate(12) # let price update and trigger liquidation of vault + self.nodes[0].generate(12) # let price update and trigger liquidation of vault vault6 = self.nodes[0].getvault(vaultId6) batches = vault6['batches'] @@ -438,7 +460,7 @@ def run_test(self): assert_equal(len(collaterals), 2) DFI = Decimal(collaterals[0].replace('@DFI', '')) BTC = Decimal(collaterals[1].replace('@BTC', '')) - assert(DFI * Decimal('220') + BTC * Decimal('220') < 10000) + assert (DFI * Decimal('220') + BTC * Decimal('220') < 10000) collateralDFI += DFI collateralBTC += BTC @@ -451,7 +473,7 @@ def run_test(self): oracle1_prices = [{"currency": "USD", "tokenAmount": "100@TSLA"}, {"currency": "USD", "tokenAmount": "100@DFI"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(oracle_id1, timestamp, oracle1_prices) - self.nodes[0].generate(12) # let price update + self.nodes[0].generate(12) # let price update vaultId7 = self.nodes[0].createvault(account, 'LOAN120') self.nodes[0].generate(1) @@ -461,31 +483,33 @@ def run_test(self): # Take TSLA loan self.nodes[0].takeloan({ - 'vaultId': vaultId7, - 'amounts': "80@TSLA"}) + 'vaultId': vaultId7, + 'amounts': "80@TSLA"}) self.nodes[0].generate(1) oracle1_prices = [{"currency": "USD", "tokenAmount": "129@TSLA"}, {"currency": "USD", "tokenAmount": "71@DFI"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(oracle_id1, timestamp, oracle1_prices) - self.nodes[0].generate(12) # let price update and trigger liquidation of vault + self.nodes[0].generate(12) # let price update and trigger liquidation of vault vault7 = self.nodes[0].getvault(vaultId7) batches = vault7['batches'] assert_equal(len(batches), 1) loan_amount = batches[0]["loan"].split("@")[0] - loan_value = float(loan_amount) * 129 # TSLA USD value + loan_value = float(loan_amount) * 129 # TSLA USD value collateral_amount = batches[0]["collaterals"][0].split("@")[0] - collateral_value = float(collateral_amount) * 71 # DFI USD value - assert(loan_value > collateral_value) + collateral_value = float(collateral_amount) * 71 # DFI USD value + assert (loan_value > collateral_value) # Case 8 With max possible oracle deviation. Loantoken value 100 -> 129 && collateral value 100 -> 71. Multi tokens # Reset prices - oracle1_prices = [{"currency": "USD", "tokenAmount": "100@TSLA"}, {"currency": "USD", "tokenAmount": "100@GOOGL"}, {"currency": "USD", "tokenAmount": "100@DFI"}, {"currency": "USD", "tokenAmount": "100@BTC"}] + oracle1_prices = [{"currency": "USD", "tokenAmount": "100@TSLA"}, + {"currency": "USD", "tokenAmount": "100@GOOGL"}, + {"currency": "USD", "tokenAmount": "100@DFI"}, {"currency": "USD", "tokenAmount": "100@BTC"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(oracle_id1, timestamp, oracle1_prices) - self.nodes[0].generate(12) # let price update + self.nodes[0].generate(12) # let price update vaultId7 = self.nodes[0].createvault(account, 'LOAN120') self.nodes[0].generate(1) @@ -497,18 +521,20 @@ def run_test(self): # Take TSLA loan self.nodes[0].takeloan({ - 'vaultId': vaultId7, - 'amounts': "100@TSLA"}) + 'vaultId': vaultId7, + 'amounts': "100@TSLA"}) # Take GOOGL loan self.nodes[0].takeloan({ - 'vaultId': vaultId7, - 'amounts': "60@GOOGL"}) + 'vaultId': vaultId7, + 'amounts': "60@GOOGL"}) self.nodes[0].generate(1) - oracle1_prices = [{"currency": "USD", "tokenAmount": "129@TSLA"}, {"currency": "USD", "tokenAmount": "129@GOOGL"}, {"currency": "USD", "tokenAmount": "71@DFI"}, {"currency": "USD", "tokenAmount": "71@BTC"}] + oracle1_prices = [{"currency": "USD", "tokenAmount": "129@TSLA"}, + {"currency": "USD", "tokenAmount": "129@GOOGL"}, {"currency": "USD", "tokenAmount": "71@DFI"}, + {"currency": "USD", "tokenAmount": "71@BTC"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(oracle_id1, timestamp, oracle1_prices) - self.nodes[0].generate(12) # let price update and trigger liquidation of vault + self.nodes[0].generate(12) # let price update and trigger liquidation of vault vault7 = self.nodes[0].getvault(vaultId7) batches = vault7['batches'] @@ -516,23 +542,29 @@ def run_test(self): for batch in batches: assert_equal(len(batch['collaterals']), 2) loan_amount_TSLA = batches[0]["loan"].split("@")[0] - loan_value_TSLA = float(loan_amount_TSLA) * 129 # TSLA USD value - collateral_amount = float(batches[0]["collaterals"][0].split("@")[0]) + float(batches[0]["collaterals"][1].split("@")[0]) - collateral_value = collateral_amount * 71 # collaterals USD value - assert(loan_value_TSLA > collateral_value) + loan_value_TSLA = float(loan_amount_TSLA) * 129 # TSLA USD value + collateral_amount = float(batches[0]["collaterals"][0].split("@")[0]) + float( + batches[0]["collaterals"][1].split("@")[0]) + collateral_value = collateral_amount * 71 # collaterals USD value + assert (loan_value_TSLA > collateral_value) loan_amount_GOOGL = batches[1]["loan"].split("@")[0] - loan_value_GOOGL = float(loan_amount_GOOGL) * 129 # GOOGL USD value - collateral_amount = float(batches[1]["collaterals"][0].split("@")[0]) + float(batches[1]["collaterals"][1].split("@")[0]) - collateral_value = float(collateral_amount) * 71 # collaterals USD value - assert(loan_value_GOOGL > collateral_value) + loan_value_GOOGL = float(loan_amount_GOOGL) * 129 # GOOGL USD value + collateral_amount = float(batches[1]["collaterals"][0].split("@")[0]) + float( + batches[1]["collaterals"][1].split("@")[0]) + collateral_value = float(collateral_amount) * 71 # collaterals USD value + assert (loan_value_GOOGL > collateral_value) # Case 9 Auction with dust amount # Reset prices - oracle1_prices = [{"currency": "USD", "tokenAmount": "100@TSLA"}, {"currency": "USD", "tokenAmount": "100@GOOGL"}, {"currency": "USD", "tokenAmount": "100@TWTR"}, {"currency": "USD", "tokenAmount": "100@MSFT"}, {"currency": "USD", "tokenAmount": "100@DFI"}, {"currency": "USD", "tokenAmount": "100@BTC"}] + oracle1_prices = [{"currency": "USD", "tokenAmount": "100@TSLA"}, + {"currency": "USD", "tokenAmount": "100@GOOGL"}, + {"currency": "USD", "tokenAmount": "100@TWTR"}, + {"currency": "USD", "tokenAmount": "100@MSFT"}, {"currency": "USD", "tokenAmount": "100@DFI"}, + {"currency": "USD", "tokenAmount": "100@BTC"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(oracle_id1, timestamp, oracle1_prices) - self.nodes[0].generate(12) # let price update + self.nodes[0].generate(12) # let price update vaultId8 = self.nodes[0].createvault(account, 'LOAN200') self.nodes[0].generate(1) @@ -544,31 +576,36 @@ def run_test(self): # Take TSLA loan self.nodes[0].takeloan({ - 'vaultId': vaultId8, - 'amounts': "25@TSLA"}) + 'vaultId': vaultId8, + 'amounts': "25@TSLA"}) # Take GOOGL loan self.nodes[0].takeloan({ - 'vaultId': vaultId8, - 'amounts': "25@GOOGL"}) + 'vaultId': vaultId8, + 'amounts': "25@GOOGL"}) # Take TWTR loan self.nodes[0].takeloan({ - 'vaultId': vaultId8, - 'amounts': "25@TWTR"}) + 'vaultId': vaultId8, + 'amounts': "25@TWTR"}) # Take MSFT loan self.nodes[0].takeloan({ - 'vaultId': vaultId8, - 'amounts': "25@MSFT"}) + 'vaultId': vaultId8, + 'amounts': "25@MSFT"}) self.nodes[0].generate(1) vault8 = self.nodes[0].getvault(vaultId8) - oracle1_prices = [{"currency": "USD", "tokenAmount": "300@TSLA"}, {"currency": "USD", "tokenAmount": "300@GOOGL"}, {"currency": "USD", "tokenAmount": "300@TWTR"}, {"currency": "USD", "tokenAmount": "300@MSFT"}, {"currency": "USD", "tokenAmount": "200.0001@DFI"}, {"currency": "USD", "tokenAmount": "200.0001@BTC"}] + oracle1_prices = [{"currency": "USD", "tokenAmount": "300@TSLA"}, + {"currency": "USD", "tokenAmount": "300@GOOGL"}, + {"currency": "USD", "tokenAmount": "300@TWTR"}, + {"currency": "USD", "tokenAmount": "300@MSFT"}, + {"currency": "USD", "tokenAmount": "200.0001@DFI"}, + {"currency": "USD", "tokenAmount": "200.0001@BTC"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(oracle_id1, timestamp, oracle1_prices) - self.nodes[0].generate(12) # let price update and trigger liquidation of vault + self.nodes[0].generate(12) # let price update and trigger liquidation of vault vault8 = self.nodes[0].getvault(vaultId8) batches = vault8['batches'] @@ -579,5 +616,6 @@ def run_test(self): assert_equal(batches[2]["loan"], '0.00001251@TSLA') assert_equal(batches[3]["loan"], '0.00001251@TWTR') + if __name__ == '__main__': AuctionsTest().main() diff --git a/test/functional/feature_loan_basics.py b/test/functional/feature_loan_basics.py index 9f4e024acd..bca2258674 100755 --- a/test/functional/feature_loan_basics.py +++ b/test/functional/feature_loan_basics.py @@ -14,16 +14,19 @@ import time from decimal import Decimal -class LoanTakeLoanTest (DefiTestFramework): + +class LoanTakeLoanTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 self.setup_clean_chain = True self.extra_args = [ - ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=1', '-fortcanningheight=50', '-eunosheight=50', '-fortcanninghillheight=220', '-txindex=1'], - ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=1', '-fortcanningheight=50', '-eunosheight=50', '-txindex=1']] + ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=1', + '-fortcanningheight=50', '-eunosheight=50', '-fortcanninghillheight=220', '-txindex=1'], + ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=1', + '-fortcanningheight=50', '-eunosheight=50', '-txindex=1']] def run_test(self): - assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI + assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI print("Generating initial chain...") self.nodes[0].generate(50) @@ -81,38 +84,38 @@ def run_test(self): self.sync_blocks() self.nodes[0].setcollateraltoken({ - 'token': idDFI, - 'factor': 1, - 'fixedIntervalPriceId': "DFI/USD"}) + 'token': idDFI, + 'factor': 1, + 'fixedIntervalPriceId': "DFI/USD"}) self.nodes[0].setcollateraltoken({ - 'token': idBTC, - 'factor': 1, - 'fixedIntervalPriceId': "BTC/USD"}) + 'token': idBTC, + 'factor': 1, + 'fixedIntervalPriceId': "BTC/USD"}) self.nodes[0].generate(1) self.sync_blocks() setLoanTokenTSLA = self.nodes[0].setloantoken({ - 'symbol': symbolTSLA, - 'name': "Tesla stock token", - 'fixedIntervalPriceId': "TSLA/USD", - 'mintable': False, - 'interest': 1}) + 'symbol': symbolTSLA, + 'name': "Tesla stock token", + 'fixedIntervalPriceId': "TSLA/USD", + 'mintable': False, + 'interest': 1}) self.nodes[0].setloantoken({ - 'symbol': symbolGOOGL, - 'name': "Tesla stock token", - 'fixedIntervalPriceId': "TSLA/USD", - 'mintable': True, - 'interest': 2}) + 'symbol': symbolGOOGL, + 'name': "Tesla stock token", + 'fixedIntervalPriceId': "TSLA/USD", + 'mintable': True, + 'interest': 2}) self.nodes[0].setloantoken({ - 'symbol': symboldUSD, - 'name': "DUSD stable token", - 'fixedIntervalPriceId': "DUSD/USD", - 'mintable': True, - 'interest': 1}) + 'symbol': symboldUSD, + 'name': "DUSD stable token", + 'fixedIntervalPriceId': "DUSD/USD", + 'mintable': True, + 'interest': 1}) self.nodes[0].generate(1) self.sync_blocks() @@ -135,7 +138,7 @@ def run_test(self): idTSLA = list(self.nodes[0].getloantoken(symbolTSLA)["token"])[0] idGOOGL = list(self.nodes[0].getloantoken(symbolGOOGL)["token"])[0] - vaultId1 = self.nodes[0].createvault( account0, 'LOAN150') + vaultId1 = self.nodes[0].createvault(account0, 'LOAN150') self.nodes[0].generate(1) self.sync_blocks() @@ -146,8 +149,8 @@ def run_test(self): self.sync_blocks() self.nodes[0].takeloan({ - 'vaultId': vaultId1, - 'amounts': "2000@" + symboldUSD}) + 'vaultId': vaultId1, + 'amounts': "2000@" + symboldUSD}) self.nodes[0].generate(1) self.sync_blocks() @@ -174,7 +177,7 @@ def run_test(self): self.nodes[0].generate(1) self.sync_blocks() - vaultId = self.nodes[0].createvault( account0, 'LOAN150') + vaultId = self.nodes[0].createvault(account0, 'LOAN150') self.nodes[0].generate(1) self.sync_blocks() @@ -183,46 +186,47 @@ def run_test(self): try: self.nodes[0].takeloan({ - 'vaultId': setLoanTokenTSLA, - 'amounts': "1@" + symbolTSLA}) + 'vaultId': setLoanTokenTSLA, + 'amounts': "1@" + symbolTSLA}) except JSONRPCException as e: errorString = e.error['message'] - assert("Vault <{}> not found".format(setLoanTokenTSLA) in errorString) + assert ("Vault <{}> not found".format(setLoanTokenTSLA) in errorString) try: self.nodes[0].takeloan({ - 'vaultId': vaultId, - 'amounts': "1@" + symbolBTC}) + 'vaultId': vaultId, + 'amounts': "1@" + symbolBTC}) except JSONRPCException as e: errorString = e.error['message'] - assert("Loan token with id (" + idBTC + ") does not exist" in errorString) + assert ("Loan token with id (" + idBTC + ") does not exist" in errorString) try: self.nodes[0].takeloan({ - 'vaultId': vaultId, - 'amounts': "1@AAAA"}) + 'vaultId': vaultId, + 'amounts': "1@AAAA"}) except JSONRPCException as e: errorString = e.error['message'] - assert("Invalid Defi token: AAAA" in errorString) + assert ("Invalid Defi token: AAAA" in errorString) try: self.nodes[1].takeloan({ - 'vaultId': vaultId, - 'amounts': "1@" + symbolTSLA}) + 'vaultId': vaultId, + 'amounts': "1@" + symbolTSLA}) except JSONRPCException as e: errorString = e.error['message'] - assert("Incorrect authorization for" in errorString) + assert ("Incorrect authorization for" in errorString) try: self.nodes[0].takeloan({ - 'vaultId': vaultId, - 'amounts': "1@" + symbolTSLA}) + 'vaultId': vaultId, + 'amounts': "1@" + symbolTSLA}) except JSONRPCException as e: errorString = e.error['message'] - assert("Loan cannot be taken on token with id (" + idTSLA + ") as \"mintable\" is currently false" in errorString) + assert ( + "Loan cannot be taken on token with id (" + idTSLA + ") as \"mintable\" is currently false" in errorString) - setLoanTokenTSLA = self.nodes[0].updateloantoken(idTSLA,{ - 'mintable': True}) + setLoanTokenTSLA = self.nodes[0].updateloantoken(idTSLA, { + 'mintable': True}) self.nodes[0].generate(1) self.sync_blocks() @@ -263,15 +267,16 @@ def run_test(self): self.sync_blocks() self.nodes[0].takeloan({ - 'vaultId': vaultId, - 'amounts': ["1@" + symbolTSLA, "2@" + symbolGOOGL]}) + 'vaultId': vaultId, + 'amounts': ["1@" + symbolTSLA, "2@" + symbolGOOGL]}) self.nodes[0].generate(1) self.sync_blocks() vaultInfo = self.nodes[0].getvault(vaultId) - assert_equal(sorted(vaultInfo['loanAmounts']), sorted(['1.00000114@' + symbolTSLA, '2.00000266@' + symbolGOOGL])) - assert_equal(sorted(vaultInfo['interestAmounts']), sorted(['0.00000266@GOOGL','0.00000114@TSLA'])) + assert_equal(sorted(vaultInfo['loanAmounts']), + sorted(['1.00000114@' + symbolTSLA, '2.00000266@' + symbolGOOGL])) + assert_equal(sorted(vaultInfo['interestAmounts']), sorted(['0.00000266@GOOGL', '0.00000114@TSLA'])) assert_equal(vaultInfo['interestValue'], Decimal('0.00003800')) assert_equal(self.nodes[0].getaccount(account0, {}, True)[idTSLA], Decimal('1')) assert_equal(self.nodes[0].getaccount(account0, {}, True)[idGOOGL], Decimal('2')) @@ -290,7 +295,7 @@ def run_test(self): assert_equal(loans['totals']['collateralTokens'], 2) assert_equal(loans['totals']['loanTokens'], 3) - vaultId2 = self.nodes[1].createvault( account1, 'LOAN150') + vaultId2 = self.nodes[1].createvault(account1, 'LOAN150') self.nodes[1].generate(2) self.sync_blocks() @@ -307,21 +312,21 @@ def run_test(self): try: self.nodes[0].paybackloan({ - 'vaultId': setLoanTokenTSLA, - 'from': account0, - 'amounts': "0.5@" + symbolTSLA}) + 'vaultId': setLoanTokenTSLA, + 'from': account0, + 'amounts': "0.5@" + symbolTSLA}) except JSONRPCException as e: errorString = e.error['message'] - assert("Cannot find existing vault with id" in errorString) + assert ("Cannot find existing vault with id" in errorString) try: self.nodes[0].paybackloan({ - 'vaultId': vaultId2, - 'from': account0, - 'amounts': "0.5@" + symbolTSLA}) + 'vaultId': vaultId2, + 'from': account0, + 'amounts': "0.5@" + symbolTSLA}) except JSONRPCException as e: errorString = e.error['message'] - assert("Vault with id " + vaultId2 + " has no collaterals" in errorString) + assert ("Vault with id " + vaultId2 + " has no collaterals" in errorString) self.nodes[1].deposittovault(vaultId2, account1, "100@" + symbolDFI) @@ -330,12 +335,12 @@ def run_test(self): try: self.nodes[0].paybackloan({ - 'vaultId': vaultId2, - 'from': account0, - 'amounts': "0.5@" + symbolTSLA}) + 'vaultId': vaultId2, + 'from': account0, + 'amounts': "0.5@" + symbolTSLA}) except JSONRPCException as e: errorString = e.error['message'] - assert("There are no loans on this vault" in errorString) + assert ("There are no loans on this vault" in errorString) for interest in self.nodes[0].getinterest('LOAN150'): if interest['token'] == symbolTSLA: @@ -344,21 +349,23 @@ def run_test(self): assert_equal(interest['totalInterest'], Decimal('0.00001064')) vaultInfo = self.nodes[0].getvault(vaultId) - assert_equal(sorted(vaultInfo['loanAmounts']), sorted(['1.00000456@' + symbolTSLA, '2.00001064@' + symbolGOOGL])) + assert_equal(sorted(vaultInfo['loanAmounts']), + sorted(['1.00000456@' + symbolTSLA, '2.00001064@' + symbolGOOGL])) assert_equal(vaultInfo['interestValue'], Decimal('0.00015200')) - assert_equal(sorted(vaultInfo['interestAmounts']), sorted(['0.00001064@GOOGL','0.00000456@TSLA'])) + assert_equal(sorted(vaultInfo['interestAmounts']), sorted(['0.00001064@GOOGL', '0.00000456@TSLA'])) assert_equal(self.nodes[0].getaccount(account0, {}, True)[idTSLA], Decimal('1.00000000')) assert_equal(self.nodes[0].getaccount(account0, {}, True)[idGOOGL], Decimal('2.00000000')) self.nodes[0].paybackloan({ - 'vaultId': vaultId, - 'from': account0, - 'amounts': ["0.50000456@" + symbolTSLA, "1.00001064@" + symbolGOOGL]}) + 'vaultId': vaultId, + 'from': account0, + 'amounts': ["0.50000456@" + symbolTSLA, "1.00001064@" + symbolGOOGL]}) self.nodes[0].generate(1) self.sync_blocks() - assert_equal(sorted(self.nodes[0].listaccounthistory(account0)[0]['amounts']), sorted(['-1.00001064@GOOGL', '-0.50000456@TSLA'])) + assert_equal(sorted(self.nodes[0].listaccounthistory(account0)[0]['amounts']), + sorted(['-1.00001064@GOOGL', '-0.50000456@TSLA'])) assert_equal(self.nodes[0].getaccount(account0, {}, True)[idTSLA], Decimal('0.49999544')) assert_equal(self.nodes[0].getaccount(account0, {}, True)[idGOOGL], Decimal('0.99998937')) @@ -371,43 +378,46 @@ def run_test(self): # loan payback burn vaultInfo = self.nodes[0].getvault(vaultId) assert_equal(self.nodes[0].getburninfo()['paybackburn'], ['0.00186822@' + symbolDFI]) - assert_equal(sorted(vaultInfo['loanAmounts']), sorted(['0.50000057@' + symbolTSLA, '1.00000133@' + symbolGOOGL])) + assert_equal(sorted(vaultInfo['loanAmounts']), + sorted(['0.50000057@' + symbolTSLA, '1.00000133@' + symbolGOOGL])) try: self.nodes[0].withdrawfromvault(vaultId, account0, "200@" + symbolDFI) except JSONRPCException as e: errorString = e.error['message'] - assert("Cannot withdraw all collaterals as there are still active loans in this vault" in errorString) + assert ("Cannot withdraw all collaterals as there are still active loans in this vault" in errorString) try: self.nodes[0].withdrawfromvault(vaultId, account0, "199@" + symbolDFI) except JSONRPCException as e: errorString = e.error['message'] - assert("Vault does not have enough collateralization ratio defined by loan scheme" in errorString) + assert ("Vault does not have enough collateralization ratio defined by loan scheme" in errorString) self.nodes[0].withdrawfromvault(vaultId, account0, "100@" + symbolDFI) # self.nodes[0].generate(1) - #to be able to repay whole loan + # to be able to repay whole loan self.nodes[0].minttokens(["0.00001083@" + symbolTSLA, "0.00002659@" + symbolGOOGL]) self.nodes[0].generate(10) self.sync_blocks() vaultInfo = self.nodes[0].getvault(vaultId) - assert_equal(sorted(vaultInfo['loanAmounts']), sorted(['0.50000627@' + symbolTSLA, '1.00001463@' + symbolGOOGL])) + assert_equal(sorted(vaultInfo['loanAmounts']), + sorted(['0.50000627@' + symbolTSLA, '1.00001463@' + symbolGOOGL])) self.nodes[0].paybackloan({ - 'vaultId': vaultId, - 'from': account0, - 'amounts': vaultInfo['loanAmounts']}) + 'vaultId': vaultId, + 'from': account0, + 'amounts': vaultInfo['loanAmounts']}) self.nodes[0].generate(1) self.sync_blocks() vaultInfo = self.nodes[0].getvault(vaultId) assert_equal(vaultInfo['loanAmounts'], []) - assert_equal(sorted(self.nodes[0].listaccounthistory(account0)[0]['amounts']), sorted(['-1.00001463@GOOGL', '-0.50000627@TSLA'])) + assert_equal(sorted(self.nodes[0].listaccounthistory(account0)[0]['amounts']), + sorted(['-1.00001463@GOOGL', '-0.50000627@TSLA'])) assert_greater_than_or_equal(self.nodes[0].getburninfo()['paybackburn'], ['0.00443685@' + symbolDFI]) for interest in self.nodes[0].getinterest('LOAN150'): @@ -429,9 +439,9 @@ def run_test(self): assert_equal(vaultInfo['loanValue'], Decimal('0.00000000')) self.nodes[0].paybackloan({ - 'vaultId': vaultId1, - 'from': account0, - 'amounts': "500@" + symboldUSD}) + 'vaultId': vaultId1, + 'from': account0, + 'amounts': "500@" + symboldUSD}) self.nodes[0].generate(1) self.sync_blocks() @@ -475,7 +485,7 @@ def run_test(self): self.nodes[0].generate(1) address2 = self.nodes[0].getnewaddress() - self.nodes[0].sendtokenstoaddress({}, {address2:["5@TSLA", "5@GOOGL"]}) # split into two address + self.nodes[0].sendtokenstoaddress({}, {address2: ["5@TSLA", "5@GOOGL"]}) # split into two address self.nodes[0].generate(1) try: @@ -486,19 +496,19 @@ def run_test(self): }) except JSONRPCException as e: errorString = e.error['message'] - assert("Not enough tokens on account, call sendtokenstoaddress to increase it." in errorString) + assert ("Not enough tokens on account, call sendtokenstoaddress to increase it." in errorString) self.nodes[0].paybackloan({ - 'vaultId': vaultId3, - 'from': "*", - 'amounts': "5@" + symbolTSLA + 'vaultId': vaultId3, + 'from': "*", + 'amounts': "5@" + symbolTSLA }) self.nodes[0].generate(1) vault = self.nodes[0].getvault(vaultId3) assert_equal(sorted(vault['loanAmounts']), sorted(['5.00002853@' + symbolTSLA, '10.00003993@' + symbolGOOGL])) - self.nodes[0].sendtokenstoaddress({}, {address2:["5@" + symbolTSLA, "10@" + symbolGOOGL]}) + self.nodes[0].sendtokenstoaddress({}, {address2: ["5@" + symbolTSLA, "10@" + symbolGOOGL]}) self.nodes[0].generate(1) self.nodes[0].paybackloan({ @@ -511,7 +521,6 @@ def run_test(self): vault = self.nodes[0].getvault(vaultId3) assert_equal(sorted(vault['loanAmounts']), sorted(['0.00003425@' + symbolTSLA, '0.00005324@' + symbolGOOGL])) - # Test 100% interest on 1 sat loan address = self.nodes[0].getnewaddress() @@ -533,12 +542,12 @@ def run_test(self): self.nodes[0].generate(1) vault = self.nodes[0].getvault(vaultId4) - assert_equal(vault['loanAmounts'][0], "0.00000002@TSLA") # 100% interest + assert_equal(vault['loanAmounts'][0], "0.00000002@TSLA") # 100% interest self.nodes[0].minttokens(["5@" + symbolTSLA]) self.nodes[0].generate(1) - self.nodes[0].sendtokenstoaddress({}, {address2 :["5@" + symbolTSLA]}) + self.nodes[0].sendtokenstoaddress({}, {address2: ["5@" + symbolTSLA]}) self.nodes[0].generate(1) for _ in range(1, 100): @@ -550,20 +559,20 @@ def run_test(self): self.nodes[0].generate(1) vault = self.nodes[0].getvault(vaultId4) - assert_equal(vault['loanAmounts'][0], "0.00000002@TSLA") # 100% interest + assert_equal(vault['loanAmounts'][0], "0.00000002@TSLA") # 100% interest self.nodes[0].generate(1) vault = self.nodes[0].getvault(vaultId4) assert_equal(vault['loanAmounts'][0], "0.00000002@TSLA") - self.nodes[0].generate(40) # 40 blocks don't accrue interest + self.nodes[0].generate(40) # 40 blocks don't accrue interest vaultAfter = self.nodes[0].getvault(vaultId4) assert_equal(vault['loanAmounts'][0], vaultAfter['loanAmounts'][0]) self.nodes[0].paybackloan({ 'vaultId': vaultId4, 'from': "*", - 'amounts': vault['loanAmounts'][0] # Has to pay whole loanAmounts to be able to close vault + 'amounts': vault['loanAmounts'][0] # Has to pay whole loanAmounts to be able to close vault }) self.nodes[0].generate(1) diff --git a/test/functional/feature_loan_deposittovault.py b/test/functional/feature_loan_deposittovault.py index c2ba7f67a3..8dbb0d22fa 100755 --- a/test/functional/feature_loan_deposittovault.py +++ b/test/functional/feature_loan_deposittovault.py @@ -12,18 +12,21 @@ from test_framework.util import assert_equal, assert_greater_than import time -class DepositToVaultTest (DefiTestFramework): + +class DepositToVaultTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 self.setup_clean_chain = True self.extra_args = [ - ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-txindex=1', '-fortcanningheight=1'], - ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-txindex=1', '-fortcanningheight=1'] - ] + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-txindex=1', + '-fortcanningheight=1'], + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-txindex=1', + '-fortcanningheight=1'] + ] def run_test(self): # Prepare tokens for deposittoloan - assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI + assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI self.nodes[0].generate(25) self.sync_blocks() self.nodes[1].generate(101) @@ -76,14 +79,14 @@ def run_test(self): self.sync_blocks() self.nodes[0].setcollateraltoken({ - 'token': idDFI, - 'factor': 1, - 'fixedIntervalPriceId': "DFI/USD"}) + 'token': idDFI, + 'factor': 1, + 'fixedIntervalPriceId': "DFI/USD"}) self.nodes[0].setcollateraltoken({ - 'token': idBTC, - 'factor': 1, - 'fixedIntervalPriceId': "BTC/USD"}) + 'token': idBTC, + 'factor': 1, + 'fixedIntervalPriceId': "BTC/USD"}) self.nodes[0].generate(7) self.sync_blocks() @@ -92,7 +95,7 @@ def run_test(self): self.nodes[0].generate(1) ownerAddress1 = self.nodes[0].getnewaddress('', 'legacy') - vaultId1 = self.nodes[0].createvault(ownerAddress1) # default loan scheme + vaultId1 = self.nodes[0].createvault(ownerAddress1) # default loan scheme self.nodes[0].generate(1) # Insufficient funds @@ -100,21 +103,22 @@ def run_test(self): self.nodes[0].deposittovault(vaultId1, accountDFI, '101@DFI') except JSONRPCException as e: errorString = e.error['message'] - assert("Insufficient funds" in errorString) + assert ("Insufficient funds" in errorString) # Check from auth try: self.nodes[0].deposittovault(vaultId1, accountBTC, '1@DFI') except JSONRPCException as e: errorString = e.error['message'] - assert("Incorrect authorization for {}".format(accountBTC) in errorString) + assert ("Incorrect authorization for {}".format(accountBTC) in errorString) # Check vault exists try: - self.nodes[0].deposittovault("76a9148080dad765cbfd1c38f95e88592e24e43fb642828a948b2a457a8ba8ac", accountDFI, '1@DFI') + self.nodes[0].deposittovault("76a9148080dad765cbfd1c38f95e88592e24e43fb642828a948b2a457a8ba8ac", accountDFI, + '1@DFI') except JSONRPCException as e: errorString = e.error['message'] - assert("Vault <76a9148080dad765cbfd1c38f95e88592e24e43fb642828a948b2a457a8ba8ac> not found" in errorString) + assert ("Vault <76a9148080dad765cbfd1c38f95e88592e24e43fb642828a948b2a457a8ba8ac> not found" in errorString) self.nodes[0].deposittovault(vaultId1, accountDFI, '0.7@DFI') self.nodes[0].generate(1) @@ -139,16 +143,16 @@ def run_test(self): self.nodes[1].generate(1) vault1 = self.nodes[1].getvault(vaultId1) - assert_equal(vault1['collateralAmounts'],['0.70000000@DFI', '0.70000000@BTC']) + assert_equal(vault1['collateralAmounts'], ['0.70000000@DFI', '0.70000000@BTC']) acBTC = self.nodes[1].getaccount(accountBTC) assert_equal(acBTC, ['9.30000000@BTC']) self.nodes[0].setloantoken({ - 'symbol': "TSLA", - 'name': "Tesla Token", - 'fixedIntervalPriceId': "TSLA/USD", - 'mintable': True, - 'interest': 0.01}) + 'symbol': "TSLA", + 'name': "Tesla Token", + 'fixedIntervalPriceId': "TSLA/USD", + 'mintable': True, + 'interest': 0.01}) self.nodes[0].generate(1) self.nodes[0].deposittovault(vaultId1, accountDFI, '0.3@DFI') @@ -171,8 +175,8 @@ def run_test(self): self.sync_blocks() self.nodes[0].takeloan({ - 'vaultId': vaultId1, - 'amounts': "0.5@TSLA"}) + 'vaultId': vaultId1, + 'amounts': "0.5@TSLA"}) self.nodes[0].generate(1) self.sync_blocks() @@ -185,19 +189,18 @@ def run_test(self): assert_greater_than(Decimal(0.50000009), vault1['loanValue']) assert_equal(vault1['informativeRatio'], Decimal('399.99992800')) - # make vault enter under liquidation state oracle1_prices = [{"currency": "USD", "tokenAmount": "4@TSLA"}] mock_time = int(time.time()) self.nodes[0].setmocktime(mock_time) self.nodes[0].setoracledata(oracle_id1, mock_time, oracle1_prices) - self.nodes[0].generate(6) # let fixed price update + self.nodes[0].generate(6) # let fixed price update self.sync_blocks() vault1 = self.nodes[1].getvault(vaultId1) assert_equal(vault1['state'], "frozen") - self.nodes[0].generate(6) # let fixed price be stable and check vault is now underLiquidation state + self.nodes[0].generate(6) # let fixed price be stable and check vault is now underLiquidation state self.sync_blocks() vault1 = self.nodes[1].getvault(vaultId1) @@ -208,7 +211,7 @@ def run_test(self): self.nodes[1].deposittovault(vaultId1, accountBTC, '0.2@BTC') except JSONRPCException as e: errorString = e.error['message'] - assert("Cannot deposit to vault under liquidation" in errorString) + assert ("Cannot deposit to vault under liquidation" in errorString) self.nodes[1].generate(1) diff --git a/test/functional/feature_loan_dusd_as_collateral.py b/test/functional/feature_loan_dusd_as_collateral.py index e7acb6d100..9694730cf6 100755 --- a/test/functional/feature_loan_dusd_as_collateral.py +++ b/test/functional/feature_loan_dusd_as_collateral.py @@ -12,12 +12,14 @@ from decimal import Decimal import time -class LoanDUSDCollateralTest (DefiTestFramework): + +class LoanDUSDCollateralTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True self.extra_args = [ - ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', '-fortcanninghillheight=200', '-fortcanningroadheight=215', '-jellyfish_regtest=1']] + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', + '-fortcanninghillheight=200', '-fortcanningroadheight=215', '-jellyfish_regtest=1']] def run_test(self): self.nodes[0].generate(120) @@ -78,12 +80,12 @@ def run_test(self): mn_address: [ '10000@' + symbolDFI, '8000@' + symbolDUSD] - }, mn_address) + }, mn_address) self.nodes[0].addpoolliquidity({ mn_address: [ '10000@' + symbolDFI, '8000@' + symbolBTC] - }, mn_address) + }, mn_address) self.nodes[0].generate(1) # Set up Oracles @@ -105,25 +107,25 @@ def run_test(self): # Set collateral tokens self.nodes[0].setcollateraltoken({ - 'token': symbolDFI, - 'factor': 1, - 'fixedIntervalPriceId': "DFI/USD" - }) + 'token': symbolDFI, + 'factor': 1, + 'fixedIntervalPriceId': "DFI/USD" + }) self.nodes[0].setcollateraltoken({ - 'token': symbolBTC, - 'factor': 1, - 'fixedIntervalPriceId': "BTC/USD" - }) + 'token': symbolBTC, + 'factor': 1, + 'fixedIntervalPriceId': "BTC/USD" + }) token_factor_dusd = 0.99 activate = self.nodes[0].getblockcount() + 50 self.nodes[0].setcollateraltoken({ - 'token': symbolDUSD, - 'factor': token_factor_dusd, - 'fixedIntervalPriceId': "DUSD/USD", - 'activateAfterBlock': activate - }) + 'token': symbolDUSD, + 'factor': token_factor_dusd, + 'fixedIntervalPriceId': "DUSD/USD", + 'activateAfterBlock': activate + }) self.nodes[0].generate(1) # Create loan scheme @@ -144,7 +146,8 @@ def run_test(self): self.nodes[0].generate(1) # DUSD is not active as a collateral token yet - assert_raises_rpc_error(-32600, "Collateral token with id (1) does not exist!", self.nodes[0].deposittovault, vault_id, vault_address, str(collateral) + "@" + symbolDUSD) + assert_raises_rpc_error(-32600, "Collateral token with id (1) does not exist!", self.nodes[0].deposittovault, + vault_id, vault_address, str(collateral) + "@" + symbolDUSD) # Activates DUSD as collateral token self.nodes[0].generate(activate - self.nodes[0].getblockcount()) @@ -155,18 +158,18 @@ def run_test(self): self.nodes[0].generate(1) vault = self.nodes[0].getvault(vault_id) - assert("DUSD" in vault['collateralAmounts'][1]) + assert ("DUSD" in vault['collateralAmounts'][1]) assert_equal(vault['collateralValue'], collateral * token_factor_dusd + collateral) # Move to FortCanningHill fork self.nodes[0].generate(200 - self.nodes[0].getblockcount()) # Enable loan payback - self.nodes[0].setgov({"ATTRIBUTES":{'v0/token/' + idDUSD + '/payback_dfi':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/token/' + idDUSD + '/payback_dfi': 'true'}}) self.nodes[0].generate(1) # Take DUSD loan - self.nodes[0].takeloan({ "vaultId": vault_id, "amounts": str(loan_dusd) + "@" + symbolDUSD }) + self.nodes[0].takeloan({"vaultId": vault_id, "amounts": str(loan_dusd) + "@" + symbolDUSD}) self.nodes[0].generate(1) # Loan value loan amount + interest @@ -203,15 +206,15 @@ def run_test(self): # Try to take DUSD loan with DUSD as sole collateral try: - self.nodes[0].takeloan({ "vaultId": vault_id, "amounts": str(loan_dusd) + "@" + symbolDUSD }) + self.nodes[0].takeloan({"vaultId": vault_id, "amounts": str(loan_dusd) + "@" + symbolDUSD}) except JSONRPCException as e: errorString = e.error['message'] - assert("At least 50% of the minimum required collateral must be in DFI" in errorString) + assert ("At least 50% of the minimum required collateral must be in DFI" in errorString) - self.nodes[0].generate(215 - self.nodes[0].getblockcount()) # move to fortcanningroad height + self.nodes[0].generate(215 - self.nodes[0].getblockcount()) # move to fortcanningroad height # Take DUSD loan with DUSD as sole collateral - self.nodes[0].takeloan({ "vaultId": vault_id, "amounts": str(loan_dusd) + "@" + symbolDUSD }) + self.nodes[0].takeloan({"vaultId": vault_id, "amounts": str(loan_dusd) + "@" + symbolDUSD}) self.nodes[0].generate(1) vault = self.nodes[0].getvault(vault_id) @@ -219,18 +222,21 @@ def run_test(self): # Try to take DUSD loan with DUSD less than 50% of total collateralized loan value # This tests for collateral factor - assert_raises_rpc_error(-32600, "Vault does not have enough collateralization ratio defined by loan scheme - 149 < 150", self.nodes[0].takeloan, { "vaultId": vault_id, "amounts": "333@" + symbolDUSD }) + assert_raises_rpc_error(-32600, + "Vault does not have enough collateralization ratio defined by loan scheme - 149 < 150", + self.nodes[0].takeloan, {"vaultId": vault_id, "amounts": "333@" + symbolDUSD}) # Set DUSD collateral factor back to 1 self.nodes[0].setcollateraltoken({ - 'token': symbolDUSD, - 'factor': 1, - 'fixedIntervalPriceId': "DUSD/USD" - }) + 'token': symbolDUSD, + 'factor': 1, + 'fixedIntervalPriceId': "DUSD/USD" + }) self.nodes[0].generate(10) - self.nodes[0].takeloan({ "vaultId": vault_id, "amounts": "333@" + symbolDUSD }) + self.nodes[0].takeloan({"vaultId": vault_id, "amounts": "333@" + symbolDUSD}) self.nodes[0].generate(1) + if __name__ == '__main__': LoanDUSDCollateralTest().main() diff --git a/test/functional/feature_loan_estimatecollateral.py b/test/functional/feature_loan_estimatecollateral.py index 26bfb28c0a..0214d53767 100755 --- a/test/functional/feature_loan_estimatecollateral.py +++ b/test/functional/feature_loan_estimatecollateral.py @@ -11,13 +11,15 @@ from test_framework.util import assert_equal import time -class EstimateCollateralTest (DefiTestFramework): + +class EstimateCollateralTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True self.extra_args = [ - ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-txindex=1', '-fortcanningheight=1'], - ] + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-txindex=1', + '-fortcanningheight=1'], + ] def run_test(self): self.nodes[0].generate(150) @@ -66,14 +68,14 @@ def run_test(self): self.nodes[0].generate(1) self.nodes[0].setcollateraltoken({ - 'token': idDFI, - 'factor': 1, - 'fixedIntervalPriceId': "DFI/USD"}) + 'token': idDFI, + 'factor': 1, + 'fixedIntervalPriceId': "DFI/USD"}) self.nodes[0].setcollateraltoken({ - 'token': idBTC, - 'factor': 0.8, - 'fixedIntervalPriceId': "BTC/USD"}) + 'token': idBTC, + 'factor': 0.8, + 'fixedIntervalPriceId': "BTC/USD"}) self.nodes[0].generate(7) @@ -82,21 +84,21 @@ def run_test(self): self.nodes[0].generate(1) ownerAddress1 = self.nodes[0].getnewaddress('', 'legacy') - vaultId1 = self.nodes[0].createvault(ownerAddress1) # default loan scheme + vaultId1 = self.nodes[0].createvault(ownerAddress1) # default loan scheme self.nodes[0].generate(1) self.nodes[0].setloantoken({ - 'symbol': "TSLA", - 'name': "Tesla Token", - 'fixedIntervalPriceId': "TSLA/USD", - 'mintable': True, - 'interest': 0.01}) + 'symbol': "TSLA", + 'name': "Tesla Token", + 'fixedIntervalPriceId': "TSLA/USD", + 'mintable': True, + 'interest': 0.01}) self.nodes[0].setloantoken({ - 'symbol': "TWTR", - 'name': "Twitter Token", - 'fixedIntervalPriceId': "TWTR/USD", - 'mintable': True, - 'interest': 0.01}) + 'symbol': "TWTR", + 'name': "Twitter Token", + 'fixedIntervalPriceId': "TWTR/USD", + 'mintable': True, + 'interest': 0.01}) self.nodes[0].generate(1) # Token that does not exists @@ -104,19 +106,19 @@ def run_test(self): self.nodes[0].estimatecollateral("10@TSLAA", 200) except JSONRPCException as e: errorString = e.error['message'] - assert("Invalid Defi token: TSLAA" in errorString) + assert ("Invalid Defi token: TSLAA" in errorString) # Token not set as loan token try: self.nodes[0].estimatecollateral("10@DFI", 200) except JSONRPCException as e: errorString = e.error['message'] - assert("not a loan token!" in errorString) + assert ("not a loan token!" in errorString) # Token without live price try: self.nodes[0].estimatecollateral("10@TSLA", 200) except JSONRPCException as e: errorString = e.error['message'] - assert("No live fixed prices for TSLA/USD" in errorString) + assert ("No live fixed prices for TSLA/USD" in errorString) oracle1_prices = [ {"currency": "USD", "tokenAmount": "1@DFI"}, @@ -128,26 +130,26 @@ def run_test(self): self.nodes[0].setmocktime(mock_time) self.nodes[0].setoracledata(oracle_id1, mock_time, oracle1_prices) - self.nodes[0].generate(8) # activate prices + self.nodes[0].generate(8) # activate prices # Negative split value try: self.nodes[0].estimatecollateral("10@TSLA", 200, {"DFI": -1}) except JSONRPCException as e: errorString = e.error['message'] - assert("Amount out of range" in errorString) + assert ("Amount out of range" in errorString) # Token not set as collateral try: self.nodes[0].estimatecollateral("10@TSLA", 200, {"TSLA": 1}) except JSONRPCException as e: errorString = e.error['message'] - assert("(TSLA) is not a valid collateral!" in errorString) + assert ("(TSLA) is not a valid collateral!" in errorString) # Total split should be equal to 1 try: self.nodes[0].estimatecollateral("10@TSLA", 200, {"DFI": 0.8}) except JSONRPCException as e: errorString = e.error['message'] - assert("total split between collateral tokens = 0.80000000 vs expected 1.00000000" in errorString) + assert ("total split between collateral tokens = 0.80000000 vs expected 1.00000000" in errorString) estimatecollateral = self.nodes[0].estimatecollateral("10@TSLA", 200) @@ -155,19 +157,21 @@ def run_test(self): self.nodes[0].generate(1) # Cannot take more loan than estimated try: - self.nodes[0].takeloan({ "vaultId": vaultId1, "amounts": "10.1@TSLA" }) + self.nodes[0].takeloan({"vaultId": vaultId1, "amounts": "10.1@TSLA"}) except JSONRPCException as e: errorString = e.error['message'] - assert("Vault does not have enough collateralization ratio" in errorString) + assert ("Vault does not have enough collateralization ratio" in errorString) - self.nodes[0].takeloan({ "vaultId": vaultId1, "amounts": "10@TSLA" }) # should be able to take loan amount from estimatecollateral + self.nodes[0].takeloan( + {"vaultId": vaultId1, "amounts": "10@TSLA"}) # should be able to take loan amount from estimatecollateral self.nodes[0].generate(1) vault1 = self.nodes[0].getvault(vaultId1) - assert_equal(vault1["collateralRatio"], 200) # vault collateral ratio should be equal to estimatecollateral targetRatio + assert_equal(vault1["collateralRatio"], + 200) # vault collateral ratio should be equal to estimatecollateral targetRatio vaultId2 = self.nodes[0].createvault(ownerAddress1) - estimatecollateral = self.nodes[0].estimatecollateral("10@TSLA", 200, {"BTC":0.5, "DFI": 0.5}) + estimatecollateral = self.nodes[0].estimatecollateral("10@TSLA", 200, {"BTC": 0.5, "DFI": 0.5}) amountDFI = next(x for x in estimatecollateral if "DFI" in x) amountBTC = next(x for x in estimatecollateral if "BTC" in x) @@ -177,14 +181,14 @@ def run_test(self): self.nodes[0].deposittovault(vaultId2, account, amountBTC) self.nodes[0].generate(1) - self.nodes[0].takeloan({ "vaultId": vaultId2, "amounts": "10@TSLA" }) + self.nodes[0].takeloan({"vaultId": vaultId2, "amounts": "10@TSLA"}) self.nodes[0].generate(1) vault2 = self.nodes[0].getvault(vaultId2) assert_equal(vault2["collateralRatio"], 200) vaultId3 = self.nodes[0].createvault(ownerAddress1) - estimatecollateral = self.nodes[0].estimatecollateral(["10@TSLA", "10@TWTR"], 200, {"BTC":0.5, "DFI": 0.5}) + estimatecollateral = self.nodes[0].estimatecollateral(["10@TSLA", "10@TWTR"], 200, {"BTC": 0.5, "DFI": 0.5}) amountDFI = next(x for x in estimatecollateral if "DFI" in x) amountBTC = next(x for x in estimatecollateral if "BTC" in x) @@ -194,11 +198,12 @@ def run_test(self): self.nodes[0].deposittovault(vaultId3, account, amountBTC) self.nodes[0].generate(1) - self.nodes[0].takeloan({ "vaultId": vaultId3, "amounts": ["10@TSLA", "10@TWTR"] }) + self.nodes[0].takeloan({"vaultId": vaultId3, "amounts": ["10@TSLA", "10@TWTR"]}) self.nodes[0].generate(1) vault3 = self.nodes[0].getvault(vaultId3) assert_equal(vault3["collateralRatio"], 200) + if __name__ == '__main__': EstimateCollateralTest().main() diff --git a/test/functional/feature_loan_estimateloan.py b/test/functional/feature_loan_estimateloan.py index fc3d092011..d7b859017a 100755 --- a/test/functional/feature_loan_estimateloan.py +++ b/test/functional/feature_loan_estimateloan.py @@ -11,13 +11,15 @@ from test_framework.util import assert_equal import time -class EstimateLoanTest (DefiTestFramework): + +class EstimateLoanTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True self.extra_args = [ - ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-txindex=1', '-fortcanningheight=1'], - ] + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-txindex=1', + '-fortcanningheight=1'], + ] def run_test(self): self.nodes[0].generate(125) @@ -30,7 +32,6 @@ def run_test(self): }) self.nodes[0].generate(1) - symbolDFI = "DFI" symbolBTC = "BTC" idDFI = list(self.nodes[0].gettoken(symbolDFI).keys())[0] @@ -67,14 +68,14 @@ def run_test(self): self.nodes[0].generate(1) self.nodes[0].setcollateraltoken({ - 'token': idDFI, - 'factor': 1, - 'fixedIntervalPriceId': "DFI/USD"}) + 'token': idDFI, + 'factor': 1, + 'fixedIntervalPriceId': "DFI/USD"}) self.nodes[0].setcollateraltoken({ - 'token': idBTC, - 'factor': 1, - 'fixedIntervalPriceId': "BTC/USD"}) + 'token': idBTC, + 'factor': 1, + 'fixedIntervalPriceId': "BTC/USD"}) self.nodes[0].generate(7) @@ -83,7 +84,7 @@ def run_test(self): self.nodes[0].generate(1) ownerAddress1 = self.nodes[0].getnewaddress('', 'legacy') - vaultId1 = self.nodes[0].createvault(ownerAddress1) # default loan scheme + vaultId1 = self.nodes[0].createvault(ownerAddress1) # default loan scheme self.nodes[0].generate(1) # Vault not found @@ -91,26 +92,26 @@ def run_test(self): self.nodes[0].estimateloan("af03dbd05492caf362d0daf623be182469bcbae7095d3bab682e40ea3d7c2cbb", {"TSLA": 1}) except JSONRPCException as e: errorString = e.error['message'] - assert("Vault not found." in errorString) + assert ("Vault not found." in errorString) # Without collaterals try: self.nodes[0].estimateloan(vaultId1, {"TSLA": 1}) except JSONRPCException as e: errorString = e.error['message'] - assert("Cannot estimate loan without collaterals." in errorString) + assert ("Cannot estimate loan without collaterals." in errorString) self.nodes[0].setloantoken({ - 'symbol': "TSLA", - 'name': "Tesla Token", - 'fixedIntervalPriceId': "TSLA/USD", - 'mintable': True, - 'interest': 0.01}) + 'symbol': "TSLA", + 'name': "Tesla Token", + 'fixedIntervalPriceId': "TSLA/USD", + 'mintable': True, + 'interest': 0.01}) self.nodes[0].setloantoken({ - 'symbol': "TWTR", - 'name': "Twitter Token", - 'fixedIntervalPriceId': "TWTR/USD", - 'mintable': True, - 'interest': 0.01}) + 'symbol': "TWTR", + 'name': "Twitter Token", + 'fixedIntervalPriceId': "TWTR/USD", + 'mintable': True, + 'interest': 0.01}) self.nodes[0].generate(1) self.nodes[0].deposittovault(vaultId1, account, '1@DFI') @@ -123,25 +124,25 @@ def run_test(self): self.nodes[0].estimateloan(vaultId1, {"TSLA": -1}) except JSONRPCException as e: errorString = e.error['message'] - assert("Amount out of range" in errorString) + assert ("Amount out of range" in errorString) # Token that does not exists try: self.nodes[0].estimateloan(vaultId1, {"TSLAAA": 1}) except JSONRPCException as e: errorString = e.error['message'] - assert("Token TSLAAA does not exist!" in errorString) + assert ("Token TSLAAA does not exist!" in errorString) # Token not set as loan token try: self.nodes[0].estimateloan(vaultId1, {"DFI": 1}) except JSONRPCException as e: errorString = e.error['message'] - assert("(DFI) is not a loan token!" in errorString) + assert ("(DFI) is not a loan token!" in errorString) # Token without live price try: self.nodes[0].estimateloan(vaultId1, {"TSLA": 1}) except JSONRPCException as e: errorString = e.error['message'] - assert("No live fixed price for TSLA" in errorString) + assert ("No live fixed price for TSLA" in errorString) oracle1_prices = [ {"currency": "USD", "tokenAmount": "1@DFI"}, @@ -153,30 +154,32 @@ def run_test(self): self.nodes[0].setmocktime(mock_time) self.nodes[0].setoracledata(oracle_id1, mock_time, oracle1_prices) - self.nodes[0].generate(8) # activate prices + self.nodes[0].generate(8) # activate prices # Total split should be equal to 1 try: self.nodes[0].estimateloan(vaultId1, {"TSLA": 0.8}) except JSONRPCException as e: errorString = e.error['message'] - assert("total split between loan tokens = 0.80000000 vs expected 1.00000000" in errorString) + assert ("total split between loan tokens = 0.80000000 vs expected 1.00000000" in errorString) - estimateloan = self.nodes[0].estimateloan(vaultId1, {"TSLA":1}) + estimateloan = self.nodes[0].estimateloan(vaultId1, {"TSLA": 1}) # Cannot take more loan than estimated try: [amount, token] = estimateloan[0].split("@") newAmount = "@".join([str(float(amount) * 1.01), token]) - self.nodes[0].takeloan({ "vaultId": vaultId1, "amounts": newAmount }) + self.nodes[0].takeloan({"vaultId": vaultId1, "amounts": newAmount}) except JSONRPCException as e: errorString = e.error['message'] - assert("Vault does not have enough collateralization ratio" in errorString) + assert ("Vault does not have enough collateralization ratio" in errorString) - self.nodes[0].takeloan({ "vaultId": vaultId1, "amounts": estimateloan }) # should be able to take loan amount from estimateloan + self.nodes[0].takeloan( + {"vaultId": vaultId1, "amounts": estimateloan}) # should be able to take loan amount from estimateloan self.nodes[0].generate(1) vault1 = self.nodes[0].getvault(vaultId1) - assert_equal(vault1["collateralRatio"], loanSchemeRatio) # vault collateral ratio should be equal to its loan scheme ratio. + assert_equal(vault1["collateralRatio"], + loanSchemeRatio) # vault collateral ratio should be equal to its loan scheme ratio. vaultId2 = self.nodes[0].createvault(ownerAddress1) self.nodes[0].generate(1) @@ -185,8 +188,9 @@ def run_test(self): self.nodes[0].deposittovault(vaultId2, account, '0.01@BTC') self.nodes[0].generate(1) - estimateloan = self.nodes[0].estimateloan(vaultId2, {"TSLA":0.8, "TWTR": 0.2}) - self.nodes[0].takeloan({ "vaultId": vaultId2, "amounts": estimateloan }) # Take multiple loan amount from estimateloan + estimateloan = self.nodes[0].estimateloan(vaultId2, {"TSLA": 0.8, "TWTR": 0.2}) + self.nodes[0].takeloan( + {"vaultId": vaultId2, "amounts": estimateloan}) # Take multiple loan amount from estimateloan self.nodes[0].generate(1) vault2 = self.nodes[0].getvault(vaultId2) @@ -200,8 +204,8 @@ def run_test(self): self.nodes[0].generate(1) targetRatio = 400 - estimateloan = self.nodes[0].estimateloan(vaultId3, {"TSLA":0.8, "TWTR": 0.2}, targetRatio) - self.nodes[0].takeloan({ "vaultId": vaultId3, "amounts": estimateloan }) + estimateloan = self.nodes[0].estimateloan(vaultId3, {"TSLA": 0.8, "TWTR": 0.2}, targetRatio) + self.nodes[0].takeloan({"vaultId": vaultId3, "amounts": estimateloan}) self.nodes[0].generate(1) vault3 = self.nodes[0].getvault(vaultId3) @@ -212,13 +216,14 @@ def run_test(self): mock_time = int(time.time()) self.nodes[0].setmocktime(mock_time) self.nodes[0].setoracledata(oracle_id1, mock_time, oracle1_prices) - self.nodes[0].generate(12) # let fixed price update + self.nodes[0].generate(12) # let fixed price update try: - self.nodes[0].estimateloan(vaultId1, {"TSLA":1}) + self.nodes[0].estimateloan(vaultId1, {"TSLA": 1}) except JSONRPCException as e: errorString = e.error['message'] - assert("Vault <" + vaultId1 + "> is in liquidation" in errorString) + assert ("Vault <" + vaultId1 + "> is in liquidation" in errorString) + if __name__ == '__main__': EstimateLoanTest().main() diff --git a/test/functional/feature_loan_get_interest.py b/test/functional/feature_loan_get_interest.py index 724baa3cf1..06c06b4026 100755 --- a/test/functional/feature_loan_get_interest.py +++ b/test/functional/feature_loan_get_interest.py @@ -12,7 +12,8 @@ import time from decimal import Decimal -class LoanGetInterestTest (DefiTestFramework): + +class LoanGetInterestTest(DefiTestFramework): symbolDFI = "DFI" symbolBTC = "BTC" symboldUSD = "DUSD" @@ -22,7 +23,8 @@ def set_test_params(self): self.setup_clean_chain = True self.extra_args = [ ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=1', - '-fortcanningheight=50', '-fortcanningmuseumheight=200', '-fortcanningparkheight=270', '-fortcanninghillheight=300', '-eunosheight=50', '-txindex=1'] + '-fortcanningheight=50', '-fortcanningmuseumheight=200', '-fortcanningparkheight=270', + '-fortcanninghillheight=300', '-eunosheight=50', '-txindex=1'] ] def setup(self): @@ -79,8 +81,8 @@ def setup(self): 'symbol': self.symboldUSD, 'name': "DUSD stable token", 'fixedIntervalPriceId': "DUSD/USD", - 'mintable': True, - 'interest': 1 + 'mintable': True, + 'interest': 1 }) self.nodes[0].generate(1) @@ -124,7 +126,7 @@ def run_test(self): }) self.nodes[0].generate(1) - self.nodes[0].generate(25) # Accrue interest + self.nodes[0].generate(25) # Accrue interest getInterest = self.nodes[0].getinterest("LOAN150", "DUSD") assert_equal(getInterest[0]['totalInterest'], Decimal('0.99923876')) @@ -143,7 +145,7 @@ def run_test(self): assert_equal(getInterest[0]['totalInterest'], Decimal('1.08571134')) assert_equal(getInterest[0]['interestPerBlock'], Decimal('0.04804032')) - self.nodes[0].generate(10) # Activate FCM + self.nodes[0].generate(10) # Activate FCM self.nodes[0].takeloan({ 'vaultId': vaultId, @@ -183,7 +185,9 @@ def run_test(self): }) self.nodes[0].generate(1) newInterest = self.nodes[0].getinterest("LOAN150", "DUSD") - assert_equal(newInterest[0]['totalInterest'], Decimal('2.69987797') + newInterest[0]['interestPerBlock'] * i) + assert_equal(newInterest[0]['totalInterest'], + Decimal('2.69987797') + newInterest[0]['interestPerBlock'] * i) + if __name__ == '__main__': LoanGetInterestTest().main() diff --git a/test/functional/feature_loan_interest.py b/test/functional/feature_loan_interest.py index b7cca760eb..eb2f686d59 100755 --- a/test/functional/feature_loan_interest.py +++ b/test/functional/feature_loan_interest.py @@ -14,16 +14,19 @@ import time from decimal import Decimal -class LoanInterestTest (DefiTestFramework): + +class LoanInterestTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 self.setup_clean_chain = True self.extra_args = [ - ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-eunosheight=50', '-fortcanningheight=50', '-fortcanningmuseumheight=50', '-txindex=1'], - ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-eunosheight=50', '-fortcanningheight=50', '-fortcanningmuseumheight=50', '-txindex=1']] + ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-eunosheight=50', '-fortcanningheight=50', + '-fortcanningmuseumheight=50', '-txindex=1'], + ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-eunosheight=50', '-fortcanningheight=50', + '-fortcanningmuseumheight=50', '-txindex=1']] def run_test(self): - assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI + assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI print("Generating initial chain...") self.nodes[0].generate(50) @@ -81,38 +84,38 @@ def run_test(self): self.sync_blocks() self.nodes[0].setcollateraltoken({ - 'token': idDFI, - 'factor': 1, - 'fixedIntervalPriceId': "DFI/USD"}) + 'token': idDFI, + 'factor': 1, + 'fixedIntervalPriceId': "DFI/USD"}) self.nodes[0].setcollateraltoken({ - 'token': idBTC, - 'factor': 1, - 'fixedIntervalPriceId': "BTC/USD"}) + 'token': idBTC, + 'factor': 1, + 'fixedIntervalPriceId': "BTC/USD"}) self.nodes[0].generate(1) self.sync_blocks() self.nodes[0].setloantoken({ - 'symbol': symbolTSLA, - 'name': "Tesla stock token", - 'fixedIntervalPriceId': "TSLA/USD", - 'mintable': True, - 'interest': 1}) + 'symbol': symbolTSLA, + 'name': "Tesla stock token", + 'fixedIntervalPriceId': "TSLA/USD", + 'mintable': True, + 'interest': 1}) self.nodes[0].setloantoken({ - 'symbol': symbolGOOGL, - 'name': "Tesla stock token", - 'fixedIntervalPriceId': "TSLA/USD", - 'mintable': True, - 'interest': 2}) + 'symbol': symbolGOOGL, + 'name': "Tesla stock token", + 'fixedIntervalPriceId': "TSLA/USD", + 'mintable': True, + 'interest': 2}) self.nodes[0].setloantoken({ - 'symbol': symboldUSD, - 'name': "DUSD stable token", - 'fixedIntervalPriceId': "DUSD/USD", - 'mintable': True, - 'interest': 1}) + 'symbol': symboldUSD, + 'name': "DUSD stable token", + 'fixedIntervalPriceId': "DUSD/USD", + 'mintable': True, + 'interest': 1}) self.nodes[0].generate(1) self.sync_blocks() @@ -135,7 +138,7 @@ def run_test(self): idTSLA = list(self.nodes[0].getloantoken(symbolTSLA)["token"])[0] idGOOGL = list(self.nodes[0].getloantoken(symbolGOOGL)["token"])[0] - vaultId1 = self.nodes[0].createvault( account0, 'LOAN150') + vaultId1 = self.nodes[0].createvault(account0, 'LOAN150') self.nodes[0].generate(1) self.sync_blocks() @@ -146,8 +149,8 @@ def run_test(self): self.sync_blocks() self.nodes[0].takeloan({ - 'vaultId': vaultId1, - 'amounts': "2000@" + symboldUSD}) + 'vaultId': vaultId1, + 'amounts': "2000@" + symboldUSD}) self.nodes[0].generate(1) self.sync_blocks() @@ -174,7 +177,7 @@ def run_test(self): self.nodes[0].generate(1) self.sync_blocks() - vaultId = self.nodes[0].createvault( account0, 'LOAN150') + vaultId = self.nodes[0].createvault(account0, 'LOAN150') self.nodes[0].generate(1) self.sync_blocks() @@ -183,8 +186,8 @@ def run_test(self): self.sync_blocks() self.nodes[0].takeloan({ - 'vaultId': vaultId, - 'amounts': ["1@" + symbolTSLA, "2@" + symbolGOOGL]}) + 'vaultId': vaultId, + 'amounts': ["1@" + symbolTSLA, "2@" + symbolGOOGL]}) self.nodes[0].generate(1) self.sync_blocks() @@ -213,25 +216,26 @@ def run_test(self): self.sync_blocks() self.nodes[0].takeloan({ - 'vaultId': vaultId, - 'amounts': ["1000@" + symboldUSD]}) + 'vaultId': vaultId, + 'amounts': ["1000@" + symboldUSD]}) self.nodes[0].generate(1) self.sync_blocks() try: self.nodes[0].paybackloan({ - 'vaultId': vaultId, - 'from': account0, - 'amounts': ["999.99900000@" + symboldUSD]}) + 'vaultId': vaultId, + 'from': account0, + 'amounts': ["999.99900000@" + symboldUSD]}) except JSONRPCException as e: errorString = e.error['message'] - assert("Cannot payback this amount of loan for " + symboldUSD + ", either payback full amount or less than this amount" in errorString) + assert ( + "Cannot payback this amount of loan for " + symboldUSD + ", either payback full amount or less than this amount" in errorString) self.nodes[0].paybackloan({ - 'vaultId': vaultId, - 'from': account0, - 'amounts': ["999.99700000@" + symboldUSD]}) + 'vaultId': vaultId, + 'from': account0, + 'amounts': ["999.99700000@" + symboldUSD]}) self.nodes[0].generate(1) self.sync_blocks() @@ -248,9 +252,9 @@ def run_test(self): DUSDbalance = self.nodes[0].getaccount(account0, {}, True)[iddUSD] self.nodes[0].paybackloan({ - 'vaultId': vaultId, - 'from': account0, - 'amounts': ["1000@" + symboldUSD]}) + 'vaultId': vaultId, + 'from': account0, + 'amounts': ["1000@" + symboldUSD]}) self.nodes[0].generate(1) self.sync_blocks() @@ -258,5 +262,6 @@ def run_test(self): newDUSDbalance = self.nodes[0].getaccount(account0, {}, True)[iddUSD] assert_equal(newDUSDbalance, DUSDbalance - Decimal('0.00414257')) + if __name__ == '__main__': LoanInterestTest().main() diff --git a/test/functional/feature_loan_listauctions.py b/test/functional/feature_loan_listauctions.py index a34c7b918f..8584167de3 100755 --- a/test/functional/feature_loan_listauctions.py +++ b/test/functional/feature_loan_listauctions.py @@ -12,13 +12,15 @@ import calendar import time -class LoanTest (DefiTestFramework): + +class LoanTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True self.extra_args = [ - ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-txindex=1', '-fortcanningheight=1'] - ] + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-txindex=1', + '-fortcanningheight=1'] + ] def run_test(self): self.nodes[0].generate(400) @@ -49,25 +51,27 @@ def run_test(self): # setup oracle oracle_address1 = self.nodes[0].getnewaddress("", "legacy") - price_feeds1 = [{"currency": "USD", "token": "DFI"}, {"currency": "USD", "token": "BTC"}, {"currency": "USD", "token": "TSLA"}] + price_feeds1 = [{"currency": "USD", "token": "DFI"}, {"currency": "USD", "token": "BTC"}, + {"currency": "USD", "token": "TSLA"}] oracle_id1 = self.nodes[0].appointoracle(oracle_address1, price_feeds1, 10) self.nodes[0].generate(1) # feed oracle - oracle1_prices = [{"currency": "USD", "tokenAmount": "10@TSLA"}, {"currency": "USD", "tokenAmount": "10@DFI"}, {"currency": "USD", "tokenAmount": "10@BTC"}] + oracle1_prices = [{"currency": "USD", "tokenAmount": "10@TSLA"}, {"currency": "USD", "tokenAmount": "10@DFI"}, + {"currency": "USD", "tokenAmount": "10@BTC"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(oracle_id1, timestamp, oracle1_prices) self.nodes[0].generate(6) # set DFI an BTC as collateral tokens self.nodes[0].setcollateraltoken({ - 'token': "DFI", - 'factor': 1, - 'fixedIntervalPriceId': "DFI/USD"}) + 'token': "DFI", + 'factor': 1, + 'fixedIntervalPriceId': "DFI/USD"}) self.nodes[0].setcollateraltoken({ - 'token': "BTC", - 'factor': 1, - 'fixedIntervalPriceId': "BTC/USD"}) + 'token': "BTC", + 'factor': 1, + 'fixedIntervalPriceId': "BTC/USD"}) self.nodes[0].generate(1) # Create loan schemes @@ -94,41 +98,46 @@ def run_test(self): # set TSLA as loan token self.nodes[0].setloantoken({ - 'symbol': "TSLA", - 'name': "Tesla Token", - 'fixedIntervalPriceId': "TSLA/USD", - 'mintable': True, - 'interest': 1}) - self.nodes[0].generate(8) # let active price update + 'symbol': "TSLA", + 'name': "Tesla Token", + 'fixedIntervalPriceId': "TSLA/USD", + 'mintable': True, + 'interest': 1}) + self.nodes[0].generate(8) # let active price update # take loan for id in vaultsId: self.nodes[0].takeloan({ - 'vaultId': id, - 'amounts': "10@TSLA"}) + 'vaultId': id, + 'amounts': "10@TSLA"}) self.nodes[0].generate(1) # Trigger liquidation updating price in oracle oracle1_prices = [{"currency": "USD", "tokenAmount": "1000@TSLA"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(oracle_id1, timestamp, oracle1_prices) - self.nodes[0].generate(12) # if price is invalid, auctions are blocked so listauction is empty. We need 2 cicles of price update. + self.nodes[0].generate( + 12) # if price is invalid, auctions are blocked so listauction is empty. We need 2 cicles of price update. # Auction tests auctionlist = self.nodes[0].listauctions() - assert_equal(len(auctionlist), vault_number) # all vaults should be under liquidation + assert_equal(len(auctionlist), vault_number) # all vaults should be under liquidation - secondAuction = auctionlist[1] # get second auction to test pagination + secondAuction = auctionlist[1] # get second auction to test pagination - auctionlist = self.nodes[0].listauctions({ "start": { "vaultId": secondAuction["vaultId"], "height": secondAuction["liquidationHeight"] }}) + auctionlist = self.nodes[0].listauctions( + {"start": {"vaultId": secondAuction["vaultId"], "height": secondAuction["liquidationHeight"]}}) assert_equal(len(auctionlist), vault_number - 2) - auctionlist = self.nodes[0].listauctions({ "start": { "vaultId": secondAuction["vaultId"], "height": secondAuction["liquidationHeight"] }, "including_start": True }) + auctionlist = self.nodes[0].listauctions( + {"start": {"vaultId": secondAuction["vaultId"], "height": secondAuction["liquidationHeight"]}, + "including_start": True}) assert_equal(len(auctionlist), vault_number - 1) assert_equal(secondAuction, auctionlist[0]) - auctionlist = self.nodes[0].listauctions({ "limit": 1 }) + auctionlist = self.nodes[0].listauctions({"limit": 1}) assert_equal(len(auctionlist), 1) + if __name__ == '__main__': LoanTest().main() diff --git a/test/functional/feature_loan_low_interest.py b/test/functional/feature_loan_low_interest.py index cabcdcd8e3..d96c4e7112 100755 --- a/test/functional/feature_loan_low_interest.py +++ b/test/functional/feature_loan_low_interest.py @@ -15,12 +15,15 @@ FCH_HEIGHT = 1200 -class LowInterestTest (DefiTestFramework): + +class LowInterestTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True self.extra_args = [ - ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=2', '-fortcanningheight=3', '-fortcanningmuseumheight=4', '-fortcanningparkheight=5', f'-fortcanninghillheight={FCH_HEIGHT}', '-jellyfish_regtest=1', '-txindex=1', '-simulatemainnet'] + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=2', '-fortcanningheight=3', + '-fortcanningmuseumheight=4', '-fortcanningparkheight=5', f'-fortcanninghillheight={FCH_HEIGHT}', + '-jellyfish_regtest=1', '-txindex=1', '-simulatemainnet'] ] account0 = None @@ -36,7 +39,7 @@ def set_test_params(self): def test_load_account0_with_DFI(self): print('loading up account0 with DFI token...') - self.nodes[0].generate(100) # get initial UTXO balance from immature to trusted -> check getbalances() + self.nodes[0].generate(100) # get initial UTXO balance from immature to trusted -> check getbalances() self.account0 = self.nodes[0].get_genesis_keys().ownerAuthAddress # UTXO -> token self.nodes[0].utxostoaccount({self.account0: "199999900@" + self.symbolDFI}) @@ -55,7 +58,7 @@ def test_setup_oracles(self): {"currency": "USD", "tokenAmount": "10@DFI"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(self.oracle_id1, timestamp, oracle1_prices) - self.nodes[0].generate(120) # let active price update + self.nodes[0].generate(120) # let active price update oracle_data = self.nodes[0].getoracledata(self.oracle_id1) assert_equal(len(oracle_data["priceFeeds"]), 2) assert_equal(len(oracle_data["tokenPrices"]), 2) @@ -63,19 +66,19 @@ def test_setup_oracles(self): def test_setup_tokens(self): print('setting up loan and collateral tokens...') self.nodes[0].setloantoken({ - 'symbol': self.symboldUSD, - 'name': "DUSD stable token", - 'fixedIntervalPriceId': "DUSD/USD", - 'mintable': True, - 'interest': 0}) + 'symbol': self.symboldUSD, + 'name': "DUSD stable token", + 'fixedIntervalPriceId': "DUSD/USD", + 'mintable': True, + 'interest': 0}) self.tokenInterest = Decimal(1) self.nodes[0].setloantoken({ - 'symbol': self.symbolDOGE, - 'name': "DOGE token", - 'fixedIntervalPriceId': "DOGE/USD", - 'mintable': True, - 'interest': Decimal(self.tokenInterest*100)}) + 'symbol': self.symbolDOGE, + 'name': "DOGE token", + 'fixedIntervalPriceId': "DOGE/USD", + 'mintable': True, + 'interest': Decimal(self.tokenInterest * 100)}) self.nodes[0].generate(1) # Set token ids @@ -86,21 +89,20 @@ def test_setup_tokens(self): # Mint tokens self.nodes[0].minttokens("1000000@DOGE") self.nodes[0].generate(1) - self.nodes[0].minttokens("2000000@" + self.symboldUSD) # necessary for pools + self.nodes[0].minttokens("2000000@" + self.symboldUSD) # necessary for pools self.nodes[0].generate(1) # Setup collateral tokens self.nodes[0].setcollateraltoken({ - 'token': self.idDFI, - 'factor': 1, - 'fixedIntervalPriceId': "DFI/USD"}) + 'token': self.idDFI, + 'factor': 1, + 'fixedIntervalPriceId': "DFI/USD"}) self.nodes[0].generate(300) assert_equal(len(self.nodes[0].listtokens()), 3) assert_equal(len(self.nodes[0].listloantokens()), 2) assert_equal(len(self.nodes[0].listcollateraltokens()), 1) - def test_setup_poolpairs(self): print("setting up pool pairs...") poolOwner = self.nodes[0].getnewaddress("", "legacy") @@ -138,11 +140,10 @@ def test_setup_loan_scheme(self): print("creating loan scheme...") self.loanInterest = Decimal(1) # Create loan schemes and vaults - self.nodes[0].createloanscheme(150, Decimal(self.loanInterest*100), 'LOAN150') + self.nodes[0].createloanscheme(150, Decimal(self.loanInterest * 100), 'LOAN150') self.nodes[0].generate(1) assert_equal(len(self.nodes[0].listloanschemes()), 1) - def setup(self): print('Generating initial chain...') self.test_load_account0_with_DFI() @@ -154,7 +155,7 @@ def setup(self): def get_new_vault_and_deposit(self, loan_scheme=None, amount=10000): vault_id = self.nodes[0].createvault(self.account0, loan_scheme) self.nodes[0].generate(1) - self.nodes[0].deposittovault(vault_id, self.account0, str(amount)+"@DFI") # enough collateral to take loans + self.nodes[0].deposittovault(vault_id, self.account0, str(amount) + "@DFI") # enough collateral to take loans self.nodes[0].generate(1) return vault_id @@ -165,7 +166,7 @@ def go_to_FCH(self): assert_equal(blockChainInfo["softforks"]["fortcanninghill"]["active"], True) def go_before_FCH(self, n_blocks=500): - self.nodes[0].invalidateblock(self.nodes[0].getblockhash(FCH_HEIGHT-n_blocks)) + self.nodes[0].invalidateblock(self.nodes[0].getblockhash(FCH_HEIGHT - n_blocks)) self.nodes[0].generate(1) def is_FCH(self): @@ -175,8 +176,8 @@ def test_new_loan_with_interest_lower_than_1satoshi(self, payback=False): vault_id = self.get_new_vault_and_deposit() self.nodes[0].takeloan({ - 'vaultId': vault_id, - 'amounts': "0.001314@DOGE"}) + 'vaultId': vault_id, + 'amounts': "0.001314@DOGE"}) self.nodes[0].generate(1) vault_data = self.nodes[0].getvault(vault_id) assert_equal(vault_data["interestAmounts"][0], '0.00000001@DOGE') @@ -184,7 +185,7 @@ def test_new_loan_with_interest_lower_than_1satoshi(self, payback=False): self.nodes[0].generate(35) vault_data = self.nodes[0].getvault(vault_id) expected_interest = self.is_FCH() and '0.00000009' or '0.00000036' - assert_equal(vault_data["interestAmounts"][0], expected_interest+'@DOGE') + assert_equal(vault_data["interestAmounts"][0], expected_interest + '@DOGE') if not payback: return @@ -192,19 +193,18 @@ def test_new_loan_with_interest_lower_than_1satoshi(self, payback=False): # Payback expected_payback = self.is_FCH() and '0.00131409' or '0.00131436' self.nodes[0].paybackloan({ - 'vaultId': vault_id, - 'from': self.account0, - 'amounts': expected_payback+'@DOGE'}) + 'vaultId': vault_id, + 'from': self.account0, + 'amounts': expected_payback + '@DOGE'}) self.nodes[0].generate(1) vault_data = self.nodes[0].getvault(vault_id) assert_equal(vault_data["interestAmounts"], []) - def test_new_loan_with_interest_exactly_25satoshi(self, payback=False): vault_id = self.get_new_vault_and_deposit() self.nodes[0].takeloan({ - 'vaultId': vault_id, - 'amounts': "0.1314@DOGE"}) + 'vaultId': vault_id, + 'amounts': "0.1314@DOGE"}) self.nodes[0].generate(1) vault_data = self.nodes[0].getvault(vault_id) assert_equal(vault_data["interestAmounts"][0], '0.00000025@DOGE') @@ -218,9 +218,9 @@ def test_new_loan_with_interest_exactly_25satoshi(self, payback=False): # Payback self.nodes[0].paybackloan({ - 'vaultId': vault_id, - 'from': self.account0, - 'amounts': '0.13140900@DOGE'}) + 'vaultId': vault_id, + 'from': self.account0, + 'amounts': '0.13140900@DOGE'}) self.nodes[0].generate(1) vault_data = self.nodes[0].getvault(vault_id) assert_equal(vault_data["interestAmounts"], []) @@ -228,8 +228,8 @@ def test_new_loan_with_interest_exactly_25satoshi(self, payback=False): def test_new_loan_with_interest_over_1satoshi(self, payback=False): vault_id = self.get_new_vault_and_deposit() self.nodes[0].takeloan({ - 'vaultId': vault_id, - 'amounts': "100@DOGE"}) + 'vaultId': vault_id, + 'amounts': "100@DOGE"}) self.nodes[0].generate(1) vault_data = self.nodes[0].getvault(vault_id) assert_equal(vault_data["interestAmounts"][0], '0.00019026@DOGE') @@ -237,16 +237,16 @@ def test_new_loan_with_interest_over_1satoshi(self, payback=False): self.nodes[0].generate(35) vault_data = self.nodes[0].getvault(vault_id) expected_interest = self.is_FCH() and '0.00684932' or '0.00684936' - assert_equal(vault_data["interestAmounts"][0], expected_interest+'@DOGE') + assert_equal(vault_data["interestAmounts"][0], expected_interest + '@DOGE') if not payback: return # Payback expected_payback = self.is_FCH() and '100.00684932' or '100.00684936' self.nodes[0].paybackloan({ - 'vaultId': vault_id, - 'from': self.account0, - 'amounts': expected_payback+'@DOGE'}) + 'vaultId': vault_id, + 'from': self.account0, + 'amounts': expected_payback + '@DOGE'}) self.nodes[0].generate(1) vault_data = self.nodes[0].getvault(vault_id) assert_equal(vault_data["interestAmounts"], []) @@ -254,8 +254,8 @@ def test_new_loan_with_interest_over_1satoshi(self, payback=False): def test_low_loan(self, payback=False): vault_id = self.get_new_vault_and_deposit() self.nodes[0].takeloan({ - 'vaultId': vault_id, - 'amounts': "0.00000001@DOGE"}) + 'vaultId': vault_id, + 'amounts': "0.00000001@DOGE"}) self.nodes[0].generate(1) vault_data = self.nodes[0].getvault(vault_id) assert_equal(vault_data["interestAmounts"][0], '0.00000001@DOGE') @@ -263,16 +263,16 @@ def test_low_loan(self, payback=False): self.nodes[0].generate(35) vault_data = self.nodes[0].getvault(vault_id) expected_interest = self.is_FCH() and '0.00000001' or '0.00000036' - assert_equal(vault_data["interestAmounts"][0], expected_interest+'@DOGE') + assert_equal(vault_data["interestAmounts"][0], expected_interest + '@DOGE') if not payback: return # Payback expected_payback = self.is_FCH() and '0.00000002' or '0.00000037' self.nodes[0].paybackloan({ - 'vaultId': vault_id, - 'from': self.account0, - 'amounts': expected_payback+'@DOGE'}) + 'vaultId': vault_id, + 'from': self.account0, + 'amounts': expected_payback + '@DOGE'}) self.nodes[0].generate(1) vault_data = self.nodes[0].getvault(vault_id) assert_equal(vault_data["interestAmounts"], []) @@ -280,8 +280,8 @@ def test_low_loan(self, payback=False): def test_high_loan(self, payback=False): vault_id = self.get_new_vault_and_deposit() self.nodes[0].takeloan({ - 'vaultId': vault_id, - 'amounts': "2345.225@DOGE"}) + 'vaultId': vault_id, + 'amounts': "2345.225@DOGE"}) self.nodes[0].generate(1) vault_data = self.nodes[0].getvault(vault_id) assert_equal(vault_data["interestAmounts"][0], '0.00446200@DOGE') @@ -289,16 +289,16 @@ def test_high_loan(self, payback=False): self.nodes[0].generate(35) vault_data = self.nodes[0].getvault(vault_id) expected_interest = self.is_FCH() and '0.16063185' or '0.16063200' - assert_equal(vault_data["interestAmounts"][0], expected_interest+'@DOGE') + assert_equal(vault_data["interestAmounts"][0], expected_interest + '@DOGE') if not payback: return # Payback expected_payback = self.is_FCH() and '2345.38563185' or '2345.38563200' self.nodes[0].paybackloan({ - 'vaultId': vault_id, - 'from': self.account0, - 'amounts': expected_payback+'@DOGE'}) + 'vaultId': vault_id, + 'from': self.account0, + 'amounts': expected_payback + '@DOGE'}) self.nodes[0].generate(1) vault_data = self.nodes[0].getvault(vault_id) assert_equal(vault_data["interestAmounts"], []) @@ -307,8 +307,8 @@ def test_1satoshi_loan_pre_post_fork(self, payback=False): self.go_before_FCH(30) vault_id = self.get_new_vault_and_deposit() self.nodes[0].takeloan({ - 'vaultId': vault_id, - 'amounts': "0.00000001@DOGE"}) + 'vaultId': vault_id, + 'amounts': "0.00000001@DOGE"}) self.nodes[0].generate(1) vault_data = self.nodes[0].getvault(vault_id) assert_equal(vault_data["interestAmounts"][0], '0.00000001@DOGE') @@ -316,8 +316,8 @@ def test_1satoshi_loan_pre_post_fork(self, payback=False): self.go_to_FCH() self.nodes[0].takeloan({ - 'vaultId': vault_id, - 'amounts': "0.00000001@DOGE"}) + 'vaultId': vault_id, + 'amounts': "0.00000001@DOGE"}) self.nodes[0].generate(10) vault_data = self.nodes[0].getvault(vault_id) assert_equal(vault_data["interestAmounts"][0], '0.00000028@DOGE') @@ -330,9 +330,9 @@ def test_1satoshi_loan_pre_post_fork(self, payback=False): return # Payback self.nodes[0].paybackloan({ - 'vaultId': vault_id, - 'from': self.account0, - 'amounts': '0.00000030@DOGE'}) + 'vaultId': vault_id, + 'from': self.account0, + 'amounts': '0.00000030@DOGE'}) self.nodes[0].generate(1) vault_data = self.nodes[0].getvault(vault_id) assert_equal(vault_data["interestAmounts"], []) @@ -341,8 +341,8 @@ def test_new_loan_with_interest_lower_than_1satoshi_pre_post_fork(self, payback= self.go_before_FCH(30) vault_id = self.get_new_vault_and_deposit() self.nodes[0].takeloan({ - 'vaultId': vault_id, - 'amounts': "0.001314@DOGE"}) + 'vaultId': vault_id, + 'amounts': "0.001314@DOGE"}) self.nodes[0].generate(1) vault_data = self.nodes[0].getvault(vault_id) assert_equal(vault_data["interestAmounts"][0], '0.00000001@DOGE') @@ -350,8 +350,8 @@ def test_new_loan_with_interest_lower_than_1satoshi_pre_post_fork(self, payback= self.go_to_FCH() self.nodes[0].takeloan({ - 'vaultId': vault_id, - 'amounts': "0.00000001@DOGE"}) + 'vaultId': vault_id, + 'amounts': "0.00000001@DOGE"}) self.nodes[0].generate(10) vault_data = self.nodes[0].getvault(vault_id) assert_equal(vault_data["interestAmounts"][0], '0.00000031@DOGE') @@ -364,9 +364,9 @@ def test_new_loan_with_interest_lower_than_1satoshi_pre_post_fork(self, payback= return # Payback self.nodes[0].paybackloan({ - 'vaultId': vault_id, - 'from': self.account0, - 'amounts': '0.00131434@DOGE'}) + 'vaultId': vault_id, + 'from': self.account0, + 'amounts': '0.00131434@DOGE'}) self.nodes[0].generate(100) vault_data = self.nodes[0].getvault(vault_id) assert_equal(vault_data["interestAmounts"], []) @@ -375,8 +375,8 @@ def test_new_loan_with_interest_over_1satoshi_pre_post_fork(self, payback=True): self.go_before_FCH(30) vault_id = self.get_new_vault_and_deposit() self.nodes[0].takeloan({ - 'vaultId': vault_id, - 'amounts': "100@DOGE"}) + 'vaultId': vault_id, + 'amounts': "100@DOGE"}) self.nodes[0].generate(1) vault_data = self.nodes[0].getvault(vault_id) assert_equal(vault_data["interestAmounts"][0], '0.00019026@DOGE') @@ -384,8 +384,8 @@ def test_new_loan_with_interest_over_1satoshi_pre_post_fork(self, payback=True): self.go_to_FCH() self.nodes[0].takeloan({ - 'vaultId': vault_id, - 'amounts': "100@DOGE"}) + 'vaultId': vault_id, + 'amounts': "100@DOGE"}) self.nodes[0].generate(10) vault_data = self.nodes[0].getvault(vault_id) assert_equal(vault_data["interestAmounts"][0], '0.00951298@DOGE') @@ -398,15 +398,13 @@ def test_new_loan_with_interest_over_1satoshi_pre_post_fork(self, payback=True): return # Payback self.nodes[0].paybackloan({ - 'vaultId': vault_id, - 'from': self.account0, - 'amounts': '200.01331815@DOGE'}) + 'vaultId': vault_id, + 'from': self.account0, + 'amounts': '200.01331815@DOGE'}) self.nodes[0].generate(10) vault_data = self.nodes[0].getvault(vault_id) assert_equal(vault_data["interestAmounts"], []) - - def run_test(self): self.setup() @@ -444,5 +442,6 @@ def run_test(self): self.test_new_loan_with_interest_lower_than_1satoshi_pre_post_fork() self.test_new_loan_with_interest_over_1satoshi_pre_post_fork() + if __name__ == '__main__': LowInterestTest().main() diff --git a/test/functional/feature_loan_payback_dfi.py b/test/functional/feature_loan_payback_dfi.py index 8695dc48cd..c403d1c10b 100755 --- a/test/functional/feature_loan_payback_dfi.py +++ b/test/functional/feature_loan_payback_dfi.py @@ -14,13 +14,14 @@ from decimal import Decimal, ROUND_UP -class PaybackDFILoanTest (DefiTestFramework): +class PaybackDFILoanTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True self.extra_args = [ ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=1', '-eunosheight=50', - '-fortcanningheight=50', '-fortcanninghillheight=50', '-fortcanningroadheight=196', '-fortcanningspringheight=200', '-debug=loan', '-txindex=1'] + '-fortcanningheight=50', '-fortcanninghillheight=50', '-fortcanningroadheight=196', + '-fortcanningspringheight=200', '-debug=loan', '-txindex=1'] ] def run_test(self): @@ -93,8 +94,8 @@ def run_test(self): 'symbol': symboldUSD, 'name': "DUSD stable token", 'fixedIntervalPriceId': "DUSD/USD", - 'mintable': True, - 'interest': 1 + 'mintable': True, + 'interest': 1 }) self.nodes[0].generate(1) @@ -144,28 +145,31 @@ def run_test(self): }) # Should not be able to payback loan before DFI payback enabled - assert_raises_rpc_error(-32600, "Payback of loan via DFI token is not currently active", self.nodes[0].paybackloan, { - 'vaultId': vaultId, - 'from': account0, - 'amounts': "1@DFI" - }) + assert_raises_rpc_error(-32600, "Payback of loan via DFI token is not currently active", + self.nodes[0].paybackloan, { + 'vaultId': vaultId, + 'from': account0, + 'amounts': "1@DFI" + }) - assert_raises_rpc_error(-5, 'Unrecognised type argument provided, valid types are: consortium, gov, locks, oracles, params, poolpairs, token,', - self.nodes[0].setgov, {"ATTRIBUTES":{'v0/live/economy/dfi_payback_tokens':'1'}}) + assert_raises_rpc_error(-5, + 'Unrecognised type argument provided, valid types are: consortium, gov, locks, oracles, params, poolpairs, token,', + self.nodes[0].setgov, {"ATTRIBUTES": {'v0/live/economy/dfi_payback_tokens': '1'}}) # Disable loan payback - self.nodes[0].setgov({"ATTRIBUTES":{'v0/token/' + iddUSD + '/payback_dfi':'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/token/' + iddUSD + '/payback_dfi': 'false'}}) self.nodes[0].generate(1) # Should not be able to payback loan before DFI payback enabled - assert_raises_rpc_error(-32600, "Payback of loan via DFI token is not currently active", self.nodes[0].paybackloan, { - 'vaultId': vaultId, - 'from': account0, - 'amounts': "1@DFI" - }) + assert_raises_rpc_error(-32600, "Payback of loan via DFI token is not currently active", + self.nodes[0].paybackloan, { + 'vaultId': vaultId, + 'from': account0, + 'amounts': "1@DFI" + }) # Enable loan payback - self.nodes[0].setgov({"ATTRIBUTES":{'v0/token/' + iddUSD + '/payback_dfi':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/token/' + iddUSD + '/payback_dfi': 'true'}}) self.nodes[0].generate(1) vaultBefore = self.nodes[0].getvault(vaultId) @@ -194,7 +198,7 @@ def run_test(self): assert_equal(Decimal(amountAfter) - Decimal(interestAfter), (Decimal(amountBefore) - (10 * Decimal('0.99')))) # Test 5% penalty - self.nodes[0].setgov({"ATTRIBUTES":{'v0/token/' + iddUSD + '/payback_dfi_fee_pct':'0.05'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/token/' + iddUSD + '/payback_dfi_fee_pct': '0.05'}}) self.nodes[0].generate(1) vaultBefore = self.nodes[0].getvault(vaultId) @@ -242,7 +246,8 @@ def run_test(self): assert_equal(len(vaultAfter['loanAmounts']), 0) assert_equal(len(vaultAfter['interestAmounts']), 0) - assert_equal(Decimal(balanceDFIBefore) - Decimal(balanceDFIAfter), (Decimal(amountBefore) / Decimal('9.5')).quantize(Decimal('1E-8'), rounding=ROUND_UP)) + assert_equal(Decimal(balanceDFIBefore) - Decimal(balanceDFIAfter), + (Decimal(amountBefore) / Decimal('9.5')).quantize(Decimal('1E-8'), rounding=ROUND_UP)) # Exact amount loan payback in DFI @@ -300,7 +305,7 @@ def run_test(self): # Multiple token payback pre FCR # Disable loan payback - self.nodes[0].setgov({"ATTRIBUTES":{'v0/token/' + iddUSD + '/payback_dfi':'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/token/' + iddUSD + '/payback_dfi': 'false'}}) self.nodes[0].generate(1) vaultId6 = self.nodes[0].createvault(account0, 'LOAN150') self.nodes[0].generate(1) @@ -342,9 +347,9 @@ def run_test(self): }) except JSONRPCException as e: errorString = e.error['message'] - assert("Payback of loan via DFI token is not currently active" in errorString) + assert ("Payback of loan via DFI token is not currently active" in errorString) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/token/' + iddUSD + '/payback_dfi':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/token/' + iddUSD + '/payback_dfi': 'true'}}) self.nodes[0].generate(1) self.nodes[0].paybackloan({ @@ -395,7 +400,9 @@ def run_test(self): {account0: ["100@" + symbolBTC, "1000@" + symboldUSD]}, account0) self.nodes[0].generate(1) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/dfip2206a/dusd_interest_burn':'true', 'v0/token/'+idTSLA+'/loan_payback/'+idBTC: 'true', 'v0/token/'+idTSLA+'/loan_payback/'+iddUSD: 'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/dfip2206a/dusd_interest_burn': 'true', + 'v0/token/' + idTSLA + '/loan_payback/' + idBTC: 'true', + 'v0/token/' + idTSLA + '/loan_payback/' + iddUSD: 'true'}}) self.nodes[0].generate(1) burnAddress = "mfburnZSAM7Gs1hpDeNaMotJXSGA7edosG" @@ -454,7 +461,7 @@ def run_test(self): balanceDFIBefore = balanceDFIAfter burn_before = burn_after - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/dfip2206a/dusd_loan_burn':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/dfip2206a/dusd_loan_burn': 'true'}}) self.nodes[0].generate(1) self.nodes[0].paybackloan({ @@ -483,7 +490,7 @@ def run_test(self): balanceDFIBefore = balanceDFIAfter burn_before = burn_after - self.nodes[0].setgov({"ATTRIBUTES":{'v0/token/' + idTSLA + '/payback_dfi':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/token/' + idTSLA + '/payback_dfi': 'true'}}) self.nodes[0].generate(1) self.nodes[0].paybackloan({ @@ -571,5 +578,6 @@ def run_test(self): assert_equal(Decimal(balanceDUSDAfter) - Decimal(balanceDUSDBefore), Decimal('10')) assert_equal(Decimal(balanceDFIAfter) - Decimal(balanceDFIBefore), Decimal('0')) + if __name__ == '__main__': PaybackDFILoanTest().main() diff --git a/test/functional/feature_loan_payback_dfi_v2.py b/test/functional/feature_loan_payback_dfi_v2.py index 50f443845d..b07772a634 100755 --- a/test/functional/feature_loan_payback_dfi_v2.py +++ b/test/functional/feature_loan_payback_dfi_v2.py @@ -14,14 +14,16 @@ from decimal import Decimal, ROUND_UP -class PaybackDFILoanTest (DefiTestFramework): +class PaybackDFILoanTest(DefiTestFramework): def set_test_params(self): self.FCR_HEIGHT = 800 self.num_nodes = 1 self.FINISHED_SETUP_BLOCK = 0 self.setup_clean_chain = True self.extra_args = [ - ['-walletbroadcast=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=1', '-eunosheight=50','-fortcanningheight=50', '-fortcanninghillheight=50', f'-fortcanningroadheight={self.FCR_HEIGHT}', '-simulatemainnet', '-txindex=1', '-jellyfish_regtest=1' ], + ['-walletbroadcast=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=1', + '-eunosheight=50', '-fortcanningheight=50', '-fortcanninghillheight=50', + f'-fortcanningroadheight={self.FCR_HEIGHT}', '-simulatemainnet', '-txindex=1', '-jellyfish_regtest=1'], ] self.symbolDFI = "DFI" self.symbolBTC = "BTC" @@ -29,7 +31,7 @@ def set_test_params(self): self.symbolTSLA = "TSLA" def go_post_FCR(self): - self.nodes[0].generate(self.FCR_HEIGHT+1) + self.nodes[0].generate(self.FCR_HEIGHT + 1) def reset_chain(self): self.nodes[0].invalidateblock(self.nodes[0].getblockhash(1)) @@ -47,7 +49,6 @@ def create_tokens(self): self.nodes[0].utxostoaccount({self.account0: "6000000@" + self.symbolDFI}) self.nodes[0].generate(1) - def setup_oracles(self): self.oracle_address1 = self.nodes[0].getnewaddress("", "legacy") price_feeds1 = [ @@ -67,7 +68,7 @@ def setup_oracles(self): ] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(self.oracle_id1, timestamp, oracle1_prices) - self.nodes[0].generate(120) # make prices active + self.nodes[0].generate(120) # make prices active def setup_loan_tokens(self): self.nodes[0].setcollateraltoken({ @@ -96,8 +97,8 @@ def setup_loan_tokens(self): 'symbol': self.symboldUSD, 'name': "DUSD stable token", 'fixedIntervalPriceId': "DUSD/USD", - 'mintable': True, - 'interest': 1 + 'mintable': True, + 'interest': 1 }) self.nodes[0].generate(1) self.nodes[0].minttokens("70000100@DUSD") @@ -161,7 +162,6 @@ def create_fill_addresses(self): self.nodes[0].accounttoaccount(self.account0, toAmounts) self.nodes[0].generate(1) - # Check balances on each account account = self.nodes[0].getaccount(self.account0) assert_equal(account, ["100.00000000@DUSD"]) @@ -247,7 +247,7 @@ def setup_loanschemes(self): def setup(self, FCR=False): self.nodes[0].generate(100) - if(FCR): + if (FCR): self.go_post_FCR() self.account0 = self.nodes[0].get_genesis_keys().ownerAuthAddress @@ -276,45 +276,47 @@ def payback_DUSD_with_BTC(self): errorString = '' try: self.nodes[0].paybackloan({ - 'vaultId': self.vaultId1, - 'from': self.account0, - 'amounts': "1@BTC" + 'vaultId': self.vaultId1, + 'from': self.account0, + 'amounts': "1@BTC" }) except JSONRPCException as e: errorString = e.error['message'] - assert("Loan token with id (1) does not exist!" in errorString) + assert ("Loan token with id (1) does not exist!" in errorString) def payback_with_DFI_prior_to_atribute_activation(self): # Should not be able to payback loan before DFI payback enabled errorString = '' try: self.nodes[0].paybackloan({ - 'vaultId': self.vaultId1, - 'from': self.account0, - 'amounts': "1@DFI" + 'vaultId': self.vaultId1, + 'from': self.account0, + 'amounts': "1@DFI" }) except JSONRPCException as e: errorString = e.error['message'] - assert("Payback of loan via DFI token is not currently active" in errorString) + assert ("Payback of loan via DFI token is not currently active" in errorString) def setgov_attribute_to_false_and_payback(self): - assert_raises_rpc_error(-5, 'Unrecognised type argument provided, valid types are: consortium, gov, locks, oracles, params, poolpairs, token,', - self.nodes[0].setgov, {"ATTRIBUTES":{'v0/live/economy/dfi_payback_tokens':'1'}}) + assert_raises_rpc_error(-5, + 'Unrecognised type argument provided, valid types are: consortium, gov, locks, oracles, params, poolpairs, token,', + self.nodes[0].setgov, {"ATTRIBUTES": {'v0/live/economy/dfi_payback_tokens': '1'}}) # Disable loan payback - self.nodes[0].setgov({"ATTRIBUTES":{'v0/token/' + self.iddUSD + '/payback_dfi':'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/token/' + self.iddUSD + '/payback_dfi': 'false'}}) self.nodes[0].generate(1) # Should not be able to payback loan before DFI payback enabled - assert_raises_rpc_error(-32600, "Payback of loan via DFI token is not currently active", self.nodes[0].paybackloan, { - 'vaultId': self.vaultId1, - 'from': self.account0, - 'amounts': "1@DFI" - }) + assert_raises_rpc_error(-32600, "Payback of loan via DFI token is not currently active", + self.nodes[0].paybackloan, { + 'vaultId': self.vaultId1, + 'from': self.account0, + 'amounts': "1@DFI" + }) def setgov_attribute_to_true_and_payback_with_dfi(self): # Enable loan payback - self.nodes[0].setgov({"ATTRIBUTES":{'v0/token/' + self.iddUSD + '/payback_dfi':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/token/' + self.iddUSD + '/payback_dfi': 'true'}}) self.nodes[0].generate(1) vaultBefore = self.nodes[0].getvault(self.vaultId1) @@ -329,8 +331,9 @@ def setgov_attribute_to_true_and_payback_with_dfi(self): self.nodes[0].generate(1) info = self.nodes[0].getburninfo() - assert_equal(info['dfipaybackfee'], Decimal('0.01000000')) # paybackfee defaults to 1% of total payback -> 0.01 DFI - assert_equal(info['dfipaybacktokens'], ['3.96000000@DUSD']) # 4 - penalty (0.01DFI->0.04USD) + assert_equal(info['dfipaybackfee'], + Decimal('0.01000000')) # paybackfee defaults to 1% of total payback -> 0.01 DFI + assert_equal(info['dfipaybacktokens'], ['3.96000000@DUSD']) # 4 - penalty (0.01DFI->0.04USD) [new_amount, _] = info['paybackburn'][0].split('@') assert_equal(Decimal(new_amount), Decimal('1')) @@ -338,10 +341,11 @@ def setgov_attribute_to_true_and_payback_with_dfi(self): [amountAfter, _] = vaultAfter['loanAmounts'][0].split('@') [interestAfter, _] = vaultAfter['interestAmounts'][0].split('@') - assert_equal(Decimal(amountAfter) - Decimal(interestAfter), Decimal(amountBefore) - Decimal('3.96')) # no payback fee + assert_equal(Decimal(amountAfter) - Decimal(interestAfter), + Decimal(amountBefore) - Decimal('3.96')) # no payback fee def test_5pct_penalty(self): - self.nodes[0].setgov({"ATTRIBUTES":{'v0/token/' + self.iddUSD + '/payback_dfi_fee_pct':'0.05'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/token/' + self.iddUSD + '/payback_dfi_fee_pct': '0.05'}}) self.nodes[0].generate(1) vaultBefore = self.nodes[0].getvault(self.vaultId1) @@ -367,7 +371,8 @@ def test_5pct_penalty(self): [amountAfter, _] = vaultAfter['loanAmounts'][0].split('@') [interestAfter, _] = vaultAfter['interestAmounts'][0].split('@') - assert_equal(Decimal(amountAfter) - Decimal(interestAfter), (Decimal(amountBefore) - (Decimal('3.8')))) # 4$ in DFI - 0.05fee = 3.8$ paid back + assert_equal(Decimal(amountAfter) - Decimal(interestAfter), + (Decimal(amountBefore) - (Decimal('3.8')))) # 4$ in DFI - 0.05fee = 3.8$ paid back def overpay_loan_in_DFI(self): vaultBefore = self.nodes[0].getvault(self.vaultId1) @@ -384,8 +389,9 @@ def overpay_loan_in_DFI(self): self.nodes[0].generate(1) info = self.nodes[0].getburninfo() - assert_equal(info['dfipaybackfee'], Decimal('1.27368435')) - assert_equal(info['dfipaybacktokens'], ['100.00001113@DUSD']) # Total loan in vault1 + previous dfipaybacktokens + assert_equal(info['dfipaybackfee'], Decimal('1.27368435')) + assert_equal(info['dfipaybacktokens'], + ['100.00001113@DUSD']) # Total loan in vault1 + previous dfipaybacktokens [new_amount, _] = info['paybackburn'][0].split('@') assert_equal(Decimal(new_amount), Decimal(old_amount) + Decimal('24.27368714')) @@ -397,7 +403,8 @@ def overpay_loan_in_DFI(self): assert_equal(len(vaultAfter['loanAmounts']), 0) assert_equal(len(vaultAfter['interestAmounts']), 0) - assert_equal(Decimal(balanceDFIBefore) - Decimal(balanceDFIAfter), (Decimal(amountBefore) / Decimal('3.8')).quantize(Decimal('1E-8'), rounding=ROUND_UP)) + assert_equal(Decimal(balanceDFIBefore) - Decimal(balanceDFIAfter), + (Decimal(amountBefore) / Decimal('3.8')).quantize(Decimal('1E-8'), rounding=ROUND_UP)) def take_new_loan_payback_exact_amount_in_DFI(self): self.nodes[0].takeloan({ @@ -412,7 +419,7 @@ def take_new_loan_payback_exact_amount_in_DFI(self): self.nodes[0].paybackloan({ 'vaultId': self.vaultId1, 'from': self.addr_DFI, - 'amounts': "26.31579449@DFI" # 25 DFI + 0.05 penalty + interests + 'amounts': "26.31579449@DFI" # 25 DFI + 0.05 penalty + interests }) self.nodes[0].generate(1) @@ -443,47 +450,47 @@ def new_vault_payback_TSLA_loan_with_DFI(self): }) self.nodes[0].generate(1) - #Should not be able to payback loan token other than DUSD with DFI + # Should not be able to payback loan token other than DUSD with DFI assert_raises_rpc_error(-32600, "There is no loan on token (DUSD) in this vault!", self.nodes[0].paybackloan, { 'vaultId': self.vaultId2, 'from': self.addr_DFI, 'amounts': "10@DFI" }) # Should not be able to payback loan before DFI payback enabled - assert_raises_rpc_error(-32600, "Payback of loan via DFI token is not currently active", self.nodes[0].paybackloan, { - 'vaultId': self.vaultId2, - 'from': self.addr_DFI, - 'loans': [{ - 'dToken': self.idTSLA, - 'amounts': "1@DFI" - }] - }) + assert_raises_rpc_error(-32600, "Payback of loan via DFI token is not currently active", + self.nodes[0].paybackloan, { + 'vaultId': self.vaultId2, + 'from': self.addr_DFI, + 'loans': [{ + 'dToken': self.idTSLA, + 'amounts': "1@DFI" + }] + }) def setgov_enable_dfi_payback_and_dfi_fee_pct(self): - self.nodes[0].setgov({"ATTRIBUTES":{'v0/token/' + self.idTSLA + '/payback_dfi':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/token/' + self.idTSLA + '/payback_dfi': 'true'}}) self.nodes[0].generate(1) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/token/' + self.idTSLA + '/payback_dfi_fee_pct':'0.01'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/token/' + self.idTSLA + '/payback_dfi_fee_pct': '0.01'}}) self.nodes[0].generate(1) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/token/' + self.idTSLA + '/payback_dfi':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/token/' + self.idTSLA + '/payback_dfi': 'true'}}) self.nodes[0].generate(1) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/token/' + self.idTSLA + '/payback_dfi_fee_pct':'0.01'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/token/' + self.idTSLA + '/payback_dfi_fee_pct': '0.01'}}) self.nodes[0].generate(1) def setgov_enable_dTSLA_to_dBTC_payback(self): self.nodes[0].setgov({ - "ATTRIBUTES":{ - 'v0/token/'+self.idTSLA+'/loan_payback/'+self.idBTC: 'true', - 'v0/token/'+self.idTSLA+'/loan_payback_fee_pct/'+self.idBTC: '0.25' + "ATTRIBUTES": { + 'v0/token/' + self.idTSLA + '/loan_payback/' + self.idBTC: 'true', + 'v0/token/' + self.idTSLA + '/loan_payback_fee_pct/' + self.idBTC: '0.25' } }) self.nodes[0].generate(1) attributes = self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'] - assert_equal(attributes['v0/token/'+self.idTSLA+'/loan_payback/'+self.idBTC], 'true') - assert_equal(attributes['v0/token/'+self.idTSLA+'/loan_payback_fee_pct/'+self.idBTC], '0.25') - + assert_equal(attributes['v0/token/' + self.idTSLA + '/loan_payback/' + self.idBTC], 'true') + assert_equal(attributes['v0/token/' + self.idTSLA + '/loan_payback_fee_pct/' + self.idBTC], '0.25') def payback_TSLA_with_1_dfi(self): [balanceDFIBefore, _] = self.nodes[0].getaccount(self.addr_DFI)[0].split('@') @@ -557,8 +564,10 @@ def payback_TSLA_and_dUSD_with_1_dfi(self): [interestTSLAAfter, _] = vaultAfter['interestAmounts'][0].split('@') [amountDUSDAfter, _] = vaultAfter['loanAmounts'][1].split('@') [interestDUSDAfter, _] = vaultAfter['interestAmounts'][1].split('@') - assert_equal(Decimal(amountTSLAAfter) - Decimal(interestTSLAAfter), (Decimal(amountTSLABefore) - Decimal('0.792'))) - assert_equal(Decimal(amountDUSDAfter) - Decimal(interestDUSDAfter), (Decimal(amountDUSDBefore) - Decimal('3.8'))) + assert_equal(Decimal(amountTSLAAfter) - Decimal(interestTSLAAfter), + (Decimal(amountTSLABefore) - Decimal('0.792'))) + assert_equal(Decimal(amountDUSDAfter) - Decimal(interestDUSDAfter), + (Decimal(amountDUSDBefore) - Decimal('3.8'))) [balanceDFIAfter, _] = self.nodes[0].getaccount(self.addr_DFI)[0].split('@') assert_equal(Decimal(balanceDFIBefore) - Decimal(balanceDFIAfter), Decimal('1.001')) @@ -632,7 +641,8 @@ def payback_TSLA_with_1_dBTC(self): vaultAfter = self.nodes[0].getvault(self.vaultId3) [amountAfter, _] = vaultAfter['loanAmounts'][0].split('@') [interestAfter, _] = vaultAfter['interestAmounts'][0].split('@') - assert_equal(Decimal(amountAfter) - Decimal(interestAfter), (Decimal(amountBefore) - Decimal('3750000'))) # add 25% fee for payback with BTC + assert_equal(Decimal(amountAfter) - Decimal(interestAfter), + (Decimal(amountBefore) - Decimal('3750000'))) # add 25% fee for payback with BTC [balanceBTCAfter, _] = self.nodes[0].getaccount(self.addr_BTC)[0].split('@') assert_equal(Decimal(balanceBTCBefore) - Decimal(balanceBTCAfter), Decimal('0.5')) @@ -664,7 +674,6 @@ def payback_dUSD_with_dUSD(self): }) self.nodes[0].generate(1) - vaultAfter = self.nodes[0].getvault(self.vaultId2) [amountAfter, _] = vaultAfter['loanAmounts'][0].split('@') [interestAfter, _] = vaultAfter['interestAmounts'][0].split('@') @@ -750,7 +759,7 @@ def multipayback_DUSD_with_DFI_and_DUSD(self): } ] }) - #self.nodes[0].paybackloan({ + # self.nodes[0].paybackloan({ # 'vaultId': self.vaultId5, # 'from': self.addr_DFI_DUSD, # 'loans': [ @@ -763,14 +772,15 @@ def multipayback_DUSD_with_DFI_and_DUSD(self): # 'amounts': "10@DFI" # } # ] - #}) + # }) self.nodes[0].generate(1) vaultAfter = self.nodes[0].getvault(self.vaultId5) assert_equal(vaultAfter["loanAmounts"], []) [balanceDUSDAfter, _] = self.nodes[0].getaccount(self.addr_DFI_DUSD)[1].split('@') [balanceDFIAfter, _] = self.nodes[0].getaccount(self.addr_DFI_DUSD)[0].split('@') - assert_equal(Decimal(balanceDUSDBefore) - Decimal(balanceDUSDAfter), Decimal('62.00000191')) # balanceAfter = 71DUSD - (100.00000191DUSD loan+interests - 38DUSD (40DFI - 5% fee) + assert_equal(Decimal(balanceDUSDBefore) - Decimal(balanceDUSDAfter), Decimal( + '62.00000191')) # balanceAfter = 71DUSD - (100.00000191DUSD loan+interests - 38DUSD (40DFI - 5% fee) assert_equal(Decimal(balanceDFIBefore) - Decimal(balanceDFIAfter), Decimal('10')) def multipayback_DUSD_with_DFI_and_DUSD_Pre_FCR(self): @@ -809,10 +819,10 @@ def multipayback_DUSD_with_DFI_and_DUSD_Pre_FCR(self): }) except JSONRPCException as e: errorString = e.error['message'] - assert("Payback of loan via DFI token is not currently active" in errorString) + assert ("Payback of loan via DFI token is not currently active" in errorString) self.nodes[0].generate(1) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/token/' + self.iddUSD + '/payback_dfi':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/token/' + self.iddUSD + '/payback_dfi': 'true'}}) self.nodes[0].generate(1) self.nodes[0].paybackloan({ @@ -829,7 +839,6 @@ def multipayback_DUSD_with_DFI_and_DUSD_Pre_FCR(self): assert_equal(Decimal(balanceDUSDBefore) - Decimal(balanceDUSDAfter), Decimal('60.40000571')) assert_equal(Decimal(balanceDFIBefore) - Decimal(balanceDFIAfter), Decimal('10')) - def run_test(self): self.setup(FCR=True) self.payback_DUSD_with_BTC() @@ -861,5 +870,6 @@ def run_test(self): self.setup(FCR=False) self.multipayback_DUSD_with_DFI_and_DUSD_Pre_FCR() + if __name__ == '__main__': PaybackDFILoanTest().main() diff --git a/test/functional/feature_loan_payback_with_collateral.py b/test/functional/feature_loan_payback_with_collateral.py index 16352a702a..dc865cc10e 100755 --- a/test/functional/feature_loan_payback_with_collateral.py +++ b/test/functional/feature_loan_payback_with_collateral.py @@ -14,7 +14,8 @@ BLOCKS_PER_YEAR = Decimal(1051200) -class LoanPaybackWithCollateralTest (DefiTestFramework): + +class LoanPaybackWithCollateralTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 @@ -34,20 +35,20 @@ def set_test_params(self): '-fortcanningepilogueheight=1', '-jellyfish_regtest=1', '-simulatemainnet=1' - ]] + ]] def createOracles(self): self.oracle_address1 = self.nodes[0].getnewaddress("", "legacy") price_feeds = [{"currency": "USD", "token": "DFI"}, - {"currency": "USD", "token": "DUSD"}, - {"currency": "USD", "token": "TSLA"}] + {"currency": "USD", "token": "DUSD"}, + {"currency": "USD", "token": "TSLA"}] self.oracle_id1 = self.nodes[0].appointoracle(self.oracle_address1, price_feeds, 10) self.nodes[0].generate(1) # feed oracle oracle_prices = [{"currency": "USD", "tokenAmount": "1@TSLA"}, - {"currency": "USD", "tokenAmount": "1@DUSD"}, - {"currency": "USD", "tokenAmount": "10@DFI"}] + {"currency": "USD", "tokenAmount": "1@DUSD"}, + {"currency": "USD", "tokenAmount": "10@DFI"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(self.oracle_id1, timestamp, oracle_prices) @@ -110,7 +111,7 @@ def setup(self): self.mn_address: [ '10000@' + self.symbolDFI, '8000@' + self.symbolDUSD] - }, self.mn_address) + }, self.mn_address) self.nodes[0].generate(1) self.nodes[0].setloantoken({ @@ -128,23 +129,24 @@ def setup(self): # Set collateral tokens self.nodes[0].setcollateraltoken({ - 'token': self.symbolDFI, - 'factor': 1, - 'fixedIntervalPriceId': "DFI/USD" - }) + 'token': self.symbolDFI, + 'factor': 1, + 'fixedIntervalPriceId': "DFI/USD" + }) self.nodes[0].setcollateraltoken({ - 'token': self.symbolDUSD, - 'factor': 1, - 'fixedIntervalPriceId': "DUSD/USD" - }) + 'token': self.symbolDUSD, + 'factor': 1, + 'fixedIntervalPriceId': "DUSD/USD" + }) self.nodes[0].generate(120) - - self.nodes[0].accounttoaccount(self.mn_address, {self.account0: str(self.collateralAmount) + "@" + self.symbolDUSD}) - self.nodes[0].accounttoaccount(self.mn_address, {self.account0: str(self.collateralAmount) + "@" + self.symbolDFI}) + self.nodes[0].accounttoaccount(self.mn_address, + {self.account0: str(self.collateralAmount) + "@" + self.symbolDUSD}) + self.nodes[0].accounttoaccount(self.mn_address, + {self.account0: str(self.collateralAmount) + "@" + self.symbolDFI}) self.nodes[0].generate(1) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/token/' + self.idDUSD + '/loan_payback_collateral':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/token/' + self.idDUSD + '/loan_payback_collateral': 'true'}}) self.nodes[0].generate(1) vault_address = self.nodes[0].getnewaddress() @@ -155,10 +157,11 @@ def setup(self): def test_guards(self): height = self.nodes[0].getblockcount() - self.nodes[0].setgov({"ATTRIBUTES":{'v0/token/' + self.idDUSD + '/loan_payback_collateral':'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/token/' + self.idDUSD + '/loan_payback_collateral': 'false'}}) self.nodes[0].generate(1) - assert_raises_rpc_error(-32600, "Payback of DUSD loan with collateral is not currently active", self.nodes[0].paybackwithcollateral, self.vaultId) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/token/' + self.idDUSD + '/loan_payback_collateral':'true'}}) + assert_raises_rpc_error(-32600, "Payback of DUSD loan with collateral is not currently active", + self.nodes[0].paybackwithcollateral, self.vaultId) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/token/' + self.idDUSD + '/loan_payback_collateral': 'true'}}) self.nodes[0].generate(1) assert_raises_rpc_error(-32600, "Vault has no collaterals", self.nodes[0].paybackwithcollateral, self.vaultId) @@ -167,7 +170,8 @@ def test_guards(self): self.nodes[0].deposittovault(self.vaultId, self.account0, str(self.collateralAmount) + "@" + self.symbolDFI) self.nodes[0].generate(1) - assert_raises_rpc_error(-32600, "Vault does not have any DUSD collaterals", self.nodes[0].paybackwithcollateral, self.vaultId) + assert_raises_rpc_error(-32600, "Vault does not have any DUSD collaterals", self.nodes[0].paybackwithcollateral, + self.vaultId) self.nodes[0].deposittovault(self.vaultId, self.account0, str(self.collateralAmount) + "@" + self.symbolDUSD) self.nodes[0].generate(1) @@ -175,17 +179,18 @@ def test_guards(self): assert_raises_rpc_error(-32600, "Vault has no loans", self.nodes[0].paybackwithcollateral, self.vaultId) # take TSLA loan - self.nodes[0].takeloan({ "vaultId": self.vaultId, "amounts": "1@" + self.symbolTSLA }) + self.nodes[0].takeloan({"vaultId": self.vaultId, "amounts": "1@" + self.symbolTSLA}) self.nodes[0].generate(1) - assert_raises_rpc_error(-32600, "Vault does not have any DUSD loans", self.nodes[0].paybackwithcollateral, self.vaultId) + assert_raises_rpc_error(-32600, "Vault does not have any DUSD loans", self.nodes[0].paybackwithcollateral, + self.vaultId) self.rollback_to(height) def test_guard_against_liquidation(self): height = self.nodes[0].getblockcount() - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_collateral_factor': '1.49'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_collateral_factor': '1.49'}}) self.nodes[0].generate(1) # Check results @@ -199,16 +204,18 @@ def test_guard_against_liquidation(self): self.nodes[0].deposittovault(self.vaultId, self.account0, "1000@" + self.symbolDUSD) self.nodes[0].generate(1) - self.nodes[0].takeloan({ "vaultId": self.vaultId, "amounts": "1900@" + self.symbolTSLA }) + self.nodes[0].takeloan({"vaultId": self.vaultId, "amounts": "1900@" + self.symbolTSLA}) self.nodes[0].generate(1) - self.nodes[0].takeloan({ "vaultId": self.vaultId, "amounts": "100@" + self.symbolDUSD }) + self.nodes[0].takeloan({"vaultId": self.vaultId, "amounts": "100@" + self.symbolDUSD}) self.nodes[0].generate(1) - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'50000000'}}) - self.nodes[0].generate(2) # accrue enough interest to drop below collateralization ratio + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '50000000'}}) + self.nodes[0].generate(2) # accrue enough interest to drop below collateralization ratio - assert_raises_rpc_error(-32600, "Vault does not have enough collateralization ratio defined by loan scheme - 143 < 150", self.nodes[0].paybackwithcollateral, self.vaultId) + assert_raises_rpc_error(-32600, + "Vault does not have enough collateralization ratio defined by loan scheme - 143 < 150", + self.nodes[0].paybackwithcollateral, self.vaultId) self.rollback_to(height) @@ -225,7 +232,7 @@ def test_collaterals_greater_than_loans(self, payback_with_collateral): self.nodes[0].generate(1) # Take DUSD loan - self.nodes[0].takeloan({ "vaultId": self.vaultId, "amounts": str(loanDUSDAmount) + "@" + self.symbolDUSD }) + self.nodes[0].takeloan({"vaultId": self.vaultId, "amounts": str(loanDUSDAmount) + "@" + self.symbolDUSD}) self.nodes[0].generate(1) mintedAmountBefore = self.nodes[0].gettoken(self.symbolDUSD)[self.idDUSD]["minted"] @@ -240,8 +247,8 @@ def test_collaterals_greater_than_loans(self, payback_with_collateral): vault = self.nodes[0].getvault(self.vaultId) [collateralAmount, _] = vault["collateralAmounts"][1].split("@") - assert(not any("DUSD" in loan for loan in vault["loanAmounts"])) # Payback all DUSD loans - assert(not any("DUSD" in interest for interest in vault["interestAmounts"])) # Payback all DUSD interests + assert (not any("DUSD" in loan for loan in vault["loanAmounts"])) # Payback all DUSD loans + assert (not any("DUSD" in interest for interest in vault["interestAmounts"])) # Payback all DUSD interests assert_equal(Decimal(collateralAmount), Decimal(collateralAmountBefore) - Decimal(loanAmountBefore)) storedInterest = self.nodes[0].getstoredinterest(self.vaultId, self.idDUSD) @@ -266,7 +273,7 @@ def test_loans_greater_than_collaterals(self, payback_with_collateral): self.nodes[0].generate(1) # Take DUSD loan - self.nodes[0].takeloan({ "vaultId": self.vaultId, "amounts": str(loanDUSDAmount) + "@" + self.symbolDUSD }) + self.nodes[0].takeloan({"vaultId": self.vaultId, "amounts": str(loanDUSDAmount) + "@" + self.symbolDUSD}) self.nodes[0].generate(1) mintedAmountBefore = self.nodes[0].gettoken(self.symbolDUSD)[self.idDUSD]["minted"] @@ -284,12 +291,14 @@ def test_loans_greater_than_collaterals(self, payback_with_collateral): vault = self.nodes[0].getvault(self.vaultId) [interestAmount, _] = vault["interestAmounts"][0].split("@") [loanAmount, _] = vault["loanAmounts"][0].split("@") - assert(not any("DUSD" in collateral for collateral in vault["collateralAmounts"])) # Used all DUSD collateral - assert_equal(Decimal(loanAmount), Decimal(loanAmountBefore) - Decimal(collateralDUSDAmount) + Decimal(interestAmount)) + assert (not any("DUSD" in collateral for collateral in vault["collateralAmounts"])) # Used all DUSD collateral + assert_equal(Decimal(loanAmount), + Decimal(loanAmountBefore) - Decimal(collateralDUSDAmount) + Decimal(interestAmount)) storedInterest = self.nodes[0].getstoredinterest(self.vaultId, self.idDUSD) assert_equal(storedInterest["interestPerBlock"], "0.000000951293859113394216") - assert_equal(Decimal(interestAmount), Decimal(storedInterest["interestPerBlock"]).quantize(Decimal('1E-8'), rounding=ROUND_UP)) + assert_equal(Decimal(interestAmount), + Decimal(storedInterest["interestPerBlock"]).quantize(Decimal('1E-8'), rounding=ROUND_UP)) assert_equal(Decimal(storedInterest["interestToHeight"]), Decimal(0)) mintedAmount = self.nodes[0].gettoken(self.symbolDUSD)[self.idDUSD]["minted"] @@ -310,11 +319,12 @@ def test_loans_equal_to_collaterals(self, payback_with_collateral): self.nodes[0].deposittovault(self.vaultId, self.account0, str(self.collateralAmount) + "@" + self.symbolDFI) self.nodes[0].generate(1) - self.nodes[0].deposittovault(self.vaultId, self.account0, str(collateralDUSDAmount) + "@" + self.symbolDUSD) # Deposit enough to match amount of loans + interest after one block + self.nodes[0].deposittovault(self.vaultId, self.account0, + str(collateralDUSDAmount) + "@" + self.symbolDUSD) # Deposit enough to match amount of loans + interest after one block self.nodes[0].generate(1) # Take DUSD loan - self.nodes[0].takeloan({ "vaultId": self.vaultId, "amounts": str(loanDUSDAmount) + "@" + self.symbolDUSD }) + self.nodes[0].takeloan({"vaultId": self.vaultId, "amounts": str(loanDUSDAmount) + "@" + self.symbolDUSD}) self.nodes[0].generate(1) mintedAmountBefore = self.nodes[0].gettoken(self.symbolDUSD)[self.idDUSD]["minted"] @@ -329,16 +339,17 @@ def test_loans_equal_to_collaterals(self, payback_with_collateral): self.nodes[0].generate(1) vault = self.nodes[0].getvault(self.vaultId) - assert(not any("DUSD" in loan for loan in vault["loanAmounts"])) # Payback all DUSD loans - assert(not any("DUSD" in interest for interest in vault["interestAmounts"])) # Payback all DUSD interests - assert(not any("DUSD" in collateral for collateral in vault["collateralAmounts"])) # Used all DUSD collateral + assert (not any("DUSD" in loan for loan in vault["loanAmounts"])) # Payback all DUSD loans + assert (not any("DUSD" in interest for interest in vault["interestAmounts"])) # Payback all DUSD interests + assert (not any("DUSD" in collateral for collateral in vault["collateralAmounts"])) # Used all DUSD collateral storedInterest = self.nodes[0].getstoredinterest(self.vaultId, self.idDUSD) assert_equal(Decimal(storedInterest["interestPerBlock"]), Decimal(0)) assert_equal(Decimal(storedInterest["interestToHeight"]), Decimal(0)) mintedAmount = self.nodes[0].gettoken(self.symbolDUSD)[self.idDUSD]["minted"] - assert_equal(mintedAmountBefore, Decimal(mintedAmount + Decimal(collateralDUSDAmount)).quantize(Decimal('1E-8'), rounding=ROUND_DOWN)) + assert_equal(mintedAmountBefore, Decimal(mintedAmount + Decimal(collateralDUSDAmount)).quantize(Decimal('1E-8'), + rounding=ROUND_DOWN)) burnInfo = self.nodes[0].getburninfo() assert_equal(burnInfo["paybackburn"][0], vaultBefore["interestAmounts"][0]) @@ -357,7 +368,7 @@ def test_interest_greater_than_collaterals(self, payback_with_collateral): self.nodes[0].deposittovault(self.vaultId, self.account0, str(collateralDUSDAmount) + "@" + self.symbolDUSD) self.nodes[0].generate(1) - self.nodes[0].takeloan({ "vaultId": self.vaultId, "amounts": str(loanDUSDAmount) + "@" + self.symbolDUSD }) + self.nodes[0].takeloan({"vaultId": self.vaultId, "amounts": str(loanDUSDAmount) + "@" + self.symbolDUSD}) self.nodes[0].generate(1) mintedAmountBefore = self.nodes[0].gettoken(self.symbolDUSD)[self.idDUSD]["minted"] @@ -373,13 +384,15 @@ def test_interest_greater_than_collaterals(self, payback_with_collateral): vault = self.nodes[0].getvault(self.vaultId) [interestAmount, _] = vault["interestAmounts"][0].split("@") - assert(not any("DUSD" in collateral for collateral in vault["collateralAmounts"])) # Used all DUSD collateral + assert (not any("DUSD" in collateral for collateral in vault["collateralAmounts"])) # Used all DUSD collateral storedInterest = self.nodes[0].getstoredinterest(self.vaultId, self.idDUSD) assert_equal(storedInterest["interestPerBlock"], "0.000009512937595129375951") assert_equal(Decimal(storedInterest["interestToHeight"]), Decimal("0.000008512937595129375951")) - assert_equal(Decimal(interestAmount), Decimal(Decimal(storedInterest["interestPerBlock"]) * 2 - Decimal(collateralDUSDAmount)).quantize(Decimal('1E-8'), rounding=ROUND_UP)) + assert_equal(Decimal(interestAmount), + Decimal(Decimal(storedInterest["interestPerBlock"]) * 2 - Decimal(collateralDUSDAmount)).quantize( + Decimal('1E-8'), rounding=ROUND_UP)) mintedAmount = self.nodes[0].gettoken(self.symbolDUSD)[self.idDUSD]["minted"] assert_equal(mintedAmountBefore, mintedAmount + Decimal(collateralDUSDAmount)) @@ -399,12 +412,12 @@ def test_interest_equal_to_collaterals(self, payback_with_collateral): self.nodes[0].deposittovault(self.vaultId, self.account0, str(self.collateralAmount) + "@" + self.symbolDFI) self.nodes[0].generate(1) - - self.nodes[0].deposittovault(self.vaultId, self.account0, str(collateralDUSDAmount) + "@" + self.symbolDUSD) # Deposit enough to match amount of interest after one block + self.nodes[0].deposittovault(self.vaultId, self.account0, + str(collateralDUSDAmount) + "@" + self.symbolDUSD) # Deposit enough to match amount of interest after one block self.nodes[0].generate(1) # Take DUSD loan - self.nodes[0].takeloan({ "vaultId": self.vaultId, "amounts": str(loanDUSDAmount) + "@" + self.symbolDUSD }) + self.nodes[0].takeloan({"vaultId": self.vaultId, "amounts": str(loanDUSDAmount) + "@" + self.symbolDUSD}) self.nodes[0].generate(1) mintedAmountBefore = self.nodes[0].gettoken(self.symbolDUSD)[self.idDUSD]["minted"] @@ -419,7 +432,7 @@ def test_interest_equal_to_collaterals(self, payback_with_collateral): self.nodes[0].generate(1) vault = self.nodes[0].getvault(self.vaultId) - assert(not any("DUSD" in collateral for collateral in vault["collateralAmounts"])) # Used all DUSD collateral + assert (not any("DUSD" in collateral for collateral in vault["collateralAmounts"])) # Used all DUSD collateral assert_equal(vault["interestAmounts"], vaultBefore["interestAmounts"]) assert_equal(vault["loanAmounts"], vaultBefore["loanAmounts"]) assert_equal(vault["collateralValue"], float(vaultBefore["collateralValue"]) - expected_IPB) @@ -429,7 +442,8 @@ def test_interest_equal_to_collaterals(self, payback_with_collateral): assert_equal(Decimal(storedInterest["interestToHeight"]), Decimal(0)) mintedAmount = self.nodes[0].gettoken(self.symbolDUSD)[self.idDUSD]["minted"] - assert_equal(mintedAmountBefore, Decimal(mintedAmount + Decimal(collateralDUSDAmount)).quantize(Decimal('1E-8'), rounding=ROUND_DOWN)) + assert_equal(mintedAmountBefore, Decimal(mintedAmount + Decimal(collateralDUSDAmount)).quantize(Decimal('1E-8'), + rounding=ROUND_DOWN)) burnInfo = self.nodes[0].getburninfo() assert_equal(burnInfo["paybackburn"][0], vaultBefore["interestAmounts"][0]) @@ -448,10 +462,10 @@ def test_negative_interest_collaterals_greater_than_loans(self, payback_with_col self.nodes[0].deposittovault(self.vaultId, self.account0, str(collateralDUSDAmount) + "@" + self.symbolDUSD) self.nodes[0].generate(1) - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'-500'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '-500'}}) self.nodes[0].generate(1) - self.nodes[0].takeloan({ "vaultId": self.vaultId, "amounts": str(loanDUSDAmount) + "@" + self.symbolDUSD }) + self.nodes[0].takeloan({"vaultId": self.vaultId, "amounts": str(loanDUSDAmount) + "@" + self.symbolDUSD}) self.nodes[0].generate(1) # accrue negative interest @@ -462,7 +476,7 @@ def test_negative_interest_collaterals_greater_than_loans(self, payback_with_col vault = self.nodes[0].getvault(self.vaultId) [DUSDInterestAmount, _] = vault["interestAmounts"][0].split("@") [DUSDloanAmount, _] = vault["loanAmounts"][0].split("@") - assert(Decimal(DUSDInterestAmount) < 0) + assert (Decimal(DUSDInterestAmount) < 0) storedInterest = self.nodes[0].getstoredinterest(self.vaultId, self.idDUSD) assert_equal(storedInterest["interestPerBlock"], "-0.004746955859969558599695") @@ -476,8 +490,8 @@ def test_negative_interest_collaterals_greater_than_loans(self, payback_with_col [DUSDCollateralAmount, _] = vault["collateralAmounts"][1].split("@") assert_equal(Decimal(DUSDCollateralAmount), Decimal(DUSDInterestAmount) * -1) - assert(not any("DUSD" in loan for loan in vault["loanAmounts"])) # Paid back all DUSD loans - assert(not any("DUSD" in interest for interest in vault["interestAmounts"])) # Paid back all DUSD interests + assert (not any("DUSD" in loan for loan in vault["loanAmounts"])) # Paid back all DUSD loans + assert (not any("DUSD" in interest for interest in vault["interestAmounts"])) # Paid back all DUSD interests storedInterest = self.nodes[0].getstoredinterest(self.vaultId, self.idDUSD) assert_equal(Decimal(storedInterest["interestPerBlock"]), Decimal("0")) @@ -487,7 +501,7 @@ def test_negative_interest_collaterals_greater_than_loans(self, payback_with_col assert_equal(mintedAmountBefore, mintedAmount + Decimal(DUSDloanAmount)) burnInfo = self.nodes[0].getburninfo() - assert_equal(burnInfo["paybackburn"], []) # no burn on negative interest + assert_equal(burnInfo["paybackburn"], []) # no burn on negative interest self.rollback_to(height) @@ -503,10 +517,10 @@ def test_negative_interest_loans_greater_than_collaterals(self, payback_with_col self.nodes[0].deposittovault(self.vaultId, self.account0, str(collateralDUSDAmount) + "@" + self.symbolDUSD) self.nodes[0].generate(1) - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'-500'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '-500'}}) self.nodes[0].generate(1) - self.nodes[0].takeloan({ "vaultId": self.vaultId, "amounts": str(loanDUSDAmount) + "@" + self.symbolDUSD }) + self.nodes[0].takeloan({"vaultId": self.vaultId, "amounts": str(loanDUSDAmount) + "@" + self.symbolDUSD}) self.nodes[0].generate(1) # accrue negative interest @@ -517,7 +531,7 @@ def test_negative_interest_loans_greater_than_collaterals(self, payback_with_col vaultBefore = self.nodes[0].getvault(self.vaultId) [DUSDLoanAmountBefore, _] = vaultBefore["loanAmounts"][0].split("@") [DUSDInterestAmount, _] = vaultBefore["interestAmounts"][0].split("@") - assert(Decimal(DUSDInterestAmount) < 0) + assert (Decimal(DUSDInterestAmount) < 0) storedInterest = self.nodes[0].getstoredinterest(self.vaultId, self.idDUSD) assert_equal(storedInterest["interestPerBlock"], "-0.005221651445966514459665") @@ -529,8 +543,9 @@ def test_negative_interest_loans_greater_than_collaterals(self, payback_with_col vault = self.nodes[0].getvault(self.vaultId) [DUSDLoanAmount, _] = vault["loanAmounts"][0].split("@") [DUSDInterestAmount, _] = vault["interestAmounts"][0].split("@") - assert_equal(Decimal(DUSDLoanAmount), Decimal(DUSDLoanAmountBefore) - Decimal(collateralDUSDAmount) + Decimal(DUSDInterestAmount)) - assert(not any("DUSD" in collateral for collateral in vault["collateralAmounts"])) # Used all DUSD collateral + assert_equal(Decimal(DUSDLoanAmount), + Decimal(DUSDLoanAmountBefore) - Decimal(collateralDUSDAmount) + Decimal(DUSDInterestAmount)) + assert (not any("DUSD" in collateral for collateral in vault["collateralAmounts"])) # Used all DUSD collateral storedInterest = self.nodes[0].getstoredinterest(self.vaultId, self.idDUSD) assert_equal(Decimal(storedInterest["interestPerBlock"]), Decimal("-0.000474546864344558599695")) @@ -540,7 +555,7 @@ def test_negative_interest_loans_greater_than_collaterals(self, payback_with_col assert_equal(mintedAmountBefore, mintedAmount + collateralDUSDAmount) burnInfo = self.nodes[0].getburninfo() - assert_equal(burnInfo["paybackburn"], []) # no burn on negative interest + assert_equal(burnInfo["paybackburn"], []) # no burn on negative interest self.rollback_to(height) @@ -554,13 +569,12 @@ def run_test(self): payback_fns = [ lambda: self.nodes[0].paybackwithcollateral(self.vaultId), lambda: self.nodes[0].paybackloan({ - 'vaultId': self.vaultId, - 'from': self.account0, - 'amounts': "9999999999.99999999@" + self.symbolDUSD}) + 'vaultId': self.vaultId, + 'from': self.account0, + 'amounts': "9999999999.99999999@" + self.symbolDUSD}) ] for payback_fn in payback_fns: - self.test_collaterals_greater_than_loans(payback_fn) self.test_loans_greater_than_collaterals(payback_fn) @@ -575,5 +589,6 @@ def run_test(self): self.test_negative_interest_loans_greater_than_collaterals(payback_fn) + if __name__ == '__main__': LoanPaybackWithCollateralTest().main() diff --git a/test/functional/feature_loan_priceupdate.py b/test/functional/feature_loan_priceupdate.py index 1d2b3ed2b3..d0581c89c7 100755 --- a/test/functional/feature_loan_priceupdate.py +++ b/test/functional/feature_loan_priceupdate.py @@ -14,13 +14,15 @@ import calendar import time -class PriceUpdateTest (DefiTestFramework): + +class PriceUpdateTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True self.FCH = 400 self.extra_args = [ - ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-txindex=1', '-fortcanningheight=1', f'-fortcanninghillheight={self.FCH}'] + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-txindex=1', + '-fortcanningheight=1', f'-fortcanninghillheight={self.FCH}'] ] def run_test(self): @@ -73,7 +75,7 @@ def run_test(self): self.nodes[0].setcollateraltoken(collTokenDFI_USD) except JSONRPCException as e: errorString = e.error['message'] - assert("no live oracles for specified request" in errorString) + assert ("no live oracles for specified request" in errorString) # feed oracle oracle1_prices = [ @@ -105,7 +107,7 @@ def run_test(self): self.nodes[0].generate(1) # Create vault - vaultId1 = self.nodes[0].createvault(account, 'LOAN1') # default loan scheme + vaultId1 = self.nodes[0].createvault(account, 'LOAN1') # default loan scheme self.nodes[0].generate(6) self.nodes[0].deposittovault(vaultId1, account, '1000@DFI') @@ -125,7 +127,7 @@ def run_test(self): self.nodes[0].setloantoken(loanTokenTSLA_USD) except JSONRPCException as e: errorString = e.error['message'] - assert("no live oracles for specified request" in errorString) + assert ("no live oracles for specified request" in errorString) oracle1_prices = [ {"currency": "USD", "tokenAmount": "20@TSLA"}, @@ -152,21 +154,21 @@ def run_test(self): 'amounts': "10@TSLA"}) except JSONRPCException as e: errorString = e.error['message'] - assert("No live fixed prices for TSLA/USD" in errorString) + assert ("No live fixed prices for TSLA/USD" in errorString) - self.nodes[0].generate(5) # let price update + self.nodes[0].generate(5) # let price update loanAmount = 40 self.nodes[0].takeloan({ 'vaultId': vaultId1, - 'amounts': str(loanAmount)+"@TSLA"}) + 'amounts': str(loanAmount) + "@TSLA"}) self.nodes[0].generate(1) takenLoanAmount = loanAmount try: fixedPrice = self.nodes[0].getfixedintervalprice("AAA/USD") except JSONRPCException as e: errorString = e.error['message'] - assert("fixedIntervalPrice with id not found" in errorString) + assert ("fixedIntervalPrice with id not found" in errorString) fixedPrice = self.nodes[0].getfixedintervalprice("TSLA/USD") assert_equal(fixedPrice['activePrice'], Decimal(15.00000000)) assert_equal(fixedPrice['nextPrice'], Decimal(15.00000000)) @@ -194,8 +196,8 @@ def run_test(self): loanAmount = 10 self.nodes[0].takeloan({ 'vaultId': vaultId1, - 'amounts': str(loanAmount)+"@TSLA"}) - self.nodes[0].generate(2) # let price update to invalid state + 'amounts': str(loanAmount) + "@TSLA"}) + self.nodes[0].generate(2) # let price update to invalid state takenLoanAmount += loanAmount vault = self.nodes[0].getvault(vaultId1) @@ -206,23 +208,22 @@ def run_test(self): 'amounts': "10@TSLA"}) except JSONRPCException as e: errorString = e.error['message'] - assert("Cannot take loan while any of the asset's price in the vault is not live" in errorString) + assert ("Cannot take loan while any of the asset's price in the vault is not live" in errorString) try: self.nodes[0].withdrawfromvault(vaultId1, account, "100@DFI") except JSONRPCException as e: errorString = e.error['message'] - assert("Cannot withdraw from vault while any of the asset's price is invalid" in errorString) + assert ("Cannot withdraw from vault while any of the asset's price is invalid" in errorString) try: self.nodes[0].paybackloan({ - 'vaultId': vaultId1, - 'from': account, - 'amounts': ["0.5@TSLA"]}) + 'vaultId': vaultId1, + 'from': account, + 'amounts': ["0.5@TSLA"]}) except JSONRPCException as e: errorString = e.error['message'] - assert("Cannot payback loan while any of the asset's price is invalid" in errorString) - + assert ("Cannot payback loan while any of the asset's price is invalid" in errorString) account2 = self.nodes[0].getnewaddress("", "legacy") self.nodes[0].generate(1) @@ -232,15 +233,14 @@ def run_test(self): self.nodes[0].updatevault(vaultId1, params) except JSONRPCException as e: errorString = e.error['message'] - assert("Cannot update vault while any of the asset's price is invalid" in errorString) + assert ("Cannot update vault while any of the asset's price is invalid" in errorString) fixedPrice = self.nodes[0].getfixedintervalprice("TSLA/USD") assert_equal(fixedPrice['isLive'], False) assert_equal(fixedPrice['activePrice'], Decimal('15.00000000')) assert_equal(fixedPrice['nextPrice'], Decimal('22.50000000')) - - self.nodes[0].generate(5) # let price update to valid state + self.nodes[0].generate(5) # let price update to valid state self.nodes[0].updatevault(vaultId1, params) self.nodes[0].generate(1) @@ -250,11 +250,12 @@ def run_test(self): loanAmount = 30 self.nodes[0].takeloan({ 'vaultId': vaultId1, - 'amounts': str(loanAmount)+ "@TSLA"}) + 'amounts': str(loanAmount) + "@TSLA"}) self.nodes[0].generate(1) takenLoanAmount += loanAmount - assert_raises_rpc_error(-32600, "At least 50% of the minimum required collateral must be in DFI", self.nodes[0].withdrawfromvault, vaultId1, account, "900@DFI") + assert_raises_rpc_error(-32600, "At least 50% of the minimum required collateral must be in DFI", + self.nodes[0].withdrawfromvault, vaultId1, account, "900@DFI") vault = self.nodes[0].getvault(vaultId1) self.nodes[0].withdrawfromvault(vaultId1, account, "100@BTC") @@ -269,7 +270,7 @@ def run_test(self): assert_equal(vault["collateralAmounts"][1], '900.00000000@BTC') interest_TSLA = self.nodes[0].getinterest('LOAN1')[0]["totalInterest"] totalLoanAmount = takenLoanAmount + interest_TSLA - assert_equal(vault["loanAmounts"][0], str(totalLoanAmount)+"@TSLA") + assert_equal(vault["loanAmounts"][0], str(totalLoanAmount) + "@TSLA") height = self.nodes[0].getblockcount() assert_equal(height, 340) @@ -355,7 +356,8 @@ def run_test(self): # Check one block interest is added correctly vaultAfterUpdate = self.nodes[0].getvault(vaultId1, True) - expectedInterestAfterOneBlock = Decimal(Decimal(amountInterestTSLA) + Decimal(interestPerBlockTSLA)).quantize(Decimal('0.00000001'), rounding=ROUND_DOWN) + expectedInterestAfterOneBlock = Decimal(Decimal(amountInterestTSLA) + Decimal(interestPerBlockTSLA)).quantize( + Decimal('0.00000001'), rounding=ROUND_DOWN) realInteresAfterOneBlock = Decimal(vaultAfterUpdate["interestAmounts"][0].split('@')[0]) assert_equal(realInteresAfterOneBlock, expectedInterestAfterOneBlock) @@ -371,9 +373,11 @@ def run_test(self): # Check one block interest is added correctly vaultAfterUpdate = self.nodes[0].getvault(vaultId1, True) - expectedInterestAfterOneBlock = Decimal(Decimal(amountInterestTSLA) + Decimal(interestPerBlockTSLA)).quantize(Decimal('0.00000001'), rounding=ROUND_DOWN) + expectedInterestAfterOneBlock = Decimal(Decimal(amountInterestTSLA) + Decimal(interestPerBlockTSLA)).quantize( + Decimal('0.00000001'), rounding=ROUND_DOWN) realInteresAfterOneBlock = Decimal(vaultAfterUpdate["interestAmounts"][0].split('@')[0]) assert_equal(realInteresAfterOneBlock, expectedInterestAfterOneBlock) + if __name__ == '__main__': PriceUpdateTest().main() diff --git a/test/functional/feature_loan_scheme.py b/test/functional/feature_loan_scheme.py index eb7458367c..f188d89a80 100755 --- a/test/functional/feature_loan_scheme.py +++ b/test/functional/feature_loan_scheme.py @@ -11,14 +11,17 @@ from test_framework.util import assert_equal from decimal import Decimal -class CreateLoanSchemeTest (DefiTestFramework): + +class CreateLoanSchemeTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 self.setup_clean_chain = True self.extra_args = [ - ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-txindex=1', '-fortcanningheight=110'], - ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-txindex=1', '-fortcanningheight=110'] - ] + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-txindex=1', + '-fortcanningheight=110'], + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-txindex=1', + '-fortcanningheight=110'] + ] def run_test(self): self.nodes[0].generate(101) @@ -28,7 +31,7 @@ def run_test(self): self.nodes[0].createloanscheme(1000, 0.5, 'LOANMAX') except JSONRPCException as e: errorString = e.error['message'] - assert("called before FortCanning height" in errorString) + assert ("called before FortCanning height" in errorString) self.nodes[0].generate(9) @@ -48,42 +51,42 @@ def run_test(self): self.nodes[0].createloanscheme(100, 1, 'LOANMAX') except JSONRPCException as e: errorString = e.error['message'] - assert("Loan scheme already exist with id LOANMAX" in errorString) + assert ("Loan scheme already exist with id LOANMAX" in errorString) # Try and create a loan scheme with duplicate ratio and rate try: self.nodes[0].createloanscheme(999, 0.6, 'LOAN0001') except JSONRPCException as e: errorString = e.error['message'] - assert("Loan scheme LOANMAX with same interestrate and mincolratio already exists" in errorString) + assert ("Loan scheme LOANMAX with same interestrate and mincolratio already exists" in errorString) # Try and create a loan scheme with too small ratio try: self.nodes[0].createloanscheme(99, 0.5, 'LOAN0001') except JSONRPCException as e: errorString = e.error['message'] - assert("minimum collateral ratio cannot be less than 100" in errorString) + assert ("minimum collateral ratio cannot be less than 100" in errorString) # Try and create a loan scheme with too small rate try: self.nodes[0].createloanscheme(1000, 0.009, 'LOAN0001') except JSONRPCException as e: errorString = e.error['message'] - assert("interest rate cannot be less than 0.01" in errorString) + assert ("interest rate cannot be less than 0.01" in errorString) # Try and create a loan scheme without ID try: self.nodes[0].createloanscheme(1000, 0.5, '') except JSONRPCException as e: errorString = e.error['message'] - assert("id cannot be empty or more than 8 chars long" in errorString) + assert ("id cannot be empty or more than 8 chars long" in errorString) # Try and create a loan scheme with too long an ID try: self.nodes[0].createloanscheme(1000, 0.5, 'XXXXXXXXX') except JSONRPCException as e: errorString = e.error['message'] - assert("id cannot be empty or more than 8 chars long" in errorString) + assert ("id cannot be empty or more than 8 chars long" in errorString) # Create one more loan scheme self.nodes[0].createloanscheme(150, 5, 'LOAN0001') @@ -94,14 +97,14 @@ def run_test(self): self.nodes[0].getloanscheme('scheme123') except JSONRPCException as e: errorString = e.error['message'] - assert("id cannot be empty or more than 8 chars long" in errorString) + assert ("id cannot be empty or more than 8 chars long" in errorString) # Try getloanscheme with wrong id try: self.nodes[0].getloanscheme('scheme12') except JSONRPCException as e: errorString = e.error['message'] - assert("Cannot find existing loan scheme with id " in errorString) + assert ("Cannot find existing loan scheme with id " in errorString) # Get loan scheme loanscheme = self.nodes[0].getloanscheme('LOAN0001') @@ -121,14 +124,14 @@ def run_test(self): self.nodes[0].updateloanscheme(1000, 0.5, 'XXXXXXXX') except JSONRPCException as e: errorString = e.error['message'] - assert("Cannot find existing loan scheme with id XXXXXXXX" in errorString) + assert ("Cannot find existing loan scheme with id XXXXXXXX" in errorString) # Try and update a loan scheme with same rate and ratio as another scheme try: self.nodes[0].updateloanscheme(150, 5, 'LOANMAX') except JSONRPCException as e: errorString = e.error['message'] - assert("Loan scheme LOAN0001 with same interestrate and mincolratio already exists" in errorString) + assert ("Loan scheme LOAN0001 with same interestrate and mincolratio already exists" in errorString) # Update loan scheme self.nodes[0].updateloanscheme(1001, 0.7, 'LOANMAX') @@ -146,7 +149,7 @@ def run_test(self): self.nodes[0].updateloanscheme(1000, 0.5, 'LOANMAX', 112) except JSONRPCException as e: errorString = e.error['message'] - assert("Update height below current block height, set future height" in errorString) + assert ("Update height below current block height, set future height" in errorString) # Update loan scheme after a delay self.nodes[0].updateloanscheme(1000, 0.5, 'LOANMAX', 115) @@ -164,7 +167,7 @@ def run_test(self): self.nodes[0].updateloanscheme(1000, 0.5, 'LOAN0001') except JSONRPCException as e: errorString = e.error['message'] - assert("Loan scheme LOANMAX with same interestrate and mincolratio pending on block 115" in errorString) + assert ("Loan scheme LOANMAX with same interestrate and mincolratio pending on block 115" in errorString) # Move to update block and check loan scheme has updated self.nodes[0].generate(1) @@ -229,28 +232,28 @@ def run_test(self): self.nodes[0].setdefaultloanscheme('') except JSONRPCException as e: errorString = e.error['message'] - assert("id cannot be empty or more than 8 chars long" in errorString) + assert ("id cannot be empty or more than 8 chars long" in errorString) # Test changing the default loan scheme with too long an ID try: self.nodes[0].setdefaultloanscheme('XXXXXXXXX') except JSONRPCException as e: errorString = e.error['message'] - assert("id cannot be empty or more than 8 chars long" in errorString) + assert ("id cannot be empty or more than 8 chars long" in errorString) # Test changing the default loan scheme to one that does not exist try: self.nodes[0].setdefaultloanscheme('XXXXXXXX') except JSONRPCException as e: errorString = e.error['message'] - assert("Cannot find existing loan scheme with id XXXXXXXX" in errorString) + assert ("Cannot find existing loan scheme with id XXXXXXXX" in errorString) # Test changing the default loan scheme to the existing loan scheme try: self.nodes[0].setdefaultloanscheme('LOANMAX') except JSONRPCException as e: errorString = e.error['message'] - assert("Loan scheme with id LOANMAX is already set as default" in errorString) + assert ("Loan scheme with id LOANMAX is already set as default" in errorString) # Test changing the loan scheme self.nodes[0].setdefaultloanscheme('LOAN0001') @@ -274,28 +277,28 @@ def run_test(self): self.nodes[0].destroyloanscheme('') except JSONRPCException as e: errorString = e.error['message'] - assert("id cannot be empty or more than 8 chars long" in errorString) + assert ("id cannot be empty or more than 8 chars long" in errorString) # Test destroying a loan scheme with too long an ID try: self.nodes[0].destroyloanscheme('XXXXXXXXX') except JSONRPCException as e: errorString = e.error['message'] - assert("id cannot be empty or more than 8 chars long" in errorString) + assert ("id cannot be empty or more than 8 chars long" in errorString) # Test destroying a loan scheme that does not exist try: self.nodes[0].destroyloanscheme('XXXXXXXX') except JSONRPCException as e: errorString = e.error['message'] - assert("Cannot find existing loan scheme with id XXXXXXXX" in errorString) + assert ("Cannot find existing loan scheme with id XXXXXXXX" in errorString) # Test destroying the default loan scheme try: self.nodes[0].destroyloanscheme('LOAN0001') except JSONRPCException as e: errorString = e.error['message'] - assert("Cannot destroy default loan scheme, set new default first" in errorString) + assert ("Cannot destroy default loan scheme, set new default first" in errorString) # Destroy a loan scheme self.nodes[0].destroyloanscheme('LOANMAX') @@ -323,7 +326,7 @@ def run_test(self): self.nodes[0].setdefaultloanscheme('LOAN0002') except JSONRPCException as e: errorString = e.error['message'] - assert("Cannot set LOAN0002 as default, set to destroyed" in errorString) + assert ("Cannot set LOAN0002 as default, set to destroyed" in errorString) # Set update on same block and later on self.nodes[0].updateloanscheme(160, 4.5, 'LOAN0002', destruction_height) @@ -346,7 +349,7 @@ def run_test(self): self.nodes[0].updateloanscheme(170, 4, 'LOAN0003') except JSONRPCException as e: errorString = e.error['message'] - assert("Loan scheme LOAN0002 with same interestrate and mincolratio pending on block 131" in errorString) + assert ("Loan scheme LOAN0002 with same interestrate and mincolratio pending on block 131" in errorString) # Go forward again to destroy loan self.nodes[0].generate(2) @@ -357,5 +360,6 @@ def run_test(self): # Can now update loan scheme as pending updates deleted self.nodes[0].updateloanscheme(170, 4, 'LOAN0003') + if __name__ == '__main__': CreateLoanSchemeTest().main() diff --git a/test/functional/feature_loan_setcollateraltoken.py b/test/functional/feature_loan_setcollateraltoken.py index 1a63402686..fb5933de0e 100755 --- a/test/functional/feature_loan_setcollateraltoken.py +++ b/test/functional/feature_loan_setcollateraltoken.py @@ -14,15 +14,17 @@ import calendar import time -class LoanSetCollateralTokenTest (DefiTestFramework): + +class LoanSetCollateralTokenTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True self.extra_args = [ - ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-eunosheight=50', '-fortcanningheight=50', '-fortcanninghillheight=50', '-fortcanningcrunchheight=150', '-txindex=1']] + ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-eunosheight=50', '-fortcanningheight=50', + '-fortcanninghillheight=50', '-fortcanningcrunchheight=150', '-txindex=1']] def run_test(self): - assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI + assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI print("Generating initial chain...") self.nodes[0].generate(101) @@ -53,21 +55,21 @@ def run_test(self): try: self.nodes[0].setcollateraltoken({ - 'token': "DOGE", - 'factor': 1, - 'fixedIntervalPriceId': "DFI/USD"}) + 'token': "DOGE", + 'factor': 1, + 'fixedIntervalPriceId': "DFI/USD"}) except JSONRPCException as e: errorString = e.error['message'] - assert("Token DOGE does not exist" in errorString) + assert ("Token DOGE does not exist" in errorString) try: self.nodes[0].setcollateraltoken({ - 'token': idDFI, - 'factor': 1, - 'fixedIntervalPriceId': "DFI/USD"}) + 'token': idDFI, + 'factor': 1, + 'fixedIntervalPriceId': "DFI/USD"}) except JSONRPCException as e: errorString = e.error['message'] - assert("Price feed DFI/USD does not belong to any oracle" in errorString) + assert ("Price feed DFI/USD does not belong to any oracle" in errorString) oracle_address1 = self.nodes[0].getnewaddress("", "legacy") price_feeds1 = [ @@ -80,12 +82,12 @@ def run_test(self): try: self.nodes[0].setcollateraltoken({ - 'token': idDFI, - 'factor': 1, - 'fixedIntervalPriceId': "DFI/USD"}) + 'token': idDFI, + 'factor': 1, + 'fixedIntervalPriceId': "DFI/USD"}) except JSONRPCException as e: errorString = e.error['message'] - assert("no live oracles for specified request" in errorString) + assert ("no live oracles for specified request" in errorString) oracle1_prices = [ {"currency": "USD", "tokenAmount": f'1@{symbolDFI}'}, @@ -96,39 +98,40 @@ def run_test(self): self.nodes[0].setoracledata(oracle_id1, timestamp, oracle1_prices) self.nodes[0].generate(1) - assert_raises_rpc_error(-32600, "setCollateralToken factor must be lower or equal than 1", self.nodes[0].setcollateraltoken, { - 'token': idDFI, - 'factor': 2, - 'fixedIntervalPriceId': "DFI/USD"}) + assert_raises_rpc_error(-32600, "setCollateralToken factor must be lower or equal than 1", + self.nodes[0].setcollateraltoken, { + 'token': idDFI, + 'factor': 2, + 'fixedIntervalPriceId': "DFI/USD"}) try: self.nodes[0].setcollateraltoken({ - 'token': idDFI, - 'factor': -1, - 'fixedIntervalPriceId': "DFI/USD"}) + 'token': idDFI, + 'factor': -1, + 'fixedIntervalPriceId': "DFI/USD"}) except JSONRPCException as e: errorString = e.error['message'] - assert("Amount out of range" in errorString) + assert ("Amount out of range" in errorString) try: self.nodes[0].setcollateraltoken({ - 'token': idDFI, - 'factor': 1, - 'fixedIntervalPriceId': "Blabla"}) + 'token': idDFI, + 'factor': 1, + 'fixedIntervalPriceId': "Blabla"}) except JSONRPCException as e: errorString = e.error['message'] - assert("price feed not in valid format - token/currency" in errorString) + assert ("price feed not in valid format - token/currency" in errorString) collTokenTx1 = self.nodes[0].setcollateraltoken({ - 'token': idDFI, - 'factor': 0.5, - 'fixedIntervalPriceId': "DFI/USD"}) + 'token': idDFI, + 'factor': 0.5, + 'fixedIntervalPriceId': "DFI/USD"}) collTokenTx3 = self.nodes[0].setcollateraltoken({ - 'token': idDFI, - 'factor': 1, - 'fixedIntervalPriceId': "DFI/USD", - 'activateAfterBlock': 135}) + 'token': idDFI, + 'factor': 1, + 'fixedIntervalPriceId': "DFI/USD", + 'activateAfterBlock': 135}) self.nodes[0].generate(1) @@ -143,9 +146,9 @@ def run_test(self): assert_equal(collToken1["fixedIntervalPriceId"], "DFI/USD") collTokenTx2 = self.nodes[0].setcollateraltoken({ - 'token': idBTC, - 'factor': 0.9, - 'fixedIntervalPriceId': "BTC/USD"}) + 'token': idBTC, + 'factor': 0.9, + 'fixedIntervalPriceId': "BTC/USD"}) self.nodes[0].generate(1) @@ -195,9 +198,9 @@ def run_test(self): assert_equal(collTokens["activateAfterBlock"], btc_activation_height) self.nodes[0].setcollateraltoken({ - 'token': idBTC, - 'factor': 0, - 'fixedIntervalPriceId': "BTC/USD"}) + 'token': idBTC, + 'factor': 0, + 'fixedIntervalPriceId': "BTC/USD"}) self.nodes[0].generate(1) @@ -208,10 +211,11 @@ def run_test(self): self.nodes[0].generate(150 - self.nodes[0].getblockcount()) # Check errors on FCC - assert_raises_rpc_error(-32600, "setCollateralToken factor must be lower or equal than 1.00000000", self.nodes[0].setcollateraltoken, { - 'token': idDFI, - 'factor': 1.01, - 'fixedIntervalPriceId': "DFI/USD"}) + assert_raises_rpc_error(-32600, "setCollateralToken factor must be lower or equal than 1.00000000", + self.nodes[0].setcollateraltoken, { + 'token': idDFI, + 'factor': 1.01, + 'fixedIntervalPriceId': "DFI/USD"}) self.nodes[0].generate(1) @@ -244,5 +248,6 @@ def run_test(self): assert_equal(result['factor'], Decimal('0.12345678')) assert_equal(result['fixedIntervalPriceId'], 'GOOGL/USD') + if __name__ == '__main__': LoanSetCollateralTokenTest().main() diff --git a/test/functional/feature_loan_setloantoken.py b/test/functional/feature_loan_setloantoken.py index a13d455b0f..5012d1f7eb 100755 --- a/test/functional/feature_loan_setloantoken.py +++ b/test/functional/feature_loan_setloantoken.py @@ -14,15 +14,17 @@ import calendar import time -class LoanSetLoanTokenTest (DefiTestFramework): + +class LoanSetLoanTokenTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True self.extra_args = [ - ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-eunosheight=50', '-fortcanningheight=50', '-fortcanninghillheight=50', '-fortcanningcrunchheight=110', '-txindex=1']] + ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-eunosheight=50', '-fortcanningheight=50', + '-fortcanninghillheight=50', '-fortcanningcrunchheight=110', '-txindex=1']] def run_test(self): - assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI + assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI print("Generating initial chain...") self.nodes[0].generate(101) @@ -38,14 +40,14 @@ def run_test(self): try: self.nodes[0].setloantoken({ - 'symbol': "TSLA", - 'name': "Tesla stock token", - 'fixedIntervalPriceId': "TSLA/USD", - 'mintable': False, - 'interest': 1}) + 'symbol': "TSLA", + 'name': "Tesla stock token", + 'fixedIntervalPriceId': "TSLA/USD", + 'mintable': False, + 'interest': 1}) except JSONRPCException as e: errorString = e.error['message'] - assert("no live oracles for specified request" in errorString) + assert ("no live oracles for specified request" in errorString) oracle_address1 = self.nodes[0].getnewaddress("", "legacy") price_feeds1 = [ @@ -66,14 +68,14 @@ def run_test(self): try: self.nodes[0].setloantoken({ - 'symbol': "TSLAA", - 'name': "Tesla stock token", - 'fixedIntervalPriceId': "aa", - 'mintable': False, - 'interest': 1}) + 'symbol': "TSLAA", + 'name': "Tesla stock token", + 'fixedIntervalPriceId': "aa", + 'mintable': False, + 'interest': 1}) except JSONRPCException as e: errorString = e.error['message'] - assert("price feed not in valid format - token/currency" in errorString) + assert ("price feed not in valid format - token/currency" in errorString) oracle1_prices = [ {"currency": "USD", "tokenAmount": "1@TSLA"}, @@ -86,11 +88,11 @@ def run_test(self): self.nodes[0].generate(1) self.nodes[0].setloantoken({ - 'symbol': "TSLAAAA", - 'name': "Tesla", - 'fixedIntervalPriceId': "TSLA/USD", - 'mintable': False, - 'interest': 1}) + 'symbol': "TSLAAAA", + 'name': "Tesla", + 'fixedIntervalPriceId': "TSLA/USD", + 'mintable': False, + 'interest': 1}) self.nodes[0].generate(1) @@ -106,11 +108,11 @@ def run_test(self): assert_equal(loanToken["fixedIntervalPriceId"], "TSLA/USD") assert_equal(loanToken["interest"], Decimal('1')) - self.nodes[0].updateloantoken("TSLAAAA",{ - 'symbol': "TSLA", - 'name': "Tesla stock token", - 'mintable': True, - 'interest': 3}) + self.nodes[0].updateloantoken("TSLAAAA", { + 'symbol': "TSLA", + 'name': "Tesla stock token", + 'mintable': True, + 'interest': 3}) self.nodes[0].generate(1) @@ -130,7 +132,7 @@ def run_test(self): self.nodes[0].setoracledata(oracle_id1, timestamp - 3600, oracle1_prices) except JSONRPCException as e: errorString = e.error['message'] - assert("Timestamp" in errorString and "is out of price update window" in errorString) + assert ("Timestamp" in errorString and "is out of price update window" in errorString) # Create loan token for DUSD/USD without Oracle self.nodes[0].setloantoken({ @@ -142,7 +144,7 @@ def run_test(self): self.nodes[0].generate(1) # Update loan token for DUSD/USD without Oracle - self.nodes[0].updateloantoken("DUSD",{ + self.nodes[0].updateloantoken("DUSD", { 'symbol': "DUSD", 'name': "DUSD", 'mintable': True, @@ -154,13 +156,14 @@ def run_test(self): # Move to FCC +1 self.nodes[0].generate(1) - assert_raises_rpc_error(-32600, 'token symbol should be non-empty and starts with a letter', self.nodes[0].setloantoken, { - 'symbol': "", - 'name': "Google", - 'fixedIntervalPriceId': "MSFT/USD", - 'mintable': True, - 'interest': 0.01 - }) + assert_raises_rpc_error(-32600, 'token symbol should be non-empty and starts with a letter', + self.nodes[0].setloantoken, { + 'symbol': "", + 'name': "Google", + 'fixedIntervalPriceId': "MSFT/USD", + 'mintable': True, + 'interest': 0.01 + }) # Create loan tokens self.nodes[0].setloantoken({ @@ -241,5 +244,6 @@ def run_test(self): assert_equal(result['v0/token/4/loan_minting_interest'], '0.05') assert_equal(result['v0/token/4/fixed_interval_price_id'], 'MSFT/USD') + if __name__ == '__main__': LoanSetLoanTokenTest().main() diff --git a/test/functional/feature_loan_vault.py b/test/functional/feature_loan_vault.py index ab5fe3cb87..6760c02aa6 100755 --- a/test/functional/feature_loan_vault.py +++ b/test/functional/feature_loan_vault.py @@ -13,14 +13,19 @@ import calendar import time -class VaultTest (DefiTestFramework): + +class VaultTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 self.setup_clean_chain = True self.extra_args = [ - ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-bayfrontgardensheight=1', '-eunosheight=1', '-txindex=1', '-fortcanningheight=1', '-fortcanninghillheight=300', '-fortcanningcrunchheight=1700', '-jellyfish_regtest=1', '-simulatemainnet'], - ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-bayfrontgardensheight=1', '-eunosheight=1', '-txindex=1', '-fortcanningheight=1', '-fortcanninghillheight=300', '-fortcanningcrunchheight=1700', '-jellyfish_regtest=1', '-simulatemainnet'] - ] + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-bayfrontgardensheight=1', '-eunosheight=1', + '-txindex=1', '-fortcanningheight=1', '-fortcanninghillheight=300', '-fortcanningcrunchheight=1700', + '-jellyfish_regtest=1', '-simulatemainnet'], + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-bayfrontgardensheight=1', '-eunosheight=1', + '-txindex=1', '-fortcanningheight=1', '-fortcanninghillheight=300', '-fortcanningcrunchheight=1700', + '-jellyfish_regtest=1', '-simulatemainnet'] + ] self.vaults = [] self.owner_addresses = [] self.oracles = [] @@ -91,7 +96,7 @@ def setup_loanschemes(self): def create_vaults(self): owner_addr_0 = self.nodes[0].getnewaddress('', 'legacy') self.owner_addresses.append(owner_addr_0) - vault_id_0 = self.nodes[0].createvault(owner_addr_0) # default loan scheme + vault_id_0 = self.nodes[0].createvault(owner_addr_0) # default loan scheme self.vaults.append(vault_id_0) owner_addr_1 = self.nodes[0].getnewaddress('', 'legacy') @@ -105,7 +110,7 @@ def create_vaults(self): self.nodes[0].generate(1) def setup_accounts_and_tokens(self): - assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI + assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI self.nodes[0].generate(25) self.sync_blocks() self.nodes[1].generate(102) @@ -176,43 +181,44 @@ def setup_accounts_and_tokens(self): self.nodes[0].utxostoaccount({self.accountDFI: "100@" + self.symbolDFI}) self.nodes[0].generate(1) self.nodes[0].setloantoken({ - 'symbol': "TSLA", - 'name': "Tesla Token", - 'fixedIntervalPriceId': "TSLA/USD", - 'mintable': True, - 'interest': 2}) + 'symbol': "TSLA", + 'name': "Tesla Token", + 'fixedIntervalPriceId': "TSLA/USD", + 'mintable': True, + 'interest': 2}) self.nodes[0].generate(1) self.nodes[0].setcollateraltoken({ - 'token': self.idDFI, - 'factor': 1, - 'fixedIntervalPriceId': "DFI/USD"}) + 'token': self.idDFI, + 'factor': 1, + 'fixedIntervalPriceId': "DFI/USD"}) self.nodes[0].setcollateraltoken({ - 'token': self.idBTC, - 'factor': 0.8, - 'fixedIntervalPriceId': "BTC/USD"}) + 'token': self.idBTC, + 'factor': 0.8, + 'fixedIntervalPriceId': "BTC/USD"}) self.nodes[0].generate(120) self.sync_blocks() self.nodes[0].setloantoken({ - 'symbol': "DUSD", - 'name': "DUSD stable token", - 'fixedIntervalPriceId': "DUSD/USD", - 'mintable': True, - 'interest': 1}) + 'symbol': "DUSD", + 'name': "DUSD stable token", + 'fixedIntervalPriceId': "DUSD/USD", + 'mintable': True, + 'interest': 1}) self.nodes[0].generate(120) - - def setup_oracles(self): oracle_address1 = self.nodes[0].getnewaddress("", "legacy") - price_feeds1 = [{"currency": "USD", "token": "DFI"}, {"currency": "USD", "token": "BTC"}, {"currency": "USD", "token": "TSLA"}, {"currency": "USD", "token": "GOOGL"}, {"currency": "USD", "token": "ETH"}] + price_feeds1 = [{"currency": "USD", "token": "DFI"}, {"currency": "USD", "token": "BTC"}, + {"currency": "USD", "token": "TSLA"}, {"currency": "USD", "token": "GOOGL"}, + {"currency": "USD", "token": "ETH"}] oracle_id1 = self.nodes[0].appointoracle(oracle_address1, price_feeds1, 10) self.oracles.append(oracle_id1) self.nodes[0].generate(1) - oracle1_prices = [{"currency": "USD", "tokenAmount": "1@DFI"}, {"currency": "USD", "tokenAmount": "1@BTC"}, {"currency": "USD", "tokenAmount": "1@TSLA"}] + oracle1_prices = [{"currency": "USD", "tokenAmount": "1@DFI"}, {"currency": "USD", "tokenAmount": "1@BTC"}, + {"currency": "USD", "tokenAmount": "1@TSLA"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(oracle_id1, timestamp, oracle1_prices) @@ -258,7 +264,6 @@ def create_poolpairs(self): }, self.accountDFI, []) self.nodes[0].generate(1) - def setup(self): self.nodes[0].generate(120) self.setup_loanschemes() @@ -267,13 +272,12 @@ def setup(self): self.setup_accounts_and_tokens() self.create_poolpairs() - def createvault_with_invalid_parameters(self): try: self.nodes[0].createvault('ffffffffff') except JSONRPCException as e: errorString = e.error['message'] - assert('recipient script (ffffffffff) does not solvable/non-standard' in errorString) + assert ('recipient script (ffffffffff) does not solvable/non-standard' in errorString) # Create vault with invalid loanschemeid and default owner address owner = self.nodes[0].getnewaddress('', 'legacy') @@ -281,7 +285,7 @@ def createvault_with_invalid_parameters(self): self.nodes[0].createvault(owner, 'FAKELOAN') except JSONRPCException as e: errorString = e.error['message'] - assert('Cannot find existing loan scheme with id FAKELOAN' in errorString) + assert ('Cannot find existing loan scheme with id FAKELOAN' in errorString) def listvaults_and_filtering(self): # check listvaults @@ -289,13 +293,13 @@ def listvaults_and_filtering(self): assert_equal(len(list_vault), 4) # check listVaults filter by owner_address - list_vault = self.nodes[0].listvaults({ "ownerAddress": self.owner_addresses[1] }) + list_vault = self.nodes[0].listvaults({"ownerAddress": self.owner_addresses[1]}) assert_equal(len(list_vault), 3) for vault in list_vault: assert_equal(vault["ownerAddress"], self.owner_addresses[1]) # check listVaults filter by loanSchemeId - list_vault = self.nodes[0].listvaults({ "loanSchemeId": "LOAN0003" }) + list_vault = self.nodes[0].listvaults({"loanSchemeId": "LOAN0003"}) assert_equal(len(list_vault), 2) for vault in list_vault: assert_equal(vault["loanSchemeId"], "LOAN0003") @@ -312,7 +316,7 @@ def getvault_wrong_vault_address(self): self.nodes[0].getvault('5474b2e9bfa96446e5ef3c9594634e1aa22d3a0722cb79084d61253acbdf87bf') except JSONRPCException as e: errorString = e.error['message'] - assert('Vault <5474b2e9bfa96446e5ef3c9594634e1aa22d3a0722cb79084d61253acbdf87bf> not found' in errorString) + assert ('Vault <5474b2e9bfa96446e5ef3c9594634e1aa22d3a0722cb79084d61253acbdf87bf> not found' in errorString) def test_getvault(self): vault = self.nodes[0].getvault(self.vaults[0]) @@ -331,7 +335,7 @@ def updatevault_with_invalid_parameters(self): self.nodes[0].updatevault(self.vaults[0], params) except JSONRPCException as e: errorString = e.error['message'] - assert("At least ownerAddress OR loanSchemeId must be set" in errorString) + assert ("At least ownerAddress OR loanSchemeId must be set" in errorString) # bad loan scheme id try: @@ -339,7 +343,7 @@ def updatevault_with_invalid_parameters(self): self.nodes[0].updatevault(self.vaults[0], params) except JSONRPCException as e: errorString = e.error['message'] - assert("Cannot find existing loan scheme with id FAKELOAN" in errorString) + assert ("Cannot find existing loan scheme with id FAKELOAN" in errorString) # bad owner address try: @@ -347,7 +351,7 @@ def updatevault_with_invalid_parameters(self): self.nodes[0].updatevault(self.vaults[0], params) except JSONRPCException as e: errorString = e.error['message'] - assert("Error: Invalid owner address" in errorString) + assert ("Error: Invalid owner address" in errorString) def actions_on_vault_with_scheme_to_be_destroyed(self): # Create or update vault with loan scheme planned to be destroyed @@ -356,10 +360,12 @@ def actions_on_vault_with_scheme_to_be_destroyed(self): self.nodes[0].generate(1) # create - assert_raises_rpc_error(-32600, 'Cannot set LOAN0002 as loan scheme, set to be destroyed', self.nodes[0].createvault, self.owner_addresses[0], 'LOAN0002') + assert_raises_rpc_error(-32600, 'Cannot set LOAN0002 as loan scheme, set to be destroyed', + self.nodes[0].createvault, self.owner_addresses[0], 'LOAN0002') # update - assert_raises_rpc_error(-32600, 'Cannot set LOAN0002 as loan scheme, set to be destroyed', self.nodes[0].updatevault, self.vaults[1], {'loanSchemeId':'LOAN0002'}) + assert_raises_rpc_error(-32600, 'Cannot set LOAN0002 as loan scheme, set to be destroyed', + self.nodes[0].updatevault, self.vaults[1], {'loanSchemeId': 'LOAN0002'}) def update_vault_scheme(self): new_address = self.nodes[0].getnewaddress('', 'legacy') @@ -387,7 +393,6 @@ def automatic_update_after_loanscheme_delete(self): vault = self.nodes[0].getvault(self.vaults[1]) assert_equal(vault['loanSchemeId'], 'LOAN0001') - def automatic_update_after_loanscheme_delete_with_delay(self): # back to non-default loan scheme and delete scheme with delay params = {'loanSchemeId': 'LOAN0004'} @@ -407,32 +412,31 @@ def automatic_update_after_loanscheme_delete_with_delay(self): vault = self.nodes[0].getvault(self.vaults[1]) assert_equal(vault['loanSchemeId'], 'LOAN0001') - def deposittovault_with_invalid_params(self): # Insufficient funds try: self.nodes[0].deposittovault(self.vaults[0], self.accountDFI, '101@DFI') except JSONRPCException as e: errorString = e.error['message'] - assert("Insufficient funds" in errorString) + assert ("Insufficient funds" in errorString) # Check from auth try: self.nodes[0].deposittovault(self.vaults[0], self.accountBTC, '1@DFI') except JSONRPCException as e: errorString = e.error['message'] - assert("Incorrect authorization for {}".format(self.accountBTC) in errorString) + assert ("Incorrect authorization for {}".format(self.accountBTC) in errorString) # Check negative amount try: self.nodes[0].deposittovault(self.vaults[0], self.accountDFI, '-1@DFI') except JSONRPCException as e: errorString = e.error['message'] - assert("Amount out of range" in errorString) + assert ("Amount out of range" in errorString) # Check too small amount try: self.nodes[0].deposittovault(self.vaults[0], self.accountDFI, '0.000000001@DFI') except JSONRPCException as e: errorString = e.error['message'] - assert("Invalid amount" in errorString) + assert ("Invalid amount" in errorString) def test_deposittovault(self): # Check deposit 1 satoshi @@ -450,9 +454,10 @@ def test_deposittovault(self): assert_equal(acBTC, ['9.30000000@BTC']) def takeloan_breaking_50pctDFI_rule(self): - assert_raises_rpc_error(-32600, "At least 50% of the minimum required collateral must be in DFI", self.nodes[0].takeloan, { - 'vaultId': self.vaults[0], - 'amounts': "0.1@TSLA"}) + assert_raises_rpc_error(-32600, "At least 50% of the minimum required collateral must be in DFI", + self.nodes[0].takeloan, { + 'vaultId': self.vaults[0], + 'amounts': "0.1@TSLA"}) def takeloan_with_50pctDFI(self): self.nodes[0].deposittovault(self.vaults[0], self.accountDFI, '0.7@DFI') @@ -473,13 +478,14 @@ def takeloan_with_50pctDFI(self): self.sync_blocks() vault = self.nodes[1].getvault(self.vaults[0]) - assert_equal(vault['collateralAmounts'],['1.00000000@DFI', '1.00000000@BTC']) + assert_equal(vault['collateralAmounts'], ['1.00000000@DFI', '1.00000000@BTC']) acBTC = self.nodes[1].getaccount(self.accountBTC) assert_equal(acBTC, ['9.00000000@BTC']) acDFI = self.nodes[0].getaccount(self.accountDFI) assert_equal(acDFI, ['99.00000000@DFI', '173.20507075@DUSD-DFI', '99.99999000@DUSD-TSLA']) - oracle1_prices = [{"currency": "USD", "tokenAmount": "1@DFI"}, {"currency": "USD", "tokenAmount": "1@TSLA"}, {"currency": "USD", "tokenAmount": "1@BTC"}] + oracle1_prices = [{"currency": "USD", "tokenAmount": "1@DFI"}, {"currency": "USD", "tokenAmount": "1@TSLA"}, + {"currency": "USD", "tokenAmount": "1@BTC"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(self.oracles[0], timestamp, oracle1_prices) @@ -487,8 +493,8 @@ def takeloan_with_50pctDFI(self): self.sync_blocks() self.nodes[0].takeloan({ - 'vaultId': self.vaults[0], - 'amounts': "0.5@TSLA"}) + 'vaultId': self.vaults[0], + 'amounts': "0.5@TSLA"}) self.nodes[0].generate(1) self.sync_blocks() @@ -499,19 +505,19 @@ def takeloan_with_50pctDFI(self): vault = self.nodes[0].getvault(self.vaults[0]) assert_equal(vault['loanAmounts'], ['0.50000003@TSLA']) assert_equal(vault['collateralValue'], Decimal('1.80000000')) - assert_equal(vault['loanValue'],Decimal('0.50000003')) - assert_equal(vault['interestValue'],Decimal('0.00000003')) - assert_equal(vault['interestAmounts'],['0.00000003@TSLA']) + assert_equal(vault['loanValue'], Decimal('0.50000003')) + assert_equal(vault['interestValue'], Decimal('0.00000003')) + assert_equal(vault['interestAmounts'], ['0.00000003@TSLA']) def withdraw_breaking_50pctDFI_rule(self): try: self.nodes[0].withdrawfromvault(self.vaults[0], self.accountDFI, "0.8@DFI") except JSONRPCException as e: error_str = e.error['message'] - assert("At least 50% of the minimum required collateral must be in DFI" in error_str) + assert ("At least 50% of the minimum required collateral must be in DFI" in error_str) def move_interest_from_old_scheme(self): - params = {'loanSchemeId':'LOAN000A'} + params = {'loanSchemeId': 'LOAN000A'} self.nodes[0].updatevault(self.vaults[0], params) self.nodes[0].generate(1) self.sync_blocks() @@ -533,7 +539,8 @@ def vault_enter_liquidation_updating_oracle(self): assert_equal(vault['liquidationPenalty'], Decimal('5.00000000')) assert_equal(vault['batchCount'], 1) - assert_raises_rpc_error(-26, 'Vault is under liquidation', self.nodes[0].closevault, self.vaults[0], self.owner_addresses[0]) + assert_raises_rpc_error(-26, 'Vault is under liquidation', self.nodes[0].closevault, self.vaults[0], + self.owner_addresses[0]) def updatevault_to_scheme_with_lower_collateralization_ratio(self): self.nodes[0].deposittovault(self.vaults[1], self.accountDFI, '2.5@DFI') @@ -545,8 +552,8 @@ def updatevault_to_scheme_with_lower_collateralization_ratio(self): assert_equal(self.nodes[0].getaccount(self.owner_addresses[1]), []) self.nodes[0].takeloan({ - 'vaultId': self.vaults[1], - 'amounts': "0.355@TSLA"}) + 'vaultId': self.vaults[1], + 'amounts': "0.355@TSLA"}) self.nodes[0].generate(1) vault = self.nodes[0].getvault(self.vaults[1]) self.nodes[0].createloanscheme(200, 2.5, 'LOAN0005') @@ -559,7 +566,7 @@ def updatevault_to_scheme_with_lower_collateralization_ratio(self): self.nodes[0].updatevault(self.vaults[1], params) except JSONRPCException as e: errorString = e.error['message'] - assert("Vault does not have enough collateralization ratio defined by loan scheme - 176 < 200" in errorString) + assert ("Vault does not have enough collateralization ratio defined by loan scheme - 176 < 200" in errorString) self.nodes[0].generate(1) def closevault_with_active_loans(self): @@ -567,7 +574,7 @@ def closevault_with_active_loans(self): self.nodes[0].closevault(self.vaults[1], self.owner_addresses[1]) except JSONRPCException as e: error_str = e.error['message'] - assert("Vault <"+self.vaults[1]+"> has loans" in error_str) + assert ("Vault <" + self.vaults[1] + "> has loans" in error_str) self.nodes[0].generate(1) self.sync_blocks() @@ -583,7 +590,7 @@ def test_closevault(self): self.nodes[1].getvault(self.vaults[3]) except JSONRPCException as e: error_str = e.error['message'] - assert("Vault <"+self.vaults[3]+"> not found" in error_str) + assert ("Vault <" + self.vaults[3] + "> not found" in error_str) def estimatevault_with_invalid_params(self): # Invalid loan token @@ -591,25 +598,25 @@ def estimatevault_with_invalid_params(self): self.nodes[0].estimatevault('3.00000000@DFI', '3.00000000@TSLAA') except JSONRPCException as e: error_str = e.error['message'] - assert("Invalid Defi token: TSLAA" in error_str) + assert ("Invalid Defi token: TSLAA" in error_str) # Invalid collateral token try: self.nodes[0].estimatevault('3.00000000@DFII', '3.00000000@TSLA') except JSONRPCException as e: error_str = e.error['message'] - assert("Invalid Defi token: DFII" in error_str) + assert ("Invalid Defi token: DFII" in error_str) # Token not set as a collateral try: self.nodes[0].estimatevault('3.00000000@TSLA', '3.00000000@TSLA') except JSONRPCException as e: error_str = e.error['message'] - assert("Token with id (6) is not a valid collateral!" in error_str) + assert ("Token with id (6) is not a valid collateral!" in error_str) # Token not set as loan token try: self.nodes[0].estimatevault('3.00000000@DFI', '3.00000000@DFI') except JSONRPCException as e: error_str = e.error['message'] - assert("Token with id (0) is not a loan token!" in error_str) + assert ("Token with id (0) is not a loan token!" in error_str) def test_estimatevault(self): vault = self.nodes[0].getvault(self.vaults[1]) @@ -621,7 +628,8 @@ def test_estimatevault(self): def test_50pctDFI_fresh_vault_takeloan_withdraw(self): # Reset price - oracle_prices = [{"currency": "USD", "tokenAmount": "1@DFI"}, {"currency": "USD", "tokenAmount": "1@TSLA"}, {"currency": "USD", "tokenAmount": "1@BTC"}] + oracle_prices = [{"currency": "USD", "tokenAmount": "1@DFI"}, {"currency": "USD", "tokenAmount": "1@TSLA"}, + {"currency": "USD", "tokenAmount": "1@BTC"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(self.oracles[0], timestamp, oracle_prices) self.nodes[0].generate(240) @@ -631,21 +639,21 @@ def test_50pctDFI_fresh_vault_takeloan_withdraw(self): self.nodes[0].generate(1) self.sync_blocks() self.owner_addresses.append(address) - self.nodes[1].sendtokenstoaddress({}, { address: '1.50@BTC'}) + self.nodes[1].sendtokenstoaddress({}, {address: '1.50@BTC'}) self.nodes[1].generate(1) self.sync_blocks() vault_id = self.nodes[0].createvault(address, 'LOAN000A') self.vaults.append(vault_id) self.nodes[0].generate(1) self.sync_blocks() - self.nodes[0].deposittovault(vault_id, address, '1.25@BTC') # 1.25@BTC as collateral factor 0.8 + self.nodes[0].deposittovault(vault_id, address, '1.25@BTC') # 1.25@BTC as collateral factor 0.8 self.nodes[0].deposittovault(vault_id, self.accountDFI, '1@DFI') self.nodes[0].generate(1) self.sync_blocks() self.nodes[0].takeloan({ - 'vaultId': vault_id, - 'amounts': "1@TSLA" - }) + 'vaultId': vault_id, + 'amounts': "1@TSLA" + }) self.nodes[0].generate(1) self.nodes[0].deposittovault(vault_id, address, '0.2@BTC') @@ -659,13 +667,13 @@ def test_50pctDFI_fresh_vault_takeloan_withdraw(self): self.nodes[0].withdrawfromvault(vault_id, address, "-0.00000001@BTC") except JSONRPCException as e: error_str = e.error['message'] - assert("Amount out of range" in error_str) + assert ("Amount out of range" in error_str) # try withdraw too small amount try: self.nodes[0].withdrawfromvault(vault_id, address, "0.000000001@BTC") except JSONRPCException as e: error_str = e.error['message'] - assert("Invalid amount" in error_str) + assert ("Invalid amount" in error_str) # try withdraw 1 satoshi self.nodes[0].withdrawfromvault(vault_id, address, "0.00000001@BTC") self.nodes[0].withdrawfromvault(vault_id, address, "0.09999999@BTC") @@ -675,7 +683,8 @@ def test_50pctDFI_fresh_vault_takeloan_withdraw(self): def test_50pctDFI_rule_after_BTC_price_increase(self): # BTC triplicates in price - oracle_prices = [{"currency": "USD", "tokenAmount": "1@DFI"}, {"currency": "USD", "tokenAmount": "1@TSLA"}, {"currency": "USD", "tokenAmount": "3@BTC"}] + oracle_prices = [{"currency": "USD", "tokenAmount": "1@DFI"}, {"currency": "USD", "tokenAmount": "1@TSLA"}, + {"currency": "USD", "tokenAmount": "3@BTC"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(self.oracles[0], timestamp, oracle_prices) self.nodes[0].generate(240) @@ -689,7 +698,7 @@ def test_50pctDFI_rule_after_BTC_price_increase(self): self.nodes[0].withdrawfromvault(self.vaults[4], self.accountDFI, "0.25@DFI") except JSONRPCException as e: errorString = e.error['message'] - assert("At least 50% of the minimum required collateral must be in DFI" in errorString) + assert ("At least 50% of the minimum required collateral must be in DFI" in errorString) # Should be able to take 0.10@TSLA and respect 50% DFI ratio self.nodes[0].takeloan({ @@ -714,18 +723,23 @@ def overflowed_collateral_value(self): }) self.nodes[0].generate(1) - oracle1_prices = [{"currency": "USD", "tokenAmount": "9999999999@DFI"}, {"currency": "USD", "tokenAmount": "1@TSLA"}, {"currency": "USD", "tokenAmount": "1@BTC"}, {"currency": "USD", "tokenAmount": "1@ETH"}, {"currency": "USD", "tokenAmount": "2@GOOGL"}] + oracle1_prices = [{"currency": "USD", "tokenAmount": "9999999999@DFI"}, + {"currency": "USD", "tokenAmount": "1@TSLA"}, {"currency": "USD", "tokenAmount": "1@BTC"}, + {"currency": "USD", "tokenAmount": "1@ETH"}, {"currency": "USD", "tokenAmount": "2@GOOGL"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(self.oracles[0], timestamp, oracle1_prices) self.nodes[0].generate(240) vault = self.nodes[0].getvault(vault_id) - assert_equal(vault['collateralValue'], 0) # collateral value overflowed + assert_equal(vault['collateralValue'], 0) # collateral value overflowed # Actions on vault should be blocked - assert_raises_rpc_error(-32600, 'Value/price too high', self.nodes[0].takeloan, {'vaultId': vault_id,'amounts': "0.5@TSLA"}) - assert_raises_rpc_error(-32600, 'Value/price too high', self.nodes[0].deposittovault, vault_id, self.accountDFI, "1@" + self.symbolDFI) - assert_raises_rpc_error(-32600, 'Value/price too high', self.nodes[0].withdrawfromvault, vault_id, address, "1@DFI") + assert_raises_rpc_error(-32600, 'Value/price too high', self.nodes[0].takeloan, + {'vaultId': vault_id, 'amounts': "0.5@TSLA"}) + assert_raises_rpc_error(-32600, 'Value/price too high', self.nodes[0].deposittovault, vault_id, self.accountDFI, + "1@" + self.symbolDFI) + assert_raises_rpc_error(-32600, 'Value/price too high', self.nodes[0].withdrawfromvault, vault_id, address, + "1@DFI") # Should be able to close vault self.nodes[0].paybackloan({'vaultId': vault_id, 'from': address, 'amounts': ["1@TSLA"]}) @@ -738,7 +752,8 @@ def loan_and_collateral_token_to_govvar(self): self.move_to_fork() # Test setting collateral token partially - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idETH}/fixed_interval_price_id':'ETH/USD', f'v0/token/{self.idETH}/loan_collateral_enabled':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idETH}/fixed_interval_price_id': 'ETH/USD', + f'v0/token/{self.idETH}/loan_collateral_enabled': 'true'}}) self.nodes[0].generate(1) # Should not show up as collateral token @@ -749,7 +764,8 @@ def loan_and_collateral_token_to_govvar(self): self.nodes[0].clearmempool() # Test setting collateral token partially - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idETH}/fixed_interval_price_id':'ETH/USD', f'v0/token/{self.idETH}/loan_collateral_factor':'0.5'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idETH}/fixed_interval_price_id': 'ETH/USD', + f'v0/token/{self.idETH}/loan_collateral_factor': '0.5'}}) self.nodes[0].generate(1) # Should not show up as collateral token @@ -760,11 +776,15 @@ def loan_and_collateral_token_to_govvar(self): self.nodes[0].clearmempool() # Set collateral token - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idETH}/fixed_interval_price_id':'ETH/USD', f'v0/token/{self.idETH}/loan_collateral_enabled':'true', f'v0/token/{self.idETH}/loan_collateral_factor':'0.5'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idETH}/fixed_interval_price_id': 'ETH/USD', + f'v0/token/{self.idETH}/loan_collateral_enabled': 'true', + f'v0/token/{self.idETH}/loan_collateral_factor': '0.5'}}) self.nodes[0].generate(1) # Test setting it again, should not be a problem. - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idETH}/fixed_interval_price_id':'ETH/USD', f'v0/token/{self.idETH}/loan_collateral_enabled':'true', f'v0/token/{self.idETH}/loan_collateral_factor':'0.5'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idETH}/fixed_interval_price_id': 'ETH/USD', + f'v0/token/{self.idETH}/loan_collateral_enabled': 'true', + f'v0/token/{self.idETH}/loan_collateral_factor': '0.5'}}) self.nodes[0].generate(1) # Should now show up as collateral token @@ -778,7 +798,8 @@ def loan_and_collateral_token_to_govvar(self): assert_equal(self.nodes[0].gettoken(self.idGOOGL)[self.idGOOGL]['isLoanToken'], False) # Test setting loan token partially. - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idGOOGL}/fixed_interval_price_id':'GOOGL/USD', f'v0/token/{self.idGOOGL}/loan_minting_enabled':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idGOOGL}/fixed_interval_price_id': 'GOOGL/USD', + f'v0/token/{self.idGOOGL}/loan_minting_enabled': 'true'}}) self.nodes[0].generate(1) # Should not show up as loan token @@ -790,7 +811,8 @@ def loan_and_collateral_token_to_govvar(self): self.nodes[0].clearmempool() # Test setting loan token partially. - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idGOOGL}/fixed_interval_price_id':'GOOGL/USD', f'v0/token/{self.idGOOGL}/loan_minting_interest':'1'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idGOOGL}/fixed_interval_price_id': 'GOOGL/USD', + f'v0/token/{self.idGOOGL}/loan_minting_interest': '1'}}) self.nodes[0].generate(1) # Should not show up as loan token @@ -802,11 +824,15 @@ def loan_and_collateral_token_to_govvar(self): self.nodes[0].clearmempool() # Set loan token - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idGOOGL}/fixed_interval_price_id':'GOOGL/USD', f'v0/token/{self.idGOOGL}/loan_minting_enabled':'true', f'v0/token/{self.idGOOGL}/loan_minting_interest':'1'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idGOOGL}/fixed_interval_price_id': 'GOOGL/USD', + f'v0/token/{self.idGOOGL}/loan_minting_enabled': 'true', + f'v0/token/{self.idGOOGL}/loan_minting_interest': '1'}}) self.nodes[0].generate(1) # Test setting it again, should not be a problem. - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idGOOGL}/fixed_interval_price_id':'GOOGL/USD', f'v0/token/{self.idGOOGL}/loan_minting_enabled':'true', f'v0/token/{self.idGOOGL}/loan_minting_interest':'1'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idGOOGL}/fixed_interval_price_id': 'GOOGL/USD', + f'v0/token/{self.idGOOGL}/loan_minting_enabled': 'true', + f'v0/token/{self.idGOOGL}/loan_minting_interest': '1'}}) self.nodes[0].generate(1) # Should now show up as loan token @@ -819,7 +845,9 @@ def loan_and_collateral_token_to_govvar(self): assert_equal(result[0]['interest'], Decimal('1.00000000')) # Set oracle price - oracle_prices = [{"currency": "USD", "tokenAmount": "1@DFI"}, {"currency": "USD", "tokenAmount": "1@TSLA"}, {"currency": "USD", "tokenAmount": "0.5@BTC"}, {"currency": "USD", "tokenAmount": "1@ETH"}, {"currency": "USD", "tokenAmount": "2@GOOGL"}] + oracle_prices = [{"currency": "USD", "tokenAmount": "1@DFI"}, {"currency": "USD", "tokenAmount": "1@TSLA"}, + {"currency": "USD", "tokenAmount": "0.5@BTC"}, {"currency": "USD", "tokenAmount": "1@ETH"}, + {"currency": "USD", "tokenAmount": "2@GOOGL"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(self.oracles[0], timestamp, oracle_prices) self.nodes[0].generate(240) @@ -842,10 +870,13 @@ def loan_and_collateral_token_to_govvar(self): # Try and deposit more GOOGL to vault self.nodes[0].minttokens("1@" + self.symbolGOOGL) self.nodes[0].generate(1) - assert_raises_rpc_error(-32600, f'Collateral token with id ({self.idGOOGL}) does not exist!', self.nodes[0].deposittovault, vaultId6, self.nodes[0].get_genesis_keys().ownerAuthAddress, '1@GOOGL') + assert_raises_rpc_error(-32600, f'Collateral token with id ({self.idGOOGL}) does not exist!', + self.nodes[0].deposittovault, vaultId6, + self.nodes[0].get_genesis_keys().ownerAuthAddress, '1@GOOGL') # Try and take collateral token as loan - assert_raises_rpc_error(-32600, f'Loan token with id ({self.idETH}) does not exist!', self.nodes[0].takeloan, {'vaultId': vaultId6, 'amounts': "1@ETH"}) + assert_raises_rpc_error(-32600, f'Loan token with id ({self.idETH}) does not exist!', self.nodes[0].takeloan, + {'vaultId': vaultId6, 'amounts': "1@ETH"}) # Take loan self.nodes[0].takeloan({'vaultId': vaultId6, 'amounts': "1@GOOGL"}) @@ -855,33 +886,37 @@ def loan_and_collateral_token_to_govvar(self): assert_equal(self.nodes[0].getvault(vaultId6)['collateralRatio'], 375) # Change collateral ratio - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idETH}/loan_collateral_factor':'1'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idETH}/loan_collateral_factor': '1'}}) self.nodes[0].generate(2) # Check new ratio assert_equal(self.nodes[0].getvault(vaultId6)['collateralRatio'], 500) - assert_equal(self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'][f'v0/token/{self.idETH}/loan_collateral_factor'], '1') + assert_equal(self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'][f'v0/token/{self.idETH}/loan_collateral_factor'], + '1') # Change collateral currency pair - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idETH}/fixed_interval_price_id':'BTC/USD'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idETH}/fixed_interval_price_id': 'BTC/USD'}}) self.nodes[0].generate(1) # Check new ratio and currency pair assert_equal(self.nodes[0].getvault(vaultId6)['collateralRatio'], 375) - assert_equal(self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'][f'v0/token/{self.idETH}/fixed_interval_price_id'], 'BTC/USD') + assert_equal(self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'][f'v0/token/{self.idETH}/fixed_interval_price_id'], + 'BTC/USD') # Disable collateral token - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idETH}/loan_collateral_enabled':'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idETH}/loan_collateral_enabled': 'false'}}) self.nodes[0].generate(1) # Check ETH collateral token disabled - assert_equal(self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'][f'v0/token/{self.idETH}/loan_collateral_enabled'], 'false') + assert_equal(self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'][f'v0/token/{self.idETH}/loan_collateral_enabled'], + 'false') # Try and deposit disabled collateral to vault - assert_raises_rpc_error(-32600, f'Collateral token ({self.idETH}) is disabled', self.nodes[0].deposittovault, vaultId6, self.nodes[0].get_genesis_keys().ownerAuthAddress, '1@ETH') + assert_raises_rpc_error(-32600, f'Collateral token ({self.idETH}) is disabled', self.nodes[0].deposittovault, + vaultId6, self.nodes[0].get_genesis_keys().ownerAuthAddress, '1@ETH') # Reduce interest to zero - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idGOOGL}/loan_minting_interest':'0'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idGOOGL}/loan_minting_interest': '0'}}) self.nodes[0].generate(1) # Take new loan with zero interest on the loan token @@ -894,7 +929,8 @@ def loan_and_collateral_token_to_govvar(self): assert_equal(self.nodes[0].getvault(vaultId6)['interestValue'], interest + Decimal('0.000000120')) # Set loan token to also be a collateral token - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idGOOGL}/loan_collateral_enabled':'true', f'v0/token/{self.idGOOGL}/loan_collateral_factor':'0.5'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idGOOGL}/loan_collateral_enabled': 'true', + f'v0/token/{self.idGOOGL}/loan_collateral_factor': '0.5'}}) self.nodes[0].generate(1) # Deposit GOOGL to vault @@ -907,7 +943,7 @@ def loan_and_collateral_token_to_govvar(self): assert_equal(result['collateralAmounts'], ['5.00000000@DFI', '5.00000000@ETH', '1.00000000@GOOGL']) # Disable loan token - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idGOOGL}/loan_minting_enabled':'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idGOOGL}/loan_minting_enabled': 'false'}}) self.nodes[0].generate(1) # Check loan token is false, still shows up in listloantokens as per previous behaviour. @@ -915,12 +951,19 @@ def loan_and_collateral_token_to_govvar(self): assert_equal(result['token'][str(self.idGOOGL)]['isLoanToken'], False) # Check that taking loan now fails - assert_raises_rpc_error(-32600, f'Loan cannot be taken on token with id ({self.idGOOGL}) as "mintable" is currently false', self.nodes[0].takeloan, {'vaultId': vaultId6, 'amounts': "1@GOOGL"}) + assert_raises_rpc_error(-32600, + f'Loan cannot be taken on token with id ({self.idGOOGL}) as "mintable" is currently false', + self.nodes[0].takeloan, {'vaultId': vaultId6, 'amounts': "1@GOOGL"}) # Set collateral and loan tokens for 10 blocks time activation_height = self.nodes[0].getblockcount() + 10 - self.nodes[0].setgovheight({"ATTRIBUTES":{f'v0/token/{self.idAAPL}/fixed_interval_price_id':'GOOGL/USD', f'v0/token/{self.idAAPL}/loan_minting_enabled':'true', f'v0/token/{self.idAAPL}/loan_minting_interest':'1', - f'v0/token/{self.idUSDT}/fixed_interval_price_id':'GOOGL/USD', f'v0/token/{self.idUSDT}/loan_collateral_enabled':'true', f'v0/token/{self.idUSDT}/loan_collateral_factor':'1'}}, activation_height) + self.nodes[0].setgovheight({"ATTRIBUTES": {f'v0/token/{self.idAAPL}/fixed_interval_price_id': 'GOOGL/USD', + f'v0/token/{self.idAAPL}/loan_minting_enabled': 'true', + f'v0/token/{self.idAAPL}/loan_minting_interest': '1', + f'v0/token/{self.idUSDT}/fixed_interval_price_id': 'GOOGL/USD', + f'v0/token/{self.idUSDT}/loan_collateral_enabled': 'true', + f'v0/token/{self.idUSDT}/loan_collateral_factor': '1'}}, + activation_height) self.nodes[0].generate(1) # Check pending tokens @@ -973,5 +1016,6 @@ def run_test(self): self.overflowed_collateral_value() self.loan_and_collateral_token_to_govvar() + if __name__ == '__main__': VaultTest().main() diff --git a/test/functional/feature_loan_vaultstate.py b/test/functional/feature_loan_vaultstate.py index ecb913d5e3..a5c202721e 100755 --- a/test/functional/feature_loan_vaultstate.py +++ b/test/functional/feature_loan_vaultstate.py @@ -13,13 +13,15 @@ import calendar import time -class VaultStateTest (DefiTestFramework): + +class VaultStateTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True self.extra_args = [ - ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-txindex=1', '-fortcanningheight=1', '-fortcanninghillheight=1', '-fortcanningcrunchheight=1'] - ] + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-txindex=1', + '-fortcanningheight=1', '-fortcanninghillheight=1', '-fortcanningcrunchheight=1'] + ] def run_test(self): self.nodes[0].generate(500) @@ -56,32 +58,34 @@ def run_test(self): # setup oracle oracle_address1 = self.nodes[0].getnewaddress("", "legacy") - price_feeds1 = [{"currency": "USD", "token": "DFI"}, {"currency": "USD", "token": "BTC"}, {"currency": "USD", "token": "TSLA"}] + price_feeds1 = [{"currency": "USD", "token": "DFI"}, {"currency": "USD", "token": "BTC"}, + {"currency": "USD", "token": "TSLA"}] oracle_id1 = self.nodes[0].appointoracle(oracle_address1, price_feeds1, 10) self.nodes[0].generate(1) # feed oracle - oracle1_prices = [{"currency": "USD", "tokenAmount": "100@TSLA"}, {"currency": "USD", "tokenAmount": "100@DFI"}, {"currency": "USD", "tokenAmount": "100@BTC"}] + oracle1_prices = [{"currency": "USD", "tokenAmount": "100@TSLA"}, {"currency": "USD", "tokenAmount": "100@DFI"}, + {"currency": "USD", "tokenAmount": "100@BTC"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(oracle_id1, timestamp, oracle1_prices) self.nodes[0].generate(6) # set DFI an BTC as collateral tokens self.nodes[0].setcollateraltoken({ - 'token': "DFI", - 'factor': 1, - 'fixedIntervalPriceId': "DFI/USD"}) + 'token': "DFI", + 'factor': 1, + 'fixedIntervalPriceId': "DFI/USD"}) self.nodes[0].setcollateraltoken({ - 'token': "BTC", - 'factor': 1, - 'fixedIntervalPriceId': "BTC/USD"}) + 'token': "BTC", + 'factor': 1, + 'fixedIntervalPriceId': "BTC/USD"}) self.nodes[0].setloantoken({ - 'symbol': "TSLA", - 'name': "Tesla Token", - 'fixedIntervalPriceId': "TSLA/USD", - 'mintable': True, - 'interest': 1}) - self.nodes[0].generate(6) # let active price update + 'symbol': "TSLA", + 'name': "Tesla Token", + 'fixedIntervalPriceId': "TSLA/USD", + 'mintable': True, + 'interest': 1}) + self.nodes[0].generate(6) # let active price update idDFI = list(self.nodes[0].gettoken("DFI").keys())[0] iddUSD = list(self.nodes[0].gettoken("DUSD").keys())[0] @@ -141,14 +145,15 @@ def run_test(self): self.nodes[0].generate(1) self.nodes[0].takeloan({ - 'vaultId': vaultId1, - 'amounts': "5@TSLA"}) + 'vaultId': vaultId1, + 'amounts': "5@TSLA"}) self.nodes[0].generate(1) # trigger liquidation - oracle1_prices = [{"currency": "USD", "tokenAmount": "134@TSLA"}, {"currency": "USD", "tokenAmount": "100@DFI"}, {"currency": "USD", "tokenAmount": "100@BTC"}] + oracle1_prices = [{"currency": "USD", "tokenAmount": "134@TSLA"}, {"currency": "USD", "tokenAmount": "100@DFI"}, + {"currency": "USD", "tokenAmount": "100@BTC"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(oracle_id1, timestamp, oracle1_prices) - self.nodes[0].generate(6) # let price enter invalid state + self.nodes[0].generate(6) # let price enter invalid state vault1 = self.nodes[0].getvault(vaultId1) listvaults = self.nodes[0].listvaults() @@ -159,7 +164,7 @@ def run_test(self): assert_equal(len(listvaults), 1) listvaults = self.nodes[0].listvaults({"state": "active"}) assert_equal(len(listvaults), 0) - self.nodes[0].generate(6) # let price update and trigger liquidation of vault + self.nodes[0].generate(6) # let price update and trigger liquidation of vault vault1 = self.nodes[0].getvault(vaultId1) listvaults = self.nodes[0].listvaults() @@ -169,44 +174,47 @@ def run_test(self): auctionlist = self.nodes[0].listauctions() assert_equal(auctionlist[0]["liquidationHeight"], 570) - self.nodes[0].generate(36) # let auction end without bids + self.nodes[0].generate(36) # let auction end without bids auctionlist = self.nodes[0].listauctions() assert_equal(auctionlist[0]["liquidationHeight"], 607) assert_equal(len(auctionlist), 1) - oracle1_prices = [{"currency": "USD", "tokenAmount": "100@TSLA"}, {"currency": "USD", "tokenAmount": "100@DFI"}, {"currency": "USD", "tokenAmount": "100@BTC"}] + oracle1_prices = [{"currency": "USD", "tokenAmount": "100@TSLA"}, {"currency": "USD", "tokenAmount": "100@DFI"}, + {"currency": "USD", "tokenAmount": "100@BTC"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(oracle_id1, timestamp, oracle1_prices) - self.nodes[0].generate(6) # update price - self.nodes[0].generate(30) # let auction end without bids and open vault again + self.nodes[0].generate(6) # update price + self.nodes[0].generate(30) # let auction end without bids and open vault again vault1 = self.nodes[0].getvault(vaultId1) listvaults = self.nodes[0].listvaults() assert_equal(vault1["state"], "active") assert_equal(listvaults[0]["state"], "active") - oracle1_prices = [{"currency": "USD", "tokenAmount": "101@TSLA"}, {"currency": "USD", "tokenAmount": "100@DFI"}, {"currency": "USD", "tokenAmount": "100@BTC"}] + oracle1_prices = [{"currency": "USD", "tokenAmount": "101@TSLA"}, {"currency": "USD", "tokenAmount": "100@DFI"}, + {"currency": "USD", "tokenAmount": "100@BTC"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(oracle_id1, timestamp, oracle1_prices) - self.nodes[0].generate(6) # let price update + self.nodes[0].generate(6) # let price update vault1 = self.nodes[0].getvault(vaultId1) listvaults = self.nodes[0].listvaults() assert_equal(vault1["state"], "mayLiquidate") assert_equal(listvaults[0]["state"], "mayLiquidate") - self.nodes[0].generate(6) # let vault enter liquidation state + self.nodes[0].generate(6) # let vault enter liquidation state - oracle1_prices = [{"currency": "USD", "tokenAmount": "136@TSLA"}, {"currency": "USD", "tokenAmount": "100@DFI"}, {"currency": "USD", "tokenAmount": "100@BTC"}] + oracle1_prices = [{"currency": "USD", "tokenAmount": "136@TSLA"}, {"currency": "USD", "tokenAmount": "100@DFI"}, + {"currency": "USD", "tokenAmount": "100@BTC"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(oracle_id1, timestamp, oracle1_prices) - self.nodes[0].generate(6) # let price update + self.nodes[0].generate(6) # let price update vault1 = self.nodes[0].getvault(vaultId1) listvaults = self.nodes[0].listvaults() assert_equal(vault1["state"], "inLiquidation") assert_equal(listvaults[0]["state"], "inLiquidation") + if __name__ == '__main__': VaultStateTest().main() - diff --git a/test/functional/feature_lock_unspends.py b/test/functional/feature_lock_unspends.py index a45dfd4bf3..f43c1dbcde 100755 --- a/test/functional/feature_lock_unspends.py +++ b/test/functional/feature_lock_unspends.py @@ -7,11 +7,13 @@ from test_framework.test_framework import DefiTestFramework + class TestLockUnspends(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True - self.extra_args = [['-txindex=1', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=50']] + self.extra_args = [ + ['-txindex=1', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=50']] def run_test(self): self.nodes[0].generate(105) @@ -39,5 +41,6 @@ def run_test(self): self.nodes[0].generate(1) + if __name__ == '__main__': TestLockUnspends().main() diff --git a/test/functional/feature_logging.py b/test/functional/feature_logging.py index 467d04355c..456ff7f107 100755 --- a/test/functional/feature_logging.py +++ b/test/functional/feature_logging.py @@ -36,8 +36,9 @@ def run_test(self): invdir = self.relative_log_path("foo") invalidname = os.path.join("foo", "foo.log") self.stop_node(0) - exp_stderr = "Error: Could not open debug log file \S+$" - self.nodes[0].assert_start_raises_init_error(["-debuglogfile=%s" % (invalidname)], exp_stderr, match=ErrorMatch.FULL_REGEX) + exp_stderr = r"Error: Could not open debug log file \S+$" + self.nodes[0].assert_start_raises_init_error(["-debuglogfile=%s" % (invalidname)], exp_stderr, + match=ErrorMatch.FULL_REGEX) assert not os.path.isfile(os.path.join(invdir, "foo.log")) # check that invalid log (relative) works after path exists @@ -50,7 +51,8 @@ def run_test(self): self.stop_node(0) invdir = os.path.join(self.options.tmpdir, "foo") invalidname = os.path.join(invdir, "foo.log") - self.nodes[0].assert_start_raises_init_error(["-debuglogfile=%s" % invalidname], exp_stderr, match=ErrorMatch.FULL_REGEX) + self.nodes[0].assert_start_raises_init_error(["-debuglogfile=%s" % invalidname], exp_stderr, + match=ErrorMatch.FULL_REGEX) assert not os.path.isfile(os.path.join(invdir, "foo.log")) # check that invalid log (absolute) works after path exists diff --git a/test/functional/feature_longterm_lockin.py b/test/functional/feature_longterm_lockin.py index d42f1d6e27..c7890a7dc6 100755 --- a/test/functional/feature_longterm_lockin.py +++ b/test/functional/feature_longterm_lockin.py @@ -12,12 +12,16 @@ from test_framework.authproxy import JSONRPCException from test_framework.util import assert_equal, disconnect_nodes, connect_nodes -class MasternodesTimelockTest (DefiTestFramework): + +class MasternodesTimelockTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 self.setup_clean_chain = True - self.extra_args = [['-dummypos=0', '-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-bayfrontgardensheight=1', '-dakotaheight=1', '-dakotacrescentheight=1', '-eunosheight=1', '-eunospayaheight=140'], - ['-dummypos=0', '-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-bayfrontgardensheight=1', '-dakotaheight=1', '-dakotacrescentheight=1', '-eunosheight=1', '-eunospayaheight=140']] + self.extra_args = [ + ['-dummypos=0', '-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-bayfrontgardensheight=1', + '-dakotaheight=1', '-dakotacrescentheight=1', '-eunosheight=1', '-eunospayaheight=140'], + ['-dummypos=0', '-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-bayfrontgardensheight=1', + '-dakotaheight=1', '-dakotacrescentheight=1', '-eunosheight=1', '-eunospayaheight=140']] def run_test(self): @@ -34,7 +38,7 @@ def run_test(self): self.nodes[0].createmasternode(collateral5, "", [], "FIVEYEARTIMELOCK") except JSONRPCException as e: errorString = e.error['message'] - assert("Timelock cannot be specified before EunosPaya hard fork" in errorString) + assert ("Timelock cannot be specified before EunosPaya hard fork" in errorString) # Create regular MN to make sure accrued multiplier moves over nodeid_pre = self.nodes[0].createmasternode(collateral_prefork) @@ -82,7 +86,7 @@ def run_test(self): self.nodes[0].sendrawtransaction(nodeid20_raw) except JSONRPCException as e: errorString = e.error['message'] - assert("Timelock must be set to either 0, 5 or 10 years" in errorString) + assert ("Timelock must be set to either 0, 5 or 10 years" in errorString) # Check state and timelock length result = self.nodes[0].getmasternode(nodeid) @@ -118,7 +122,7 @@ def run_test(self): result5 = self.nodes[0].getmasternode(nodeid5) assert_equal(result5[nodeid5]['targetMultipliers'], [1, 1, 1]) - assert('multiplierSubnode3' not in result5[nodeid5]) + assert ('multiplierSubnode3' not in result5[nodeid5]) result10 = self.nodes[0].getmasternode(nodeid10) assert_equal(result10[nodeid10]['targetMultipliers'], [1, 1, 1, 1]) @@ -170,13 +174,13 @@ def run_test(self): self.nodes[0].resignmasternode(nodeid5) except JSONRPCException as e: errorString = e.error['message'] - assert("Trying to resign masternode before timelock expiration" in errorString) + assert ("Trying to resign masternode before timelock expiration" in errorString) try: self.nodes[0].resignmasternode(nodeid10) except JSONRPCException as e: errorString = e.error['message'] - assert("Trying to resign masternode before timelock expiration" in errorString) + assert ("Trying to resign masternode before timelock expiration" in errorString) # Time travel five years, add a day as we moved forward a day at the start self.nodes[0].set_mocktime(int(time.time()) + (5 * 365 * 24 * 60 * 60) + (24 * 60 * 60)) @@ -199,7 +203,7 @@ def run_test(self): self.nodes[0].resignmasternode(nodeid10) except JSONRPCException as e: errorString = e.error['message'] - assert("Trying to resign masternode before timelock expiration" in errorString) + assert ("Trying to resign masternode before timelock expiration" in errorString) # Generate enough blocks to confirm resignation self.nodes[0].generate(41) @@ -227,5 +231,6 @@ def run_test(self): result10 = self.nodes[0].getmasternode(nodeid10) assert_equal(result10[nodeid10]['state'], 'RESIGNED') + if __name__ == '__main__': MasternodesTimelockTest().main() diff --git a/test/functional/feature_masternode_operator.py b/test/functional/feature_masternode_operator.py index 273057dcc3..f924c43059 100755 --- a/test/functional/feature_masternode_operator.py +++ b/test/functional/feature_masternode_operator.py @@ -9,6 +9,7 @@ connect_nodes_bi, ) + class TestMasternodeOperator(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 @@ -31,7 +32,7 @@ def run_test(self): self.log.info("Restart nodes...") self.restart_node(0, ['-gen', '-masternode_operator=' + operators[0]]) self.restart_node(1, ['-gen', '-rewardaddress=' + operators[1]] + - ['-masternode_operator=' + x for x in operators]) + ['-masternode_operator=' + x for x in operators]) connect_nodes_bi(self.nodes, 0, 1) diff --git a/test/functional/feature_maxuploadtarget.py b/test/functional/feature_maxuploadtarget.py index 9ed0d035c2..2b267c1002 100755 --- a/test/functional/feature_maxuploadtarget.py +++ b/test/functional/feature_maxuploadtarget.py @@ -18,7 +18,8 @@ from test_framework.test_framework import DefiTestFramework from test_framework.util import assert_equal, mine_large_block -MAXUPLOADTARGET=9376 # moore than 9216 (daily buffer, semi-fixed) !!! +MAXUPLOADTARGET = 9376 # moore than 9216 (daily buffer, semi-fixed) !!! + class TestP2PConn(P2PInterface): def __init__(self): @@ -32,12 +33,13 @@ def on_block(self, message): message.block.calc_sha256() self.block_receive_map[message.block.sha256] += 1 + class MaxUploadTest(DefiTestFramework): def set_test_params(self): self.setup_clean_chain = True self.num_nodes = 1 - self.extra_args = [["-maxuploadtarget="+str(MAXUPLOADTARGET), "-acceptnonstdtxn=1"]] + self.extra_args = [["-maxuploadtarget=" + str(MAXUPLOADTARGET), "-acceptnonstdtxn=1"]] # Cache for utxos, as the listunspent may take a long time later in the test self.utxo_cache = [] @@ -51,7 +53,7 @@ def run_test(self): # time counters can't be reset backward after initialization from test_framework.test_node import TestNode # TestNode.Mocktime is required now for successful 'generate' - TestNode.Mocktime = int(time.time() - 2*60*60*24*7) + TestNode.Mocktime = int(time.time() - 2 * 60 * 60 * 24 * 7) # Generate some old blocks self.nodes[0].generate(130) @@ -73,7 +75,7 @@ def run_test(self): big_old_block = int(big_old_block, 16) # Advance to two days ago - TestNode.Mocktime = int(time.time()) - 2*60*60*24 + TestNode.Mocktime = int(time.time()) - 2 * 60 * 60 * 24 # Mine one more block, so that the prior block looks old mine_large_block(self.nodes[0], self.utxo_cache) @@ -89,8 +91,8 @@ def run_test(self): getdata_request = msg_getdata() getdata_request.inv.append(CInv(2, big_old_block)) - max_bytes_per_day = MAXUPLOADTARGET*1024*1024 - daily_buffer = 16*144 * 4000000 # see `buffer` in OutboundTargetReached() in net.cpp + max_bytes_per_day = MAXUPLOADTARGET * 1024 * 1024 + daily_buffer = 16 * 144 * 4000000 # see `buffer` in OutboundTargetReached() in net.cpp max_bytes_available = max_bytes_per_day - daily_buffer success_count = max_bytes_available // old_block_size @@ -99,7 +101,7 @@ def run_test(self): for i in range(success_count): p2p_conns[0].send_message(getdata_request) p2p_conns[0].sync_with_ping() - assert_equal(p2p_conns[0].block_receive_map[big_old_block], i+1) + assert_equal(p2p_conns[0].block_receive_map[big_old_block], i + 1) assert_equal(len(self.nodes[0].getpeerinfo()), 3) # At most a couple more tries should succeed (depending on how long @@ -113,10 +115,10 @@ def run_test(self): # Requesting the current block on p2p_conns[1] should succeed indefinitely, # even when over the max upload target. getdata_request.inv = [CInv(2, big_new_block)] - for i in range(max_bytes_available // new_block_size + 3): # +3 to exceed limit + for i in range(max_bytes_available // new_block_size + 3): # +3 to exceed limit p2p_conns[1].send_message(getdata_request) p2p_conns[1].sync_with_ping() - assert_equal(p2p_conns[1].block_receive_map[big_new_block], i+1) + assert_equal(p2p_conns[1].block_receive_map[big_new_block], i + 1) self.log.info("Peer 1 able to repeatedly download new block") @@ -143,7 +145,7 @@ def run_test(self): self.nodes[0].disconnect_p2ps() - #stop and start node 0 with 1MB maxuploadtarget, whitelist 127.0.0.1 + # stop and start node 0 with 1MB maxuploadtarget, whitelist 127.0.0.1 self.log.info("Restarting nodes with -whitelist=127.0.0.1") self.stop_node(0) self.start_node(0, ["-whitelist=127.0.0.1", "-maxuploadtarget=1"]) @@ -151,18 +153,19 @@ def run_test(self): # Reconnect to self.nodes[0] self.nodes[0].add_p2p_connection(TestP2PConn()) - #retrieve 20 blocks which should be enough to break the 1MB limit + # retrieve 20 blocks which should be enough to break the 1MB limit getdata_request.inv = [CInv(2, big_new_block)] for i in range(20): self.nodes[0].p2p.send_message(getdata_request) self.nodes[0].p2p.sync_with_ping() - assert_equal(self.nodes[0].p2p.block_receive_map[big_new_block], i+1) + assert_equal(self.nodes[0].p2p.block_receive_map[big_new_block], i + 1) getdata_request.inv = [CInv(2, big_old_block)] self.nodes[0].p2p.send_and_ping(getdata_request) - assert_equal(len(self.nodes[0].getpeerinfo()), 1) #node is still connected because of the whitelist + assert_equal(len(self.nodes[0].getpeerinfo()), 1) # node is still connected because of the whitelist self.log.info("Peer still connected after trying to download old block (whitelisted)") + if __name__ == '__main__': MaxUploadTest().main() diff --git a/test/functional/feature_median_time.py b/test/functional/feature_median_time.py index 18ce1da2f0..22ff9d55b9 100755 --- a/test/functional/feature_median_time.py +++ b/test/functional/feature_median_time.py @@ -10,10 +10,11 @@ import time from random import randint + class MedianTimeTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 - self.extra_args = [ "-dummypos=1", '-amkheight=0', "-dakotaheight=1", "-fortcanningheight=100"], + self.extra_args = ["-dummypos=1", '-amkheight=0', "-dakotaheight=1", "-fortcanningheight=100"], self.setup_clean_chain = True def CalcMedianTime(self): @@ -33,19 +34,24 @@ def GenerateBlocks(self, blocks): def run_test(self): self.nodes[0].generate(11) - assert_equal(self.nodes[0].getblock(self.nodes[0].getblockhash(self.nodes[0].getblockcount()))['mediantime'], self.CalcMedianTime()) + assert_equal(self.nodes[0].getblock(self.nodes[0].getblockhash(self.nodes[0].getblockcount()))['mediantime'], + self.CalcMedianTime()) # Test some random block times pre-fork self.GenerateBlocks(11) - assert_equal(self.nodes[0].getblock(self.nodes[0].getblockhash(self.nodes[0].getblockcount()))['mediantime'], self.CalcMedianTime()) + assert_equal(self.nodes[0].getblock(self.nodes[0].getblockhash(self.nodes[0].getblockcount()))['mediantime'], + self.CalcMedianTime()) # Move to hard fork self.nodes[0].generate(100 - self.nodes[0].getblockcount()) - assert_equal(self.nodes[0].getblock(self.nodes[0].getblockhash(self.nodes[0].getblockcount()))['mediantime'], self.CalcMedianTime()) + assert_equal(self.nodes[0].getblock(self.nodes[0].getblockhash(self.nodes[0].getblockcount()))['mediantime'], + self.CalcMedianTime()) # Test some random block times post-fork self.GenerateBlocks(5) - assert_equal(self.nodes[0].getblock(self.nodes[0].getblockhash(self.nodes[0].getblockcount()))['mediantime'], self.CalcMedianTime()) + assert_equal(self.nodes[0].getblock(self.nodes[0].getblockhash(self.nodes[0].getblockcount()))['mediantime'], + self.CalcMedianTime()) + if __name__ == '__main__': MedianTimeTest().main() diff --git a/test/functional/feature_mempool_dakota.py b/test/functional/feature_mempool_dakota.py index b03a18428d..b97b9945d9 100755 --- a/test/functional/feature_mempool_dakota.py +++ b/test/functional/feature_mempool_dakota.py @@ -11,15 +11,16 @@ assert_raises_rpc_error, ) + class MempoolDakotaTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 3 self.setup_clean_chain = True self.extra_args = [ - ['-txnotokens=0', '-amkheight=50', '-dakotaheight=100'], - ['-txnotokens=0', '-amkheight=50', '-dakotaheight=100'], - ['-txnotokens=0', '-amkheight=50', '-dakotaheight=100'], - ] + ['-txnotokens=0', '-amkheight=50', '-dakotaheight=100'], + ['-txnotokens=0', '-amkheight=50', '-dakotaheight=100'], + ['-txnotokens=0', '-amkheight=50', '-dakotaheight=100'], + ] def run_test(self): node = self.nodes[0] @@ -27,7 +28,7 @@ def run_test(self): node.generate(101) self.sync_blocks() - assert_equal(node.getblockcount(), 101) # Dakota height + assert_equal(node.getblockcount(), 101) # Dakota height # Get addresses and set up account wallet1_addr = node1.getnewaddress("", "legacy") @@ -48,5 +49,6 @@ def run_test(self): node.generate(1) self.sync_blocks() + if __name__ == '__main__': - MempoolDakotaTest().main () + MempoolDakotaTest().main() diff --git a/test/functional/feature_migrate_v1_in_futures.py b/test/functional/feature_migrate_v1_in_futures.py index 7139fef531..3f7af8c8f8 100755 --- a/test/functional/feature_migrate_v1_in_futures.py +++ b/test/functional/feature_migrate_v1_in_futures.py @@ -11,15 +11,17 @@ from decimal import Decimal import time + class MigrateV1Test(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True self.extra_args = [ - ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', '-fortcanningmuseumheight=1', '-fortcanninghillheight=1', '-fortcanningroadheight=1', '-fortcanningcrunchheight=1']] + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', + '-fortcanningmuseumheight=1', '-fortcanninghillheight=1', '-fortcanningroadheight=1', + '-fortcanningcrunchheight=1']] def run_test(self): - # Set up tokens self.setup_test_tokens() @@ -90,16 +92,15 @@ def setup_test_tokens(self): self.nodes[0].generate(1) def test_migration_on_fork(self): - # Set all futures attributes - self.nodes[0].setgov({"ATTRIBUTES":{ - 'v0/params/dfip2203/reward_pct':'0.05', - 'v0/params/dfip2203/block_period':'10' + self.nodes[0].setgov({"ATTRIBUTES": { + 'v0/params/dfip2203/reward_pct': '0.05', + 'v0/params/dfip2203/block_period': '10' }}) self.nodes[0].generate(1) - self.nodes[0].setgov({"ATTRIBUTES":{ - 'v0/params/dfip2203/active':'true' + self.nodes[0].setgov({"ATTRIBUTES": { + 'v0/params/dfip2203/active': 'true' }}) self.nodes[0].generate(1) @@ -109,21 +110,28 @@ def test_migration_on_fork(self): self.nodes[0].generate(10) # Get pre-split values - [current_amount, current_symbol] = self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES']['v0/live/economy/dfip2203_current'][1].split('@') - [burnt_amount, burnt_symbol] = self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES']['v0/live/economy/dfip2203_burned'][1].split('@') - [minted_amount, minted_symbol] = self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES']['v0/live/economy/dfip2203_minted'][1].split('@') + [current_amount, current_symbol] = \ + self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES']['v0/live/economy/dfip2203_current'][1].split('@') + [burnt_amount, burnt_symbol] = \ + self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES']['v0/live/economy/dfip2203_burned'][1].split('@') + [minted_amount, minted_symbol] = \ + self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES']['v0/live/economy/dfip2203_minted'][1].split('@') # Define multiplier multiplier = 2 # Token split - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/oracles/splits/{self.nodes[0].getblockcount() + 2}':f'{self.idTSLA}/{multiplier}'}}) + self.nodes[0].setgov( + {"ATTRIBUTES": {f'v0/oracles/splits/{self.nodes[0].getblockcount() + 2}': f'{self.idTSLA}/{multiplier}'}}) self.nodes[0].generate(2) # Get split amounts - [current_split_amount, current_split_symbol] = self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES']['v0/live/economy/dfip2203_current'][1].split('@') - [burnt_split_amount, burnt_split_symbol] = self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES']['v0/live/economy/dfip2203_burned'][1].split('@') - [minted_split_amount, minted_split_symbol] = self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES']['v0/live/economy/dfip2203_minted'][1].split('@') + [current_split_amount, current_split_symbol] = \ + self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES']['v0/live/economy/dfip2203_current'][1].split('@') + [burnt_split_amount, burnt_split_symbol] = \ + self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES']['v0/live/economy/dfip2203_burned'][1].split('@') + [minted_split_amount, minted_split_symbol] = \ + self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES']['v0/live/economy/dfip2203_minted'][1].split('@') # Check amounts updated as expected assert_equal(Decimal(current_amount) * multiplier, Decimal(current_split_amount)) @@ -135,5 +143,6 @@ def test_migration_on_fork(self): assert_equal(burnt_symbol, burnt_split_symbol) assert_equal(minted_symbol, minted_split_symbol) + if __name__ == '__main__': MigrateV1Test().main() diff --git a/test/functional/feature_minchainwork.py b/test/functional/feature_minchainwork.py index 977214ee89..fbbc88cb98 100755 --- a/test/functional/feature_minchainwork.py +++ b/test/functional/feature_minchainwork.py @@ -23,6 +23,7 @@ # 2 hashes required per regtest block (with no difficulty adjustment) REGTEST_WORK_PER_BLOCK = 2 + class MinimumChainWorkTest(DefiTestFramework): def set_test_params(self): self.setup_clean_chain = True @@ -38,13 +39,13 @@ def setup_network(self): # peers, so ensure that we're mining on an outbound peer and testing # block relay to inbound peers. self.setup_nodes() - for i in range(self.num_nodes-1): - connect_nodes(self.nodes[i+1], i) + for i in range(self.num_nodes - 1): + connect_nodes(self.nodes[i + 1], i) def run_test(self): # Start building a chain on node0. node2 shouldn't be able to sync until node1's # minchainwork is exceeded - starting_chain_work = REGTEST_WORK_PER_BLOCK # Genesis block's work + starting_chain_work = REGTEST_WORK_PER_BLOCK # Genesis block's work self.log.info("Testing relay across node %d (minChainWork = %d)", 1, self.node_min_work[1]) starting_blockcount = self.nodes[2].getblockcount() @@ -85,5 +86,6 @@ def run_test(self): self.sync_blocks() self.log.info("Blockcounts: %s", [n.getblockcount() for n in self.nodes]) + if __name__ == '__main__': MinimumChainWorkTest().main() diff --git a/test/functional/feature_mine_cached.py b/test/functional/feature_mine_cached.py index 546d045a6b..0d8b3a7d50 100755 --- a/test/functional/feature_mine_cached.py +++ b/test/functional/feature_mine_cached.py @@ -15,6 +15,7 @@ assert_raises_rpc_error, ) + class IsMineCachedTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 @@ -27,7 +28,7 @@ def set_test_params(self): ] def run_test(self): - assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI + assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI self.nodes[0].generate(101) self.sync_blocks() @@ -47,5 +48,6 @@ def run_test(self): self.nodes[0].sendtokenstoaddress({}, to) + if __name__ == '__main__': IsMineCachedTest().main() diff --git a/test/functional/feature_negative_interest.py b/test/functional/feature_negative_interest.py index 401d2714b7..ac9725347c 100755 --- a/test/functional/feature_negative_interest.py +++ b/test/functional/feature_negative_interest.py @@ -13,17 +13,21 @@ import time from decimal import ROUND_DOWN, ROUND_UP, Decimal + def getDecimalAmount(amount): amountTmp = amount.split('@')[0] return Decimal(amountTmp) -class NegativeInterestTest (DefiTestFramework): +class NegativeInterestTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True self.extra_args = [ - ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', '-fortcanningmuseumheight=1', '-fortcanningspringheight=1', '-fortcanninghillheight=1', '-fortcanningcrunchheight=1', '-fortcanninggreatworldheight=1', '-fortcanningepilogueheight=1', '-jellyfish_regtest=1', '-txindex=1', '-simulatemainnet=1'] + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', + '-fortcanningmuseumheight=1', '-fortcanningspringheight=1', '-fortcanninghillheight=1', + '-fortcanningcrunchheight=1', '-fortcanninggreatworldheight=1', '-fortcanningepilogueheight=1', + '-jellyfish_regtest=1', '-txindex=1', '-simulatemainnet=1'] ] def createTokens(self): @@ -39,34 +43,34 @@ def createTokens(self): self.nodes[0].generate(1) self.nodes[0].setcollateraltoken({ - 'token': self.idDFI, - 'factor': 1, - 'fixedIntervalPriceId': "DFI/USD"}) + 'token': self.idDFI, + 'factor': 1, + 'fixedIntervalPriceId': "DFI/USD"}) self.nodes[0].generate(120) self.nodes[0].setloantoken({ - 'symbol': self.symboldUSD, - 'name': "DUSD stable token", - 'fixedIntervalPriceId': "DUSD/USD", - 'mintable': True, - 'interest': -1}) + 'symbol': self.symboldUSD, + 'name': "DUSD stable token", + 'fixedIntervalPriceId': "DUSD/USD", + 'mintable': True, + 'interest': -1}) self.nodes[0].generate(120) self.iddUSD = list(self.nodes[0].gettoken(self.symboldUSD).keys())[0] self.nodes[0].setloantoken({ - 'symbol': self.symbolTSLA, - 'name': "TSLA token", - 'fixedIntervalPriceId': "TSLA/USD", - 'mintable': True, - 'interest': 0}) + 'symbol': self.symbolTSLA, + 'name': "TSLA token", + 'fixedIntervalPriceId': "TSLA/USD", + 'mintable': True, + 'interest': 0}) self.nodes[0].generate(1) self.idTSLA = list(self.nodes[0].gettoken(self.symbolTSLA).keys())[0] self.nodes[0].setloantoken({ - 'symbol': self.symbolGOLD, - 'name': "GOLD token", - 'fixedIntervalPriceId': "GOLD/USD", - 'mintable': True, - 'interest': -3}) + 'symbol': self.symbolGOLD, + 'name': "GOLD token", + 'fixedIntervalPriceId': "GOLD/USD", + 'mintable': True, + 'interest': -3}) self.nodes[0].generate(1) self.idGOLD = list(self.nodes[0].gettoken(self.symbolGOLD).keys())[0] self.nodes[0].minttokens("1000@GOLD") @@ -81,21 +85,20 @@ def createTokens(self): self.nodes[0].utxostoaccount({self.account0: "10000@0"}) self.nodes[0].generate(1) - def createOracles(self): self.oracle_address1 = self.nodes[0].getnewaddress("", "legacy") price_feeds = [{"currency": "USD", "token": "DFI"}, - {"currency": "USD", "token": "DUSD"}, - {"currency": "USD", "token": "GOLD"}, - {"currency": "USD", "token": "TSLA"}] + {"currency": "USD", "token": "DUSD"}, + {"currency": "USD", "token": "GOLD"}, + {"currency": "USD", "token": "TSLA"}] self.oracle_id1 = self.nodes[0].appointoracle(self.oracle_address1, price_feeds, 10) self.nodes[0].generate(1) # feed oracle oracle_prices = [{"currency": "USD", "tokenAmount": "10@TSLA"}, - {"currency": "USD", "tokenAmount": "1@DUSD"}, - {"currency": "USD", "tokenAmount": "10@GOLD"}, - {"currency": "USD", "tokenAmount": "10@DFI"}] + {"currency": "USD", "tokenAmount": "1@DUSD"}, + {"currency": "USD", "tokenAmount": "10@GOLD"}, + {"currency": "USD", "tokenAmount": "10@DFI"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(self.oracle_id1, timestamp, oracle_prices) @@ -156,7 +159,7 @@ def createPoolPairs(self): self.nodes[0].generate(1) def setup(self): - assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI + assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI self.nodes[0].generate(100) self.account0 = self.nodes[0].get_genesis_keys().ownerAuthAddress self.createOracles() @@ -177,8 +180,8 @@ def vault_interest_zero(self): self.nodes[0].generate(1) # Take loan self.nodes[0].takeloan({ - 'vaultId': self.vaultId0, - 'amounts': "1@" + self.symboldUSD}) + 'vaultId': self.vaultId0, + 'amounts': "1@" + self.symboldUSD}) self.nodes[0].generate(1) # Check interests = 0 @@ -212,8 +215,8 @@ def vault_interest_over_zero_and_lower_than_loanscheme(self): self.nodes[0].generate(1) # Take loan self.nodes[0].takeloan({ - 'vaultId': self.vaultId1, - 'amounts': "1@" + self.symboldUSD}) + 'vaultId': self.vaultId1, + 'amounts': "1@" + self.symboldUSD}) self.nodes[0].generate(1) # Check interests = 1% @@ -236,8 +239,8 @@ def vault_loantoken_interest_zero(self): self.nodes[0].generate(1) # Take loan self.nodes[0].takeloan({ - 'vaultId': self.vaultId2, - 'amounts': "1@" + self.symbolTSLA}) + 'vaultId': self.vaultId2, + 'amounts': "1@" + self.symbolTSLA}) self.nodes[0].generate(1) # Check interests = 2% @@ -251,7 +254,7 @@ def vault_loantoken_interest_zero(self): # Loan scheme interest->1% and loan token interest-> -3% # Resulting interest must be 0% def vault_with_negative_interest(self): - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idTSLA}/loan_minting_interest':'-3'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idTSLA}/loan_minting_interest': '-3'}}) self.nodes[0].generate(1) # Init vault (create, deposit takeloan) # Create @@ -262,8 +265,8 @@ def vault_with_negative_interest(self): self.nodes[0].generate(1) # Take loan self.nodes[0].takeloan({ - 'vaultId': self.vaultId3, - 'amounts': "1@" + self.symbolTSLA}) + 'vaultId': self.vaultId3, + 'amounts': "1@" + self.symbolTSLA}) self.nodes[0].generate(1) # Check interests = 0 @@ -277,7 +280,7 @@ def vault_with_negative_interest(self): # Loan scheme interest->1% and loan token interest-> -30% # Resulting interest must be 0% def vault_with_big_negative_interest(self): - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idTSLA}/loan_minting_interest':'-30'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idTSLA}/loan_minting_interest': '-30'}}) self.nodes[0].generate(1) # Init vault (create, deposit takeloan) # Create @@ -288,8 +291,8 @@ def vault_with_big_negative_interest(self): self.nodes[0].generate(1) # Take loan self.nodes[0].takeloan({ - 'vaultId': self.vaultId4, - 'amounts': "1@" + self.symbolTSLA}) + 'vaultId': self.vaultId4, + 'amounts': "1@" + self.symbolTSLA}) self.nodes[0].generate(1) # Check interests = 0 @@ -313,8 +316,8 @@ def takeloan_after_interest_increase(self): loanAmount = 1 totalLoanAmount = loanAmount self.nodes[0].takeloan({ - 'vaultId': self.vaultId5, - 'amounts': str(loanAmount) + "@" + self.symbolTSLA}) + 'vaultId': self.vaultId5, + 'amounts': str(loanAmount) + "@" + self.symbolTSLA}) self.nodes[0].generate(1) # Check interests = 0 verbose = True @@ -324,17 +327,17 @@ def takeloan_after_interest_increase(self): assert_equal(Decimal(vault["interestValue"]), Decimal('-0.00001100')) assert_equal(vault["interestsPerBlock"], ["-0.000000275875190258751902@TSLA"]) - - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idTSLA}/loan_minting_interest':'30'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idTSLA}/loan_minting_interest': '30'}}) self.nodes[0].generate(1) loanAmount = 1 totalLoanAmount += loanAmount - expected_IPB = Decimal(Decimal('0.31')/Decimal(1051200)*totalLoanAmount).quantize(Decimal('1E-24'), ROUND_DOWN) + expected_IPB = Decimal(Decimal('0.31') / Decimal(1051200) * totalLoanAmount).quantize(Decimal('1E-24'), + ROUND_DOWN) # Use same vault as previous case self.nodes[0].takeloan({ - 'vaultId': self.vaultId5, - 'amounts': str(loanAmount) +"@" + self.symbolTSLA}) + 'vaultId': self.vaultId5, + 'amounts': str(loanAmount) + "@" + self.symbolTSLA}) self.nodes[0].generate(1) # Check interests = 0 @@ -345,7 +348,7 @@ def takeloan_after_interest_increase(self): # Loan scheme interest -> 1% and loan token -> -30% # Resulting interest -> -29% def takeloan_after_interest_decrease(self): - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idTSLA}/loan_minting_interest':'-30'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idTSLA}/loan_minting_interest': '-30'}}) self.nodes[0].generate(1) # Increase previously -30% interest -> +30% self.vaultId6 = self.nodes[0].createvault(self.account0, 'LOAN1') @@ -357,8 +360,8 @@ def takeloan_after_interest_decrease(self): loanAmount = 1 totalLoanAmount = loanAmount self.nodes[0].takeloan({ - 'vaultId': self.vaultId6, - 'amounts': str(loanAmount) + "@" + self.symbolTSLA}) + 'vaultId': self.vaultId6, + 'amounts': str(loanAmount) + "@" + self.symbolTSLA}) self.nodes[0].generate(1) verbose = True @@ -368,16 +371,15 @@ def takeloan_after_interest_decrease(self): assert_equal(Decimal(vault["interestValue"]), Decimal('-0.00000270')) assert_equal(vault["interestsPerBlock"], ["-0.000000275875190258751902@TSLA"]) - - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idTSLA}/loan_minting_interest':'-50'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idTSLA}/loan_minting_interest': '-50'}}) self.nodes[0].generate(1) loanAmount = 1 totalLoanAmount += loanAmount # Use same vault as previous case self.nodes[0].takeloan({ - 'vaultId': self.vaultId6, - 'amounts': str(loanAmount) +"@" + self.symbolTSLA}) + 'vaultId': self.vaultId6, + 'amounts': str(loanAmount) + "@" + self.symbolTSLA}) self.nodes[0].generate(1) # Check interests = 0 @@ -395,9 +397,9 @@ def payback_interest_zero(self): vaultBefore = self.nodes[0].getvault(self.vaultId6, verbose) self.nodes[0].paybackloan({ - 'vaultId': self.vaultId6, - 'from': self.account0, - 'amounts': ["1@" + self.symbolTSLA]}) + 'vaultId': self.vaultId6, + 'from': self.account0, + 'amounts': ["1@" + self.symbolTSLA]}) self.nodes[0].generate(1) # Check interests = 0 @@ -417,7 +419,7 @@ def payback_interest_zero(self): # Test withdrawfromvault after setting back negative interest def withdraw_interest_zero(self): - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idTSLA}/loan_minting_interest':'-50'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idTSLA}/loan_minting_interest': '-50'}}) self.nodes[0].generate(1) verbose = True @@ -445,7 +447,7 @@ def payback_after_interest_increase(self): assert_equal(vault["interestPerBlockValue"], '-0.000004661331637176560120') # Set token interest -> 0% - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idTSLA}/loan_minting_interest':'1'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idTSLA}/loan_minting_interest': '1'}}) self.nodes[0].generate(1) # Check interests @@ -457,7 +459,7 @@ def payback_after_interest_increase(self): # Set total interest to zero and increase after some blocks to positive interest to test withdraw def check_interest_amounts_after_interest_changes(self): # Total interest: 1% (loan scheme) -1% (token) = 0% - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idTSLA}/loan_minting_interest':'-1'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idTSLA}/loan_minting_interest': '-1'}}) self.nodes[0].generate(1) verbose = True @@ -472,7 +474,7 @@ def check_interest_amounts_after_interest_changes(self): assert_equal(vault["interestAmounts"], ['-0.00000137@TSLA']) # Set token interest to 0% - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idTSLA}/loan_minting_interest':'0'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idTSLA}/loan_minting_interest': '0'}}) self.nodes[0].generate(1) # Now total interest should be 1% @@ -507,7 +509,7 @@ def check_interest_amounts_after_interest_changes(self): # Updating vault should put interest to 0% and -1% after def updates_of_vault_scheme(self): # Total interest: 3% (loan scheme) -2% (token) = 1% - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idTSLA}/loan_minting_interest':'-2'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idTSLA}/loan_minting_interest': '-2'}}) self.nodes[0].createloanscheme(175, 3, 'LOAN3') self.nodes[0].generate(1) self.nodes[0].updatevault(self.vaultId6, {'loanSchemeId': 'LOAN3'}) @@ -525,8 +527,8 @@ def updates_of_vault_scheme(self): # After takeloan vault is updated and new interest per block are set self.nodes[0].takeloan({ - 'vaultId': self.vaultId6, - 'amounts': "1@" + self.symbolTSLA}) + 'vaultId': self.vaultId6, + 'amounts': "1@" + self.symbolTSLA}) self.nodes[0].generate(1) vault = self.nodes[0].getvault(self.vaultId6, verbose) @@ -550,9 +552,9 @@ def updates_of_vault_scheme(self): # After takeloan vault is updated and new interest per block are set self.nodes[0].paybackloan({ - 'vaultId': self.vaultId6, - 'from': self.account0, - 'amounts': ["1@" + self.symbolTSLA]}) + 'vaultId': self.vaultId6, + 'from': self.account0, + 'amounts': ["1@" + self.symbolTSLA]}) self.nodes[0].generate(1) vault = self.nodes[0].getvault(self.vaultId6, verbose) # Updated after payback @@ -566,8 +568,8 @@ def updates_of_vault_scheme(self): assert_equal(Decimal(balanceTSLAafter), Decimal(balanceTSLAbefore) - Decimal('1')) self.nodes[0].takeloan({ - 'vaultId': self.vaultId6, - 'amounts': "1@" + self.symbolTSLA}) + 'vaultId': self.vaultId6, + 'amounts': "1@" + self.symbolTSLA}) self.nodes[0].generate(1) vault = self.nodes[0].getvault(self.vaultId6, verbose) assert_equal(vault["interestPerBlockValue"], '-0.000000190258620624048700') @@ -583,9 +585,9 @@ def updates_of_vault_scheme(self): vaultBefore = self.nodes[0].getvault(self.vaultId6, verbose) self.nodes[0].paybackloan({ - 'vaultId': self.vaultId6, - 'from': self.account0, - 'amounts': ["1@" + self.symbolTSLA]}) + 'vaultId': self.vaultId6, + 'from': self.account0, + 'amounts': ["1@" + self.symbolTSLA]}) self.nodes[0].generate(1) vault = self.nodes[0].getvault(self.vaultId6, verbose) @@ -622,9 +624,9 @@ def updates_of_vault_scheme(self): # Update IPB with paybackloan self.nodes[0].paybackloan({ - 'vaultId': self.vaultId6, - 'from': self.account0, - 'amounts': ["0.1@" + self.symbolTSLA]}) + 'vaultId': self.vaultId6, + 'from': self.account0, + 'amounts': ["0.1@" + self.symbolTSLA]}) self.nodes[0].generate(1) vault = self.nodes[0].getvault(self.vaultId6, verbose) # IPB is updated again after paybackloan @@ -639,7 +641,7 @@ def updates_of_vault_scheme(self): # Check total interest with different loans taken def total_interest_with_multiple_takeloan(self): - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idTSLA}/loan_minting_interest':'-2'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idTSLA}/loan_minting_interest': '-2'}}) self.nodes[0].generate(1) self.vaultId7 = self.nodes[0].createvault(self.account0, 'LOAN1') self.nodes[0].generate(1) @@ -652,15 +654,15 @@ def total_interest_with_multiple_takeloan(self): vault = self.nodes[0].getvault(self.vaultId7, verbose) assert_equal(vault["interestPerBlockValue"], '0.000000000000000000000000') # Update with token interest - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idTSLA}/loan_minting_interest':'-1'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idTSLA}/loan_minting_interest': '-1'}}) self.nodes[0].generate(1) vault = self.nodes[0].getvault(self.vaultId7, verbose) assert_equal(vault["interestPerBlockValue"], '0.000000000000000000000000') # Take loan 1 and accrue interest at 0% (loan scheme interest 1% - token interest -1%) self.nodes[0].takeloan({ - 'vaultId': self.vaultId7, - 'amounts': "1@" + self.symbolTSLA}) + 'vaultId': self.vaultId7, + 'amounts': "1@" + self.symbolTSLA}) self.nodes[0].generate(10) vault = self.nodes[0].getvault(self.vaultId7, verbose) assert_equal(vault["interestPerBlockValue"], '0.000000000000000000000000') @@ -673,20 +675,20 @@ def total_interest_with_multiple_takeloan(self): # IPB update through takeloan self.nodes[0].takeloan({ - 'vaultId': self.vaultId7, - 'amounts': "1@" + self.symbolTSLA}) + 'vaultId': self.vaultId7, + 'amounts': "1@" + self.symbolTSLA}) self.nodes[0].generate(1) vault = self.nodes[0].getvault(self.vaultId7, verbose) assert_equal(vault["interestPerBlockValue"], '0.000000380517503805175030') # Take GOLD loan self.nodes[0].takeloan({ - 'vaultId': self.vaultId7, - 'amounts': "1@" + self.symbolGOLD}) + 'vaultId': self.vaultId7, + 'amounts': "1@" + self.symbolGOLD}) self.nodes[0].generate(1) vault = self.nodes[0].getvault(self.vaultId7, verbose) assert_equal(vault["interestPerBlockValue"], '0.000000380517503805175030') - assert_equal(vault["interestsPerBlock"], ['0.000000038051750380517503@TSLA','0.000000000000000000000000@GOLD']) + assert_equal(vault["interestsPerBlock"], ['0.000000038051750380517503@TSLA', '0.000000000000000000000000@GOLD']) # Update loan scheme to 1%. # TSLA loan interest -> -1% # GOLD loan interest -> -2% @@ -694,15 +696,15 @@ def total_interest_with_multiple_takeloan(self): self.nodes[0].generate(1) vault = self.nodes[0].getvault(self.vaultId7, verbose) assert_equal(vault["interestPerBlockValue"], '0.000000380517503805175030') - assert_equal(vault["interestsPerBlock"], ['0.000000038051750380517503@TSLA','0.000000000000000000000000@GOLD']) + assert_equal(vault["interestsPerBlock"], ['0.000000038051750380517503@TSLA', '0.000000000000000000000000@GOLD']) # Update GOLD interest to 1 so total GOLD loan has positive interest 2% - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idGOLD}/loan_minting_interest':'-1'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idGOLD}/loan_minting_interest': '-1'}}) self.nodes[0].generate(1) vault = self.nodes[0].getvault(self.vaultId7, verbose) # Only GOLD loan should update assert_equal(vault["interestPerBlockValue"], '0.000000570776255707762540') - assert_equal(vault["interestsPerBlock"], ['0.000000038051750380517503@TSLA','0.000000019025875190258751@GOLD']) + assert_equal(vault["interestsPerBlock"], ['0.000000038051750380517503@TSLA', '0.000000019025875190258751@GOLD']) # Check vault limit states with negative interest def vault_status_with_negative_interest(self): @@ -712,8 +714,8 @@ def vault_status_with_negative_interest(self): # Take absolut maximum amount of loan to leave the vault about to enter liquidation self.nodes[0].takeloan({ - 'vaultId': self.vaultId7, - 'amounts': "0.43839516@" + self.symbolGOLD}) + 'vaultId': self.vaultId7, + 'amounts': "0.43839516@" + self.symbolGOLD}) self.nodes[0].generate(1) verbose = True vault = self.nodes[0].getvault(self.vaultId7, verbose) @@ -725,9 +727,9 @@ def vault_status_with_negative_interest(self): assert_equal(vault["state"], 'mayLiquidate') # set total interest to 0% - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idTSLA}/loan_minting_interest':'-3'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idTSLA}/loan_minting_interest': '-3'}}) self.nodes[0].generate(1) - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idGOLD}/loan_minting_interest':'-3'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idGOLD}/loan_minting_interest': '-3'}}) self.nodes[0].generate(1) self.nodes[0].generate(1) @@ -736,9 +738,9 @@ def vault_status_with_negative_interest(self): assert_equal(vault["interestPerBlockValue"], '0.000000000000000000000000') # set total interest to -10% and check if exits mayLiquidate state - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idTSLA}/loan_minting_interest':'-10'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idTSLA}/loan_minting_interest': '-10'}}) self.nodes[0].generate(1) - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idGOLD}/loan_minting_interest':'-10'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idGOLD}/loan_minting_interest': '-10'}}) self.nodes[0].generate(1) self.nodes[0].generate(1) @@ -752,9 +754,9 @@ def payback_interests_and_continue_with_negative_interest(self): vaultBefore = self.nodes[0].getvault(self.vaultId7, verbose) self.nodes[0].paybackloan({ - 'vaultId': self.vaultId7, - 'from': self.account0, - 'amounts': ["0.00001000@" + self.symbolTSLA]}) + 'vaultId': self.vaultId7, + 'from': self.account0, + 'amounts': ["0.00001000@" + self.symbolTSLA]}) self.nodes[0].generate(1) vault = self.nodes[0].getvault(self.vaultId7, verbose) @@ -797,7 +799,7 @@ def payback_interests_and_continue_with_negative_interest(self): def let_loan_be_paid_by_negative_interests(self): verbose = True # set negative high negative interest for testing - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.iddUSD}/loan_minting_interest':'-1000000'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.iddUSD}/loan_minting_interest': '-1000000'}}) self.nodes[0].generate(1) # Brand new vault with new account associated @@ -812,11 +814,11 @@ def let_loan_be_paid_by_negative_interests(self): self.nodes[0].generate(1) # Take loan self.nodes[0].takeloan({ - 'vaultId': self.vaultId8, - 'amounts': "5@" + self.symboldUSD}) + 'vaultId': self.vaultId8, + 'amounts': "5@" + self.symboldUSD}) self.nodes[0].generate(1) # let the interest payback the full loan - self.nodes[0].generate(104) # Just one block before loan is fully paid + self.nodes[0].generate(104) # Just one block before loan is fully paid accountInfo = self.nodes[0].getaccount(self.account1) assert_equal(accountInfo, ['5.00000000@DUSD']) vault = self.nodes[0].getvault(self.vaultId8, verbose) @@ -839,7 +841,7 @@ def let_loan_be_paid_by_negative_interests(self): vault = self.nodes[0].getvault(self.vaultId8) except JSONRPCException as e: errorString = e.error['message'] - assert("not found" in errorString) + assert ("not found" in errorString) # Revert self.rollback_to(block) @@ -855,8 +857,8 @@ def let_loan_be_paid_by_negative_interests(self): self.nodes[0].generate(10) # Test take loan after loan is paid back self.nodes[0].takeloan({ - 'vaultId': self.vaultId8, - 'amounts': "5@" + self.symboldUSD}) + 'vaultId': self.vaultId8, + 'amounts': "5@" + self.symboldUSD}) self.nodes[0].generate(1) accountInfo = self.nodes[0].getaccount(self.account1) @@ -872,24 +874,25 @@ def let_loan_be_paid_by_negative_interests(self): self.nodes[0].generate(10) self.nodes[0].takeloan({ - 'vaultId': self.vaultId8, - 'amounts': "0.00000001@" + self.symboldUSD}) + 'vaultId': self.vaultId8, + 'amounts': "0.00000001@" + self.symboldUSD}) self.nodes[0].generate(1) storedLoans1 = self.nodes[0].getloantokens(self.vaultId8) storedAmount1 = getDecimalAmount(storedLoans1[0]) storedInterest1 = self.nodes[0].getstoredinterest(self.vaultId8, self.symboldUSD) - - assert(storedAmount > storedAmount1) - expectedAmount = Decimal(Decimal('5') + 11 * Decimal(storedInterest["interestPerBlock"]) + Decimal('0.00000001')).quantize(Decimal('1E-8'), ROUND_UP) - assert_equal(storedAmount1, expectedAmount) #4.47678897 + assert (storedAmount > storedAmount1) + expectedAmount = Decimal( + Decimal('5') + 11 * Decimal(storedInterest["interestPerBlock"]) + Decimal('0.00000001')).quantize( + Decimal('1E-8'), ROUND_UP) + assert_equal(storedAmount1, expectedAmount) # 4.47678897 assert_equal(storedInterest1["interestPerBlock"], '-0.042587371510759417808219') assert_equal(storedInterest1["interestToHeight"], '0.000000000000000000000000') def various_payback_tests(self): verbose = True # set negative high negative interest for testing - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.iddUSD}/loan_minting_interest':'-1000000'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.iddUSD}/loan_minting_interest': '-1000000'}}) self.nodes[0].generate(1) # Brand new vault with new account associated @@ -904,8 +907,8 @@ def various_payback_tests(self): self.nodes[0].generate(1) # Take loan self.nodes[0].takeloan({ - 'vaultId': self.vaultId9, - 'amounts': "10@" + self.symboldUSD}) + 'vaultId': self.vaultId9, + 'amounts': "10@" + self.symboldUSD}) self.nodes[0].generate(10) accountInfo = self.nodes[0].getaccount(self.account) @@ -923,13 +926,13 @@ def various_payback_tests(self): # payback overpay self.nodes[0].paybackloan({ - 'vaultId': self.vaultId9, - 'from': self.account, - 'amounts': ["10@" + self.symboldUSD]}) + 'vaultId': self.vaultId9, + 'from': self.account, + 'amounts': ["10@" + self.symboldUSD]}) self.nodes[0].generate(1) vault = self.nodes[0].getvault(self.vaultId9, verbose) - assert_equal(vault["loanAmounts"],[]) + assert_equal(vault["loanAmounts"], []) storedLoans1 = self.nodes[0].getloantokens(self.vaultId9) assert_equal(storedLoans1, []) @@ -938,8 +941,8 @@ def various_payback_tests(self): # Take loan self.nodes[0].takeloan({ - 'vaultId': self.vaultId9, - 'amounts': "10@" + self.symboldUSD}) + 'vaultId': self.vaultId9, + 'amounts': "10@" + self.symboldUSD}) self.nodes[0].generate(10) accountInfo = self.nodes[0].getaccount(self.account) @@ -958,9 +961,9 @@ def various_payback_tests(self): # payback 1 satoshi self.nodes[0].paybackloan({ - 'vaultId': self.vaultId9, - 'from': self.account, - 'amounts': ["0.00000001@" + self.symboldUSD]}) + 'vaultId': self.vaultId9, + 'from': self.account, + 'amounts': ["0.00000001@" + self.symboldUSD]}) self.nodes[0].generate(1) vault = self.nodes[0].getvault(self.vaultId9, verbose) @@ -971,7 +974,9 @@ def various_payback_tests(self): storedLoans1 = self.nodes[0].getloantokens(self.vaultId9) storedAmount1 = getDecimalAmount(storedLoans1[0]) - expectedAmount = Decimal(Decimal('10') + 10 * Decimal(storedInterest["interestPerBlock"]) - Decimal('0.00000001')).quantize(Decimal('1E-8'), ROUND_UP) + expectedAmount = Decimal( + Decimal('10') + 10 * Decimal(storedInterest["interestPerBlock"]) - Decimal('0.00000001')).quantize( + Decimal('1E-8'), ROUND_UP) assert_equal(storedAmount1, expectedAmount) [balanceDUSDafter, _] = self.nodes[0].getaccount(self.account)[0].split('@') @@ -982,9 +987,9 @@ def various_payback_tests(self): # payback 1 coin self.nodes[0].paybackloan({ - 'vaultId': self.vaultId9, - 'from': self.account, - 'amounts': ["1.00000000@" + self.symboldUSD]}) + 'vaultId': self.vaultId9, + 'from': self.account, + 'amounts': ["1.00000000@" + self.symboldUSD]}) self.nodes[0].generate(1) vault = self.nodes[0].getvault(self.vaultId9, verbose) @@ -1016,5 +1021,6 @@ def run_test(self): self.let_loan_be_paid_by_negative_interests() self.various_payback_tests() + if __name__ == '__main__': NegativeInterestTest().main() diff --git a/test/functional/feature_negative_loan_interest.py b/test/functional/feature_negative_loan_interest.py index 0529d8003a..0cae6964ce 100755 --- a/test/functional/feature_negative_loan_interest.py +++ b/test/functional/feature_negative_loan_interest.py @@ -12,12 +12,15 @@ import time import calendar -class NegativeInterestTest (DefiTestFramework): + +class NegativeInterestTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True self.extra_args = [ - ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', '-fortcanninghillheight=1', '-fortcanningcrunchheight=1', '-fortcanninggreatworldheight=1', '-fortcanningepilogueheight=1','-jellyfish_regtest=1', '-simulatemainnet=1', '-negativeinterest=1']] + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', + '-fortcanninghillheight=1', '-fortcanningcrunchheight=1', '-fortcanninggreatworldheight=1', + '-fortcanningepilogueheight=1', '-jellyfish_regtest=1', '-simulatemainnet=1', '-negativeinterest=1']] def run_test(self): # Create tokens for tests @@ -65,7 +68,6 @@ def setup_test_tokens(self): self.nodes[0].generate(1) def setup_test_pools(self): - # Create pool pair self.nodes[0].createpoolpair({ "tokenA": self.symbolDFI, @@ -81,11 +83,10 @@ def setup_test_pools(self): self.address: [ '10000@' + self.symbolDFI, '10000@' + self.symbolDUSD] - }, self.address) + }, self.address) self.nodes[0].generate(1) def setup_test_oracles(self): - # Create Oracle address oracle_address = self.nodes[0].getnewaddress("", "legacy") @@ -122,14 +123,13 @@ def setup_test_oracles(self): # Set collateral tokens self.nodes[0].setcollateraltoken({ - 'token': self.symbolDFI, - 'factor': 1, - 'fixedIntervalPriceId': "DFI/USD" - }) + 'token': self.symbolDFI, + 'factor': 1, + 'fixedIntervalPriceId': "DFI/USD" + }) self.nodes[0].generate(120) def test_negative_interest(self): - # Create vault vault_address = self.nodes[0].getnewaddress('', 'legacy') vault_id = self.nodes[0].createvault(vault_address, 'LOAN001') @@ -144,11 +144,11 @@ def test_negative_interest(self): self.nodes[0].generate(1) # Set negative interest rate to cancel out scheme interest - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'-5'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '-5'}}) self.nodes[0].generate(1) # Take DUSD loan - self.nodes[0].takeloan({ "vaultId": vault_id, "amounts": f"1@{self.symbolDUSD}"}) + self.nodes[0].takeloan({"vaultId": vault_id, "amounts": f"1@{self.symbolDUSD}"}) self.nodes[0].generate(1) # Check stored interest is nil @@ -158,7 +158,7 @@ def test_negative_interest(self): assert_equal(stored_interest['height'], self.nodes[0].getblockcount()) # Set overall negative interest rate to -5 - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'-10'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '-10'}}) self.nodes[0].generate(1) # Check stored interest @@ -172,7 +172,7 @@ def test_negative_interest(self): assert_equal(vault['interestAmounts'], [f'-0.00000004@{self.symbolDUSD}']) # Take DUSD loan - self.nodes[0].takeloan({ "vaultId": vault_id, "amounts": f"1@{self.symbolDUSD}"}) + self.nodes[0].takeloan({"vaultId": vault_id, "amounts": f"1@{self.symbolDUSD}"}) self.nodes[0].generate(1) # Check IPB doubled and ITH wiped @@ -206,7 +206,7 @@ def test_negative_interest(self): assert_equal(Decimal(balanceDUSDafter), Decimal(balanceDUSDbefore) - Decimal('1.9999')) # Set negative interest rate very high to speed up negating vault amount - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'-8000000'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '-8000000'}}) self.nodes[0].generate(20) # Check loan amount and interest fully negated @@ -222,5 +222,6 @@ def test_negative_interest(self): attrs = self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'] assert_equal(attrs['v0/live/economy/negative_interest'], [f'0.00010000@{self.symbolDUSD}']) + if __name__ == '__main__': NegativeInterestTest().main() diff --git a/test/functional/feature_notifications.py b/test/functional/feature_notifications.py index c6241d1b62..2f75dcc2e8 100755 --- a/test/functional/feature_notifications.py +++ b/test/functional/feature_notifications.py @@ -25,17 +25,18 @@ def setup_network(self): # -alertnotify and -blocknotify on node0, walletnotify on node1 self.extra_args = [[ - "-alertnotify=echo > {}".format(os.path.join(self.alertnotify_dir, '%s')), - "-blocknotify=echo > {}".format(os.path.join(self.blocknotify_dir, '%s'))], - ["-blockversion=211", - "-rescan", - "-walletnotify=echo > {}".format(os.path.join(self.walletnotify_dir, '%s'))]] + "-alertnotify=echo > {}".format(os.path.join(self.alertnotify_dir, '%s')), + "-blocknotify=echo > {}".format(os.path.join(self.blocknotify_dir, '%s'))], + ["-blockversion=211", + "-rescan", + "-walletnotify=echo > {}".format(os.path.join(self.walletnotify_dir, '%s'))]] super().setup_network() def run_test(self): self.log.info("test -blocknotify") block_count = 10 - blocks = self.nodes[1].generate(nblocks=block_count, address=self.nodes[1].getnewaddress() if self.is_wallet_compiled() else ADDRESS_BCRT1_UNSPENDABLE) + blocks = self.nodes[1].generate(nblocks=block_count, address=self.nodes[ + 1].getnewaddress() if self.is_wallet_compiled() else ADDRESS_BCRT1_UNSPENDABLE) # wait at most 10 seconds for expected number of files before reading the content wait_until(lambda: len(os.listdir(self.blocknotify_dir)) == block_count, timeout=10) @@ -46,10 +47,11 @@ def run_test(self): if self.is_wallet_compiled(): self.log.info("test -walletnotify") # wait at most 10 seconds for expected number of files before reading the content - wait_until(lambda: len(os.listdir(self.walletnotify_dir)) == block_count+1, timeout=10) # block_count+1 due to +1 genesis mn tx + wait_until(lambda: len(os.listdir(self.walletnotify_dir)) == block_count + 1, + timeout=10) # block_count+1 due to +1 genesis mn tx # directory content should equal the generated transaction hashes - txids_rpc = list(map(lambda t: t['txid'], self.nodes[1].listtransactions("*", block_count+1))) + txids_rpc = list(map(lambda t: t['txid'], self.nodes[1].listtransactions("*", block_count + 1))) assert_equal(sorted(txids_rpc), sorted(os.listdir(self.walletnotify_dir))) self.stop_node(1) for tx_file in os.listdir(self.walletnotify_dir): @@ -60,13 +62,14 @@ def run_test(self): self.start_node(1) connect_nodes_bi(self.nodes, 0, 1) - wait_until(lambda: len(os.listdir(self.walletnotify_dir)) == block_count+1, timeout=10) + wait_until(lambda: len(os.listdir(self.walletnotify_dir)) == block_count + 1, timeout=10) # directory content should equal the generated transaction hashes - txids_rpc = list(map(lambda t: t['txid'], self.nodes[1].listtransactions("*", block_count+1))) + txids_rpc = list(map(lambda t: t['txid'], self.nodes[1].listtransactions("*", block_count + 1))) assert_equal(sorted(txids_rpc), sorted(os.listdir(self.walletnotify_dir))) # TODO: add test for `-alertnotify` large fork notifications + if __name__ == '__main__': NotificationsTest().main() diff --git a/test/functional/feature_nulldummy.py b/test/functional/feature_nulldummy.py index 6d6e3737aa..914009d4b2 100755 --- a/test/functional/feature_nulldummy.py +++ b/test/functional/feature_nulldummy.py @@ -20,6 +20,7 @@ NULLDUMMY_ERROR = "non-mandatory-script-verify-flag (Dummy CHECKMULTISIG argument must be zero) (code 64)" + def trueDummy(tx): scriptSig = CScript(tx.vin[0].scriptSig) newscript = [] @@ -32,6 +33,7 @@ def trueDummy(tx): tx.vin[0].scriptSig = CScript(newscript) tx.rehash() + class NULLDUMMYTest(DefiTestFramework): def set_test_params(self): @@ -60,7 +62,8 @@ def run_test(self): self.lastblockheight = 429 self.lastblocktime = self.nodes[0].getblockheader(self.lastblockhash)["time"] - self.log.info("Test 1: NULLDUMMY compliant base transactions should be accepted to mempool and mined before activation [430]") + self.log.info( + "Test 1: NULLDUMMY compliant base transactions should be accepted to mempool and mined before activation [430]") test1txs = [create_transaction(self.nodes[0], coinbase_txid[0], self.ms_address, amount=49)] txid1 = self.nodes[0].sendrawtransaction(test1txs[0].serialize_with_witness().hex(), 0) test1txs.append(create_transaction(self.nodes[0], txid1, self.ms_address, amount=48)) @@ -69,10 +72,12 @@ def run_test(self): txid3 = self.nodes[0].sendrawtransaction(test1txs[2].serialize_with_witness().hex(), 0) self.block_submit(self.nodes[0], test1txs, False, True) - self.log.info("Test 2: Non-NULLDUMMY base multisig transaction should not be accepted to mempool before activation") + self.log.info( + "Test 2: Non-NULLDUMMY base multisig transaction should not be accepted to mempool before activation") test2tx = create_transaction(self.nodes[0], txid2, self.ms_address, amount=47) trueDummy(test2tx) - assert_raises_rpc_error(-26, NULLDUMMY_ERROR, self.nodes[0].sendrawtransaction, test2tx.serialize_with_witness().hex(), 0) + assert_raises_rpc_error(-26, NULLDUMMY_ERROR, self.nodes[0].sendrawtransaction, + test2tx.serialize_with_witness().hex(), 0) self.log.info("Test 3: Non-NULLDUMMY base transactions should be accepted in a block before activation [431]") self.block_submit(self.nodes[0], [test2tx], False, True) @@ -81,17 +86,20 @@ def run_test(self): test4tx = create_transaction(self.nodes[0], test2tx.hash, self.address, amount=46) test6txs = [CTransaction(test4tx)] trueDummy(test4tx) - assert_raises_rpc_error(-26, NULLDUMMY_ERROR, self.nodes[0].sendrawtransaction, test4tx.serialize_with_witness().hex(), 0) + assert_raises_rpc_error(-26, NULLDUMMY_ERROR, self.nodes[0].sendrawtransaction, + test4tx.serialize_with_witness().hex(), 0) self.block_submit(self.nodes[0], [test4tx]) self.log.info("Test 5: Non-NULLDUMMY P2WSH multisig transaction invalid after activation") test5tx = create_transaction(self.nodes[0], txid3, self.wit_address, amount=48) test6txs.append(CTransaction(test5tx)) test5tx.wit.vtxinwit[0].scriptWitness.stack[0] = b'\x01' - assert_raises_rpc_error(-26, NULLDUMMY_ERROR, self.nodes[0].sendrawtransaction, test5tx.serialize_with_witness().hex(), 0) + assert_raises_rpc_error(-26, NULLDUMMY_ERROR, self.nodes[0].sendrawtransaction, + test5tx.serialize_with_witness().hex(), 0) self.block_submit(self.nodes[0], [test5tx], True) - self.log.info("Test 6: NULLDUMMY compliant base/witness transactions should be accepted to mempool and in block after activation [432]") + self.log.info( + "Test 6: NULLDUMMY compliant base/witness transactions should be accepted to mempool and in block after activation [432]") for i in test6txs: self.nodes[0].sendrawtransaction(i.serialize_with_witness().hex(), 0) self.block_submit(self.nodes[0], test6txs, True, True) @@ -116,5 +124,6 @@ def block_submit(self, node, txs, witness=False, accept=False): else: assert_equal(node.getbestblockhash(), self.lastblockhash) + if __name__ == '__main__': NULLDUMMYTest().main() diff --git a/test/functional/feature_on_chain_government.py b/test/functional/feature_on_chain_government.py index 23b5c88c0d..2d4a2e0123 100755 --- a/test/functional/feature_on_chain_government.py +++ b/test/functional/feature_on_chain_government.py @@ -14,6 +14,7 @@ from decimal import Decimal + class OnChainGovernanceTest(DefiTestFramework): mns = None proposalId = "" @@ -22,10 +23,22 @@ def set_test_params(self): self.num_nodes = 4 self.setup_clean_chain = True self.extra_args = [ - ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', '-fortcanningepilogueheight=96', '-grandcentralheight=101', '-subsidytest=1', '-txindex=1'], - ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', '-fortcanningepilogueheight=96', '-grandcentralheight=101', '-subsidytest=1'], - ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', '-fortcanningepilogueheight=96', '-grandcentralheight=101', '-subsidytest=1'], - ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', '-fortcanningepilogueheight=96', '-grandcentralheight=101', '-subsidytest=1'], + ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', + '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', + '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', + '-fortcanningepilogueheight=96', '-grandcentralheight=101', '-subsidytest=1', '-txindex=1'], + ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', + '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', + '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', + '-fortcanningepilogueheight=96', '-grandcentralheight=101', '-subsidytest=1'], + ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', + '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', + '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', + '-fortcanningepilogueheight=96', '-grandcentralheight=101', '-subsidytest=1'], + ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', + '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', + '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', + '-fortcanningepilogueheight=96', '-grandcentralheight=101', '-subsidytest=1'], ] def run_test(self): @@ -73,10 +86,13 @@ def run_test(self): context = "" # check that on-chain governance is disabled - assert_raises_rpc_error(-32600, "Cannot create tx, on-chain governance is not enabled", self.nodes[0].creategovcfp, {"title": "test", "context": context, "amount": 100, "cycles": 4, "payoutAddress": address}) + assert_raises_rpc_error(-32600, "Cannot create tx, on-chain governance is not enabled", + self.nodes[0].creategovcfp, + {"title": "test", "context": context, "amount": 100, "cycles": 4, + "payoutAddress": address}) # activate on-chain governance - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/feature/gov':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/feature/gov': 'true'}}) self.nodes[0].generate(1) self.sync_blocks() @@ -87,8 +103,12 @@ def run_test(self): assert_equal(result['nonutxo'][0]['CommunityDevelopmentFunds'], Decimal('19.88746400')) # Check errors - assert_raises_rpc_error(-32600, "proposal cycles can be between 1 and 100", self.nodes[0].creategovcfp, {"title": "test", "context": context, "amount": 100, "cycles": 101, "payoutAddress": address}) - assert_raises_rpc_error(-32600, "proposal cycles can be between 1 and 100", self.nodes[0].creategovcfp, {"title": "test", "context": context, "amount": 100, "cycles": 0, "payoutAddress": address}) + assert_raises_rpc_error(-32600, "proposal cycles can be between 1 and 100", self.nodes[0].creategovcfp, + {"title": "test", "context": context, "amount": 100, "cycles": 101, + "payoutAddress": address}) + assert_raises_rpc_error(-32600, "proposal cycles can be between 1 and 100", self.nodes[0].creategovcfp, + {"title": "test", "context": context, "amount": 100, "cycles": 0, + "payoutAddress": address}) # Check burn empty assert_equal(self.nodes[0].getburninfo()['feeburn'], 0) @@ -96,10 +116,11 @@ def run_test(self): title = "Create test community fund request proposal" # Test invalid title try: - self.nodes[0].creategovcfp({"title":"a" * 129, "context": context, "amount":100, "cycles":2, "payoutAddress":address}) + self.nodes[0].creategovcfp( + {"title": "a" * 129, "context": context, "amount": 100, "cycles": 2, "payoutAddress": address}) except JSONRPCException as e: errorString = e.error['message'] - assert("proposal title cannot be more than 128 bytes" in errorString) + assert ("proposal title cannot be more than 128 bytes" in errorString) # Test invalid context try: @@ -107,7 +128,7 @@ def run_test(self): {"title": title, "context": "a" * 513, "amount": 100, "cycles": 2, "payoutAddress": address}) except JSONRPCException as e: errorString = e.error['message'] - assert("proposal context cannot be more than 512 bytes" in errorString) + assert ("proposal context cannot be more than 512 bytes" in errorString) # Test invalid keys try: @@ -115,19 +136,20 @@ def run_test(self): {"title": title, "context": "a", "amount": 100, "cycle": 2, "payoutAddress": address}) except JSONRPCException as e: errorString = e.error['message'] - assert("Unexpected key cycle" in errorString) + assert ("Unexpected key cycle" in errorString) try: self.nodes[0].creategovvoc( {"title": title, "context": "a", "amounts": 100}) except JSONRPCException as e: errorString = e.error['message'] - assert("Unexpected key amounts" in errorString) + assert ("Unexpected key amounts" in errorString) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/gov/proposals/fee_redistribution':'true'}}) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/feature/gov-payout':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/gov/proposals/fee_redistribution': 'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/feature/gov-payout': 'true'}}) # Create CFP - cfp1 = self.nodes[0].creategovcfp({"title": title, "context": context, "amount": 100, "cycles": 2, "payoutAddress": address}) + cfp1 = self.nodes[0].creategovcfp( + {"title": title, "context": context, "amount": 100, "cycles": 2, "payoutAddress": address}) # Fund addresses self.nodes[0].sendtoaddress(address1, Decimal("1.0")) self.nodes[0].sendtoaddress(address2, Decimal("1.0")) @@ -147,7 +169,9 @@ def run_test(self): # cannot vote by non owning masternode assert_raises_rpc_error(-5, "Incorrect authorization", self.nodes[0].votegov, cfp1, mn1, "yes") - assert_raises_rpc_error(-8, "Decision supports yes or no. Neutral is currently disabled because of issue https://github.com/DeFiCh/ain/issues/1704", self.nodes[0].votegov, cfp1, mn0, "neutral") + assert_raises_rpc_error(-8, + "Decision supports yes or no. Neutral is currently disabled because of issue https://github.com/DeFiCh/ain/issues/1704", + self.nodes[0].votegov, cfp1, mn0, "neutral") # Vote on proposal self.nodes[0].votegov(cfp1, mn0, "yes") @@ -231,10 +255,11 @@ def run_test(self): assert_equal(blockcount, cycle1) # First cycle should last for at least a votingPeriod - assert(cycle1 - creationHeight >= votingPeriod) + assert (cycle1 - creationHeight >= votingPeriod) # CommunityDevelopmentFunds is charged by proposal - assert_equal(self.nodes[0].listcommunitybalances()['CommunityDevelopmentFunds'], bal + Decimal("19.887464") - Decimal(100)) + assert_equal(self.nodes[0].listcommunitybalances()['CommunityDevelopmentFunds'], + bal + Decimal("19.887464") - Decimal(100)) # payout address assert_equal(self.nodes[1].getaccount(address), ['100.00000000@DFI']) @@ -358,10 +383,10 @@ def run_test(self): assert_equal(self.nodes[0].listgovproposals("all", "completed"), []) assert_equal(len(self.nodes[0].listgovproposals("all", "rejected")), 1) - self.nodes[0].setgov({"ATTRIBUTES":{ - 'v0/params/feature/gov-payout':'false', - 'v0/gov/proposals/cfp_fee':'0.25', - 'v0/gov/proposals/voting_period':'100', + self.nodes[0].setgov({"ATTRIBUTES": { + 'v0/params/feature/gov-payout': 'false', + 'v0/gov/proposals/cfp_fee': '0.25', + 'v0/gov/proposals/voting_period': '100', }}) votingPeriod = 100 @@ -372,10 +397,10 @@ def run_test(self): # Create CFP propId = self.nodes[0].creategovcfp({"title": title, - "context": context, - "amount": 50, - "cycles": 2, - "payoutAddress": address}) + "context": context, + "amount": 50, + "cycles": 2, + "payoutAddress": address}) self.nodes[0].generate(1) creationHeight = self.nodes[0].getblockcount() @@ -411,7 +436,7 @@ def run_test(self): proposalEndHeight = cycle1 + votingPeriod # Check proposal and votes - results = self.nodes[0].listgovproposals("cfp","voting") + results = self.nodes[0].listgovproposals("cfp", "voting") result = results[0] assert_equal(result["proposalId"], propId) assert_equal(result["creationHeight"], creationHeight) @@ -491,7 +516,6 @@ def run_test(self): listvotes = self.nodes[0].listgovproposalvotes(propId, 'all', 2) assert_equal(len(listvotes), 1) - # Move to just before final height self.nodes[0].generate(proposalEndHeight - self.nodes[0].getblockcount() - 1) bal = self.nodes[0].listcommunitybalances()['CommunityDevelopmentFunds'] @@ -507,7 +531,7 @@ def run_test(self): assert_equal(self.nodes[0].listcommunitybalances()['CommunityDevelopmentFunds'], bal + Decimal("19.23346268")) # not votes on 2nd cycle makes proposal to rejected - result = self.nodes[0].listgovproposals({"pagination":{"start": propId, "including_start":True}})[0] + result = self.nodes[0].listgovproposals({"pagination": {"start": propId, "including_start": True}})[0] assert_equal(result["status"], "Rejected") # No proposals pending @@ -518,11 +542,11 @@ def run_test(self): emergencyPeriod = 25 title = 'Emergency VOC' - self.nodes[0].setgov({"ATTRIBUTES":{ - 'v0/params/feature/gov-payout':'true', + self.nodes[0].setgov({"ATTRIBUTES": { + 'v0/params/feature/gov-payout': 'true', 'v0/gov/proposals/voc_emergency_period': f'{emergencyPeriod}', - 'v0/gov/proposals/voc_emergency_fee':'20.00000000', - 'v0/gov/proposals/voc_approval_threshold':'50.00%' + 'v0/gov/proposals/voc_emergency_fee': '20.00000000', + 'v0/gov/proposals/voc_approval_threshold': '50.00%' }}) self.nodes[0].generate(1) self.sync_blocks() @@ -592,13 +616,15 @@ def run_test(self): assert_equal(len(self.nodes[0].listgovproposals("all", "rejected")), 2) # Test emergency quorum - self.nodes[0].setgov({"ATTRIBUTES":{ - 'v0/gov/proposals/voc_emergency_quorum':'80.01%' + self.nodes[0].setgov({"ATTRIBUTES": { + 'v0/gov/proposals/voc_emergency_quorum': '80.01%' }}) self.nodes[0].generate(1) self.sync_blocks() - tx = self.nodes[0].creategovvoc({"title": "Create vote of confidence custom fee custom majority", "context": "test context", "special": True}) + tx = self.nodes[0].creategovvoc( + {"title": "Create vote of confidence custom fee custom majority", "context": "test context", + "special": True}) self.nodes[0].generate(1) self.sync_blocks() @@ -626,90 +652,111 @@ def run_test(self): assert_equal(len(self.nodes[0].listgovproposals("all", "completed")), 1) assert_equal(len(self.nodes[0].listgovproposals("all", "rejected")), 4) - assert_equal(len(self.nodes[0].listgovproposals("all", "rejected", 0, {"limit":1})), 1) - assert_equal(len(self.nodes[0].listgovproposals("all", "rejected", 0, {"limit":0})), 4) - assert_equal(len(self.nodes[0].listgovproposals("all", "rejected", 0, {"limit":10})), 4) - assert_equal(self.nodes[0].listgovproposals("all", "rejected", 0, {"start": tx, "including_start": True})[0]["proposalId"], tx) + assert_equal(len(self.nodes[0].listgovproposals("all", "rejected", 0, {"limit": 1})), 1) + assert_equal(len(self.nodes[0].listgovproposals("all", "rejected", 0, {"limit": 0})), 4) + assert_equal(len(self.nodes[0].listgovproposals("all", "rejected", 0, {"limit": 10})), 4) + assert_equal(self.nodes[0].listgovproposals("all", "rejected", 0, {"start": tx, "including_start": True})[0][ + "proposalId"], tx) - assert_equal(len(self.nodes[0].listgovproposals({"type":"all", "status":"voting"})), 0) - assert_equal(len(self.nodes[0].listgovproposals({"type":"all", "status":"completed"})), 1) - assert_equal(len(self.nodes[0].listgovproposals({"type":"all", "status":"rejected"})), 4) + assert_equal(len(self.nodes[0].listgovproposals({"type": "all", "status": "voting"})), 0) + assert_equal(len(self.nodes[0].listgovproposals({"type": "all", "status": "completed"})), 1) + assert_equal(len(self.nodes[0].listgovproposals({"type": "all", "status": "rejected"})), 4) - assert_equal(len(self.nodes[0].listgovproposals({"type":"all", "status":"rejected", "pagination": {"limit":1}})), 1) - assert_equal(len(self.nodes[0].listgovproposals({"type":"all", "status":"rejected", "pagination": {"limit":0}})), 4) - assert_equal(len(self.nodes[0].listgovproposals({"type":"all", "status":"rejected", "pagination": {"limit":10}})), 4) - assert_equal(self.nodes[0].listgovproposals({"type":"all", "status":"rejected", "pagination": {"start": tx, "including_start": True}})[0]["proposalId"], tx) + assert_equal( + len(self.nodes[0].listgovproposals({"type": "all", "status": "rejected", "pagination": {"limit": 1}})), 1) + assert_equal( + len(self.nodes[0].listgovproposals({"type": "all", "status": "rejected", "pagination": {"limit": 0}})), 4) + assert_equal( + len(self.nodes[0].listgovproposals({"type": "all", "status": "rejected", "pagination": {"limit": 10}})), 4) + assert_equal(self.nodes[0].listgovproposals( + {"type": "all", "status": "rejected", "pagination": {"start": tx, "including_start": True}})[0][ + "proposalId"], tx) # Test pagination, total number of votes is 3 assert_equal(len(self.nodes[1].listgovproposalvotes( {"proposalId": tx, "masternode": "all", "cycle": -1, "pagination": {"start": 0}})), 2) assert_equal(len(self.nodes[1].listgovproposalvotes( {"proposalId": tx, "masternode": "all", "cycle": -1, "pagination": {"start": 0, "including_start": True}})), - 3) + 3) assert_equal( - len(self.nodes[1].listgovproposalvotes({"proposalId": tx, "masternode": "all", "cycle": -1, "pagination": {"start": 0, "including_start": True, "limit": 2}})), + len(self.nodes[1].listgovproposalvotes({"proposalId": tx, "masternode": "all", "cycle": -1, + "pagination": {"start": 0, "including_start": True, "limit": 2}})), 2) assert_equal( - len(self.nodes[1].listgovproposalvotes({"proposalId": tx, "masternode": "all", "cycle": -1, "pagination": {"start": 0, "including_start": True, "limit": 1}})), + len(self.nodes[1].listgovproposalvotes({"proposalId": tx, "masternode": "all", "cycle": -1, + "pagination": {"start": 0, "including_start": True, "limit": 1}})), 1) # should be empty if start > number of entries assert_equal( - len(self.nodes[1].listgovproposalvotes({"proposalId": tx, "masternode": "all", "cycle": -1, "pagination": {"start": 10, "including_start": True, "limit": 1}})), + len(self.nodes[1].listgovproposalvotes({"proposalId": tx, "masternode": "all", "cycle": -1, + "pagination": {"start": 10, "including_start": True, "limit": 1}})), 0) # should return all entries if limit is 0 assert_equal( - len(self.nodes[1].listgovproposalvotes({"proposalId": tx, "masternode": "all", "cycle": -1, "pagination": {"start": 0, "including_start": True, "limit": 0}})), + len(self.nodes[1].listgovproposalvotes({"proposalId": tx, "masternode": "all", "cycle": -1, + "pagination": {"start": 0, "including_start": True, "limit": 0}})), 3) # should return all entries if limit is 0 assert_equal( - len(self.nodes[1].listgovproposalvotes({"proposalId": tx, "masternode": "all", "cycle": -1, "pagination": {"start": 0, "including_start": False, "limit": 0}})), + len(self.nodes[1].listgovproposalvotes({"proposalId": tx, "masternode": "all", "cycle": -1, + "pagination": {"start": 0, "including_start": False, "limit": 0}})), 2) # should respect filters - assert_equal(len(self.nodes[1].listgovproposalvotes({"proposalId": tx, "masternode": mn1, "cycle": -1, "pagination": {"start": 0}})), 0) + assert_equal(len(self.nodes[1].listgovproposalvotes( + {"proposalId": tx, "masternode": mn1, "cycle": -1, "pagination": {"start": 0}})), 0) # test non-object RPC arguments assert_equal(len(self.nodes[0].listgovproposalvotes(propId, 'all', -1, {"limit": 2})), 2) tx1 = self.nodes[0].creategovcfp({"title": "1111", - "context": context, - "amount": 50, - "cycles": 1, - "payoutAddress": address}) + "context": context, + "amount": 50, + "cycles": 1, + "payoutAddress": address}) self.nodes[0].generate(1) self.sync_blocks() tx2 = self.nodes[0].creategovcfp({"title": "2222", - "context": context, - "amount": 50, - "cycles": 1, - "payoutAddress": address}) + "context": context, + "amount": 50, + "cycles": 1, + "payoutAddress": address}) self.nodes[0].generate(1) self.sync_blocks() tx3 = self.nodes[0].creategovcfp({"title": "3333", - "context": context, - "amount": 50, - "cycles": 1, - "payoutAddress": address}) + "context": context, + "amount": 50, + "cycles": 1, + "payoutAddress": address}) self.nodes[0].generate(1) self.sync_blocks() - assert_equal(self.nodes[0].listgovproposals({"cycle":1, "pagination": {"start": cfp1, "including_start": True, "limit": 1}})[0]["proposalId"], cfp1) - assert_equal(len(self.nodes[0].listgovproposals({"cycle":6})), 3) - assert_equal(self.nodes[0].listgovproposals({"cycle":6, "pagination": {"start": tx2, "including_start": True, "limit": 1}})[0]["proposalId"], tx2) - assert_equal(self.nodes[0].listgovproposals({"cycle":6, "pagination": {"start": tx3, "including_start": True, "limit": 1}})[0]["proposalId"], tx3) + assert_equal(self.nodes[0].listgovproposals( + {"cycle": 1, "pagination": {"start": cfp1, "including_start": True, "limit": 1}})[0]["proposalId"], cfp1) + assert_equal(len(self.nodes[0].listgovproposals({"cycle": 6})), 3) + assert_equal(self.nodes[0].listgovproposals( + {"cycle": 6, "pagination": {"start": tx2, "including_start": True, "limit": 1}})[0]["proposalId"], tx2) + assert_equal(self.nodes[0].listgovproposals( + {"cycle": 6, "pagination": {"start": tx3, "including_start": True, "limit": 1}})[0]["proposalId"], tx3) assert_equal(len(self.nodes[0].listgovproposals({"type": "cfp"})), 5) - assert_equal(self.nodes[0].listgovproposals({"type": "cfp", "pagination": {"start": cfp1, "including_start": True, "limit": 1}})[0]["proposalId"], cfp1) - assert_equal(self.nodes[0].listgovproposals({"type": "cfp", "pagination": {"start": tx2, "including_start": True, "limit": 1}})[0]["proposalId"], tx2) + assert_equal(self.nodes[0].listgovproposals( + {"type": "cfp", "pagination": {"start": cfp1, "including_start": True, "limit": 1}})[0]["proposalId"], cfp1) + assert_equal(self.nodes[0].listgovproposals( + {"type": "cfp", "pagination": {"start": tx2, "including_start": True, "limit": 1}})[0]["proposalId"], tx2) assert_equal(len(self.nodes[0].listgovproposals({"status": "voting"})), 3) - assert_equal(self.nodes[0].listgovproposals({"status": "voting", "pagination": {"start": tx1, "including_start": True, "limit": 1}})[0]["proposalId"], tx1) - assert_equal(self.nodes[0].listgovproposals({"status": "voting", "pagination": {"start": tx3, "including_start": True, "limit": 1}})[0]["proposalId"], tx3) + assert_equal(self.nodes[0].listgovproposals( + {"status": "voting", "pagination": {"start": tx1, "including_start": True, "limit": 1}})[0]["proposalId"], + tx1) + assert_equal(self.nodes[0].listgovproposals( + {"status": "voting", "pagination": {"start": tx3, "including_start": True, "limit": 1}})[0]["proposalId"], + tx3) allProposals = self.nodes[0].listgovproposals({"status": "voting"}) nextProposal = [] @@ -848,8 +895,9 @@ def test_valid_votes(self): validVotes = self.nodes[0].listgovproposalvotes(propId, "all", 1, {}, False, True) invalidVotes = self.nodes[0].listgovproposalvotes(propId, "all", 1, {}, False, False) - assert(self.mns[2] not in [x["masternodeId"] for x in validVotes]) + assert (self.mns[2] not in [x["masternodeId"] for x in validVotes]) assert_equal(self.mns[2], invalidVotes[0]["masternodeId"]) + if __name__ == '__main__': OnChainGovernanceTest().main() diff --git a/test/functional/feature_on_chain_government_fee_distribution.py b/test/functional/feature_on_chain_government_fee_distribution.py index d8b2bc26d3..eb6d99c152 100755 --- a/test/functional/feature_on_chain_government_fee_distribution.py +++ b/test/functional/feature_on_chain_government_fee_distribution.py @@ -11,20 +11,33 @@ ) from decimal import ROUND_DOWN, Decimal -VOTING_PERIOD=70 +VOTING_PERIOD = 70 + class CFPFeeDistributionTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 4 self.setup_clean_chain = True self.extra_args = [ - ['-dummypos=0', '-txnotokens=0', '-rpc-governance-accept-neutral', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', '-grandcentralheight=101'], - ['-dummypos=0', '-txnotokens=0', '-rpc-governance-accept-neutral', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', '-grandcentralheight=101'], - ['-dummypos=0', '-txnotokens=0', '-rpc-governance-accept-neutral', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', '-grandcentralheight=101'], - ['-dummypos=0', '-txnotokens=0', '-rpc-governance-accept-neutral', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', '-grandcentralheight=101'], + ['-dummypos=0', '-txnotokens=0', '-rpc-governance-accept-neutral', '-amkheight=50', '-bayfrontheight=51', + '-eunosheight=80', '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', + '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', + '-grandcentralheight=101'], + ['-dummypos=0', '-txnotokens=0', '-rpc-governance-accept-neutral', '-amkheight=50', '-bayfrontheight=51', + '-eunosheight=80', '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', + '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', + '-grandcentralheight=101'], + ['-dummypos=0', '-txnotokens=0', '-rpc-governance-accept-neutral', '-amkheight=50', '-bayfrontheight=51', + '-eunosheight=80', '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', + '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', + '-grandcentralheight=101'], + ['-dummypos=0', '-txnotokens=0', '-rpc-governance-accept-neutral', '-amkheight=50', '-bayfrontheight=51', + '-eunosheight=80', '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', + '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', + '-grandcentralheight=101'], ] - def test_cfp_fee_distribution(self, amount, expectedFee, burnPct, vote, cycles=2, changeFeeAndBurnPCT = False): + def test_cfp_fee_distribution(self, amount, expectedFee, burnPct, vote, cycles=2, changeFeeAndBurnPCT=False): height = self.nodes[0].getblockcount() # Create address for CFP @@ -32,7 +45,8 @@ def test_cfp_fee_distribution(self, amount, expectedFee, burnPct, vote, cycles=2 context = "" title = "Create test community fund request proposal without automatic payout" # Create CFP - propId = self.nodes[0].creategovcfp({"title": title, "context": context, "amount": amount, "cycles": cycles, "payoutAddress": address}) + propId = self.nodes[0].creategovcfp( + {"title": title, "context": context, "amount": amount, "cycles": cycles, "payoutAddress": address}) # Fund addresses self.nodes[0].sendtoaddress(self.address1, Decimal("1.0")) @@ -52,9 +66,9 @@ def test_cfp_fee_distribution(self, amount, expectedFee, burnPct, vote, cycles=2 assert_equal(self.nodes[0].getburninfo()['feeburn'], Decimal(expectedFee * burnPct / 100)) # increase the fee in the middle of CFP and check that refund to MNs didn't change - if (changeFeeAndBurnPCT) : - self.nodes[0].setgov({"ATTRIBUTES":{'v0/gov/proposals/cfp_fee':'0.05'}}) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/gov/proposals/fee_burn_pct':'40%'}}) + if (changeFeeAndBurnPCT): + self.nodes[0].setgov({"ATTRIBUTES": {'v0/gov/proposals/cfp_fee': '0.05'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/gov/proposals/fee_burn_pct': '40%'}}) self.nodes[0].generate(1) expectedAmount = Decimal(expectedFee * (100 - burnPct) / 100 / 3).quantize(Decimal('1E-8'), rounding=ROUND_DOWN) @@ -165,13 +179,13 @@ def run_test(self): self.test_cfp_fee_distribution(amount=1000, expectedFee=10, burnPct=50, vote="yes", changeFeeAndBurnPCT=True) self.test_cfp_fee_distribution(amount=1000, expectedFee=10, burnPct=50, vote="no", changeFeeAndBurnPCT=True) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/gov/proposals/fee_burn_pct':'30%'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/gov/proposals/fee_burn_pct': '30%'}}) self.nodes[0].generate(1) self.sync_blocks() self.test_cfp_fee_distribution(amount=1000, expectedFee=10, burnPct=30, vote="neutral") - self.nodes[0].setgov({"ATTRIBUTES":{'v0/gov/proposals/cfp_fee':'2%'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/gov/proposals/cfp_fee': '2%'}}) self.nodes[0].generate(1) self.sync_blocks() @@ -179,5 +193,6 @@ def run_test(self): self.test_cfp_fee_distribution(amount=1000, expectedFee=20, burnPct=30, vote="yes", cycles=3, changeFeeAndBurnPCT=True) + if __name__ == '__main__': - CFPFeeDistributionTest().main () + CFPFeeDistributionTest().main() diff --git a/test/functional/feature_on_chain_government_govvar_update.py b/test/functional/feature_on_chain_government_govvar_update.py index 210f8c5086..f1f10196c0 100755 --- a/test/functional/feature_on_chain_government_govvar_update.py +++ b/test/functional/feature_on_chain_government_govvar_update.py @@ -13,18 +13,31 @@ from decimal import ROUND_DOWN, Decimal VOTING_PERIOD = 70 -EMERGENCY_PERIOD=100 -EMERGENCY_FEE=0.1 +EMERGENCY_PERIOD = 100 +EMERGENCY_FEE = 0.1 + class CFPFeeDistributionTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 4 self.setup_clean_chain = True self.extra_args = [ - ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', '-grandcentralheight=101'], - ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', '-grandcentralheight=101'], - ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', '-grandcentralheight=101'], - ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', '-grandcentralheight=101'], + ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', + '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', + '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', + '-grandcentralheight=101'], + ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', + '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', + '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', + '-grandcentralheight=101'], + ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', + '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', + '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', + '-grandcentralheight=101'], + ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', + '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', + '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', + '-grandcentralheight=101'], ] def test_cfp_update_automatic_payout(self): @@ -36,7 +49,8 @@ def test_cfp_update_automatic_payout(self): title = "Create test community fund request proposal without automatic payout" amount = 100 # Create CFP - propId = self.nodes[0].creategovcfp({"title": title, "context": context, "amount": amount, "cycles": 2, "payoutAddress": address}) + propId = self.nodes[0].creategovcfp( + {"title": title, "context": context, "amount": amount, "cycles": 2, "payoutAddress": address}) # Fund addresses self.nodes[0].sendtoaddress(self.address1, Decimal("1.0")) @@ -68,16 +82,20 @@ def test_cfp_update_automatic_payout(self): self.sync_blocks(timeout=120) # Activate payout on second cycle - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/feature/gov-payout':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/feature/gov-payout': 'true'}}) self.nodes[0].generate(1) # Import MN keys into MN0 - self.nodes[0].importprivkey(self.nodes[1].dumpprivkey(self.nodes[0].getmasternode(self.mn1)[self.mn1]['ownerAuthAddress'])) - self.nodes[0].importprivkey(self.nodes[2].dumpprivkey(self.nodes[0].getmasternode(self.mn2)[self.mn2]['ownerAuthAddress'])) - self.nodes[0].importprivkey(self.nodes[3].dumpprivkey(self.nodes[0].getmasternode(self.mn3)[self.mn3]['ownerAuthAddress'])) + self.nodes[0].importprivkey( + self.nodes[1].dumpprivkey(self.nodes[0].getmasternode(self.mn1)[self.mn1]['ownerAuthAddress'])) + self.nodes[0].importprivkey( + self.nodes[2].dumpprivkey(self.nodes[0].getmasternode(self.mn2)[self.mn2]['ownerAuthAddress'])) + self.nodes[0].importprivkey( + self.nodes[3].dumpprivkey(self.nodes[0].getmasternode(self.mn3)[self.mn3]['ownerAuthAddress'])) # Vote during second cycle using multi-vote - self.nodes[0].votegovbatch([[propId, self.mn0, "yes"], [propId, self.mn1, "yes"], [propId, self.mn2, "yes"], [propId, self.mn3, "yes"]]) + self.nodes[0].votegovbatch([[propId, self.mn0, "yes"], [propId, self.mn1, "yes"], [propId, self.mn2, "yes"], + [propId, self.mn3, "yes"]]) self.nodes[0].generate(1) # End proposal @@ -103,7 +121,8 @@ def test_cfp_update_quorum(self): title = "Create test community fund request proposal without automatic payout" amount = 100 # Create CFP - propId = self.nodes[0].creategovcfp({"title": title, "context": context, "amount": amount, "cycles": 2, "payoutAddress": address}) + propId = self.nodes[0].creategovcfp( + {"title": title, "context": context, "amount": amount, "cycles": 2, "payoutAddress": address}) # Fund addresses self.nodes[0].sendtoaddress(self.address1, Decimal("1.0")) @@ -114,7 +133,7 @@ def test_cfp_update_quorum(self): # Update quorum during first cycle. # 80% of masternodes should vote - self.nodes[0].setgov({"ATTRIBUTES":{'v0/gov/proposals/quorum':'80%'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/gov/proposals/quorum': '80%'}}) self.nodes[0].generate(1) # Vote during first cycle @@ -167,7 +186,8 @@ def test_cfp_update_approval_threshold(self): title = "Create test community fund request proposal without automatic payout" amount = 100 # Create CFP - propId = self.nodes[0].creategovcfp({"title": title, "context": context, "amount": amount, "cycles": 2, "payoutAddress": address}) + propId = self.nodes[0].creategovcfp( + {"title": title, "context": context, "amount": amount, "cycles": 2, "payoutAddress": address}) # Fund addresses self.nodes[0].sendtoaddress(self.address1, Decimal("1.0")) @@ -178,7 +198,7 @@ def test_cfp_update_approval_threshold(self): # Update majority threshold during first cycle # 80% of masternodes should approve a CFP - self.nodes[0].setgov({"ATTRIBUTES":{'v0/gov/proposals/cfp_approval_threshold':'80%'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/gov/proposals/cfp_approval_threshold': '80%'}}) self.nodes[0].generate(1) # Vote during first cycle @@ -204,7 +224,7 @@ def test_cfp_update_approval_threshold(self): assert_equal(proposal['status'], 'Voting') # 80% of masternodes should approve a CFP - self.nodes[0].setgov({"ATTRIBUTES":{'v0/gov/proposals/cfp_approval_threshold':'0.8'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/gov/proposals/cfp_approval_threshold': '0.8'}}) self.nodes[0].generate(1) # Vote during second cycle @@ -240,7 +260,8 @@ def test_cfp_update_fee_redistribution(self): title = "Create test community fund request proposal without automatic payout" amount = 100 # Create CFP - propId = self.nodes[0].creategovcfp({"title": title, "context": context, "amount": amount, "cycles": 2, "payoutAddress": address}) + propId = self.nodes[0].creategovcfp( + {"title": title, "context": context, "amount": amount, "cycles": 2, "payoutAddress": address}) # Fund addresses self.nodes[0].sendtoaddress(self.address1, Decimal("1.0")) @@ -270,7 +291,7 @@ def test_cfp_update_fee_redistribution(self): account1 = self.nodes[0].getaccount(mn1['ownerAuthAddress']) assert_equal(account1, []) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/gov/proposals/fee_redistribution':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/gov/proposals/fee_redistribution': 'true'}}) self.nodes[0].generate(1) # Vote during second cycle @@ -307,7 +328,8 @@ def test_cfp_update_cfp_fee(self): title = "Create test community fund request proposal without automatic payout" amount = 100 # Create CFP - propId = self.nodes[0].creategovcfp({"title": title, "context": context, "amount": amount, "cycles": 2, "payoutAddress": address}) + propId = self.nodes[0].creategovcfp( + {"title": title, "context": context, "amount": amount, "cycles": 2, "payoutAddress": address}) # Fund addresses self.nodes[0].sendtoaddress(self.address1, Decimal("1.0")) @@ -329,8 +351,8 @@ def test_cfp_update_cfp_fee(self): self.sync_blocks(timeout=120) # Set higher fee - self.nodes[0].setgov({"ATTRIBUTES":{'v0/gov/proposals/cfp_fee':'50%'}}) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/gov/proposals/fee_redistribution':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/gov/proposals/cfp_fee': '50%'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/gov/proposals/fee_redistribution': 'true'}}) self.nodes[0].generate(1) # Vote during second cycle @@ -368,7 +390,8 @@ def test_cfp_update_voting_period(self): title = "Create test community fund request proposal without automatic payout" amount = 100 # Create CFP - propId = self.nodes[0].creategovcfp({"title": title, "context": context, "amount": amount, "cycles": 2, "payoutAddress": address}) + propId = self.nodes[0].creategovcfp( + {"title": title, "context": context, "amount": amount, "cycles": 2, "payoutAddress": address}) # Fund addresses self.nodes[0].sendtoaddress(self.address1, Decimal("1.0")) @@ -389,7 +412,7 @@ def test_cfp_update_voting_period(self): self.sync_blocks(timeout=120) # Set higher fee - self.nodes[0].setgov({"ATTRIBUTES":{'v0/gov/proposals/voting_period': '200'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/gov/proposals/voting_period': '200'}}) self.nodes[0].generate(1) # Vote during second cycle @@ -421,7 +444,7 @@ def test_cfp_update_voc_emergency_period(self): self.sync_blocks(timeout=120) # Set longer emergency period - self.nodes[0].setgov({"ATTRIBUTES":{'v0/gov/proposals/voc_emergency_period': str(EMERGENCY_PERIOD * 2)}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/gov/proposals/voc_emergency_period': str(EMERGENCY_PERIOD * 2)}}) self.nodes[0].generate(1) # Move to next cycle @@ -450,8 +473,8 @@ def test_cfp_update_voc_emergency_fee(self): self.sync_blocks(timeout=120) # Set higher fee - self.nodes[0].setgov({"ATTRIBUTES":{'v0/gov/proposals/voc_emergency_fee': str(EMERGENCY_FEE * 2)}}) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/gov/proposals/fee_redistribution': 'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/gov/proposals/voc_emergency_fee': str(EMERGENCY_FEE * 2)}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/gov/proposals/fee_redistribution': 'true'}}) self.nodes[0].generate(1) self.nodes[0].votegov(propId, self.mn0, "yes") @@ -488,7 +511,8 @@ def test_cfp_state_after_update(self): title = "Create test community fund request proposal without automatic payout" amount = 100 # Create CFP - propId = self.nodes[0].creategovcfp({"title": title, "context": context, "amount": amount, "cycles": 1, "payoutAddress": address}) + propId = self.nodes[0].creategovcfp( + {"title": title, "context": context, "amount": amount, "cycles": 1, "payoutAddress": address}) # Fund addresses self.nodes[0].sendtoaddress(self.address1, Decimal("1.0")) @@ -519,7 +543,7 @@ def test_cfp_state_after_update(self): # Update quorum after end of proposal. # 80% of masternodes should vote - self.nodes[0].setgov({"ATTRIBUTES":{'v0/gov/proposals/cfp_approval_threshold':'80%'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/gov/proposals/cfp_approval_threshold': '80%'}}) self.nodes[0].generate(1) # Attributes change should not impact state of resolved proposals @@ -562,8 +586,8 @@ def setup(self): self.sync_blocks(timeout=120) # activate on-chain governance - self.nodes[0].setgov({"ATTRIBUTES":{ - 'v0/params/feature/gov':'true', + self.nodes[0].setgov({"ATTRIBUTES": { + 'v0/params/feature/gov': 'true', 'v0/gov/proposals/voting_period': str(VOTING_PERIOD), }}) self.nodes[0].generate(1) @@ -571,7 +595,6 @@ def setup(self): self.sync_blocks(timeout=120) def run_test(self): - self.setup() self.test_cfp_update_automatic_payout() @@ -581,7 +604,7 @@ def run_test(self): self.test_cfp_update_cfp_fee() self.test_cfp_update_voting_period() - self.nodes[0].setgov({"ATTRIBUTES":{ + self.nodes[0].setgov({"ATTRIBUTES": { 'v0/gov/proposals/voc_emergency_period': str(EMERGENCY_PERIOD), 'v0/gov/proposals/voc_emergency_fee': str(EMERGENCY_FEE), }}) @@ -593,5 +616,6 @@ def run_test(self): self.test_cfp_state_after_update() + if __name__ == '__main__': - CFPFeeDistributionTest().main () + CFPFeeDistributionTest().main() diff --git a/test/functional/feature_on_chain_government_voting_period_alignment.py b/test/functional/feature_on_chain_government_voting_period_alignment.py index 1cba5342bc..b3b10abe2a 100755 --- a/test/functional/feature_on_chain_government_voting_period_alignment.py +++ b/test/functional/feature_on_chain_government_voting_period_alignment.py @@ -12,19 +12,31 @@ from decimal import Decimal + class OnChainGovernanceTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 4 self.setup_clean_chain = True self.extra_args = [ - ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', '-fortcanningepilogueheight=96', '-grandcentralheight=101', '-subsidytest=1', '-txindex=1'], - ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', '-fortcanningepilogueheight=96', '-grandcentralheight=101', '-subsidytest=1'], - ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', '-fortcanningepilogueheight=96', '-grandcentralheight=101', '-subsidytest=1'], - ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', '-fortcanningepilogueheight=96', '-grandcentralheight=101', '-subsidytest=1'], + ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', + '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', + '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', + '-fortcanningepilogueheight=96', '-grandcentralheight=101', '-subsidytest=1', '-txindex=1'], + ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', + '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', + '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', + '-fortcanningepilogueheight=96', '-grandcentralheight=101', '-subsidytest=1'], + ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', + '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', + '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', + '-fortcanningepilogueheight=96', '-grandcentralheight=101', '-subsidytest=1'], + ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', + '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', + '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', + '-fortcanningepilogueheight=96', '-grandcentralheight=101', '-subsidytest=1'], ] def run_test(self): - # Get MN addresses address1 = self.nodes[1].get_genesis_keys().ownerAuthAddress address2 = self.nodes[2].get_genesis_keys().ownerAuthAddress @@ -56,15 +68,17 @@ def run_test(self): context = "" # activate on-chain governance - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/feature/gov':'true', - 'v0/gov/proposals/voting_period':'40'}}, ) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/feature/gov': 'true', + 'v0/gov/proposals/voting_period': '40'}}, ) self.nodes[0].generate(1) self.sync_blocks() # voting period votingPeriod = 40 # Create CFP - tx = self.nodes[0].creategovcfp({"title": "Single cycle CFP (70)", "context": context, "amount": 100, "cycles": 1, "payoutAddress": address}) + tx = self.nodes[0].creategovcfp( + {"title": "Single cycle CFP (70)", "context": context, "amount": 100, "cycles": 1, + "payoutAddress": address}) # Generate a block self.nodes[0].generate(1) @@ -72,7 +86,9 @@ def run_test(self): creationHeight = self.nodes[0].getblockcount() # Create CFP with 2 cycles - tx1 = self.nodes[2].creategovcfp({"title": "Multi cycle CFP (70)", "context": context, "amount": 100, "cycles": 2, "payoutAddress": address2}) + tx1 = self.nodes[2].creategovcfp( + {"title": "Multi cycle CFP (70)", "context": context, "amount": 100, "cycles": 2, + "payoutAddress": address2}) self.nodes[2].generate(1) self.sync_blocks() @@ -124,7 +140,7 @@ def run_test(self): assert_equal(result["fee"], Decimal("10")) # Change voting period at height - 1 when voting period ends - self.nodes[0].setgovheight({"ATTRIBUTES":{'v0/gov/proposals/voting_period':'130'}}, cycleAlignemnt - 1) + self.nodes[0].setgovheight({"ATTRIBUTES": {'v0/gov/proposals/voting_period': '130'}}, cycleAlignemnt - 1) self.nodes[0].generate(1) self.sync_blocks() @@ -135,7 +151,9 @@ def run_test(self): self.sync_blocks() # Create CFP in new voting period - tx2 = self.nodes[0].creategovcfp({"title": "Single cycle CFP (200)", "context": context, "amount": 100, "cycles": 1, "payoutAddress": address}) + tx2 = self.nodes[0].creategovcfp( + {"title": "Single cycle CFP (200)", "context": context, "amount": 100, "cycles": 1, + "payoutAddress": address}) self.nodes[0].generate(1) self.sync_blocks() @@ -176,5 +194,6 @@ def run_test(self): assert_equal(result["cycleEndHeight"], proposalEndHeight) assert_equal(result["proposalEndHeight"], proposalEndHeight) + if __name__ == '__main__': - OnChainGovernanceTest().main () + OnChainGovernanceTest().main() diff --git a/test/functional/feature_on_chain_government_voting_scenarios.py b/test/functional/feature_on_chain_government_voting_scenarios.py index 18791998fb..4d5143b97f 100644 --- a/test/functional/feature_on_chain_government_voting_scenarios.py +++ b/test/functional/feature_on_chain_government_voting_scenarios.py @@ -11,20 +11,25 @@ assert_raises_rpc_error ) -APPROVAL_THRESHOLD=50 -QUORUM=50 -VOTING_PERIOD=10 -NEXT_NETWORK_UPGRADE_HEIGHT=200 +APPROVAL_THRESHOLD = 50 +QUORUM = 50 +VOTING_PERIOD = 10 +NEXT_NETWORK_UPGRADE_HEIGHT = 200 + class OCGVotingScenarionTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True self.extra_args = [ - ['-jellyfish_regtest=1', '-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', '-grandcentralheight=101', f'-nextnetworkupgradeheight={NEXT_NETWORK_UPGRADE_HEIGHT}', '-rpc-governance-accept-neutral=1', '-simulatemainnet=1'], + ['-jellyfish_regtest=1', '-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=51', + '-eunosheight=80', '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', + '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', + '-grandcentralheight=101', f'-nextnetworkupgradeheight={NEXT_NETWORK_UPGRADE_HEIGHT}', + '-rpc-governance-accept-neutral=1', '-simulatemainnet=1'], ] - def setup_masternodes(self, nMasternodes = 19): + def setup_masternodes(self, nMasternodes=19): self.nodes[0].mns = [] self.operatorAddresses = [] @@ -34,11 +39,12 @@ def setup_masternodes(self, nMasternodes = 19): self.operatorAddresses.append(address) self.nodes[0].generate(1) - self.nodes[0].generate(20) # Enables all MNs + self.nodes[0].generate(20) # Enables all MNs self.sync_blocks(timeout=120) # restart node with masternode_operator addresses to be able to mint with every MNs - self.restart_node(0, self.nodes[0].extra_args + ['-masternode_operator={}'.format(address) for address in self.operatorAddresses]) + self.restart_node(0, self.nodes[0].extra_args + ['-masternode_operator={}'.format(address) for address in + self.operatorAddresses]) # Mint with every MNs to meet voting eligibility criteria for address in self.operatorAddresses: @@ -52,8 +58,8 @@ def setup(self): self.setup_masternodes() # activate on-chain governance - self.nodes[0].setgov({"ATTRIBUTES":{ - 'v0/params/feature/gov':'true', + self.nodes[0].setgov({"ATTRIBUTES": { + 'v0/params/feature/gov': 'true', 'v0/gov/proposals/voting_period': '{}'.format(VOTING_PERIOD), }}) self.nodes[0].generate(1) @@ -68,7 +74,8 @@ def test_vote_on_cfp(self, yesVote, noVote, neutralVote, expectedStatus): amount = 100 # Create CFP - propId = self.nodes[0].creategovcfp({"title": title, "context": context, "amount": amount, "cycles": 1, "payoutAddress": address}) + propId = self.nodes[0].creategovcfp( + {"title": title, "context": context, "amount": amount, "cycles": 1, "payoutAddress": address}) self.nodes[0].generate(1) mnIterator = iter(self.nodes[0].mns) @@ -103,7 +110,8 @@ def test_vote_on_cfp_with_address(self, yesVote, noVote, neutralVote, expectedSt amount = 100 # Create CFP - propId = self.nodes[0].creategovcfp({"title": title, "context": context, "amount": amount, "cycles": 1, "payoutAddress": address}) + propId = self.nodes[0].creategovcfp( + {"title": title, "context": context, "amount": amount, "cycles": 1, "payoutAddress": address}) self.nodes[0].generate(1) addressIterator = iter(self.operatorAddresses) @@ -137,12 +145,14 @@ def test_vote_with_address_without_masternode(self): amount = 100 # Create CFP - propId = self.nodes[0].creategovcfp({"title": title, "context": context, "amount": amount, "cycles": 1, "payoutAddress": address}) + propId = self.nodes[0].creategovcfp( + {"title": title, "context": context, "amount": amount, "cycles": 1, "payoutAddress": address}) self.nodes[0].generate(1) address = self.nodes[0].getnewaddress('', 'legacy') - assert_raises_rpc_error(-8, "The masternode does not exist or the address doesn't own a masternode: {}".format(address), self.nodes[0].votegov, propId, address, 'yes') + assert_raises_rpc_error(-8, "The masternode does not exist or the address doesn't own a masternode: {}".format( + address), self.nodes[0].votegov, propId, address, 'yes') def test_vote_with_invalid_address(self): # Create address for CFP @@ -152,11 +162,13 @@ def test_vote_with_invalid_address(self): amount = 100 # Create CFP - propId = self.nodes[0].creategovcfp({"title": title, "context": context, "amount": amount, "cycles": 1, "payoutAddress": address}) + propId = self.nodes[0].creategovcfp( + {"title": title, "context": context, "amount": amount, "cycles": 1, "payoutAddress": address}) self.nodes[0].generate(1) address = "fake_address" - assert_raises_rpc_error(-8, "The masternode id or address is not valid: {}".format(address), self.nodes[0].votegov, propId, address, 'yes') + assert_raises_rpc_error(-8, "The masternode id or address is not valid: {}".format(address), + self.nodes[0].votegov, propId, address, 'yes') def test_scenario_below_approval_threshold(self, expectedStatus): self.test_vote_on_cfp(yesVote=4, noVote=6, neutralVote=2, expectedStatus=expectedStatus) @@ -192,19 +204,22 @@ def test_scenario_only_yes_and_neutral(self, expectedStatus): def test_scenario_66_6_percent_approval_full_yes_votes(self, expectedStatus): self.test_vote_on_cfp(yesVote=len(self.nodes[0].mns), noVote=0, neutralVote=0, expectedStatus=expectedStatus) - self.test_vote_on_cfp_with_address(yesVote=len(self.nodes[0].mns), noVote=0, neutralVote=0, expectedStatus=expectedStatus) + self.test_vote_on_cfp_with_address(yesVote=len(self.nodes[0].mns), noVote=0, neutralVote=0, + expectedStatus=expectedStatus) def test_scenario_66_6_percent_approval_full_no_votes(self, expectedStatus): self.test_vote_on_cfp(yesVote=0, noVote=len(self.nodes[0].mns), neutralVote=0, expectedStatus=expectedStatus) - self.test_vote_on_cfp_with_address(yesVote=0, noVote=len(self.nodes[0].mns), neutralVote=0, expectedStatus=expectedStatus) + self.test_vote_on_cfp_with_address(yesVote=0, noVote=len(self.nodes[0].mns), neutralVote=0, + expectedStatus=expectedStatus) def test_scenario_66_6_percent_approval_full_neutral_votes(self, expectedStatus): self.test_vote_on_cfp(yesVote=0, noVote=0, neutralVote=len(self.nodes[0].mns), expectedStatus=expectedStatus) - self.test_vote_on_cfp_with_address(yesVote=0, noVote=0, neutralVote=len(self.nodes[0].mns), expectedStatus=expectedStatus) + self.test_vote_on_cfp_with_address(yesVote=0, noVote=0, neutralVote=len(self.nodes[0].mns), + expectedStatus=expectedStatus) def scenarios_test(self): - self.nodes[0].setgov({"ATTRIBUTES":{ - 'v0/gov/proposals/cfp_approval_threshold':'{}%'.format(APPROVAL_THRESHOLD), + self.nodes[0].setgov({"ATTRIBUTES": { + 'v0/gov/proposals/cfp_approval_threshold': '{}%'.format(APPROVAL_THRESHOLD), }}) self.nodes[0].generate(1) @@ -212,8 +227,8 @@ def scenarios_test(self): self.test_scenario_at_approval_threshold(expectedStatus='Rejected') self.test_scenario_above_approval_threshold(expectedStatus='Completed') - self.nodes[0].setgov({"ATTRIBUTES":{ - 'v0/gov/proposals/quorum':'{}%'.format(QUORUM), + self.nodes[0].setgov({"ATTRIBUTES": { + 'v0/gov/proposals/quorum': '{}%'.format(QUORUM), }}) self.nodes[0].generate(1) @@ -229,8 +244,8 @@ def scenarios_test(self): # Should assert that it's Completed once https://github.com/DeFiCh/ain/issues/1704 is fixed self.test_scenario_only_yes_and_neutral(expectedStatus='Rejected') - self.nodes[0].setgov({"ATTRIBUTES":{ - 'v0/gov/proposals/cfp_approval_threshold':'{}%'.format(66.6), + self.nodes[0].setgov({"ATTRIBUTES": { + 'v0/gov/proposals/cfp_approval_threshold': '{}%'.format(66.6), }}) self.nodes[0].generate(1) @@ -241,8 +256,8 @@ def scenarios_test(self): def scenarios_neutral_votes_not_counted_test(self): self.nodes[0].generate(NEXT_NETWORK_UPGRADE_HEIGHT - self.nodes[0].getblockcount()) - self.nodes[0].setgov({"ATTRIBUTES":{ - 'v0/gov/proposals/cfp_approval_threshold':'{}%'.format(APPROVAL_THRESHOLD), + self.nodes[0].setgov({"ATTRIBUTES": { + 'v0/gov/proposals/cfp_approval_threshold': '{}%'.format(APPROVAL_THRESHOLD), }}) self.nodes[0].generate(1) @@ -250,8 +265,8 @@ def scenarios_neutral_votes_not_counted_test(self): self.test_scenario_at_approval_threshold(expectedStatus='Rejected') self.test_scenario_above_approval_threshold(expectedStatus='Completed') - self.nodes[0].setgov({"ATTRIBUTES":{ - 'v0/gov/proposals/quorum':'{}%'.format(QUORUM), + self.nodes[0].setgov({"ATTRIBUTES": { + 'v0/gov/proposals/quorum': '{}%'.format(QUORUM), }}) self.nodes[0].generate(1) @@ -265,8 +280,8 @@ def scenarios_neutral_votes_not_counted_test(self): # Now it should be Completed after neutral votes fix self.test_scenario_only_yes_and_neutral(expectedStatus='Completed') - self.nodes[0].setgov({"ATTRIBUTES":{ - 'v0/gov/proposals/cfp_approval_threshold':'{}%'.format(66.6), + self.nodes[0].setgov({"ATTRIBUTES": { + 'v0/gov/proposals/cfp_approval_threshold': '{}%'.format(66.6), }}) self.nodes[0].generate(1) @@ -284,5 +299,6 @@ def run_test(self): self.scenarios_neutral_votes_not_counted_test() + if __name__ == '__main__': - OCGVotingScenarionTest().main () + OCGVotingScenarionTest().main() diff --git a/test/functional/feature_oracles.py b/test/functional/feature_oracles.py index 175f8b5a75..60d7db5f44 100755 --- a/test/functional/feature_oracles.py +++ b/test/functional/feature_oracles.py @@ -90,7 +90,7 @@ def assert_compare_oracle_data(self, oracle_data_json, oracle_id=None, oracle_ad p['currency'] == q['currency'] and math.isclose(decimal.Decimal(p['amount']), decimal.Decimal(q['amount'])), - tpjs, tpps), True): + tpjs, tpps), True): raise Exception("prices are not equal") def synchronize(self, node: int): @@ -178,14 +178,14 @@ def run_test(self): oracle_id=oracle_id1, weightage=10, price_feeds=price_feeds1, - token_prices=[] # no prices yet + token_prices=[] # no prices yet ) self.assert_compare_oracle_data(oracle_data_json=self.nodes[1].getoracledata(oracle_id2), oracle_id=oracle_id2, weightage=15, price_feeds=price_feeds2, - token_prices=[] # no prices yet + token_prices=[] # no prices yet ) all_oracles = self.nodes[1].listoracles() @@ -216,17 +216,17 @@ def run_test(self): oracle_data_json = self.nodes[1].getoracledata(oracle_id1) self.assert_compare_oracle_data(oracle_data_json=oracle_data_json, oracle_id=oracle_id1, price_feeds=price_feeds1, weightage=10, - token_prices=oracle1_prices) # now we have prices + token_prices=oracle1_prices) # now we have prices # decimals are not strict values, so we need to look how small is the difference assert (math.isclose( - self.nodes[1].getprice({"currency":"USD", "token":"PT"}), decimal.Decimal(10.1))) + self.nodes[1].getprice({"currency": "USD", "token": "PT"}), decimal.Decimal(10.1))) assert (math.isclose( - self.nodes[1].getprice({"currency":"USD", "token":"GOLD"}), decimal.Decimal(5))) + self.nodes[1].getprice({"currency": "USD", "token": "GOLD"}), decimal.Decimal(5))) # Make sure that DUSD-USD always returns 1 - assert_equal(self.nodes[1].getprice({"currency":"USD", "token":"DUSD"}), decimal.Decimal("1.00000000")) + assert_equal(self.nodes[1].getprice({"currency": "USD", "token": "DUSD"}), decimal.Decimal("1.00000000")) price_feeds1 = [ {"currency": "USD", "token": "PT"}, @@ -324,14 +324,14 @@ def run_test(self): self.nodes[1].getprice, {"currency": "EUR", "token": "PT"}) self.nodes[2].setoracledata(oracle_id2, timestamp, [ - {"currency":"USD", "tokenAmount":"10@GOLD"}, - {"currency":"EUR", "tokenAmount":"7@PT"}]) + {"currency": "USD", "tokenAmount": "10@GOLD"}, + {"currency": "EUR", "tokenAmount": "7@PT"}]) token_prices1 = [ - {"currency":"USD", "tokenAmount":"11@GOLD"}, - {"currency":"EUR", "tokenAmount":"8@PT"}, - {"currency":"EUR", "tokenAmount":"10@GOLD"}, - {"currency":"USD", "tokenAmount":"7@PT"} + {"currency": "USD", "tokenAmount": "11@GOLD"}, + {"currency": "EUR", "tokenAmount": "8@PT"}, + {"currency": "EUR", "tokenAmount": "10@GOLD"}, + {"currency": "USD", "tokenAmount": "7@PT"} ] self.nodes[2].setoracledata(oracle_id1, timestamp, token_prices1) @@ -344,33 +344,33 @@ def run_test(self): token_prices=token_prices1) # === check date in range 0 -> now+300s (5 minutes) === - token_prices1 = [{"currency":"USD", "tokenAmount":"7@PT"}] + token_prices1 = [{"currency": "USD", "tokenAmount": "7@PT"}] - future_timestamp = (calendar.timegm(time.gmtime()))+310 # add 5 minutes +10s for slow tests case + future_timestamp = (calendar.timegm(time.gmtime())) + 310 # add 5 minutes +10s for slow tests case assert_raises_rpc_error(-8, 'timestamp cannot be negative, zero or over 5 minutes in the future', self.nodes[2].setoracledata, oracle_id1, future_timestamp, token_prices1) # === check expired price feed === token_prices1 = [ - {"currency":"USD", "tokenAmount":"11@GOLD"}, - {"currency":"EUR", "tokenAmount":"8@PT"}, - {"currency":"EUR", "tokenAmount":"10@GOLD"}, - {"currency":"USD", "tokenAmount":"7@PT"} + {"currency": "USD", "tokenAmount": "11@GOLD"}, + {"currency": "EUR", "tokenAmount": "8@PT"}, + {"currency": "EUR", "tokenAmount": "10@GOLD"}, + {"currency": "USD", "tokenAmount": "7@PT"} ] self.nodes[2].setoracledata(oracle_id1, timestamp - 7200, token_prices1) - self.nodes[2].setoracledata(oracle_id3, timestamp - 7200, [{"currency":"USD", "tokenAmount":"7@PT"}]) + self.nodes[2].setoracledata(oracle_id3, timestamp - 7200, [{"currency": "USD", "tokenAmount": "7@PT"}]) self.synchronize(node=2) - pt_in_usd_raw_prices = self.nodes[1].listlatestrawprices({"currency":"USD", "token":"PT"}) + pt_in_usd_raw_prices = self.nodes[1].listlatestrawprices({"currency": "USD", "token": "PT"}) assert_equal(len(pt_in_usd_raw_prices), 2) assert_equal(pt_in_usd_raw_prices[0]['state'], 'expired') assert_equal(pt_in_usd_raw_prices[1]['state'], 'expired') # === check price not be zero - token_prices1 = [{"currency":"USD", "tokenAmount":"1@PT"}] + token_prices1 = [{"currency": "USD", "tokenAmount": "1@PT"}] tx = self.nodes[2].setoracledata(oracle_id1, timestamp, token_prices1) rawTx = self.nodes[2].getrawtransaction(tx) self.nodes[2].clearmempool() @@ -387,14 +387,15 @@ def run_test(self): assert_raises_rpc_error(-32600, 'oracle <{}> not found'.format(invalid_oracle_id), self.nodes[0].updateoracle, - invalid_oracle_id, oracle_address2, [{"currency":"USD", "token":"PT"}], 15) + invalid_oracle_id, oracle_address2, [{"currency": "USD", "token": "PT"}], 15) assert_raises_rpc_error(-32600, 'oracle <{}> not found'.format(invalid_oracle_id), self.nodes[0].setoracledata, - invalid_oracle_id, timestamp, [{"currency":"USD", "tokenAmount":"10@PT"}]) + invalid_oracle_id, timestamp, [{"currency": "USD", "tokenAmount": "10@PT"}]) self.nodes[0].removeoracle(oracle_id1) self.nodes[0].removeoracle(oracle_id2) + if __name__ == '__main__': OraclesTest().main() diff --git a/test/functional/feature_poolpair.py b/test/functional/feature_poolpair.py index fe494e3d25..02b2138079 100755 --- a/test/functional/feature_poolpair.py +++ b/test/functional/feature_poolpair.py @@ -14,7 +14,8 @@ from test_framework.util import assert_equal, \ connect_nodes_bi -class PoolPairTest (DefiTestFramework): + +class PoolPairTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 4 # node0: main (Foundation) @@ -27,9 +28,8 @@ def set_test_params(self): ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50'], ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50']] - def run_test(self): - assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI + assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI self.nodes[0].generate(100) self.sync_blocks() @@ -38,7 +38,7 @@ def run_test(self): self.stop_node(3) # CREATION: - #======================== + # ======================== collateral0 = self.nodes[0].getnewaddress("", "legacy") self.nodes[0].generate(1) @@ -96,29 +96,29 @@ def run_test(self): # Trying to create the same again and fail try: self.nodes[0].createpoolpair({ - "tokenA": "PT", - "tokenB": "GOLD#128", - "comission": 0.001, - "status": True, - "ownerAddress": collateral0, - "pairSymbol": "PTGD" - }, []) + "tokenA": "PT", + "tokenB": "GOLD#128", + "comission": 0.001, + "status": True, + "ownerAddress": collateral0, + "pairSymbol": "PTGD" + }, []) except JSONRPCException as e: errorString = e.error['message'] - assert("Error, there is already a poolpair with same tokens, but different poolId" in errorString) + assert ("Error, there is already a poolpair with same tokens, but different poolId" in errorString) try: self.nodes[0].createpoolpair({ - "tokenA": "PT", - "tokenB": "GOLD#128", - "comission": 0.001, - "status": True, - "ownerAddress": collateral0, - "pairSymbol": "000000000" - }, []) + "tokenA": "PT", + "tokenB": "GOLD#128", + "comission": 0.001, + "status": True, + "ownerAddress": collateral0, + "pairSymbol": "000000000" + }, []) except JSONRPCException as e: errorString = e.error['message'] - assert("pairSymbol is larger than" in errorString) + assert ("pairSymbol is larger than" in errorString) # Creating another one trPP = self.nodes[0].createpoolpair({ @@ -134,9 +134,9 @@ def run_test(self): tx = self.nodes[0].getrawtransaction(trPP) decodeTx = self.nodes[0].decoderawtransaction(tx) assert_equal(len(decodeTx['vout']), 2) - #print(decodeTx['vout'][1]['scriptPubKey']['hex']) + # print(decodeTx['vout'][1]['scriptPubKey']['hex']) - spendTx = self.nodes[0].createrawtransaction([{'txid':decodeTx['txid'], 'vout':1}],[{collateral0:9.999}]) + spendTx = self.nodes[0].createrawtransaction([{'txid': decodeTx['txid'], 'vout': 1}], [{collateral0: 9.999}]) signedTx = self.nodes[0].signrawtransactionwithwallet(spendTx) assert_equal(signedTx['complete'], True) @@ -144,50 +144,50 @@ def run_test(self): # 8 Creating PoolPair not from Foundation -> Error try: self.nodes[2].createpoolpair({ - "tokenA": "DFI", - "tokenB": "GOLD#128", - "comission": 0.001, - "status": True, - "ownerAddress": collateral0, - "pairSymbol": "DFIGOLD" - }, []) + "tokenA": "DFI", + "tokenB": "GOLD#128", + "comission": 0.001, + "status": True, + "ownerAddress": collateral0, + "pairSymbol": "DFIGOLD" + }, []) except JSONRPCException as e: errorString = e.error['message'] - assert("tx not from foundation member" in errorString) + assert ("tx not from foundation member" in errorString) # 9 Checking pool existence p0 = self.nodes[0].getpoolpair("PTGOLD") assert_equal(p0['2']['symbol'], "PTGOLD") - #10 Checking nonexistent pool + # 10 Checking nonexistent pool try: self.nodes[0].getpoolpair("DFIGOLD") except JSONRPCException as e: errorString = e.error['message'] - assert("Pool not found" in errorString) + assert ("Pool not found" in errorString) try: self.nodes[2].getpoolpair("PTGOLD") except JSONRPCException as e: errorString = e.error['message'] - assert("Pool not found" in errorString) + assert ("Pool not found" in errorString) - #11 Checking listpoolpairs + # 11 Checking listpoolpairs poolpairsn0 = self.nodes[0].listpoolpairs() assert_equal(len(poolpairsn0), 2) self.sync_blocks([self.nodes[0], self.nodes[2]]) poolpairsn2 = self.nodes[2].listpoolpairs() - #print (poolpairsn2) + # print (poolpairsn2) assert_equal(len(poolpairsn2), 2) # 12 Checking pool existence after sync p1 = self.nodes[2].getpoolpair("PTGOLD") - #print(p1) + # print(p1) assert_equal(p1['2']['symbol'], "PTGOLD") - assert(p1['2']['idTokenA'] == '1') - assert(p1['2']['idTokenB'] == '128') + assert (p1['2']['idTokenA'] == '1') + assert (p1['2']['idTokenB'] == '128') # 13 Change pool status assert_equal(self.nodes[0].getpoolpair("PTGOLD")['2']['status'], True) @@ -213,7 +213,7 @@ def run_test(self): self.nodes[0].updatepoolpair({"pool": "PTGOLD", "commission": 2}) except JSONRPCException as e: errorString = e.error['message'] - assert("commission > 100%" in errorString) + assert ("commission > 100%" in errorString) self.nodes[0].updatepoolpair({"pool": "PTGOLD", "status": True}, []) self.nodes[0].generate(1) @@ -226,15 +226,15 @@ def run_test(self): self.nodes[0].generate(1) assert_equal(self.nodes[0].getpoolpair("PTGOLD")['2']['status'], True) assert_equal(str(self.nodes[0].getpoolpair("PTGOLD")['2']['commission']), "0.10000000") - assert(self.nodes[0].getpoolpair("PTGOLD")['2']['ownerAddress'] != ownerAddress) + assert (self.nodes[0].getpoolpair("PTGOLD")['2']['ownerAddress'] != ownerAddress) self.nodes[0].updatepoolpair({"pool": "PTGOLD", "ownerAddress": collateral0}, []) self.nodes[0].generate(1) assert_equal(self.nodes[0].getpoolpair("PTGOLD")['2']['ownerAddress'], ownerAddress) # REVERTING: - #======================== - print ("Reverting...") + # ======================== + print("Reverting...") # Reverting creation! self.start_node(3) self.nodes[3].generate(30) @@ -243,5 +243,6 @@ def run_test(self): self.sync_blocks() assert_equal(len(self.nodes[0].listpoolpairs()), 0) + if __name__ == '__main__': - PoolPairTest ().main () + PoolPairTest().main() diff --git a/test/functional/feature_poolpair_liquidity.py b/test/functional/feature_poolpair_liquidity.py index d7a13a1534..5995406c5e 100755 --- a/test/functional/feature_poolpair_liquidity.py +++ b/test/functional/feature_poolpair_liquidity.py @@ -18,10 +18,12 @@ from pprint import pprint -def make_rounded_decimal(value) : + +def make_rounded_decimal(value): return Decimal(value).quantize(Decimal('0.00000001'), rounding=ROUND_DOWN) -class PoolLiquidityTest (DefiTestFramework): + +class PoolLiquidityTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 4 # node0: main @@ -35,7 +37,7 @@ def set_test_params(self): ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50']] def run_test(self): - assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI + assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI print("Generating initial chain...") self.setup_tokens() @@ -80,11 +82,11 @@ def run_test(self): # check tokens id pool = self.nodes[0].getpoolpair("GS") idGS = list(self.nodes[0].gettoken("GS").keys())[0] - assert(pool[idGS]['idTokenA'] == idGold) - assert(pool[idGS]['idTokenB'] == idSilver) + assert (pool[idGS]['idTokenA'] == idGold) + assert (pool[idGS]['idTokenB'] == idSilver) # Add liquidity - #======================== + # ======================== # one token try: self.nodes[0].addpoolliquidity({ @@ -92,7 +94,7 @@ def run_test(self): }, accountGold, []) except JSONRPCException as e: errorString = e.error['message'] - assert("the pool pair requires two tokens" in errorString) + assert ("the pool pair requires two tokens" in errorString) # missing amount try: @@ -101,7 +103,7 @@ def run_test(self): }, accountGold, []) except JSONRPCException as e: errorString = e.error['message'] - assert("Amount out of range" in errorString) + assert ("Amount out of range" in errorString) # missing pool try: @@ -110,7 +112,7 @@ def run_test(self): }, accountGold, []) except JSONRPCException as e: errorString = e.error['message'] - assert("there is no such pool pair" in errorString) + assert ("there is no such pool pair" in errorString) # transfer self.nodes[0].addpoolliquidity({ @@ -189,7 +191,7 @@ def run_test(self): assert_equal(pool['1']['totalLiquidity'], 150) # Remove liquidity - #======================== + # ======================== amountGold = accountGoldInfo[idGold] amountSilver = accountGoldInfo[idSilver] @@ -203,29 +205,28 @@ def run_test(self): self.nodes[0].removepoolliquidity(accountGold, "100@DFI", []) except JSONRPCException as e: errorString = e.error['message'] - assert("there is no such pool pair" in errorString) + assert ("there is no such pool pair" in errorString) # missing amount try: self.nodes[0].removepoolliquidity(accountGold, "0@GS", []) except JSONRPCException as e: errorString = e.error['message'] - assert("Amount out of range" in errorString) + assert ("Amount out of range" in errorString) # missing (account exists, but does not belong) try: self.nodes[0].removepoolliquidity(accountTest, "10@GS", []) except JSONRPCException as e: errorString = e.error['message'] - assert("Incorrect auth" in errorString) + assert ("Incorrect auth" in errorString) # missing amount of share (account exists and mine, but it is not a LP share account) try: self.nodes[0].removepoolliquidity(poolOwner, "10@GS", []) except JSONRPCException as e: errorString = e.error['message'] - assert("amount 0.00000000 is less" in errorString) - + assert ("amount 0.00000000 is less" in errorString) resAmountA = make_rounded_decimal(25 * poolReserveA / poolLiquidity) resAmountB = make_rounded_decimal(25 * poolReserveB / poolLiquidity) @@ -237,7 +238,6 @@ def run_test(self): accountGoldInfo = self.nodes[0].getaccount(accountGold, {}, True) pool = self.nodes[0].getpoolpair("GS", True) - assert_equal(accountGoldInfo[idGS], amountGS - 25) assert_equal(accountGoldInfo[idGold], amountGold + resAmountA) assert_equal(accountGoldInfo[idSilver], amountSilver + resAmountB) @@ -247,7 +247,7 @@ def run_test(self): assert_equal(pool['1']['totalLiquidity'], poolLiquidity - 25) # Sending pool token - #======================== + # ======================== list_poolshares = self.nodes[0].listpoolshares() assert_equal(len(list_poolshares), 2) @@ -279,7 +279,7 @@ def run_test(self): # assert_equal(len(list_poolshares), 2) # Remove all liquidity - #======================== + # ======================== pool = self.nodes[0].getpoolpair("GS", True) accountGoldInfo = self.nodes[0].getaccount(accountGold, {}, True) accountTestInfo = self.nodes[0].getaccount(accountTest, {}, True) @@ -301,13 +301,13 @@ def run_test(self): resAmountB = make_rounded_decimal(gsAmountAcc1 * poolReserveB / poolLiquidity) # transfer - self.nodes[0].removepoolliquidity(accountGold, str(gsAmountAcc1)+"@GS", []) + self.nodes[0].removepoolliquidity(accountGold, str(gsAmountAcc1) + "@GS", []) self.nodes[0].generate(1) accountGoldInfo = self.nodes[0].getaccount(accountGold, {}, True) pool = self.nodes[0].getpoolpair("GS", True) - assert(not idGS in accountGoldInfo) + assert (not idGS in accountGoldInfo) assert_equal(accountGoldInfo[idGold], goldAmountAcc1 + resAmountA) assert_equal(accountGoldInfo[idSilver], silverAmountAcc1 + resAmountB) @@ -325,14 +325,14 @@ def run_test(self): # transfer self.sync_blocks([self.nodes[0], self.nodes[3]]) - self.nodes[3].removepoolliquidity(accountTest, str(gsAmountAcc2)+"@GS", []) + self.nodes[3].removepoolliquidity(accountTest, str(gsAmountAcc2) + "@GS", []) self.sync_mempools([self.nodes[0], self.nodes[3]]) self.nodes[0].generate(1) accountTestInfo = self.nodes[0].getaccount(accountTest, {}, True) pool = self.nodes[0].getpoolpair("GS", True) - assert(not idGS in accountTestInfo) + assert (not idGS in accountTestInfo) assert_equal(accountTestInfo[idGold], goldAmountAcc2 + resAmountA) assert_equal(accountTestInfo[idSilver], silverAmountAcc2 + resAmountB) @@ -347,8 +347,8 @@ def run_test(self): assert_equal(pool['1']['totalLiquidity'], Decimal('0.00001')) # REVERTING: - #======================== - print ("Reverting...") + # ======================== + print("Reverting...") self.start_node(2) self.nodes[2].generate(20) @@ -402,11 +402,11 @@ def run_test(self): }, address) self.nodes[0].generate(1) - self.nodes[0].setgov({ "LP_DAILY_DFI_REWARD": 1 }) + self.nodes[0].setgov({"LP_DAILY_DFI_REWARD": 1}) self.nodes[0].generate(1) pool_pair_id = list(self.nodes[0].getpoolpair("BTC-DFI").keys())[0] - self.nodes[0].setgov({ "LP_SPLITS": { pool_pair_id: 1 }}) + self.nodes[0].setgov({"LP_SPLITS": {pool_pair_id: 1}}) self.nodes[0].generate(1) self.nodes[0].updatepoolpair({ @@ -419,7 +419,9 @@ def run_test(self): self.nodes[0].generate(1) rewardsAfter = self.nodes[0].getaccount(address, {}, True) - assert(rewardsAfter['0'] > rewards['0']) # Liquidity pool providers should keep getting rewards while pool status is false + assert (rewardsAfter['0'] > rewards[ + '0']) # Liquidity pool providers should keep getting rewards while pool status is false + if __name__ == '__main__': - PoolLiquidityTest ().main () + PoolLiquidityTest().main() diff --git a/test/functional/feature_poolswap.py b/test/functional/feature_poolswap.py index 97e24d4d54..f404af2e2b 100755 --- a/test/functional/feature_poolswap.py +++ b/test/functional/feature_poolswap.py @@ -20,18 +20,25 @@ from decimal import Decimal from math import trunc -class PoolPairTest (DefiTestFramework): + +class PoolPairTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 3 # node0: main (Foundation) self.setup_clean_chain = True self.extra_args = [ - ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=0', '-dakotaheight=160', '-fortcanningheight=163', '-fortcanninghillheight=170', '-fortcanningroadheight=177', '-grandcentralheight=200', '-acindex=1', '-dexstats'], - ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=0', '-dakotaheight=160', '-fortcanningheight=163', '-fortcanninghillheight=170', '-fortcanningroadheight=177', '-grandcentralheight=200', '-acindex=1', '-dexstats'], - ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=0', '-dakotaheight=160', '-fortcanningheight=163', '-fortcanninghillheight=170', '-fortcanningroadheight=177', '-grandcentralheight=200', '-dexstats']] + ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=0', '-dakotaheight=160', + '-fortcanningheight=163', '-fortcanninghillheight=170', '-fortcanningroadheight=177', + '-grandcentralheight=200', '-acindex=1', '-dexstats'], + ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=0', '-dakotaheight=160', + '-fortcanningheight=163', '-fortcanninghillheight=170', '-fortcanningroadheight=177', + '-grandcentralheight=200', '-acindex=1', '-dexstats'], + ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=0', '-dakotaheight=160', + '-fortcanningheight=163', '-fortcanninghillheight=170', '-fortcanningroadheight=177', + '-grandcentralheight=200', '-dexstats']] def setup(self): - assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI + assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI self.setup_tokens() self.symbolGOLD = "GOLD#" + self.get_id_token("GOLD") self.symbolSILVER = "SILVER#" + self.get_id_token("SILVER") @@ -41,7 +48,6 @@ def setup(self): self.init_accounts() self.create_poolpair() - def init_accounts(self): self.accountGN0 = self.nodes[0].get_genesis_keys().ownerAuthAddress self.accountSN1 = self.nodes[1].get_genesis_keys().ownerAuthAddress @@ -76,13 +82,13 @@ def create_poolpair(self): def test_swap_with_no_liquidity(self): assert_raises_rpc_error(-32600, "Lack of liquidity", self.nodes[0].poolswap, { - "from": self.accountGN0, - "tokenFrom": self.symbolSILVER, - "amountFrom": 10, - "to": self.accountSN1, - "tokenTo": self.symbolGOLD, - } - ) + "from": self.accountGN0, + "tokenFrom": self.symbolSILVER, + "amountFrom": 10, + "to": self.accountSN1, + "tokenTo": self.symbolGOLD, + } + ) def test_add_liquidity_from_different_nodes(self): self.nodes[0].addpoolliquidity({ @@ -108,7 +114,7 @@ def test_add_liquidity_from_different_nodes(self): list_pool = self.nodes[0].listpoolpairs() assert_equal(list_pool['1']['reserveA'], 200) # GOLD - assert_equal(list_pool['1']['reserveB'], 1000) # SILVER + assert_equal(list_pool['1']['reserveB'], 1000) # SILVER def turn_off_pool_and_try_swap(self): self.nodes[0].updatepoolpair({"pool": "GS", "status": False}) @@ -123,13 +129,13 @@ def turn_off_pool_and_try_swap(self): }, []) except JSONRPCException as e: errorString = e.error['message'] - assert("turned off" in errorString) + assert ("turned off" in errorString) def turn_on_pool_and_swap(self): self.nodes[0].updatepoolpair({"pool": "GS", "status": True}) self.nodes[0].generate(1) - testPoolSwapRes = self.nodes[0].testpoolswap({ + testPoolSwapRes = self.nodes[0].testpoolswap({ "from": self.accountGN0, "tokenFrom": self.symbolSILVER, "amountFrom": 10, @@ -145,7 +151,7 @@ def turn_on_pool_and_swap(self): psTestTokenId = testPoolSwapSplit[1] assert_equal(psTestTokenId, self.idGold) - testPoolSwapVerbose = self.nodes[0].testpoolswap({ + testPoolSwapVerbose = self.nodes[0].testpoolswap({ "from": self.accountGN0, "tokenFrom": self.symbolSILVER, "amountFrom": 10, @@ -170,8 +176,8 @@ def test_swap_and_live_dex_data(self): attributes = self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'] # silver is tokenB - assert_equal(attributes['v0/live/economy/dex/%s/total_swap_b'%(self.idGS)], Decimal('9.0')) - assert_equal(attributes['v0/live/economy/dex/%s/total_commission_b'%(self.idGS)], Decimal('1.0')) + assert_equal(attributes['v0/live/economy/dex/%s/total_swap_b' % (self.idGS)], Decimal('9.0')) + assert_equal(attributes['v0/live/economy/dex/%s/total_commission_b' % (self.idGS)], Decimal('1.0')) goldCheckN0 = self.nodes[2].getaccount(self.accountGN0, {}, True)[self.idGold] silverCheckN0 = self.nodes[2].getaccount(self.accountGN0, {}, True)[self.idSilver] @@ -182,11 +188,11 @@ def test_swap_and_live_dex_data(self): list_pool = self.nodes[2].listpoolpairs() assert_equal(goldCheckN0, 700) - assert_equal(str(silverCheckN0), "490.49999997") # TODO: calculate "true" values with trading fee! - assert_equal(list_pool['1']['reserveA'] + goldCheckN1 , 300) + assert_equal(str(silverCheckN0), "490.49999997") # TODO: calculate "true" values with trading fee! + assert_equal(list_pool['1']['reserveA'] + goldCheckN1, 300) assert_equal(Decimal(self.goldCheckPS) + Decimal(self.psTestAmount), Decimal(goldCheckN1)) assert_equal(str(silverCheckN1), "500.50000000") - assert_equal(list_pool['1']['reserveB'], 1009) #1010 - 1 (commission) + assert_equal(list_pool['1']['reserveB'], 1009) # 1010 - 1 (commission) def test_price_higher_than_indicated(self): list_pool = self.nodes[2].listpoolpairs() @@ -202,7 +208,7 @@ def test_price_higher_than_indicated(self): }, []) except JSONRPCException as e: errorString = e.error['message'] - assert("Price is higher than indicated." in errorString) + assert ("Price is higher than indicated." in errorString) def test_max_price(self): maxPrice = self.nodes[0].listpoolpairs()['1']['reserveB/reserveA'] @@ -223,12 +229,12 @@ def test_max_price(self): "tokenTo": self.symbolGOLD, "maxPrice": maxPrice, } - ) + ) self.nodes[0].generate(1) attributes = self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'] - assert_equal(attributes['v0/live/economy/dex/%s/total_swap_b'%(self.idGS)], Decimal('189.0')) - assert_equal(attributes['v0/live/economy/dex/%s/total_commission_b'%(self.idGS)], Decimal('21.0')) + assert_equal(attributes['v0/live/economy/dex/%s/total_swap_b' % (self.idGS)], Decimal('189.0')) + assert_equal(attributes['v0/live/economy/dex/%s/total_commission_b' % (self.idGS)], Decimal('21.0')) maxPrice = self.nodes[0].listpoolpairs()['1']['reserveB/reserveA'] # exchange tokens each other should work @@ -252,10 +258,10 @@ def test_max_price(self): self.nodes[0].generate(1) attributes = self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'] - assert_equal(attributes['v0/live/economy/dex/%s/total_swap_a'%(self.idGS)], Decimal('180.0')) - assert_equal(attributes['v0/live/economy/dex/%s/total_commission_a'%(self.idGS)], Decimal('20.0')) - assert_equal(attributes['v0/live/economy/dex/%s/total_swap_b'%(self.idGS)], Decimal('369.0')) - assert_equal(attributes['v0/live/economy/dex/%s/total_commission_b'%(self.idGS)], Decimal('41.0')) + assert_equal(attributes['v0/live/economy/dex/%s/total_swap_a' % (self.idGS)], Decimal('180.0')) + assert_equal(attributes['v0/live/economy/dex/%s/total_commission_a' % (self.idGS)], Decimal('20.0')) + assert_equal(attributes['v0/live/economy/dex/%s/total_swap_b' % (self.idGS)], Decimal('369.0')) + assert_equal(attributes['v0/live/economy/dex/%s/total_commission_b' % (self.idGS)], Decimal('41.0')) def test_fort_canning_max_price_change(self): disconnect_nodes(self.nodes[0], 1) @@ -308,7 +314,7 @@ def test_fort_canning_max_price_one_satoshi_below(self): }) except JSONRPCException as e: errorString = e.error['message'] - assert("Price is higher than indicated" in errorString) + assert ("Price is higher than indicated" in errorString) def setup_new_pool_BTC_LTC(self): @@ -316,17 +322,17 @@ def setup_new_pool_BTC_LTC(self): self.symbolLTC = "LTC" self.nodes[0].createtoken({ - "symbol": self.symbolBTC, - "name": self.symbolBTC, - "collateralAddress": self.accountGN0, - "isDAT" : True - }) + "symbol": self.symbolBTC, + "name": self.symbolBTC, + "collateralAddress": self.accountGN0, + "isDAT": True + }) self.nodes[0].createtoken({ - "symbol": self.symbolLTC, - "name": self.symbolLTC, - "collateralAddress": self.accountGN0, - "isDAT" : True - }) + "symbol": self.symbolLTC, + "name": self.symbolLTC, + "collateralAddress": self.accountGN0, + "isDAT": True + }) self.nodes[0].generate(1) self.idBTC = list(self.nodes[0].gettoken(self.symbolBTC).keys())[0] @@ -356,12 +362,12 @@ def setup_new_pool_BTC_LTC(self): def one_satoshi_swap(self): new_dest = self.nodes[0].getnewaddress("", "legacy") self.nodes[0].poolswap({ - "from": self.accountGN0, - "tokenFrom": self.symbolLTC, - "amountFrom": 0.00000001, - "to": new_dest, - "tokenTo": self.symbolBTC - }) + "from": self.accountGN0, + "tokenFrom": self.symbolLTC, + "amountFrom": 0.00000001, + "to": new_dest, + "tokenTo": self.symbolBTC + }) self.nodes[0].generate(1) assert_equal(self.nodes[0].getaccount(new_dest, {}, True)[self.idBTC], Decimal('0.00000001')) @@ -373,19 +379,19 @@ def test_two_satoshi_round_up(self, FCP=False): new_dest = self.nodes[0].getnewaddress("", "legacy") self.nodes[0].poolswap({ - "from": self.accountGN0, - "tokenFrom": self.symbolLTC, - "amountFrom": 0.00000190, - "to": new_dest, - "tokenTo": self.symbolBTC - }) + "from": self.accountGN0, + "tokenFrom": self.symbolLTC, + "amountFrom": 0.00000190, + "to": new_dest, + "tokenTo": self.symbolBTC + }) self.nodes[0].generate(1) attributes = self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'] - assert_equal(attributes['v0/live/economy/dex/%s/total_swap_a'%(self.idBL)], Decimal('0.0')) - assert_equal(attributes['v0/live/economy/dex/%s/total_commission_a'%(self.idBL)], Decimal('0.0')) - assert_equal(attributes['v0/live/economy/dex/%s/total_swap_b'%(self.idBL)], Decimal('0.00000189')) - assert_equal(attributes['v0/live/economy/dex/%s/total_commission_b'%(self.idBL)], Decimal('1E-8')) + assert_equal(attributes['v0/live/economy/dex/%s/total_swap_a' % (self.idBL)], Decimal('0.0')) + assert_equal(attributes['v0/live/economy/dex/%s/total_commission_a' % (self.idBL)], Decimal('0.0')) + assert_equal(attributes['v0/live/economy/dex/%s/total_swap_b' % (self.idBL)], Decimal('0.00000189')) + assert_equal(attributes['v0/live/economy/dex/%s/total_commission_b' % (self.idBL)], Decimal('1E-8')) expected_round_up = FCP and Decimal('0.00000001') or Decimal('0.00000002') assert_equal(self.nodes[0].getaccount(new_dest, {}, True)[self.idBTC], expected_round_up) @@ -398,23 +404,24 @@ def reset_swap_move_to_FCP_and_swap(self): new_dest = self.nodes[0].getnewaddress("", "legacy") # Test swap now results in zero amount self.nodes[0].poolswap({ - "from": self.accountGN0, - "tokenFrom": self.symbolLTC, - "amountFrom": 0.00000001, - "to": new_dest, - "tokenTo": self.symbolBTC - }) + "from": self.accountGN0, + "tokenFrom": self.symbolLTC, + "amountFrom": 0.00000001, + "to": new_dest, + "tokenTo": self.symbolBTC + }) self.nodes[0].generate(1) - assert(self.idBTC not in self.nodes[0].getaccount(new_dest, {}, True)) + assert (self.idBTC not in self.nodes[0].getaccount(new_dest, {}, True)) def set_token_and_pool_fees(self): - self.nodes[0].setgov({"ATTRIBUTES":{'v0/poolpairs/%s/token_a_fee_pct'%(self.idGS): '0.05', 'v0/poolpairs/%s/token_b_fee_pct'%(self.idGS): '0.08'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/poolpairs/%s/token_a_fee_pct' % (self.idGS): '0.05', + 'v0/poolpairs/%s/token_b_fee_pct' % (self.idGS): '0.08'}}) self.nodes[0].generate(1) attributes = self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'] - assert_equal(attributes['v0/poolpairs/%s/token_a_fee_pct'%(self.idGS)], '0.05') - assert_equal(attributes['v0/poolpairs/%s/token_b_fee_pct'%(self.idGS)], '0.08') + assert_equal(attributes['v0/poolpairs/%s/token_a_fee_pct' % (self.idGS)], '0.05') + assert_equal(attributes['v0/poolpairs/%s/token_b_fee_pct' % (self.idGS)], '0.08') result = self.nodes[0].getpoolpair(self.idGS) assert_equal(result[self.idGS]['dexFeePctTokenA'], Decimal('0.05')) @@ -445,21 +452,24 @@ def test_listaccounthistory_and_burninfo(self): amountB = reserveB - pool['reserveB'] dexoutfee = round(amountB * Decimal(0.08), 8) assert_equal(amountB - dexoutfee, swapped) - assert_equal(self.nodes[0].listaccounthistory(self.accountGN0, {'token':self.symbolGOLD})[0]['amounts'], ['-200.00000000@'+self.symbolGOLD]) + assert_equal(self.nodes[0].listaccounthistory(self.accountGN0, {'token': self.symbolGOLD})[0]['amounts'], + ['-200.00000000@' + self.symbolGOLD]) - assert_equal(self.nodes[0].getburninfo()['dexfeetokens'].sort(), ['%.8f'%(dexinfee)+self.symbolGOLD, '%.8f'%(dexoutfee)+self.symbolSILVER].sort()) + assert_equal(self.nodes[0].getburninfo()['dexfeetokens'].sort(), + ['%.8f' % (dexinfee) + self.symbolGOLD, '%.8f' % (dexoutfee) + self.symbolSILVER].sort()) attributes = self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'] - assert_equal(attributes['v0/live/economy/dex/%s/fee_burn_a'%(self.idGS)], dexinfee) - assert_equal(attributes['v0/live/economy/dex/%s/fee_burn_b'%(self.idGS)], dexoutfee) + assert_equal(attributes['v0/live/economy/dex/%s/fee_burn_a' % (self.idGS)], dexinfee) + assert_equal(attributes['v0/live/economy/dex/%s/fee_burn_b' % (self.idGS)], dexoutfee) def update_comission_and_fee_to_1pct_pool1(self): - self.nodes[0].setgov({"ATTRIBUTES":{'v0/poolpairs/%s/token_a_fee_pct'%(self.idGS): '0.01', 'v0/poolpairs/%s/token_b_fee_pct'%(self.idGS): '0.01'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/poolpairs/%s/token_a_fee_pct' % (self.idGS): '0.01', + 'v0/poolpairs/%s/token_b_fee_pct' % (self.idGS): '0.01'}}) self.nodes[0].generate(1) attributes = self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'] - assert_equal(attributes['v0/poolpairs/%s/token_a_fee_pct'%(self.idGS)], '0.01') - assert_equal(attributes['v0/poolpairs/%s/token_b_fee_pct'%(self.idGS)], '0.01') + assert_equal(attributes['v0/poolpairs/%s/token_a_fee_pct' % (self.idGS)], '0.01') + assert_equal(attributes['v0/poolpairs/%s/token_b_fee_pct' % (self.idGS)], '0.01') self.nodes[0].updatepoolpair({"pool": "GS", "commission": 0.01}) self.nodes[0].generate(1) @@ -481,21 +491,23 @@ def update_comission_and_fee_to_1pct_pool1(self): pool = self.nodes[0].getpoolpair("GS")[self.idGS] assert_equal(reserveA, pool['reserveA']) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/poolpairs/%s/token_a_fee_pct'%(self.idBL): '0.01', 'v0/poolpairs/%s/token_b_fee_pct'%(self.idBL): '0.01'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/poolpairs/%s/token_a_fee_pct' % (self.idBL): '0.01', + 'v0/poolpairs/%s/token_b_fee_pct' % (self.idBL): '0.01'}}) self.nodes[0].generate(1) attributes = self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'] - assert_equal(attributes['v0/poolpairs/%s/token_a_fee_pct'%(self.idGS)], '0.01') - assert_equal(attributes['v0/poolpairs/%s/token_b_fee_pct'%(self.idGS)], '0.01') - assert_equal(attributes['v0/poolpairs/%s/token_a_fee_pct'%(self.idBL)], '0.01') - assert_equal(attributes['v0/poolpairs/%s/token_b_fee_pct'%(self.idBL)], '0.01') + assert_equal(attributes['v0/poolpairs/%s/token_a_fee_pct' % (self.idGS)], '0.01') + assert_equal(attributes['v0/poolpairs/%s/token_b_fee_pct' % (self.idGS)], '0.01') + assert_equal(attributes['v0/poolpairs/%s/token_a_fee_pct' % (self.idBL)], '0.01') + assert_equal(attributes['v0/poolpairs/%s/token_b_fee_pct' % (self.idBL)], '0.01') def update_comission_and_fee_to_1pct_pool2(self): self.nodes[0].invalidateblock(self.nodes[0].getblockhash(self.nodes[0].getblockcount())) self.nodes[0].clearmempool() self.nodes[0].generate(1) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/token/%s/dex_in_fee_pct'%(self.idLTC): '0.02', 'v0/token/%s/dex_out_fee_pct'%(self.idBTC): '0.05'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/token/%s/dex_in_fee_pct' % (self.idLTC): '0.02', + 'v0/token/%s/dex_out_fee_pct' % (self.idBTC): '0.05'}}) self.nodes[0].generate(1) result = self.nodes[0].getpoolpair(self.idBL) @@ -505,11 +517,11 @@ def update_comission_and_fee_to_1pct_pool2(self): destBTC = self.nodes[0].getnewaddress("", "legacy") swapltc = 10 self.nodes[0].poolswap({ - "from": self.accountGN0, - "tokenFrom": self.symbolLTC, - "amountFrom": swapltc, - "to": destBTC, - "tokenTo": self.symbolBTC + "from": self.accountGN0, + "tokenFrom": self.symbolLTC, + "amountFrom": swapltc, + "to": destBTC, + "tokenTo": self.symbolBTC }) commission = round((swapltc * 0.01), 8) amountB = Decimal(swapltc - commission) @@ -529,8 +541,8 @@ def update_comission_and_fee_to_1pct_pool2(self): assert_equal(round(amountA - Decimal(dexoutfee), 8), round(swapped, 8)) attributes = self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'] - assert_equal(attributes['v0/live/economy/dex/%s/fee_burn_b'%(self.idBL)], round(dexinfee, 8)) - assert_equal(attributes['v0/live/economy/dex/%s/fee_burn_a'%(self.idBL)], Decimal(str(round(dexoutfee, 8)))) + assert_equal(attributes['v0/live/economy/dex/%s/fee_burn_b' % (self.idBL)], round(dexinfee, 8)) + assert_equal(attributes['v0/live/economy/dex/%s/fee_burn_a' % (self.idBL)], Decimal(str(round(dexoutfee, 8)))) def test_swap_to_self(self): @@ -556,11 +568,14 @@ def test_swap_to_self(self): def test_testpoolswap_errors(self): assert_raises_rpc_error(-8, "tokenFrom is empty", self.nodes[0].testpoolswap, { - "amountFrom": 0.1, "tokenFrom": "", "tokenTo": self.symbolBTC, "from": self.accountGN0, "to": self.accountSN1, "maxPrice": 0.1}) + "amountFrom": 0.1, "tokenFrom": "", "tokenTo": self.symbolBTC, "from": self.accountGN0, + "to": self.accountSN1, "maxPrice": 0.1}) assert_raises_rpc_error(-8, "tokenTo is empty", self.nodes[0].testpoolswap, { - "amountFrom": 0.1, "tokenFrom": self.symbolBTC, "tokenTo": "", "from": self.accountGN0, "to": self.accountSN1, "maxPrice": 0.1}) + "amountFrom": 0.1, "tokenFrom": self.symbolBTC, "tokenTo": "", "from": self.accountGN0, + "to": self.accountSN1, "maxPrice": 0.1}) assert_raises_rpc_error(-32600, "Input amount should be positive", self.nodes[0].testpoolswap, { - "amountFrom": 0, "tokenFrom": self.symbolLTC, "tokenTo": self.symbolBTC, "from": self.accountGN0, "to": self.accountSN1, "maxPrice": 0.1}) + "amountFrom": 0, "tokenFrom": self.symbolLTC, "tokenTo": self.symbolBTC, "from": self.accountGN0, + "to": self.accountSN1, "maxPrice": 0.1}) def revert_to_initial_state(self): self.rollback_to(block=0) @@ -568,7 +583,6 @@ def revert_to_initial_state(self): assert_equal(len(self.nodes[1].listpoolpairs()), 0) assert_equal(len(self.nodes[2].listpoolpairs()), 0) - def run_test(self): self.setup() self.test_swap_with_no_liquidity() @@ -593,5 +607,6 @@ def run_test(self): self.test_swap_to_self() self.revert_to_initial_state() + if __name__ == '__main__': - PoolPairTest ().main () + PoolPairTest().main() diff --git a/test/functional/feature_poolswap_composite.py b/test/functional/feature_poolswap_composite.py index b1fe7a1437..2190b723e2 100755 --- a/test/functional/feature_poolswap_composite.py +++ b/test/functional/feature_poolswap_composite.py @@ -16,13 +16,16 @@ from decimal import Decimal + class PoolPairCompositeTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 self.setup_clean_chain = True self.extra_args = [ - ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=106', '-bayfrontgardensheight=107', '-dakotaheight=108', '-eunosheight=109', '-fortcanningheight=110', '-grandcentralheight=170', '-fortcanninghillheight=200'], - ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=106', '-bayfrontgardensheight=107', '-dakotaheight=108', '-eunosheight=109', '-fortcanningheight=110', '-grandcentralheight=170', '-fortcanninghillheight=200']] + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=106', '-bayfrontgardensheight=107', '-dakotaheight=108', + '-eunosheight=109', '-fortcanningheight=110', '-grandcentralheight=170', '-fortcanninghillheight=200'], + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=106', '-bayfrontgardensheight=107', '-dakotaheight=108', + '-eunosheight=109', '-fortcanningheight=110', '-grandcentralheight=170', '-fortcanninghillheight=200']] def run_test(self): @@ -149,8 +152,8 @@ def run_test(self): }) except JSONRPCException as e: errorString = e.error['message'] - assert('"LTC-DFI":"Lack of liquidity."' in errorString) - assert('"LTC-USDC":"Lack of liquidity."' in errorString) + assert ('"LTC-DFI":"Lack of liquidity."' in errorString) + assert ('"LTC-USDC":"Lack of liquidity."' in errorString) # Add pool liquidity self.nodes[0].addpoolliquidity({ @@ -168,7 +171,6 @@ def run_test(self): }, collateral, []) self.nodes[0].generate(1) - self.nodes[0].compositeswap({ "from": source, "tokenFrom": symbolLTC, @@ -229,8 +231,8 @@ def run_test(self): }) except JSONRPCException as e: errorString = e.error['message'] - assert('"DOGE-DFI":"Price is higher than indicated."' in errorString) - assert('"LTC-USDC":"Lack of liquidity."' in errorString) + assert ('"DOGE-DFI":"Price is higher than indicated."' in errorString) + assert ('"LTC-USDC":"Lack of liquidity."' in errorString) # Add better route for swap with double amount self.nodes[0].addpoolliquidity({ @@ -282,7 +284,7 @@ def run_test(self): }) except JSONRPCException as e: errorString = e.error['message'] - assert('Cannot find usable pool pair.' in errorString) + assert ('Cannot find usable pool pair.' in errorString) # Let's add a pool to bridge TSLA-DUSD and LTC-DFI self.nodes[0].createpoolpair({ @@ -306,7 +308,7 @@ def run_test(self): }) except JSONRPCException as e: errorString = e.error['message'] - assert('"DUSD-DFI":"Lack of liquidity."' in errorString) + assert ('"DUSD-DFI":"Lack of liquidity."' in errorString) # Add some liquidity self.nodes[0].addpoolliquidity({ @@ -326,7 +328,7 @@ def run_test(self): }) except JSONRPCException as e: errorString = e.error['message'] - assert('"LTC-DFI":"Price is higher than indicated."' in errorString) + assert ('"LTC-DFI":"Price is higher than indicated."' in errorString) self.nodes[0].compositeswap({ "from": source, @@ -382,8 +384,8 @@ def run_test(self): }) except JSONRPCException as e: errorString = e.error['message'] - assert('"LTC-DFI":"Price is higher than indicated."' in errorString) - assert('"LTC-USDC":"Price is higher than indicated."' in errorString) + assert ('"LTC-DFI":"Price is higher than indicated."' in errorString) + assert ('"LTC-USDC":"Price is higher than indicated."' in errorString) tx = self.nodes[0].compositeswap({ "from": source, @@ -392,7 +394,7 @@ def run_test(self): "to": destination, "tokenTo": symbolLTC, "maxPrice": "0.03361578" - }) + }) self.nodes[0].generate(1) # Check source @@ -446,7 +448,8 @@ def run_test(self): rawtx = self.nodes[0].getrawtransaction(tx) updated_metadata = metadata.replace(hex(int(idLTC))[ - 2] + "00" + hex(int(idLTC))[3], hex(int(idTSLA))[2] + "00" + hex(int(idTSLA))[3]) + 2] + "00" + hex(int(idLTC))[3], + hex(int(idTSLA))[2] + "00" + hex(int(idTSLA))[3]) updated_rawtx = rawtx.replace(metadata, updated_metadata) self.nodes[0].clearmempool() @@ -469,7 +472,7 @@ def run_test(self): "amountFrom": tsla_to_ltc_from, "to": destination, "tokenTo": 0 - }) + }) rawtx_verbose = self.nodes[0].getrawtransaction(tx, 1) metadata = rawtx_verbose['vout'][0]['scriptPubKey']['hex'] @@ -479,17 +482,20 @@ def run_test(self): updated_metadata = metadata.replace('020206', '0402060206') updated_rawtx = rawtx.replace('5a' + metadata, '5c6a4c59' + updated_metadata[6:]) - assert_raises_rpc_error(-26, "Too many pool IDs provided, max 3 allowed, 4 provided", self.nodes[0].sendrawtransaction, updated_rawtx) + assert_raises_rpc_error(-26, "Too many pool IDs provided, max 3 allowed, 4 provided", + self.nodes[0].sendrawtransaction, updated_rawtx) updated_metadata = metadata.replace('020206', '03020602') updated_rawtx = rawtx.replace('5a' + metadata, '5b6a4c58' + updated_metadata[6:]) - assert_raises_rpc_error(-26, "Final swap should have idTokenTo as destination, not source", self.nodes[0].sendrawtransaction, updated_rawtx) + assert_raises_rpc_error(-26, "Final swap should have idTokenTo as destination, not source", + self.nodes[0].sendrawtransaction, updated_rawtx) updated_metadata = metadata.replace('020206', '0102') updated_rawtx = rawtx.replace('5a' + metadata, '596a4c56' + updated_metadata[6:]) - assert_raises_rpc_error(-26, "Final swap pool should have idTokenTo, incorrect final pool ID provided", self.nodes[0].sendrawtransaction, updated_rawtx) + assert_raises_rpc_error(-26, "Final swap pool should have idTokenTo, incorrect final pool ID provided", + self.nodes[0].sendrawtransaction, updated_rawtx) self.nodes[0].clearmempool() # Test too many pools error message. @@ -499,14 +505,16 @@ def run_test(self): idUSDCLTC = list(self.nodes[0].gettoken("LTC-USDC").keys())[0] # Test four pool composite swap - assert_raises_rpc_error(-32600, 'Too many pool IDs provided, max 3 allowed, 4 provided', self.nodes[0].testpoolswap, - { - "from": source, - "tokenFrom": symbolDOGE, - "amountFrom": 1, - "to": destination, - "tokenTo": symbolLTC, - }, [idDOGEDFI, idDFIDUSD, idDUSDUSDC, idUSDCLTC]) + assert_raises_rpc_error(-32600, 'Too many pool IDs provided, max 3 allowed, 4 provided', + self.nodes[0].testpoolswap, + { + "from": source, + "tokenFrom": symbolDOGE, + "amountFrom": 1, + "to": destination, + "tokenTo": symbolLTC, + }, [idDOGEDFI, idDFIDUSD, idDUSDUSDC, idUSDCLTC]) + if __name__ == '__main__': PoolPairCompositeTest().main() diff --git a/test/functional/feature_poolswap_mainnet.py b/test/functional/feature_poolswap_mainnet.py index 53da32f440..1650474e65 100755 --- a/test/functional/feature_poolswap_mainnet.py +++ b/test/functional/feature_poolswap_mainnet.py @@ -13,15 +13,18 @@ from test_framework.util import assert_equal from decimal import Decimal -class PoolPairTest (DefiTestFramework): + +class PoolPairTest(DefiTestFramework): def set_test_params(self): self.FCH_HEIGHT = 170 self.FCR_HEIGHT = 200 self.num_nodes = 1 self.setup_clean_chain = True self.extra_args = [ - ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=0', '-dakotaheight=160', '-fortcanningheight=163', '-fortcanninghillheight='+str(self.FCH_HEIGHT), '-fortcanningroadheight='+str(self.FCR_HEIGHT),'-simulatemainnet', '-jellyfish_regtest=1'] - ] + ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=0', '-dakotaheight=160', + '-fortcanningheight=163', '-fortcanninghillheight=' + str(self.FCH_HEIGHT), + '-fortcanningroadheight=' + str(self.FCR_HEIGHT), '-simulatemainnet', '-jellyfish_regtest=1'] + ] def create_tokens(self): self.symbolGOLD = "GOLD" @@ -90,14 +93,14 @@ def create_pool_pairs(self): self.nodes[0].generate(1) def add_1satoshi_liquidity_empty_pool(self): - errorString='' # remove [pylint E0601] + errorString = '' # remove [pylint E0601] try: self.nodes[0].addpoolliquidity({ self.account_gs: ["0.0000001@" + self.symbol_key_GOLD, "0.0000001@" + self.symbol_key_SILVER] }, self.account_gs, []) except JSONRPCException as e: errorString = e.error['message'] - assert('liquidity too low' in errorString) + assert ('liquidity too low' in errorString) def add_liquidity(self): self.nodes[0].addpoolliquidity({ @@ -109,15 +112,14 @@ def add_liquidity(self): self.nodes[0].generate(1) def add_1satoshi_liquidity_non_empty_pool(self): - errorString='' # remove [pylint E0601] + errorString = '' # remove [pylint E0601] try: self.nodes[0].addpoolliquidity({ self.account_gs: ["0.00000001@" + self.symbol_key_GOLD, "0.00000001@" + self.symbol_key_SILVER] }, self.account_gs, []) except JSONRPCException as e: errorString = e.error['message'] - assert('amounts too low, zero liquidity' in errorString) - + assert ('amounts too low, zero liquidity' in errorString) def setup(self): self.nodes[0].generate(self.FCH_HEIGHT) @@ -134,7 +136,7 @@ def test_swap_with_wrong_amounts(self): to_address = self.nodes[0].getnewaddress("") assert_equal(from_account[1], '45000000.00000000@GOLD#128') # try swap negative amount - errorString='' # remove [pylint E0601] + errorString = '' # remove [pylint E0601] try: self.nodes[0].poolswap({ "from": self.account_gs, @@ -142,12 +144,12 @@ def test_swap_with_wrong_amounts(self): "amountFrom": Decimal('-0.00000001'), "to": to_address, "tokenTo": self.symbol_key_SILVER, - },[]) + }, []) except JSONRPCException as e: errorString = e.error['message'] - assert('Amount out of range' in errorString) + assert ('Amount out of range' in errorString) - #try swap too small amount + # try swap too small amount try: self.nodes[0].poolswap({ "from": self.account_gs, @@ -155,11 +157,10 @@ def test_swap_with_wrong_amounts(self): "amountFrom": Decimal('0.000000001'), "to": to_address, "tokenTo": self.symbol_key_SILVER, - },[]) + }, []) except JSONRPCException as e: errorString = e.error['message'] - assert('Invalid amount' in errorString) - + assert ('Invalid amount' in errorString) def test_simple_swap_1Satoshi(self): from_address = self.account_gs @@ -173,7 +174,7 @@ def test_simple_swap_1Satoshi(self): "amountFrom": 0.00000001, "to": to_address, "tokenTo": self.symbol_key_SILVER, - },[]) + }, []) self.nodes[0].generate(1) from_account = self.nodes[0].getaccount(from_address) @@ -199,7 +200,7 @@ def test_50_simple_swaps_1Satoshi(self): "amountFrom": 0.00000001, "to": to_address, "tokenTo": self.symbol_key_SILVER, - },[]) + }, []) self.nodes[0].generate(1) from_account = self.nodes[0].getaccount(from_address) @@ -218,7 +219,7 @@ def test_compositeswap_1Satoshi(self): to_address = self.nodes[0].getnewaddress("") assert_equal(from_account[1], '44999999.99999949@GOLD#128') - testPoolSwapRes = self.nodes[0].testpoolswap({ + testPoolSwapRes = self.nodes[0].testpoolswap({ "from": from_address, "tokenFrom": self.symbol_key_GOLD, "amountFrom": 0.00000001, @@ -234,7 +235,7 @@ def test_compositeswap_1Satoshi(self): "amountFrom": 0.00000001, "to": to_address, "tokenTo": self.symbol_key_DOGE, - },[]) + }, []) self.nodes[0].generate(1) from_account = self.nodes[0].getaccount(from_address) @@ -275,7 +276,7 @@ def test_50_compositeswaps_1Satoshi(self): "amountFrom": 0.00000001, "to": to_address, "tokenTo": self.symbol_key_DOGE, - },[]) + }, []) self.nodes[0].generate(1) @@ -304,7 +305,7 @@ def test_swap_full_amount_of_one_side_of_pool(self): to_address = self.nodes[0].getnewaddress("") assert_equal(from_account[1], '44999999.99999898@GOLD#128') - testPoolSwapRes = self.nodes[0].testpoolswap({ + testPoolSwapRes = self.nodes[0].testpoolswap({ "from": from_address, "tokenFrom": self.symbol_key_GOLD, "amountFrom": Decimal('5000000.00000102'), @@ -320,7 +321,7 @@ def test_swap_full_amount_of_one_side_of_pool(self): "amountFrom": Decimal('5000000.00000102'), "to": to_address, "tokenTo": self.symbol_key_SILVER, - },[]) + }, []) self.nodes[0].generate(1) from_account = self.nodes[0].getaccount(from_address) @@ -342,9 +343,10 @@ def run_test(self): self.test_compositeswap_1Satoshi() self.test_50_compositeswaps_1Satoshi() - self.goto(self.FCR_HEIGHT) # Move to FCR + self.goto(self.FCR_HEIGHT) # Move to FCR self.test_swap_full_amount_of_one_side_of_pool() + if __name__ == '__main__': - PoolPairTest ().main () + PoolPairTest().main() diff --git a/test/functional/feature_poolswap_mechanism.py b/test/functional/feature_poolswap_mechanism.py index b0df3c1166..08009e714d 100755 --- a/test/functional/feature_poolswap_mechanism.py +++ b/test/functional/feature_poolswap_mechanism.py @@ -17,7 +17,8 @@ import time from decimal import Decimal -class PoolSwapTest (DefiTestFramework): + +class PoolSwapTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 3 # node0: main @@ -25,14 +26,17 @@ def set_test_params(self): # node2: revert create (all) self.setup_clean_chain = True self.extra_args = [ - ['-txnotokens=0', '-amkheight=0', '-bayfrontheight=0', '-bayfrontgardensheight=0', '-eunosheight=120', '-fortcanningheight=200', '-subsidytest=1'], - ['-txnotokens=0', '-amkheight=0', '-bayfrontheight=0', '-bayfrontgardensheight=0', '-eunosheight=120', '-fortcanningheight=200', '-subsidytest=1'], - ['-txnotokens=0', '-amkheight=0', '-bayfrontheight=0', '-bayfrontgardensheight=0', '-eunosheight=120', '-fortcanningheight=200', '-subsidytest=1'] + ['-txnotokens=0', '-amkheight=0', '-bayfrontheight=0', '-bayfrontgardensheight=0', '-eunosheight=120', + '-fortcanningheight=200', '-subsidytest=1'], + ['-txnotokens=0', '-amkheight=0', '-bayfrontheight=0', '-bayfrontgardensheight=0', '-eunosheight=120', + '-fortcanningheight=200', '-subsidytest=1'], + ['-txnotokens=0', '-amkheight=0', '-bayfrontheight=0', '-bayfrontgardensheight=0', '-eunosheight=120', + '-fortcanningheight=200', '-subsidytest=1'] ] # SET parameters for create tokens and pools - #======================== - self.COUNT_POOLS = 1 # 10 + # ======================== + self.COUNT_POOLS = 1 # 10 self.COUNT_ACCOUNT = 10 # 1000 self.COMMISSION = 0.001 self.AMOUNT_TOKEN = 2000 @@ -99,7 +103,7 @@ def create_pools(self, owner): def mint_tokens(self, owner): mint_amount = str(self.COUNT_ACCOUNT * self.AMOUNT_TOKEN) for item in self.tokens: - self.nodes[0].sendmany("", { owner : 0.02 }) + self.nodes[0].sendmany("", {owner: 0.02}) self.nodes[0].generate(1) self.nodes[0].minttokens(mint_amount + "@" + self.get_id_token(item), []) self.nodes[0].generate(1) @@ -117,7 +121,7 @@ def send_tokens(self, owner): end = start + 10 for idx in range(start, end): outputs[self.accounts[idx]] = send_amount + "@" + self.get_id_token(token) - self.nodes[0].sendmany("", { owner : 0.02 }) + self.nodes[0].sendmany("", {owner: 0.02}) self.nodes[0].generate(1) self.nodes[0].accounttoaccount(owner, outputs, []) self.nodes[0].generate(1) @@ -135,7 +139,7 @@ def add_pools_liquidity(self, owner): else: end = start + 10 for idx in range(start, end): - self.nodes[0].sendmany("", { self.accounts[idx] : 0.02 }) + self.nodes[0].sendmany("", {self.accounts[idx]: 0.02}) self.nodes[0].generate(1) for idx in range(start, end): amountA = random.randint(1, self.AMOUNT_TOKEN // 2) @@ -169,7 +173,7 @@ def poolswap(self, nodes): else: end = start + 10 for idx in range(start, end): - self.nodes[0].sendmany("", { self.accounts[idx] : 0.02 }) + self.nodes[0].sendmany("", {self.accounts[idx]: 0.02}) self.nodes[0].generate(1) self.sync_blocks(nodes) @@ -185,7 +189,8 @@ def poolswap(self, nodes): for idx in range(start, end): poolRewards[idx] = self.nodes[0].getaccount(self.accounts[idx], {}, True)['0'] amountsB[idx] = self.nodes[0].getaccount(self.accounts[idx], {}, True)[self.get_id_token(tokenB)] - blockCommissionB += (amount * self.DECIMAL) * (commission * self.DECIMAL) / self.DECIMAL / self.DECIMAL + blockCommissionB += (amount * self.DECIMAL) * ( + commission * self.DECIMAL) / self.DECIMAL / self.DECIMAL self.nodes[0].poolswap({ "from": self.accounts[idx], "tokenFrom": self.get_id_token(tokenB), @@ -204,16 +209,19 @@ def poolswap(self, nodes): totalLiquidity = int(totalLiquidity * self.DECIMAL) feeB = (int(blockCommissionB * self.DECIMAL) * liquidity) // totalLiquidity - (reserveB, reserveA) = self.slope_swap(Decimal(amount - (amount * self.COMMISSION)), reserveB, reserveA) + (reserveB, reserveA) = self.slope_swap(Decimal(amount - (amount * self.COMMISSION)), reserveB, + reserveA) newReserveB = reserveB - assert_equal(amountsB[idx] - amount + Decimal(str(feeB / self.DECIMAL)), self.nodes[0].getaccount(self.accounts[idx], {}, True)[self.get_id_token(tokenB)]) + assert_equal(amountsB[idx] - amount + Decimal(str(feeB / self.DECIMAL)), + self.nodes[0].getaccount(self.accounts[idx], {}, True)[self.get_id_token(tokenB)]) realPoolReward = self.nodes[0].getaccount(self.accounts[idx], {}, True)['0'] - poolRewards[idx] - yieldFarming = int(self.LP_DAILY_DFI_REWARD * self.DECIMAL) / (60 * 60 * 24 / 600) # Regression test in chainparams.cpp + yieldFarming = int(self.LP_DAILY_DFI_REWARD * self.DECIMAL) / ( + 60 * 60 * 24 / 600) # Regression test in chainparams.cpp rewardPct = self.nodes[0].getpoolpair(pool, True)[idPool]['rewardPct'] - assert(rewardPct > 0) + assert (rewardPct > 0) poolReward = yieldFarming * int(rewardPct * self.DECIMAL) // self.DECIMAL poolLoanReward = 0 @@ -221,7 +229,7 @@ def poolswap(self, nodes): if self.LP_DAILY_LOAN_TOKEN_REWARD > 0: loanYieldFarming = int(self.LP_DAILY_LOAN_TOKEN_REWARD * self.DECIMAL) / (60 * 60 * 24 / 600) rewardLoanPct = self.nodes[0].getpoolpair(pool, True)[idPool]['rewardLoanPct'] - assert(rewardLoanPct > 0) + assert (rewardLoanPct > 0) poolLoanReward = loanYieldFarming * int(rewardLoanPct * self.DECIMAL) // self.DECIMAL if poolReward: @@ -234,7 +242,7 @@ def poolswap(self, nodes): assert_equal(str(reserveB), format(newReserveB, '.8f')) def run_test(self): - assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI + assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI print("Generating initial chain...") @@ -244,7 +252,7 @@ def run_test(self): self.sync_blocks() # START - #======================== + # ======================== print("Generating accounts...") self.generate_accounts() assert_equal(len(self.accounts), self.COUNT_ACCOUNT) @@ -264,7 +272,8 @@ def run_test(self): print("Sending tokens...") self.send_tokens(owner) for account in self.accounts: - assert_equal(self.nodes[0].getaccount(account, {}, True)[self.get_id_token(self.tokens[0])], self.AMOUNT_TOKEN) + assert_equal(self.nodes[0].getaccount(account, {}, True)[self.get_id_token(self.tokens[0])], + self.AMOUNT_TOKEN) print("Tokens sent out") print("Adding liquidity...") @@ -282,8 +291,10 @@ def run_test(self): reserveAB = self.nodes[0].getpoolpair(pool, True)[idPool]['reserveA/reserveB'] reserveBA = self.nodes[0].getpoolpair(pool, True)[idPool]['reserveB/reserveA'] - resAB = int((self.liquidity[idTokenA] * self.DECIMAL) / (self.liquidity[idTokenB] * self.DECIMAL) * self.DECIMAL) - resBA = int((self.liquidity[idTokenB] * self.DECIMAL) / (self.liquidity[idTokenA] * self.DECIMAL) * self.DECIMAL) + resAB = int( + (self.liquidity[idTokenA] * self.DECIMAL) / (self.liquidity[idTokenB] * self.DECIMAL) * self.DECIMAL) + resBA = int( + (self.liquidity[idTokenB] * self.DECIMAL) / (self.liquidity[idTokenA] * self.DECIMAL) * self.DECIMAL) assert_equal(reserveAB * self.DECIMAL, resAB) assert_equal(reserveBA * self.DECIMAL, resBA) print("Liquidity added") @@ -293,8 +304,8 @@ def run_test(self): for i in range(self.COUNT_POOLS): obj[str(i + 1)] = 1 / self.COUNT_POOLS - self.nodes[0].setgov({ "LP_SPLITS": obj }) - self.nodes[0].setgov({ "LP_DAILY_DFI_REWARD": self.LP_DAILY_DFI_REWARD }) + self.nodes[0].setgov({"LP_SPLITS": obj}) + self.nodes[0].setgov({"LP_DAILY_DFI_REWARD": self.LP_DAILY_DFI_REWARD}) self.nodes[0].generate(1) self.sync_blocks() @@ -303,7 +314,7 @@ def run_test(self): assert_equal(g1['LP_SPLITS'][str(i + 1)], 1 / self.COUNT_POOLS) g2 = self.nodes[0].getgov("LP_DAILY_DFI_REWARD") - assert(g2 == {'LP_DAILY_DFI_REWARD': Decimal(self.LP_DAILY_DFI_REWARD)} ) + assert (g2 == {'LP_DAILY_DFI_REWARD': Decimal(self.LP_DAILY_DFI_REWARD)}) print("Set governance variables") # Stop node #2 for future revert @@ -318,8 +329,8 @@ def run_test(self): print("Elapsed time: {} s".format(end_time)) # REVERTING: - #======================== - print ("Reverting...") + # ======================== + print("Reverting...") self.start_node(2) self.nodes[2].generate(5) @@ -331,10 +342,10 @@ def run_test(self): self.nodes[1].clearmempool() self.nodes[2].clearmempool() - assert(self.nodes[0].getblockcount() == 120) # eunos + assert (self.nodes[0].getblockcount() == 120) # eunos self.LP_DAILY_DFI_REWARD = self.nodes[0].getgov("LP_DAILY_DFI_REWARD")['LP_DAILY_DFI_REWARD'] - assert_equal(self.LP_DAILY_DFI_REWARD, Decimal('14843.90592000')) # 144 blocks a day times 103.08268000 + assert_equal(self.LP_DAILY_DFI_REWARD, Decimal('14843.90592000')) # 144 blocks a day times 103.08268000 print("Swapping tokens after eunos height...") self.poolswap(self.nodes) @@ -343,15 +354,17 @@ def run_test(self): self.nodes[0].generate(200 - self.nodes[0].getblockcount()) # Set new splits - self.nodes[0].setgov({ "LP_LOAN_TOKEN_SPLITS": obj }) + self.nodes[0].setgov({"LP_LOAN_TOKEN_SPLITS": obj}) self.nodes[0].generate(1) self.sync_blocks() - self.LP_DAILY_LOAN_TOKEN_REWARD = self.nodes[0].getgov("LP_DAILY_LOAN_TOKEN_REWARD")['LP_DAILY_LOAN_TOKEN_REWARD'] + self.LP_DAILY_LOAN_TOKEN_REWARD = self.nodes[0].getgov("LP_DAILY_LOAN_TOKEN_REWARD")[ + 'LP_DAILY_LOAN_TOKEN_REWARD'] assert_equal(self.LP_DAILY_LOAN_TOKEN_REWARD, Decimal('14394.79756800')) print("Swapping tokens after FortCanning height...") self.poolswap(self.nodes) + if __name__ == '__main__': - PoolSwapTest ().main () + PoolSwapTest().main() diff --git a/test/functional/feature_prevent_bad_tx_propagation.py b/test/functional/feature_prevent_bad_tx_propagation.py index 23c7d89c96..26d4a56ad6 100755 --- a/test/functional/feature_prevent_bad_tx_propagation.py +++ b/test/functional/feature_prevent_bad_tx_propagation.py @@ -9,6 +9,7 @@ from test_framework.test_framework import DefiTestFramework from test_framework.util import assert_equal + class AccountMiningTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 @@ -39,7 +40,7 @@ def run_test(self): except JSONRPCException as e: errorString = e.error['message'] - assert('bad-txns-customtx' in errorString) + assert ('bad-txns-customtx' in errorString) # Store block height blockcount = node.getblockcount() @@ -53,5 +54,6 @@ def run_test(self): # Account should have 1@DFI assert_equal(node.getaccount(account)[0], "1.00000000@DFI") + if __name__ == '__main__': - AccountMiningTest().main () + AccountMiningTest().main() diff --git a/test/functional/feature_proxy.py b/test/functional/feature_proxy.py index 6a96c3bec3..c3cff13ad1 100755 --- a/test/functional/feature_proxy.py +++ b/test/functional/feature_proxy.py @@ -41,6 +41,7 @@ RANGE_BEGIN = PORT_MIN + 2 * PORT_RANGE # Start after p2p and rpc ports + class ProxyTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 4 @@ -80,13 +81,13 @@ def setup_nodes(self): # Note: proxies are not used to connect to local nodes # this is because the proxy to use is based on CService.GetNetwork(), which return NET_UNROUTABLE for localhost args = [ - ['-listen', '-proxy=%s:%i' % (self.conf1.addr),'-proxyrandomize=1'], - ['-listen', '-proxy=%s:%i' % (self.conf1.addr),'-onion=%s:%i' % (self.conf2.addr),'-proxyrandomize=0'], - ['-listen', '-proxy=%s:%i' % (self.conf2.addr),'-proxyrandomize=1'], + ['-listen', '-proxy=%s:%i' % (self.conf1.addr), '-proxyrandomize=1'], + ['-listen', '-proxy=%s:%i' % (self.conf1.addr), '-onion=%s:%i' % (self.conf2.addr), '-proxyrandomize=0'], + ['-listen', '-proxy=%s:%i' % (self.conf2.addr), '-proxyrandomize=1'], [] - ] + ] if self.have_ipv6: - args[3] = ['-listen', '-proxy=[%s]:%i' % (self.conf3.addr),'-proxyrandomize=0', '-noonion'] + args[3] = ['-listen', '-proxy=[%s]:%i' % (self.conf3.addr), '-proxyrandomize=0', '-noonion'] self.add_nodes(self.num_nodes, extra_args=args) self.start_nodes() @@ -156,7 +157,7 @@ def run_test(self): # -proxy plus -onion, -proxyrandomize rv = self.node_test(self.nodes[2], [self.serv2, self.serv2, self.serv2, self.serv2], True) # Check that credentials as used for -proxyrandomize connections are unique - credentials = set((x.username,x.password) for x in rv) + credentials = set((x.username, x.password) for x in rv) assert_equal(len(credentials), len(rv)) if self.have_ipv6: @@ -171,13 +172,13 @@ def networks_dict(d): # test RPC getnetworkinfo n0 = networks_dict(self.nodes[0].getnetworkinfo()) - for net in ['ipv4','ipv6','onion']: + for net in ['ipv4', 'ipv6', 'onion']: assert_equal(n0[net]['proxy'], '%s:%i' % (self.conf1.addr)) assert_equal(n0[net]['proxy_randomize_credentials'], True) assert_equal(n0['onion']['reachable'], True) n1 = networks_dict(self.nodes[1].getnetworkinfo()) - for net in ['ipv4','ipv6']: + for net in ['ipv4', 'ipv6']: assert_equal(n1[net]['proxy'], '%s:%i' % (self.conf1.addr)) assert_equal(n1[net]['proxy_randomize_credentials'], False) assert_equal(n1['onion']['proxy'], '%s:%i' % (self.conf2.addr)) @@ -185,17 +186,18 @@ def networks_dict(d): assert_equal(n1['onion']['reachable'], True) n2 = networks_dict(self.nodes[2].getnetworkinfo()) - for net in ['ipv4','ipv6','onion']: + for net in ['ipv4', 'ipv6', 'onion']: assert_equal(n2[net]['proxy'], '%s:%i' % (self.conf2.addr)) assert_equal(n2[net]['proxy_randomize_credentials'], True) assert_equal(n2['onion']['reachable'], True) if self.have_ipv6: n3 = networks_dict(self.nodes[3].getnetworkinfo()) - for net in ['ipv4','ipv6']: + for net in ['ipv4', 'ipv6']: assert_equal(n3[net]['proxy'], '[%s]:%i' % (self.conf3.addr)) assert_equal(n3[net]['proxy_randomize_credentials'], False) assert_equal(n3['onion']['reachable'], False) + if __name__ == '__main__': ProxyTest().main() diff --git a/test/functional/feature_pruning.py b/test/functional/feature_pruning.py index de972d1387..4231d694eb 100755 --- a/test/functional/feature_pruning.py +++ b/test/functional/feature_pruning.py @@ -28,6 +28,7 @@ # compatible with pruning based on key creation time. TIMESTAMP_WINDOW = 2 * 60 * 60 + def mine_large_blocks(node, n): # Make a large scriptPubKey for the coinbase transaction. This is OP_RETURN # followed by 950k of OP_NOP. This would be non-standard in a non-coinbase @@ -70,8 +71,12 @@ def mine_large_blocks(node, n): height += 1 mine_large_blocks.nTime += 1 + def calc_usage(blockdir): - return sum(os.path.getsize(blockdir + f) for f in os.listdir(blockdir) if os.path.isfile(os.path.join(blockdir, f))) / (1024. * 1024.) + return sum( + os.path.getsize(blockdir + f) for f in os.listdir(blockdir) if os.path.isfile(os.path.join(blockdir, f))) / ( + 1024. * 1024.) + class PruneTest(DefiTestFramework): def set_test_params(self): @@ -142,7 +147,8 @@ def test_height_min(self): def create_chain_with_staleblocks(self): # Create stale blocks in manageable sized chunks - self.log.info("Mine 24 (stale) blocks on Node 1, followed by 25 (main chain) block reorg from Node 0, for 12 rounds") + self.log.info( + "Mine 24 (stale) blocks on Node 1, followed by 25 (main chain) block reorg from Node 0, for 12 rounds") for j in range(12): # Disconnect node 0 so it can mine a longer reorg chain without knowing about node 1's soon-to-be-stale chain @@ -190,7 +196,7 @@ def reorg_test(self): disconnect_nodes(self.nodes[1], 2) self.log.info("Generating new longer chain of 300 more blocks") - self.nodes[1].pullup_mocktime() # Pull mocktime to last block due to previous manual block submitting + self.nodes[1].pullup_mocktime() # Pull mocktime to last block due to previous manual block submitting self.nodes[1].generate(300) self.log.info("Reconnect nodes") @@ -199,7 +205,8 @@ def reorg_test(self): self.sync_blocks(self.nodes[0:3], timeout=120) self.log.info("Verify height on node 2: %d" % self.nodes[2].getblockcount()) - self.log.info("Usage possibly still high because of stale blocks in block files: %d" % calc_usage(self.prunedir)) + self.log.info( + "Usage possibly still high because of stale blocks in block files: %d" % calc_usage(self.prunedir)) self.log.info("Mine 220 more large blocks so we have requisite history") @@ -213,7 +220,8 @@ def reorg_test(self): def reorg_back(self): # Verify that a block on the old main chain fork has been pruned away assert_raises_rpc_error(-1, "Block not available (pruned data)", self.nodes[2].getblock, self.forkhash) - with self.nodes[2].assert_debug_log(expected_msgs=['block verification stopping at height', '(pruning, no data)']): + with self.nodes[2].assert_debug_log( + expected_msgs=['block verification stopping at height', '(pruning, no data)']): self.nodes[2].verifychain(checklevel=4, nblocks=0) self.log.info("Will need to redownload block %d" % self.forkheight) @@ -239,7 +247,8 @@ def reorg_back(self): # At this point node 2 is within 288 blocks of the fork point so it will preserve its ability to reorg if self.nodes[2].getblockcount() < self.mainchainheight: blocks_to_mine = first_reorg_height + 1 - self.mainchainheight - self.log.info("Rewind node 0 to prev main chain to mine longer chain to trigger redownload. Blocks needed: %d" % blocks_to_mine) + self.log.info( + "Rewind node 0 to prev main chain to mine longer chain to trigger redownload. Blocks needed: %d" % blocks_to_mine) self.nodes[0].invalidateblock(curchainhash) assert_equal(self.nodes[0].getblockcount(), self.mainchainheight) assert_equal(self.nodes[0].getbestblockhash(), self.mainchainhash2) @@ -277,7 +286,8 @@ def prune(index): assert_equal(ret, node.getblockchaininfo()['pruneheight']) def has_block(index): - return os.path.isfile(os.path.join(self.nodes[node_number].datadir, "regtest", "blocks", "blk{:05}.dat".format(index))) + return os.path.isfile( + os.path.join(self.nodes[node_number].datadir, "regtest", "blocks", "blk{:05}.dat".format(index))) # should not prune because chain tip of node 3 (995) < PruneAfterHeight (1000) assert_raises_rpc_error(-1, "Blockchain is too short for pruning", node.pruneblockchain, height(500)) @@ -457,5 +467,6 @@ def run_test(self): self.log.info("Done") + if __name__ == '__main__': PruneTest().main() diff --git a/test/functional/feature_rbf.py b/test/functional/feature_rbf.py index a773801646..9de32506d7 100755 --- a/test/functional/feature_rbf.py +++ b/test/functional/feature_rbf.py @@ -13,9 +13,11 @@ MAX_REPLACEMENT_LIMIT = 100 + def txToHex(tx): return tx.serialize().hex() + def make_utxo(node, amount, confirmed=True, scriptPubKey=CScript([1])): """Create a txout with a given amount and scriptPubKey @@ -24,12 +26,12 @@ def make_utxo(node, amount, confirmed=True, scriptPubKey=CScript([1])): confirmed - txouts created will be confirmed in the blockchain; unconfirmed otherwise. """ - fee = 1*COIN - while node.getbalance() < satoshi_round((amount + fee)/COIN): + fee = 1 * COIN + while node.getbalance() < satoshi_round((amount + fee) / COIN): node.generate(100) new_addr = node.getnewaddress() - txid = node.sendtoaddress(new_addr, satoshi_round((amount+fee)/COIN)) + txid = node.sendtoaddress(new_addr, satoshi_round((amount + fee) / COIN)) tx1 = node.getrawtransaction(txid, 1) txid = int(txid, 16) i = None @@ -83,7 +85,7 @@ def run_test(self): # Leave IBD self.nodes[0].generate(1) - make_utxo(self.nodes[0], 1*COIN) + make_utxo(self.nodes[0], 1 * COIN) self.log.info("Running test simple doublespend...") self.test_simple_doublespend() @@ -119,7 +121,7 @@ def run_test(self): def test_simple_doublespend(self): """Simple doublespend""" - tx0_outpoint = make_utxo(self.nodes[0], int(1.1*COIN)) + tx0_outpoint = make_utxo(self.nodes[0], int(1.1 * COIN)) tx1a = CTransaction() tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)] @@ -154,14 +156,14 @@ def test_simple_doublespend(self): def test_doublespend_chain(self): """Doublespend of a long chain""" - initial_nValue = 50*COIN + initial_nValue = 50 * COIN tx0_outpoint = make_utxo(self.nodes[0], initial_nValue) prevout = tx0_outpoint remaining_value = initial_nValue chain_txids = [] - while remaining_value > 10*COIN: - remaining_value -= 1*COIN + while remaining_value > 10 * COIN: + remaining_value -= 1 * COIN tx = CTransaction() tx.vin = [CTxIn(prevout, nSequence=0)] tx.vout = [CTxOut(remaining_value, CScript([1, OP_DROP] * 15 + [1]))] @@ -194,10 +196,10 @@ def test_doublespend_chain(self): def test_doublespend_tree(self): """Doublespend of a big tree of transactions""" - initial_nValue = 50*COIN + initial_nValue = 50 * COIN tx0_outpoint = make_utxo(self.nodes[0], initial_nValue) - def branch(prevout, initial_value, max_txs, tree_width=5, fee=0.0001*COIN, _total_txs=None): + def branch(prevout, initial_value, max_txs, tree_width=5, fee=0.0001 * COIN, _total_txs=None): if _total_txs is None: _total_txs = [0] if _total_txs[0] >= max_txs: @@ -207,7 +209,7 @@ def branch(prevout, initial_value, max_txs, tree_width=5, fee=0.0001*COIN, _tota if txout_value < fee: return - vout = [CTxOut(txout_value, CScript([i+1])) + vout = [CTxOut(txout_value, CScript([i + 1])) for i in range(tree_width)] tx = CTransaction() tx.vin = [CTxIn(prevout, nSequence=0)] @@ -223,12 +225,12 @@ def branch(prevout, initial_value, max_txs, tree_width=5, fee=0.0001*COIN, _tota for i, txout in enumerate(tx.vout): for x in branch(COutPoint(txid, i), txout_value, - max_txs, - tree_width=tree_width, fee=fee, - _total_txs=_total_txs): + max_txs, + tree_width=tree_width, fee=fee, + _total_txs=_total_txs): yield x - fee = int(0.0001*COIN) + fee = int(0.0001 * COIN) n = MAX_REPLACEMENT_LIMIT tree_txs = list(branch(tx0_outpoint, initial_nValue, n, fee=fee)) assert_equal(len(tree_txs), n) @@ -256,8 +258,8 @@ def branch(prevout, initial_value, max_txs, tree_width=5, fee=0.0001*COIN, _tota # Try again, but with more total transactions than the "max txs # double-spent at once" anti-DoS limit. - for n in (MAX_REPLACEMENT_LIMIT+1, MAX_REPLACEMENT_LIMIT*2): - fee = int(0.0001*COIN) + for n in (MAX_REPLACEMENT_LIMIT + 1, MAX_REPLACEMENT_LIMIT * 2): + fee = int(0.0001 * COIN) tx0_outpoint = make_utxo(self.nodes[0], initial_nValue) tree_txs = list(branch(tx0_outpoint, initial_nValue, n, fee=fee)) assert_equal(len(tree_txs), n) @@ -267,7 +269,8 @@ def branch(prevout, initial_value, max_txs, tree_width=5, fee=0.0001*COIN, _tota dbl_tx.vout = [CTxOut(initial_nValue - 2 * fee * n, CScript([1] * 35))] dbl_tx_hex = txToHex(dbl_tx) # This will raise an exception - assert_raises_rpc_error(-26, "too many potential replacements", self.nodes[0].sendrawtransaction, dbl_tx_hex, 0) + assert_raises_rpc_error(-26, "too many potential replacements", self.nodes[0].sendrawtransaction, + dbl_tx_hex, 0) for tx in tree_txs: tx.rehash() @@ -275,7 +278,7 @@ def branch(prevout, initial_value, max_txs, tree_width=5, fee=0.0001*COIN, _tota def test_replacement_feeperkb(self): """Replacement requires fee-per-KB to be higher""" - tx0_outpoint = make_utxo(self.nodes[0], int(1.1*COIN)) + tx0_outpoint = make_utxo(self.nodes[0], int(1.1 * COIN)) tx1a = CTransaction() tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)] @@ -287,7 +290,7 @@ def test_replacement_feeperkb(self): # rejected. tx1b = CTransaction() tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)] - tx1b.vout = [CTxOut(int(0.001*COIN), CScript([b'a'*999000]))] + tx1b.vout = [CTxOut(int(0.001 * COIN), CScript([b'a' * 999000]))] tx1b_hex = txToHex(tx1b) # This will raise an exception due to insufficient fee @@ -295,8 +298,8 @@ def test_replacement_feeperkb(self): def test_spends_of_conflicting_outputs(self): """Replacements that spend conflicting tx outputs are rejected""" - utxo1 = make_utxo(self.nodes[0], int(1.2*COIN)) - utxo2 = make_utxo(self.nodes[0], 3*COIN) + utxo1 = make_utxo(self.nodes[0], int(1.2 * COIN)) + utxo2 = make_utxo(self.nodes[0], 3 * COIN) tx1a = CTransaction() tx1a.vin = [CTxIn(utxo1, nSequence=0)] @@ -335,8 +338,8 @@ def test_spends_of_conflicting_outputs(self): def test_new_unconfirmed_inputs(self): """Replacements that add new unconfirmed inputs are rejected""" - confirmed_utxo = make_utxo(self.nodes[0], int(1.1*COIN)) - unconfirmed_utxo = make_utxo(self.nodes[0], int(0.1*COIN), False) + confirmed_utxo = make_utxo(self.nodes[0], int(1.1 * COIN)) + unconfirmed_utxo = make_utxo(self.nodes[0], int(0.1 * COIN), False) tx1 = CTransaction() tx1.vin = [CTxIn(confirmed_utxo)] @@ -358,13 +361,13 @@ def test_too_many_replacements(self): # transactions # Start by creating a single transaction with many outputs - initial_nValue = 10*COIN + initial_nValue = 10 * COIN utxo = make_utxo(self.nodes[0], initial_nValue) - fee = int(0.0001*COIN) - split_value = int((initial_nValue-fee)/(MAX_REPLACEMENT_LIMIT+1)) + fee = int(0.0001 * COIN) + split_value = int((initial_nValue - fee) / (MAX_REPLACEMENT_LIMIT + 1)) outputs = [] - for i in range(MAX_REPLACEMENT_LIMIT+1): + for i in range(MAX_REPLACEMENT_LIMIT + 1): outputs.append(CTxOut(split_value, CScript([1]))) splitting_tx = CTransaction() @@ -376,7 +379,7 @@ def test_too_many_replacements(self): txid = int(txid, 16) # Now spend each of those outputs individually - for i in range(MAX_REPLACEMENT_LIMIT+1): + for i in range(MAX_REPLACEMENT_LIMIT + 1): tx_i = CTransaction() tx_i.vin = [CTxIn(COutPoint(txid, i), nSequence=0)] tx_i.vout = [CTxOut(split_value - fee, CScript([b'a' * 35]))] @@ -386,9 +389,9 @@ def test_too_many_replacements(self): # Now create doublespend of the whole lot; should fail. # Need a big enough fee to cover all spending transactions and have # a higher fee rate - double_spend_value = (split_value-100*fee)*(MAX_REPLACEMENT_LIMIT+1) + double_spend_value = (split_value - 100 * fee) * (MAX_REPLACEMENT_LIMIT + 1) inputs = [] - for i in range(MAX_REPLACEMENT_LIMIT+1): + for i in range(MAX_REPLACEMENT_LIMIT + 1): inputs.append(CTxIn(COutPoint(txid, i), nSequence=0)) double_tx = CTransaction() double_tx.vin = inputs @@ -396,7 +399,8 @@ def test_too_many_replacements(self): double_tx_hex = txToHex(double_tx) # This will raise an exception - assert_raises_rpc_error(-26, "too many potential replacements", self.nodes[0].sendrawtransaction, double_tx_hex, 0) + assert_raises_rpc_error(-26, "too many potential replacements", self.nodes[0].sendrawtransaction, double_tx_hex, + 0) # If we remove an input, it should pass double_tx = CTransaction() @@ -407,7 +411,7 @@ def test_too_many_replacements(self): def test_opt_in(self): """Replacing should only work if orig tx opted in""" - tx0_outpoint = make_utxo(self.nodes[0], int(1.1*COIN)) + tx0_outpoint = make_utxo(self.nodes[0], int(1.1 * COIN)) # Create a non-opting in transaction tx1a = CTransaction() @@ -428,7 +432,7 @@ def test_opt_in(self): # This will raise an exception assert_raises_rpc_error(-26, "txn-mempool-conflict", self.nodes[0].sendrawtransaction, tx1b_hex, 0) - tx1_outpoint = make_utxo(self.nodes[0], int(1.1*COIN)) + tx1_outpoint = make_utxo(self.nodes[0], int(1.1 * COIN)) # Create a different non-opting in transaction tx2a = CTransaction() @@ -456,7 +460,7 @@ def test_opt_in(self): tx3a = CTransaction() tx3a.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=0xffffffff), CTxIn(COutPoint(tx2a_txid, 0), nSequence=0xfffffffd)] - tx3a.vout = [CTxOut(int(0.9*COIN), CScript([b'c'])), CTxOut(int(0.9*COIN), CScript([b'd']))] + tx3a.vout = [CTxOut(int(0.9 * COIN), CScript([b'c'])), CTxOut(int(0.9 * COIN), CScript([b'd']))] tx3a_hex = txToHex(tx3a) tx3a_txid = self.nodes[0].sendrawtransaction(tx3a_hex, 0) @@ -484,7 +488,7 @@ def test_prioritised_transactions(self): # correctly used by replacement logic # 1. Check that feeperkb uses modified fees - tx0_outpoint = make_utxo(self.nodes[0], int(1.1*COIN)) + tx0_outpoint = make_utxo(self.nodes[0], int(1.1 * COIN)) tx1a = CTransaction() tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)] @@ -495,14 +499,14 @@ def test_prioritised_transactions(self): # Higher fee, but the actual fee per KB is much lower. tx1b = CTransaction() tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)] - tx1b.vout = [CTxOut(int(0.001*COIN), CScript([b'a'*740000]))] + tx1b.vout = [CTxOut(int(0.001 * COIN), CScript([b'a' * 740000]))] tx1b_hex = txToHex(tx1b) # Verify tx1b cannot replace tx1a. assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx1b_hex, 0) # Use prioritisetransaction to set tx1a's fee to 0. - self.nodes[0].prioritisetransaction(txid=tx1a_txid, fee_delta=int(-0.1*COIN)) + self.nodes[0].prioritisetransaction(txid=tx1a_txid, fee_delta=int(-0.1 * COIN)) # Now tx1b should be able to replace tx1a tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, 0) @@ -510,7 +514,7 @@ def test_prioritised_transactions(self): assert tx1b_txid in self.nodes[0].getrawmempool() # 2. Check that absolute fee checks use modified fee. - tx1_outpoint = make_utxo(self.nodes[0], int(1.1*COIN)) + tx1_outpoint = make_utxo(self.nodes[0], int(1.1 * COIN)) tx2a = CTransaction() tx2a.vin = [CTxIn(tx1_outpoint, nSequence=0)] @@ -529,7 +533,7 @@ def test_prioritised_transactions(self): assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx2b_hex, 0) # Now prioritise tx2b to have a higher modified fee - self.nodes[0].prioritisetransaction(txid=tx2b.hash, fee_delta=int(0.1*COIN)) + self.nodes[0].prioritisetransaction(txid=tx2b.hash, fee_delta=int(0.1 * COIN)) # tx2b should now be accepted tx2b_txid = self.nodes[0].sendrawtransaction(tx2b_hex, 0) @@ -539,11 +543,11 @@ def test_prioritised_transactions(self): def test_rpc(self): us0 = self.nodes[0].listunspent()[0] ins = [us0] - outs = {self.nodes[0].getnewaddress() : Decimal(1.0000000)} + outs = {self.nodes[0].getnewaddress(): Decimal(1.0000000)} rawtx0 = self.nodes[0].createrawtransaction(ins, outs, 0, True) rawtx1 = self.nodes[0].createrawtransaction(ins, outs, 0, False) - json0 = self.nodes[0].decoderawtransaction(rawtx0) - json1 = self.nodes[0].decoderawtransaction(rawtx1) + json0 = self.nodes[0].decoderawtransaction(rawtx0) + json1 = self.nodes[0].decoderawtransaction(rawtx1) assert_equal(json0["vin"][0]["sequence"], 4294967293) assert_equal(json1["vin"][0]["sequence"], 4294967295) @@ -551,10 +555,11 @@ def test_rpc(self): frawtx2a = self.nodes[0].fundrawtransaction(rawtx2, {"replaceable": True}) frawtx2b = self.nodes[0].fundrawtransaction(rawtx2, {"replaceable": False}) - json0 = self.nodes[0].decoderawtransaction(frawtx2a['hex']) - json1 = self.nodes[0].decoderawtransaction(frawtx2b['hex']) + json0 = self.nodes[0].decoderawtransaction(frawtx2a['hex']) + json1 = self.nodes[0].decoderawtransaction(frawtx2b['hex']) assert_equal(json0["vin"][0]["sequence"], 4294967293) assert_equal(json1["vin"][0]["sequence"], 4294967294) + if __name__ == '__main__': ReplaceByFeeTest().main() diff --git a/test/functional/feature_reindex.py b/test/functional/feature_reindex.py index 303418f018..6cffda8045 100755 --- a/test/functional/feature_reindex.py +++ b/test/functional/feature_reindex.py @@ -12,6 +12,7 @@ from test_framework.test_framework import DefiTestFramework from test_framework.util import wait_until + class ReindexTest(DefiTestFramework): def set_test_params(self): @@ -33,5 +34,6 @@ def run_test(self): self.reindex(False) self.reindex(True) + if __name__ == '__main__': ReindexTest().main() diff --git a/test/functional/feature_reject_customtxs.py b/test/functional/feature_reject_customtxs.py index e11272d74c..ecf6322640 100755 --- a/test/functional/feature_reject_customtxs.py +++ b/test/functional/feature_reject_customtxs.py @@ -10,11 +10,14 @@ from test_framework.authproxy import JSONRPCException from test_framework.util import assert_equal + class RejectCustomTx(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True - self.extra_args = [['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-bayfrontgardensheight=1', '-dakotaheight=1', '-fortcanningheight=120']] + self.extra_args = [ + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-bayfrontgardensheight=1', '-dakotaheight=1', + '-fortcanningheight=120']] def run_test(self): self.nodes[0].generate(101) @@ -53,7 +56,9 @@ def run_test(self): self.nodes[0].clearmempool() # Test sending DfTx in a vout other than 0 - rawtx_opreturn_vout1 = self.nodes[0].createrawtransaction([{"txid":rawtx['vin'][0]['txid'], "vout":rawtx['vin'][0]['vout']}], [{collateral:0.99999000},{"data":pushdata[2:]}]) + rawtx_opreturn_vout1 = self.nodes[0].createrawtransaction( + [{"txid": rawtx['vin'][0]['txid'], "vout": rawtx['vin'][0]['vout']}], + [{collateral: 0.99999000}, {"data": pushdata[2:]}]) signed_opreturn_vout1 = self.nodes[0].signrawtransactionwithwallet(rawtx_opreturn_vout1) self.nodes[0].sendrawtransaction(signed_opreturn_vout1['hex']) @@ -61,7 +66,9 @@ def run_test(self): self.nodes[0].clearmempool() # Test sending DfTx with None type - rawtx_none = self.nodes[0].createrawtransaction([{"txid":rawtx['vin'][0]['txid'], "vout":rawtx['vin'][0]['vout']}], [{collateral:0.99999000},{"data":"4466547800"}]) + rawtx_none = self.nodes[0].createrawtransaction( + [{"txid": rawtx['vin'][0]['txid'], "vout": rawtx['vin'][0]['vout']}], + [{collateral: 0.99999000}, {"data": "4466547800"}]) signed_none = self.nodes[0].signrawtransactionwithwallet(rawtx_none) self.nodes[0].sendrawtransaction(signed_none['hex']) @@ -69,7 +76,9 @@ def run_test(self): self.nodes[0].clearmempool() # Test sending DfTx with unknown type z - rawtx_unknown = self.nodes[0].createrawtransaction([{"txid":rawtx['vin'][0]['txid'], "vout":rawtx['vin'][0]['vout']}], [{collateral:0.99999000},{"data":"4466547879"}]) + rawtx_unknown = self.nodes[0].createrawtransaction( + [{"txid": rawtx['vin'][0]['txid'], "vout": rawtx['vin'][0]['vout']}], + [{collateral: 0.99999000}, {"data": "4466547879"}]) signed_unknown = self.nodes[0].signrawtransactionwithwallet(rawtx_unknown) self.nodes[0].sendrawtransaction(signed_unknown['hex']) @@ -85,34 +94,35 @@ def run_test(self): # Try and send multi opcode TX after hard fork try: self.nodes[0].sendrawtransaction(signed_multiop['hex']) - assert(False) + assert (False) except JSONRPCException as e: errorString = e.error['message'] - assert("Invalid custom transaction" in errorString) + assert ("Invalid custom transaction" in errorString) # Try and send DfTx in a vout other than 0 after hard fork try: self.nodes[0].sendrawtransaction(signed_opreturn_vout1['hex']) - assert(False) + assert (False) except JSONRPCException as e: errorString = e.error['message'] - assert("Invalid custom transaction" in errorString) + assert ("Invalid custom transaction" in errorString) # Try and send DfTx with None type after hard fork try: self.nodes[0].sendrawtransaction(signed_none['hex']) - assert(False) + assert (False) except JSONRPCException as e: errorString = e.error['message'] - assert("Invalid custom transaction" in errorString) + assert ("Invalid custom transaction" in errorString) # Try and send DfTx with unknown type after hard fork try: self.nodes[0].sendrawtransaction(signed_unknown['hex']) - assert(False) + assert (False) except JSONRPCException as e: errorString = e.error['message'] - assert("Invalid custom transaction" in errorString) + assert ("Invalid custom transaction" in errorString) + if __name__ == '__main__': RejectCustomTx().main() diff --git a/test/functional/feature_restore_utxo.py b/test/functional/feature_restore_utxo.py index 1e37a9a007..e70a15c013 100755 --- a/test/functional/feature_restore_utxo.py +++ b/test/functional/feature_restore_utxo.py @@ -9,6 +9,7 @@ from test_framework.util import assert_equal, disconnect_nodes + class TestRestoreUTXOs(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 @@ -75,5 +76,6 @@ def run_test(self): self.rollback_to(block) assert_equal(len(self.nodes[1].listunspent()), node1_utxos) + if __name__ == '__main__': TestRestoreUTXOs().main() diff --git a/test/functional/feature_rpcstats.py b/test/functional/feature_rpcstats.py index 5a7acb6efa..831062887d 100755 --- a/test/functional/feature_rpcstats.py +++ b/test/functional/feature_rpcstats.py @@ -13,13 +13,15 @@ ) from test_framework.authproxy import JSONRPCException + class RPCstats(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 self.setup_clean_chain = True self.extra_args = [ ['-acindex=1', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=50'], - ['-acindex=1', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=50', '-rpcstats=0'], + ['-acindex=1', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=50', + '-rpcstats=0'], ] def run_test(self): @@ -29,12 +31,12 @@ def run_test(self): self.nodes[0].getnewaddress("", "legacy") self.nodes[0].listunspent() - time.sleep(1) # sleep to get different timestamp + time.sleep(1) # sleep to get different timestamp self.nodes[0].listunspent() listrpcstats = self.nodes[0].listrpcstats() - assert(any(elem for elem in listrpcstats if elem["name"] == "getnewaddress")) - assert(any(elem for elem in listrpcstats if elem["name"] == "listunspent")) + assert (any(elem for elem in listrpcstats if elem["name"] == "getnewaddress")) + assert (any(elem for elem in listrpcstats if elem["name"] == "listunspent")) getrpcstats = self.nodes[0].getrpcstats("listunspent") assert_equal(getrpcstats["name"], "listunspent") @@ -48,26 +50,27 @@ def run_test(self): getrpcstats = self.nodes[0].getrpcstats("listunspent") assert_equal(getrpcstats["count"], 6) - assert(historyEntry1 not in getrpcstats["history"]) + assert (historyEntry1 not in getrpcstats["history"]) assert_equal(getrpcstats["history"][0], historyEntry2) try: self.nodes[0].getrpcstats("WRONGCMD") except JSONRPCException as e: errorString = e.error['message'] - assert("No stats for this command." in errorString) + assert ("No stats for this command." in errorString) try: self.nodes[1].getrpcstats("listunspent") except JSONRPCException as e: errorString = e.error['message'] - assert("Rpcstats is desactivated." in errorString) + assert ("Rpcstats is desactivated." in errorString) try: self.nodes[1].listrpcstats() except JSONRPCException as e: errorString = e.error['message'] - assert("Rpcstats is desactivated." in errorString) + assert ("Rpcstats is desactivated." in errorString) + if __name__ == '__main__': - RPCstats().main () + RPCstats().main() diff --git a/test/functional/feature_segwit.py b/test/functional/feature_segwit.py index ecefa10335..96a3cf1217 100755 --- a/test/functional/feature_segwit.py +++ b/test/functional/feature_segwit.py @@ -16,7 +16,8 @@ ) from test_framework.blocktools import witness_script, send_to_witness from test_framework.messages import COIN, COutPoint, CTransaction, CTxIn, CTxOut, FromHex, sha256, ToHex -from test_framework.script import CScript, OP_HASH160, OP_CHECKSIG, OP_0, hash160, OP_EQUAL, OP_DUP, OP_EQUALVERIFY, OP_1, OP_2, OP_CHECKMULTISIG, OP_TRUE, OP_DROP +from test_framework.script import CScript, OP_HASH160, OP_CHECKSIG, OP_0, hash160, OP_EQUAL, OP_DUP, OP_EQUALVERIFY, \ + OP_1, OP_2, OP_CHECKMULTISIG, OP_TRUE, OP_DROP from test_framework.test_framework import DefiTestFramework from test_framework.util import ( assert_equal, @@ -31,12 +32,14 @@ WIT_V0 = 0 WIT_V1 = 1 + def getutxo(txid): utxo = {} utxo["vout"] = 0 utxo["txid"] = txid return utxo + def find_spendable_utxo(node, min_value): for utxo in node.listunspent(query_options={'minimumAmount': min_value}): if utxo['spendable']: @@ -44,7 +47,9 @@ def find_spendable_utxo(node, min_value): raise AssertionError("Unspent output equal or higher than %s not found" % min_value) -txs_mined = {} # txindex from txid to blockhash + +txs_mined = {} # txindex from txid to blockhash + class SegWitTest(DefiTestFramework): def set_test_params(self): @@ -93,7 +98,9 @@ def skip_mine(self, node, txid, sign, redeem_script=""): self.sync_blocks() def fail_accept(self, node, error_msg, txid, sign, redeem_script=""): - assert_raises_rpc_error(-26, error_msg, send_to_witness, use_p2wsh=1, node=node, utxo=getutxo(txid), pubkey=self.pubkey[0], encode_p2sh=False, amount=Decimal("49.998"), sign=sign, insert_redeem_script=redeem_script) + assert_raises_rpc_error(-26, error_msg, send_to_witness, use_p2wsh=1, node=node, utxo=getutxo(txid), + pubkey=self.pubkey[0], encode_p2sh=False, amount=Decimal("49.998"), sign=sign, + insert_redeem_script=redeem_script) def run_test(self): self.nodes[0].generate(161) # block 161 @@ -135,8 +142,12 @@ def run_test(self): for i in range(5): for n in range(3): for v in range(2): - wit_ids[n][v].append(send_to_witness(v, self.nodes[0], find_spendable_utxo(self.nodes[0], 50), self.pubkey[n], False, Decimal("49.999"))) - p2sh_ids[n][v].append(send_to_witness(v, self.nodes[0], find_spendable_utxo(self.nodes[0], 50), self.pubkey[n], True, Decimal("49.999"))) + wit_ids[n][v].append( + send_to_witness(v, self.nodes[0], find_spendable_utxo(self.nodes[0], 50), self.pubkey[n], False, + Decimal("49.999"))) + p2sh_ids[n][v].append( + send_to_witness(v, self.nodes[0], find_spendable_utxo(self.nodes[0], 50), self.pubkey[n], True, + Decimal("49.999"))) self.nodes[0].generate(1) # block 163 self.sync_blocks() @@ -176,26 +187,41 @@ def run_test(self): self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V0][0], False) self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V1][0], False) # unsigned with redeem script - self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V0][0], False, witness_script(False, self.pubkey[0])) - self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V1][0], False, witness_script(True, self.pubkey[0])) + self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V0][0], False, + witness_script(False, self.pubkey[0])) + self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V1][0], False, + witness_script(True, self.pubkey[0])) - self.log.info("Verify block and transaction serialization rpcs return differing serializations depending on rpc serialization flag") + self.log.info( + "Verify block and transaction serialization rpcs return differing serializations depending on rpc serialization flag") assert self.nodes[2].getblock(blockhash, False) != self.nodes[0].getblock(blockhash, False) assert self.nodes[1].getblock(blockhash, False) == self.nodes[2].getblock(blockhash, False) for tx_id in segwit_tx_list: tx = FromHex(CTransaction(), self.nodes[2].gettransaction(tx_id)["hex"]) - assert self.nodes[2].getrawtransaction(tx_id, False, blockhash) != self.nodes[0].getrawtransaction(tx_id, False, blockhash) - assert self.nodes[1].getrawtransaction(tx_id, False, blockhash) == self.nodes[2].getrawtransaction(tx_id, False, blockhash) - assert self.nodes[0].getrawtransaction(tx_id, False, blockhash) != self.nodes[2].gettransaction(tx_id)["hex"] - assert self.nodes[1].getrawtransaction(tx_id, False, blockhash) == self.nodes[2].gettransaction(tx_id)["hex"] + assert self.nodes[2].getrawtransaction(tx_id, False, blockhash) != self.nodes[0].getrawtransaction(tx_id, + False, + blockhash) + assert self.nodes[1].getrawtransaction(tx_id, False, blockhash) == self.nodes[2].getrawtransaction(tx_id, + False, + blockhash) + assert self.nodes[0].getrawtransaction(tx_id, False, blockhash) != self.nodes[2].gettransaction(tx_id)[ + "hex"] + assert self.nodes[1].getrawtransaction(tx_id, False, blockhash) == self.nodes[2].gettransaction(tx_id)[ + "hex"] assert self.nodes[0].getrawtransaction(tx_id, False, blockhash) == tx.serialize_without_witness().hex() self.log.info("Verify witness txs without witness data are invalid after the fork") - self.fail_accept(self.nodes[2], 'non-mandatory-script-verify-flag (Witness program hash mismatch) (code 64)', wit_ids[NODE_2][WIT_V0][2], sign=False) - self.fail_accept(self.nodes[2], 'non-mandatory-script-verify-flag (Witness program was passed an empty witness) (code 64)', wit_ids[NODE_2][WIT_V1][2], sign=False) - self.fail_accept(self.nodes[2], 'non-mandatory-script-verify-flag (Witness program hash mismatch) (code 64)', p2sh_ids[NODE_2][WIT_V0][2], sign=False, redeem_script=witness_script(False, self.pubkey[2])) - self.fail_accept(self.nodes[2], 'non-mandatory-script-verify-flag (Witness program was passed an empty witness) (code 64)', p2sh_ids[NODE_2][WIT_V1][2], sign=False, redeem_script=witness_script(True, self.pubkey[2])) + self.fail_accept(self.nodes[2], 'non-mandatory-script-verify-flag (Witness program hash mismatch) (code 64)', + wit_ids[NODE_2][WIT_V0][2], sign=False) + self.fail_accept(self.nodes[2], + 'non-mandatory-script-verify-flag (Witness program was passed an empty witness) (code 64)', + wit_ids[NODE_2][WIT_V1][2], sign=False) + self.fail_accept(self.nodes[2], 'non-mandatory-script-verify-flag (Witness program hash mismatch) (code 64)', + p2sh_ids[NODE_2][WIT_V0][2], sign=False, redeem_script=witness_script(False, self.pubkey[2])) + self.fail_accept(self.nodes[2], + 'non-mandatory-script-verify-flag (Witness program was passed an empty witness) (code 64)', + p2sh_ids[NODE_2][WIT_V1][2], sign=False, redeem_script=witness_script(True, self.pubkey[2])) self.log.info("Verify default node can now use witness txs") self.success_mine(self.nodes[0], wit_ids[NODE_0][WIT_V0][0], True) # block 432 @@ -219,7 +245,8 @@ def run_test(self): # tx2 (segwit input, paying to a non-segwit output) -> # tx3 (non-segwit input, paying to a non-segwit output). # tx1 is allowed to appear in the block, but no others. - txid1 = send_to_witness(1, self.nodes[0], find_spendable_utxo(self.nodes[0], 50), self.pubkey[0], False, Decimal("49.996")) + txid1 = send_to_witness(1, self.nodes[0], find_spendable_utxo(self.nodes[0], 50), self.pubkey[0], False, + Decimal("49.996")) hex_tx = self.nodes[0].gettransaction(txid)['hex'] tx = FromHex(CTransaction(), hex_tx) assert tx.wit.is_null() # This should not be a segwit input @@ -232,8 +259,10 @@ def run_test(self): assert_equal(int(self.nodes[0].getmempoolentry(txid1)["wtxid"], 16), tx1.calc_sha256(True)) # Check that weight and vsize are properly reported in mempool entry (txid1) - assert_equal(self.nodes[0].getmempoolentry(txid1)["vsize"], (self.nodes[0].getmempoolentry(txid1)["weight"] + 3) // 4) - assert_equal(self.nodes[0].getmempoolentry(txid1)["weight"], len(tx1.serialize_without_witness())*3 + len(tx1.serialize_with_witness())) + assert_equal(self.nodes[0].getmempoolentry(txid1)["vsize"], + (self.nodes[0].getmempoolentry(txid1)["weight"] + 3) // 4) + assert_equal(self.nodes[0].getmempoolentry(txid1)["weight"], + len(tx1.serialize_without_witness()) * 3 + len(tx1.serialize_with_witness())) # Now create tx2, which will spend from txid1. tx = CTransaction() @@ -248,8 +277,10 @@ def run_test(self): assert_equal(int(self.nodes[0].getmempoolentry(txid2)["wtxid"], 16), tx.calc_sha256(True)) # Check that weight and vsize are properly reported in mempool entry (txid2) - assert_equal(self.nodes[0].getmempoolentry(txid2)["vsize"], (self.nodes[0].getmempoolentry(txid2)["weight"] + 3) // 4) - assert_equal(self.nodes[0].getmempoolentry(txid2)["weight"], len(tx.serialize_without_witness())*3 + len(tx.serialize_with_witness())) + assert_equal(self.nodes[0].getmempoolentry(txid2)["vsize"], + (self.nodes[0].getmempoolentry(txid2)["weight"] + 3) // 4) + assert_equal(self.nodes[0].getmempoolentry(txid2)["weight"], + len(tx.serialize_without_witness()) * 3 + len(tx.serialize_with_witness())) # Now create tx3, which will spend from txid2 tx = CTransaction() @@ -271,8 +302,10 @@ def run_test(self): assert_equal(int(self.nodes[0].getmempoolentry(txid3)["wtxid"], 16), tx.calc_sha256(True)) # Check that weight and vsize are properly reported in mempool entry (txid3) - assert_equal(self.nodes[0].getmempoolentry(txid3)["vsize"], (self.nodes[0].getmempoolentry(txid3)["weight"] + 3) // 4) - assert_equal(self.nodes[0].getmempoolentry(txid3)["weight"], len(tx.serialize_without_witness())*3 + len(tx.serialize_with_witness())) + assert_equal(self.nodes[0].getmempoolentry(txid3)["vsize"], + (self.nodes[0].getmempoolentry(txid3)["weight"] + 3) // 4) + assert_equal(self.nodes[0].getmempoolentry(txid3)["weight"], + len(tx.serialize_without_witness()) * 3 + len(tx.serialize_with_witness())) # Mine a block to clear the gbt cache again. self.nodes[0].generate(1) @@ -281,13 +314,20 @@ def run_test(self): # Some public keys to be used later pubkeys = [ - "0363D44AABD0F1699138239DF2F042C3282C0671CC7A76826A55C8203D90E39242", # cPiM8Ub4heR9NBYmgVzJQiUH1if44GSBGiqaeJySuL2BKxubvgwb - "02D3E626B3E616FC8662B489C123349FECBFC611E778E5BE739B257EAE4721E5BF", # cPpAdHaD6VoYbW78kveN2bsvb45Q7G5PhaPApVUGwvF8VQ9brD97 - "04A47F2CBCEFFA7B9BCDA184E7D5668D3DA6F9079AD41E422FA5FD7B2D458F2538A62F5BD8EC85C2477F39650BD391EA6250207065B2A81DA8B009FC891E898F0E", # 91zqCU5B9sdWxzMt1ca3VzbtVm2YM6Hi5Rxn4UDtxEaN9C9nzXV - "02A47F2CBCEFFA7B9BCDA184E7D5668D3DA6F9079AD41E422FA5FD7B2D458F2538", # cPQFjcVRpAUBG8BA9hzr2yEzHwKoMgLkJZBBtK9vJnvGJgMjzTbd - "036722F784214129FEB9E8129D626324F3F6716555B603FFE8300BBCB882151228", # cQGtcm34xiLjB1v7bkRa4V3aAc9tS2UTuBZ1UnZGeSeNy627fN66 - "0266A8396EE936BF6D99D17920DB21C6C7B1AB14C639D5CD72B300297E416FD2EC", # cTW5mR5M45vHxXkeChZdtSPozrFwFgmEvTNnanCW6wrqwaCZ1X7K - "0450A38BD7F0AC212FEBA77354A9B036A32E0F7C81FC4E0C5ADCA7C549C4505D2522458C2D9AE3CEFD684E039194B72C8A10F9CB9D4764AB26FCC2718D421D3B84", # 92h2XPssjBpsJN5CqSP7v9a7cf2kgDunBC6PDFwJHMACM1rrVBJ + "0363D44AABD0F1699138239DF2F042C3282C0671CC7A76826A55C8203D90E39242", + # cPiM8Ub4heR9NBYmgVzJQiUH1if44GSBGiqaeJySuL2BKxubvgwb + "02D3E626B3E616FC8662B489C123349FECBFC611E778E5BE739B257EAE4721E5BF", + # cPpAdHaD6VoYbW78kveN2bsvb45Q7G5PhaPApVUGwvF8VQ9brD97 + "04A47F2CBCEFFA7B9BCDA184E7D5668D3DA6F9079AD41E422FA5FD7B2D458F2538A62F5BD8EC85C2477F39650BD391EA6250207065B2A81DA8B009FC891E898F0E", + # 91zqCU5B9sdWxzMt1ca3VzbtVm2YM6Hi5Rxn4UDtxEaN9C9nzXV + "02A47F2CBCEFFA7B9BCDA184E7D5668D3DA6F9079AD41E422FA5FD7B2D458F2538", + # cPQFjcVRpAUBG8BA9hzr2yEzHwKoMgLkJZBBtK9vJnvGJgMjzTbd + "036722F784214129FEB9E8129D626324F3F6716555B603FFE8300BBCB882151228", + # cQGtcm34xiLjB1v7bkRa4V3aAc9tS2UTuBZ1UnZGeSeNy627fN66 + "0266A8396EE936BF6D99D17920DB21C6C7B1AB14C639D5CD72B300297E416FD2EC", + # cTW5mR5M45vHxXkeChZdtSPozrFwFgmEvTNnanCW6wrqwaCZ1X7K + "0450A38BD7F0AC212FEBA77354A9B036A32E0F7C81FC4E0C5ADCA7C549C4505D2522458C2D9AE3CEFD684E039194B72C8A10F9CB9D4764AB26FCC2718D421D3B84", + # 92h2XPssjBpsJN5CqSP7v9a7cf2kgDunBC6PDFwJHMACM1rrVBJ ] # Import a compressed key and an uncompressed key, generate some multisig addresses @@ -305,19 +345,31 @@ def run_test(self): self.nodes[0].importpubkey(pubkeys[2]) uncompressed_solvable_address = [key_to_p2pkh(pubkeys[2])] - spendable_anytime = [] # These outputs should be seen anytime after importprivkey and addmultisigaddress - spendable_after_importaddress = [] # These outputs should be seen after importaddress - solvable_after_importaddress = [] # These outputs should be seen after importaddress but not spendable - unsolvable_after_importaddress = [] # These outputs should be unsolvable after importaddress - solvable_anytime = [] # These outputs should be solvable after importpubkey - unseen_anytime = [] # These outputs should never be seen - - uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], compressed_spendable_address[0]])['address']) - uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], uncompressed_spendable_address[0]])['address']) - compressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_spendable_address[0]])['address']) - uncompressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], uncompressed_solvable_address[0]])['address']) - compressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_solvable_address[0]])['address']) - compressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_solvable_address[0], compressed_solvable_address[1]])['address']) + spendable_anytime = [] # These outputs should be seen anytime after importprivkey and addmultisigaddress + spendable_after_importaddress = [] # These outputs should be seen after importaddress + solvable_after_importaddress = [] # These outputs should be seen after importaddress but not spendable + unsolvable_after_importaddress = [] # These outputs should be unsolvable after importaddress + solvable_anytime = [] # These outputs should be solvable after importpubkey + unseen_anytime = [] # These outputs should never be seen + + uncompressed_spendable_address.append( + self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], compressed_spendable_address[0]])[ + 'address']) + uncompressed_spendable_address.append( + self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], uncompressed_spendable_address[0]])[ + 'address']) + compressed_spendable_address.append( + self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_spendable_address[0]])[ + 'address']) + uncompressed_solvable_address.append( + self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], uncompressed_solvable_address[0]])[ + 'address']) + compressed_solvable_address.append( + self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_solvable_address[0]])[ + 'address']) + compressed_solvable_address.append( + self.nodes[0].addmultisigaddress(2, [compressed_solvable_address[0], compressed_solvable_address[1]])[ + 'address']) # Test multisig_without_privkey # We have 2 public keys without private keys, use addmultisigaddress to add to wallet. @@ -338,11 +390,13 @@ def run_test(self): # P2WSH and P2SH(P2WSH) multisig with compressed keys are spendable after direct importaddress spendable_after_importaddress.extend([p2wsh, p2sh_p2wsh]) else: - [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) + [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, + p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) # normal P2PKH and P2PK with compressed keys should always be spendable spendable_anytime.extend([p2pkh, p2pk]) # P2SH_P2PK, P2SH_P2PKH with compressed keys are spendable after direct importaddress - spendable_after_importaddress.extend([p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh]) + spendable_after_importaddress.extend( + [p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh]) # P2WPKH and P2SH_P2WPKH with compressed keys should always be spendable spendable_anytime.extend([p2wpkh, p2sh_p2wpkh]) @@ -357,7 +411,8 @@ def run_test(self): # P2WSH and P2SH(P2WSH) multisig with uncompressed keys are never seen unseen_anytime.extend([p2wsh, p2sh_p2wsh]) else: - [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) + [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, + p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) # normal P2PKH and P2PK with uncompressed keys should always be spendable spendable_anytime.extend([p2pkh, p2pk]) # P2SH_P2PK and P2SH_P2PKH are spendable after direct importaddress @@ -372,11 +427,13 @@ def run_test(self): [bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v) solvable_after_importaddress.extend([bare, p2sh, p2wsh, p2sh_p2wsh]) else: - [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) + [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, + p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) # normal P2PKH, P2PK, P2WPKH and P2SH_P2WPKH with compressed keys should always be seen solvable_anytime.extend([p2pkh, p2pk, p2wpkh, p2sh_p2wpkh]) # P2SH_P2PK, P2SH_P2PKH with compressed keys are seen after direct importaddress - solvable_after_importaddress.extend([p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh]) + solvable_after_importaddress.extend( + [p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh]) for i in uncompressed_solvable_address: v = self.nodes[0].getaddressinfo(i) @@ -387,7 +444,8 @@ def run_test(self): # P2WSH and P2SH(P2WSH) multisig with uncompressed keys are never seen unseen_anytime.extend([p2wsh, p2sh_p2wsh]) else: - [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) + [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, + p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) # normal P2PKH and P2PK with uncompressed keys should always be seen solvable_anytime.extend([p2pkh, p2pk]) # P2SH_P2PK, P2SH_P2PKH with uncompressed keys are seen after direct importaddress @@ -414,7 +472,9 @@ def run_test(self): solvable_txid = [] spendable_txid.append(self.mine_and_test_listunspent(spendable_anytime, 2)) solvable_txid.append(self.mine_and_test_listunspent(solvable_anytime, 1)) - self.mine_and_test_listunspent(spendable_after_importaddress + solvable_after_importaddress + unseen_anytime + unsolvable_after_importaddress, 0) + self.mine_and_test_listunspent( + spendable_after_importaddress + solvable_after_importaddress + unseen_anytime + unsolvable_after_importaddress, + 0) importlist = [] for i in compressed_spendable_address + uncompressed_spendable_address + compressed_solvable_address + uncompressed_solvable_address: @@ -441,7 +501,8 @@ def run_test(self): for i in importlist: # import all generated addresses. The wallet already has the private keys for some of these, so catch JSON RPC # exceptions and continue. - try_rpc(-4, "The wallet already contains the private key for this address or script", self.nodes[0].importaddress, i, "", False, True) + try_rpc(-4, "The wallet already contains the private key for this address or script", + self.nodes[0].importaddress, i, "", False, True) self.nodes[0].importaddress(script_to_p2sh(op0)) # import OP_0 as address only self.nodes[0].importaddress(multisig_without_privkey_address) # Test multisig_without_privkey @@ -468,15 +529,25 @@ def run_test(self): self.nodes[0].importpubkey(pubkeys[6]) uncompressed_solvable_address = [key_to_p2pkh(pubkeys[6])] - unseen_anytime = [] # These outputs should never be seen - solvable_anytime = [] # These outputs should be solvable after importpubkey - unseen_anytime = [] # These outputs should never be seen - - uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], compressed_spendable_address[0]])['address']) - uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], uncompressed_spendable_address[0]])['address']) - compressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_spendable_address[0]])['address']) - uncompressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_solvable_address[0], uncompressed_solvable_address[0]])['address']) - compressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_solvable_address[0]])['address']) + unseen_anytime = [] # These outputs should never be seen + solvable_anytime = [] # These outputs should be solvable after importpubkey + unseen_anytime = [] # These outputs should never be seen + + uncompressed_spendable_address.append( + self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], compressed_spendable_address[0]])[ + 'address']) + uncompressed_spendable_address.append( + self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], uncompressed_spendable_address[0]])[ + 'address']) + compressed_spendable_address.append( + self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_spendable_address[0]])[ + 'address']) + uncompressed_solvable_address.append( + self.nodes[0].addmultisigaddress(2, [compressed_solvable_address[0], uncompressed_solvable_address[0]])[ + 'address']) + compressed_solvable_address.append( + self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_solvable_address[0]])[ + 'address']) premature_witaddress = [] @@ -486,7 +557,8 @@ def run_test(self): [bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v) premature_witaddress.append(script_to_p2sh(p2wsh)) else: - [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) + [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, + p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) # P2WPKH, P2SH_P2WPKH are always spendable spendable_anytime.extend([p2wpkh, p2sh_p2wpkh]) @@ -497,7 +569,8 @@ def run_test(self): # P2WSH and P2SH(P2WSH) multisig with uncompressed keys are never seen unseen_anytime.extend([p2wsh, p2sh_p2wsh]) else: - [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) + [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, + p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) # P2WPKH, P2SH_P2WPKH with uncompressed keys are never seen unseen_anytime.extend([p2wpkh, p2sh_p2wpkh]) @@ -507,7 +580,8 @@ def run_test(self): [bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v) premature_witaddress.append(script_to_p2sh(p2wsh)) else: - [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) + [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, + p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v) # P2SH_P2PK, P2SH_P2PKH with compressed keys are always solvable solvable_anytime.extend([p2wpkh, p2sh_p2wpkh]) @@ -589,7 +663,7 @@ def p2sh_address_to_script(self, v): p2sh = CScript(hex_str_to_bytes(v['scriptPubKey'])) p2wsh = CScript([OP_0, sha256(bare)]) p2sh_p2wsh = CScript([OP_HASH160, hash160(p2wsh), OP_EQUAL]) - return([bare, p2sh, p2wsh, p2sh_p2wsh]) + return ([bare, p2sh, p2wsh, p2sh_p2wsh]) def p2pkh_address_to_script(self, v): pubkey = hex_str_to_bytes(v['pubkey']) @@ -603,7 +677,8 @@ def p2pkh_address_to_script(self, v): p2wsh_p2pkh = CScript([OP_0, sha256(p2pkh)]) p2sh_p2wsh_p2pk = CScript([OP_HASH160, hash160(p2wsh_p2pk), OP_EQUAL]) p2sh_p2wsh_p2pkh = CScript([OP_HASH160, hash160(p2wsh_p2pkh), OP_EQUAL]) - return [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] + return [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, + p2sh_p2wsh_p2pkh] def create_and_mine_tx_from_txids(self, txids, success=True): tx = CTransaction() diff --git a/test/functional/feature_sendtokenstoaddress.py b/test/functional/feature_sendtokenstoaddress.py index c4e0b773a8..f3a48b1fc8 100755 --- a/test/functional/feature_sendtokenstoaddress.py +++ b/test/functional/feature_sendtokenstoaddress.py @@ -13,7 +13,8 @@ from test_framework.util import assert_equal from decimal import Decimal -class SendTokensToAddressTest (DefiTestFramework): + +class SendTokensToAddressTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 self.setup_clean_chain = True @@ -25,7 +26,7 @@ def set_test_params(self): ] def run_test(self): - assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI + assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI print("Generating initial chain...") tokens = [ @@ -102,10 +103,11 @@ def run_test(self): wallet1_addr2_balance = self.nodes[0].getaccount(wallet1_addr2, {}, True) # crumbs gets amount by asc order, 0 balances not present - assert(token1_tokenId not in wallet1_addr1_balance) - assert(token0_tokenId not in wallet1_addr2_balance) + assert (token1_tokenId not in wallet1_addr1_balance) + assert (token0_tokenId not in wallet1_addr2_balance) assert_equal(wallet1_addr1_balance[token0_tokenId], Decimal(9)) assert_equal(wallet1_addr2_balance[token1_tokenId], Decimal(8)) + if __name__ == '__main__': SendTokensToAddressTest().main() diff --git a/test/functional/feature_sendutxosfrom.py b/test/functional/feature_sendutxosfrom.py index ee581eef28..bf3b844571 100755 --- a/test/functional/feature_sendutxosfrom.py +++ b/test/functional/feature_sendutxosfrom.py @@ -10,6 +10,7 @@ from test_framework.authproxy import JSONRPCException from test_framework.util import assert_equal + class SendUTXOsFromTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 @@ -31,7 +32,7 @@ def run_test(self): self.nodes[1].sendutxosfrom(address, to, 0.1) except JSONRPCException as e: errorString = e.error['message'] - assert("Insufficient funds" in errorString) + assert ("Insufficient funds" in errorString) # Fund from address for _ in range(10): @@ -44,29 +45,28 @@ def run_test(self): self.nodes[1].sendutxosfrom("", to, 0.1) except JSONRPCException as e: errorString = e.error['message'] - assert("Invalid from address" in errorString) + assert ("Invalid from address" in errorString) # Invalid to address try: self.nodes[1].sendutxosfrom(address, "", 0.1) except JSONRPCException as e: errorString = e.error['message'] - assert("Invalid to address" in errorString) - + assert ("Invalid to address" in errorString) # Invalid change address try: self.nodes[1].sendutxosfrom(address, to, 0.1, "") except JSONRPCException as e: errorString = e.error['message'] - assert("Invalid change address" in errorString) + assert ("Invalid change address" in errorString) # Try sending too little try: self.nodes[1].sendutxosfrom(address, to, 0) except JSONRPCException as e: errorString = e.error['message'] - assert("Invalid amount" in errorString) + assert ("Invalid amount" in errorString) # Fund many addresses for _ in range(100): @@ -92,7 +92,7 @@ def run_test(self): if change in vout['scriptPubKey']['addresses']: found = True - assert(found) + assert (found) # Test send with change to default from address txid = self.nodes[1].sendutxosfrom(address, to, 1.5) @@ -112,7 +112,7 @@ def run_test(self): if address in vout['scriptPubKey']['addresses']: found = True - assert(found) + assert (found) # Test fee is not deducted from recipient 'to' amount = 2.5 @@ -128,7 +128,8 @@ def run_test(self): found = True assert_equal(vout['value'], amount) - assert(found) + assert (found) + if __name__ == '__main__': SendUTXOsFromTest().main() diff --git a/test/functional/feature_setgov.py b/test/functional/feature_setgov.py index 5d7b435c60..7826a42fd6 100755 --- a/test/functional/feature_setgov.py +++ b/test/functional/feature_setgov.py @@ -16,13 +16,18 @@ from decimal import Decimal import time -class GovsetTest (DefiTestFramework): + +class GovsetTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 self.setup_clean_chain = True self.extra_args = [ - ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-eunosheight=200', '-fortcanningheight=400', '-fortcanninghillheight=1110', '-fortcanningroadheight=1150', '-fortcanningcrunchheight=1200', '-fortcanningspringheight=1250', '-grandcentralheight=1300', '-subsidytest=1'], - ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-eunosheight=200', '-fortcanningheight=400', '-fortcanninghillheight=1110', '-fortcanningroadheight=1150', '-fortcanningcrunchheight=1200', '-fortcanningspringheight=1250', '-grandcentralheight=1300', '-subsidytest=1']] + ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-eunosheight=200', '-fortcanningheight=400', + '-fortcanninghillheight=1110', '-fortcanningroadheight=1150', '-fortcanningcrunchheight=1200', + '-fortcanningspringheight=1250', '-grandcentralheight=1300', '-subsidytest=1'], + ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-eunosheight=200', '-fortcanningheight=400', + '-fortcanninghillheight=1110', '-fortcanningroadheight=1150', '-fortcanningcrunchheight=1200', + '-fortcanningspringheight=1250', '-grandcentralheight=1300', '-subsidytest=1']] def run_test(self): self.setup_tokens() @@ -35,12 +40,12 @@ def run_test(self): self.nodes[0].setgov({"REWARD": "any"}) except JSONRPCException as e: errorString = e.error['message'] - assert("not registered" in errorString) + assert ("not registered" in errorString) try: self.nodes[0].getgov("REWARD") except JSONRPCException as e: errorString = e.error['message'] - assert("not registered" in errorString) + assert ("not registered" in errorString) # # prepare the pools for LP_SPLITS @@ -53,7 +58,7 @@ def run_test(self): self.nodes[0].createtoken({ "symbol": "BRONZE", "name": "just bronze", - "collateralAddress": owner # doesn't matter + "collateralAddress": owner # doesn't matter }) self.nodes[0].generate(1) @@ -82,46 +87,46 @@ def run_test(self): "pairSymbol": "SB", }, []) self.nodes[0].generate(1) - assert(len(self.nodes[0].listpoolpairs()) == 3) + assert (len(self.nodes[0].listpoolpairs()) == 3) # set LP_SPLITS with absent pools id try: self.nodes[0].setgov({ - "LP_SPLITS": { "0": 0.5, "1": 0.4, "2": 0.2 } - }) + "LP_SPLITS": {"0": 0.5, "1": 0.4, "2": 0.2} + }) except JSONRPCException as e: errorString = e.error['message'] - assert("id=0 not found" in errorString) + assert ("id=0 not found" in errorString) # set LP_SPLITS with total >100% try: self.nodes[0].setgov({ - "LP_SPLITS": { "1": 0.5, "2": 0.4, "3": 0.2 } - }) + "LP_SPLITS": {"1": 0.5, "2": 0.4, "3": 0.2} + }) except JSONRPCException as e: errorString = e.error['message'] - assert("total" in errorString) - + assert ("total" in errorString) self.nodes[0].setgov({ - "LP_SPLITS": { "1": 0.5, "2": 0.4, "3": 0.1 } + "LP_SPLITS": {"1": 0.5, "2": 0.4, "3": 0.1} }) - self.nodes[0].setgov({ "LP_DAILY_DFI_REWARD": 35.5}) + self.nodes[0].setgov({"LP_DAILY_DFI_REWARD": 35.5}) self.nodes[0].generate(1) g1 = self.nodes[0].getgov("LP_SPLITS") - assert (g1 == {'LP_SPLITS': {'1': Decimal('0.50000000'), '2': Decimal('0.40000000'), '3': Decimal('0.10000000')}} ) + assert (g1 == { + 'LP_SPLITS': {'1': Decimal('0.50000000'), '2': Decimal('0.40000000'), '3': Decimal('0.10000000')}}) g2 = self.nodes[0].getgov("LP_DAILY_DFI_REWARD") - assert(g2 == {'LP_DAILY_DFI_REWARD': Decimal('35.50000000')} ) + assert (g2 == {'LP_DAILY_DFI_REWARD': Decimal('35.50000000')}) pool1 = self.nodes[0].getpoolpair("1", True)['1'] pool2 = self.nodes[0].getpoolpair("2", True)['2'] pool3 = self.nodes[0].getpoolpair("3", True)['3'] assert (pool1['rewardPct'] == Decimal('0.50000000') - and pool2['rewardPct'] == Decimal('0.40000000') - and pool3['rewardPct'] == Decimal('0.10000000')) + and pool2['rewardPct'] == Decimal('0.40000000') + and pool3['rewardPct'] == Decimal('0.10000000')) # start node 1 and sync for reverting to this chain point self.start_node(1) @@ -130,30 +135,31 @@ def run_test(self): # check sync between nodes 0 and 1 g1 = self.nodes[1].getgov("LP_SPLITS") - assert (g1 == {'LP_SPLITS': {'1': Decimal('0.50000000'), '2': Decimal('0.40000000'), '3': Decimal('0.10000000')}} ) + assert (g1 == { + 'LP_SPLITS': {'1': Decimal('0.50000000'), '2': Decimal('0.40000000'), '3': Decimal('0.10000000')}}) g2 = self.nodes[1].getgov("LP_DAILY_DFI_REWARD") - assert(g2 == {'LP_DAILY_DFI_REWARD': Decimal('35.50000000')} ) + assert (g2 == {'LP_DAILY_DFI_REWARD': Decimal('35.50000000')}) pool1 = self.nodes[1].getpoolpair("1", True)['1'] pool2 = self.nodes[1].getpoolpair("2", True)['2'] pool3 = self.nodes[1].getpoolpair("3", True)['3'] assert (pool1['rewardPct'] == Decimal('0.50000000') - and pool2['rewardPct'] == Decimal('0.40000000') - and pool3['rewardPct'] == Decimal('0.10000000')) + and pool2['rewardPct'] == Decimal('0.40000000') + and pool3['rewardPct'] == Decimal('0.10000000')) # disconnect node #1 disconnect_nodes(self.nodes[0], 1) # test set multuple: self.nodes[0].setgov({ - "LP_SPLITS": { "1": 1 }, + "LP_SPLITS": {"1": 1}, "LP_DAILY_DFI_REWARD": 45 }) self.nodes[0].generate(1) g1 = self.nodes[0].getgov("LP_SPLITS") - assert (g1 == {'LP_SPLITS': {'1': 1}} ) + assert (g1 == {'LP_SPLITS': {'1': 1}}) # test that all previous pool's values was reset pool1 = self.nodes[0].getpoolpair("1", True)['1'] @@ -164,7 +170,7 @@ def run_test(self): assert (pool3['rewardPct'] == 0) g2 = self.nodes[0].getgov("LP_DAILY_DFI_REWARD") - assert(g2 == {'LP_DAILY_DFI_REWARD': 45} ) + assert (g2 == {'LP_DAILY_DFI_REWARD': 45}) # REVERTING # mine blocks at node 1 @@ -175,17 +181,18 @@ def run_test(self): # check that node 0 was synced to neccesary chain point g1 = self.nodes[0].getgov("LP_SPLITS") - assert (g1 == {'LP_SPLITS': {'1': Decimal('0.50000000'), '2': Decimal('0.40000000'), '3': Decimal('0.10000000')}} ) + assert (g1 == { + 'LP_SPLITS': {'1': Decimal('0.50000000'), '2': Decimal('0.40000000'), '3': Decimal('0.10000000')}}) g2 = self.nodes[0].getgov("LP_DAILY_DFI_REWARD") - assert(g2 == {'LP_DAILY_DFI_REWARD': Decimal('35.50000000')} ) + assert (g2 == {'LP_DAILY_DFI_REWARD': Decimal('35.50000000')}) pool1 = self.nodes[0].getpoolpair("1", True)['1'] pool2 = self.nodes[0].getpoolpair("2", True)['2'] pool3 = self.nodes[0].getpoolpair("3", True)['3'] assert (pool1['rewardPct'] == Decimal('0.50000000') - and pool2['rewardPct'] == Decimal('0.40000000') - and pool3['rewardPct'] == Decimal('0.10000000')) + and pool2['rewardPct'] == Decimal('0.40000000') + and pool3['rewardPct'] == Decimal('0.10000000')) self.nodes[0].clearmempool() # Generate to Eunos hard fork @@ -193,13 +200,14 @@ def run_test(self): # Try and set LP_DAILY_DFI_REWARD manually try: - self.nodes[0].setgov({ "LP_DAILY_DFI_REWARD": 100}) + self.nodes[0].setgov({"LP_DAILY_DFI_REWARD": 100}) except JSONRPCException as e: errorString = e.error['message'] - assert("Cannot be set manually after Eunos hard fork" in errorString) + assert ("Cannot be set manually after Eunos hard fork" in errorString) # Check new subsidy - assert_equal(self.nodes[0].getgov('LP_DAILY_DFI_REWARD')['LP_DAILY_DFI_REWARD'], Decimal('14843.90592000')) # 144 blocks a day times 103.08268000 + assert_equal(self.nodes[0].getgov('LP_DAILY_DFI_REWARD')['LP_DAILY_DFI_REWARD'], + Decimal('14843.90592000')) # 144 blocks a day times 103.08268000 # Roll back self.nodes[0].invalidateblock(self.nodes[0].getblockhash(self.nodes[0].getblockcount())) @@ -209,7 +217,8 @@ def run_test(self): # Move to second reduction and check reward self.nodes[0].generate(350 - self.nodes[0].getblockcount()) - assert_equal(self.nodes[0].getgov('LP_DAILY_DFI_REWARD')['LP_DAILY_DFI_REWARD'], Decimal('14597.79395904')) # 144 blocks a day times 101.37356916 + assert_equal(self.nodes[0].getgov('LP_DAILY_DFI_REWARD')['LP_DAILY_DFI_REWARD'], + Decimal('14597.79395904')) # 144 blocks a day times 101.37356916 # Rollback from second reduction self.nodes[0].invalidateblock(self.nodes[0].getblockhash(self.nodes[0].getblockcount())) @@ -218,109 +227,115 @@ def run_test(self): assert_equal(self.nodes[0].getgov('LP_DAILY_DFI_REWARD')['LP_DAILY_DFI_REWARD'], Decimal('14843.90592000')) # Check LP_DAILY_LOAN_TOKEN_REWARD before FortCanning - assert_equal(self.nodes[0].getgov('LP_DAILY_LOAN_TOKEN_REWARD')['LP_DAILY_LOAN_TOKEN_REWARD'], Decimal('0.00000000')) + assert_equal(self.nodes[0].getgov('LP_DAILY_LOAN_TOKEN_REWARD')['LP_DAILY_LOAN_TOKEN_REWARD'], + Decimal('0.00000000')) # Try and use setgovheight start height before FortCanning try: - self.nodes[0].setgov({ "ORACLE_BLOCK_INTERVAL": 200}) + self.nodes[0].setgov({"ORACLE_BLOCK_INTERVAL": 200}) except JSONRPCException as e: errorString = e.error['message'] - assert("Cannot be set before FortCanning" in errorString) + assert ("Cannot be set before FortCanning" in errorString) # Try and set LP_LOAN_TOKEN_SPLITS before FortCanning try: - self.nodes[0].setgov({"LP_LOAN_TOKEN_SPLITS": { "1": 0.1, "2": 0.2, "3": 0.7 }}) + self.nodes[0].setgov({"LP_LOAN_TOKEN_SPLITS": {"1": 0.1, "2": 0.2, "3": 0.7}}) except JSONRPCException as e: errorString = e.error['message'] - assert("Cannot be set before FortCanning" in errorString) + assert ("Cannot be set before FortCanning" in errorString) # Generate to FortCanning self.nodes[0].generate(400 - self.nodes[0].getblockcount()) # Try and use setgovheight with ORACLE_BLOCK_INTERVAL try: - self.nodes[0].setgovheight({ "ORACLE_BLOCK_INTERVAL": 200}, 600) + self.nodes[0].setgovheight({"ORACLE_BLOCK_INTERVAL": 200}, 600) except JSONRPCException as e: errorString = e.error['message'] - assert("Cannot set via setgovheight." in errorString) + assert ("Cannot set via setgovheight." in errorString) # Test ORACLE_BLOCK_INTERVAL try: - self.nodes[0].setgov({ "ORACLE_BLOCK_INTERVAL": 0}) + self.nodes[0].setgov({"ORACLE_BLOCK_INTERVAL": 0}) except JSONRPCException as e: errorString = e.error['message'] - assert("Block interval cannot be less than 1" in errorString) + assert ("Block interval cannot be less than 1" in errorString) try: - self.nodes[0].setgov({ "ORACLE_BLOCK_INTERVAL": "120"}) + self.nodes[0].setgov({"ORACLE_BLOCK_INTERVAL": "120"}) except JSONRPCException as e: errorString = e.error['message'] - assert("Block interval amount is not a number" in errorString) + assert ("Block interval amount is not a number" in errorString) # Empty variable try: self.nodes[0].setgovheight({}, 600) except JSONRPCException as e: errorString = e.error['message'] - assert("No Governance variable provided" in errorString) + assert ("No Governance variable provided" in errorString) # Test changing Gov var by height. Check equal to next block failure. try: - self.nodes[0].setgovheight({ "ORACLE_DEVIATION": Decimal('0.01000000')}, self.nodes[0].getblockcount() + 1) + self.nodes[0].setgovheight({"ORACLE_DEVIATION": Decimal('0.01000000')}, self.nodes[0].getblockcount() + 1) except JSONRPCException as e: errorString = e.error['message'] - assert("startHeight must be above the current block height" in errorString) + assert ("startHeight must be above the current block height" in errorString) # Make sure erronous values still get picked up try: - self.nodes[0].setgovheight({ "ORACLE_DEVIATION": Decimal('0.00100000')}, self.nodes[0].getblockcount() + 10) + self.nodes[0].setgovheight({"ORACLE_DEVIATION": Decimal('0.00100000')}, self.nodes[0].getblockcount() + 10) except JSONRPCException as e: errorString = e.error['message'] - assert("Deviation cannot be less than 1 percent" in errorString) + assert ("Deviation cannot be less than 1 percent" in errorString) # Check new subsidy - assert_equal(self.nodes[0].getgov('LP_DAILY_LOAN_TOKEN_REWARD')['LP_DAILY_LOAN_TOKEN_REWARD'], Decimal('14156.13182400')) # 144 blocks a day times 98.30647100 + assert_equal(self.nodes[0].getgov('LP_DAILY_LOAN_TOKEN_REWARD')['LP_DAILY_LOAN_TOKEN_REWARD'], + Decimal('14156.13182400')) # 144 blocks a day times 98.30647100 # Roll back self.nodes[0].invalidateblock(self.nodes[0].getblockhash(self.nodes[0].getblockcount())) # Check subsidy restored - assert_equal(self.nodes[0].getgov('LP_DAILY_LOAN_TOKEN_REWARD')['LP_DAILY_LOAN_TOKEN_REWARD'], Decimal('0.00000000')) + assert_equal(self.nodes[0].getgov('LP_DAILY_LOAN_TOKEN_REWARD')['LP_DAILY_LOAN_TOKEN_REWARD'], + Decimal('0.00000000')) # Move to next reduction and check reward self.nodes[0].generate(500 - self.nodes[0].getblockcount()) - assert_equal(self.nodes[0].getgov('LP_DAILY_LOAN_TOKEN_REWARD')['LP_DAILY_LOAN_TOKEN_REWARD'], Decimal('13921.42315824')) # 144 blocks a day times 96.67654971 + assert_equal(self.nodes[0].getgov('LP_DAILY_LOAN_TOKEN_REWARD')['LP_DAILY_LOAN_TOKEN_REWARD'], + Decimal('13921.42315824')) # 144 blocks a day times 96.67654971 # Rollback from second reduction self.nodes[0].invalidateblock(self.nodes[0].getblockhash(self.nodes[0].getblockcount())) # Check subsidy restored - assert_equal(self.nodes[0].getgov('LP_DAILY_LOAN_TOKEN_REWARD')['LP_DAILY_LOAN_TOKEN_REWARD'], Decimal('14156.13182400')) + assert_equal(self.nodes[0].getgov('LP_DAILY_LOAN_TOKEN_REWARD')['LP_DAILY_LOAN_TOKEN_REWARD'], + Decimal('14156.13182400')) # Test ORACLE_DEVIATION try: - self.nodes[0].setgov({ "ORACLE_DEVIATION": Decimal('0.00100000')}) + self.nodes[0].setgov({"ORACLE_DEVIATION": Decimal('0.00100000')}) except JSONRPCException as e: errorString = e.error['message'] - assert("Deviation cannot be less than 1 percent" in errorString) + assert ("Deviation cannot be less than 1 percent" in errorString) - self.nodes[0].setgov({ "ORACLE_DEVIATION": Decimal('0.01000000')}) + self.nodes[0].setgov({"ORACLE_DEVIATION": Decimal('0.01000000')}) self.nodes[0].generate(1) assert_equal(self.nodes[0].getgov("ORACLE_DEVIATION")["ORACLE_DEVIATION"], Decimal('0.01000000')) # Test LOAN_LIQUIDATION_PENALTY try: - self.nodes[0].setgov({ "LOAN_LIQUIDATION_PENALTY": Decimal('0.00100000')}) + self.nodes[0].setgov({"LOAN_LIQUIDATION_PENALTY": Decimal('0.00100000')}) except JSONRPCException as e: errorString = e.error['message'] - assert("Penalty cannot be less than 0.01 DFI" in errorString) + assert ("Penalty cannot be less than 0.01 DFI" in errorString) - self.nodes[0].setgov({ "LOAN_LIQUIDATION_PENALTY": Decimal('0.01000000')}) + self.nodes[0].setgov({"LOAN_LIQUIDATION_PENALTY": Decimal('0.01000000')}) self.nodes[0].generate(1) - assert_equal(self.nodes[0].getgov("LOAN_LIQUIDATION_PENALTY")["LOAN_LIQUIDATION_PENALTY"], Decimal('0.01000000')) + assert_equal(self.nodes[0].getgov("LOAN_LIQUIDATION_PENALTY")["LOAN_LIQUIDATION_PENALTY"], + Decimal('0.01000000')) # Set Gov var change 10 blocks ahead. - self.nodes[0].setgovheight({ "ORACLE_DEVIATION": Decimal('0.02000000')}, self.nodes[0].getblockcount() + 10) + self.nodes[0].setgovheight({"ORACLE_DEVIATION": Decimal('0.02000000')}, self.nodes[0].getblockcount() + 10) self.nodes[0].generate(1) assert_equal(self.nodes[0].getgov('ORACLE_DEVIATION')['ORACLE_DEVIATION'], Decimal('0.01000000')) self.nodes[0].generate(9) @@ -336,43 +351,46 @@ def run_test(self): # Test multiple queued changes and make sure the last one is that one that take effect activate = self.nodes[0].getblockcount() + 10 - self.nodes[0].setgovheight({"LP_SPLITS": { "1": 0.1, "2": 0.2, "3": 0.7 }}, activate) + self.nodes[0].setgovheight({"LP_SPLITS": {"1": 0.1, "2": 0.2, "3": 0.7}}, activate) self.nodes[0].generate(1) - self.nodes[0].setgovheight({"LP_SPLITS": { "1": 0.2, "2": 0.2, "3": 0.6 }}, activate) + self.nodes[0].setgovheight({"LP_SPLITS": {"1": 0.2, "2": 0.2, "3": 0.6}}, activate) self.nodes[0].generate(1) - self.nodes[0].setgovheight({"LP_SPLITS": { "1": 0.3, "2": 0.2, "3": 0.5 }}, activate) + self.nodes[0].setgovheight({"LP_SPLITS": {"1": 0.3, "2": 0.2, "3": 0.5}}, activate) self.nodes[0].generate(1) - self.nodes[0].setgovheight({"LP_SPLITS": { "1": 0.4, "2": 0.2, "3": 0.4 }}, activate) + self.nodes[0].setgovheight({"LP_SPLITS": {"1": 0.4, "2": 0.2, "3": 0.4}}, activate) self.nodes[0].generate(7) - assert_equal(self.nodes[0].getgov('LP_SPLITS')['LP_SPLITS'], {'1': Decimal('0.40000000'), '2': Decimal('0.20000000'), '3': Decimal('0.40000000')}) + assert_equal(self.nodes[0].getgov('LP_SPLITS')['LP_SPLITS'], + {'1': Decimal('0.40000000'), '2': Decimal('0.20000000'), '3': Decimal('0.40000000')}) # Test multiple updates on future height with multiple changes. activate = self.nodes[0].getblockcount() + 10 - self.nodes[0].setgovheight({"LP_SPLITS": { "1": 0.5, "2": 0.2, "3": 0.3 }}, activate) - self.nodes[0].setgovheight({ "ORACLE_DEVIATION": Decimal('0.03000000')}, activate) + self.nodes[0].setgovheight({"LP_SPLITS": {"1": 0.5, "2": 0.2, "3": 0.3}}, activate) + self.nodes[0].setgovheight({"ORACLE_DEVIATION": Decimal('0.03000000')}, activate) self.nodes[0].generate(1) - self.nodes[0].setgovheight({ "ORACLE_DEVIATION": Decimal('0.04000000')}, activate) + self.nodes[0].setgovheight({"ORACLE_DEVIATION": Decimal('0.04000000')}, activate) self.nodes[0].generate(1) - self.nodes[0].setgovheight({"LP_SPLITS": { "1": 0.6, "2": 0.2, "3": 0.2 }}, activate) + self.nodes[0].setgovheight({"LP_SPLITS": {"1": 0.6, "2": 0.2, "3": 0.2}}, activate) self.nodes[0].generate(1) - self.nodes[0].setgovheight({ "ORACLE_DEVIATION": Decimal('0.05000000')}, activate) + self.nodes[0].setgovheight({"ORACLE_DEVIATION": Decimal('0.05000000')}, activate) self.nodes[0].generate(1) - self.nodes[0].setgovheight({"LP_SPLITS": { "1": 0.7, "2": 0.2, "3": 0.1 }}, activate) + self.nodes[0].setgovheight({"LP_SPLITS": {"1": 0.7, "2": 0.2, "3": 0.1}}, activate) self.nodes[0].generate(6) - assert_equal(self.nodes[0].getgov('LP_SPLITS')['LP_SPLITS'], {'1': Decimal('0.70000000'), '2': Decimal('0.20000000'), '3': Decimal('0.10000000')}) + assert_equal(self.nodes[0].getgov('LP_SPLITS')['LP_SPLITS'], + {'1': Decimal('0.70000000'), '2': Decimal('0.20000000'), '3': Decimal('0.10000000')}) assert_equal(self.nodes[0].getgov('ORACLE_DEVIATION')['ORACLE_DEVIATION'], Decimal('0.05000000')) # Try and set less than 100% try: - self.nodes[0].setgov({"LP_LOAN_TOKEN_SPLITS": { "1": 0.1, "2": 0.2, "3": 0.3 }}) + self.nodes[0].setgov({"LP_LOAN_TOKEN_SPLITS": {"1": 0.1, "2": 0.2, "3": 0.3}}) except JSONRPCException as e: errorString = e.error['message'] - assert("60000000 vs expected 100000000" in errorString) + assert ("60000000 vs expected 100000000" in errorString) # Now set LP_LOAN_TOKEN_SPLITS - self.nodes[0].setgov({"LP_LOAN_TOKEN_SPLITS": { "1": 0.1, "2": 0.2, "3": 0.7 }}) + self.nodes[0].setgov({"LP_LOAN_TOKEN_SPLITS": {"1": 0.1, "2": 0.2, "3": 0.7}}) self.nodes[0].generate(1) - assert_equal(self.nodes[0].getgov('LP_LOAN_TOKEN_SPLITS')['LP_LOAN_TOKEN_SPLITS'], {'1': Decimal('0.10000000'), '2': Decimal('0.20000000'), '3': Decimal('0.70000000')}) + assert_equal(self.nodes[0].getgov('LP_LOAN_TOKEN_SPLITS')['LP_LOAN_TOKEN_SPLITS'], + {'1': Decimal('0.10000000'), '2': Decimal('0.20000000'), '3': Decimal('0.70000000')}) # Check reward set on pool pairs assert_equal(self.nodes[0].getpoolpair("1", True)['1']['rewardLoanPct'], Decimal('0.10000000')) @@ -383,19 +401,21 @@ def run_test(self): result = self.nodes[0].listgovs() assert_equal(result[0][0]['ICX_TAKERFEE_PER_BTC'], Decimal('0E-8')) assert_equal(result[1][0]['LP_DAILY_LOAN_TOKEN_REWARD'], Decimal('13921.42315824')) - assert_equal(result[2][0]['LP_LOAN_TOKEN_SPLITS'], {'1': Decimal('0.10000000'), '2': Decimal('0.20000000'), '3': Decimal('0.70000000')}) + assert_equal(result[2][0]['LP_LOAN_TOKEN_SPLITS'], + {'1': Decimal('0.10000000'), '2': Decimal('0.20000000'), '3': Decimal('0.70000000')}) assert_equal(result[3][0]['LP_DAILY_DFI_REWARD'], Decimal('14355.76253472')) assert_equal(result[4][0]['LOAN_LIQUIDATION_PENALTY'], Decimal('0.01000000')) - assert_equal(result[5][0]['LP_SPLITS'], {'1': Decimal('0.70000000'), '2': Decimal('0.20000000'), '3': Decimal('0.10000000')} ) + assert_equal(result[5][0]['LP_SPLITS'], + {'1': Decimal('0.70000000'), '2': Decimal('0.20000000'), '3': Decimal('0.10000000')}) assert_equal(result[6][0]['ORACLE_BLOCK_INTERVAL'], 0) assert_equal(result[7][0]['ORACLE_DEVIATION'], Decimal('0.05000000')) # Test visibility of pending changes in setgov activate = self.nodes[0].getblockcount() + 100 - self.nodes[0].setgovheight({ "ORACLE_DEVIATION": Decimal('0.06000000')}, activate) - self.nodes[0].setgovheight({ "ORACLE_DEVIATION": Decimal('0.07000000')}, activate + 1) - self.nodes[0].setgovheight({ "ICX_TAKERFEE_PER_BTC": Decimal('0.00100000')}, activate) - self.nodes[0].setgovheight({ "ICX_TAKERFEE_PER_BTC": Decimal('0.00200000')}, activate + 1) + self.nodes[0].setgovheight({"ORACLE_DEVIATION": Decimal('0.06000000')}, activate) + self.nodes[0].setgovheight({"ORACLE_DEVIATION": Decimal('0.07000000')}, activate + 1) + self.nodes[0].setgovheight({"ICX_TAKERFEE_PER_BTC": Decimal('0.00100000')}, activate) + self.nodes[0].setgovheight({"ICX_TAKERFEE_PER_BTC": Decimal('0.00200000')}, activate + 1) self.nodes[0].generate(1) # Test visibility of pending changes in listgovs @@ -408,15 +428,15 @@ def run_test(self): assert_equal(result[7][2][str(activate + 1)], Decimal('0.07000000')) # Test setting on next interval - interval = 6 # regtest default to 60 * 60 / 600 + interval = 6 # regtest default to 60 * 60 / 600 self.nodes[0].generate((self.nodes[0].getblockcount() % interval) + 1) - self.nodes[0].setgov({ "ORACLE_BLOCK_INTERVAL": 20}) + self.nodes[0].setgov({"ORACLE_BLOCK_INTERVAL": 20}) self.nodes[0].generate(1) interval = self.nodes[0].getgov("ORACLE_BLOCK_INTERVAL")["ORACLE_BLOCK_INTERVAL"] assert_equal(self.nodes[0].getgov("ORACLE_BLOCK_INTERVAL")["ORACLE_BLOCK_INTERVAL"], 20) # Set and view change pending for next interval - self.nodes[0].setgov({ "ORACLE_BLOCK_INTERVAL": 30}) + self.nodes[0].setgov({"ORACLE_BLOCK_INTERVAL": 30}) self.nodes[0].generate(1) result = self.nodes[0].listgovs() assert_equal(result[6][0]['ORACLE_BLOCK_INTERVAL'], 20) @@ -431,48 +451,81 @@ def run_test(self): assert_equal(result[6][0]['ORACLE_BLOCK_INTERVAL'], 30) # Test ATTRIBUTE before FCH - assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set before FortCanningHill", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/payback_dfi':'true'}}) + assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set before FortCanningHill", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/5/payback_dfi': 'true'}}) # Move to FCH fork self.nodes[0].generate(1110 - self.nodes[0].getblockcount()) # Set ATTRIBUTE with invalid settings - assert_raises_rpc_error(-5, "Object of values expected", self.nodes[0].setgov, {"ATTRIBUTES":'error'}) - assert_raises_rpc_error(-5, "Object of values expected", self.nodes[0].setgov, {"ATTRIBUTES":'{}'}) - assert_raises_rpc_error(-5, "Empty version", self.nodes[0].setgov, {"ATTRIBUTES":{'':'true'}}) - assert_raises_rpc_error(-5, "Unsupported version", self.nodes[0].setgov, {"ATTRIBUTES":{'1/token/15/payback_dfi':'true'}}) - assert_raises_rpc_error(-5, "Empty value", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/15/payback_dfi':''}}) - assert_raises_rpc_error(-5, "Incorrect key for . Object of ['//ID/','value'] expected", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/payback_dfi':'true'}}) - assert_raises_rpc_error(-5, "Unrecognised type argument provided, valid types are: consortium, gov, locks, oracles, params, poolpairs, token,", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/unrecognised/5/payback_dfi':'true'}}) - assert_raises_rpc_error(-5, "Unrecognised key argument provided, valid keys are: dex_in_fee_pct, dex_out_fee_pct, dfip2203, fixed_interval_price_id, loan_collateral_enabled, loan_collateral_factor, loan_minting_enabled, loan_minting_interest, loan_payback, loan_payback_collateral, loan_payback_fee_pct, payback_dfi, payback_dfi_fee_pct,", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/unrecognised':'true'}}) - assert_raises_rpc_error(-5, "Unrecognised key argument provided, valid keys are: members, mint_limit, mint_limit_daily,", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/consortium/5/unrecognised':'true'}}) - assert_raises_rpc_error(-5, "Value must be an integer", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/not_a_number/payback_dfi':'true'}}) - assert_raises_rpc_error(-5, 'Boolean value must be either "true" or "false"', self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/payback_dfi':'not_a_number'}}) - assert_raises_rpc_error(-5, 'Boolean value must be either "true" or "false"', self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/payback_dfi':'unrecognised'}}) - assert_raises_rpc_error(-5, "Amount must be a positive value", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/payback_dfi_fee_pct':'not_a_number'}}) - assert_raises_rpc_error(-5, "Amount must be a positive value", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/payback_dfi_fee_pct':'-1'}}) - assert_raises_rpc_error(-32600, "ATTRIBUTES: No such loan token (5)", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/payback_dfi':'true'}}) - assert_raises_rpc_error(-5, "Boolean value must be either \"true\" or \"false\"", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2201/active':'not_a_bool'}}) - assert_raises_rpc_error(-5, "Amount must be a positive value", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2201/minswap':'-1'}}) - assert_raises_rpc_error(-5, "Amount must be a positive value", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2201/minswap':'not_a_number'}}) - assert_raises_rpc_error(-5, "Amount must be a positive value", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2201/premium': 'not_a_number'}}) - assert_raises_rpc_error(-5, "Amount must be a positive value", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2201/premium': '-1'}}) - assert_raises_rpc_error(-5, "Unsupported type for DFIP2201", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2201/reward_pct': '0.1'}}) - assert_raises_rpc_error(-5, "Unsupported type for DFIP2201", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2201/block_period': '2880'}}) - assert_raises_rpc_error(-5, "Percentage exceeds 100%", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2201/premium': '1.00000001'}}) + assert_raises_rpc_error(-5, "Object of values expected", self.nodes[0].setgov, {"ATTRIBUTES": 'error'}) + assert_raises_rpc_error(-5, "Object of values expected", self.nodes[0].setgov, {"ATTRIBUTES": '{}'}) + assert_raises_rpc_error(-5, "Empty version", self.nodes[0].setgov, {"ATTRIBUTES": {'': 'true'}}) + assert_raises_rpc_error(-5, "Unsupported version", self.nodes[0].setgov, + {"ATTRIBUTES": {'1/token/15/payback_dfi': 'true'}}) + assert_raises_rpc_error(-5, "Empty value", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/15/payback_dfi': ''}}) + assert_raises_rpc_error(-5, + "Incorrect key for . Object of ['//ID/','value'] expected", + self.nodes[0].setgov, {"ATTRIBUTES": {'v0/token/payback_dfi': 'true'}}) + assert_raises_rpc_error(-5, + "Unrecognised type argument provided, valid types are: consortium, gov, locks, oracles, params, poolpairs, token,", + self.nodes[0].setgov, {"ATTRIBUTES": {'v0/unrecognised/5/payback_dfi': 'true'}}) + assert_raises_rpc_error(-5, + "Unrecognised key argument provided, valid keys are: dex_in_fee_pct, dex_out_fee_pct, dfip2203, fixed_interval_price_id, loan_collateral_enabled, loan_collateral_factor, loan_minting_enabled, loan_minting_interest, loan_payback, loan_payback_collateral, loan_payback_fee_pct, payback_dfi, payback_dfi_fee_pct,", + self.nodes[0].setgov, {"ATTRIBUTES": {'v0/token/5/unrecognised': 'true'}}) + assert_raises_rpc_error(-5, + "Unrecognised key argument provided, valid keys are: members, mint_limit, mint_limit_daily,", + self.nodes[0].setgov, {"ATTRIBUTES": {'v0/consortium/5/unrecognised': 'true'}}) + assert_raises_rpc_error(-5, "Value must be an integer", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/not_a_number/payback_dfi': 'true'}}) + assert_raises_rpc_error(-5, 'Boolean value must be either "true" or "false"', self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/5/payback_dfi': 'not_a_number'}}) + assert_raises_rpc_error(-5, 'Boolean value must be either "true" or "false"', self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/5/payback_dfi': 'unrecognised'}}) + assert_raises_rpc_error(-5, "Amount must be a positive value", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/5/payback_dfi_fee_pct': 'not_a_number'}}) + assert_raises_rpc_error(-5, "Amount must be a positive value", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/5/payback_dfi_fee_pct': '-1'}}) + assert_raises_rpc_error(-32600, "ATTRIBUTES: No such loan token (5)", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/5/payback_dfi': 'true'}}) + assert_raises_rpc_error(-5, "Boolean value must be either \"true\" or \"false\"", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2201/active': 'not_a_bool'}}) + assert_raises_rpc_error(-5, "Amount must be a positive value", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2201/minswap': '-1'}}) + assert_raises_rpc_error(-5, "Amount must be a positive value", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2201/minswap': 'not_a_number'}}) + assert_raises_rpc_error(-5, "Amount must be a positive value", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2201/premium': 'not_a_number'}}) + assert_raises_rpc_error(-5, "Amount must be a positive value", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2201/premium': '-1'}}) + assert_raises_rpc_error(-5, "Unsupported type for DFIP2201", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2201/reward_pct': '0.1'}}) + assert_raises_rpc_error(-5, "Unsupported type for DFIP2201", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2201/block_period': '2880'}}) + assert_raises_rpc_error(-5, "Percentage exceeds 100%", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2201/premium': '1.00000001'}}) # Check DFIP2203 attributes cannot be set before FCR - assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set before FortCanningRoad", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2203/active':'true'}}) - assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set before FortCanningRoad", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2203/reward_pct':'0.05'}}) - assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set before FortCanningRoad", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2203/block_period':'2880'}}) - assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set before FortCanningRoad", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/dfip2203':'true'}}) + assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set before FortCanningRoad", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2203/active': 'true'}}) + assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set before FortCanningRoad", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2203/reward_pct': '0.05'}}) + assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set before FortCanningRoad", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2203/block_period': '2880'}}) + assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set before FortCanningRoad", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/5/dfip2203': 'true'}}) # Setup for loan related tests oracle_address = self.nodes[0].getnewaddress("", "legacy") - appoint_oracle_tx = self.nodes[0].appointoracle(oracle_address, [{"currency": "USD", "token": "DFI"},{"currency": "USD", "token": "TSLA"},{"currency": "USD", "token": "AMZN"}], 1) + appoint_oracle_tx = self.nodes[0].appointoracle(oracle_address, [{"currency": "USD", "token": "DFI"}, + {"currency": "USD", "token": "TSLA"}, + {"currency": "USD", "token": "AMZN"}], 1) self.nodes[0].generate(1) - oracle_prices = [{"currency": "USD", "tokenAmount": "100.00000000@DFI"},{"currency": "USD", "tokenAmount": "100.00000000@TSLA"},{"currency": "USD", "tokenAmount": "100.00000000@AMZN"}] + oracle_prices = [{"currency": "USD", "tokenAmount": "100.00000000@DFI"}, + {"currency": "USD", "tokenAmount": "100.00000000@TSLA"}, + {"currency": "USD", "tokenAmount": "100.00000000@AMZN"}] self.nodes[0].setoracledata(appoint_oracle_tx, int(time.time()), oracle_prices) self.nodes[0].generate(12) @@ -488,11 +541,11 @@ def run_test(self): self.nodes[0].generate(1) self.nodes[0].setloantoken({ - 'symbol': 'TSLA', - 'name': "TSLA", - 'fixedIntervalPriceId': "TSLA/USD", - 'mintable': False, - 'interest': 5}) + 'symbol': 'TSLA', + 'name': "TSLA", + 'fixedIntervalPriceId': "TSLA/USD", + 'mintable': False, + 'interest': 5}) self.nodes[0].generate(1) self.nodes[0].setcollateraltoken({ @@ -502,52 +555,70 @@ def run_test(self): self.nodes[0].generate(1) # Test setting of new Gov var - self.nodes[0].setgov({"ATTRIBUTES":{'v0/token/5/payback_dfi':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/token/5/payback_dfi': 'true'}}) self.nodes[0].generate(1) assert_equal(self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'], {'v0/token/5/payback_dfi': 'true'}) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/token/5/payback_dfi_fee_pct':'0.05'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/token/5/payback_dfi_fee_pct': '0.05'}}) self.nodes[0].generate(1) - assert_equal(self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'], {'v0/token/5/payback_dfi': 'true', 'v0/token/5/payback_dfi_fee_pct': '0.05'}) - assert_equal(self.nodes[0].listgovs()[8][0]['ATTRIBUTES'], {'v0/token/5/payback_dfi': 'true', 'v0/token/5/payback_dfi_fee_pct': '0.05'}) + assert_equal(self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'], + {'v0/token/5/payback_dfi': 'true', 'v0/token/5/payback_dfi_fee_pct': '0.05'}) + assert_equal(self.nodes[0].listgovs()[8][0]['ATTRIBUTES'], + {'v0/token/5/payback_dfi': 'true', 'v0/token/5/payback_dfi_fee_pct': '0.05'}) # Test setting multiple ATTRIBUTES - self.nodes[0].setgov({"ATTRIBUTES":{'v0/token/5/payback_dfi':'false','v0/token/5/payback_dfi_fee_pct':'0.02378'}}) + self.nodes[0].setgov( + {"ATTRIBUTES": {'v0/token/5/payback_dfi': 'false', 'v0/token/5/payback_dfi_fee_pct': '0.02378'}}) self.nodes[0].generate(1) - assert_equal(self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'], {'v0/token/5/payback_dfi': 'false', 'v0/token/5/payback_dfi_fee_pct': '0.02378'}) + assert_equal(self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'], + {'v0/token/5/payback_dfi': 'false', 'v0/token/5/payback_dfi_fee_pct': '0.02378'}) # Test pending change activate = self.nodes[0].getblockcount() + 10 - self.nodes[0].setgovheight({"ATTRIBUTES":{'v0/token/5/payback_dfi':'true','v0/token/5/payback_dfi_fee_pct':'0.01'}}, activate) + self.nodes[0].setgovheight( + {"ATTRIBUTES": {'v0/token/5/payback_dfi': 'true', 'v0/token/5/payback_dfi_fee_pct': '0.01'}}, activate) self.nodes[0].generate(9) # No change yet - assert_equal(self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'], {'v0/token/5/payback_dfi': 'false', 'v0/token/5/payback_dfi_fee_pct': '0.02378'}) + assert_equal(self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'], + {'v0/token/5/payback_dfi': 'false', 'v0/token/5/payback_dfi_fee_pct': '0.02378'}) # Pending change present - assert_equal(self.nodes[0].listgovs()[8][1][str(activate)], {'v0/token/5/payback_dfi': 'true', 'v0/token/5/payback_dfi_fee_pct': '0.01'}) + assert_equal(self.nodes[0].listgovs()[8][1][str(activate)], + {'v0/token/5/payback_dfi': 'true', 'v0/token/5/payback_dfi_fee_pct': '0.01'}) # Check pending change applied self.nodes[0].generate(1) - assert_equal(self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'], {'v0/token/5/payback_dfi': 'true', 'v0/token/5/payback_dfi_fee_pct': '0.01'}) - assert_equal(self.nodes[0].listgovs()[8][0]['ATTRIBUTES'], {'v0/token/5/payback_dfi': 'true', 'v0/token/5/payback_dfi_fee_pct': '0.01'}) + assert_equal(self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'], + {'v0/token/5/payback_dfi': 'true', 'v0/token/5/payback_dfi_fee_pct': '0.01'}) + assert_equal(self.nodes[0].listgovs()[8][0]['ATTRIBUTES'], + {'v0/token/5/payback_dfi': 'true', 'v0/token/5/payback_dfi_fee_pct': '0.01'}) # Test params - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/dfip2201/active':'true','v0/params/dfip2201/minswap':'0.001','v0/params/dfip2201/premium':'0.025'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/dfip2201/active': 'true', 'v0/params/dfip2201/minswap': '0.001', + 'v0/params/dfip2201/premium': '0.025'}}) self.nodes[0].generate(1) - assert_equal(self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'], {'v0/params/dfip2201/active': 'true', 'v0/params/dfip2201/premium': '0.025', 'v0/params/dfip2201/minswap': '0.001', 'v0/token/5/payback_dfi': 'true', 'v0/token/5/payback_dfi_fee_pct': '0.01'}) - assert_equal(self.nodes[0].listgovs()[8][0]['ATTRIBUTES'], {'v0/params/dfip2201/active': 'true', 'v0/params/dfip2201/premium': '0.025', 'v0/params/dfip2201/minswap': '0.001', 'v0/token/5/payback_dfi': 'true', 'v0/token/5/payback_dfi_fee_pct': '0.01'}) + assert_equal(self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'], + {'v0/params/dfip2201/active': 'true', 'v0/params/dfip2201/premium': '0.025', + 'v0/params/dfip2201/minswap': '0.001', 'v0/token/5/payback_dfi': 'true', + 'v0/token/5/payback_dfi_fee_pct': '0.01'}) + assert_equal(self.nodes[0].listgovs()[8][0]['ATTRIBUTES'], + {'v0/params/dfip2201/active': 'true', 'v0/params/dfip2201/premium': '0.025', + 'v0/params/dfip2201/minswap': '0.001', 'v0/token/5/payback_dfi': 'true', + 'v0/token/5/payback_dfi_fee_pct': '0.01'}) # Move to FCR fork self.nodes[0].generate(1150 - self.nodes[0].getblockcount()) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/token/5/loan_payback/1': 'true', 'v0/token/5/loan_payback/2': 'true', 'v0/token/5/loan_payback_fee_pct/1': '0.25'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/token/5/loan_payback/1': 'true', 'v0/token/5/loan_payback/2': 'true', + 'v0/token/5/loan_payback_fee_pct/1': '0.25'}}) self.nodes[0].generate(1) attributes = self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'] assert_equal(attributes['v0/token/5/loan_payback/1'], 'true') assert_equal(attributes['v0/token/5/loan_payback/2'], 'true') assert_equal(attributes['v0/token/5/loan_payback_fee_pct/1'], '0.25') - self.nodes[0].setgov({"ATTRIBUTES":{'v0/token/5/loan_payback/0': 'true', 'v0/token/5/loan_payback_fee_pct/0': '0.33'}}) + self.nodes[0].setgov( + {"ATTRIBUTES": {'v0/token/5/loan_payback/0': 'true', 'v0/token/5/loan_payback_fee_pct/0': '0.33'}}) self.nodes[0].generate(1) attributes = self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'] @@ -555,10 +626,10 @@ def run_test(self): assert_equal(attributes['v0/token/5/payback_dfi'], 'true') assert_equal(attributes['v0/token/5/payback_dfi_fee_pct'], '0.33') # no new keys for DFI - assert('v0/token/5/loan_payback/0' not in attributes) - assert('v0/token/5/loan_payback_fee_pct/0' not in attributes) + assert ('v0/token/5/loan_payback/0' not in attributes) + assert ('v0/token/5/loan_payback_fee_pct/0' not in attributes) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/token/5/dex_in_fee_pct':'0.6','v0/token/5/dex_out_fee_pct':'0.12'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/token/5/dex_in_fee_pct': '0.6', 'v0/token/5/dex_out_fee_pct': '0.12'}}) self.nodes[0].generate(1) attributes = self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'] @@ -566,21 +637,33 @@ def run_test(self): assert_equal(attributes['v0/token/5/dex_out_fee_pct'], '0.12') # Set FCR ATTRIBUTE with invalid settings - assert_raises_rpc_error(-5, "Boolean value must be either \"true\" or \"false\"", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2203/active':'not_a_bool'}}) - assert_raises_rpc_error(-5, "Amount must be a positive value", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2203/reward_pct':'not_a_number'}}) - assert_raises_rpc_error(-5, "Amount must be a positive value", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2203/reward_pct':'-1'}}) - assert_raises_rpc_error(-5, "Percentage exceeds 100%", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2203/reward_pct':'2'}}) - assert_raises_rpc_error(-5, "Value must be a positive integer", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2203/block_period':'not_a_number'}}) - assert_raises_rpc_error(-5, "Value must be a positive integer", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2203/block_period':'-1'}}) - assert_raises_rpc_error(-5, "Boolean value must be either \"true\" or \"false\"", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/dfip2203':'not_a_bool'}}) - assert_raises_rpc_error(-32600, "No such loan token", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/4/dfip2203':'true'}}) - assert_raises_rpc_error(-5, "Unsupported type for this DFIP", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2203/premium': '0.025'}}) - assert_raises_rpc_error(-5, "Unsupported type for this DFIP", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2203/minswap': '0.025'}}) + assert_raises_rpc_error(-5, "Boolean value must be either \"true\" or \"false\"", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2203/active': 'not_a_bool'}}) + assert_raises_rpc_error(-5, "Amount must be a positive value", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2203/reward_pct': 'not_a_number'}}) + assert_raises_rpc_error(-5, "Amount must be a positive value", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2203/reward_pct': '-1'}}) + assert_raises_rpc_error(-5, "Percentage exceeds 100%", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2203/reward_pct': '2'}}) + assert_raises_rpc_error(-5, "Value must be a positive integer", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2203/block_period': 'not_a_number'}}) + assert_raises_rpc_error(-5, "Value must be a positive integer", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2203/block_period': '-1'}}) + assert_raises_rpc_error(-5, "Boolean value must be either \"true\" or \"false\"", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/5/dfip2203': 'not_a_bool'}}) + assert_raises_rpc_error(-32600, "No such loan token", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/4/dfip2203': 'true'}}) + assert_raises_rpc_error(-5, "Unsupported type for this DFIP", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2203/premium': '0.025'}}) + assert_raises_rpc_error(-5, "Unsupported type for this DFIP", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2203/minswap': '0.025'}}) # Test setting FCR ATTRBIUTES - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/dfip2203/reward_pct':'0.05','v0/params/dfip2203/block_period':'20160','v0/token/5/dfip2203':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/dfip2203/reward_pct': '0.05', + 'v0/params/dfip2203/block_period': '20160', + 'v0/token/5/dfip2203': 'true'}}) self.nodes[0].generate(1) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/dfip2203/active':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/dfip2203/active': 'true'}}) self.nodes[0].generate(1) # Verify FCR results @@ -597,24 +680,38 @@ def run_test(self): # Should only have attributes assert_equal(len(result[0]), 1) # Verify attributes - assert_equal(result[0][0], {'ATTRIBUTES': {'v0/token/5/payback_dfi': 'true', 'v0/token/5/payback_dfi_fee_pct': '0.33', 'v0/token/5/loan_payback/1': 'true', 'v0/token/5/loan_payback/2': 'true', 'v0/token/5/loan_payback_fee_pct/1': '0.25', 'v0/token/5/dex_in_fee_pct': '0.6', 'v0/token/5/dex_out_fee_pct': '0.12', 'v0/token/5/dfip2203': 'true'}}) + assert_equal(result[0][0], { + 'ATTRIBUTES': {'v0/token/5/payback_dfi': 'true', 'v0/token/5/payback_dfi_fee_pct': '0.33', + 'v0/token/5/loan_payback/1': 'true', 'v0/token/5/loan_payback/2': 'true', + 'v0/token/5/loan_payback_fee_pct/1': '0.25', 'v0/token/5/dex_in_fee_pct': '0.6', + 'v0/token/5/dex_out_fee_pct': '0.12', 'v0/token/5/dfip2203': 'true'}}) result = self.nodes[0].listgovs("token/5/loan") # Should only have attributes assert_equal(len(result[0]), 1) # Verify attributes - assert_equal(result[0][0], {'ATTRIBUTES': {'v0/token/5/loan_payback/1': 'true', 'v0/token/5/loan_payback/2': 'true', 'v0/token/5/loan_payback_fee_pct/1': '0.25'}}) + assert_equal(result[0][0], { + 'ATTRIBUTES': {'v0/token/5/loan_payback/1': 'true', 'v0/token/5/loan_payback/2': 'true', + 'v0/token/5/loan_payback_fee_pct/1': '0.25'}}) # test for manual v0 prefix result = self.nodes[0].listgovs("v0/token/5/loan") # Should only have attributes assert_equal(len(result[0]), 1) # Verify attributes - assert_equal(result[0][0], {'ATTRIBUTES': {'v0/token/5/loan_payback/1': 'true', 'v0/token/5/loan_payback/2': 'true', 'v0/token/5/loan_payback_fee_pct/1': '0.25'}}) + assert_equal(result[0][0], { + 'ATTRIBUTES': {'v0/token/5/loan_payback/1': 'true', 'v0/token/5/loan_payback/2': 'true', + 'v0/token/5/loan_payback_fee_pct/1': '0.25'}}) # gov only test result = self.nodes[0].listgovs("gov") - assert_equal(result, [[{'ICX_TAKERFEE_PER_BTC': Decimal('0.00200000')}], [{'LP_DAILY_LOAN_TOKEN_REWARD': Decimal('13020.86331792')}], [{'LP_LOAN_TOKEN_SPLITS': {'1': Decimal('0.10000000'), '2': Decimal('0.20000000'), '3': Decimal('0.70000000')}}], [{'LP_DAILY_DFI_REWARD': Decimal('13427.10581184')}], [{'LOAN_LIQUIDATION_PENALTY': Decimal('0.01000000')}], [{'LP_SPLITS': {'1': Decimal('0.70000000'), '2': Decimal('0.20000000'), '3': Decimal('0.10000000')}}], [{'ORACLE_BLOCK_INTERVAL': 30}], [{'ORACLE_DEVIATION': Decimal('0.07000000')}], []]) + assert_equal(result, [[{'ICX_TAKERFEE_PER_BTC': Decimal('0.00200000')}], + [{'LP_DAILY_LOAN_TOKEN_REWARD': Decimal('13020.86331792')}], [{'LP_LOAN_TOKEN_SPLITS': { + '1': Decimal('0.10000000'), '2': Decimal('0.20000000'), '3': Decimal('0.70000000')}}], + [{'LP_DAILY_DFI_REWARD': Decimal('13427.10581184')}], + [{'LOAN_LIQUIDATION_PENALTY': Decimal('0.01000000')}], [{'LP_SPLITS': { + '1': Decimal('0.70000000'), '2': Decimal('0.20000000'), '3': Decimal('0.10000000')}}], + [{'ORACLE_BLOCK_INTERVAL': 30}], [{'ORACLE_DEVIATION': Decimal('0.07000000')}], []]) # live test. No live on this. For now, just ensure, no other attrs are listed assert_equal(self.nodes[0].listgovs("live"), [[{'ATTRIBUTES': {}}]]) @@ -628,63 +725,131 @@ def run_test(self): assert_equal(result, result_27) assert_equal(result, result_all) - assert_equal(result, [[{'ICX_TAKERFEE_PER_BTC': Decimal('0.00200000')}], [{'LP_DAILY_LOAN_TOKEN_REWARD': Decimal('13020.86331792')}], [{'LP_LOAN_TOKEN_SPLITS': {'1': Decimal('0.10000000'), '2': Decimal('0.20000000'), '3': Decimal('0.70000000')}}], [{'LP_DAILY_DFI_REWARD': Decimal('13427.10581184')}], [{'LOAN_LIQUIDATION_PENALTY': Decimal('0.01000000')}], [{'LP_SPLITS': {'1': Decimal('0.70000000'), '2': Decimal('0.20000000'), '3': Decimal('0.10000000')}}], [{'ORACLE_BLOCK_INTERVAL': 30}], [{'ORACLE_DEVIATION': Decimal('0.07000000')}], [{'ATTRIBUTES': {'v0/params/dfip2201/active': 'true', 'v0/params/dfip2201/premium': '0.025', 'v0/params/dfip2201/minswap': '0.001', 'v0/params/dfip2203/active': 'true', 'v0/params/dfip2203/reward_pct': '0.05', 'v0/params/dfip2203/fee_pct': '0.05', 'v0/params/dfip2203/block_period': '20160', 'v0/token/5/payback_dfi': 'true', 'v0/token/5/payback_dfi_fee_pct': '0.33', 'v0/token/5/loan_payback/1': 'true', 'v0/token/5/loan_payback/2': 'true', 'v0/token/5/loan_payback_fee_pct/1': '0.25', 'v0/token/5/dex_in_fee_pct': '0.6', 'v0/token/5/dex_out_fee_pct': '0.12', 'v0/token/5/dfip2203': 'true'}}]]) + assert_equal(result, [[{'ICX_TAKERFEE_PER_BTC': Decimal('0.00200000')}], + [{'LP_DAILY_LOAN_TOKEN_REWARD': Decimal('13020.86331792')}], [{'LP_LOAN_TOKEN_SPLITS': { + '1': Decimal('0.10000000'), '2': Decimal('0.20000000'), '3': Decimal('0.70000000')}}], + [{'LP_DAILY_DFI_REWARD': Decimal('13427.10581184')}], + [{'LOAN_LIQUIDATION_PENALTY': Decimal('0.01000000')}], [{'LP_SPLITS': { + '1': Decimal('0.70000000'), '2': Decimal('0.20000000'), '3': Decimal('0.10000000')}}], + [{'ORACLE_BLOCK_INTERVAL': 30}], [{'ORACLE_DEVIATION': Decimal('0.07000000')}], [{ + 'ATTRIBUTES': { + 'v0/params/dfip2201/active': 'true', + 'v0/params/dfip2201/premium': '0.025', + 'v0/params/dfip2201/minswap': '0.001', + 'v0/params/dfip2203/active': 'true', + 'v0/params/dfip2203/reward_pct': '0.05', + 'v0/params/dfip2203/fee_pct': '0.05', + 'v0/params/dfip2203/block_period': '20160', + 'v0/token/5/payback_dfi': 'true', + 'v0/token/5/payback_dfi_fee_pct': '0.33', + 'v0/token/5/loan_payback/1': 'true', + 'v0/token/5/loan_payback/2': 'true', + 'v0/token/5/loan_payback_fee_pct/1': '0.25', + 'v0/token/5/dex_in_fee_pct': '0.6', + 'v0/token/5/dex_out_fee_pct': '0.12', + 'v0/token/5/dfip2203': 'true'}}]]) # Check errors - assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set before FortCanningCrunch", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/locks/token/5':'true'}}) - assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set before FortCanningCrunch", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/oracles/splits/4000': '1/50'}}) - assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set before FortCanningCrunch", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/fixed_interval_price_id':'TSLA/USD'}}) - assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set before FortCanningCrunch", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/loan_collateral_enabled':'true'}}) - assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set before FortCanningCrunch", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/loan_collateral_factor':'1.00000000'}}) - assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set before FortCanningCrunch", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/loan_minting_enabled':'true'}}) - assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set before FortCanningCrunch", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/loan_minting_interest':'5.00000000'}}) + assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set before FortCanningCrunch", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/locks/token/5': 'true'}}) + assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set before FortCanningCrunch", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/oracles/splits/4000': '1/50'}}) + assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set before FortCanningCrunch", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/5/fixed_interval_price_id': 'TSLA/USD'}}) + assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set before FortCanningCrunch", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/5/loan_collateral_enabled': 'true'}}) + assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set before FortCanningCrunch", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/5/loan_collateral_factor': '1.00000000'}}) + assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set before FortCanningCrunch", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/5/loan_minting_enabled': 'true'}}) + assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set before FortCanningCrunch", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/5/loan_minting_interest': '5.00000000'}}) # Move to FCC fork self.nodes[0].generate(1200 - self.nodes[0].getblockcount()) # Check errors - assert_raises_rpc_error(-5, "Unrecognised locks argument provided, valid lockss are: token,", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/locks/oracle/5':'true'}}) - assert_raises_rpc_error(-32600, "No loan token with id (4)", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/locks/token/4':'true'}}) - assert_raises_rpc_error(-5, "Unrecognised key argument provided", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/ascendant': '1'}}) - assert_raises_rpc_error(-5, "Unrecognised key argument provided", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/descendant': '1'}}) - assert_raises_rpc_error(-5, "Unrecognised key argument provided", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/epitaph': '1'}}) - assert_raises_rpc_error(-5, "Value must be an integer", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/oracles/splits/1200': '1/50,600'}}) - assert_raises_rpc_error(-5, "Two int values expected for split in id/mutliplier", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/oracles/splits/1200':'1/50,5/10'}}) - assert_raises_rpc_error(-5, "Mutliplier cannot be zero", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/oracles/splits/1201': '1/0'}}) - assert_raises_rpc_error(-32600, "ATTRIBUTES: Token (127) does not exist", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/oracles/splits/1201': '127/50'}}) - assert_raises_rpc_error(-32600, "ATTRIBUTES: Only DATs can be split", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/oracles/splits/1201': '128/50'}}) - assert_raises_rpc_error(-32600, "ATTRIBUTES: Tokenised DFI cannot be split", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/oracles/splits/1201': '0/50'}}) - assert_raises_rpc_error(-32600, "ATTRIBUTES: Pool tokens cannot be split", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/oracles/splits/1201': '1/50'}}) - assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set at or below current height", self.nodes[0].setgov, {"ATTRIBUTES":{f'v0/oracles/splits/{self.nodes[0].getblockcount()}': '5/50'}}) - assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set at or below current height", self.nodes[0].setgov, {"ATTRIBUTES":{f'v0/oracles/splits/{self.nodes[0].getblockcount() + 1}': '5/50'}}) - assert_raises_rpc_error(-32600, "ATTRIBUTES: Cumulative application of Gov vars failed: Cannot be set at or below current height", self.nodes[0].setgovheight, {"ATTRIBUTES":{f'v0/oracles/splits/2000': '5/50'}}, 2000) - assert_raises_rpc_error(-32600, "No loan token with id (4)", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/oracles/splits/4000':'4/2'}}) - assert_raises_rpc_error(-32600, "ATTRIBUTES: Price feed DUFF/USD does not belong to any oracle", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/fixed_interval_price_id':'DUFF/USD'}}) - assert_raises_rpc_error(-5, "Empty token / currency", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/fixed_interval_price_id':' /USD'}}) - assert_raises_rpc_error(-5, "Empty token / currency", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/fixed_interval_price_id':'DUFF/ '}}) - assert_raises_rpc_error(-5, "Empty token / currency", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/fixed_interval_price_id':' / '}}) - assert_raises_rpc_error(-32600, "No such token (127)", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/127/fixed_interval_price_id':'TSLA/USD'}}) - assert_raises_rpc_error(-5, "Exactly two entires expected for currency pair", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/fixed_interval_price_id':'5'}}) - assert_raises_rpc_error(-5, "Exactly two entires expected for currency pair", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/fixed_interval_price_id':'5/10/20'}}) - assert_raises_rpc_error(-5, "Boolean value must be either \"true\" or \"false\"", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/loan_collateral_enabled':'not_a_bool'}}) - assert_raises_rpc_error(-32600, "No such token (127)", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/127/loan_collateral_enabled':'true'}}) - assert_raises_rpc_error(-32600, "Fixed interval price currency pair must be set first", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/loan_collateral_enabled':'true'}}) - assert_raises_rpc_error(-5, "Amount must be a positive value", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/loan_collateral_factor':'-1'}}) - assert_raises_rpc_error(-32600, "Percentage exceeds 100%", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/loan_collateral_factor':'1.00000001'}}) - assert_raises_rpc_error(-5, "Amount must be a positive value", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/loan_collateral_factor':'not_a_number'}}) - assert_raises_rpc_error(-32600, "No such token (127)", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/127/loan_collateral_factor':'1'}}) - assert_raises_rpc_error(-32600, "Fixed interval price currency pair must be set first", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/loan_collateral_factor':'1'}}) - assert_raises_rpc_error(-5, "Boolean value must be either \"true\" or \"false\"", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/loan_minting_enabled':'not_a_bool'}}) - assert_raises_rpc_error(-32600, "No such token (127)", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/127/loan_minting_enabled':'true'}}) - assert_raises_rpc_error(-32600, "Fixed interval price currency pair must be set first", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/loan_minting_enabled':'true'}}) - assert_raises_rpc_error(-32600, "Amount must be a positive value", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/loan_minting_interest':'-1'}}) - assert_raises_rpc_error(-5, "Amount must be a valid number", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/loan_minting_interest':'not_a_number'}}) - assert_raises_rpc_error(-32600, "No such token (127)", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/127/loan_minting_interest':'1'}}) - assert_raises_rpc_error(-32600, "Fixed interval price currency pair must be set first", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/token/5/loan_minting_interest':'1'}}) - + assert_raises_rpc_error(-5, "Unrecognised locks argument provided, valid lockss are: token,", + self.nodes[0].setgov, {"ATTRIBUTES": {'v0/locks/oracle/5': 'true'}}) + assert_raises_rpc_error(-32600, "No loan token with id (4)", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/locks/token/4': 'true'}}) + assert_raises_rpc_error(-5, "Unrecognised key argument provided", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/5/ascendant': '1'}}) + assert_raises_rpc_error(-5, "Unrecognised key argument provided", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/5/descendant': '1'}}) + assert_raises_rpc_error(-5, "Unrecognised key argument provided", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/5/epitaph': '1'}}) + assert_raises_rpc_error(-5, "Value must be an integer", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/oracles/splits/1200': '1/50,600'}}) + assert_raises_rpc_error(-5, "Two int values expected for split in id/mutliplier", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/oracles/splits/1200': '1/50,5/10'}}) + assert_raises_rpc_error(-5, "Mutliplier cannot be zero", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/oracles/splits/1201': '1/0'}}) + assert_raises_rpc_error(-32600, "ATTRIBUTES: Token (127) does not exist", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/oracles/splits/1201': '127/50'}}) + assert_raises_rpc_error(-32600, "ATTRIBUTES: Only DATs can be split", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/oracles/splits/1201': '128/50'}}) + assert_raises_rpc_error(-32600, "ATTRIBUTES: Tokenised DFI cannot be split", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/oracles/splits/1201': '0/50'}}) + assert_raises_rpc_error(-32600, "ATTRIBUTES: Pool tokens cannot be split", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/oracles/splits/1201': '1/50'}}) + assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set at or below current height", self.nodes[0].setgov, + {"ATTRIBUTES": {f'v0/oracles/splits/{self.nodes[0].getblockcount()}': '5/50'}}) + assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set at or below current height", self.nodes[0].setgov, + {"ATTRIBUTES": {f'v0/oracles/splits/{self.nodes[0].getblockcount() + 1}': '5/50'}}) + assert_raises_rpc_error(-32600, + "ATTRIBUTES: Cumulative application of Gov vars failed: Cannot be set at or below current height", + self.nodes[0].setgovheight, {"ATTRIBUTES": {f'v0/oracles/splits/2000': '5/50'}}, 2000) + assert_raises_rpc_error(-32600, "No loan token with id (4)", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/oracles/splits/4000': '4/2'}}) + assert_raises_rpc_error(-32600, "ATTRIBUTES: Price feed DUFF/USD does not belong to any oracle", + self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/5/fixed_interval_price_id': 'DUFF/USD'}}) + assert_raises_rpc_error(-5, "Empty token / currency", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/5/fixed_interval_price_id': ' /USD'}}) + assert_raises_rpc_error(-5, "Empty token / currency", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/5/fixed_interval_price_id': 'DUFF/ '}}) + assert_raises_rpc_error(-5, "Empty token / currency", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/5/fixed_interval_price_id': ' / '}}) + assert_raises_rpc_error(-32600, "No such token (127)", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/127/fixed_interval_price_id': 'TSLA/USD'}}) + assert_raises_rpc_error(-5, "Exactly two entires expected for currency pair", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/5/fixed_interval_price_id': '5'}}) + assert_raises_rpc_error(-5, "Exactly two entires expected for currency pair", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/5/fixed_interval_price_id': '5/10/20'}}) + assert_raises_rpc_error(-5, "Boolean value must be either \"true\" or \"false\"", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/5/loan_collateral_enabled': 'not_a_bool'}}) + assert_raises_rpc_error(-32600, "No such token (127)", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/127/loan_collateral_enabled': 'true'}}) + assert_raises_rpc_error(-32600, "Fixed interval price currency pair must be set first", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/5/loan_collateral_enabled': 'true'}}) + assert_raises_rpc_error(-5, "Amount must be a positive value", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/5/loan_collateral_factor': '-1'}}) + assert_raises_rpc_error(-32600, "Percentage exceeds 100%", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/5/loan_collateral_factor': '1.00000001'}}) + assert_raises_rpc_error(-5, "Amount must be a positive value", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/5/loan_collateral_factor': 'not_a_number'}}) + assert_raises_rpc_error(-32600, "No such token (127)", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/127/loan_collateral_factor': '1'}}) + assert_raises_rpc_error(-32600, "Fixed interval price currency pair must be set first", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/5/loan_collateral_factor': '1'}}) + assert_raises_rpc_error(-5, "Boolean value must be either \"true\" or \"false\"", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/5/loan_minting_enabled': 'not_a_bool'}}) + assert_raises_rpc_error(-32600, "No such token (127)", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/127/loan_minting_enabled': 'true'}}) + assert_raises_rpc_error(-32600, "Fixed interval price currency pair must be set first", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/5/loan_minting_enabled': 'true'}}) + assert_raises_rpc_error(-32600, "Amount must be a positive value", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/5/loan_minting_interest': '-1'}}) + assert_raises_rpc_error(-5, "Amount must be a valid number", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/5/loan_minting_interest': 'not_a_number'}}) + assert_raises_rpc_error(-32600, "No such token (127)", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/127/loan_minting_interest': '1'}}) + assert_raises_rpc_error(-32600, "Fixed interval price currency pair must be set first", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/token/5/loan_minting_interest': '1'}}) # Set locks - self.nodes[0].setgov({"ATTRIBUTES":{'v0/locks/token/5':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/locks/token/5': 'true'}}) self.nodes[0].generate(1) # Check locks @@ -692,29 +857,31 @@ def run_test(self): assert_equal(attributes['v0/locks/token/5'], 'true') # Set loan token for 4 - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/4/fixed_interval_price_id':'TSLA/USD', f'v0/token/4/loan_minting_enabled':'true', f'v0/token/4/loan_minting_interest':'1'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/4/fixed_interval_price_id': 'TSLA/USD', + f'v0/token/4/loan_minting_enabled': 'true', + f'v0/token/4/loan_minting_interest': '1'}}) self.nodes[0].generate(1) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/oracles/splits/4000':'4/50'}}) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/oracles/splits/4001':'5/5'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/oracles/splits/4000': '4/50'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/oracles/splits/4001': '5/5'}}) self.nodes[0].generate(1) # Check auto lock assert_equal(self.nodes[0].listgovs()[8][1]['3928'], {'v0/locks/token/4': 'true'}) # Disable auto lock - self.nodes[0].setgovheight({"ATTRIBUTES":{'v0/locks/token/4':'false'}}, 3928) + self.nodes[0].setgovheight({"ATTRIBUTES": {'v0/locks/token/4': 'false'}}, 3928) self.nodes[0].generate(1) assert_equal(self.nodes[0].listgovs()[8][1]['3928'], {'v0/locks/token/4': 'false'}) # Re-enable auto lock - self.nodes[0].setgovheight({"ATTRIBUTES":{'v0/locks/token/4':'true'}}, 3928) + self.nodes[0].setgovheight({"ATTRIBUTES": {'v0/locks/token/4': 'true'}}, 3928) self.nodes[0].generate(1) assert_equal(self.nodes[0].listgovs()[8][1]['3928'], {'v0/locks/token/4': 'true'}) # Set pending split activation_height = self.nodes[0].getblockcount() + 5 - self.nodes[0].setgovheight({"ATTRIBUTES":{'v0/oracles/splits/4001':'5/10'}}, activation_height) + self.nodes[0].setgovheight({"ATTRIBUTES": {'v0/oracles/splits/4001': '5/10'}}, activation_height) self.nodes[0].generate(1) # Check value unchanged @@ -730,12 +897,12 @@ def run_test(self): # Set stored lock activation_height = self.nodes[0].getblockcount() + 5 - self.nodes[0].setgovheight({"ATTRIBUTES":{'v0/locks/token/4':'true'}}, activation_height) + self.nodes[0].setgovheight({"ATTRIBUTES": {'v0/locks/token/4': 'true'}}, activation_height) self.nodes[0].generate(1) # Make sure lock pending but not active attributes = self.nodes[0].listgovs()[8] - assert('v0/locks/token/4' not in attributes[0]['ATTRIBUTES']) + assert ('v0/locks/token/4' not in attributes[0]['ATTRIBUTES']) assert_equal(attributes[1][str(activation_height)]['v0/locks/token/4'], 'true') # Move to pending height @@ -746,12 +913,13 @@ def run_test(self): assert_equal(attributes['v0/locks/token/4'], 'true') # Disable lock - self.nodes[0].setgov({"ATTRIBUTES":{'v0/locks/token/5':'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/locks/token/5': 'false'}}) self.nodes[0].generate(1) # Set split activation_height = self.nodes[0].getblockcount() + 5 - self.nodes[0].setgovheight({"ATTRIBUTES":{f'v0/oracles/splits/{activation_height + 10}':'5/10'}}, activation_height) + self.nodes[0].setgovheight({"ATTRIBUTES": {f'v0/oracles/splits/{activation_height + 10}': '5/10'}}, + activation_height) self.nodes[0].generate(1) # Move to pending height @@ -762,39 +930,62 @@ def run_test(self): assert_equal(attributes['v0/locks/token/5'], 'true') # Try and set Gov vars before fork - assert_raises_rpc_error(-32600, "Cannot be set before FortCanningSpringHeight", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/poolpairs/3/token_a_fee_direction': 'both'}}) - assert_raises_rpc_error(-32600, "Cannot be set before FortCanningSpringHeight", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/poolpairs/3/token_b_fee_direction': 'both'}}) - assert_raises_rpc_error(-32600, "Cannot be set before FortCanningSpringHeight", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2206f/active':'true'}}) - assert_raises_rpc_error(-32600, "Cannot be set before FortCanningSpringHeight", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2206f/reward_pct':'0.05'}}) - assert_raises_rpc_error(-32600, "Cannot be set before FortCanningSpringHeight", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2206f/block_period':'2880'}}) - assert_raises_rpc_error(-32600, "Cannot be set before FortCanningSpringHeight", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2203/start_block':'0'}}) - assert_raises_rpc_error(-32600, "Cannot be set before FortCanningSpringHeight", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2206f/start_block':'0'}}) + assert_raises_rpc_error(-32600, "Cannot be set before FortCanningSpringHeight", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/poolpairs/3/token_a_fee_direction': 'both'}}) + assert_raises_rpc_error(-32600, "Cannot be set before FortCanningSpringHeight", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/poolpairs/3/token_b_fee_direction': 'both'}}) + assert_raises_rpc_error(-32600, "Cannot be set before FortCanningSpringHeight", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2206f/active': 'true'}}) + assert_raises_rpc_error(-32600, "Cannot be set before FortCanningSpringHeight", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2206f/reward_pct': '0.05'}}) + assert_raises_rpc_error(-32600, "Cannot be set before FortCanningSpringHeight", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2206f/block_period': '2880'}}) + assert_raises_rpc_error(-32600, "Cannot be set before FortCanningSpringHeight", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2203/start_block': '0'}}) + assert_raises_rpc_error(-32600, "Cannot be set before FortCanningSpringHeight", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2206f/start_block': '0'}}) # Move to fork self.nodes[0].generate(1250 - self.nodes[0].getblockcount()) # Test invalid calls - assert_raises_rpc_error(-5, "Fee direction value must be both, in or out", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/poolpairs/3/token_a_fee_direction': 'invalid'}}) - assert_raises_rpc_error(-5, "Boolean value must be either \"true\" or \"false\"", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2206f/active':'not_a_bool'}}) - assert_raises_rpc_error(-5, "Amount must be a positive value", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2206f/reward_pct':'not_a_number'}}) - assert_raises_rpc_error(-5, "Amount must be a positive value", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2206f/reward_pct':'-1'}}) - assert_raises_rpc_error(-5, "Percentage exceeds 100%", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2206f/reward_pct':'2'}}) - assert_raises_rpc_error(-5, "Value must be a positive integer", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2206f/block_period':'not_a_number'}}) - assert_raises_rpc_error(-5, "Value must be a positive integer", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2206f/block_period':'-1'}}) - assert_raises_rpc_error(-5, "Unsupported type for this DFIP", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2206f/premium': '0.025'}}) - assert_raises_rpc_error(-5, "Unsupported type for this DFIP", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2206f/minswap': '0.025'}}) - assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot set block period while DFIP2203 is active", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2203/start_block':'0'}}) - assert_raises_rpc_error(-5, "Boolean value must be either \"true\" or \"false\"", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2206a/dusd_interest_burn':'not_a_bool'}}) - assert_raises_rpc_error(-5, "Boolean value must be either \"true\" or \"false\"", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2206a/dusd_loan_burn':'not_a_bool'}}) - assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set before GrandCentral", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/consortium/5/members' : {"01":{"name":"test", - "ownerAddress": owner, - "backingId":"blablabla", - "mintLimit": "10.00000000", - "mintLimitDaily": "1.0000000"}}}}) - assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set before GrandCentral", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/feature/consortium':'true'}}) - assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set before GrandCentral", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/consortium/5/mint_limit':'1000000000'}}) - - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/dfip2206a/dusd_interest_burn':'true', 'v0/params/dfip2206a/dusd_loan_burn':'true'}}) + assert_raises_rpc_error(-5, "Fee direction value must be both, in or out", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/poolpairs/3/token_a_fee_direction': 'invalid'}}) + assert_raises_rpc_error(-5, "Boolean value must be either \"true\" or \"false\"", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2206f/active': 'not_a_bool'}}) + assert_raises_rpc_error(-5, "Amount must be a positive value", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2206f/reward_pct': 'not_a_number'}}) + assert_raises_rpc_error(-5, "Amount must be a positive value", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2206f/reward_pct': '-1'}}) + assert_raises_rpc_error(-5, "Percentage exceeds 100%", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2206f/reward_pct': '2'}}) + assert_raises_rpc_error(-5, "Value must be a positive integer", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2206f/block_period': 'not_a_number'}}) + assert_raises_rpc_error(-5, "Value must be a positive integer", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2206f/block_period': '-1'}}) + assert_raises_rpc_error(-5, "Unsupported type for this DFIP", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2206f/premium': '0.025'}}) + assert_raises_rpc_error(-5, "Unsupported type for this DFIP", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2206f/minswap': '0.025'}}) + assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot set block period while DFIP2203 is active", + self.nodes[0].setgov, {"ATTRIBUTES": {'v0/params/dfip2203/start_block': '0'}}) + assert_raises_rpc_error(-5, "Boolean value must be either \"true\" or \"false\"", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2206a/dusd_interest_burn': 'not_a_bool'}}) + assert_raises_rpc_error(-5, "Boolean value must be either \"true\" or \"false\"", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/dfip2206a/dusd_loan_burn': 'not_a_bool'}}) + assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set before GrandCentral", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/consortium/5/members': {"01": {"name": "test", + "ownerAddress": owner, + "backingId": "blablabla", + "mintLimit": "10.00000000", + "mintLimitDaily": "1.0000000"}}}}) + assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set before GrandCentral", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/feature/consortium': 'true'}}) + assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot be set before GrandCentral", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/consortium/5/mint_limit': '1000000000'}}) + + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/dfip2206a/dusd_interest_burn': 'true', + 'v0/params/dfip2206a/dusd_loan_burn': 'true'}}) self.nodes[0].generate(1) # Verify FCR results @@ -803,7 +994,7 @@ def run_test(self): assert_equal(result['v0/params/dfip2206a/dusd_loan_burn'], 'true') # Set fee direction Gov vars - self.nodes[0].setgov({"ATTRIBUTES":{ + self.nodes[0].setgov({"ATTRIBUTES": { 'v0/poolpairs/3/token_a_fee_direction': 'both', 'v0/poolpairs/3/token_b_fee_direction': 'both', }}) @@ -815,7 +1006,7 @@ def run_test(self): assert_equal(result['v0/poolpairs/3/token_b_fee_direction'], "both") # Set fee direction Gov vars - self.nodes[0].setgov({"ATTRIBUTES":{ + self.nodes[0].setgov({"ATTRIBUTES": { 'v0/poolpairs/3/token_a_fee_direction': 'in', 'v0/poolpairs/3/token_b_fee_direction': 'in', }}) @@ -827,7 +1018,7 @@ def run_test(self): assert_equal(result['v0/poolpairs/3/token_b_fee_direction'], "in") # Set fee direction Gov vars - self.nodes[0].setgov({"ATTRIBUTES":{ + self.nodes[0].setgov({"ATTRIBUTES": { 'v0/poolpairs/3/token_a_fee_direction': 'out', 'v0/poolpairs/3/token_b_fee_direction': 'out', }}) @@ -839,9 +1030,10 @@ def run_test(self): assert_equal(result['v0/poolpairs/3/token_b_fee_direction'], "out") # Test setting ATTRBIUTES - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/dfip2206f/reward_pct':'0.05','v0/params/dfip2206f/block_period':'20160'}}) + self.nodes[0].setgov( + {"ATTRIBUTES": {'v0/params/dfip2206f/reward_pct': '0.05', 'v0/params/dfip2206f/block_period': '20160'}}) self.nodes[0].generate(1) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/dfip2206f/active':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/dfip2206f/active': 'true'}}) self.nodes[0].generate(1) # Verify results @@ -851,20 +1043,21 @@ def run_test(self): assert_equal(result['v0/params/dfip2206f/block_period'], '20160') # Check error now DFIP2206F active - assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot set block period while DFIP2206F is active", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/dfip2206f/start_block':'0'}}) + assert_raises_rpc_error(-32600, "ATTRIBUTES: Cannot set block period while DFIP2206F is active", + self.nodes[0].setgov, {"ATTRIBUTES": {'v0/params/dfip2206f/start_block': '0'}}) # Disable DFIP2203 - self.nodes[0].setgov({"ATTRIBUTES":{ - 'v0/params/dfip2203/active':'false', - 'v0/params/dfip2206f/active':'false' + self.nodes[0].setgov({"ATTRIBUTES": { + 'v0/params/dfip2203/active': 'false', + 'v0/params/dfip2206f/active': 'false' }}) self.nodes[0].generate(1) # Set start block height start_block = self.nodes[0].getblockcount() + 100 - self.nodes[0].setgov({"ATTRIBUTES":{ - 'v0/params/dfip2203/start_block':f'{start_block}', - 'v0/params/dfip2206f/start_block':f'{start_block}' + self.nodes[0].setgov({"ATTRIBUTES": { + 'v0/params/dfip2203/start_block': f'{start_block}', + 'v0/params/dfip2206f/start_block': f'{start_block}' }}) self.nodes[0].generate(1) @@ -874,59 +1067,74 @@ def run_test(self): assert_equal(attributes['v0/params/dfip2206f/start_block'], f'{start_block}') # Check errors before fork - assert_raises_rpc_error(-32600, "called before GrandCentral height", self.nodes[0].unsetgov, {'ATTRIBUTES': ['v0/locks/token/4', 'v0/params/dfip2206f/active', 'v0/token/4/fixed_interval_price_id', 'v0/oracles/splits/4000', 'v0/poolpairs/3/token_a_fee_direction']}) - assert_raises_rpc_error(-32600, "Cannot be set before GrandCentralHeight", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/feature/gov-unset':'true'}}) + assert_raises_rpc_error(-32600, "called before GrandCentral height", self.nodes[0].unsetgov, { + 'ATTRIBUTES': ['v0/locks/token/4', 'v0/params/dfip2206f/active', 'v0/token/4/fixed_interval_price_id', + 'v0/oracles/splits/4000', 'v0/poolpairs/3/token_a_fee_direction']}) + assert_raises_rpc_error(-32600, "Cannot be set before GrandCentralHeight", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/feature/gov-unset': 'true'}}) # Move to GrandCentral self.nodes[0].generate(1300 - self.nodes[0].getblockcount()) - assert_raises_rpc_error(-5, "Invalid ownerAddress in consortium member data", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/consortium/4/members' : {"01":{"name":"test", - "ownerAddress":"", - "backingId":"blablabla", - "mintLimit":10.00000000}}}}) - assert_raises_rpc_error(-5, "Member name too short, must be at least 3 chars long", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/consortium/4/members' : {"01":{"name":"12", - "ownerAddress": owner, - "backingId":"blablabla", - "mintLimit":10.00000000}}}}) - assert_raises_rpc_error(-5, "Mint limit is an invalid amount", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/consortium/4/members' : {"01":{"name":"test", - "ownerAddress": owner, - "backingId":"blablabla", - "mintLimit":-10.00000000}}}}) - assert_raises_rpc_error(-5, "Daily mint limit is an invalid amount", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/consortium/4/members' : {"01":{"name":"test", - "ownerAddress": owner, - "backingId":"blablabla", - "mintLimit":10.00000000, - "mintLimitDaily":-10.00000000}}}}) - assert_raises_rpc_error(-5, "Status must be a positive number", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/consortium/4/members' : {"01":{"name":"test", - "ownerAddress": owner, - "backingId":"blablabla", - "mintLimit":10.00000000, - "mintLimitDaily":1.00000000, - "status":-1}}}}) - assert_raises_rpc_error(-5, "Status can be either 0 or 1", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/consortium/4/members' : {"01":{"name":"test", "ownerAddress": owner, "backingId":"blablabla", "mintLimit":10.00000000, "mintLimitDaily":1.00000000, "status":2}}}}) - - self.nodes[0].setgov({"ATTRIBUTES":{'v0/consortium/5/mint_limit' : '10', 'v0/consortium/5/mint_limit_daily' : '1'}}) - self.nodes[0].generate(1) - - self.nodes[0].setgov({"ATTRIBUTES":{'v0/consortium/5/members' : {"01":{"name":"test", - "ownerAddress": owner, - "backingId":"blablabla", - "mintLimit": 10, - "mintLimitDaily": 1}}}}) + assert_raises_rpc_error(-5, "Invalid ownerAddress in consortium member data", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/consortium/4/members': {"01": {"name": "test", + "ownerAddress": "", + "backingId": "blablabla", + "mintLimit": 10.00000000}}}}) + assert_raises_rpc_error(-5, "Member name too short, must be at least 3 chars long", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/consortium/4/members': {"01": {"name": "12", + "ownerAddress": owner, + "backingId": "blablabla", + "mintLimit": 10.00000000}}}}) + assert_raises_rpc_error(-5, "Mint limit is an invalid amount", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/consortium/4/members': {"01": {"name": "test", + "ownerAddress": owner, + "backingId": "blablabla", + "mintLimit": -10.00000000}}}}) + assert_raises_rpc_error(-5, "Daily mint limit is an invalid amount", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/consortium/4/members': {"01": {"name": "test", + "ownerAddress": owner, + "backingId": "blablabla", + "mintLimit": 10.00000000, + "mintLimitDaily": -10.00000000}}}}) + assert_raises_rpc_error(-5, "Status must be a positive number", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/consortium/4/members': {"01": {"name": "test", + "ownerAddress": owner, + "backingId": "blablabla", + "mintLimit": 10.00000000, + "mintLimitDaily": 1.00000000, + "status": -1}}}}) + assert_raises_rpc_error(-5, "Status can be either 0 or 1", self.nodes[0].setgov, {"ATTRIBUTES": { + 'v0/consortium/4/members': { + "01": {"name": "test", "ownerAddress": owner, "backingId": "blablabla", "mintLimit": 10.00000000, + "mintLimitDaily": 1.00000000, "status": 2}}}}) + + self.nodes[0].setgov( + {"ATTRIBUTES": {'v0/consortium/5/mint_limit': '10', 'v0/consortium/5/mint_limit_daily': '1'}}) + self.nodes[0].generate(1) + + self.nodes[0].setgov({"ATTRIBUTES": {'v0/consortium/5/members': {"01": {"name": "test", + "ownerAddress": owner, + "backingId": "blablabla", + "mintLimit": 10, + "mintLimitDaily": 1}}}}) self.nodes[0].generate(1) # Check result result = self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'] - assert_equal(result['v0/consortium/5/members'], {"01":{"name":"test", - "ownerAddress": owner, - "backingId":"blablabla", - "mintLimit": Decimal('10.00000000'), - "mintLimitDaily": Decimal('1.00000000'), - "status": 0}}) - - assert_raises_rpc_error(-5, "Percentage exceeds 100%", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/gov/proposals/fee_burn_pct':'1.23'}}) - assert_raises_rpc_error(-5, "Percentage exceeds 100%", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/gov/proposals/fee_burn_pct':'101%'}}) - assert_raises_rpc_error(-5, "Percentage exceeds 100%", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/gov/proposals/cfp_fee':'101.66%'}}) + assert_equal(result['v0/consortium/5/members'], {"01": {"name": "test", + "ownerAddress": owner, + "backingId": "blablabla", + "mintLimit": Decimal('10.00000000'), + "mintLimitDaily": Decimal('1.00000000'), + "status": 0}}) + + assert_raises_rpc_error(-5, "Percentage exceeds 100%", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/gov/proposals/fee_burn_pct': '1.23'}}) + assert_raises_rpc_error(-5, "Percentage exceeds 100%", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/gov/proposals/fee_burn_pct': '101%'}}) + assert_raises_rpc_error(-5, "Percentage exceeds 100%", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/gov/proposals/cfp_fee': '101.66%'}}) result = self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'] assert_equal(result['v0/locks/token/4'], 'true') @@ -936,14 +1144,20 @@ def run_test(self): assert_equal(result['v0/poolpairs/3/token_a_fee_direction'], 'out') # Check unset does not work as it is not enabled in attributes - assert_raises_rpc_error(-32600, "Unset Gov variables not currently enabled in attributes.", self.nodes[0].unsetgov, {'ATTRIBUTES': ['v0/locks/token/4', 'v0/params/dfip2206f/active', 'v0/token/4/fixed_interval_price_id', 'v0/oracles/splits/4000', 'v0/poolpairs/3/token_a_fee_direction']}) + assert_raises_rpc_error(-32600, "Unset Gov variables not currently enabled in attributes.", + self.nodes[0].unsetgov, { + 'ATTRIBUTES': ['v0/locks/token/4', 'v0/params/dfip2206f/active', + 'v0/token/4/fixed_interval_price_id', 'v0/oracles/splits/4000', + 'v0/poolpairs/3/token_a_fee_direction']}) # Enable unset Gov variables in attributes - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/feature/gov-unset':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/feature/gov-unset': 'true'}}) self.nodes[0].generate(1) # Unset Gov variables - self.nodes[0].unsetgov({'ATTRIBUTES': ['v0/locks/token/4', 'v0/params/dfip2206f/active', 'v0/token/4/fixed_interval_price_id', 'v0/oracles/splits/4000', 'v0/poolpairs/3/token_a_fee_direction']}) + self.nodes[0].unsetgov({'ATTRIBUTES': ['v0/locks/token/4', 'v0/params/dfip2206f/active', + 'v0/token/4/fixed_interval_price_id', 'v0/oracles/splits/4000', + 'v0/poolpairs/3/token_a_fee_direction']}) self.nodes[0].generate(1) attributes = self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'] @@ -957,9 +1171,10 @@ def run_test(self): assert_equal(result['ORACLE_DEVIATION'], Decimal('0.07000000')) result = self.nodes[0].getgov('LP_SPLITS') - assert_equal(result['LP_SPLITS'], {'1': Decimal('0.70000000'), '2': Decimal('0.20000000'), '3': Decimal('0.10000000')}) + assert_equal(result['LP_SPLITS'], + {'1': Decimal('0.70000000'), '2': Decimal('0.20000000'), '3': Decimal('0.10000000')}) - self.nodes[0].unsetgov({'ORACLE_DEVIATION':'', 'LP_SPLITS':['1', '2']}) + self.nodes[0].unsetgov({'ORACLE_DEVIATION': '', 'LP_SPLITS': ['1', '2']}) self.nodes[0].generate(1) result = self.nodes[0].getgov('ORACLE_DEVIATION') @@ -968,5 +1183,6 @@ def run_test(self): result = self.nodes[0].getgov('LP_SPLITS') assert_equal(result['LP_SPLITS'], {'3': Decimal('0.10000000')}) + if __name__ == '__main__': - GovsetTest ().main () + GovsetTest().main() diff --git a/test/functional/feature_shutdown.py b/test/functional/feature_shutdown.py index 64473befaf..cb6b7b9019 100755 --- a/test/functional/feature_shutdown.py +++ b/test/functional/feature_shutdown.py @@ -8,10 +8,12 @@ from test_framework.util import assert_equal, get_rpc_proxy, wait_until from threading import Thread + def test_long_call(node): block = node.waitfornewblock() assert_equal(block['height'], 0) + class ShutdownTest(DefiTestFramework): def set_test_params(self): @@ -30,5 +32,6 @@ def run_test(self): # to close. self.stop_node(0, wait=1000) + if __name__ == '__main__': ShutdownTest().main() diff --git a/test/functional/feature_skip_collateral_factor_check.py b/test/functional/feature_skip_collateral_factor_check.py index 1c58501a66..93402bd81a 100755 --- a/test/functional/feature_skip_collateral_factor_check.py +++ b/test/functional/feature_skip_collateral_factor_check.py @@ -8,12 +8,15 @@ from test_framework.test_framework import DefiTestFramework -class SkipCollateralFactorTest (DefiTestFramework): +class SkipCollateralFactorTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True - self.extra_args = [['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-bayfrontgardensheight=1', '-eunosheight=1', '-txindex=1', '-fortcanningheight=1', '-fortcanningroadheight=1', - '-fortcanninghillheight=1', '-fortcanningcrunchheight=1', '-fortcanninggreatworldheight=1', '-fortcanningepilogueheight=200', '-regtest-skip-loan-collateral-validation', '-jellyfish_regtest=1']] + self.extra_args = [ + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-bayfrontgardensheight=1', '-eunosheight=1', + '-txindex=1', '-fortcanningheight=1', '-fortcanningroadheight=1', + '-fortcanninghillheight=1', '-fortcanningcrunchheight=1', '-fortcanninggreatworldheight=1', + '-fortcanningepilogueheight=200', '-regtest-skip-loan-collateral-validation', '-jellyfish_regtest=1']] def run_test(self): # Generate chain diff --git a/test/functional/feature_smart_contracts.py b/test/functional/feature_smart_contracts.py index edeb1cc4d2..3ba1c5abf5 100755 --- a/test/functional/feature_smart_contracts.py +++ b/test/functional/feature_smart_contracts.py @@ -11,11 +11,14 @@ from decimal import Decimal import time + class SmartContractTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True - self.extra_args = [['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', '-fortcanninghillheight=1010', '-subsidytest=1', '-txindex=1', '-jellyfish_regtest=1']] + self.extra_args = [ + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', + '-fortcanninghillheight=1010', '-subsidytest=1', '-txindex=1', '-jellyfish_regtest=1']] def run_test(self): self.nodes[0].generate(1000) @@ -27,10 +30,14 @@ def run_test(self): dfip = 'dbtcdfiswap' # Check invalid calls - assert_raises_rpc_error(-5, 'Incorrect authorization for {}'.format(invalid_address), self.nodes[0].executesmartcontract, dfip, str(btc_amount) + '@2', invalid_address) - assert_raises_rpc_error(-4, 'Insufficient funds', self.nodes[0].executesmartcontract, dfip, str(dfi_amount) + '@0') - assert_raises_rpc_error(-8, 'Specified smart contract not found', self.nodes[0].executesmartcontract, 'DFIP9999', str(dfi_amount) + '@0') - assert_raises_rpc_error(-8, 'BTC source address must be provided for DFIP2201', self.nodes[0].executesmartcontract, dfip, str(btc_amount) + '@2') + assert_raises_rpc_error(-5, 'Incorrect authorization for {}'.format(invalid_address), + self.nodes[0].executesmartcontract, dfip, str(btc_amount) + '@2', invalid_address) + assert_raises_rpc_error(-4, 'Insufficient funds', self.nodes[0].executesmartcontract, dfip, + str(dfi_amount) + '@0') + assert_raises_rpc_error(-8, 'Specified smart contract not found', self.nodes[0].executesmartcontract, + 'DFIP9999', str(dfi_amount) + '@0') + assert_raises_rpc_error(-8, 'BTC source address must be provided for DFIP2201', + self.nodes[0].executesmartcontract, dfip, str(btc_amount) + '@2') # Create tokens self.nodes[0].createtoken({ @@ -56,36 +63,44 @@ def run_test(self): self.nodes[0].generate(1) # Check invalid calls - assert_raises_rpc_error(-32600, 'called before FortCanningHill height', self.nodes[0].executesmartcontract, dfip, str(btc_amount) + '@2', address) + assert_raises_rpc_error(-32600, 'called before FortCanningHill height', self.nodes[0].executesmartcontract, + dfip, str(btc_amount) + '@2', address) # Move to FortCanningHill self.nodes[0].generate(1010 - self.nodes[0].getblockcount()) # Check invalid call - assert_raises_rpc_error(-32600, 'DFIP2201 smart contract is not enabled', self.nodes[0].executesmartcontract, dfip, str(btc_amount) + '@2', address) + assert_raises_rpc_error(-32600, 'DFIP2201 smart contract is not enabled', self.nodes[0].executesmartcontract, + dfip, str(btc_amount) + '@2', address) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/dfip2201/active':'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/dfip2201/active': 'false'}}) self.nodes[0].generate(1) # Check invalid call - assert_raises_rpc_error(-32600, 'DFIP2201 smart contract is not enabled', self.nodes[0].executesmartcontract, dfip, str(btc_amount) + '@2', address) + assert_raises_rpc_error(-32600, 'DFIP2201 smart contract is not enabled', self.nodes[0].executesmartcontract, + dfip, str(btc_amount) + '@2', address) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/dfip2201/active':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/dfip2201/active': 'true'}}) self.nodes[0].generate(1) # Check invalid calls - assert_raises_rpc_error(-32600, 'is less than', self.nodes[0].executesmartcontract, dfip, '20000.00000001@2', address) + assert_raises_rpc_error(-32600, 'is less than', self.nodes[0].executesmartcontract, dfip, '20000.00000001@2', + address) assert_raises_rpc_error(-3, 'Amount out of range', self.nodes[0].executesmartcontract, dfip, '0@2', address) - assert_raises_rpc_error(-32600, 'Specified token not found', self.nodes[0].executesmartcontract, dfip, str(btc_amount) + '@9999', address) - assert_raises_rpc_error(-32600, 'Only Bitcoin can be swapped in DFIP2201', self.nodes[0].executesmartcontract, dfip, str(btc_amount) + '@1', address) - assert_raises_rpc_error(-32600, 'fixedIntervalPrice with id not found', self.nodes[0].executesmartcontract, dfip, str(btc_amount) + '@2', address) + assert_raises_rpc_error(-32600, 'Specified token not found', self.nodes[0].executesmartcontract, dfip, + str(btc_amount) + '@9999', address) + assert_raises_rpc_error(-32600, 'Only Bitcoin can be swapped in DFIP2201', self.nodes[0].executesmartcontract, + dfip, str(btc_amount) + '@1', address) + assert_raises_rpc_error(-32600, 'fixedIntervalPrice with id not found', + self.nodes[0].executesmartcontract, dfip, str(btc_amount) + '@2', address) # Test min swap - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/dfip2201/minswap':'0.00001'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/dfip2201/minswap': '0.00001'}}) self.nodes[0].generate(1) # Check invalid calls - assert_raises_rpc_error(-32600, 'Below minimum swapable amount, must be at least 0.00001000 BTC', self.nodes[0].executesmartcontract, dfip, '0.00000999@2', address) + assert_raises_rpc_error(-32600, 'Below minimum swapable amount, must be at least 0.00001000 BTC', + self.nodes[0].executesmartcontract, dfip, '0.00000999@2', address) # Set up oracles oracle_address = self.nodes[0].getnewaddress("", "legacy") @@ -100,14 +115,14 @@ def run_test(self): self.nodes[0].generate(1) self.nodes[0].setcollateraltoken({ - 'token': 'DFI', - 'factor': 1, - 'fixedIntervalPriceId': "DFI/USD"}) + 'token': 'DFI', + 'factor': 1, + 'fixedIntervalPriceId': "DFI/USD"}) self.nodes[0].setcollateraltoken({ - 'token': 'BTC', - 'factor': 1, - 'fixedIntervalPriceId': "BTC/USD"}) + 'token': 'BTC', + 'factor': 1, + 'fixedIntervalPriceId': "BTC/USD"}) self.nodes[0].generate(7) @@ -116,14 +131,15 @@ def run_test(self): balance = self.nodes[0].getbalance() # Try and fund more than is in community balance - assert_raises_rpc_error(-4, 'Insufficient funds', self.nodes[0].executesmartcontract, dfip, '18336.22505381@0', address) + assert_raises_rpc_error(-4, 'Insufficient funds', self.nodes[0].executesmartcontract, dfip, '18336.22505381@0', + address) # Check smart contract details and balance result = self.nodes[0].listsmartcontracts() assert_equal(result[0]['name'], 'DFIP2201') assert_equal(result[0]['call'], 'dbtcdfiswap') assert_equal(result[0]['address'], 'bcrt1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqdku202') - assert('0' not in result[0]) + assert ('0' not in result[0]) # Fund smart contract tx = self.nodes[0].executesmartcontract(dfip, '18336.225@0') @@ -139,19 +155,21 @@ def run_test(self): staker_reward = rewards[0]['value'] community_reward = rewards[1]['value'] fee = self.nodes[0].gettransaction(tx)['fee'] - assert_equal(balance + staker_reward + community_reward - Decimal('18336.225') + fee, self.nodes[0].getbalance()) + assert_equal(balance + staker_reward + community_reward - Decimal('18336.225') + fee, + self.nodes[0].getbalance()) # Test swap for more than in community fund by 1 Sat block = self.nodes[0].getblockcount() - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/dfip2201/premium':'0.00000000'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/dfip2201/premium': '0.00000000'}}) self.nodes[0].generate(1) - assert_raises_rpc_error(-32600, 'amount 18336.22500000 is less than 18336.22500001', self.nodes[0].executesmartcontract, dfip, '18336.22500001@2', address) + assert_raises_rpc_error(-32600, 'amount 18336.22500000 is less than 18336.22500001', + self.nodes[0].executesmartcontract, dfip, '18336.22500001@2', address) # Test again for full amount in community balance self.nodes[0].executesmartcontract(dfip, '18336.22500000@2', address) self.nodes[0].generate(1) assert_equal(18336.22500000, float(self.nodes[0].getaccount(address)[0].split('@')[0])) - assert('0' not in self.nodes[0].listsmartcontracts()) + assert ('0' not in self.nodes[0].listsmartcontracts()) # Set "real world" prices self.rollback_to(block) @@ -168,7 +186,7 @@ def run_test(self): # Test 5% premium self.rollback_to(block) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/dfip2201/premium':'0.05'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/dfip2201/premium': '0.05'}}) self.nodes[0].generate(1) self.nodes[0].executesmartcontract(dfip, '0.09999999@2', address) self.nodes[0].generate(1) @@ -176,7 +194,7 @@ def run_test(self): # Test 0.1% premium self.rollback_to(block) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/dfip2201/premium':'0.001'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/dfip2201/premium': '0.001'}}) self.nodes[0].generate(1) self.nodes[0].executesmartcontract(dfip, '0.09999999@2', address) self.nodes[0].generate(1) @@ -184,7 +202,7 @@ def run_test(self): # Test 0.000001% premium self.rollback_to(block) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/dfip2201/premium':'0.00000001'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/dfip2201/premium': '0.00000001'}}) self.nodes[0].generate(1) self.nodes[0].executesmartcontract(dfip, '0.1@2', address) self.nodes[0].generate(1) @@ -192,7 +210,7 @@ def run_test(self): # Test 0% premium self.rollback_to(block) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/dfip2201/premium':'0.00000000'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/dfip2201/premium': '0.00000000'}}) self.nodes[0].generate(1) self.nodes[0].executesmartcontract(dfip, '0.1@2', address) self.nodes[0].generate(1) @@ -206,7 +224,7 @@ def run_test(self): # Test smallest min amount self.rollback_to(block) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/dfip2201/minswap':'0.00000001'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/dfip2201/minswap': '0.00000001'}}) self.nodes[0].generate(1) self.nodes[0].executesmartcontract(dfip, '0.00000001@2', address) self.nodes[0].generate(1) @@ -214,17 +232,18 @@ def run_test(self): # Test no smallest min amount self.rollback_to(block) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/dfip2201/minswap':'0.00000001'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/dfip2201/minswap': '0.00000001'}}) self.nodes[0].generate(1) self.nodes[0].executesmartcontract(dfip, '0.00000001@2', address) self.nodes[0].generate(1) assert_equal(0.000205, float(self.nodes[0].getaccount(address)[0].split('@')[0])) # Test disabling DFIP201 - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/dfip2201/active':'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/dfip2201/active': 'false'}}) self.nodes[0].generate(1) - assert_raises_rpc_error(-32600, 'DFIP2201 smart contract is not enabled', self.nodes[0].executesmartcontract, dfip, '1@2', address) + assert_raises_rpc_error(-32600, 'DFIP2201 smart contract is not enabled', self.nodes[0].executesmartcontract, + dfip, '1@2', address) + if __name__ == '__main__': SmartContractTest().main() - diff --git a/test/functional/feature_split_migrate_lock.py b/test/functional/feature_split_migrate_lock.py index cde045cf8d..e84b7b6fbb 100755 --- a/test/functional/feature_split_migrate_lock.py +++ b/test/functional/feature_split_migrate_lock.py @@ -11,23 +11,24 @@ from decimal import Decimal import time + class TokenSplitMigrateLockTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True self.extra_args = [ ['-vaultindex=1', '-txnotokens=0', - '-amkheight=1', - '-bayfrontheight=1', - '-eunosheight=1', - '-fortcanningheight=1', - '-fortcanningmuseumheight=1', - '-fortcanninghillheight=1', - '-fortcanningroadheight=1', - '-fortcanningcrunchheight=200', - '-greatworldheight=200', - '-grandcentralheight=200', - '-subsidytest=1']] + '-amkheight=1', + '-bayfrontheight=1', + '-eunosheight=1', + '-fortcanningheight=1', + '-fortcanningmuseumheight=1', + '-fortcanninghillheight=1', + '-fortcanningroadheight=1', + '-fortcanningcrunchheight=200', + '-greatworldheight=200', + '-grandcentralheight=200', + '-subsidytest=1']] def run_test(self): self.setup_test_tokens() @@ -80,7 +81,6 @@ def setup_test_tokens(self): self.nodes[0].generate(1) def test_unlock_migration(self): - # Move to FCC / GW self.nodes[0].generate(200 - self.nodes[0].getblockcount()) @@ -88,15 +88,16 @@ def test_unlock_migration(self): split_height = self.nodes[0].getblockcount() + 11 # Lock token - self.nodes[0].setgovheight({"ATTRIBUTES":{f'v0/locks/token/{self.idGOOGL}':'true'}}, split_height - 2) + self.nodes[0].setgovheight({"ATTRIBUTES": {f'v0/locks/token/{self.idGOOGL}': 'true'}}, split_height - 2) self.nodes[0].generate(1) # Token split - self.nodes[0].setgovheight({"ATTRIBUTES":{f'v0/oracles/splits/{split_height}':f'{self.idGOOGL}/2'}}, split_height - 1) + self.nodes[0].setgovheight({"ATTRIBUTES": {f'v0/oracles/splits/{split_height}': f'{self.idGOOGL}/2'}}, + split_height - 1) self.nodes[0].generate(1) # Token unlock - self.nodes[0].setgovheight({"ATTRIBUTES":{f'v0/locks/token/{self.idGOOGL}':'false'}}, split_height + 10) + self.nodes[0].setgovheight({"ATTRIBUTES": {f'v0/locks/token/{self.idGOOGL}': 'false'}}, split_height + 10) self.nodes[0].generate(1) # Move to split height @@ -113,5 +114,6 @@ def test_unlock_migration(self): result = self.nodes[0].listgovs()[8][1] assert_equal(result[f'{split_height + 10}'], {f'v0/locks/token/{self.idGOOGL}': 'false'}) + if __name__ == '__main__': TokenSplitMigrateLockTest().main() diff --git a/test/functional/feature_stored_interest.py b/test/functional/feature_stored_interest.py index 20bea881df..53de53e491 100755 --- a/test/functional/feature_stored_interest.py +++ b/test/functional/feature_stored_interest.py @@ -11,12 +11,15 @@ from decimal import Decimal import time -class StoredInterestTest (DefiTestFramework): + +class StoredInterestTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True self.extra_args = [ - ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', '-fortcanninghillheight=1', '-fortcanningcrunchheight=1', '-fortcanninggreatworldheight=1', '-jellyfish_regtest=1', '-negativeinterest=1']] + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', + '-fortcanninghillheight=1', '-fortcanningcrunchheight=1', '-fortcanninggreatworldheight=1', + '-jellyfish_regtest=1', '-negativeinterest=1']] def run_test(self): # Create tokens for tests @@ -94,7 +97,6 @@ def setup_test_tokens(self): self.nodes[0].generate(1) def setup_test_pools(self): - # Create pool pair self.nodes[0].createpoolpair({ "tokenA": self.symbolDFI, @@ -110,11 +112,10 @@ def setup_test_pools(self): self.address: [ '10000@' + self.symbolDFI, '10000@' + self.symbolDUSD] - }, self.address) + }, self.address) self.nodes[0].generate(1) def setup_test_oracles(self): - # Create Oracle address oracle_address = self.nodes[0].getnewaddress("", "legacy") @@ -136,10 +137,10 @@ def setup_test_oracles(self): # Set collateral tokens self.nodes[0].setcollateraltoken({ - 'token': self.symbolDFI, - 'factor': 1, - 'fixedIntervalPriceId': "DFI/USD" - }) + 'token': self.symbolDFI, + 'factor': 1, + 'fixedIntervalPriceId': "DFI/USD" + }) self.nodes[0].generate(1) # Create loan scheme @@ -151,7 +152,6 @@ def setup_test_oracles(self): self.nodes[0].generate(1) def test_token_interest_change(self): - # Create vault vault_address = self.nodes[0].getnewaddress('', 'legacy') vault_id = self.nodes[0].createvault(vault_address, 'LOAN001') @@ -166,11 +166,11 @@ def test_token_interest_change(self): self.nodes[0].generate(1) # Take DUSD loan - self.nodes[0].takeloan({ "vaultId": vault_id, "amounts": f"1@{self.symbolDUSD}"}) + self.nodes[0].takeloan({"vaultId": vault_id, "amounts": f"1@{self.symbolDUSD}"}) self.nodes[0].generate(10) # Change token interest to create positive interestToHeight value - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'1'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '1'}}) self.nodes[0].generate(1) # Check stored interest increased as expected @@ -181,11 +181,11 @@ def test_token_interest_change(self): assert_equal(stored_interest['height'], self.nodes[0].getblockcount()) # Set negative interest to be inverse of positive interest - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'-3'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '-3'}}) self.nodes[0].generate(6) # Apply again to update stored interest - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'-3'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '-3'}}) self.nodes[0].generate(10) # Check interest is now set to be negative and that interest to height has reduced @@ -195,7 +195,7 @@ def test_token_interest_change(self): assert_equal(stored_interest['height'], self.nodes[0].getblockcount() - 9) # Apply again to update stored interest - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'-3'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '-3'}}) self.nodes[0].generate(1) # Check amount negated shown in attributes, 5 * negative_stored_ipb @@ -215,7 +215,7 @@ def test_token_interest_change(self): assert_equal(stored_interest['height'], self.nodes[0].getblockcount() - 4) # Apply again to update stored interest - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'-3'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '-3'}}) self.nodes[0].generate(1) # Check amount negated shown in attributes, 10 * negative_stored_ipb @@ -229,11 +229,11 @@ def test_token_interest_change(self): assert_equal(stored_interest['height'], self.nodes[0].getblockcount()) # Set positive token interest - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'1'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '1'}}) self.nodes[0].generate(6) # Apply again to update stored interest - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'1'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '1'}}) self.nodes[0].generate(10) # Check interest to height has additional negative interest @@ -243,7 +243,7 @@ def test_token_interest_change(self): assert_equal(stored_interest['height'], self.nodes[0].getblockcount() - 9) # Apply again to update stored interest - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'1'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '1'}}) self.nodes[0].generate(1) # Check interest to height has additional negative interest @@ -253,9 +253,8 @@ def test_token_interest_change(self): assert_equal(stored_interest['height'], self.nodes[0].getblockcount()) def test_scheme_change(self): - # Reset token interest - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'1'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '1'}}) self.nodes[0].generate(1) # Create vault @@ -272,7 +271,7 @@ def test_scheme_change(self): self.nodes[0].generate(1) # Take DUSD loan - self.nodes[0].takeloan({ "vaultId": vault_id, "amounts": f"1@{self.symbolDUSD}"}) + self.nodes[0].takeloan({"vaultId": vault_id, "amounts": f"1@{self.symbolDUSD}"}) self.nodes[0].generate(10) # Change vault scheme to create positive interest to height @@ -291,7 +290,7 @@ def test_scheme_change(self): assert_equal(stored_interest['height'], self.nodes[0].getblockcount()) # Set negative interest to be inverse of positive interest - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'-3'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '-3'}}) self.nodes[0].generate(6) # Apply scheme change to update stored interest @@ -338,7 +337,7 @@ def test_scheme_change(self): assert_equal(stored_interest['height'], self.nodes[0].getblockcount()) # Set positive token interest - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'1'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '1'}}) self.nodes[0].generate(6) # Apply scheme change to update stored interest @@ -370,9 +369,8 @@ def test_scheme_change(self): assert_equal(stored_interest['height'], self.nodes[0].getblockcount()) def test_take_loan_neg_ipb_pos_ith(self): - # Reset token interest - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'1'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '1'}}) self.nodes[0].generate(1) # Create vault @@ -389,7 +387,7 @@ def test_take_loan_neg_ipb_pos_ith(self): self.nodes[0].generate(1) # Take DUSD loan - self.nodes[0].takeloan({ "vaultId": vault_id, "amounts": f"1@{self.symbolDUSD}"}) + self.nodes[0].takeloan({"vaultId": vault_id, "amounts": f"1@{self.symbolDUSD}"}) self.nodes[0].generate(10) # Check interest @@ -397,7 +395,7 @@ def test_take_loan_neg_ipb_pos_ith(self): assert_equal(stored_interest, '0.000000380517503805175038') # Take another loan to update stored interest - self.nodes[0].takeloan({ "vaultId": vault_id, "amounts": f"0.00000001@{self.symbolDUSD}"}) + self.nodes[0].takeloan({"vaultId": vault_id, "amounts": f"0.00000001@{self.symbolDUSD}"}) self.nodes[0].generate(1) # Check interest has updated as expected @@ -407,7 +405,7 @@ def test_take_loan_neg_ipb_pos_ith(self): assert_equal(stored_interest['height'], self.nodes[0].getblockcount()) # Set negative interest to be inverse of positive interest - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'-3'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '-3'}}) self.nodes[0].generate(6) # Check negative rate @@ -415,13 +413,13 @@ def test_take_loan_neg_ipb_pos_ith(self): assert_equal(stored_interest['interestPerBlock'], '-0.000000380517507610350076') # Take another loan to update stored interest - self.nodes[0].takeloan({ "vaultId": vault_id, "amounts": f"0.00000001@{self.symbolDUSD}"}) + self.nodes[0].takeloan({"vaultId": vault_id, "amounts": f"0.00000001@{self.symbolDUSD}"}) self.nodes[0].generate(6) # Check interest has reduced as expected stored_interest = self.nodes[0].getstoredinterest(vault_id, self.symbolDUSD) assert_equal(stored_interest['interestPerBlock'], '-0.000000380517511415525114') - assert_equal(stored_interest['interestToHeight'], '0.000001902587500000000000') # Reduced 6 * IPB + assert_equal(stored_interest['interestToHeight'], '0.000001902587500000000000') # Reduced 6 * IPB assert_equal(stored_interest['height'], self.nodes[0].getblockcount() - 5) # Check loan amount before taking new loan @@ -429,7 +427,7 @@ def test_take_loan_neg_ipb_pos_ith(self): assert_equal(loan_tokens, [f'1.00000002@{self.symbolDUSD}']) # Take another loan to update stored interest - self.nodes[0].takeloan({ "vaultId": vault_id, "amounts": f"0.00000040@{self.symbolDUSD}"}) + self.nodes[0].takeloan({"vaultId": vault_id, "amounts": f"0.00000040@{self.symbolDUSD}"}) self.nodes[0].generate(1) # Check amount negated shown in attributes @@ -454,7 +452,7 @@ def test_take_loan_neg_ipb_pos_ith(self): self.nodes[0].clearmempool() # Take another loan to update stored interest - self.nodes[0].takeloan({ "vaultId": vault_id, "amounts": f"0.00000001@{self.symbolDUSD}"}) + self.nodes[0].takeloan({"vaultId": vault_id, "amounts": f"0.00000001@{self.symbolDUSD}"}) self.nodes[0].generate(1) # Check ITH is wiped and IPB decreased slightly @@ -472,11 +470,11 @@ def test_take_loan_neg_ipb_pos_ith(self): self.nodes[0].clearmempool() # Set mega negative interest - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'-1000000'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '-1000000'}}) self.nodes[0].generate(10) # Update token rate to negative - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'-3'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '-3'}}) self.nodes[0].generate(1) # Check ITH is more than loan amount @@ -486,7 +484,7 @@ def test_take_loan_neg_ipb_pos_ith(self): assert_equal(stored_interest['height'], self.nodes[0].getblockcount()) # Take new loan. Old loan amount should be paid off only. - self.nodes[0].takeloan({ "vaultId": vault_id, "amounts": f"0.50000000@{self.symbolDUSD}"}) + self.nodes[0].takeloan({"vaultId": vault_id, "amounts": f"0.50000000@{self.symbolDUSD}"}) self.nodes[0].generate(1) # Check loan amount only shows new loan @@ -504,9 +502,8 @@ def test_take_loan_neg_ipb_pos_ith(self): assert_equal(stored_interest['height'], self.nodes[0].getblockcount()) def test_payback_loan(self): - # Reset token interest - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'1'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '1'}}) self.nodes[0].generate(1) # Create vault @@ -523,7 +520,7 @@ def test_payback_loan(self): self.nodes[0].generate(1) # Take loan - self.nodes[0].takeloan({ "vaultId": vault_id, "amounts": f"1@{self.symbolDUSD}"}) + self.nodes[0].takeloan({"vaultId": vault_id, "amounts": f"1@{self.symbolDUSD}"}) self.nodes[0].generate(10) # Check interest @@ -531,17 +528,18 @@ def test_payback_loan(self): assert_equal(stored_interest, '0.000000380517503805175038') # Payback DUSD loan to update stored interest - self.nodes[0].paybackloan({ "vaultId": vault_id, "from": self.address, "amounts": f"0.00000001@{self.symbolDUSD}"}) + self.nodes[0].paybackloan( + {"vaultId": vault_id, "from": self.address, "amounts": f"0.00000001@{self.symbolDUSD}"}) self.nodes[0].generate(1) # Check interest has updated as expected stored_interest = self.nodes[0].getstoredinterest(vault_id, self.symbolDUSD) assert_equal(stored_interest['interestPerBlock'], '0.000000380517503805175038') - assert_equal(stored_interest['interestToHeight'], '0.000003795175038051750380') # Less 1 Sat payback + assert_equal(stored_interest['interestToHeight'], '0.000003795175038051750380') # Less 1 Sat payback assert_equal(stored_interest['height'], self.nodes[0].getblockcount()) # Set negative interest to be inverse of positive interest - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'-3'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '-3'}}) self.nodes[0].generate(6) # Check negative rate @@ -549,7 +547,8 @@ def test_payback_loan(self): assert_equal(stored_interest['interestPerBlock'], '-0.000000380517503805175038') # Payback DUSD loan to update stored interest - self.nodes[0].paybackloan({ "vaultId": vault_id, "from": self.address, "amounts": f"0.00000001@{self.symbolDUSD}"}) + self.nodes[0].paybackloan( + {"vaultId": vault_id, "from": self.address, "amounts": f"0.00000001@{self.symbolDUSD}"}) self.nodes[0].generate(6) # Check interest has reduced as expected @@ -559,7 +558,8 @@ def test_payback_loan(self): assert_equal(stored_interest['height'], self.nodes[0].getblockcount() - 5) # Payback DUSD loan to update stored interest - self.nodes[0].paybackloan({ "vaultId": vault_id, "from": self.address, "amounts": f"0.00000001@{self.symbolDUSD}"}) + self.nodes[0].paybackloan( + {"vaultId": vault_id, "from": self.address, "amounts": f"0.00000001@{self.symbolDUSD}"}) self.nodes[0].generate(6) # Check attributes. Amount was 2.00000003 before. @@ -577,7 +577,7 @@ def test_payback_loan(self): assert_equal(loan_tokens, ['0.99999959@DUSD']) # Apply token interest to update interest to height - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'-3'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '-3'}}) self.nodes[0].generate(1) # Check interest increased as expected @@ -587,7 +587,8 @@ def test_payback_loan(self): assert_equal(stored_interest['height'], self.nodes[0].getblockcount()) # Payback loan in full - self.nodes[0].paybackloan({ "vaultId": vault_id, "from": self.address, "amounts": self.nodes[0].getloantokens(vault_id)[0]}) + self.nodes[0].paybackloan( + {"vaultId": vault_id, "from": self.address, "amounts": self.nodes[0].getloantokens(vault_id)[0]}) self.nodes[0].generate(6) # Check interest has wiped as expected @@ -597,7 +598,7 @@ def test_payback_loan(self): assert_equal(stored_interest['height'], self.nodes[0].getblockcount() - 5) # Apply token interest to update interest to height - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'-3'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '-3'}}) self.nodes[0].generate(1) # Make sure that interest is still wiped and not updated @@ -607,9 +608,8 @@ def test_payback_loan(self): assert_equal(stored_interest['height'], self.nodes[0].getblockcount() - 6) def test_takeloan_close_loan(self): - # Set mega negative interest - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'-200000'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '-200000'}}) self.nodes[0].generate(1) # Create vault @@ -626,7 +626,7 @@ def test_takeloan_close_loan(self): self.nodes[0].generate(1) # Take loan - self.nodes[0].takeloan({ "vaultId": vault_id, "amounts": f"0.00000001@{self.symbolDUSD}"}) + self.nodes[0].takeloan({"vaultId": vault_id, "amounts": f"0.00000001@{self.symbolDUSD}"}) self.nodes[0].generate(60) # Check interest @@ -634,7 +634,7 @@ def test_takeloan_close_loan(self): assert_equal(stored_interest, '-0.000000000380515601217656') # Set resonable negative interest. Ends up at 0% in vault. - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'-1'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '-1'}}) self.nodes[0].generate(1) # Check interest fully negates loan amount of 1 Sat @@ -643,7 +643,7 @@ def test_takeloan_close_loan(self): assert_equal(stored_interest['interestToHeight'], '-0.000000022830936073059360') # Take loan - self.nodes[0].takeloan({ "vaultId": vault_id, "amounts": f"1@{self.symbolDUSD}"}) + self.nodes[0].takeloan({"vaultId": vault_id, "amounts": f"1@{self.symbolDUSD}"}) self.nodes[0].generate(1) # Check interest and interest to height are both zero @@ -655,9 +655,8 @@ def test_takeloan_close_loan(self): assert_equal(self.nodes[0].getloantokens(vault_id), ['1.00000000@DUSD']) def test_payback_close_loan(self): - # Set mega negative interest - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'-200000'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '-200000'}}) self.nodes[0].generate(1) # Create vault @@ -674,7 +673,7 @@ def test_payback_close_loan(self): self.nodes[0].generate(1) # Take loan - self.nodes[0].takeloan({ "vaultId": vault_id, "amounts": f"0.00000001@{self.symbolDUSD}"}) + self.nodes[0].takeloan({"vaultId": vault_id, "amounts": f"0.00000001@{self.symbolDUSD}"}) self.nodes[0].generate(60) # Check interest @@ -682,7 +681,7 @@ def test_payback_close_loan(self): assert_equal(stored_interest, '-0.000000000380515601217656') # Set resonable negative interest. Ends up at 0% in vault. - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'-1'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '-1'}}) self.nodes[0].generate(1) # Check interest fully negates loan amount of 1 Sat @@ -691,7 +690,8 @@ def test_payback_close_loan(self): assert_equal(stored_interest['interestToHeight'], '-0.000000022830936073059360') # Payback loan - self.nodes[0].paybackloan({ "vaultId": vault_id, "from": vault_address, "amounts": f"0.00000001@{self.symbolDUSD}"}) + self.nodes[0].paybackloan( + {"vaultId": vault_id, "from": vault_address, "amounts": f"0.00000001@{self.symbolDUSD}"}) self.nodes[0].generate(1) # Check interest and interest to height are both zero @@ -708,9 +708,8 @@ def test_payback_close_loan(self): assert_equal(loan_tokens, []) def test_payback_partial_close_loan(self): - # Set mega negative interest - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'-100000'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '-100000'}}) self.nodes[0].generate(1) # Create vault @@ -727,7 +726,7 @@ def test_payback_partial_close_loan(self): self.nodes[0].generate(1) # Take loan - self.nodes[0].takeloan({ "vaultId": vault_id, "amounts": f"1@{self.symbolDUSD}"}) + self.nodes[0].takeloan({"vaultId": vault_id, "amounts": f"1@{self.symbolDUSD}"}) self.nodes[0].generate(27) # Check interest @@ -735,7 +734,7 @@ def test_payback_partial_close_loan(self): assert_equal(stored_interest, '-0.019025684931506849315068') # Set resonable negative interest. Ends up at 0% in vault. - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'-1'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '-1'}}) self.nodes[0].generate(1) # Check interest fully negates loan amount of 1 Sat @@ -748,7 +747,7 @@ def test_payback_partial_close_loan(self): assert_equal(vault['interestAmounts'], [f'-0.51369349@{self.symbolDUSD}']) # Payback loan - self.nodes[0].paybackloan({ "vaultId": vault_id, "from": vault_address, "amounts": f"1@{self.symbolDUSD}"}) + self.nodes[0].paybackloan({"vaultId": vault_id, "from": vault_address, "amounts": f"1@{self.symbolDUSD}"}) self.nodes[0].generate(1) # Check interest and interest to height are both zero @@ -765,9 +764,8 @@ def test_payback_partial_close_loan(self): assert_equal(loan_tokens, []) def test_take_loan_pos_ipb_neg_ith(self): - # Set negative interest - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'-3'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '-3'}}) self.nodes[0].generate(1) # Create vault @@ -784,11 +782,11 @@ def test_take_loan_pos_ipb_neg_ith(self): self.nodes[0].generate(1) # Take DUSD loan - self.nodes[0].takeloan({ "vaultId": vault_id, "amounts": f"1@{self.symbolDUSD}"}) + self.nodes[0].takeloan({"vaultId": vault_id, "amounts": f"1@{self.symbolDUSD}"}) self.nodes[0].generate(10) # Set interest to for positive IPB - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'1'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '1'}}) self.nodes[0].generate(20) # Check interest has updated as expected @@ -798,7 +796,7 @@ def test_take_loan_pos_ipb_neg_ith(self): assert_equal(stored_interest['height'], self.nodes[0].getblockcount() - 19) # Take DUSD loan - self.nodes[0].takeloan({ "vaultId": vault_id, "amounts": f"0.00000001@{self.symbolDUSD}"}) + self.nodes[0].takeloan({"vaultId": vault_id, "amounts": f"0.00000001@{self.symbolDUSD}"}) self.nodes[0].generate(1) # Accrued interes should have wiped negative interest and left positive ITH @@ -816,15 +814,15 @@ def test_take_loan_pos_ipb_neg_ith(self): assert_equal(loan_tokens, [f'1.00000001@{self.symbolDUSD}']) # Set negative interest - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'-3'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '-3'}}) self.nodes[0].generate(20) # Set positive interest - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'1'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '1'}}) self.nodes[0].generate(1) # Take DUSD loan - self.nodes[0].takeloan({ "vaultId": vault_id, "amounts": f"0.00000400@{self.symbolDUSD}"}) + self.nodes[0].takeloan({"vaultId": vault_id, "amounts": f"0.00000400@{self.symbolDUSD}"}) self.nodes[0].generate(1) # Accrued interes should have wiped negative interest and left positive ITH @@ -846,7 +844,7 @@ def test_take_loan_pos_ipb_neg_ith(self): self.nodes[0].clearmempool() # Take DUSD loan smaller than negative interest - self.nodes[0].takeloan({ "vaultId": vault_id, "amounts": f"0.00000100@{self.symbolDUSD}"}) + self.nodes[0].takeloan({"vaultId": vault_id, "amounts": f"0.00000100@{self.symbolDUSD}"}) self.nodes[0].generate(1) # Accrued interes should have wiped negative interest and left positive ITH @@ -868,11 +866,11 @@ def test_take_loan_pos_ipb_neg_ith(self): self.nodes[0].clearmempool() # Set mega negative interest - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'-1000000'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '-1000000'}}) self.nodes[0].generate(10) # Update token interest to positive - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'1'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '1'}}) self.nodes[0].generate(1) # Check ITH is more than loan amount @@ -882,7 +880,7 @@ def test_take_loan_pos_ipb_neg_ith(self): assert_equal(stored_interest['height'], self.nodes[0].getblockcount()) # Take new loan. Old loan amount should be paid off only. - self.nodes[0].takeloan({ "vaultId": vault_id, "amounts": f"0.50000000@{self.symbolDUSD}"}) + self.nodes[0].takeloan({"vaultId": vault_id, "amounts": f"0.50000000@{self.symbolDUSD}"}) self.nodes[0].generate(1) # Check loan amount only shows new loan @@ -900,9 +898,8 @@ def test_take_loan_pos_ipb_neg_ith(self): assert_equal(stored_interest['height'], self.nodes[0].getblockcount()) def check_minimum_interest_takeloan(self): - # Set negative interest - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'-2'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '-2'}}) self.nodes[0].generate(1) # Create vault @@ -919,7 +916,7 @@ def check_minimum_interest_takeloan(self): self.nodes[0].generate(1) # Take DUSD loan - self.nodes[0].takeloan({ "vaultId": vault_id, "amounts": f"0.00000001@{self.symbolDUSD}"}) + self.nodes[0].takeloan({"vaultId": vault_id, "amounts": f"0.00000001@{self.symbolDUSD}"}) self.nodes[0].generate(1) # Check IPB is sub satoshi @@ -929,7 +926,7 @@ def check_minimum_interest_takeloan(self): assert_equal(stored_interest['height'], self.nodes[0].getblockcount()) # Take new Sat loan - self.nodes[0].takeloan({ "vaultId": vault_id, "amounts": f"0.00000001@{self.symbolDUSD}"}) + self.nodes[0].takeloan({"vaultId": vault_id, "amounts": f"0.00000001@{self.symbolDUSD}"}) self.nodes[0].generate(1) # Check IPB is doubled and ITH updated @@ -946,11 +943,9 @@ def check_minimum_interest_takeloan(self): account = self.nodes[0].getaccount(vault_address) assert_equal(account, [f'0.00000002@{self.symbolDUSD}']) - def check_minimum_interest_payback(self): - # Set negative interest - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'-2'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '-2'}}) self.nodes[0].generate(1) # Create vault @@ -967,7 +962,7 @@ def check_minimum_interest_payback(self): self.nodes[0].generate(1) # Take DUSD loan - self.nodes[0].takeloan({ "vaultId": vault_id, "amounts": f"0.00000003@{self.symbolDUSD}"}) + self.nodes[0].takeloan({"vaultId": vault_id, "amounts": f"0.00000003@{self.symbolDUSD}"}) self.nodes[0].generate(1) # Check IPB is sub satoshi @@ -977,7 +972,8 @@ def check_minimum_interest_payback(self): assert_equal(stored_interest['height'], self.nodes[0].getblockcount()) # Payback part of the DUSD loan - self.nodes[0].paybackloan({ "vaultId": vault_id, "from": vault_address, "amounts": f"0.00000001@{self.symbolDUSD}"}) + self.nodes[0].paybackloan( + {"vaultId": vault_id, "from": vault_address, "amounts": f"0.00000001@{self.symbolDUSD}"}) self.nodes[0].generate(1) # Check IPB is doubled and ITH updated @@ -995,7 +991,8 @@ def check_minimum_interest_payback(self): assert_equal(account, [f'0.00000002@{self.symbolDUSD}']) # Payback the rest of the DUSD loan - self.nodes[0].paybackloan({ "vaultId": vault_id, "from": vault_address, "amounts": f"0.00000001@{self.symbolDUSD}"}) + self.nodes[0].paybackloan( + {"vaultId": vault_id, "from": vault_address, "amounts": f"0.00000001@{self.symbolDUSD}"}) self.nodes[0].generate(1) # Check IPB is doubled and ITH updated @@ -1013,7 +1010,8 @@ def check_minimum_interest_payback(self): assert_equal(account, [f'0.00000001@{self.symbolDUSD}']) # Payback the rest of the DUSD loan - self.nodes[0].paybackloan({ "vaultId": vault_id, "from": vault_address, "amounts": f"0.00000001@{self.symbolDUSD}"}) + self.nodes[0].paybackloan( + {"vaultId": vault_id, "from": vault_address, "amounts": f"0.00000001@{self.symbolDUSD}"}) self.nodes[0].generate(1) # Check IPB and ITH now wiped @@ -1031,9 +1029,8 @@ def check_minimum_interest_payback(self): assert_equal(account, []) def test_withdraw_from_vault(self): - # Set mega negative interest - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'-100000'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '-100000'}}) self.nodes[0].generate(1) # Create vault @@ -1050,11 +1047,11 @@ def test_withdraw_from_vault(self): self.nodes[0].generate(1) # Take loan - self.nodes[0].takeloan({ "vaultId": vault_id, "amounts": f"1@{self.symbolDUSD}"}) + self.nodes[0].takeloan({"vaultId": vault_id, "amounts": f"1@{self.symbolDUSD}"}) self.nodes[0].generate(26) # Set same interest to update and check stored interest - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'-100000'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '-100000'}}) self.nodes[0].generate(1) # Check interest @@ -1087,7 +1084,7 @@ def test_withdraw_from_vault(self): assert_equal(loan_tokens, [f'0.48630651@{self.symbolDUSD}']) # Set same interest to update and check stored interest - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'-100000'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '-100000'}}) self.nodes[0].generate(1) # Check interest now enough to fully negate loan @@ -1096,7 +1093,7 @@ def test_withdraw_from_vault(self): assert_equal(stored_interest['interestToHeight'], '-0.555138866364041095890360') # Set mega negative interest - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idDUSD}/loan_minting_interest':'-100000'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idDUSD}/loan_minting_interest': '-100000'}}) self.nodes[0].generate(1) # Withdraw the rest of the collateral from vault @@ -1116,5 +1113,6 @@ def test_withdraw_from_vault(self): loan_tokens = self.nodes[0].getloantokens(vault_id) assert_equal(loan_tokens, []) + if __name__ == '__main__': StoredInterestTest().main() diff --git a/test/functional/feature_testpoolswap.py b/test/functional/feature_testpoolswap.py index be076f8bca..9d1dfe72e3 100755 --- a/test/functional/feature_testpoolswap.py +++ b/test/functional/feature_testpoolswap.py @@ -11,7 +11,8 @@ import calendar import time -class PoolPairTestPoolSwapTest (DefiTestFramework): + +class PoolPairTestPoolSwapTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 @@ -26,22 +27,22 @@ def set_test_params(self): '-fortcanningspringheight=1', '-jellyfish_regtest=1', '-simulatemainnet=1' - ]] + ]] def createOracles(self): self.oracle_address1 = self.nodes[0].getnewaddress("", "legacy") price_feeds = [{"currency": "USD", "token": "DFI"}, - {"currency": "USD", "token": "DUSD"}, - {"currency": "USD", "token": "TSLA"}, - {"currency": "USD", "token": "BTC"}] + {"currency": "USD", "token": "DUSD"}, + {"currency": "USD", "token": "TSLA"}, + {"currency": "USD", "token": "BTC"}] self.oracle_id1 = self.nodes[0].appointoracle(self.oracle_address1, price_feeds, 10) self.nodes[0].generate(1) # feed oracle oracle_prices = [{"currency": "USD", "tokenAmount": "1@TSLA"}, - {"currency": "USD", "tokenAmount": "1@DUSD"}, - {"currency": "USD", "tokenAmount": "1@BTC"}, - {"currency": "USD", "tokenAmount": "10@DFI"}] + {"currency": "USD", "tokenAmount": "1@DUSD"}, + {"currency": "USD", "tokenAmount": "1@BTC"}, + {"currency": "USD", "tokenAmount": "10@DFI"}] timestamp = calendar.timegm(time.gmtime()) self.nodes[0].setoracledata(self.oracle_id1, timestamp, oracle_prices) @@ -140,22 +141,25 @@ def setup(self): self.mn_address: [ '10000@' + self.symbolDFI, '10000@' + self.symbolDUSD] - }, self.mn_address) + }, self.mn_address) self.nodes[0].addpoolliquidity({ self.mn_address: [ '10000@' + self.symbolTSLA, '10000@' + self.symbolDFI] - }, self.mn_address) + }, self.mn_address) self.nodes[0].addpoolliquidity({ self.mn_address: [ '10000@' + self.symbolTSLA, '10000@' + self.symbolBTC] - }, self.mn_address) + }, self.mn_address) self.nodes[0].generate(1) - self.nodes[0].accounttoaccount(self.mn_address, {self.account0: str(self.swapAmount * 2) + "@" + self.symbolDFI}) - self.nodes[0].accounttoaccount(self.mn_address, {self.account0: str(self.swapAmount * 2) + "@" + self.symbolTSLA}) - self.nodes[0].accounttoaccount(self.mn_address, {self.account0: str(self.swapAmount * 2) + "@" + self.symbolBTC}) + self.nodes[0].accounttoaccount(self.mn_address, + {self.account0: str(self.swapAmount * 2) + "@" + self.symbolDFI}) + self.nodes[0].accounttoaccount(self.mn_address, + {self.account0: str(self.swapAmount * 2) + "@" + self.symbolTSLA}) + self.nodes[0].accounttoaccount(self.mn_address, + {self.account0: str(self.swapAmount * 2) + "@" + self.symbolBTC}) self.nodes[0].generate(1) def assert_testpoolswap_amount(self, swap_fn, tokenFrom, path): @@ -179,7 +183,7 @@ def test_testpoolswap_no_fee(self, swap_fn, tokenFrom, path): self.assert_testpoolswap_amount(swap_fn, tokenFrom, path) def test_testpoolswap_with_token_a_fee_in(self, swap_fn, tokenFrom, path): - self.nodes[0].setgov({"ATTRIBUTES":{ + self.nodes[0].setgov({"ATTRIBUTES": { f'v0/poolpairs/{self.DUSD_DFIPoolID}/token_a_fee_pct': '0.10', f'v0/poolpairs/{self.DUSD_DFIPoolID}/token_a_fee_direction': 'in' }}) @@ -187,7 +191,7 @@ def test_testpoolswap_with_token_a_fee_in(self, swap_fn, tokenFrom, path): self.assert_testpoolswap_amount(swap_fn, tokenFrom, path) def test_testpoolswap_with_token_b_fee_in(self, swap_fn, tokenFrom, path): - self.nodes[0].setgov({"ATTRIBUTES":{ + self.nodes[0].setgov({"ATTRIBUTES": { f'v0/poolpairs/{self.DUSD_DFIPoolID}/token_b_fee_pct': '0.10', f'v0/poolpairs/{self.DUSD_DFIPoolID}/token_b_fee_direction': 'in' }}) @@ -195,7 +199,7 @@ def test_testpoolswap_with_token_b_fee_in(self, swap_fn, tokenFrom, path): self.assert_testpoolswap_amount(swap_fn, tokenFrom, path) def test_testpoolswap_with_token_a_fee_out(self, swap_fn, tokenFrom, path): - self.nodes[0].setgov({"ATTRIBUTES":{ + self.nodes[0].setgov({"ATTRIBUTES": { f'v0/poolpairs/{self.DUSD_DFIPoolID}/token_a_fee_pct': '0.10', f'v0/poolpairs/{self.DUSD_DFIPoolID}/token_a_fee_direction': 'out' }}) @@ -203,7 +207,7 @@ def test_testpoolswap_with_token_a_fee_out(self, swap_fn, tokenFrom, path): self.assert_testpoolswap_amount(swap_fn, tokenFrom, path) def test_testpoolswap_with_token_b_fee_out(self, swap_fn, tokenFrom, path): - self.nodes[0].setgov({"ATTRIBUTES":{ + self.nodes[0].setgov({"ATTRIBUTES": { f'v0/poolpairs/{self.DUSD_DFIPoolID}/token_b_fee_pct': '0.10', f'v0/poolpairs/{self.DUSD_DFIPoolID}/token_b_fee_direction': 'out' }}) @@ -211,7 +215,7 @@ def test_testpoolswap_with_token_b_fee_out(self, swap_fn, tokenFrom, path): self.assert_testpoolswap_amount(swap_fn, tokenFrom, path) def test_testpoolswap_with_token_a_fee_in_token_b_fee_in(self, swap_fn, tokenFrom, path): - self.nodes[0].setgov({"ATTRIBUTES":{ + self.nodes[0].setgov({"ATTRIBUTES": { f'v0/poolpairs/{self.DUSD_DFIPoolID}/token_a_fee_pct': '0.10', f'v0/poolpairs/{self.DUSD_DFIPoolID}/token_b_fee_pct': '0.10', f'v0/poolpairs/{self.DUSD_DFIPoolID}/token_a_fee_direction': 'in', @@ -221,7 +225,7 @@ def test_testpoolswap_with_token_a_fee_in_token_b_fee_in(self, swap_fn, tokenFro self.assert_testpoolswap_amount(swap_fn, tokenFrom, path) def test_testpoolswap_with_token_a_fee_in_token_b_fee_out(self, swap_fn, tokenFrom, path): - self.nodes[0].setgov({"ATTRIBUTES":{ + self.nodes[0].setgov({"ATTRIBUTES": { f'v0/poolpairs/{self.DUSD_DFIPoolID}/token_a_fee_pct': '0.10', f'v0/poolpairs/{self.DUSD_DFIPoolID}/token_b_fee_pct': '0.10', f'v0/poolpairs/{self.DUSD_DFIPoolID}/token_a_fee_direction': 'in', @@ -231,7 +235,7 @@ def test_testpoolswap_with_token_a_fee_in_token_b_fee_out(self, swap_fn, tokenFr self.assert_testpoolswap_amount(swap_fn, tokenFrom, path) def test_testpoolswap_with_token_a_fee_out_token_b_fee_in(self, swap_fn, tokenFrom, path): - self.nodes[0].setgov({"ATTRIBUTES":{ + self.nodes[0].setgov({"ATTRIBUTES": { f'v0/poolpairs/{self.DUSD_DFIPoolID}/token_a_fee_pct': '0.10', f'v0/poolpairs/{self.DUSD_DFIPoolID}/token_b_fee_pct': '0.10', f'v0/poolpairs/{self.DUSD_DFIPoolID}/token_a_fee_direction': 'out', @@ -241,7 +245,7 @@ def test_testpoolswap_with_token_a_fee_out_token_b_fee_in(self, swap_fn, tokenFr self.assert_testpoolswap_amount(swap_fn, tokenFrom, path) def test_testpoolswap_with_token_a_fee_out_token_b_fee_out(self, swap_fn, tokenFrom, path): - self.nodes[0].setgov({"ATTRIBUTES":{ + self.nodes[0].setgov({"ATTRIBUTES": { f'v0/poolpairs/{self.DUSD_DFIPoolID}/token_a_fee_pct': '0.10', f'v0/poolpairs/{self.DUSD_DFIPoolID}/token_b_fee_pct': '0.10', f'v0/poolpairs/{self.DUSD_DFIPoolID}/token_a_fee_direction': 'out', @@ -251,7 +255,7 @@ def test_testpoolswap_with_token_a_fee_out_token_b_fee_out(self, swap_fn, tokenF self.assert_testpoolswap_amount(swap_fn, tokenFrom, path) def test_testpoolswap_with_multi_pool_fee(self, swap_fn, tokenFrom, path): - self.nodes[0].setgov({"ATTRIBUTES":{ + self.nodes[0].setgov({"ATTRIBUTES": { f'v0/poolpairs/{self.DUSD_DFIPoolID}/token_a_fee_pct': '0.10', f'v0/poolpairs/{self.DUSD_DFIPoolID}/token_a_fee_direction': 'in', f'v0/poolpairs/{self.DFI_TSLAPoolID}/token_a_fee_pct': '0.10', @@ -289,7 +293,8 @@ def run_test(self): # comspositeswap BTC -> DUSD swap through BTC-TSLA -> TSLA-DFI -> DFI-DUSD pools (self.nodes[0].compositeswap, self.symbolBTC, "auto"), (self.nodes[0].compositeswap, self.symbolBTC, "composite"), - (self.nodes[0].compositeswap, self.symbolBTC, [str(self.BTC_TSLAPoolID), str(self.DFI_TSLAPoolID), str(self.DUSD_DFIPoolID)]), + (self.nodes[0].compositeswap, self.symbolBTC, + [str(self.BTC_TSLAPoolID), str(self.DFI_TSLAPoolID), str(self.DUSD_DFIPoolID)]), ] testCases = [ @@ -312,5 +317,6 @@ def run_test(self): test(swap_fn, tokenFrom, path) self.rollback_to(height) + if __name__ == '__main__': PoolPairTestPoolSwapTest().main() diff --git a/test/functional/feature_token_fork.py b/test/functional/feature_token_fork.py index 171f857835..5cc41f4c28 100755 --- a/test/functional/feature_token_fork.py +++ b/test/functional/feature_token_fork.py @@ -13,19 +13,20 @@ from test_framework.authproxy import JSONRPCException from test_framework.util import assert_equal, assert_raises_rpc_error -class TokensForkTest (DefiTestFramework): + +class TokensForkTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True self.extra_args = [['-txnotokens=0', '-amkheight=120']] def run_test(self): - assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI + assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI self.nodes[0].generate(102) # Try to create token before AMK fork height but will fail: - #======================== + # ======================== collateralGold = self.nodes[0].getnewaddress("", "legacy") collateralSilver = self.nodes[0].getnewaddress("", "legacy") try: @@ -41,7 +42,7 @@ def run_test(self): }, []) except JSONRPCException as e: errorString = e.error['message'] - assert("before AMK height" in errorString) + assert ("before AMK height" in errorString) self.nodes[0].generate(1) # Before fork, create should fail, so now only have default token @@ -49,7 +50,7 @@ def run_test(self): assert_equal(len(tokens), 1) # Try to mint token before AMK fork height but will fail: - #======================== + # ======================== # Minting can't be checked here on rpc level cause token doesn't exist and it's impossible to create it # we'll check it at the end with a trick @@ -78,7 +79,7 @@ def run_test(self): self.nodes[0].generate(1) # Get token ID - id_silver = list(self.nodes[0].gettoken('SILVER#129').keys())[0] + id_silver = list(self.nodes[0].gettoken('SILVER#129').keys())[0] # Check rollback of token self.nodes[0].invalidateblock(self.nodes[0].getblockhash(self.nodes[0].getblockcount())) @@ -115,12 +116,12 @@ def run_test(self): symbolSilver = "SILVER#" + idSilver # MINT: - #======================== + # ======================== # Funding auth addresses - self.nodes[0].sendmany("", { collateralGold : 1, collateralSilver : 1 }) + self.nodes[0].sendmany("", {collateralGold: 1, collateralSilver: 1}) self.nodes[0].generate(1) - self.nodes[0].sendmany("", { collateralGold : 1, collateralSilver : 1 }) + self.nodes[0].sendmany("", {collateralGold: 1, collateralSilver: 1}) self.nodes[0].generate(1) self.nodes[0].minttokens("300@" + symbolGold, []) @@ -132,10 +133,11 @@ def run_test(self): self.start_node(0, ['-txnotokens=0']) try: self.nodes[0].minttokens("300@128", []) - assert(False) + assert (False) except JSONRPCException as e: errorString = e.error['message'] - assert("before AMK height" in errorString) + assert ("before AMK height" in errorString) + if __name__ == '__main__': - TokensForkTest ().main () + TokensForkTest().main() diff --git a/test/functional/feature_token_lock.py b/test/functional/feature_token_lock.py index 169809fab5..c031cec0d4 100755 --- a/test/functional/feature_token_lock.py +++ b/test/functional/feature_token_lock.py @@ -11,11 +11,14 @@ from decimal import Decimal import time + class TokenLockTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True - self.extra_args = [['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', '-fortcanninghillheight=1', '-fortcanningroadheight=1', '-fortcanningcrunchheight=200', '-subsidytest=1']] + self.extra_args = [ + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', + '-fortcanninghillheight=1', '-fortcanningroadheight=1', '-fortcanningcrunchheight=200', '-subsidytest=1']] def run_test(self): self.nodes[0].generate(150) @@ -36,16 +39,15 @@ def run_test(self): self.token_lock() def setup_test(self): - # Store address self.address = self.nodes[0].get_genesis_keys().ownerAuthAddress # Set token symbols - self.symbolDFI = 'DFI' - self.symbolDUSD = 'DUSD' - self.symbolTSLA = 'TSLA' + self.symbolDFI = 'DFI' + self.symbolDUSD = 'DUSD' + self.symbolTSLA = 'TSLA' self.symbolGOOGL = 'GOOGL' - self.symbolTD = 'TSLA-DUSD' + self.symbolTD = 'TSLA-DUSD' # Setup oracle oracle_address = self.nodes[0].getnewaddress("", "legacy") @@ -58,8 +60,8 @@ def setup_test(self): self.nodes[0].generate(1) # Create Oracle prices - self.price_dfi = 5 - self.price_tsla = 870 + self.price_dfi = 5 + self.price_tsla = 870 self.price_googl = 2850 # Set Oracle data @@ -102,9 +104,9 @@ def setup_test(self): }) # Set token ids - self.idDUSD = list(self.nodes[0].gettoken(self.symbolDUSD).keys())[0] - self.idTSLA = list(self.nodes[0].gettoken(self.symbolTSLA).keys())[0] - self.idGOOGL = list(self.nodes[0].gettoken(self.symbolGOOGL).keys())[0] + self.idDUSD = list(self.nodes[0].gettoken(self.symbolDUSD).keys())[0] + self.idTSLA = list(self.nodes[0].gettoken(self.symbolTSLA).keys())[0] + self.idGOOGL = list(self.nodes[0].gettoken(self.symbolGOOGL).keys())[0] # Mint tokens self.nodes[0].minttokens([f'1000000@{self.idDUSD}']) @@ -158,12 +160,11 @@ def setup_test(self): self.nodes[0].generate(1) def pool_lock(self): - # Move to fork block self.nodes[0].generate(200 - self.nodes[0].getblockcount()) # Enable token lock - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/locks/token/{self.idTSLA}':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/locks/token/{self.idTSLA}': 'true'}}) self.nodes[0].generate(1) # Try test pool swap in both directions @@ -199,7 +200,7 @@ def pool_lock(self): }) # Disable token lock - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/locks/token/{self.idTSLA}':'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/locks/token/{self.idTSLA}': 'false'}}) self.nodes[0].generate(1) # Test pool swap should now work @@ -222,7 +223,6 @@ def pool_lock(self): self.nodes[0].clearmempool() def oracle_lock(self): - # Set Oracle data self.nodes[0].setoracledata(self.oracle_id, int(time.time()), self.oracle_prices) self.nodes[0].generate(10) @@ -233,14 +233,15 @@ def oracle_lock(self): assert_equal(result['isLive'], True) # Enable token lock - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/locks/token/{self.idTSLA}':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/locks/token/{self.idTSLA}': 'true'}}) self.nodes[0].generate(1) # Check price feed disabled - assert_raises_rpc_error(-5, "Fixed interval price currently disabled due to locked token", self.nodes[0].getfixedintervalprice, f'{self.symbolTSLA}/USD') + assert_raises_rpc_error(-5, "Fixed interval price currently disabled due to locked token", + self.nodes[0].getfixedintervalprice, f'{self.symbolTSLA}/USD') # Disable token lock - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/locks/token/{self.idTSLA}':'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/locks/token/{self.idTSLA}': 'false'}}) self.nodes[0].generate(1) # Set Oracle data @@ -253,18 +254,19 @@ def oracle_lock(self): assert_equal(result['isLive'], True) def vault_lock(self): - # Take loan self.nodes[0].takeloan({'vaultId': self.vault, 'amounts': f'1@{self.symbolTSLA}'}) self.nodes[0].generate(1) # Enable token lock - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/locks/token/{self.idTSLA}':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/locks/token/{self.idTSLA}': 'true'}}) self.nodes[0].generate(1) # Try and take loan while token in vault locked - assert_raises_rpc_error(-32600, "Cannot take loan while any of the asset's price in the vault is not live", self.nodes[0].takeloan, {'vaultId': self.vault, 'amounts': f'1@{self.symbolTSLA}'}) - assert_raises_rpc_error(-32600, "Cannot take loan while any of the asset's price in the vault is not live", self.nodes[0].takeloan, {'vaultId': self.vault, 'amounts': f'1@{self.symbolGOOGL}'}) + assert_raises_rpc_error(-32600, "Cannot take loan while any of the asset's price in the vault is not live", + self.nodes[0].takeloan, {'vaultId': self.vault, 'amounts': f'1@{self.symbolTSLA}'}) + assert_raises_rpc_error(-32600, "Cannot take loan while any of the asset's price in the vault is not live", + self.nodes[0].takeloan, {'vaultId': self.vault, 'amounts': f'1@{self.symbolGOOGL}'}) # Vault amounts should be -1 while token locked result = self.nodes[0].getvault(self.vault) @@ -283,13 +285,15 @@ def vault_lock(self): assert_equal(result['interestsPerBlock'], []) # Deposit to vault should fail - assert_raises_rpc_error(-32600, "Fixed interval price currently disabled due to locked token", self.nodes[0].deposittovault, self.vault, self.address, f'100000@{self.symbolDUSD}') + assert_raises_rpc_error(-32600, "Fixed interval price currently disabled due to locked token", + self.nodes[0].deposittovault, self.vault, self.address, f'100000@{self.symbolDUSD}') # Payback loan with native token failed due to no pool to swap interest to DFI - assert_raises_rpc_error(-32600, "Pool currently disabled due to locked token", self.nodes[0].paybackloan, {'vaultId': self.vault, 'from': self.address, 'amounts': f'1@{self.symbolTSLA}'}) + assert_raises_rpc_error(-32600, "Pool currently disabled due to locked token", self.nodes[0].paybackloan, + {'vaultId': self.vault, 'from': self.address, 'amounts': f'1@{self.symbolTSLA}'}) # Disable token lock - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/locks/token/{self.idTSLA}':'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/locks/token/{self.idTSLA}': 'false'}}) self.nodes[0].generate(1) # Set Oracle data @@ -305,26 +309,26 @@ def vault_lock(self): assert_equal(result['collateralRatio'], 11494) def token_lock(self): - # Enable token lock - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/locks/token/{self.idTSLA}':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/locks/token/{self.idTSLA}': 'true'}}) self.nodes[0].generate(1) # Try and update token - assert_raises_rpc_error(-32600, "Cannot update token during lock", self.nodes[0].updatetoken, self.idTSLA, {'name':'Tesla'}) + assert_raises_rpc_error(-32600, "Cannot update token during lock", self.nodes[0].updatetoken, self.idTSLA, + {'name': 'Tesla'}) # Disable token lock - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/locks/token/{self.idTSLA}':'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/locks/token/{self.idTSLA}': 'false'}}) self.nodes[0].generate(1) # Try same update - self.nodes[0].updatetoken(self.idTSLA, {'name':'Tesla'}) + self.nodes[0].updatetoken(self.idTSLA, {'name': 'Tesla'}) self.nodes[0].generate(1) # Verify results result = self.nodes[0].gettoken(self.idTSLA)[self.idTSLA] assert_equal(result['name'], 'Tesla') + if __name__ == '__main__': TokenLockTest().main() - diff --git a/test/functional/feature_token_merge.py b/test/functional/feature_token_merge.py index 75ca0d4da8..7107375d69 100755 --- a/test/functional/feature_token_merge.py +++ b/test/functional/feature_token_merge.py @@ -11,15 +11,19 @@ from test_framework.test_framework import DefiTestFramework + def truncate(str, decimal): return str if not str.find('.') + 1 else str[:str.find('.') + decimal + 1] + class TokenMergeTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True self.extra_args = [ - ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', '-fortcanningmuseumheight=1', '-fortcanninghillheight=1', '-fortcanningroadheight=1', '-fortcanningcrunchheight=1', '-greatworldheight=1', '-jellyfish_regtest=1', '-subsidytest=1']] + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', + '-fortcanningmuseumheight=1', '-fortcanninghillheight=1', '-fortcanningroadheight=1', + '-fortcanningcrunchheight=1', '-greatworldheight=1', '-jellyfish_regtest=1', '-subsidytest=1']] def setup_oracles(self): # Symbols @@ -142,8 +146,10 @@ def setup_accounts(self): self.nodes[0].generate(1) self.sync_blocks() - self.nodes[0].accounttoaccount(self.account1, {self.account2: ["55039700.499@DUSD", "49900@DFI", "54890@T1", "102295@T2", "49900000@T3"]}) - self.nodes[0].accounttoaccount(self.account1, {self.account3: ["110300.0010@DUSD", "100@DFI", "110@T1", "205@T2", "100000@T3"]}) + self.nodes[0].accounttoaccount(self.account1, { + self.account2: ["55039700.499@DUSD", "49900@DFI", "54890@T1", "102295@T2", "49900000@T3"]}) + self.nodes[0].accounttoaccount(self.account1, { + self.account3: ["110300.0010@DUSD", "100@DFI", "110@T1", "205@T2", "100000@T3"]}) self.nodes[0].generate(1) self.sync_blocks() @@ -207,7 +213,6 @@ def setup_pools(self): self.symbolT1_T2 = "T1-T2" self.idT1_T2 = list(self.nodes[0].gettoken(self.symbolT1_T2).keys())[0] - # Add liquidity for _ in range(10): self.nodes[0].addpoolliquidity({self.account1: ["5000@DFI", "15000@DUSD"]}, self.account1) @@ -259,17 +264,17 @@ def setup(self): # Make the split and return split height for revert if needed def merge(self, tokenId, keepLocked=False): tokenSymbol = self.getTokenSymbolFromId(tokenId) - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/locks/token/{tokenId}':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/locks/token/{tokenId}': 'true'}}) self.nodes[0].generate(1) # Token split splitHeight = self.nodes[0].getblockcount() + 2 - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/oracles/splits/{str(splitHeight)}':f'{tokenId}/-2'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/oracles/splits/{str(splitHeight)}': f'{tokenId}/-2'}}) self.nodes[0].generate(2) tokenId = list(self.nodes[0].gettoken(tokenSymbol).keys())[0] if not keepLocked: - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/locks/token/{tokenId}':'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/locks/token/{tokenId}': 'false'}}) self.nodes[0].generate(1) return splitHeight @@ -287,7 +292,7 @@ def getTokenPools(self, tokenId): for pool in currentPools: if tokenSymbol in currentPools[pool]["symbol"] and currentPools[pool]["status"]: tokenPools[pool] = currentPools[pool] - assert(len(tokenPools) > 0) + assert (len(tokenPools) > 0) return tokenPools def check_attributes_on_merge(self, tokenId, revert=False): @@ -300,19 +305,19 @@ def check_attributes_on_merge(self, tokenId, revert=False): # set LP and Tokens gov vars for poolId in pools: - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/poolpairs/{poolId}/token_a_fee_pct': '0.01', - f'v0/poolpairs/{poolId}/token_b_fee_pct': '0.03'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/poolpairs/{poolId}/token_a_fee_pct': '0.01', + f'v0/poolpairs/{poolId}/token_b_fee_pct': '0.03'}}) - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{tokenId}/dex_in_fee_pct': '0.02', - f'v0/token/{tokenId}/dex_out_fee_pct': '0.005'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{tokenId}/dex_in_fee_pct': '0.02', + f'v0/token/{tokenId}/dex_out_fee_pct': '0.005'}}) self.nodes[0].generate(1) result = self.nodes[0].listgovs()[8][0]['ATTRIBUTES'] - assert(f'v0/token/{tokenId}/dex_in_fee_pct' in result) - assert(f'v0/token/{tokenId}/dex_out_fee_pct' in result) + assert (f'v0/token/{tokenId}/dex_in_fee_pct' in result) + assert (f'v0/token/{tokenId}/dex_out_fee_pct' in result) for poolId in pools: - assert(f'v0/poolpairs/{poolId}/token_a_fee_pct' in result) - assert(f'v0/poolpairs/{poolId}/token_b_fee_pct' in result) + assert (f'v0/poolpairs/{poolId}/token_a_fee_pct' in result) + assert (f'v0/poolpairs/{poolId}/token_b_fee_pct' in result) splitHeight = self.merge(tokenId) - 2 self.nodes[0].generate(1) @@ -325,16 +330,16 @@ def check_attributes_on_merge(self, tokenId, revert=False): result = self.nodes[0].listgovs()[8][0]['ATTRIBUTES'] for poolId in pools: - assert(f'v0/poolpairs/{poolId}/token_a_fee_pct' not in result) - assert(f'v0/poolpairs/{poolId}/token_b_fee_pct' not in result) - assert(f'v0/token/{tokenId}/dex_in_fee_pct' not in result) - assert(f'v0/token/{tokenId}/dex_out_fee_pct' not in result) + assert (f'v0/poolpairs/{poolId}/token_a_fee_pct' not in result) + assert (f'v0/poolpairs/{poolId}/token_b_fee_pct' not in result) + assert (f'v0/token/{tokenId}/dex_in_fee_pct' not in result) + assert (f'v0/token/{tokenId}/dex_out_fee_pct' not in result) for new_pool_id in new_pools: - assert(f'v0/poolpairs/{new_pool_id}/token_a_fee_pct' in result) - assert(f'v0/poolpairs/{new_pool_id}/token_b_fee_pct' in result) - assert(f'v0/token/{new_token_id}/dex_in_fee_pct' in result) - assert(f'v0/token/{new_token_id}/dex_out_fee_pct' in result) + assert (f'v0/poolpairs/{new_pool_id}/token_a_fee_pct' in result) + assert (f'v0/poolpairs/{new_pool_id}/token_b_fee_pct' in result) + assert (f'v0/token/{new_token_id}/dex_in_fee_pct' in result) + assert (f'v0/token/{new_token_id}/dex_out_fee_pct' in result) if not revert: return new_token_id @@ -342,23 +347,23 @@ def check_attributes_on_merge(self, tokenId, revert=False): self.rollback_to(splitHeight) result = self.nodes[0].listgovs()[8][0]['ATTRIBUTES'] for poolId in pools: - assert(f'v0/poolpairs/{poolId}/token_a_fee_pct' in result) - assert(f'v0/poolpairs/{poolId}/token_b_fee_pct' in result) - assert(f'v0/token/{tokenId}/dex_in_fee_pct' in result) - assert(f'v0/token/{tokenId}/dex_out_fee_pct' in result) + assert (f'v0/poolpairs/{poolId}/token_a_fee_pct' in result) + assert (f'v0/poolpairs/{poolId}/token_b_fee_pct' in result) + assert (f'v0/token/{tokenId}/dex_in_fee_pct' in result) + assert (f'v0/token/{tokenId}/dex_out_fee_pct' in result) for new_pool_id in new_pools: - assert(f'v0/poolpairs/{new_pool_id}/token_a_fee_pct' not in result) - assert(f'v0/poolpairs/{new_pool_id}/token_b_fee_pct' not in result) - assert(f'v0/token/{new_token_id}/dex_in_fee_pct' not in result) - assert(f'v0/token/{new_token_id}/dex_out_fee_pct' not in result) + assert (f'v0/poolpairs/{new_pool_id}/token_a_fee_pct' not in result) + assert (f'v0/poolpairs/{new_pool_id}/token_b_fee_pct' not in result) + assert (f'v0/token/{new_token_id}/dex_in_fee_pct' not in result) + assert (f'v0/token/{new_token_id}/dex_out_fee_pct' not in result) self.rollback_to(revert_block) result = self.nodes[0].listgovs()[8][0]['ATTRIBUTES'] for new_pool_id in new_pools: - assert(f'v0/poolpairs/{new_pool_id}/token_a_fee_pct' not in result) - assert(f'v0/poolpairs/{new_pool_id}/token_b_fee_pct' not in result) - assert(f'v0/token/{new_token_id}/dex_in_fee_pct' not in result) - assert(f'v0/token/{new_token_id}/dex_out_fee_pct' not in result) + assert (f'v0/poolpairs/{new_pool_id}/token_a_fee_pct' not in result) + assert (f'v0/poolpairs/{new_pool_id}/token_b_fee_pct' not in result) + assert (f'v0/token/{new_token_id}/dex_in_fee_pct' not in result) + assert (f'v0/token/{new_token_id}/dex_out_fee_pct' not in result) return 0 def getAmountFromAccount(self, account, symbol): @@ -383,13 +388,13 @@ def check_amounts_on_merge(self, poolId, tokenId, revert=False): amountLPBeforeAcc2 = self.getAmountFromAccount(self.account2, poolSymbol) amountLPBeforeAcc3 = self.getAmountFromAccount(self.account3, poolSymbol) if amountLPBeforeAcc1 != '0': - self.nodes[0].removepoolliquidity(self.account1, amountLPBeforeAcc1+"@"+poolSymbol, []) + self.nodes[0].removepoolliquidity(self.account1, amountLPBeforeAcc1 + "@" + poolSymbol, []) self.nodes[0].generate(1) if amountLPBeforeAcc2 != '0': - self.nodes[0].removepoolliquidity(self.account2, amountLPBeforeAcc2+"@"+poolSymbol, []) + self.nodes[0].removepoolliquidity(self.account2, amountLPBeforeAcc2 + "@" + poolSymbol, []) self.nodes[0].generate(1) if amountLPBeforeAcc3 != '0': - self.nodes[0].removepoolliquidity(self.account3, amountLPBeforeAcc3+"@"+poolSymbol, []) + self.nodes[0].removepoolliquidity(self.account3, amountLPBeforeAcc3 + "@" + poolSymbol, []) self.nodes[0].generate(1) amountTokenBeforeAcc1 = self.getAmountFromAccount(self.account1, tokenSymbol) @@ -407,11 +412,11 @@ def check_amounts_on_merge(self, poolId, tokenId, revert=False): amountLPAfterAcc1 = self.getAmountFromAccount(self.account1, poolSymbol) amountLPAfterAcc2 = self.getAmountFromAccount(self.account2, poolSymbol) amountLPAfterAcc3 = self.getAmountFromAccount(self.account3, poolSymbol) - self.nodes[0].removepoolliquidity(self.account1, amountLPAfterAcc1+"@"+poolSymbol, []) + self.nodes[0].removepoolliquidity(self.account1, amountLPAfterAcc1 + "@" + poolSymbol, []) self.nodes[0].generate(1) - self.nodes[0].removepoolliquidity(self.account2, amountLPAfterAcc2+"@"+poolSymbol, []) + self.nodes[0].removepoolliquidity(self.account2, amountLPAfterAcc2 + "@" + poolSymbol, []) self.nodes[0].generate(1) - self.nodes[0].removepoolliquidity(self.account3, amountLPAfterAcc3+"@"+poolSymbol, []) + self.nodes[0].removepoolliquidity(self.account3, amountLPAfterAcc3 + "@" + poolSymbol, []) self.nodes[0].generate(1) amountTokenAfterAcc1 = self.getAmountFromAccount(self.account1, tokenSymbol) amountTokenB_AfterAcc1 = self.getAmountFromAccount(self.account1, tokenBSymbol) @@ -420,12 +425,18 @@ def check_amounts_on_merge(self, poolId, tokenId, revert=False): amountTokenAfterAcc3 = self.getAmountFromAccount(self.account3, tokenSymbol) amountTokenB_AfterAcc3 = self.getAmountFromAccount(self.account3, tokenBSymbol) # Check difference is not grater than 0,001% rounding difference - assert((Decimal(amountTokenB_BeforeAcc1) - Decimal(amountTokenB_AfterAcc1)).copy_abs() <= (Decimal(0.00001)*Decimal(amountTokenB_BeforeAcc1))) - assert((Decimal(amountTokenB_BeforeAcc2) - Decimal(amountTokenB_AfterAcc2)).copy_abs() <= (Decimal(0.00001)*Decimal(amountTokenB_BeforeAcc2))) - assert((Decimal(amountTokenB_BeforeAcc3) - Decimal(amountTokenB_AfterAcc3)).copy_abs() <= (Decimal(0.00001)*Decimal(amountTokenB_BeforeAcc3))) - assert(((Decimal(amountTokenBeforeAcc1)/2) - Decimal(amountTokenAfterAcc1)).copy_abs() <= Decimal(0.00001)*Decimal(amountTokenBeforeAcc1)) - assert(((Decimal(amountTokenBeforeAcc2)/2) - Decimal(amountTokenAfterAcc2)).copy_abs() <= Decimal(0.00001)*Decimal(amountTokenBeforeAcc2)) - assert(((Decimal(amountTokenBeforeAcc3)/2) - Decimal(amountTokenAfterAcc3)).copy_abs() <= Decimal(0.00001)*Decimal(amountTokenBeforeAcc3)) + assert ((Decimal(amountTokenB_BeforeAcc1) - Decimal(amountTokenB_AfterAcc1)).copy_abs() <= ( + Decimal(0.00001) * Decimal(amountTokenB_BeforeAcc1))) + assert ((Decimal(amountTokenB_BeforeAcc2) - Decimal(amountTokenB_AfterAcc2)).copy_abs() <= ( + Decimal(0.00001) * Decimal(amountTokenB_BeforeAcc2))) + assert ((Decimal(amountTokenB_BeforeAcc3) - Decimal(amountTokenB_AfterAcc3)).copy_abs() <= ( + Decimal(0.00001) * Decimal(amountTokenB_BeforeAcc3))) + assert (((Decimal(amountTokenBeforeAcc1) / 2) - Decimal(amountTokenAfterAcc1)).copy_abs() <= Decimal( + 0.00001) * Decimal(amountTokenBeforeAcc1)) + assert (((Decimal(amountTokenBeforeAcc2) / 2) - Decimal(amountTokenAfterAcc2)).copy_abs() <= Decimal( + 0.00001) * Decimal(amountTokenBeforeAcc2)) + assert (((Decimal(amountTokenBeforeAcc3) / 2) - Decimal(amountTokenAfterAcc3)).copy_abs() <= Decimal( + 0.00001) * Decimal(amountTokenBeforeAcc3)) if revert: self.rollback_to(revertHeight) @@ -463,6 +474,6 @@ def run_test(self): self.idT3 = self.check_amounts_on_merge(self.idT3_DUSD, self.idT3, revert=False) self.idT2 = self.check_amounts_on_merge(self.idT1_T2, self.idT2, revert=False) + if __name__ == '__main__': TokenMergeTest().main() - diff --git a/test/functional/feature_token_merge_usd_value.py b/test/functional/feature_token_merge_usd_value.py index ab36e12b81..2841b392e4 100755 --- a/test/functional/feature_token_merge_usd_value.py +++ b/test/functional/feature_token_merge_usd_value.py @@ -13,15 +13,19 @@ import time import random + def truncate(str, decimal): return str if not str.find('.') + 1 else str[:str.find('.') + decimal + 1] + class TokenMergeUSDValueTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True self.extra_args = [ - ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', '-fortcanningmuseumheight=1', '-fortcanninghillheight=1', '-fortcanningroadheight=1', '-fortcanningcrunchheight=1', '-greatworldheight=1', '-jellyfish_regtest=1', '-subsidytest=1']] + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', + '-fortcanningmuseumheight=1', '-fortcanninghillheight=1', '-fortcanningroadheight=1', + '-fortcanningcrunchheight=1', '-greatworldheight=1', '-jellyfish_regtest=1', '-subsidytest=1']] def setup_oracles(self): # Symbols @@ -94,14 +98,15 @@ def generate_and_fill_accounts(self, nAccounts=20): totalT1 = 10000000 self.accounts.sort() self.nodes[0].utxostoaccount({self.account1: "10000000@0"}) - self.nodes[0].minttokens(str(totalDUSD)+"@DUSD") - self.nodes[0].minttokens(str(totalT1)+"@T1") + self.nodes[0].minttokens(str(totalDUSD) + "@DUSD") + self.nodes[0].minttokens(str(totalT1) + "@T1") self.nodes[0].generate(1) - perAccountDUSD = totalDUSD/nAccounts - perAccountT1 = totalT1/nAccounts + perAccountDUSD = totalDUSD / nAccounts + perAccountT1 = totalT1 / nAccounts for account in self.accounts: - self.nodes[0].accounttoaccount(self.account1, {account: [str(perAccountDUSD)+"@DUSD", str(perAccountT1)+"@T1"]}) + self.nodes[0].accounttoaccount(self.account1, + {account: [str(perAccountDUSD) + "@DUSD", str(perAccountT1) + "@T1"]}) self.nodes[0].generate(1) def setup_accounts(self): @@ -114,13 +119,14 @@ def add_total_account_to_liquidity_pool(self): totalAmount = Decimal(self.get_amount_from_account(account, self.symbolDUSD)) while size >= 10: while Decimal(totalAmount) >= size: - tmpAmount = Decimal(random.randint(int(size/10), int(size-1))) - self.nodes[0].addpoolliquidity({account: [str(tmpAmount)+"@T1", str(tmpAmount)+"@DUSD"]}, account) + tmpAmount = Decimal(random.randint(int(size / 10), int(size - 1))) + self.nodes[0].addpoolliquidity({account: [str(tmpAmount) + "@T1", str(tmpAmount) + "@DUSD"]}, + account) self.nodes[0].generate(1) totalAmount -= tmpAmount size /= 10 finalAmount = Decimal(self.get_amount_from_account(account, self.symbolDUSD)) - self.nodes[0].addpoolliquidity({account: [str(finalAmount)+"@T1", str(finalAmount)+"@DUSD"]}, account) + self.nodes[0].addpoolliquidity({account: [str(finalAmount) + "@T1", str(finalAmount) + "@DUSD"]}, account) self.nodes[0].generate(1) totalAmount -= finalAmount @@ -155,7 +161,7 @@ def oracle_split(self): self.nodes[0].generate(10) def merge(self, tokenId, keepLocked=False, oracleSplit=False, multiplier=2): - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/locks/token/{tokenId}':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/locks/token/{tokenId}': 'true'}}) self.nodes[0].generate(1) if oracleSplit: @@ -163,23 +169,23 @@ def merge(self, tokenId, keepLocked=False, oracleSplit=False, multiplier=2): # Token split splitHeight = self.nodes[0].getblockcount() + 2 - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/oracles/splits/{str(splitHeight)}':f'{tokenId}/-{multiplier}'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/oracles/splits/{str(splitHeight)}': f'{tokenId}/-{multiplier}'}}) self.nodes[0].generate(2) self.idT1old = tokenId self.idT1 = list(self.nodes[0].gettoken(self.symbolT1).keys())[0] if not keepLocked: - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/locks/token/{self.idT1}':'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/locks/token/{self.idT1}': 'false'}}) self.nodes[0].generate(1) def remove_from_pool(self, account): amountLP = self.get_amount_from_account(account, "T1-DUSD") - self.nodes[0].removepoolliquidity(account, amountLP+"@T1-DUSD", []) + self.nodes[0].removepoolliquidity(account, amountLP + "@T1-DUSD", []) self.nodes[0].generate(1) def accounts_usd_values(self): - values =[] + values = [] revertHeight = self.nodes[0].getblockcount() activePriceT1 = self.nodes[0].getfixedintervalprice(f"{self.symbolT1}/USD")["activePrice"] activePriceDUSD = self.nodes[0].getfixedintervalprice(f"{self.symbolDUSD}/USD")["activePrice"] @@ -188,7 +194,7 @@ def accounts_usd_values(self): self.remove_from_pool(account) amounts["account"] = account amounts["DUSD"] = Decimal(self.get_amount_from_account(account, "DUSD")) * Decimal(activePriceDUSD) - amounts["T1"] = Decimal(self.get_amount_from_account(account, "T1")) *Decimal(activePriceT1) + amounts["T1"] = Decimal(self.get_amount_from_account(account, "T1")) * Decimal(activePriceT1) values.append(amounts) self.rollback_to(revertHeight) return values @@ -219,7 +225,7 @@ def get_token_pools(self, tokenId): for pool in currentPools: if tokenSymbol in currentPools[pool]["symbol"] and currentPools[pool]["status"]: tokenPools[pool] = currentPools[pool] - assert(len(tokenPools) > 0) + assert (len(tokenPools) > 0) return tokenPools def get_amount_from_account(self, account, symbol): @@ -240,7 +246,7 @@ def compare_usd_account_value_on_merge(self, revert=False): self.compare_value_list(value_accounts_pre_split, value_accounts_post_split) if revert: self.rollback_to(revertHeight) - self.idT1=self.idT1old + self.idT1 = self.idT1old def setup_vaults(self, collateralSplit=False): self.nodes[0].createloanscheme(200, 0.01, 'LOAN_0') @@ -249,24 +255,24 @@ def setup_vaults(self, collateralSplit=False): vaultCount = 0 for account in self.accounts: self.remove_from_pool(account) - vaultId= self.nodes[0].createvault(account) + vaultId = self.nodes[0].createvault(account) self.nodes[0].generate(1) vaultCount += 1 self.vaults.append(vaultId) amountT1 = self.get_amount_from_account(account, "T1") - amountT1 = Decimal(amountT1)/Decimal(4) + amountT1 = Decimal(amountT1) / Decimal(4) if collateralSplit: - amountT1 = Decimal(amountT1)/Decimal(2) + amountT1 = Decimal(amountT1) / Decimal(2) amountDUSD = self.get_amount_from_account(account, "DUSD") - amountDUSD = Decimal(amountDUSD)/Decimal(2) + amountDUSD = Decimal(amountDUSD) / Decimal(2) if collateralSplit: - self.nodes[0].deposittovault(vaultId, account, str(amountT1)+"@T1") - self.nodes[0].deposittovault(vaultId, account, str(amountDUSD)+"@DUSD") + self.nodes[0].deposittovault(vaultId, account, str(amountT1) + "@T1") + self.nodes[0].deposittovault(vaultId, account, str(amountDUSD) + "@DUSD") self.nodes[0].generate(1) - amountT1Loan = Decimal(amountT1)/Decimal(2) + amountT1Loan = Decimal(amountT1) / Decimal(2) self.nodes[0].takeloan({ - 'vaultId': vaultId, - 'amounts': str(amountT1Loan)+"@T1"}) + 'vaultId': vaultId, + 'amounts': str(amountT1Loan) + "@T1"}) self.nodes[0].generate(1) def get_vaults_usd_values(self): @@ -283,11 +289,11 @@ def compare_usd_vaults_values_on_split(self, revert=False): self.merge(self.idT1, oracleSplit=True, multiplier=20) self.nodes[0].generate(40) vault_values_post_split = self.get_vaults_usd_values() - self.compare_vaults_list(vault_values_pre_split,vault_values_post_split) + self.compare_vaults_list(vault_values_pre_split, vault_values_post_split) if revert: self.rollback_to(revertHeight) - self.idT1=self.idT1old + self.idT1 = self.idT1old def test_values_non_zero_with_token_locked(self): self.setup_vaults() @@ -303,7 +309,7 @@ def test_values_non_zero_with_token_locked(self): def test_values_after_token_unlock(self): # Unlock token - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/locks/token/{self.idT1}':'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/locks/token/{self.idT1}': 'false'}}) self.nodes[0].generate(1) vaults_values = self.get_vaults_usd_values() for vault in vaults_values: @@ -321,5 +327,6 @@ def run_test(self): self.test_values_non_zero_with_token_locked() self.test_values_after_token_unlock() + if __name__ == '__main__': TokenMergeUSDValueTest().main() diff --git a/test/functional/feature_token_split.py b/test/functional/feature_token_split.py index 0e12c64deb..63d5e23d0c 100755 --- a/test/functional/feature_token_split.py +++ b/test/functional/feature_token_split.py @@ -12,16 +12,20 @@ import time import random + def truncate(str, decimal): return str if not str.find('.') + 1 else str[:str.find('.') + decimal + 1] + class TokenSplitTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True self.fort_canning_crunch = 600 self.extra_args = [ - ['-vaultindex=1', '-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', '-fortcanningmuseumheight=1', '-fortcanninghillheight=1', '-fortcanningroadheight=1', f'-fortcanningcrunchheight={self.fort_canning_crunch}', '-subsidytest=1']] + ['-vaultindex=1', '-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', + '-fortcanningheight=1', '-fortcanningmuseumheight=1', '-fortcanninghillheight=1', + '-fortcanningroadheight=1', f'-fortcanningcrunchheight={self.fort_canning_crunch}', '-subsidytest=1']] def run_test(self): self.setup_test_tokens() @@ -266,10 +270,12 @@ def setup_test_pools(self): self.idGD = list(self.nodes[0].gettoken(self.symbolGD).keys())[0] # Set pool gov vars - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/poolpairs/{self.idGD}/token_a_fee_pct': '0.01', f'v0/poolpairs/{self.idGD}/token_b_fee_pct': '0.03', - f'v0/token/{self.idGOOGL}/dex_in_fee_pct': '0.02', f'v0/token/{self.idGOOGL}/dex_out_fee_pct': '0.005'}}) - self.nodes[0].setgov({"LP_SPLITS": { str(self.idGD): 1}}) - self.nodes[0].setgov({"LP_LOAN_TOKEN_SPLITS": { str(self.idGD): 1}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/poolpairs/{self.idGD}/token_a_fee_pct': '0.01', + f'v0/poolpairs/{self.idGD}/token_b_fee_pct': '0.03', + f'v0/token/{self.idGOOGL}/dex_in_fee_pct': '0.02', + f'v0/token/{self.idGOOGL}/dex_out_fee_pct': '0.005'}}) + self.nodes[0].setgov({"LP_SPLITS": {str(self.idGD): 1}}) + self.nodes[0].setgov({"LP_LOAN_TOKEN_SPLITS": {str(self.idGD): 1}}) self.nodes[0].generate(1) # Randomly populate pool @@ -339,14 +345,14 @@ def check_token_split(self, token_id, token_symbol, token_suffix, multiplier, mi # Check old token in Gov vars result = self.nodes[0].listgovs("attrs")[0][0]['ATTRIBUTES'] - assert(f'v0/token/{token_id}/fixed_interval_price_id' not in result) + assert (f'v0/token/{token_id}/fixed_interval_price_id' not in result) if collateral: - assert(f'v0/token/{token_id}/loan_collateral_enabled' not in result) - assert(f'v0/token/{token_id}/loan_collateral_factor' not in result) + assert (f'v0/token/{token_id}/loan_collateral_enabled' not in result) + assert (f'v0/token/{token_id}/loan_collateral_factor' not in result) if loan: - assert(f'v0/token/{token_id}/loan_minting_enabled' not in result) - assert(f'v0/token/{token_id}/loan_minting_interest' not in result) - assert(f'v0/locks/token/{token_id}' not in result) + assert (f'v0/token/{token_id}/loan_minting_enabled' not in result) + assert (f'v0/token/{token_id}/loan_minting_interest' not in result) + assert (f'v0/locks/token/{token_id}' not in result) # Save old ID and get new one token_idv1 = token_id @@ -360,7 +366,7 @@ def check_token_split(self, token_id, token_symbol, token_suffix, multiplier, mi if loan: assert_equal(result[f'v0/token/{token_id}/loan_minting_enabled'], 'true') assert_equal(result[f'v0/token/{token_id}/loan_minting_interest'], '0') - assert(f'v0/oracles/splits/{self.nodes[0].getblockcount()}' not in result) + assert (f'v0/oracles/splits/{self.nodes[0].getblockcount()}' not in result) assert_equal(result[f'v0/token/{token_idv1}/descendant'], f'{token_id}/{self.nodes[0].getblockcount()}') assert_equal(result[f'v0/token/{token_id}/ascendant'], f'{token_idv1}/split') assert_equal(result[f'v0/locks/token/{token_id}'], 'true') @@ -383,7 +389,8 @@ def check_token_split(self, token_id, token_symbol, token_suffix, multiplier, mi for val in result: assert_equal(val.find(f'{token_symbol}{token_suffix}'), -1) - def check_pool_split(self, pool_id, pool_symbol, token_id, token_symbol, token_suffix, minted, reserve_a, reserve_b): + def check_pool_split(self, pool_id, pool_symbol, token_id, token_symbol, token_suffix, minted, reserve_a, + reserve_b): # Check old pool result = self.nodes[0].getpoolpair(pool_id)[pool_id] @@ -394,21 +401,21 @@ def check_pool_split(self, pool_id, pool_symbol, token_id, token_symbol, token_s assert_equal(result['reserveB/reserveA'], '0') assert_equal(result['status'], False) assert_equal(result['tradeEnabled'], False) - assert('dexFeePctTokenA' not in result) - assert('dexFeeInPctTokenA' not in result) - assert('dexFeeOutPctTokenA' not in result) - assert('dexFeePctTokenB' not in result) - assert('dexFeeInPctTokenB' not in result) - assert('dexFeeOutPctTokenB' not in result) + assert ('dexFeePctTokenA' not in result) + assert ('dexFeeInPctTokenA' not in result) + assert ('dexFeeOutPctTokenA' not in result) + assert ('dexFeePctTokenB' not in result) + assert ('dexFeeInPctTokenB' not in result) + assert ('dexFeeOutPctTokenB' not in result) assert_equal(result['rewardPct'], Decimal('0.00000000')) assert_equal(result['rewardLoanPct'], Decimal('0.00000000')) # Validate old Gov vars removed result = self.nodes[0].listgovs("attrs")[0][0]['ATTRIBUTES'] - assert(f'v0/poolpairs/{pool_id}/token_a_fee_pct' not in result) - assert(f'v0/poolpairs/{pool_id}/token_b_fee_pct' not in result) - assert(f'v0/token/{token_id}/dex_in_fee_pct' not in result) - assert(f'v0/token/{token_id}/dex_out_fee_pct' not in result) + assert (f'v0/poolpairs/{pool_id}/token_a_fee_pct' not in result) + assert (f'v0/poolpairs/{pool_id}/token_b_fee_pct' not in result) + assert (f'v0/token/{token_id}/dex_in_fee_pct' not in result) + assert (f'v0/token/{token_id}/dex_out_fee_pct' not in result) # Swap old for new values token_id = list(self.nodes[0].gettoken(token_symbol).keys())[0] @@ -448,7 +455,8 @@ def check_pool_split(self, pool_id, pool_symbol, token_id, token_symbol, token_s # Check that LP_SPLITS and LP_LOAN_TOKEN_SPLITS updated assert_equal(self.nodes[0].getgov('LP_SPLITS')['LP_SPLITS'], {pool_id: Decimal('1.00000000')}) - assert_equal(self.nodes[0].getgov('LP_LOAN_TOKEN_SPLITS')['LP_LOAN_TOKEN_SPLITS'], {pool_id: Decimal('1.00000000')}) + assert_equal(self.nodes[0].getgov('LP_LOAN_TOKEN_SPLITS')['LP_LOAN_TOKEN_SPLITS'], + {pool_id: Decimal('1.00000000')}) def token_split(self): @@ -495,13 +503,13 @@ def token_split(self): }) # Set extra Gov vars for token - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idTSLA}/dfip2203':'true', - f'v0/token/{self.idTSLA}/loan_payback/{self.idDUSD}': 'true', - f'v0/token/{self.idGOOGL}/loan_payback/{self.idTSLA}': 'true', - f'v0/token/{self.idTSLA}/loan_payback/{self.idTSLA}': 'true', - f'v0/token/{self.idGOOGL}/loan_payback_fee_pct/{self.idTSLA}': '0.25', - f'v0/token/{self.idTSLA}/loan_payback_fee_pct/{self.idTSLA}': '0.25', - f'v0/token/{self.idTSLA}/loan_payback_fee_pct/{self.idDUSD}': '0.25'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.idTSLA}/dfip2203': 'true', + f'v0/token/{self.idTSLA}/loan_payback/{self.idDUSD}': 'true', + f'v0/token/{self.idGOOGL}/loan_payback/{self.idTSLA}': 'true', + f'v0/token/{self.idTSLA}/loan_payback/{self.idTSLA}': 'true', + f'v0/token/{self.idGOOGL}/loan_payback_fee_pct/{self.idTSLA}': '0.25', + f'v0/token/{self.idTSLA}/loan_payback_fee_pct/{self.idTSLA}': '0.25', + f'v0/token/{self.idTSLA}/loan_payback_fee_pct/{self.idDUSD}': '0.25'}}) self.nodes[0].generate(1) result = self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'] @@ -524,11 +532,12 @@ def token_split(self): minted = self.nodes[0].gettoken(self.idTSLA)[self.idTSLA]['minted'] * 2 # Lock token - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/locks/token/{self.idTSLA}':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/locks/token/{self.idTSLA}': 'true'}}) self.nodes[0].generate(1) # Token split - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/oracles/splits/{str(self.nodes[0].getblockcount() + 2)}':f'{self.idTSLA}/2'}}) + self.nodes[0].setgov( + {"ATTRIBUTES": {f'v0/oracles/splits/{str(self.nodes[0].getblockcount() + 2)}': f'{self.idTSLA}/2'}}) self.nodes[0].generate(2) # Check token split correctly @@ -558,7 +567,8 @@ def token_split(self): assert_equal(history[1]['amounts'][0], account[0]) # Token split - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/oracles/splits/{str(self.nodes[0].getblockcount() + 2)}':f'{self.idTSLA}/-3'}}) + self.nodes[0].setgov( + {"ATTRIBUTES": {f'v0/oracles/splits/{str(self.nodes[0].getblockcount() + 2)}': f'{self.idTSLA}/-3'}}) self.nodes[0].generate(2) # Check new balances @@ -577,7 +587,7 @@ def token_split(self): self.idTSLA = list(self.nodes[0].gettoken(self.symbolTSLA).keys())[0] # Unlock token - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/locks/token/{self.idTSLA}':'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/locks/token/{self.idTSLA}': 'false'}}) self.nodes[0].generate(1) def pool_split(self): @@ -600,26 +610,30 @@ def pool_split(self): assert_equal(result['rewardLoanPct'], Decimal('1.00000000')) # Lock token - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/locks/token/{self.idGOOGL}':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/locks/token/{self.idGOOGL}': 'true'}}) self.nodes[0].generate(1) # Token split - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/oracles/splits/{str(self.nodes[0].getblockcount() + 2)}':f'{self.idGOOGL}/2'}}) + self.nodes[0].setgov( + {"ATTRIBUTES": {f'v0/oracles/splits/{str(self.nodes[0].getblockcount() + 2)}': f'{self.idGOOGL}/2'}}) self.nodes[0].generate(2) # Check token split correctly self.check_token_split(self.idGOOGL, self.symbolGOOGL, '/v1', 2, str(self.poolGDTotal * 2), False, True) # Check pool migrated successfully - self.check_pool_split(self.idGD, self.symbolGD, self.idGOOGL, self.symbolGOOGL, '/v1', self.poolGDTotal * 2, Decimal('2.00000000'), Decimal('0.50000000')) + self.check_pool_split(self.idGD, self.symbolGD, self.idGOOGL, self.symbolGOOGL, '/v1', self.poolGDTotal * 2, + Decimal('2.00000000'), Decimal('0.50000000')) # Swap old for new values self.idGOOGL = list(self.nodes[0].gettoken(self.symbolGOOGL).keys())[0] self.idGD = list(self.nodes[0].gettoken(self.symbolGD).keys())[0] # Check token split records in account history - balances = self.nodes[0].gettokenbalances({'start': int(self.idGD), 'including_start': True, 'limit': 1}, False, True) - result = self.nodes[0].listaccounthistory(self.address, {"maxBlockHeight":self.nodes[0].getblockcount(), 'txtype': 'TokenSplit', 'depth':0}) + balances = self.nodes[0].gettokenbalances({'start': int(self.idGD), 'including_start': True, 'limit': 1}, False, + True) + result = self.nodes[0].listaccounthistory(self.address, {"maxBlockHeight": self.nodes[0].getblockcount(), + 'txtype': 'TokenSplit', 'depth': 0}) assert_equal(result[0]['owner'], self.address) assert_equal(result[0]['type'], 'TokenSplit') assert_equal(result[0]['amounts'], [f'-{self.poolGDTotal - Decimal("0.00001")}@{self.symbolGD}/v1']) @@ -628,7 +642,8 @@ def pool_split(self): assert_equal(result[1]['amounts'], balances) # Token split - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/oracles/splits/{str(self.nodes[0].getblockcount() + 2)}':f'{self.idGOOGL}/-3'}}) + self.nodes[0].setgov( + {"ATTRIBUTES": {f'v0/oracles/splits/{str(self.nodes[0].getblockcount() + 2)}': f'{self.idGOOGL}/-3'}}) self.nodes[0].generate(2) # Check token split correctly @@ -636,13 +651,14 @@ def pool_split(self): self.check_token_split(self.idGOOGL, self.symbolGOOGL, '/v2', -3, minted, False, True) # Check pool migrated successfully - self.check_pool_split(self.idGD, self.symbolGD, self.idGOOGL, self.symbolGOOGL, '/v2', minted, Decimal('0.66666666'), Decimal('1.50000000')) + self.check_pool_split(self.idGD, self.symbolGD, self.idGOOGL, self.symbolGOOGL, '/v2', minted, + Decimal('0.66666666'), Decimal('1.50000000')) # Swap old for new values self.idGOOGL = list(self.nodes[0].gettoken(self.symbolGOOGL).keys())[0] # Unlock token - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/locks/token/{self.idGOOGL}':'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/locks/token/{self.idGOOGL}': 'false'}}) self.nodes[0].generate(1) def execute_vault_split(self, token_id, token_symbol, multiplier, suffix): @@ -654,11 +670,12 @@ def execute_vault_split(self, token_id, token_symbol, multiplier, suffix): minted = self.nodes[0].gettoken(token_id)[token_id]['minted'] * multiplier # Lock token - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/locks/token/{token_id}':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/locks/token/{token_id}': 'true'}}) self.nodes[0].generate(1) # Token split - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/oracles/splits/{str(self.nodes[0].getblockcount() + 2)}':f'{token_id}/{multiplier}'}}) + self.nodes[0].setgov( + {"ATTRIBUTES": {f'v0/oracles/splits/{str(self.nodes[0].getblockcount() + 2)}': f'{token_id}/{multiplier}'}}) self.nodes[0].generate(1) # Vault array @@ -706,7 +723,7 @@ def execute_vault_split(self, token_id, token_symbol, multiplier, suffix): token_id = list(self.nodes[0].gettoken(token_symbol).keys())[0] # Unlock token - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/locks/token/{token_id}':'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/locks/token/{token_id}': 'false'}}) self.nodes[0].generate(1) def vault_split(self): @@ -739,7 +756,8 @@ def vault_split(self): self.execute_vault_split(self.idNVDA, self.symbolNVDA, 2, '/v1') # Check split history - result = self.nodes[0].listvaulthistory(self.vault_id, {'maxBlockHeight': self.nodes[0].getblockcount(), 'depth':1}) + result = self.nodes[0].listvaulthistory(self.vault_id, + {'maxBlockHeight': self.nodes[0].getblockcount(), 'depth': 1}) assert_equal(result[0]['address'], self.address) assert_equal(result[0]['type'], 'TokenSplit') assert_equal(result[0]['amounts'], [f'-{self.vault_loan}@{self.symbolNVDA}/v1']) @@ -758,15 +776,15 @@ def vault_split(self): def check_govvar_deletion(self): # Lock token - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/locks/token/{self.idTSLA}':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/locks/token/{self.idTSLA}': 'true'}}) self.nodes[0].generate(1) # Token split split_height = self.nodes[0].getblockcount() + 2 - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/oracles/splits/{split_height}':f'{self.idTSLA}/2'}}) - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/oracles/splits/500000':f'{self.idTSLA}/2'}}) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/oracles/splits/1000000':f'{self.idTSLA}/2'}}) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/oracles/splits/1000001':f'{self.idNVDA}/2'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/oracles/splits/{split_height}': f'{self.idTSLA}/2'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/oracles/splits/500000': f'{self.idTSLA}/2'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/oracles/splits/1000000': f'{self.idTSLA}/2'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/oracles/splits/1000001': f'{self.idNVDA}/2'}}) self.nodes[0].generate(1) # Check splits @@ -781,28 +799,28 @@ def check_govvar_deletion(self): # Check TSLA entries removed result = self.nodes[0].listgovs("attrs")[0][0]['ATTRIBUTES'] - assert(f'v0/oracles/splits/{split_height}' not in result) - assert(f'v0/oracles/splits/500000' not in result) + assert (f'v0/oracles/splits/{split_height}' not in result) + assert (f'v0/oracles/splits/500000' not in result) assert_equal(result[f'v0/oracles/splits/1000001'], f'{self.idNVDA}/2') # Swap old for new values self.idTSLA = list(self.nodes[0].gettoken(self.symbolTSLA).keys())[0] # Unlock token - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/locks/token/{self.idTSLA}':'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/locks/token/{self.idTSLA}': 'false'}}) self.nodes[0].generate(1) def check_future_swap_refund(self): # Set all futures attributes - self.nodes[0].setgov({"ATTRIBUTES":{ - 'v0/params/dfip2203/reward_pct':'0.05', - 'v0/params/dfip2203/block_period':'2880' + self.nodes[0].setgov({"ATTRIBUTES": { + 'v0/params/dfip2203/reward_pct': '0.05', + 'v0/params/dfip2203/block_period': '2880' }}) self.nodes[0].generate(1) - self.nodes[0].setgov({"ATTRIBUTES":{ - 'v0/params/dfip2203/active':'true' + self.nodes[0].setgov({"ATTRIBUTES": { + 'v0/params/dfip2203/active': 'true' }}) self.nodes[0].generate(1) @@ -838,12 +856,15 @@ def check_future_swap_refund(self): assert_equal(result, []) # Token split - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/oracles/splits/{str(self.nodes[0].getblockcount() + 2)}':f'{self.idMSFT}/2'}}) + self.nodes[0].setgov( + {"ATTRIBUTES": {f'v0/oracles/splits/{str(self.nodes[0].getblockcount() + 2)}': f'{self.idMSFT}/2'}}) self.nodes[0].generate(1) # Test creating future swaps with locked tokens - assert_raises_rpc_error(-32600, 'Cannot create future swap for locked token', self.nodes[0].futureswap, address_locked, f'1@{self.symbolDUSD}', int(self.idMSFT)) - assert_raises_rpc_error(-32600, 'Cannot create future swap for locked token', self.nodes[0].futureswap, address_locked, f'1@{self.symbolMSFT}') + assert_raises_rpc_error(-32600, 'Cannot create future swap for locked token', self.nodes[0].futureswap, + address_locked, f'1@{self.symbolDUSD}', int(self.idMSFT)) + assert_raises_rpc_error(-32600, 'Cannot create future swap for locked token', self.nodes[0].futureswap, + address_locked, f'1@{self.symbolMSFT}') # Move to split block self.nodes[0].generate(1) @@ -853,7 +874,8 @@ def check_future_swap_refund(self): assert_equal(result, [f'1.00000000@{self.symbolDUSD}', f'2.00000000@{self.symbolMSFT}']) # Check future swap and token split account history - result = self.nodes[0].listaccounthistory(address_msft, {"maxBlockHeight":self.nodes[0].getblockcount(), 'depth':0}) + result = self.nodes[0].listaccounthistory(address_msft, + {"maxBlockHeight": self.nodes[0].getblockcount(), 'depth': 0}) assert_equal(result[0]['owner'], address_msft) assert_equal(result[0]['type'], 'FutureSwapRefund') assert_equal(result[0]['amounts'], [f'1.00000000@{self.symbolDUSD}']) @@ -880,7 +902,8 @@ def check_future_swap_refund(self): assert_equal(self.nodes[0].getblockcount(), future_block) # Account history should now be empty - result = self.nodes[0].listaccounthistory(address_msft, {"maxBlockHeight":self.nodes[0].getblockcount(), 'depth':0}) + result = self.nodes[0].listaccounthistory(address_msft, + {"maxBlockHeight": self.nodes[0].getblockcount(), 'depth': 0}) assert_equal(result, []) def migrate_auction_batches(self): @@ -950,9 +973,12 @@ def migrate_auction_batches(self): self.nodes[0].generate(1) # Token split - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/oracles/splits/{str(self.nodes[0].getblockcount() + 2)}':f'{self.idMSFT}/2'}}) - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/oracles/splits/{str(self.nodes[0].getblockcount() + 3)}':f'{self.idTWTR}/2'}}) - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/oracles/splits/{str(self.nodes[0].getblockcount() + 4)}':f'{self.idNVDA}/2'}}) + self.nodes[0].setgov( + {"ATTRIBUTES": {f'v0/oracles/splits/{str(self.nodes[0].getblockcount() + 2)}': f'{self.idMSFT}/2'}}) + self.nodes[0].setgov( + {"ATTRIBUTES": {f'v0/oracles/splits/{str(self.nodes[0].getblockcount() + 3)}': f'{self.idTWTR}/2'}}) + self.nodes[0].setgov( + {"ATTRIBUTES": {f'v0/oracles/splits/{str(self.nodes[0].getblockcount() + 4)}': f'{self.idNVDA}/2'}}) self.nodes[0].generate(4) # Swap old for new values @@ -978,17 +1004,19 @@ def migrate_auction_batches(self): assert_equal(vault2_result['batches'][0]['loan'], f'4.00000070@{self.symbolMSFT}') assert_equal(vault2_result['batches'][0]['collaterals'], [f'2.00000000@{self.symbolDFI}']) assert_equal(vault3_result['batches'][0]['loan'], f'2.00000035@{self.symbolGOOGL}') - assert_equal(vault3_result['batches'][0]['collaterals'], [f'1.00000000@{self.symbolDUSD}', f'1.00000000@{self.symbolTWTR}']) + assert_equal(vault3_result['batches'][0]['collaterals'], + [f'1.00000000@{self.symbolDUSD}', f'1.00000000@{self.symbolTWTR}']) # Unlock token - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/locks/token/{self.idMSFT}':'false'}}) - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/locks/token/{self.idTWTR}':'false'}}) - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/locks/token/{self.idNVDA}':'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/locks/token/{self.idMSFT}': 'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/locks/token/{self.idTWTR}': 'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/locks/token/{self.idNVDA}': 'false'}}) self.nodes[0].generate(1) # Check collateral ratio still the same result = self.nodes[0].getvault(vault4) assert_equal(result['collateralRatio'], 150) + if __name__ == '__main__': TokenSplitTest().main() diff --git a/test/functional/feature_token_split_mechanism.py b/test/functional/feature_token_split_mechanism.py index fc15f2c259..8c70462e7e 100755 --- a/test/functional/feature_token_split_mechanism.py +++ b/test/functional/feature_token_split_mechanism.py @@ -11,16 +11,20 @@ from decimal import Decimal import time + def truncate(str, decimal): return str if not str.find('.') + 1 else str[:str.find('.') + decimal + 1] + class TokenSplitMechanismTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.FCC_HEIGHT = 300 self.setup_clean_chain = True self.extra_args = [ - ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', '-fortcanningmuseumheight=1', '-fortcanninghillheight=1', '-fortcanningroadheight=1', f'-fortcanningcrunchheight={self.FCC_HEIGHT}', '-jellyfish_regtest=1', '-subsidytest=1']] + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', + '-fortcanningmuseumheight=1', '-fortcanninghillheight=1', '-fortcanningroadheight=1', + f'-fortcanningcrunchheight={self.FCC_HEIGHT}', '-jellyfish_regtest=1', '-subsidytest=1']] def setup_oracles(self): # Symbols @@ -143,8 +147,10 @@ def setup_accounts(self): self.nodes[0].generate(1) self.sync_blocks() - self.nodes[0].accounttoaccount(self.account1, {self.account2: ["55039700.499@DUSD", "49900@DFI", "54890@T1", "102295@T2", "49900000@T3"]}) - self.nodes[0].accounttoaccount(self.account1, {self.account3: ["110300.0010@DUSD", "100@DFI", "110@T1", "205@T2", "100000@T3"]}) + self.nodes[0].accounttoaccount(self.account1, { + self.account2: ["55039700.499@DUSD", "49900@DFI", "54890@T1", "102295@T2", "49900000@T3"]}) + self.nodes[0].accounttoaccount(self.account1, { + self.account3: ["110300.0010@DUSD", "100@DFI", "110@T1", "205@T2", "100000@T3"]}) self.nodes[0].generate(1) self.sync_blocks() @@ -208,7 +214,6 @@ def setup_pools(self): self.symbolT1_T2 = "T1-T2" self.idT1_T2 = list(self.nodes[0].gettoken(self.symbolT1_T2).keys())[0] - # Add liquidity for _ in range(10): self.nodes[0].addpoolliquidity({self.account1: ["5000@DFI", "15000@DUSD"]}, self.account1) @@ -266,17 +271,17 @@ def setup(self): # Make the split and return split height for revert if needed def split(self, tokenId, keepLocked=False): tokenSymbol = self.getTokenSymbolFromId(tokenId) - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/locks/token/{tokenId}':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/locks/token/{tokenId}': 'true'}}) self.nodes[0].generate(1) # Token split splitHeight = self.nodes[0].getblockcount() + 2 - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/oracles/splits/{str(splitHeight)}':f'{tokenId}/2'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/oracles/splits/{str(splitHeight)}': f'{tokenId}/2'}}) self.nodes[0].generate(2) tokenId = list(self.nodes[0].gettoken(tokenSymbol).keys())[0] if not keepLocked: - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/locks/token/{tokenId}':'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/locks/token/{tokenId}': 'false'}}) self.nodes[0].generate(1) return splitHeight @@ -294,7 +299,7 @@ def getTokenPools(self, tokenId): for pool in currentPools: if tokenSymbol in currentPools[pool]["symbol"] and currentPools[pool]["status"]: tokenPools[pool] = currentPools[pool] - assert(len(tokenPools) > 0) + assert (len(tokenPools) > 0) return tokenPools def check_attributes_on_split(self, tokenId, revert=False): @@ -308,19 +313,19 @@ def check_attributes_on_split(self, tokenId, revert=False): # set LP and Tokens gov vars for poolId in pools: - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/poolpairs/{poolId}/token_a_fee_pct': '0.01', - f'v0/poolpairs/{poolId}/token_b_fee_pct': '0.03'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/poolpairs/{poolId}/token_a_fee_pct': '0.01', + f'v0/poolpairs/{poolId}/token_b_fee_pct': '0.03'}}) - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{tokenId}/dex_in_fee_pct': '0.02', - f'v0/token/{tokenId}/dex_out_fee_pct': '0.005'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{tokenId}/dex_in_fee_pct': '0.02', + f'v0/token/{tokenId}/dex_out_fee_pct': '0.005'}}) self.nodes[0].generate(1) result = self.nodes[0].listgovs()[8][0]['ATTRIBUTES'] - assert(f'v0/token/{tokenId}/dex_in_fee_pct' in result) - assert(f'v0/token/{tokenId}/dex_out_fee_pct' in result) + assert (f'v0/token/{tokenId}/dex_in_fee_pct' in result) + assert (f'v0/token/{tokenId}/dex_out_fee_pct' in result) for poolId in pools: - assert(f'v0/poolpairs/{poolId}/token_a_fee_pct' in result) - assert(f'v0/poolpairs/{poolId}/token_b_fee_pct' in result) + assert (f'v0/poolpairs/{poolId}/token_a_fee_pct' in result) + assert (f'v0/poolpairs/{poolId}/token_b_fee_pct' in result) splitHeight = self.split(tokenId) - 2 self.nodes[0].generate(1) @@ -333,16 +338,16 @@ def check_attributes_on_split(self, tokenId, revert=False): result = self.nodes[0].listgovs()[8][0]['ATTRIBUTES'] for poolId in pools: - assert(f'v0/poolpairs/{poolId}/token_a_fee_pct' not in result) - assert(f'v0/poolpairs/{poolId}/token_b_fee_pct' not in result) - assert(f'v0/token/{tokenId}/dex_in_fee_pct' not in result) - assert(f'v0/token/{tokenId}/dex_out_fee_pct' not in result) + assert (f'v0/poolpairs/{poolId}/token_a_fee_pct' not in result) + assert (f'v0/poolpairs/{poolId}/token_b_fee_pct' not in result) + assert (f'v0/token/{tokenId}/dex_in_fee_pct' not in result) + assert (f'v0/token/{tokenId}/dex_out_fee_pct' not in result) for new_pool_id in new_pools: - assert(f'v0/poolpairs/{new_pool_id}/token_a_fee_pct' in result) - assert(f'v0/poolpairs/{new_pool_id}/token_b_fee_pct' in result) - assert(f'v0/token/{new_token_id}/dex_in_fee_pct' in result) - assert(f'v0/token/{new_token_id}/dex_out_fee_pct' in result) + assert (f'v0/poolpairs/{new_pool_id}/token_a_fee_pct' in result) + assert (f'v0/poolpairs/{new_pool_id}/token_b_fee_pct' in result) + assert (f'v0/token/{new_token_id}/dex_in_fee_pct' in result) + assert (f'v0/token/{new_token_id}/dex_out_fee_pct' in result) if not revert: return new_token_id @@ -350,23 +355,23 @@ def check_attributes_on_split(self, tokenId, revert=False): self.rollback_to(splitHeight) result = self.nodes[0].listgovs()[8][0]['ATTRIBUTES'] for poolId in pools: - assert(f'v0/poolpairs/{poolId}/token_a_fee_pct' in result) - assert(f'v0/poolpairs/{poolId}/token_b_fee_pct' in result) - assert(f'v0/token/{tokenId}/dex_in_fee_pct' in result) - assert(f'v0/token/{tokenId}/dex_out_fee_pct' in result) + assert (f'v0/poolpairs/{poolId}/token_a_fee_pct' in result) + assert (f'v0/poolpairs/{poolId}/token_b_fee_pct' in result) + assert (f'v0/token/{tokenId}/dex_in_fee_pct' in result) + assert (f'v0/token/{tokenId}/dex_out_fee_pct' in result) for new_pool_id in new_pools: - assert(f'v0/poolpairs/{new_pool_id}/token_a_fee_pct' not in result) - assert(f'v0/poolpairs/{new_pool_id}/token_b_fee_pct' not in result) - assert(f'v0/token/{new_token_id}/dex_in_fee_pct' not in result) - assert(f'v0/token/{new_token_id}/dex_out_fee_pct' not in result) + assert (f'v0/poolpairs/{new_pool_id}/token_a_fee_pct' not in result) + assert (f'v0/poolpairs/{new_pool_id}/token_b_fee_pct' not in result) + assert (f'v0/token/{new_token_id}/dex_in_fee_pct' not in result) + assert (f'v0/token/{new_token_id}/dex_out_fee_pct' not in result) self.rollback_to(revert_block) result = self.nodes[0].listgovs()[8][0]['ATTRIBUTES'] for new_pool_id in new_pools: - assert(f'v0/poolpairs/{new_pool_id}/token_a_fee_pct' not in result) - assert(f'v0/poolpairs/{new_pool_id}/token_b_fee_pct' not in result) - assert(f'v0/token/{new_token_id}/dex_in_fee_pct' not in result) - assert(f'v0/token/{new_token_id}/dex_out_fee_pct' not in result) + assert (f'v0/poolpairs/{new_pool_id}/token_a_fee_pct' not in result) + assert (f'v0/poolpairs/{new_pool_id}/token_b_fee_pct' not in result) + assert (f'v0/token/{new_token_id}/dex_in_fee_pct' not in result) + assert (f'v0/token/{new_token_id}/dex_out_fee_pct' not in result) return 0 def getAmountFromAccount(self, account, symbol): @@ -391,13 +396,13 @@ def check_amounts_on_split(self, poolId, tokenId, revert=False): amountLPBeforeAcc2 = self.getAmountFromAccount(self.account2, poolSymbol) amountLPBeforeAcc3 = self.getAmountFromAccount(self.account3, poolSymbol) if amountLPBeforeAcc1 != '0': - self.nodes[0].removepoolliquidity(self.account1, amountLPBeforeAcc1+"@"+poolSymbol, []) + self.nodes[0].removepoolliquidity(self.account1, amountLPBeforeAcc1 + "@" + poolSymbol, []) self.nodes[0].generate(1) if amountLPBeforeAcc2 != '0': - self.nodes[0].removepoolliquidity(self.account2, amountLPBeforeAcc2+"@"+poolSymbol, []) + self.nodes[0].removepoolliquidity(self.account2, amountLPBeforeAcc2 + "@" + poolSymbol, []) self.nodes[0].generate(1) if amountLPBeforeAcc3 != '0': - self.nodes[0].removepoolliquidity(self.account3, amountLPBeforeAcc3+"@"+poolSymbol, []) + self.nodes[0].removepoolliquidity(self.account3, amountLPBeforeAcc3 + "@" + poolSymbol, []) self.nodes[0].generate(1) amountTokenBeforeAcc1 = self.getAmountFromAccount(self.account1, tokenSymbol) @@ -415,11 +420,11 @@ def check_amounts_on_split(self, poolId, tokenId, revert=False): amountLPAfterAcc1 = self.getAmountFromAccount(self.account1, poolSymbol) amountLPAfterAcc2 = self.getAmountFromAccount(self.account2, poolSymbol) amountLPAfterAcc3 = self.getAmountFromAccount(self.account3, poolSymbol) - self.nodes[0].removepoolliquidity(self.account1, amountLPAfterAcc1+"@"+poolSymbol, []) + self.nodes[0].removepoolliquidity(self.account1, amountLPAfterAcc1 + "@" + poolSymbol, []) self.nodes[0].generate(1) - self.nodes[0].removepoolliquidity(self.account2, amountLPAfterAcc2+"@"+poolSymbol, []) + self.nodes[0].removepoolliquidity(self.account2, amountLPAfterAcc2 + "@" + poolSymbol, []) self.nodes[0].generate(1) - self.nodes[0].removepoolliquidity(self.account3, amountLPAfterAcc3+"@"+poolSymbol, []) + self.nodes[0].removepoolliquidity(self.account3, amountLPAfterAcc3 + "@" + poolSymbol, []) self.nodes[0].generate(1) amountTokenAfterAcc1 = self.getAmountFromAccount(self.account1, tokenSymbol) amountTokenB_AfterAcc1 = self.getAmountFromAccount(self.account1, tokenBSymbol) @@ -428,12 +433,18 @@ def check_amounts_on_split(self, poolId, tokenId, revert=False): amountTokenAfterAcc3 = self.getAmountFromAccount(self.account3, tokenSymbol) amountTokenB_AfterAcc3 = self.getAmountFromAccount(self.account3, tokenBSymbol) # Check difference is not grater than 0,001% rounding difference - assert((Decimal(amountTokenB_BeforeAcc1) - Decimal(amountTokenB_AfterAcc1)).copy_abs() <= (Decimal(0.00001)*Decimal(amountTokenB_BeforeAcc1))) - assert((Decimal(amountTokenB_BeforeAcc2) - Decimal(amountTokenB_AfterAcc2)).copy_abs() <= (Decimal(0.00001)*Decimal(amountTokenB_BeforeAcc2))) - assert((Decimal(amountTokenB_BeforeAcc3) - Decimal(amountTokenB_AfterAcc3)).copy_abs() <= (Decimal(0.00001)*Decimal(amountTokenB_BeforeAcc3))) - assert(((Decimal(amountTokenBeforeAcc1)*2) - Decimal(amountTokenAfterAcc1)).copy_abs() <= Decimal(0.00001)*Decimal(amountTokenBeforeAcc1)) - assert(((Decimal(amountTokenBeforeAcc2)*2) - Decimal(amountTokenAfterAcc2)).copy_abs() <= Decimal(0.00001)*Decimal(amountTokenBeforeAcc2)) - assert(((Decimal(amountTokenBeforeAcc3)*2) - Decimal(amountTokenAfterAcc3)).copy_abs() <= Decimal(0.00001)*Decimal(amountTokenBeforeAcc3)) + assert ((Decimal(amountTokenB_BeforeAcc1) - Decimal(amountTokenB_AfterAcc1)).copy_abs() <= ( + Decimal(0.00001) * Decimal(amountTokenB_BeforeAcc1))) + assert ((Decimal(amountTokenB_BeforeAcc2) - Decimal(amountTokenB_AfterAcc2)).copy_abs() <= ( + Decimal(0.00001) * Decimal(amountTokenB_BeforeAcc2))) + assert ((Decimal(amountTokenB_BeforeAcc3) - Decimal(amountTokenB_AfterAcc3)).copy_abs() <= ( + Decimal(0.00001) * Decimal(amountTokenB_BeforeAcc3))) + assert (((Decimal(amountTokenBeforeAcc1) * 2) - Decimal(amountTokenAfterAcc1)).copy_abs() <= Decimal( + 0.00001) * Decimal(amountTokenBeforeAcc1)) + assert (((Decimal(amountTokenBeforeAcc2) * 2) - Decimal(amountTokenAfterAcc2)).copy_abs() <= Decimal( + 0.00001) * Decimal(amountTokenBeforeAcc2)) + assert (((Decimal(amountTokenBeforeAcc3) * 2) - Decimal(amountTokenAfterAcc3)).copy_abs() <= Decimal( + 0.00001) * Decimal(amountTokenBeforeAcc3)) if revert: self.rollback_to(revertHeight) @@ -478,6 +489,6 @@ def run_test(self): self.idT3 = self.check_amounts_on_split(self.idT3_DUSD, self.idT3, revert=False) self.idT2 = self.check_amounts_on_split(self.idT1_T2, self.idT2, revert=False) + if __name__ == '__main__': TokenSplitMechanismTest().main() - diff --git a/test/functional/feature_token_split_usd_value.py b/test/functional/feature_token_split_usd_value.py index fcc6fcb5cb..225be9cb1c 100755 --- a/test/functional/feature_token_split_usd_value.py +++ b/test/functional/feature_token_split_usd_value.py @@ -13,11 +13,14 @@ import time import random + def truncate(str, decimal): return str if not str.find('.') + 1 else str[:str.find('.') + decimal + 1] + def almost_equal(x, y, threshold=0.0001): - return abs(x-y) < threshold + return abs(x - y) < threshold + class TokenSplitUSDValueTest(DefiTestFramework): def set_test_params(self): @@ -25,7 +28,9 @@ def set_test_params(self): self.FCC_HEIGHT = 300 self.setup_clean_chain = True self.extra_args = [ - ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', '-fortcanningmuseumheight=1', '-fortcanninghillheight=1', '-fortcanningroadheight=1', f'-fortcanningcrunchheight={self.FCC_HEIGHT}', '-jellyfish_regtest=1', '-subsidytest=1']] + ['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', + '-fortcanningmuseumheight=1', '-fortcanninghillheight=1', '-fortcanningroadheight=1', + f'-fortcanningcrunchheight={self.FCC_HEIGHT}', '-jellyfish_regtest=1', '-subsidytest=1']] def setup_oracles(self): # Symbols @@ -98,14 +103,15 @@ def generate_and_fill_accounts(self, nAccounts=20): totalT1 = 10000000 self.accounts.sort() self.nodes[0].utxostoaccount({self.account1: "10000000@0"}) - self.nodes[0].minttokens(str(totalDUSD)+"@DUSD") - self.nodes[0].minttokens(str(totalT1)+"@T1") + self.nodes[0].minttokens(str(totalDUSD) + "@DUSD") + self.nodes[0].minttokens(str(totalT1) + "@T1") self.nodes[0].generate(1) - perAccountDUSD = totalDUSD/nAccounts - perAccountT1 = totalT1/nAccounts + perAccountDUSD = totalDUSD / nAccounts + perAccountT1 = totalT1 / nAccounts for account in self.accounts: - self.nodes[0].accounttoaccount(self.account1, {account: [str(perAccountDUSD)+"@DUSD", str(perAccountT1)+"@T1"]}) + self.nodes[0].accounttoaccount(self.account1, + {account: [str(perAccountDUSD) + "@DUSD", str(perAccountT1) + "@T1"]}) self.nodes[0].generate(1) def setup_accounts(self): @@ -118,13 +124,14 @@ def add_total_account_to_liquidity_pool(self): totalAmount = Decimal(self.get_amount_from_account(account, self.symbolDUSD)) while size >= 10: while Decimal(totalAmount) >= size: - tmpAmount = Decimal(random.randint(int(size/10), int(size-1))) - self.nodes[0].addpoolliquidity({account: [str(tmpAmount)+"@T1", str(tmpAmount)+"@DUSD"]}, account) + tmpAmount = Decimal(random.randint(int(size / 10), int(size - 1))) + self.nodes[0].addpoolliquidity({account: [str(tmpAmount) + "@T1", str(tmpAmount) + "@DUSD"]}, + account) self.nodes[0].generate(1) totalAmount -= tmpAmount size /= 10 finalAmount = Decimal(self.get_amount_from_account(account, self.symbolDUSD)) - self.nodes[0].addpoolliquidity({account: [str(finalAmount)+"@T1", str(finalAmount)+"@DUSD"]}, account) + self.nodes[0].addpoolliquidity({account: [str(finalAmount) + "@T1", str(finalAmount) + "@DUSD"]}, account) self.nodes[0].generate(1) totalAmount -= finalAmount @@ -165,7 +172,7 @@ def oracle_split(self): self.nodes[0].generate(10) def split(self, tokenId, keepLocked=False, oracleSplit=False, multiplier=2): - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/locks/token/{tokenId}':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/locks/token/{tokenId}': 'true'}}) self.nodes[0].generate(1) if oracleSplit: @@ -173,23 +180,23 @@ def split(self, tokenId, keepLocked=False, oracleSplit=False, multiplier=2): # Token split splitHeight = self.nodes[0].getblockcount() + 2 - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/oracles/splits/{str(splitHeight)}':f'{tokenId}/{multiplier}'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/oracles/splits/{str(splitHeight)}': f'{tokenId}/{multiplier}'}}) self.nodes[0].generate(2) self.idT1old = tokenId self.idT1 = list(self.nodes[0].gettoken(self.symbolT1).keys())[0] if not keepLocked: - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/locks/token/{self.idT1}':'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/locks/token/{self.idT1}': 'false'}}) self.nodes[0].generate(1) def remove_from_pool(self, account): amountLP = self.get_amount_from_account(account, "T1-DUSD") - self.nodes[0].removepoolliquidity(account, amountLP+"@T1-DUSD", []) + self.nodes[0].removepoolliquidity(account, amountLP + "@T1-DUSD", []) self.nodes[0].generate(1) def accounts_usd_values(self): - values =[] + values = [] revertHeight = self.nodes[0].getblockcount() activePriceT1 = self.nodes[0].getfixedintervalprice(f"{self.symbolT1}/USD")["activePrice"] activePriceDUSD = self.nodes[0].getfixedintervalprice(f"{self.symbolDUSD}/USD")["activePrice"] @@ -198,7 +205,7 @@ def accounts_usd_values(self): self.remove_from_pool(account) amounts["account"] = account amounts["DUSD"] = Decimal(self.get_amount_from_account(account, "DUSD")) * Decimal(activePriceDUSD) - amounts["T1"] = Decimal(self.get_amount_from_account(account, "T1")) *Decimal(activePriceT1) + amounts["T1"] = Decimal(self.get_amount_from_account(account, "T1")) * Decimal(activePriceT1) values.append(amounts) self.rollback_to(revertHeight) return values @@ -229,7 +236,7 @@ def get_token_pools(self, tokenId): for pool in currentPools: if tokenSymbol in currentPools[pool]["symbol"] and currentPools[pool]["status"]: tokenPools[pool] = currentPools[pool] - assert(len(tokenPools) > 0) + assert (len(tokenPools) > 0) return tokenPools def get_amount_from_account(self, account, symbol): @@ -250,7 +257,7 @@ def compare_usd_account_value_on_split(self, revert=False): self.compare_value_list(value_accounts_pre_split, value_accounts_post_split) if revert: self.rollback_to(revertHeight) - self.idT1=self.idT1old + self.idT1 = self.idT1old def setup_vaults(self, collateralSplit=False): self.nodes[0].createloanscheme(200, 0.01, 'LOAN_0') @@ -259,24 +266,24 @@ def setup_vaults(self, collateralSplit=False): vaultCount = 0 for account in self.accounts: self.remove_from_pool(account) - vaultId= self.nodes[0].createvault(account) + vaultId = self.nodes[0].createvault(account) self.nodes[0].generate(1) vaultCount += 1 self.vaults.append(vaultId) amountT1 = self.get_amount_from_account(account, "T1") - amountT1 = Decimal(amountT1)/Decimal(4) + amountT1 = Decimal(amountT1) / Decimal(4) if collateralSplit: - amountT1 = Decimal(amountT1)/Decimal(2) + amountT1 = Decimal(amountT1) / Decimal(2) amountDUSD = self.get_amount_from_account(account, "DUSD") - amountDUSD = Decimal(amountDUSD)/Decimal(2) + amountDUSD = Decimal(amountDUSD) / Decimal(2) if collateralSplit: - self.nodes[0].deposittovault(vaultId, account, str(amountT1)+"@T1") - self.nodes[0].deposittovault(vaultId, account, str(amountDUSD)+"@DUSD") + self.nodes[0].deposittovault(vaultId, account, str(amountT1) + "@T1") + self.nodes[0].deposittovault(vaultId, account, str(amountDUSD) + "@DUSD") self.nodes[0].generate(1) - amountT1Loan = Decimal(amountT1)/Decimal(2) + amountT1Loan = Decimal(amountT1) / Decimal(2) self.nodes[0].takeloan({ - 'vaultId': vaultId, - 'amounts': str(amountT1Loan)+"@T1"}) + 'vaultId': vaultId, + 'amounts': str(amountT1Loan) + "@T1"}) self.nodes[0].generate(1) def get_vaults_usd_values(self): @@ -293,11 +300,11 @@ def compare_usd_vaults_values_on_split(self, revert=False): self.split(self.idT1, oracleSplit=True, multiplier=20) self.nodes[0].generate(40) vault_values_post_split = self.get_vaults_usd_values() - self.compare_vaults_list(vault_values_pre_split,vault_values_post_split) + self.compare_vaults_list(vault_values_pre_split, vault_values_post_split) if revert: self.rollback_to(revertHeight) - self.idT1=self.idT1old + self.idT1 = self.idT1old def test_values_non_zero_with_token_locked(self): self.setup_vaults() @@ -313,7 +320,7 @@ def test_values_non_zero_with_token_locked(self): def test_values_after_token_unlock(self): # Unlock token - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/locks/token/{self.idT1}':'false'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/locks/token/{self.idT1}': 'false'}}) self.nodes[0].generate(1) vaults_values = self.get_vaults_usd_values() for vault in vaults_values: @@ -326,11 +333,12 @@ def test_values_after_token_unlock(self): def run_test(self): self.setup() - assert_equal(1,1) # Make linter happy for now + assert_equal(1, 1) # Make linter happy for now self.compare_usd_account_value_on_split(revert=True) self.compare_usd_vaults_values_on_split(revert=True) self.test_values_non_zero_with_token_locked() self.test_values_after_token_unlock() + if __name__ == '__main__': TokenSplitUSDValueTest().main() diff --git a/test/functional/feature_tokens_basic.py b/test/functional/feature_tokens_basic.py index db2640971a..8e196aa376 100755 --- a/test/functional/feature_tokens_basic.py +++ b/test/functional/feature_tokens_basic.py @@ -13,7 +13,8 @@ from test_framework.authproxy import JSONRPCException from test_framework.util import assert_equal -class TokensBasicTest (DefiTestFramework): + +class TokensBasicTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 3 # node0: main @@ -26,7 +27,7 @@ def set_test_params(self): ['-txnotokens=0', '-amkheight=50']] def run_test(self): - assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI + assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI self.nodes[0].generate(100) self.sync_blocks() @@ -35,7 +36,7 @@ def run_test(self): self.stop_node(2) # CREATION: - #======================== + # ======================== collateral0 = self.nodes[0].getnewaddress("", "legacy") # Fail to create: Insufficient funds (not matured coins) @@ -47,7 +48,7 @@ def run_test(self): }, []) except JSONRPCException as e: errorString = e.error['message'] - assert("Insufficient funds" in errorString) + assert ("Insufficient funds" in errorString) self.nodes[0].generate(1) @@ -60,9 +61,9 @@ def run_test(self): }, []) except JSONRPCException as e: errorString = e.error['message'] - assert("token symbol should not contain '#'" in errorString) + assert ("token symbol should not contain '#'" in errorString) - print ("Create token 'GOLD' (128)...") + print("Create token 'GOLD' (128)...") createTokenTx = self.nodes[0].createtoken({ "symbol": "GOLD", "name": "shiny gold", @@ -70,7 +71,7 @@ def run_test(self): }, []) # Create and sign (only) collateral spending tx - spendTx = self.nodes[0].createrawtransaction([{'txid':createTokenTx, 'vout':1}],[{collateral0:9.999}]) + spendTx = self.nodes[0].createrawtransaction([{'txid': createTokenTx, 'vout': 1}], [{collateral0: 9.999}]) signedTx = self.nodes[0].signrawtransactionwithwallet(spendTx) assert_equal(signedTx['complete'], True) @@ -79,7 +80,7 @@ def run_test(self): self.nodes[0].sendrawtransaction(signedTx['hex']) except JSONRPCException as e: errorString = e.error['message'] - assert("collateral-locked-in-mempool," in errorString) + assert ("collateral-locked-in-mempool," in errorString) self.nodes[0].generate(1) self.sync_blocks([self.nodes[0], self.nodes[1]]) @@ -110,7 +111,7 @@ def run_test(self): self.nodes[0].gettoken("GOLD") except JSONRPCException as e: errorString = e.error['message'] - assert("Token not found" in errorString) + assert ("Token not found" in errorString) # Stop node #1 for future revert self.stop_node(1) @@ -120,7 +121,7 @@ def run_test(self): self.nodes[0].sendrawtransaction(signedTx['hex']) except JSONRPCException as e: errorString = e.error['message'] - assert("collateral-locked," in errorString) + assert ("collateral-locked," in errorString) # Create new GOLD token, mintable and tradable by default self.nodes[0].createtoken({ @@ -143,7 +144,8 @@ def run_test(self): assert_equal(sorted(self.nodes[0].getrawmempool()), sorted([])) assert_equal(self.nodes[0].listtokens()['128']['destructionHeight'], -1) - assert_equal(self.nodes[0].listtokens()['128']['destructionTx'], '0000000000000000000000000000000000000000000000000000000000000000') + assert_equal(self.nodes[0].listtokens()['128']['destructionTx'], + '0000000000000000000000000000000000000000000000000000000000000000') # Create new neither mintable nor tradable token self.nodes[0].createtoken({ @@ -161,5 +163,6 @@ def run_test(self): assert_equal(t130['130']['mintable'], False) assert_equal(t130['130']['tradeable'], False) + if __name__ == '__main__': - TokensBasicTest ().main () + TokensBasicTest().main() diff --git a/test/functional/feature_tokens_dat.py b/test/functional/feature_tokens_dat.py index d3cda0c573..e41405c780 100755 --- a/test/functional/feature_tokens_dat.py +++ b/test/functional/feature_tokens_dat.py @@ -14,7 +14,8 @@ from test_framework.util import assert_equal, \ connect_nodes_bi -class TokensBasicTest (DefiTestFramework): + +class TokensBasicTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 4 # node0: main (Foundation) @@ -27,9 +28,8 @@ def set_test_params(self): ['-txnotokens=0', '-amkheight=50'], ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50']] - def run_test(self): - assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI + assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI self.nodes[0].generate(100) self.sync_blocks() @@ -38,7 +38,7 @@ def run_test(self): self.stop_node(3) # CREATION: - #======================== + # ======================== collateral0 = self.nodes[0].getnewaddress("", "legacy") self.nodes[0].generate(1) @@ -99,7 +99,7 @@ def run_test(self): self.sync_blocks([self.nodes[0], self.nodes[1], self.nodes[2]]) - self.stop_node(1) # for future test + self.stop_node(1) # for future test connect_nodes_bi(self.nodes, 0, 2) # 4 Trying to make it DAT not from Foundation @@ -107,14 +107,14 @@ def run_test(self): self.nodes[2].updatetoken("GOLD#128", {"isDAT": True}, []) except JSONRPCException as e: errorString = e.error['message'] - assert("tx not from foundation member" in errorString) + assert ("tx not from foundation member" in errorString) # 4.1 Trying to set smth else try: self.nodes[2].updatetoken("GOLD#128", {"symbol": "G"}) except JSONRPCException as e: errorString = e.error['message'] - assert("before Bayfront fork" in errorString) + assert ("before Bayfront fork" in errorString) # 5 Making token isDAT from Foundation self.nodes[0].updatetoken("GOLD#128", {"isDAT": True}, []) @@ -131,18 +131,19 @@ def run_test(self): self.sync_blocks([self.nodes[0], self.nodes[2]]) tokens = self.nodes[2].listtokens() assert_equal(len(tokens), 3) - assert_equal(tokens['128']["isDAT"], False) # not synced cause new tx type (from node 0) + assert_equal(tokens['128']["isDAT"], False) # not synced cause new tx type (from node 0) # 6.1 Restart with proper height and retry self.stop_node(2) - self.start_node(2, ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-reindex-chainstate']) # warning! simple '-reindex' not works! + self.start_node(2, ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', + '-reindex-chainstate']) # warning! simple '-reindex' not works! # it looks like node can serve rpc in async while reindexing... wait: self.sync_blocks([self.nodes[0], self.nodes[2]]) tokens = self.nodes[2].listtokens() assert_equal(len(tokens), 3) - assert_equal(tokens['128']["isDAT"], True) # synced now + assert_equal(tokens['128']["isDAT"], True) # synced now - connect_nodes_bi(self.nodes, 0, 2) # for final sync at "REVERT" + connect_nodes_bi(self.nodes, 0, 2) # for final sync at "REVERT" # 7 Removing DAT self.nodes[0].updatetoken("GOLD", {"isDAT": False}, []) @@ -158,16 +159,16 @@ def run_test(self): assert_equal(self.nodes[0].gettoken('128')['128']["isDAT"], False) assert_equal(self.nodes[1].gettoken('128')['128']["isDAT"], False) - self.nodes[1].importprivkey(self.nodes[0].get_genesis_keys().ownerPrivKey) # there is no need to import the key, cause node#1 is founder itself... but it has no utxos for auth + self.nodes[1].importprivkey(self.nodes[ + 0].get_genesis_keys().ownerPrivKey) # there is no need to import the key, cause node#1 is founder itself... but it has no utxos for auth self.nodes[1].updatetoken('128', {"isDAT": True}) self.nodes[1].generate(1) self.sync_blocks([self.nodes[0], self.nodes[1]]) - assert_equal(self.nodes[0].gettoken('128')['128']["isDAT"], False) # tx not applyed cause "old" + assert_equal(self.nodes[0].gettoken('128')['128']["isDAT"], False) # tx not applyed cause "old" assert_equal(self.nodes[1].gettoken('128')['128']["isDAT"], True) - # 8. changing token's symbol: - self.nodes[0].updatetoken("GOLD#128", {"symbol":"gold"}) + self.nodes[0].updatetoken("GOLD#128", {"symbol": "gold"}) self.nodes[0].generate(1) token = self.nodes[0].gettoken('128') assert_equal(token['128']["symbol"], "gold") @@ -176,16 +177,16 @@ def run_test(self): assert_equal(self.nodes[0].gettoken('gold#128'), token) # changing token's symbol AND DAT at once: - self.nodes[0].updatetoken("128", {"symbol":"goldy", "isDAT":True}) + self.nodes[0].updatetoken("128", {"symbol": "goldy", "isDAT": True}) self.nodes[0].generate(1) token = self.nodes[0].gettoken('128') assert_equal(token['128']["symbol"], "goldy") assert_equal(token['128']["symbolKey"], "goldy") assert_equal(token['128']["isDAT"], True) - assert_equal(self.nodes[0].gettoken('goldy'), token) # can do it w/o '#'' cause it should be DAT + assert_equal(self.nodes[0].gettoken('goldy'), token) # can do it w/o '#'' cause it should be DAT # changing other properties: - self.nodes[0].updatetoken("128", {"name":"new name", "tradeable": False, "mintable": False, "finalize": True}) + self.nodes[0].updatetoken("128", {"name": "new name", "tradeable": False, "mintable": False, "finalize": True}) self.nodes[0].generate(1) token = self.nodes[0].gettoken('128') assert_equal(token['128']["name"], "new name") @@ -198,14 +199,14 @@ def run_test(self): self.nodes[0].updatetoken("128", {"tradable": True}) except JSONRPCException as e: errorString = e.error['message'] - assert("can't alter 'Finalized' tokens" in errorString) + assert ("can't alter 'Finalized' tokens" in errorString) # Fail get token try: self.nodes[0].gettoken("GOLD") except JSONRPCException as e: errorString = e.error['message'] - assert("Token not found" in errorString) + assert ("Token not found" in errorString) self.nodes[0].generate(1) @@ -234,14 +235,14 @@ def run_test(self): }, []) except JSONRPCException as e: errorString = e.error['message'] - assert("already exists" in errorString) + assert ("already exists" in errorString) # 10 Fail to update self.nodes[0].createtoken({ "symbol": "TEST", "name": "TEST token copy", "isDAT": False, - "collateralAddress": self.nodes[0].get_genesis_keys().ownerAuthAddress # !from founders!! + "collateralAddress": self.nodes[0].get_genesis_keys().ownerAuthAddress # !from founders!! }, []) self.nodes[0].generate(1) @@ -256,12 +257,11 @@ def run_test(self): self.nodes[0].updatetoken("TEST#129", {"isDAT": True}) except JSONRPCException as e: errorString = e.error['message'] - assert("already exists" in errorString) - + assert ("already exists" in errorString) # REVERTING: - #======================== - print ("Reverting...") + # ======================== + print("Reverting...") # Reverting creation! self.start_node(3) self.nodes[3].generate(30) @@ -270,5 +270,6 @@ def run_test(self): self.sync_blocks() assert_equal(len(self.nodes[0].listtokens()), 1) + if __name__ == '__main__': - TokensBasicTest ().main () + TokensBasicTest().main() diff --git a/test/functional/feature_tokens_minting.py b/test/functional/feature_tokens_minting.py index 1f819b968a..bdb0b85e45 100755 --- a/test/functional/feature_tokens_minting.py +++ b/test/functional/feature_tokens_minting.py @@ -13,22 +13,23 @@ from test_framework.authproxy import JSONRPCException from test_framework.util import assert_equal -class TokensMintingTest (DefiTestFramework): + +class TokensMintingTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 self.setup_clean_chain = True self.extra_args = [['-txnotokens=0', '-amkheight=50'], ['-txnotokens=0', '-amkheight=50']] def run_test(self): - assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI + assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI self.nodes[0].generate(100) self.sync_blocks() - self.nodes[0].generate(2) # for 2 matured utxos + self.nodes[0].generate(2) # for 2 matured utxos # CREATION: - #======================== + # ======================== collateralGold = self.nodes[0].getnewaddress("", "legacy") collateralSilver = self.nodes[0].getnewaddress("", "legacy") collateralCupper = self.nodes[0].getnewaddress("", "legacy") @@ -65,7 +66,8 @@ def run_test(self): assert_equal(self.nodes[0].isappliedcustomtx(txid2, txid2_blockHeight), True) assert_equal(self.nodes[0].isappliedcustomtx(txid3, txid3_blockHeight), True) # Not apllied tx - assert_equal(self.nodes[0].isappliedcustomtx("b2bb09ffe9f9b292f13d23bafa1225ef26d0b9906da7af194c5738b63839b235", txid2_blockHeight), False) + assert_equal(self.nodes[0].isappliedcustomtx("b2bb09ffe9f9b292f13d23bafa1225ef26d0b9906da7af194c5738b63839b235", + txid2_blockHeight), False) list_tokens = self.nodes[0].listtokens() for idx, token in list_tokens.items(): @@ -83,12 +85,12 @@ def run_test(self): self.sync_blocks() # MINT: - #======================== + # ======================== # Funding auth addresses - self.nodes[0].sendmany("", { collateralGold : 1, collateralSilver : 1, collateralCupper : 1 }) + self.nodes[0].sendmany("", {collateralGold: 1, collateralSilver: 1, collateralCupper: 1}) self.nodes[0].generate(1) - self.nodes[0].sendmany("", { collateralGold : 1, collateralSilver : 1, collateralCupper : 1 }) + self.nodes[0].sendmany("", {collateralGold: 1, collateralSilver: 1, collateralCupper: 1}) self.nodes[0].generate(1) # print(self.nodes[0].listunspent()) @@ -112,13 +114,18 @@ def run_test(self): assert_equal(self.nodes[0].gettoken(symbolSilver)[idSilver]['collateralAddress'], collateralSilver) try: - self.nodes[0].accounttoutxos(collateralGold, { self.nodes[0].getnewaddress("", "legacy"): "100@" + symbolGold, alienMintAddr: "200@" + symbolGold}, []) - self.nodes[0].accounttoutxos(collateralSilver, { self.nodes[0].getnewaddress("", "legacy"): "1000@" + symbolSilver, alienMintAddr: "2000@" + symbolSilver}, []) + self.nodes[0].accounttoutxos(collateralGold, + {self.nodes[0].getnewaddress("", "legacy"): "100@" + symbolGold, + alienMintAddr: "200@" + symbolGold}, []) + self.nodes[0].accounttoutxos(collateralSilver, + {self.nodes[0].getnewaddress("", "legacy"): "1000@" + symbolSilver, + alienMintAddr: "2000@" + symbolSilver}, []) self.nodes[0].generate(1) self.sync_blocks() except JSONRPCException as e: errorString = e.error['message'] - assert("only available for DFI transactions" in errorString) + assert ("only available for DFI transactions" in errorString) + if __name__ == '__main__': - TokensMintingTest ().main () + TokensMintingTest().main() diff --git a/test/functional/feature_tokens_multisig.py b/test/functional/feature_tokens_multisig.py index a26d305260..47cdddd2bf 100755 --- a/test/functional/feature_tokens_multisig.py +++ b/test/functional/feature_tokens_multisig.py @@ -9,6 +9,7 @@ from test_framework.util import assert_equal, assert_raises_rpc_error + class TokensMultisigOwnerTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 @@ -16,7 +17,7 @@ def set_test_params(self): self.extra_args = [['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50']] def run_test(self): - assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI + assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI self.nodes[0].generate(101) @@ -74,10 +75,10 @@ def run_test(self): self.nodes[0].generate(1) # Payloads to change name. - creationTxReversed = "".join(reversed([createTokenTx[i:i+2] for i in range(0, len(createTokenTx), 2)])) - name_change_1 = "446654786e" + creationTxReversed + "04474f4c44034f4e4508000000000000000003" # name ONE - name_change_2 = "446654786e" + creationTxReversed + "04474f4c440354574f08000000000000000003" # name TWO - name_change_3 = "446654786e" + creationTxReversed + "04474f4c4405544852454508000000000000000003" # name THREE + creationTxReversed = "".join(reversed([createTokenTx[i:i + 2] for i in range(0, len(createTokenTx), 2)])) + name_change_1 = "446654786e" + creationTxReversed + "04474f4c44034f4e4508000000000000000003" # name ONE + name_change_2 = "446654786e" + creationTxReversed + "04474f4c440354574f08000000000000000003" # name TWO + name_change_3 = "446654786e" + creationTxReversed + "04474f4c4405544852454508000000000000000003" # name THREE # Make sure member of multisig cannot change token without using multisig txid_owner_1 = self.nodes[0].sendtoaddress(owner_1, 1) @@ -93,22 +94,34 @@ def run_test(self): self.nodes[0].generate(1) # Create, sign, check and send - rawtx_1 = self.nodes[0].createrawtransaction([{"txid":txid_owner_1,"vout":vout_owner_1}], [{"data":name_change_1},{owner_1:0.9999}]) - signed_rawtx_1 = self.nodes[0].signrawtransactionwithkey(rawtx_1, [owner_1_privkey], [{"txid":txid_owner_1,"vout":vout_owner_1,"scriptPubKey":owner_1_scriptpubkey}]) + rawtx_1 = self.nodes[0].createrawtransaction([{"txid": txid_owner_1, "vout": vout_owner_1}], + [{"data": name_change_1}, {owner_1: 0.9999}]) + signed_rawtx_1 = self.nodes[0].signrawtransactionwithkey(rawtx_1, [owner_1_privkey], [ + {"txid": txid_owner_1, "vout": vout_owner_1, "scriptPubKey": owner_1_scriptpubkey}]) assert_equal(signed_rawtx_1['complete'], True) # Send should fail as transaction is invalid - assert_raises_rpc_error(-26, "tx must have at least one input from the owner", self.nodes[0].sendrawtransaction, signed_rawtx_1['hex']) + assert_raises_rpc_error(-26, "tx must have at least one input from the owner", self.nodes[0].sendrawtransaction, + signed_rawtx_1['hex']) # Test that multisig TXs can change names - rawtx_1 = self.nodes[0].createrawtransaction([{"txid":txid_1,"vout":vout_1}], [{"data":name_change_1},{owner_1:0.9999}]) - rawtx_2 = self.nodes[0].createrawtransaction([{"txid":txid_2,"vout":vout_2}], [{"data":name_change_2},{owner_2:0.9999}]) - rawtx_3 = self.nodes[0].createrawtransaction([{"txid":txid_3,"vout":vout_3}], [{"data":name_change_3},{owner_3:0.9999}]) + rawtx_1 = self.nodes[0].createrawtransaction([{"txid": txid_1, "vout": vout_1}], + [{"data": name_change_1}, {owner_1: 0.9999}]) + rawtx_2 = self.nodes[0].createrawtransaction([{"txid": txid_2, "vout": vout_2}], + [{"data": name_change_2}, {owner_2: 0.9999}]) + rawtx_3 = self.nodes[0].createrawtransaction([{"txid": txid_3, "vout": vout_3}], + [{"data": name_change_3}, {owner_3: 0.9999}]) # Sign TXs - signed_rawtx_1 = self.nodes[0].signrawtransactionwithkey(rawtx_1, [owner_1_privkey], [{"txid":txid_1,"vout":vout_1,"scriptPubKey":multisig_scriptpubkey,"redeemScript":multisig['redeemScript']}]) - signed_rawtx_2 = self.nodes[0].signrawtransactionwithkey(rawtx_2, [owner_2_privkey], [{"txid":txid_2,"vout":vout_2,"scriptPubKey":multisig_scriptpubkey,"redeemScript":multisig['redeemScript']}]) - signed_rawtx_3 = self.nodes[0].signrawtransactionwithkey(rawtx_3, [owner_3_privkey], [{"txid":txid_3,"vout":vout_3,"scriptPubKey":multisig_scriptpubkey,"redeemScript":multisig['redeemScript']}]) + signed_rawtx_1 = self.nodes[0].signrawtransactionwithkey(rawtx_1, [owner_1_privkey], [ + {"txid": txid_1, "vout": vout_1, "scriptPubKey": multisig_scriptpubkey, + "redeemScript": multisig['redeemScript']}]) + signed_rawtx_2 = self.nodes[0].signrawtransactionwithkey(rawtx_2, [owner_2_privkey], [ + {"txid": txid_2, "vout": vout_2, "scriptPubKey": multisig_scriptpubkey, + "redeemScript": multisig['redeemScript']}]) + signed_rawtx_3 = self.nodes[0].signrawtransactionwithkey(rawtx_3, [owner_3_privkey], [ + {"txid": txid_3, "vout": vout_3, "scriptPubKey": multisig_scriptpubkey, + "redeemScript": multisig['redeemScript']}]) # Check TXs marked as complete assert_equal(signed_rawtx_1['complete'], True) @@ -170,21 +183,27 @@ def run_test(self): self.nodes[0].generate(1) # Payload to change name. - creationTxReversed = "".join(reversed([createTokenTx[i:i+2] for i in range(0, len(createTokenTx), 2)])) - name_change = "446654786e" + creationTxReversed + "0653494c564552034f4e4508000000000000000003" # name ONE + creationTxReversed = "".join(reversed([createTokenTx[i:i + 2] for i in range(0, len(createTokenTx), 2)])) + name_change = "446654786e" + creationTxReversed + "0653494c564552034f4e4508000000000000000003" # name ONE # Test that single signature on 2-of-3 multisig fails to update token - rawtx_1 = self.nodes[0].createrawtransaction([{"txid":txid_1,"vout":vout_4}], [{"data":name_change},{owner_1:0.9999}]) - signed_rawtx_1 = self.nodes[0].signrawtransactionwithkey(rawtx_1, [owner_1_privkey], [{"txid":txid_1,"vout":vout_4,"scriptPubKey":multisig_scriptpubkey,"redeemScript":multisig['redeemScript']}]) + rawtx_1 = self.nodes[0].createrawtransaction([{"txid": txid_1, "vout": vout_4}], + [{"data": name_change}, {owner_1: 0.9999}]) + signed_rawtx_1 = self.nodes[0].signrawtransactionwithkey(rawtx_1, [owner_1_privkey], [ + {"txid": txid_1, "vout": vout_4, "scriptPubKey": multisig_scriptpubkey, + "redeemScript": multisig['redeemScript']}]) # Check TX marked as not complete assert_equal(signed_rawtx_1['complete'], False) # Try to send partially signed multisig, expect failure - assert_raises_rpc_error(-26, "Signature must be zero for failed CHECK(MULTI)SIG operation", self.nodes[0].sendrawtransaction, signed_rawtx_1['hex']) + assert_raises_rpc_error(-26, "Signature must be zero for failed CHECK(MULTI)SIG operation", + self.nodes[0].sendrawtransaction, signed_rawtx_1['hex']) # Add second signate and try again - signed_rawtx_1 = self.nodes[0].signrawtransactionwithkey(signed_rawtx_1['hex'], [owner_2_privkey], [{"txid":txid_1,"vout":vout_4,"scriptPubKey":multisig_scriptpubkey,"redeemScript":multisig['redeemScript']}]) + signed_rawtx_1 = self.nodes[0].signrawtransactionwithkey(signed_rawtx_1['hex'], [owner_2_privkey], [ + {"txid": txid_1, "vout": vout_4, "scriptPubKey": multisig_scriptpubkey, + "redeemScript": multisig['redeemScript']}]) # Check TX now marked as complete assert_equal(signed_rawtx_1['complete'], True) @@ -197,5 +216,6 @@ def run_test(self): t129 = self.nodes[0].gettoken(129) assert_equal(t129['129']['name'], "ONE") + if __name__ == '__main__': TokensMultisigOwnerTest().main() diff --git a/test/functional/feature_uacomment.py b/test/functional/feature_uacomment.py index 9452110c5e..60b7d239b7 100755 --- a/test/functional/feature_uacomment.py +++ b/test/functional/feature_uacomment.py @@ -27,13 +27,14 @@ def run_test(self): self.log.info("test -uacomment max length") self.stop_node(0) - expected = "Error: Total length of network version string \([0-9]+\) exceeds maximum length \(256\). Reduce the number or size of uacomments." + expected = r"Error: Total length of network version string \([0-9]+\) exceeds maximum length \(256\). Reduce the number or size of uacomments." self.nodes[0].assert_start_raises_init_error(["-uacomment=" + 'a' * 256], expected, match=ErrorMatch.FULL_REGEX) self.log.info("test -uacomment unsafe characters") for unsafe_char in ['/', ':', '(', ')']: - expected = "Error: User Agent comment \(" + re.escape(unsafe_char) + "\) contains unsafe characters." - self.nodes[0].assert_start_raises_init_error(["-uacomment=" + unsafe_char], expected, match=ErrorMatch.FULL_REGEX) + expected = r"Error: User Agent comment \(" + re.escape(unsafe_char) + r"\) contains unsafe characters." + self.nodes[0].assert_start_raises_init_error(["-uacomment=" + unsafe_char], expected, + match=ErrorMatch.FULL_REGEX) if __name__ == '__main__': diff --git a/test/functional/feature_update_mn.py b/test/functional/feature_update_mn.py index 0c70fa6358..5e4597f70c 100755 --- a/test/functional/feature_update_mn.py +++ b/test/functional/feature_update_mn.py @@ -15,13 +15,18 @@ assert_raises_rpc_error, ) -class MasternodesRpcBasicTest (DefiTestFramework): + +class MasternodesRpcBasicTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 3 self.setup_clean_chain = True - self.extra_args = [['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=50', '-dakotaheight=136', '-eunosheight=140', '-eunospayaheight=140', '-fortcanningheight=145'], - ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=50', '-dakotaheight=136', '-eunosheight=140', '-eunospayaheight=140', '-fortcanningheight=145'], - ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=50', '-dakotaheight=136', '-eunosheight=140', '-eunospayaheight=140', '-fortcanningheight=145']] + self.extra_args = [ + ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=50', '-dakotaheight=136', + '-eunosheight=140', '-eunospayaheight=140', '-fortcanningheight=145'], + ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=50', '-dakotaheight=136', + '-eunosheight=140', '-eunospayaheight=140', '-fortcanningheight=145'], + ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=50', '-dakotaheight=136', + '-eunosheight=140', '-eunospayaheight=140', '-fortcanningheight=145']] def run_test(self): assert_equal(len(self.nodes[0].listmasternodes()), 8) @@ -29,21 +34,22 @@ def run_test(self): self.sync_blocks() # CREATION: - #======================== + # ======================== collateral0 = self.nodes[0].getnewaddress("", "legacy") # Create node0 self.nodes[0].generate(1) collateral1 = self.nodes[1].getnewaddress("", "legacy") - assert_raises_rpc_error(-8, "Address ({}) is not owned by the wallet".format(collateral1), self.nodes[0].createmasternode, collateral1) + assert_raises_rpc_error(-8, "Address ({}) is not owned by the wallet".format(collateral1), + self.nodes[0].createmasternode, collateral1) idnode0 = self.nodes[0].createmasternode( collateral0 ) # Create and sign (only) collateral spending tx - spendTx = self.nodes[0].createrawtransaction([{'txid':idnode0, 'vout':1}],[{collateral0:9.999}]) + spendTx = self.nodes[0].createrawtransaction([{'txid': idnode0, 'vout': 1}], [{collateral0: 9.999}]) signedTx = self.nodes[0].signrawtransactionwithwallet(spendTx) assert_equal(signedTx['complete'], True) @@ -58,7 +64,7 @@ def run_test(self): assert_equal(self.nodes[1].listmasternodes()[idnode0]["operatorAuthAddress"], collateral0) # RESIGNING: - #======================== + # ======================== # Funding auth address and successful resign self.nodes[0].sendtoaddress(collateral0, 1) @@ -79,5 +85,6 @@ def run_test(self): # Don't mine here, check mempool after reorg! # self.nodes[0].generate(1) + if __name__ == '__main__': - MasternodesRpcBasicTest ().main () + MasternodesRpcBasicTest().main() diff --git a/test/functional/feature_vault_pct_check_factor.py b/test/functional/feature_vault_pct_check_factor.py index 895b8e349d..22294a5bb9 100755 --- a/test/functional/feature_vault_pct_check_factor.py +++ b/test/functional/feature_vault_pct_check_factor.py @@ -11,19 +11,23 @@ import time from decimal import Decimal + def get_decimal_amount(amount): account_tmp = amount.split('@')[0] return Decimal(account_tmp) + def token_index_in_account(accounts, symbol): for id in range(len(accounts)): if symbol in accounts[id]: return id return -1 + ERR_STRING_MIN_COLLATERAL_DFI_PCT = "At least 50% of the minimum required collateral must be in DFI" ERR_STRING_MIN_COLLATERAL_DFI_DUSD_PCT = "At least 50% of the minimum required collateral must be in DFI or DUSD" + class DUSDFactorPctTests(DefiTestFramework): def set_test_params(self): @@ -32,19 +36,19 @@ def set_test_params(self): self.grandcentralheight = 1000 self.extra_args = [ ['-txnotokens=0', - '-amkheight=1', - '-bayfrontheight=1', - '-eunosheight=1', - '-fortcanningheight=1', - '-fortcanningmuseumheight=1', - '-fortcanningparkheight=1', - '-fortcanninghillheight=1', - '-fortcanningcrunchheight=1', - '-fortcanningroadheight=1', - '-fortcanninggreatworldheight=1', - '-fortcanningepilogueheight=1', - f'-grandcentralheight={self.grandcentralheight}', - '-jellyfish_regtest=1', '-txindex=1', '-simulatemainnet=1'] + '-amkheight=1', + '-bayfrontheight=1', + '-eunosheight=1', + '-fortcanningheight=1', + '-fortcanningmuseumheight=1', + '-fortcanningparkheight=1', + '-fortcanninghillheight=1', + '-fortcanningcrunchheight=1', + '-fortcanningroadheight=1', + '-fortcanninggreatworldheight=1', + '-fortcanningepilogueheight=1', + f'-grandcentralheight={self.grandcentralheight}', + '-jellyfish_regtest=1', '-txindex=1', '-simulatemainnet=1'] ] def takeloan_withdraw(self, vaultId, amount, type='takeloan'): @@ -71,7 +75,7 @@ def takeloan_withdraw(self, vaultId, amount, type='takeloan'): # Utils - def new_vault(self, loan_scheme, amounts = None): + def new_vault(self, loan_scheme, amounts=None): if amounts is None: amounts = [] vaultId = self.nodes[0].createvault(self.account0, loan_scheme) @@ -90,7 +94,6 @@ def goto_gc_height(self): blockchainInfo = self.nodes[0].getblockchaininfo() assert_equal(blockchainInfo["softforks"]["grandcentral"]["active"], True) - def create_tokens(self): self.symboldUSD = "DUSD" self.symbolWMT = "WMT" @@ -170,8 +173,7 @@ def create_oracles(self): self.nodes[0].setoracledata(self.oracle_id2, timestamp, oracle_prices) self.nodes[0].generate(120) - - mock_time = int(time.time()+3000) + mock_time = int(time.time() + 3000) self.nodes[0].setmocktime(mock_time) self.nodes[0].setoracledata(self.oracle_id1, mock_time, oracle_prices) self.nodes[0].generate(120) @@ -208,7 +210,7 @@ def setup(self): self.nodes[0].generate(10) self.setup_height = self.nodes[0].getblockcount() - def rollback_checks(self, vaults = None): + def rollback_checks(self, vaults=None): if vaults is None: vaults = [] for vault in vaults: @@ -216,7 +218,7 @@ def rollback_checks(self, vaults = None): self.nodes[0].getvault(vault) except JSONRPCException as e: errorString = e.error['message'] - assert(f"Vault <{vault}> not found" in errorString) + assert (f"Vault <{vault}> not found" in errorString) # TESTS def post_FCE_DFI_minimum_check_takeloan(self): @@ -224,7 +226,7 @@ def post_FCE_DFI_minimum_check_takeloan(self): self.goto_gc_height() - self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.iddUSD}/loan_collateral_factor': '1.2'}}) + self.nodes[0].setgov({"ATTRIBUTES": {f'v0/token/{self.iddUSD}/loan_collateral_factor': '1.2'}}) self.nodes[0].generate(1) vault_id = self.new_vault('LOAN1', ["0.90000000@BTC", "20931.30417782@DUSD"]) self.takeloan_withdraw(vault_id, "204.81447327@WMT", 'takeloan') @@ -240,5 +242,6 @@ def run_test(self): self.setup() self.post_FCE_DFI_minimum_check_takeloan() + if __name__ == '__main__': DUSDFactorPctTests().main() diff --git a/test/functional/feature_versionbits_warning.py b/test/functional/feature_versionbits_warning.py index 93579e9add..b289ce494f 100755 --- a/test/functional/feature_versionbits_warning.py +++ b/test/functional/feature_versionbits_warning.py @@ -16,15 +16,16 @@ from test_framework.test_framework import DefiTestFramework from test_framework.util import wait_until -VB_PERIOD = 144 # versionbits period length for regtest -VB_THRESHOLD = 108 # versionbits activation threshold for regtest +VB_PERIOD = 144 # versionbits period length for regtest +VB_THRESHOLD = 108 # versionbits activation threshold for regtest VB_TOP_BITS = 0x20000000 -VB_UNKNOWN_BIT = 27 # Choose a bit unassigned to any deployment +VB_UNKNOWN_BIT = 27 # Choose a bit unassigned to any deployment VB_UNKNOWN_VERSION = VB_TOP_BITS | (1 << VB_UNKNOWN_BIT) WARN_UNKNOWN_RULES_ACTIVE = "unknown new rules activated (versionbit {})".format(VB_UNKNOWN_BIT) VB_PATTERN = re.compile("Warning: unknown new rules activated.*versionbit") + class VersionBitsWarningTest(DefiTestFramework): def set_test_params(self): self.setup_clean_chain = True @@ -67,7 +68,8 @@ def run_test(self): # Mine one period worth of blocks node.generate(VB_PERIOD) - self.log.info("Check that there is no warning if previous VB_BLOCKS have =VB_THRESHOLD blocks with unknown versionbits version.") + self.log.info( + "Check that there is a warning if previous VB_BLOCKS have >=VB_THRESHOLD blocks with unknown versionbits version.") # Mine a period worth of expected blocks so the generic block-version warning # is cleared. This will move the versionbit state to ACTIVE. node.generate(VB_PERIOD) @@ -101,5 +104,6 @@ def run_test(self): # Check that the alert file shows the versionbits unknown rules warning wait_until(lambda: self.versionbits_in_alert_file(), timeout=60) + if __name__ == '__main__': VersionBitsWarningTest().main() diff --git a/test/functional/interface_defi_cli.py b/test/functional/interface_defi_cli.py index 2dc69c26ea..8cb6c4b60e 100755 --- a/test/functional/interface_defi_cli.py +++ b/test/functional/interface_defi_cli.py @@ -6,6 +6,7 @@ from test_framework.test_framework import DefiTestFramework from test_framework.util import assert_equal, assert_raises_process_error, get_auth_cookie + class TestDefiCli(DefiTestFramework): def set_test_params(self): @@ -33,17 +34,22 @@ def run_test(self): self.log.info("Test -stdinrpcpass option") assert_equal(0, self.nodes[0].cli('-rpcuser=%s' % user, '-stdinrpcpass', input=password).getblockcount()) - assert_raises_process_error(1, "Incorrect rpcuser or rpcpassword", self.nodes[0].cli('-rpcuser=%s' % user, '-stdinrpcpass', input="foo").echo) + assert_raises_process_error(1, "Incorrect rpcuser or rpcpassword", + self.nodes[0].cli('-rpcuser=%s' % user, '-stdinrpcpass', input="foo").echo) self.log.info("Test -stdin and -stdinrpcpass") - assert_equal(["foo", "bar"], self.nodes[0].cli('-rpcuser=%s' % user, '-stdin', '-stdinrpcpass', input=password + "\nfoo\nbar").echo()) - assert_raises_process_error(1, "Incorrect rpcuser or rpcpassword", self.nodes[0].cli('-rpcuser=%s' % user, '-stdin', '-stdinrpcpass', input="foo").echo) + assert_equal(["foo", "bar"], self.nodes[0].cli('-rpcuser=%s' % user, '-stdin', '-stdinrpcpass', + input=password + "\nfoo\nbar").echo()) + assert_raises_process_error(1, "Incorrect rpcuser or rpcpassword", + self.nodes[0].cli('-rpcuser=%s' % user, '-stdin', '-stdinrpcpass', + input="foo").echo) self.log.info("Test connecting to a non-existing server") assert_raises_process_error(1, "Could not connect to the server", self.nodes[0].cli('-rpcport=1').echo) self.log.info("Test connecting with non-existing RPC cookie file") - assert_raises_process_error(1, "Could not locate RPC credentials", self.nodes[0].cli('-rpccookiefile=does-not-exist', '-rpcpassword=').echo) + assert_raises_process_error(1, "Could not locate RPC credentials", + self.nodes[0].cli('-rpccookiefile=does-not-exist', '-rpcpassword=').echo) self.log.info("Make sure that -getinfo with arguments fails") assert_raises_process_error(1, "-getinfo takes no arguments", self.nodes[0].cli('-getinfo').help) diff --git a/test/functional/interface_http.py b/test/functional/interface_http.py index 00b667fbd0..6365bd862c 100755 --- a/test/functional/interface_http.py +++ b/test/functional/interface_http.py @@ -10,7 +10,8 @@ import http.client import urllib.parse -class HTTPBasicsTest (DefiTestFramework): + +class HTTPBasicsTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 3 @@ -18,7 +19,6 @@ def setup_network(self): self.setup_nodes() def run_test(self): - ################################################# # lowlevel check for http persistent connection # ################################################# @@ -31,16 +31,16 @@ def run_test(self): conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) out1 = conn.getresponse().read() assert b'"error":null' in out1 - assert conn.sock is not None #according to http/1.1 connection must still be open! + assert conn.sock is not None # according to http/1.1 connection must still be open! - #send 2nd request without closing connection + # send 2nd request without closing connection conn.request('POST', '/', '{"method": "getchaintips"}', headers) out1 = conn.getresponse().read() - assert b'"error":null' in out1 #must also response with a correct json-rpc message - assert conn.sock is not None #according to http/1.1 connection must still be open! + assert b'"error":null' in out1 # must also response with a correct json-rpc message + assert conn.sock is not None # according to http/1.1 connection must still be open! conn.close() - #same should be if we add keep-alive because this should be the std. behaviour + # same should be if we add keep-alive because this should be the std. behaviour headers = {"Authorization": "Basic " + str_to_b64str(authpair), "Connection": "keep-alive"} conn = http.client.HTTPConnection(url.hostname, url.port) @@ -48,26 +48,26 @@ def run_test(self): conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) out1 = conn.getresponse().read() assert b'"error":null' in out1 - assert conn.sock is not None #according to http/1.1 connection must still be open! + assert conn.sock is not None # according to http/1.1 connection must still be open! - #send 2nd request without closing connection + # send 2nd request without closing connection conn.request('POST', '/', '{"method": "getchaintips"}', headers) out1 = conn.getresponse().read() - assert b'"error":null' in out1 #must also response with a correct json-rpc message - assert conn.sock is not None #according to http/1.1 connection must still be open! + assert b'"error":null' in out1 # must also response with a correct json-rpc message + assert conn.sock is not None # according to http/1.1 connection must still be open! conn.close() - #now do the same with "Connection: close" - headers = {"Authorization": "Basic " + str_to_b64str(authpair), "Connection":"close"} + # now do the same with "Connection: close" + headers = {"Authorization": "Basic " + str_to_b64str(authpair), "Connection": "close"} conn = http.client.HTTPConnection(url.hostname, url.port) conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) out1 = conn.getresponse().read() assert b'"error":null' in out1 - assert conn.sock is None #now the connection must be closed after the response + assert conn.sock is None # now the connection must be closed after the response - #node1 (2nd node) is running with disabled keep-alive option + # node1 (2nd node) is running with disabled keep-alive option urlNode1 = urllib.parse.urlparse(self.nodes[1].url) authpair = urlNode1.username + ':' + urlNode1.password headers = {"Authorization": "Basic " + str_to_b64str(authpair)} @@ -78,7 +78,7 @@ def run_test(self): out1 = conn.getresponse().read() assert b'"error":null' in out1 - #node2 (third node) is running with standard keep-alive parameters which means keep-alive is on + # node2 (third node) is running with standard keep-alive parameters which means keep-alive is on urlNode2 = urllib.parse.urlparse(self.nodes[2].url) authpair = urlNode2.username + ':' + urlNode2.password headers = {"Authorization": "Basic " + str_to_b64str(authpair)} @@ -88,21 +88,21 @@ def run_test(self): conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) out1 = conn.getresponse().read() assert b'"error":null' in out1 - assert conn.sock is not None #connection must be closed because defid should use keep-alive by default + assert conn.sock is not None # connection must be closed because defid should use keep-alive by default # Check excessive request size conn = http.client.HTTPConnection(urlNode2.hostname, urlNode2.port) conn.connect() - conn.request('GET', '/' + ('x'*1000), '', headers) + conn.request('GET', '/' + ('x' * 1000), '', headers) out1 = conn.getresponse() assert_equal(out1.status, http.client.NOT_FOUND) conn = http.client.HTTPConnection(urlNode2.hostname, urlNode2.port) conn.connect() - conn.request('GET', '/' + ('x'*10000), '', headers) + conn.request('GET', '/' + ('x' * 10000), '', headers) out1 = conn.getresponse() assert_equal(out1.status, http.client.BAD_REQUEST) if __name__ == '__main__': - HTTPBasicsTest ().main () + HTTPBasicsTest().main() diff --git a/test/functional/interface_http_cors.py b/test/functional/interface_http_cors.py index 68f9fedd1d..65b00d1346 100755 --- a/test/functional/interface_http_cors.py +++ b/test/functional/interface_http_cors.py @@ -10,18 +10,18 @@ import http.client import urllib.parse -class HTTPCorsTest (DefiTestFramework): + +class HTTPCorsTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.cors_origin = "http://localhost:8000" self.extra_args = [["-rpcallowcors=" + self.cors_origin]] def run_test(self): - url = urllib.parse.urlparse(self.nodes[0].url) authpair = url.username + ':' + url.password - #same should be if we add keep-alive because this should be the std. behaviour + # same should be if we add keep-alive because this should be the std. behaviour headers = {"Authorization": "Basic " + str_to_b64str(authpair), "Connection": "keep-alive"} conn = http.client.HTTPConnection(url.hostname, url.port) @@ -32,7 +32,6 @@ def run_test(self): assert_equal(res.status, http.client.OK) res.close() - conn.request('OPTIONS', '/', '{"method": "getbestblockhash"}', headers) res = conn.getresponse() self.check_cors_headers(res) @@ -47,4 +46,4 @@ def check_cors_headers(self, res): if __name__ == '__main__': - HTTPCorsTest ().main () + HTTPCorsTest().main() diff --git a/test/functional/interface_rest.py b/test/functional/interface_rest.py index ae9ff1df98..9a048345a3 100755 --- a/test/functional/interface_rest.py +++ b/test/functional/interface_rest.py @@ -24,22 +24,26 @@ from test_framework.messages import BLOCK_HEADER_SIZE + class ReqType(Enum): JSON = 1 BIN = 2 HEX = 3 + class RetType(Enum): OBJ = 1 BYTES = 2 JSON = 3 + def filter_output_indices_by_value(vouts, value): for vout in vouts: if vout['value'] == value: yield vout['n'] -class RESTTest (DefiTestFramework): + +class RESTTest(DefiTestFramework): def set_test_params(self): self.setup_clean_chain = True self.num_nodes = 2 @@ -48,7 +52,8 @@ def set_test_params(self): def skip_test_if_missing_module(self): self.skip_if_no_wallet() - def test_rest_request(self, uri, http_method='GET', req_type=ReqType.JSON, body='', status=200, ret_type=RetType.JSON): + def test_rest_request(self, uri, http_method='GET', req_type=ReqType.JSON, body='', status=200, + ret_type=RetType.JSON): rest_uri = '/rest' + uri if req_type == ReqType.JSON: rest_uri += '.json' @@ -99,9 +104,10 @@ def run_test(self): # Check hex format response hex_response = self.test_rest_request("/tx/{}".format(txid), req_type=ReqType.HEX, ret_type=RetType.OBJ) assert_greater_than_or_equal(int(hex_response.getheader('content-length')), - json_obj['size']*2) + json_obj['size'] * 2) - spent = (json_obj['vin'][0]['txid'], json_obj['vin'][0]['vout']) # get the vin to later check for utxo (should be spent by then) + spent = (json_obj['vin'][0]['txid'], + json_obj['vin'][0]['vout']) # get the vin to later check for utxo (should be spent by then) # get n of 0.1 outpoint n, = filter_output_indices_by_value(json_obj['vout'], Decimal('0.1')) spending = (txid, n) @@ -149,7 +155,8 @@ def run_test(self): bin_request += hex_str_to_bytes(txid) bin_request += pack("i", n) - bin_response = self.test_rest_request("/getutxos", http_method='POST', req_type=ReqType.BIN, body=bin_request, ret_type=RetType.BYTES) + bin_response = self.test_rest_request("/getutxos", http_method='POST', req_type=ReqType.BIN, body=bin_request, + ret_type=RetType.BYTES) output = BytesIO(bin_response) chain_height, = unpack("i", output.read(4)) response_hash = output.read(32)[::-1].hex() @@ -193,13 +200,17 @@ def run_test(self): assert_equal(len(json_obj['utxos']), 1) # Do some invalid requests - self.test_rest_request("/getutxos", http_method='POST', req_type=ReqType.JSON, body='{"checkmempool', status=400, ret_type=RetType.OBJ) - self.test_rest_request("/getutxos", http_method='POST', req_type=ReqType.BIN, body='{"checkmempool', status=400, ret_type=RetType.OBJ) - self.test_rest_request("/getutxos/checkmempool", http_method='POST', req_type=ReqType.JSON, status=400, ret_type=RetType.OBJ) + self.test_rest_request("/getutxos", http_method='POST', req_type=ReqType.JSON, body='{"checkmempool', + status=400, ret_type=RetType.OBJ) + self.test_rest_request("/getutxos", http_method='POST', req_type=ReqType.BIN, body='{"checkmempool', status=400, + ret_type=RetType.OBJ) + self.test_rest_request("/getutxos/checkmempool", http_method='POST', req_type=ReqType.JSON, status=400, + ret_type=RetType.OBJ) # Test limits long_uri = '/'.join(["{}-{}".format(txid, n_) for n_ in range(20)]) - self.test_rest_request("/getutxos/checkmempool/{}".format(long_uri), http_method='POST', status=400, ret_type=RetType.OBJ) + self.test_rest_request("/getutxos/checkmempool/{}".format(long_uri), http_method='POST', status=400, + ret_type=RetType.OBJ) long_uri = '/'.join(['{}-{}'.format(txid, n_) for n_ in range(15)]) self.test_rest_request("/getutxos/checkmempool/{}".format(long_uri), http_method='POST', status=200) @@ -211,8 +222,10 @@ def run_test(self): bb_hash = self.nodes[0].getbestblockhash() # Check result if block does not exists - assert_equal(self.test_rest_request('/headers/1/0000000000000000000000000000000000000000000000000000000000000000'), []) - self.test_rest_request('/block/0000000000000000000000000000000000000000000000000000000000000000', status=404, ret_type=RetType.OBJ) + assert_equal( + self.test_rest_request('/headers/1/0000000000000000000000000000000000000000000000000000000000000000'), []) + self.test_rest_request('/block/0000000000000000000000000000000000000000000000000000000000000000', status=404, + ret_type=RetType.OBJ) # Check result if block is not in the active chain self.nodes[0].invalidateblock(bb_hash) @@ -226,32 +239,37 @@ def run_test(self): response_bytes = response.read() # Compare with block header - response_header = self.test_rest_request("/headers/1/{}".format(bb_hash), req_type=ReqType.BIN, ret_type=RetType.OBJ) + response_header = self.test_rest_request("/headers/1/{}".format(bb_hash), req_type=ReqType.BIN, + ret_type=RetType.OBJ) assert_equal(int(response_header.getheader('content-length')), BLOCK_HEADER_SIZE) response_header_bytes = response_header.read() assert_equal(response_bytes[:BLOCK_HEADER_SIZE], response_header_bytes) # Check block hex format response_hex = self.test_rest_request("/block/{}".format(bb_hash), req_type=ReqType.HEX, ret_type=RetType.OBJ) - assert_greater_than(int(response_hex.getheader('content-length')), BLOCK_HEADER_SIZE*2) + assert_greater_than(int(response_hex.getheader('content-length')), BLOCK_HEADER_SIZE * 2) response_hex_bytes = response_hex.read().strip(b'\n') assert_equal(binascii.hexlify(response_bytes), response_hex_bytes) # Compare with hex block header - response_header_hex = self.test_rest_request("/headers/1/{}".format(bb_hash), req_type=ReqType.HEX, ret_type=RetType.OBJ) - assert_greater_than(int(response_header_hex.getheader('content-length')), BLOCK_HEADER_SIZE*2) - response_header_hex_bytes = response_header_hex.read(BLOCK_HEADER_SIZE*2) + response_header_hex = self.test_rest_request("/headers/1/{}".format(bb_hash), req_type=ReqType.HEX, + ret_type=RetType.OBJ) + assert_greater_than(int(response_header_hex.getheader('content-length')), BLOCK_HEADER_SIZE * 2) + response_header_hex_bytes = response_header_hex.read(BLOCK_HEADER_SIZE * 2) assert_equal(binascii.hexlify(response_bytes[:BLOCK_HEADER_SIZE]), response_header_hex_bytes) # Check json format block_json_obj = self.test_rest_request("/block/{}".format(bb_hash)) assert_equal(block_json_obj['hash'], bb_hash) - assert_equal(self.test_rest_request("/blockhashbyheight/{}".format(block_json_obj['height']))['blockhash'], bb_hash) + assert_equal(self.test_rest_request("/blockhashbyheight/{}".format(block_json_obj['height']))['blockhash'], + bb_hash) # Check hex/bin format - resp_hex = self.test_rest_request("/blockhashbyheight/{}".format(block_json_obj['height']), req_type=ReqType.HEX, ret_type=RetType.OBJ) + resp_hex = self.test_rest_request("/blockhashbyheight/{}".format(block_json_obj['height']), + req_type=ReqType.HEX, ret_type=RetType.OBJ) assert_equal(resp_hex.read().decode('utf-8').rstrip(), bb_hash) - resp_bytes = self.test_rest_request("/blockhashbyheight/{}".format(block_json_obj['height']), req_type=ReqType.BIN, ret_type=RetType.BYTES) + resp_bytes = self.test_rest_request("/blockhashbyheight/{}".format(block_json_obj['height']), + req_type=ReqType.BIN, ret_type=RetType.BYTES) blockhash = resp_bytes[::-1].hex() assert_equal(blockhash, bb_hash) @@ -271,7 +289,8 @@ def run_test(self): # Compare with normal RPC block response rpc_block_json = self.nodes[0].getblock(bb_hash) - for key in ['hash', 'confirmations', 'height', 'version', 'merkleroot', 'time', 'bits', 'difficulty', 'chainwork', 'previousblockhash']: + for key in ['hash', 'confirmations', 'height', 'version', 'merkleroot', 'time', 'bits', 'difficulty', + 'chainwork', 'previousblockhash']: assert_equal(json_obj[0][key], rpc_block_json[key]) # See if we can get 5 headers in one response @@ -324,5 +343,6 @@ def run_test(self): json_obj = self.test_rest_request("/chaininfo") assert_equal(json_obj['bestblockhash'], bb_hash) + if __name__ == '__main__': RESTTest().main() diff --git a/test/functional/interface_rpc.py b/test/functional/interface_rpc.py index e24593a2cb..6f8a76a8cf 100755 --- a/test/functional/interface_rpc.py +++ b/test/functional/interface_rpc.py @@ -9,6 +9,7 @@ from test_framework.test_framework import DefiTestFramework from test_framework.util import assert_equal, assert_greater_than_or_equal + def expect_http_status(expected_http_status, expected_rpc_code, fcn, *args): try: @@ -18,6 +19,7 @@ def expect_http_status(expected_http_status, expected_rpc_code, assert_equal(exc.error["code"], expected_rpc_code) assert_equal(exc.http_status, expected_http_status) + class RPCInterfaceTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 diff --git a/test/functional/interface_zmq.py b/test/functional/interface_zmq.py index 280a3c0c12..8047f5bfbf 100755 --- a/test/functional/interface_zmq.py +++ b/test/functional/interface_zmq.py @@ -12,9 +12,11 @@ from io import BytesIO from time import sleep + def hash256_reversed(byte_str): return hash256(byte_str)[::-1] + class ZMQSubscriber: def __init__(self, socket, topic): self.sequence = 0 @@ -34,7 +36,7 @@ def receive(self): return body -class ZMQTest (DefiTestFramework): +class ZMQTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 @@ -69,7 +71,8 @@ def test_basic(self): rawblock = ZMQSubscriber(socket, b"rawblock") rawtx = ZMQSubscriber(socket, b"rawtx") - self.restart_node(0, ["-zmqpub%s=%s" % (sub.topic.decode(), address) for sub in [hashblock, hashtx, rawblock, rawtx]]) + self.restart_node(0, ["-zmqpub%s=%s" % (sub.topic.decode(), address) for sub in + [hashblock, hashtx, rawblock, rawtx]]) connect_nodes(self.nodes[0], 1) socket.connect(address) # Relax so that the subscriber is ready before publishing zmq messages @@ -114,7 +117,6 @@ def test_basic(self): hex = rawtx.receive() assert_equal(payment_txid, hash256_reversed(hex).hex()) - self.log.info("Test the getzmqnotifications RPC") assert_equal(self.nodes[0].getzmqnotifications(), [ {"type": "pubhashblock", "address": address, "hwm": 1000}, @@ -151,5 +153,6 @@ def test_reorg(self): # Should receive nodes[1] tip assert_equal(self.nodes[1].getbestblockhash(), hashblock.receive().hex()) + if __name__ == '__main__': ZMQTest().main() diff --git a/test/functional/mempool_accept.py b/test/functional/mempool_accept.py index 9b5426cdc3..8301b2de78 100755 --- a/test/functional/mempool_accept.py +++ b/test/functional/mempool_accept.py @@ -58,8 +58,10 @@ def run_test(self): coins = node.listunspent() self.log.info('Should not accept garbage to testmempoolaccept') - assert_raises_rpc_error(-3, 'Expected type array, got string', lambda: node.testmempoolaccept(rawtxs='ff00baar')) - assert_raises_rpc_error(-8, 'Array must contain exactly one raw transaction for now', lambda: node.testmempoolaccept(rawtxs=['ff00baar', 'ff22'])) + assert_raises_rpc_error(-3, 'Expected type array, got string', + lambda: node.testmempoolaccept(rawtxs='ff00baar')) + assert_raises_rpc_error(-8, 'Array must contain exactly one raw transaction for now', + lambda: node.testmempoolaccept(rawtxs=['ff00baar', 'ff22'])) assert_raises_rpc_error(-22, 'TX decode failed', lambda: node.testmempoolaccept(rawtxs=['ff00baar'])) self.log.info('A transaction already in the blockchain') @@ -150,7 +152,8 @@ def run_test(self): self.log.info('A transaction with missing inputs, that existed once in the past') tx.deserialize(BytesIO(hex_str_to_bytes(raw_tx_0))) - tx.vin[0].prevout.n = 1 # Set vout to 1, to spend the other outpoint (49 coins) of the in-chain-tx we want to double spend + tx.vin[ + 0].prevout.n = 1 # Set vout to 1, to spend the other outpoint (49 coins) of the in-chain-tx we want to double spend raw_tx_1 = node.signrawtransactionwithwallet(tx.serialize().hex())['hex'] txid_1 = node.sendrawtransaction(hexstring=raw_tx_1, maxfeerate=0) # Now spend both to "clearly hide" the outputs, ie. remove the coins from the utxo set by spending them @@ -225,7 +228,8 @@ def run_test(self): tx.vout = [tx.vout[0]] * 2 tx.vout[0].nValue = MAXMONEY self.check_mempool_result( - result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': '16: bad-txns-txouttotal-toolarge'}], + result_expected=[ + {'txid': tx.rehash(), 'allowed': False, 'reject-reason': '16: bad-txns-txouttotal-toolarge'}], rawtxs=[tx.serialize().hex()], ) @@ -239,7 +243,8 @@ def run_test(self): self.log.info('A coinbase transaction') # Pick the input of the first tx we signed, so it has to be a coinbase tx - raw_tx_coinbase_spent = node.getrawtransaction(txid=node.decoderawtransaction(hexstring=raw_tx_in_block)['vin'][0]['txid']) + raw_tx_coinbase_spent = node.getrawtransaction( + txid=node.decoderawtransaction(hexstring=raw_tx_in_block)['vin'][0]['txid']) tx.deserialize(BytesIO(hex_str_to_bytes(raw_tx_coinbase_spent))) self.check_mempool_result( result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': '16: coinbase'}], @@ -267,7 +272,8 @@ def run_test(self): ) tx.deserialize(BytesIO(hex_str_to_bytes(raw_tx_reference))) output_p2sh_burn = CTxOut(nValue=540, scriptPubKey=CScript([OP_HASH160, hash160(b'burn'), OP_EQUAL])) - num_scripts = 100000 // len(output_p2sh_burn.serialize()) # Use enough outputs to make the tx too large for our policy + num_scripts = 100000 // len( + output_p2sh_burn.serialize()) # Use enough outputs to make the tx too large for our policy tx.vout = [output_p2sh_burn] * num_scripts self.check_mempool_result( result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': '64: tx-size'}], diff --git a/test/functional/mempool_limit.py b/test/functional/mempool_limit.py index 1fd90168ab..1af50995fa 100755 --- a/test/functional/mempool_limit.py +++ b/test/functional/mempool_limit.py @@ -7,7 +7,9 @@ from decimal import Decimal from test_framework.test_framework import DefiTestFramework -from test_framework.util import assert_equal, assert_greater_than, assert_raises_rpc_error, create_confirmed_utxos, create_lots_of_big_transactions, gen_return_txouts +from test_framework.util import assert_equal, assert_greater_than, assert_raises_rpc_error, create_confirmed_utxos, \ + create_lots_of_big_transactions, gen_return_txouts + class MempoolLimitTest(DefiTestFramework): def set_test_params(self): @@ -35,25 +37,26 @@ def run_test(self): self.log.info('Create a mempool tx that will be evicted') us0 = utxos.pop() - inputs = [{ "txid" : us0["txid"], "vout" : us0["vout"]}] - outputs = {self.nodes[0].getnewaddress() : 0.0001} + inputs = [{"txid": us0["txid"], "vout": us0["vout"]}] + outputs = {self.nodes[0].getnewaddress(): 0.0001} tx = self.nodes[0].createrawtransaction(inputs, outputs) - self.nodes[0].settxfee(relayfee) # specifically fund this tx with low fee + self.nodes[0].settxfee(relayfee) # specifically fund this tx with low fee txF = self.nodes[0].fundrawtransaction(tx) - self.nodes[0].settxfee(0) # return to automatic fee selection + self.nodes[0].settxfee(0) # return to automatic fee selection txFS = self.nodes[0].signrawtransactionwithwallet(txF['hex']) txid = self.nodes[0].sendrawtransaction(txFS['hex']) relayfee = self.nodes[0].getnetworkinfo()['relayfee'] - base_fee = relayfee*100 - for i in range (3): + base_fee = relayfee * 100 + for i in range(3): txids.append([]) - txids[i] = create_lots_of_big_transactions(self.nodes[0], txouts, utxos[30*i:30*i+30], 30, (i+1)*base_fee) + txids[i] = create_lots_of_big_transactions(self.nodes[0], txouts, utxos[30 * i:30 * i + 30], 30, + (i + 1) * base_fee) self.log.info('The tx should be evicted by now') assert txid not in self.nodes[0].getrawmempool() txdata = self.nodes[0].gettransaction(txid) - assert txdata['confirmations'] == 0 #confirmation should still be 0 + assert txdata['confirmations'] == 0 # confirmation should still be 0 self.log.info('Check that mempoolminfee is larger than minrelytxfee') assert_equal(self.nodes[0].getmempoolinfo()['minrelaytxfee'], Decimal('0.00001000')) @@ -61,13 +64,14 @@ def run_test(self): self.log.info('Create a mempool tx that will not pass mempoolminfee') us0 = utxos.pop() - inputs = [{ "txid" : us0["txid"], "vout" : us0["vout"]}] - outputs = {self.nodes[0].getnewaddress() : 0.0001} + inputs = [{"txid": us0["txid"], "vout": us0["vout"]}] + outputs = {self.nodes[0].getnewaddress(): 0.0001} tx = self.nodes[0].createrawtransaction(inputs, outputs) # specifically fund this tx with a fee < mempoolminfee, >= than minrelaytxfee txF = self.nodes[0].fundrawtransaction(tx, {'feeRate': relayfee}) txFS = self.nodes[0].signrawtransactionwithwallet(txF['hex']) assert_raises_rpc_error(-26, "mempool min fee not met", self.nodes[0].sendrawtransaction, txFS['hex']) + if __name__ == '__main__': MempoolLimitTest().main() diff --git a/test/functional/mempool_package_onemore.py b/test/functional/mempool_package_onemore.py index 52e170084b..d886bcea7b 100755 --- a/test/functional/mempool_package_onemore.py +++ b/test/functional/mempool_package_onemore.py @@ -15,6 +15,7 @@ MAX_ANCESTORS = 25 MAX_DESCENDANTS = 25 + class MempoolPackagesTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 @@ -26,10 +27,10 @@ def skip_test_if_missing_module(self): # Build a transaction that spends parent_txid:vout # Return amount sent def chain_transaction(self, node, parent_txids, vouts, value, fee, num_outputs): - send_value = satoshi_round((value - fee)/num_outputs) + send_value = satoshi_round((value - fee) / num_outputs) inputs = [] for (txid, vout) in zip(parent_txids, vouts): - inputs.append({'txid' : txid, 'vout' : vout}) + inputs.append({'txid': txid, 'vout': vout}) outputs = {} for i in range(num_outputs): outputs[node.getnewaddress()] = send_value @@ -60,20 +61,27 @@ def run_test(self): (txid, sent_value) = self.chain_transaction(self.nodes[0], [txid], [0], value, fee, 1) value = sent_value chain.append([txid, value]) - (second_chain, second_chain_value) = self.chain_transaction(self.nodes[0], [utxo[1]['txid']], [utxo[1]['vout']], utxo[1]['amount'], fee, 1) + (second_chain, second_chain_value) = self.chain_transaction(self.nodes[0], [utxo[1]['txid']], [utxo[1]['vout']], + utxo[1]['amount'], fee, 1) # Check mempool has MAX_ANCESTORS + 1 transactions in it assert_equal(len(self.nodes[0].getrawmempool(True)), MAX_ANCESTORS + 1) # Adding one more transaction on to the chain should fail. - assert_raises_rpc_error(-26, "too-long-mempool-chain, too many unconfirmed ancestors [limit: 25]", self.chain_transaction, self.nodes[0], [txid], [0], value, fee, 1) + assert_raises_rpc_error(-26, "too-long-mempool-chain, too many unconfirmed ancestors [limit: 25]", + self.chain_transaction, self.nodes[0], [txid], [0], value, fee, 1) # ...even if it chains on from some point in the middle of the chain. - assert_raises_rpc_error(-26, "too-long-mempool-chain, too many descendants", self.chain_transaction, self.nodes[0], [chain[2][0]], [1], chain[2][1], fee, 1) - assert_raises_rpc_error(-26, "too-long-mempool-chain, too many descendants", self.chain_transaction, self.nodes[0], [chain[1][0]], [1], chain[1][1], fee, 1) + assert_raises_rpc_error(-26, "too-long-mempool-chain, too many descendants", self.chain_transaction, + self.nodes[0], [chain[2][0]], [1], chain[2][1], fee, 1) + assert_raises_rpc_error(-26, "too-long-mempool-chain, too many descendants", self.chain_transaction, + self.nodes[0], [chain[1][0]], [1], chain[1][1], fee, 1) # ...even if it chains on to two parent transactions with one in the chain. - assert_raises_rpc_error(-26, "too-long-mempool-chain, too many descendants", self.chain_transaction, self.nodes[0], [chain[0][0], second_chain], [1, 0], chain[0][1] + second_chain_value, fee, 1) + assert_raises_rpc_error(-26, "too-long-mempool-chain, too many descendants", self.chain_transaction, + self.nodes[0], [chain[0][0], second_chain], [1, 0], chain[0][1] + second_chain_value, + fee, 1) # ...especially if its > 40k weight - assert_raises_rpc_error(-26, "too-long-mempool-chain, too many descendants", self.chain_transaction, self.nodes[0], [chain[0][0]], [1], chain[0][1], fee, 350) + assert_raises_rpc_error(-26, "too-long-mempool-chain, too many descendants", self.chain_transaction, + self.nodes[0], [chain[0][0]], [1], chain[0][1], fee, 350) # But not if it chains directly off the first transaction self.chain_transaction(self.nodes[0], [chain[0][0]], [1], chain[0][1], fee, 1) # and the second chain should work just fine @@ -82,5 +90,6 @@ def run_test(self): # Finally, check that we added two transactions assert_equal(len(self.nodes[0].getrawmempool(True)), MAX_ANCESTORS + 3) + if __name__ == '__main__': MempoolPackagesTest().main() diff --git a/test/functional/mempool_packages.py b/test/functional/mempool_packages.py index 3b3ae92efd..6503f7edc5 100755 --- a/test/functional/mempool_packages.py +++ b/test/functional/mempool_packages.py @@ -17,6 +17,7 @@ MAX_ANCESTORS = 25 MAX_DESCENDANTS = 25 + class MempoolPackagesTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 @@ -28,8 +29,8 @@ def skip_test_if_missing_module(self): # Build a transaction that spends parent_txid:vout # Return amount sent def chain_transaction(self, node, parent_txid, vout, value, fee, num_outputs): - send_value = satoshi_round((value - fee)/num_outputs) - inputs = [ {'txid' : parent_txid, 'vout' : vout} ] + send_value = satoshi_round((value - fee) / num_outputs) + inputs = [{'txid': parent_txid, 'vout': vout}] outputs = {} for i in range(num_outputs): outputs[node.getnewaddress()] = send_value @@ -104,9 +105,9 @@ def run_test(self): # Check getmempooldescendants verbose output is correct for descendant, dinfo in self.nodes[0].getmempooldescendants(x, True).items(): - assert_equal(dinfo['depends'], [chain[chain.index(descendant)-1]]) + assert_equal(dinfo['depends'], [chain[chain.index(descendant) - 1]]) if dinfo['descendantcount'] > 1: - assert_equal(dinfo['spentby'], [chain[chain.index(descendant)+1]]) + assert_equal(dinfo['spentby'], [chain[chain.index(descendant) + 1]]) else: assert_equal(dinfo['spentby'], []) descendants.append(x) @@ -117,22 +118,21 @@ def run_test(self): # Check that getmempoolancestors verbose output is correct for ancestor, ainfo in self.nodes[0].getmempoolancestors(x, True).items(): - assert_equal(ainfo['spentby'], [chain[chain.index(ancestor)+1]]) + assert_equal(ainfo['spentby'], [chain[chain.index(ancestor) + 1]]) if ainfo['ancestorcount'] > 1: - assert_equal(ainfo['depends'], [chain[chain.index(ancestor)-1]]) + assert_equal(ainfo['depends'], [chain[chain.index(ancestor) - 1]]) else: assert_equal(ainfo['depends'], []) - # Check that getmempoolancestors/getmempooldescendants correctly handle verbose=true v_ancestors = self.nodes[0].getmempoolancestors(chain[-1], True) - assert_equal(len(v_ancestors), len(chain)-1) + assert_equal(len(v_ancestors), len(chain) - 1) for x in v_ancestors.keys(): assert_equal(mempool[x], v_ancestors[x]) assert chain[-1] not in v_ancestors.keys() v_descendants = self.nodes[0].getmempooldescendants(chain[0], True) - assert_equal(len(v_descendants), len(chain)-1) + assert_equal(len(v_descendants), len(chain) - 1) for x in v_descendants.keys(): assert_equal(mempool[x], v_descendants[x]) assert chain[0] not in v_descendants.keys() @@ -162,7 +162,8 @@ def run_test(self): assert_equal(mempool[x]['descendantfees'], descendant_fees * COIN + 1000) # Adding one more transaction on to the chain should fail. - assert_raises_rpc_error(-26, "too-long-mempool-chain", self.chain_transaction, self.nodes[0], txid, vout, value, fee, 1) + assert_raises_rpc_error(-26, "too-long-mempool-chain", self.chain_transaction, self.nodes[0], txid, vout, value, + fee, 1) # Check that prioritising a tx before it's added to the mempool works # First clear the mempool by mining a block. @@ -183,10 +184,10 @@ def run_test(self): for x in reversed(chain): descendant_fees += mempool[x]['fee'] if (x == chain[-1]): - assert_equal(mempool[x]['modifiedfee'], mempool[x]['fee']+satoshi_round(0.00002)) - assert_equal(mempool[x]['fees']['modified'], mempool[x]['fee']+satoshi_round(0.00002)) + assert_equal(mempool[x]['modifiedfee'], mempool[x]['fee'] + satoshi_round(0.00002)) + assert_equal(mempool[x]['fees']['modified'], mempool[x]['fee'] + satoshi_round(0.00002)) assert_equal(mempool[x]['descendantfees'], descendant_fees * COIN + 2000) - assert_equal(mempool[x]['fees']['descendant'], descendant_fees+satoshi_round(0.00002)) + assert_equal(mempool[x]['fees']['descendant'], descendant_fees + satoshi_round(0.00002)) # TODO: check that node1's mempool is as expected @@ -208,7 +209,8 @@ def run_test(self): # Sign and send up to MAX_DESCENDANT transactions chained off the parent tx for i in range(MAX_DESCENDANTS - 1): utxo = transaction_package.pop(0) - (txid, sent_value) = self.chain_transaction(self.nodes[0], utxo['txid'], utxo['vout'], utxo['amount'], fee, 10) + (txid, sent_value) = self.chain_transaction(self.nodes[0], utxo['txid'], utxo['vout'], utxo['amount'], fee, + 10) if utxo['txid'] is parent_transaction: tx_children.append(txid) for j in range(10): @@ -223,7 +225,8 @@ def run_test(self): # Sending one more chained transaction will fail utxo = transaction_package.pop(0) - assert_raises_rpc_error(-26, "too-long-mempool-chain", self.chain_transaction, self.nodes[0], utxo['txid'], utxo['vout'], utxo['amount'], fee, 10) + assert_raises_rpc_error(-26, "too-long-mempool-chain", self.chain_transaction, self.nodes[0], utxo['txid'], + utxo['vout'], utxo['amount'], fee, 10) # TODO: check that node1's mempool is as expected @@ -255,8 +258,8 @@ def run_test(self): value = utxo[0]['amount'] vout = utxo[0]['vout'] - send_value = satoshi_round((value - fee)/2) - inputs = [ {'txid' : txid, 'vout' : vout} ] + send_value = satoshi_round((value - fee) / 2) + inputs = [{'txid': txid, 'vout': vout}] outputs = {} for i in range(2): outputs[self.nodes[0].getnewaddress()] = send_value @@ -282,8 +285,8 @@ def run_test(self): self.sync_blocks() # Now generate tx8, with a big fee - inputs = [ {'txid' : tx1_id, 'vout': 0}, {'txid' : txid, 'vout': 0} ] - outputs = { self.nodes[0].getnewaddress() : send_value + value - 4*fee } + inputs = [{'txid': tx1_id, 'vout': 0}, {'txid': txid, 'vout': 0}] + outputs = {self.nodes[0].getnewaddress(): send_value + value - 4 * fee} rawtx = self.nodes[0].createrawtransaction(inputs, outputs) signedtx = self.nodes[0].signrawtransactionwithwallet(rawtx) txid = self.nodes[0].sendrawtransaction(signedtx['hex']) @@ -294,5 +297,6 @@ def run_test(self): self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash()) self.sync_blocks() + if __name__ == '__main__': MempoolPackagesTest().main() diff --git a/test/functional/mempool_persist.py b/test/functional/mempool_persist.py index 347dffe96b..e1a07d5a9f 100755 --- a/test/functional/mempool_persist.py +++ b/test/functional/mempool_persist.py @@ -75,7 +75,8 @@ def run_test(self): fees = self.nodes[0].getmempoolentry(txid=last_txid)['fees'] assert_equal(fees['base'] + Decimal('0.00001000'), fees['modified']) - self.log.debug("Stop-start the nodes. Verify that node0 has the transactions in its mempool and node1 does not. Verify that node2 calculates its balance correctly after loading wallet transactions.") + self.log.debug( + "Stop-start the nodes. Verify that node0 has the transactions in its mempool and node1 does not. Verify that node2 calculates its balance correctly after loading wallet transactions.") self.stop_nodes() # Give this node a head-start, so we can be "extra-sure" that it didn't load anything later # Also don't store the mempool, to keep the datadir clean diff --git a/test/functional/mempool_reorg.py b/test/functional/mempool_reorg.py index aaebfad21c..563209e1f5 100755 --- a/test/functional/mempool_reorg.py +++ b/test/functional/mempool_reorg.py @@ -40,14 +40,15 @@ def run_test(self): # 3. Indirect (coinbase and child both in chain) : spend_103 and spend_103_1 # Use invalidatblock to make all of the above coinbase spends invalid (immature coinbase), # and make sure the mempool code behaves correctly. - b = [ self.nodes[0].getblockhash(n) for n in range(101, 105) ] - coinbase_txids = [ self.nodes[0].getblock(h)['tx'][0] for h in b ] + b = [self.nodes[0].getblockhash(n) for n in range(101, 105)] + coinbase_txids = [self.nodes[0].getblock(h)['tx'][0] for h in b] spend_101_raw = create_raw_transaction(self.nodes[0], coinbase_txids[1], node1_address, amount=49.99) spend_102_raw = create_raw_transaction(self.nodes[0], coinbase_txids[2], node0_address, amount=49.99) spend_103_raw = create_raw_transaction(self.nodes[0], coinbase_txids[3], node0_address, amount=49.99) # Create a transaction which is time-locked to two blocks in the future - timelock_tx = self.nodes[0].createrawtransaction([{"txid": coinbase_txids[0], "vout": 0}], {node0_address: 49.99}) + timelock_tx = self.nodes[0].createrawtransaction([{"txid": coinbase_txids[0], "vout": 0}], + {node0_address: 49.99}) # Set the time lock timelock_tx = timelock_tx.replace("ffffffff", "11111191", 1) timelock_tx = timelock_tx[:-8] + hex(self.nodes[0].getblockcount() + 2)[2:] + "000000" @@ -96,5 +97,6 @@ def run_test(self): # mempool should be empty. assert_equal(set(self.nodes[0].getrawmempool()), set()) + if __name__ == '__main__': MempoolCoinbaseTest().main() diff --git a/test/functional/mempool_resurrect.py b/test/functional/mempool_resurrect.py index afd2deea2f..9403b1c869 100755 --- a/test/functional/mempool_resurrect.py +++ b/test/functional/mempool_resurrect.py @@ -30,7 +30,8 @@ def run_test(self): b = [self.nodes[0].getblockhash(n) for n in range(1, 4)] coinbase_txids = [self.nodes[0].getblock(h)['tx'][0] for h in b] - spends1_raw = [create_raw_transaction(self.nodes[0], txid, node0_address, amount=49.99) for txid in coinbase_txids] + spends1_raw = [create_raw_transaction(self.nodes[0], txid, node0_address, amount=49.99) for txid in + coinbase_txids] spends1_id = [self.nodes[0].sendrawtransaction(tx) for tx in spends1_raw] blocks = [] @@ -43,7 +44,7 @@ def run_test(self): # mempool should be empty, all txns confirmed assert_equal(set(self.nodes[0].getrawmempool()), set()) - for txid in spends1_id+spends2_id: + for txid in spends1_id + spends2_id: tx = self.nodes[0].gettransaction(txid) assert tx["confirmations"] > 0 @@ -52,8 +53,8 @@ def run_test(self): node.invalidateblock(blocks[0]) # All txns should be back in mempool with 0 confirmations - assert_equal(set(self.nodes[0].getrawmempool()), set(spends1_id+spends2_id)) - for txid in spends1_id+spends2_id: + assert_equal(set(self.nodes[0].getrawmempool()), set(spends1_id + spends2_id)) + for txid in spends1_id + spends2_id: tx = self.nodes[0].gettransaction(txid) assert tx["confirmations"] == 0 @@ -61,7 +62,7 @@ def run_test(self): self.nodes[0].generate(1) # mempool should be empty, all txns confirmed assert_equal(set(self.nodes[0].getrawmempool()), set()) - for txid in spends1_id+spends2_id: + for txid in spends1_id + spends2_id: tx = self.nodes[0].gettransaction(txid) assert tx["confirmations"] > 0 diff --git a/test/functional/mempool_spend_coinbase.py b/test/functional/mempool_spend_coinbase.py index 9095fee160..853f796bd7 100755 --- a/test/functional/mempool_spend_coinbase.py +++ b/test/functional/mempool_spend_coinbase.py @@ -34,15 +34,17 @@ def run_test(self): # is too immature to spend. b = [self.nodes[0].getblockhash(n) for n in range(101, 103)] coinbase_txids = [self.nodes[0].getblock(h)['tx'][0] for h in b] - spends_raw = [create_raw_transaction(self.nodes[0], txid, node0_address, amount=49.99) for txid in coinbase_txids] + spends_raw = [create_raw_transaction(self.nodes[0], txid, node0_address, amount=49.99) for txid in + coinbase_txids] spend_101_id = self.nodes[0].sendrawtransaction(spends_raw[0]) # coinbase at height 102 should be too immature to spend - assert_raises_rpc_error(-26,"bad-txns-premature-spend-of-coinbase", self.nodes[0].sendrawtransaction, spends_raw[1]) + assert_raises_rpc_error(-26, "bad-txns-premature-spend-of-coinbase", self.nodes[0].sendrawtransaction, + spends_raw[1]) # mempool should have just spend_101: - assert_equal(self.nodes[0].getrawmempool(), [ spend_101_id ]) + assert_equal(self.nodes[0].getrawmempool(), [spend_101_id]) # mine a block, spend_101 should get confirmed self.nodes[0].generate(1) @@ -50,7 +52,8 @@ def run_test(self): # ... and now height 102 can be spent: spend_102_id = self.nodes[0].sendrawtransaction(spends_raw[1]) - assert_equal(self.nodes[0].getrawmempool(), [ spend_102_id ]) + assert_equal(self.nodes[0].getrawmempool(), [spend_102_id]) + if __name__ == '__main__': MempoolSpendCoinbaseTest().main() diff --git a/test/functional/mining_basic.py b/test/functional/mining_basic.py index b9013e32a0..2c6b38b52e 100755 --- a/test/functional/mining_basic.py +++ b/test/functional/mining_basic.py @@ -34,7 +34,8 @@ def assert_template(node, block, expect, rehash=True): if rehash: block.hashMerkleRoot = block.calc_merkle_root() - rsp = node.getblocktemplate(template_request={'data': block.serialize().hex(), 'mode': 'proposal', 'rules': ['segwit']}) + rsp = node.getblocktemplate( + template_request={'data': block.serialize().hex(), 'mode': 'proposal', 'rules': ['segwit']}) assert_equal(rsp, expect) @@ -46,7 +47,7 @@ def set_test_params(self): def mine_chain(self): self.log.info('Create some old blocks') address = self.nodes[0].get_genesis_keys().ownerAuthAddress - for t in range(TIME_GENESIS_BLOCK+1, TIME_GENESIS_BLOCK + 200 * 600 +1, 600): + for t in range(TIME_GENESIS_BLOCK + 1, TIME_GENESIS_BLOCK + 200 * 600 + 1, 600): self.nodes[0].setmocktime(t) self.nodes[0].generatetoaddress(1, address) @@ -122,10 +123,12 @@ def assert_submitblock(block, result_str_1, result_str_2=None): assert_template(node, bad_block, 'bad-cb-missing') self.log.info("submitblock: Test invalid coinbase transaction") - assert_raises_rpc_error(-22, "Block does not start with a coinbase", node.submitblock, bad_block.serialize().hex()) + assert_raises_rpc_error(-22, "Block does not start with a coinbase", node.submitblock, + bad_block.serialize().hex()) self.log.info("getblocktemplate: Test truncated final transaction") - assert_raises_rpc_error(-22, "Block decode failed", node.getblocktemplate, {'data': block.serialize()[:-1].hex(), 'mode': 'proposal', 'rules': ['segwit']}) + assert_raises_rpc_error(-22, "Block decode failed", node.getblocktemplate, + {'data': block.serialize()[:-1].hex(), 'mode': 'proposal', 'rules': ['segwit']}) self.log.info("getblocktemplate: Test duplicate transaction") bad_block = copy.deepcopy(block) @@ -154,7 +157,8 @@ def assert_submitblock(block, result_str_1, result_str_2=None): bad_block_sn = bytearray(block.serialize()) assert_equal(bad_block_sn[BLOCK_HEADER_SIZE], 1) bad_block_sn[BLOCK_HEADER_SIZE] += 1 - assert_raises_rpc_error(-22, "Block decode failed", node.getblocktemplate, {'data': bad_block_sn.hex(), 'mode': 'proposal', 'rules': ['segwit']}) + assert_raises_rpc_error(-22, "Block decode failed", node.getblocktemplate, + {'data': bad_block_sn.hex(), 'mode': 'proposal', 'rules': ['segwit']}) self.log.info("getblocktemplate: Test bad bits") bad_block = copy.deepcopy(block) @@ -183,9 +187,12 @@ def assert_submitblock(block, result_str_1, result_str_2=None): assert_submitblock(bad_block, 'prev-blk-not-found', 'prev-blk-not-found') self.log.info('submitheader tests') - assert_raises_rpc_error(-22, 'Block header decode failed', lambda: node.submitheader(hexdata='xx' * BLOCK_HEADER_SIZE)) - assert_raises_rpc_error(-22, 'Block header decode failed', lambda: node.submitheader(hexdata='ff' * (BLOCK_HEADER_SIZE-2))) - assert_raises_rpc_error(-25, 'Must submit previous header', lambda: node.submitheader(hexdata=super(CBlock, bad_block).serialize().hex())) + assert_raises_rpc_error(-22, 'Block header decode failed', + lambda: node.submitheader(hexdata='xx' * BLOCK_HEADER_SIZE)) + assert_raises_rpc_error(-22, 'Block header decode failed', + lambda: node.submitheader(hexdata='ff' * (BLOCK_HEADER_SIZE - 2))) + assert_raises_rpc_error(-25, 'Must submit previous header', + lambda: node.submitheader(hexdata=super(CBlock, bad_block).serialize().hex())) block.nTime += 1 block.solve() @@ -214,7 +221,7 @@ def chain_tip(b_hash, *, status='headers-only', branchlen=1): assert chain_tip(bad_block_root.hash) in node.getchaintips() bad_block_lock = copy.deepcopy(block) - bad_block_lock.vtx[0].nLockTime = 2**32 - 1 + bad_block_lock.vtx[0].nLockTime = 2 ** 32 - 1 bad_block_lock.vtx[0].rehash() bad_block_lock.hashMerkleRoot = bad_block_lock.calc_merkle_root() bad_block_lock.solve() @@ -224,13 +231,15 @@ def chain_tip(b_hash, *, status='headers-only', branchlen=1): bad_block2 = copy.deepcopy(block) bad_block2.hashPrevBlock = bad_block_lock.sha256 bad_block2.solve() - assert_raises_rpc_error(-25, 'bad-prevblk', lambda: node.submitheader(hexdata=CBlockHeader(bad_block2).serialize().hex())) + assert_raises_rpc_error(-25, 'bad-prevblk', + lambda: node.submitheader(hexdata=CBlockHeader(bad_block2).serialize().hex())) # Should reject invalid header right away bad_block_time = copy.deepcopy(block) bad_block_time.nTime = 1 bad_block_time.solve() - assert_raises_rpc_error(-25, 'time-too-old', lambda: node.submitheader(hexdata=CBlockHeader(bad_block_time).serialize().hex())) + assert_raises_rpc_error(-25, 'time-too-old', + lambda: node.submitheader(hexdata=CBlockHeader(bad_block_time).serialize().hex())) # Should ask for the block from a p2p node, if they announce the header as well: node.add_p2p_connection(P2PDataStore()) @@ -241,8 +250,10 @@ def chain_tip(b_hash, *, status='headers-only', branchlen=1): # Building a few blocks should give the same results node.generate(10) - assert_raises_rpc_error(-25, 'time-too-old', lambda: node.submitheader(hexdata=CBlockHeader(bad_block_time).serialize().hex())) - assert_raises_rpc_error(-25, 'bad-prevblk', lambda: node.submitheader(hexdata=CBlockHeader(bad_block2).serialize().hex())) + assert_raises_rpc_error(-25, 'time-too-old', + lambda: node.submitheader(hexdata=CBlockHeader(bad_block_time).serialize().hex())) + assert_raises_rpc_error(-25, 'bad-prevblk', + lambda: node.submitheader(hexdata=CBlockHeader(bad_block2).serialize().hex())) node.submitheader(hexdata=CBlockHeader(block).serialize().hex()) node.submitheader(hexdata=CBlockHeader(bad_block_root).serialize().hex()) assert_equal(node.submitblock(hexdata=block.serialize().hex()), 'duplicate') # valid diff --git a/test/functional/mining_getblocktemplate_longpoll.py b/test/functional/mining_getblocktemplate_longpoll.py index 4893667022..e03a793332 100755 --- a/test/functional/mining_getblocktemplate_longpoll.py +++ b/test/functional/mining_getblocktemplate_longpoll.py @@ -11,6 +11,7 @@ import threading + class LongpollThread(threading.Thread): def __init__(self, node): threading.Thread.__init__(self) @@ -24,6 +25,7 @@ def __init__(self, node): def run(self): self.node.getblocktemplate({'longpollid': self.longpollid, 'rules': ['segwit']}) + class GetBlockTemplateLPTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 @@ -71,5 +73,6 @@ def run_test(self): thr.join(60 + 20) assert not thr.is_alive() + if __name__ == '__main__': GetBlockTemplateLPTest().main() diff --git a/test/functional/mining_prioritisetransaction.py b/test/functional/mining_prioritisetransaction.py index ac780175ed..a6038f6bac 100755 --- a/test/functional/mining_prioritisetransaction.py +++ b/test/functional/mining_prioritisetransaction.py @@ -8,7 +8,9 @@ from test_framework.messages import COIN, MAX_BLOCK_BASE_SIZE from test_framework.test_framework import DefiTestFramework -from test_framework.util import assert_equal, assert_raises_rpc_error, create_confirmed_utxos, create_lots_of_big_transactions, gen_return_txouts +from test_framework.util import assert_equal, assert_raises_rpc_error, create_confirmed_utxos, \ + create_lots_of_big_transactions, gen_return_txouts + class PrioritiseTransactionTest(DefiTestFramework): def set_test_params(self): @@ -32,23 +34,31 @@ def run_test(self): assert_raises_rpc_error(-1, "prioritisetransaction", self.nodes[0].prioritisetransaction, '', 0, 0, 0) # Test `prioritisetransaction` invalid `txid` - assert_raises_rpc_error(-8, "txid must be of length 64 (not 3, for 'foo')", self.nodes[0].prioritisetransaction, txid='foo', fee_delta=0) - assert_raises_rpc_error(-8, "txid must be hexadecimal string (not 'Zd1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000')", self.nodes[0].prioritisetransaction, txid='Zd1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000', fee_delta=0) + assert_raises_rpc_error(-8, "txid must be of length 64 (not 3, for 'foo')", self.nodes[0].prioritisetransaction, + txid='foo', fee_delta=0) + assert_raises_rpc_error(-8, + "txid must be hexadecimal string (not 'Zd1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000')", + self.nodes[0].prioritisetransaction, + txid='Zd1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000', fee_delta=0) # Test `prioritisetransaction` invalid `dummy` txid = '1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000' - assert_raises_rpc_error(-1, "JSON value is not a number as expected", self.nodes[0].prioritisetransaction, txid, 'foo', 0) - assert_raises_rpc_error(-8, "Priority is no longer supported, dummy argument to prioritisetransaction must be 0.", self.nodes[0].prioritisetransaction, txid, 1, 0) + assert_raises_rpc_error(-1, "JSON value is not a number as expected", self.nodes[0].prioritisetransaction, txid, + 'foo', 0) + assert_raises_rpc_error(-8, + "Priority is no longer supported, dummy argument to prioritisetransaction must be 0.", + self.nodes[0].prioritisetransaction, txid, 1, 0) # Test `prioritisetransaction` invalid `fee_delta` - assert_raises_rpc_error(-1, "JSON value is not an integer as expected", self.nodes[0].prioritisetransaction, txid=txid, fee_delta='foo') + assert_raises_rpc_error(-1, "JSON value is not an integer as expected", self.nodes[0].prioritisetransaction, + txid=txid, fee_delta='foo') self.txouts = gen_return_txouts() self.relayfee = self.nodes[0].getnetworkinfo()['relayfee'] - utxo_count = 90*8 # 90 for original 1M block + utxo_count = 90 * 8 # 90 for original 1M block utxos = create_confirmed_utxos(self.relayfee, self.nodes[0], utxo_count) - base_fee = self.relayfee*100 # our transactions are smaller than 100kb + base_fee = self.relayfee * 100 # our transactions are smaller than 100kb txids = [] # Create 3 batches of transactions at 3 different fee rate levels @@ -57,7 +67,8 @@ def run_test(self): txids.append([]) start_range = i * range_size end_range = start_range + range_size - txids[i] = create_lots_of_big_transactions(self.nodes[0], self.txouts, utxos[start_range:end_range], end_range - start_range, (i+1)*base_fee) + txids[i] = create_lots_of_big_transactions(self.nodes[0], self.txouts, utxos[start_range:end_range], + end_range - start_range, (i + 1) * base_fee) # Make sure that the size of each group of transactions exceeds # MAX_BLOCK_BASE_SIZE -- otherwise the test needs to be revised to create @@ -72,7 +83,7 @@ def run_test(self): # add a fee delta to something in the cheapest bucket and make sure it gets mined # also check that a different entry in the cheapest bucket is NOT mined - self.nodes[0].prioritisetransaction(txid=txids[0][0], fee_delta=int(3*base_fee*COIN)) + self.nodes[0].prioritisetransaction(txid=txids[0][0], fee_delta=int(3 * base_fee * COIN)) self.nodes[0].generate(1) @@ -91,7 +102,7 @@ def run_test(self): # Add a prioritisation before a tx is in the mempool (de-prioritising a # high-fee transaction so that it's now low fee). - self.nodes[0].prioritisetransaction(txid=high_fee_tx, fee_delta=-int(2*base_fee*COIN)) + self.nodes[0].prioritisetransaction(txid=high_fee_tx, fee_delta=-int(2 * base_fee * COIN)) # Add everything back to mempool self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash()) @@ -122,7 +133,7 @@ def run_test(self): inputs = [] outputs = {} - inputs.append({"txid" : utxo["txid"], "vout" : utxo["vout"]}) + inputs.append({"txid": utxo["txid"], "vout": utxo["vout"]}) outputs[self.nodes[0].getnewaddress()] = utxo["amount"] raw_tx = self.nodes[0].createrawtransaction(inputs, outputs) tx_hex = self.nodes[0].signrawtransactionwithwallet(raw_tx)["hex"] @@ -135,7 +146,7 @@ def run_test(self): # This is a less than 1000-byte transaction, so just set the fee # to be the minimum for a 1000-byte transaction and check that it is # accepted. - self.nodes[0].prioritisetransaction(txid=tx_id, fee_delta=int(self.relayfee*COIN)) + self.nodes[0].prioritisetransaction(txid=tx_id, fee_delta=int(self.relayfee * COIN)) self.log.info("Assert that prioritised free transaction is accepted to mempool") assert_equal(self.nodes[0].sendrawtransaction(tx_hex), tx_id) @@ -146,11 +157,12 @@ def run_test(self): mock_time = int(time.time()) self.nodes[0].setmocktime(mock_time) template = self.nodes[0].getblocktemplate({'rules': ['segwit']}) - self.nodes[0].prioritisetransaction(txid=tx_id, fee_delta=-int(self.relayfee*COIN)) - self.nodes[0].setmocktime(mock_time+10) + self.nodes[0].prioritisetransaction(txid=tx_id, fee_delta=-int(self.relayfee * COIN)) + self.nodes[0].setmocktime(mock_time + 10) new_template = self.nodes[0].getblocktemplate({'rules': ['segwit']}) assert template != new_template + if __name__ == '__main__': PrioritiseTransactionTest().main() diff --git a/test/functional/p2p_compactblocks.py b/test/functional/p2p_compactblocks.py index 88f1c5842b..6d3f16cf29 100755 --- a/test/functional/p2p_compactblocks.py +++ b/test/functional/p2p_compactblocks.py @@ -10,12 +10,17 @@ import random from test_framework.blocktools import create_block, create_coinbase, add_witness_commitment -from test_framework.messages import BlockTransactions, BlockTransactionsRequest, calculate_shortid, CBlock, CBlockHeader, CInv, COutPoint, CTransaction, CTxIn, CTxInWitness, CTxOut, FromHex, HeaderAndShortIDs, msg_no_witness_block, msg_no_witness_blocktxn, msg_cmpctblock, msg_getblocktxn, msg_getdata, msg_getheaders, msg_headers, msg_inv, msg_sendcmpct, msg_sendheaders, msg_tx, msg_block, msg_blocktxn, MSG_WITNESS_FLAG, NODE_NETWORK, P2PHeaderAndShortIDs, PrefilledTransaction, ser_uint256, ToHex +from test_framework.messages import BlockTransactions, BlockTransactionsRequest, calculate_shortid, CBlock, \ + CBlockHeader, CInv, COutPoint, CTransaction, CTxIn, CTxInWitness, CTxOut, FromHex, HeaderAndShortIDs, \ + msg_no_witness_block, msg_no_witness_blocktxn, msg_cmpctblock, msg_getblocktxn, msg_getdata, msg_getheaders, \ + msg_headers, msg_inv, msg_sendcmpct, msg_sendheaders, msg_tx, msg_block, msg_blocktxn, MSG_WITNESS_FLAG, \ + NODE_NETWORK, P2PHeaderAndShortIDs, PrefilledTransaction, ser_uint256, ToHex from test_framework.mininode import mininode_lock, P2PInterface from test_framework.script import CScript, OP_TRUE, OP_DROP from test_framework.test_framework import DefiTestFramework from test_framework.util import assert_equal, wait_until + # TestP2PConn: A peer we use to send messages to defid, and store responses. class TestP2PConn(P2PInterface): def __init__(self, cmpct_version): @@ -81,6 +86,7 @@ def request_headers_and_sync(self, locator, hashstop=0): def wait_for_block_announcement(self, block_hash, timeout=30): def received_hash(): return (block_hash in self.announced_blockhashes) + wait_until(received_hash, timeout=timeout, lock=mininode_lock) def send_await_disconnect(self, message, timeout=30): @@ -91,6 +97,7 @@ def send_await_disconnect(self, message, timeout=30): self.send_message(message) wait_until(lambda: not self.is_connected, timeout=timeout, lock=mininode_lock) + class CompactBlocksTest(DefiTestFramework): def set_test_params(self): self.setup_clean_chain = True @@ -137,7 +144,6 @@ def make_utxos(self): assert_equal(int(self.nodes[0].getbestblockhash(), 16), block2.sha256) self.utxos.extend([[tx.sha256, i, out_value] for i in range(10)]) - # Test "sendcmpct" (between peers preferring the same version): # - No compact block announcements unless sendcmpct is sent. # - If sendcmpct is sent with version > preferred_version, the message is ignored. @@ -154,6 +160,7 @@ def test_sendcmpct(self, test_node, old_node=None): # Make sure we get a SENDCMPCT message from our peer def received_sendcmpct(): return (len(test_node.last_sendcmpct) > 0) + wait_until(received_sendcmpct, timeout=30, lock=mininode_lock) with mininode_lock: # Check that the first version received is the preferred one @@ -180,7 +187,8 @@ def check_announcement_of_new_block(node, peer, predicate): # Try one more time, this time after requesting headers. test_node.request_headers_and_sync(locator=[tip]) - check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" not in p.last_message and "inv" in p.last_message) + check_announcement_of_new_block(node, test_node, + lambda p: "cmpctblock" not in p.last_message and "inv" in p.last_message) # Test a few ways of using sendcmpct that should NOT # result in compact block announcements. @@ -229,7 +237,8 @@ def check_announcement_of_new_block(node, peer, predicate): sendcmpct.version = preferred_version sendcmpct.announce = False test_node.send_and_ping(sendcmpct) - check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" not in p.last_message and "headers" in p.last_message) + check_announcement_of_new_block(node, test_node, + lambda p: "cmpctblock" not in p.last_message and "headers" in p.last_message) if old_node is not None: # Verify that a peer using an older protocol version can receive @@ -569,7 +578,8 @@ def test_incorrect_blocktxn_response(self, test_node): # We should receive a getdata request wait_until(lambda: "getdata" in test_node.last_message, timeout=10, lock=mininode_lock) assert_equal(len(test_node.last_message["getdata"].inv), 1) - assert test_node.last_message["getdata"].inv[0].type == 2 or test_node.last_message["getdata"].inv[0].type == 2 | MSG_WITNESS_FLAG + assert test_node.last_message["getdata"].inv[0].type == 2 or test_node.last_message["getdata"].inv[ + 0].type == 2 | MSG_WITNESS_FLAG assert_equal(test_node.last_message["getdata"].inv[0].hash, block.sha256) # Deliver the block diff --git a/test/functional/p2p_disconnect_ban.py b/test/functional/p2p_disconnect_ban.py index 62772d2c13..22a99399c5 100755 --- a/test/functional/p2p_disconnect_ban.py +++ b/test/functional/p2p_disconnect_ban.py @@ -13,6 +13,7 @@ wait_until, ) + class DisconnectBanTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 @@ -39,7 +40,8 @@ def run_test(self): self.log.info("setban: fail to ban an invalid subnet") assert_raises_rpc_error(-30, "Error: Invalid IP/Subnet", self.nodes[1].setban, "127.0.0.1/42", "add") - assert_equal(len(self.nodes[1].listbanned()), 1) # still only one banned ip because 127.0.0.1 is within the range of 127.0.0.0/24 + assert_equal(len(self.nodes[1].listbanned()), + 1) # still only one banned ip because 127.0.0.1 is within the range of 127.0.0.0/24 self.log.info("setban remove: fail to unban a non-banned subnet") assert_raises_rpc_error(-30, "Error: Unban failed", self.nodes[1].setban, "127.0.0.1", "remove") @@ -82,10 +84,12 @@ def run_test(self): self.log.info("disconnectnode: fail to disconnect when calling with address and nodeid") address1 = self.nodes[0].getpeerinfo()[0]['addr'] node1 = self.nodes[0].getpeerinfo()[0]['addr'] - assert_raises_rpc_error(-32602, "Only one of address and nodeid should be provided.", self.nodes[0].disconnectnode, address=address1, nodeid=node1) + assert_raises_rpc_error(-32602, "Only one of address and nodeid should be provided.", + self.nodes[0].disconnectnode, address=address1, nodeid=node1) self.log.info("disconnectnode: fail to disconnect when calling with junk address") - assert_raises_rpc_error(-29, "Node not found in connected nodes", self.nodes[0].disconnectnode, address="221B Baker Street") + assert_raises_rpc_error(-29, "Node not found in connected nodes", self.nodes[0].disconnectnode, + address="221B Baker Street") self.log.info("disconnectnode: successfully disconnect node by address") address1 = self.nodes[0].getpeerinfo()[0]['addr'] @@ -104,5 +108,6 @@ def run_test(self): wait_until(lambda: len(self.nodes[0].getpeerinfo()) == 1, timeout=10) assert not [node for node in self.nodes[0].getpeerinfo() if node['id'] == id1] + if __name__ == '__main__': DisconnectBanTest().main() diff --git a/test/functional/p2p_feefilter.py b/test/functional/p2p_feefilter.py index 7e785f51d2..b8b3d5800f 100755 --- a/test/functional/p2p_feefilter.py +++ b/test/functional/p2p_feefilter.py @@ -15,6 +15,7 @@ def hashToHex(hash): return format(hash, '064x') + # Wait up to 60 secs to see if the testnode has received all the expected invs def allInvsMatch(invsExpected, testnode): for x in range(60): @@ -24,6 +25,7 @@ def allInvsMatch(invsExpected, testnode): time.sleep(1) return False + class TestP2PConn(P2PInterface): def __init__(self): super().__init__() @@ -38,6 +40,7 @@ def clear_invs(self): with mininode_lock: self.txinvs = [] + class FeeFilterTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 @@ -71,7 +74,7 @@ def run_test(self): # Change tx fee rate to 10 sat/byte and test they are no longer received node1.settxfee(Decimal("0.00010000")) [node1.sendtoaddress(node1.getnewaddress(), 1) for x in range(3)] - self.sync_mempools() # must be sure node 0 has received all txs + self.sync_mempools() # must be sure node 0 has received all txs # Send one transaction from node0 that should be received, so that we # we can sync the test on receipt (if node1's txs were relayed, they'd @@ -91,5 +94,6 @@ def run_test(self): assert allInvsMatch(txids, self.nodes[0].p2p) self.nodes[0].p2p.clear_invs() + if __name__ == '__main__': FeeFilterTest().main() diff --git a/test/functional/p2p_fingerprint.py b/test/functional/p2p_fingerprint.py index bd8d781749..a5d4e2b625 100755 --- a/test/functional/p2p_fingerprint.py +++ b/test/functional/p2p_fingerprint.py @@ -25,6 +25,7 @@ wait_until, ) + class P2PFingerprintTest(DefiTestFramework): def set_test_params(self): self.setup_clean_chain = True @@ -110,7 +111,7 @@ def run_test(self): wait_until(test_function, timeout=3) # Longest chain is extended so stale is much older than chain tip - self.nodes[0].set_mocktime(int(time.time())) # NOT 0 NOR None, but current time + self.nodes[0].set_mocktime(int(time.time())) # NOT 0 NOR None, but current time tip = self.nodes[0].generate(1)[0] assert_equal(self.nodes[0].getblockcount(), 14) @@ -144,5 +145,6 @@ def run_test(self): test_function = lambda: self.last_header_equals(block_hash, node0) wait_until(test_function, timeout=3) + if __name__ == '__main__': P2PFingerprintTest().main() diff --git a/test/functional/p2p_invalid_block.py b/test/functional/p2p_invalid_block.py index 9f9982210e..0aafc98a22 100755 --- a/test/functional/p2p_invalid_block.py +++ b/test/functional/p2p_invalid_block.py @@ -18,6 +18,7 @@ from test_framework.test_framework import DefiTestFramework from test_framework.util import assert_equal + class InvalidBlockRequestTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 diff --git a/test/functional/p2p_invalid_locator.py b/test/functional/p2p_invalid_locator.py index f164402c47..41127a18cb 100755 --- a/test/functional/p2p_invalid_locator.py +++ b/test/functional/p2p_invalid_locator.py @@ -25,14 +25,16 @@ def run_test(self): for msg in [msg_getheaders(), msg_getblocks()]: self.log.info('Wait for disconnect when sending {} hashes in locator'.format(MAX_LOCATOR_SZ + 1)) node.add_p2p_connection(P2PInterface()) - msg.locator.vHave = [int(node.getblockhash(i - 1), 16) for i in range(block_count, block_count - (MAX_LOCATOR_SZ + 1), -1)] + msg.locator.vHave = [int(node.getblockhash(i - 1), 16) for i in + range(block_count, block_count - (MAX_LOCATOR_SZ + 1), -1)] node.p2p.send_message(msg) node.p2p.wait_for_disconnect() node.disconnect_p2ps() self.log.info('Wait for response when sending {} hashes in locator'.format(MAX_LOCATOR_SZ)) node.add_p2p_connection(P2PInterface()) - msg.locator.vHave = [int(node.getblockhash(i - 1), 16) for i in range(block_count, block_count - (MAX_LOCATOR_SZ), -1)] + msg.locator.vHave = [int(node.getblockhash(i - 1), 16) for i in + range(block_count, block_count - (MAX_LOCATOR_SZ), -1)] node.p2p.send_message(msg) if type(msg) == msg_getheaders: node.p2p.wait_for_header(int(node.getbestblockhash(), 16)) diff --git a/test/functional/p2p_invalid_messages.py b/test/functional/p2p_invalid_messages.py index 24fd93c3c4..8289137a04 100755 --- a/test/functional/p2p_invalid_messages.py +++ b/test/functional/p2p_invalid_messages.py @@ -161,12 +161,13 @@ async def swap_magic_bytes(): def test_checksum(self): conn = self.nodes[0].add_p2p_connection(P2PDataStore()) - with self.nodes[0].assert_debug_log(['ProcessMessages(badmsg, 2 bytes): CHECKSUM ERROR expected 78df0a04 was ffffffff']): + with self.nodes[0].assert_debug_log( + ['ProcessMessages(badmsg, 2 bytes): CHECKSUM ERROR expected 78df0a04 was ffffffff']): msg = conn.build_message(msg_unrecognized(str_data="d")) cut_len = ( - 4 + # magic - 12 + # command - 4 #len + 4 + # magic + 12 + # command + 4 # len ) # modify checksum msg = msg[:cut_len] + b'\xff' * 4 + msg[cut_len + 4:] @@ -179,8 +180,8 @@ def test_size(self): with self.nodes[0].assert_debug_log(['']): msg = conn.build_message(msg_unrecognized(str_data="d")) cut_len = ( - 4 + # magic - 12 # command + 4 + # magic + 12 # command ) # modify len to MAX_DESER_SIZE + 1 msg = msg[:cut_len] + struct.pack(" MAX_BLOCK_BASE_SIZE # TODO: repeat this test with a block that can be relayed @@ -929,7 +945,8 @@ def test_witness_block_size(self): while additional_bytes > 0: # Add some more bytes to each input until we hit MAX_BLOCK_BASE_SIZE+1 extra_bytes = min(additional_bytes + 1, 55) - block.vtx[-1].wit.vtxinwit[int(i / (2 * NUM_DROPS))].scriptWitness.stack[i % (2 * NUM_DROPS)] = b'a' * (filler_size + extra_bytes) + block.vtx[-1].wit.vtxinwit[int(i / (2 * NUM_DROPS))].scriptWitness.stack[i % (2 * NUM_DROPS)] = b'a' * ( + filler_size + extra_bytes) additional_bytes -= extra_bytes i += 1 @@ -1398,7 +1415,8 @@ def test_segwit_versions(self): tx3.rehash() # Spending a higher version witness output is not allowed by policy, # even with fRequireStandard=false. - test_transaction_acceptance(self.nodes[0], self.test_node, tx3, with_witness=True, accepted=False, reason="reserved for soft-fork upgrades") + test_transaction_acceptance(self.nodes[0], self.test_node, tx3, with_witness=True, accepted=False, + reason="reserved for soft-fork upgrades") # Building a block with the transaction must be valid, however. block = self.build_next_block() @@ -1491,7 +1509,8 @@ def test_uncompressed_pubkey(self): tx2.rehash() # Should fail policy test. - test_transaction_acceptance(self.nodes[0], self.test_node, tx2, True, False, 'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)') + test_transaction_acceptance(self.nodes[0], self.test_node, tx2, True, False, + 'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)') # But passes consensus. block = self.build_next_block() self.update_witness_block_with_transactions(block, [tx2]) @@ -1511,7 +1530,8 @@ def test_uncompressed_pubkey(self): sign_p2pk_witness_input(witness_program, tx3, 0, SIGHASH_ALL, tx2.vout[0].nValue, key) # Should fail policy test. - test_transaction_acceptance(self.nodes[0], self.test_node, tx3, True, False, 'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)') + test_transaction_acceptance(self.nodes[0], self.test_node, tx3, True, False, + 'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)') # But passes consensus. block = self.build_next_block() self.update_witness_block_with_transactions(block, [tx3]) @@ -1528,7 +1548,8 @@ def test_uncompressed_pubkey(self): sign_p2pk_witness_input(witness_program, tx4, 0, SIGHASH_ALL, tx3.vout[0].nValue, key) # Should fail policy test. - test_transaction_acceptance(self.nodes[0], self.test_node, tx4, True, False, 'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)') + test_transaction_acceptance(self.nodes[0], self.test_node, tx4, True, False, + 'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)') block = self.build_next_block() self.update_witness_block_with_transactions(block, [tx4]) test_witness_block(self.nodes[0], self.test_node, block, accepted=True) @@ -1909,7 +1930,8 @@ def test_witness_sigops(self): """Test sigop counting is correct inside witnesses.""" # Keep this under MAX_OPS_PER_SCRIPT (201) - witness_program = CScript([OP_TRUE, OP_IF, OP_TRUE, OP_ELSE] + [OP_CHECKMULTISIG] * 5 + [OP_CHECKSIG] * 193 + [OP_ENDIF]) + witness_program = CScript( + [OP_TRUE, OP_IF, OP_TRUE, OP_ELSE] + [OP_CHECKMULTISIG] * 5 + [OP_CHECKSIG] * 193 + [OP_ENDIF]) witness_hash = sha256(witness_program) script_pubkey = CScript([OP_0, witness_hash]) @@ -1926,13 +1948,15 @@ def test_witness_sigops(self): # This script, when spent with the first # N(=MAX_SIGOP_COST//sigops_per_script) outputs of our transaction, # would push us just over the block sigop limit. - witness_program_toomany = CScript([OP_TRUE, OP_IF, OP_TRUE, OP_ELSE] + [OP_CHECKSIG] * (extra_sigops_available + 1) + [OP_ENDIF]) + witness_program_toomany = CScript( + [OP_TRUE, OP_IF, OP_TRUE, OP_ELSE] + [OP_CHECKSIG] * (extra_sigops_available + 1) + [OP_ENDIF]) witness_hash_toomany = sha256(witness_program_toomany) script_pubkey_toomany = CScript([OP_0, witness_hash_toomany]) # If we spend this script instead, we would exactly reach our sigop # limit (for witness sigops). - witness_program_justright = CScript([OP_TRUE, OP_IF, OP_TRUE, OP_ELSE] + [OP_CHECKSIG] * (extra_sigops_available) + [OP_ENDIF]) + witness_program_justright = CScript( + [OP_TRUE, OP_IF, OP_TRUE, OP_ELSE] + [OP_CHECKSIG] * (extra_sigops_available) + [OP_ENDIF]) witness_hash_justright = sha256(witness_program_justright) script_pubkey_justright = CScript([OP_0, witness_hash_justright]) @@ -2035,9 +2059,11 @@ def serialize(self): self.nodes[0].generate(1) unspent = next(u for u in self.nodes[0].listunspent() if u['spendable'] and u['address'].startswith('bcrt')) - raw = self.nodes[0].createrawtransaction([{"txid": unspent['txid'], "vout": unspent['vout']}], {self.nodes[0].getnewaddress(): 1}) + raw = self.nodes[0].createrawtransaction([{"txid": unspent['txid'], "vout": unspent['vout']}], + {self.nodes[0].getnewaddress(): 1}) tx = FromHex(CTransaction(), raw) - assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].decoderawtransaction, serialize_with_bogus_witness(tx).hex()) + assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].decoderawtransaction, + serialize_with_bogus_witness(tx).hex()) with self.nodes[0].assert_debug_log(['Superfluous witness record']): self.nodes[0].p2p.send_message(msg_bogus_tx(tx)) self.nodes[0].p2p.sync_with_ping() @@ -2045,7 +2071,8 @@ def serialize(self): assert raw['complete'] raw = raw['hex'] tx = FromHex(CTransaction(), raw) - assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].decoderawtransaction, serialize_with_bogus_witness(tx).hex()) + assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].decoderawtransaction, + serialize_with_bogus_witness(tx).hex()) with self.nodes[0].assert_debug_log(['Unknown transaction optional data']): self.nodes[0].p2p.send_message(msg_bogus_tx(tx)) self.nodes[0].p2p.sync_with_ping() diff --git a/test/functional/p2p_segwit2.py b/test/functional/p2p_segwit2.py index 9c3d1430f3..82d9367388 100755 --- a/test/functional/p2p_segwit2.py +++ b/test/functional/p2p_segwit2.py @@ -60,16 +60,21 @@ SEGWIT_HEIGHT = 120 + class UTXO(): """Used to keep track of anyone-can-spend outputs that we can use in the tests.""" + def __init__(self, sha256, n, value): self.sha256 = sha256 self.n = n self.nValue = value + def get_p2pkh_script(pubkeyhash): """Get the script associated with a P2PKH.""" - return CScript([CScriptOp(OP_DUP), CScriptOp(OP_HASH160), pubkeyhash, CScriptOp(OP_EQUALVERIFY), CScriptOp(OP_CHECKSIG)]) + return CScript( + [CScriptOp(OP_DUP), CScriptOp(OP_HASH160), pubkeyhash, CScriptOp(OP_EQUALVERIFY), CScriptOp(OP_CHECKSIG)]) + def sign_p2pk_witness_input(script, tx_to, in_idx, hashtype, value, key): """Add signature for a P2PK witness program.""" @@ -78,6 +83,7 @@ def sign_p2pk_witness_input(script, tx_to, in_idx, hashtype, value, key): tx_to.wit.vtxinwit[in_idx].scriptWitness.stack = [signature, script] tx_to.rehash() + def get_virtual_size(witness_block): """Calculate the virtual size of a witness block. @@ -88,6 +94,7 @@ def get_virtual_size(witness_block): vsize = int((3 * base_size + total_size + 3) / 4) return vsize + def test_transaction_acceptance(node, p2p, tx, with_witness, accepted, reason=None): """Send a transaction to the node and check that it's accepted to the mempool @@ -99,6 +106,7 @@ def test_transaction_acceptance(node, p2p, tx, with_witness, accepted, reason=No p2p.sync_with_ping() assert_equal(tx.hash in node.getrawmempool(), accepted) + def test_witness_block(node, p2p, block, accepted, with_witness=True, reason=None): """Send a block to the node and check that it's accepted @@ -151,6 +159,7 @@ def request_block(self, blockhash, inv_type, timeout=60): self.wait_for_block(blockhash, timeout) return self.last_message["block"].block + class SegWitTest2(DefiTestFramework): def set_test_params(self): self.setup_clean_chain = True @@ -214,6 +223,7 @@ def run_test(self): def subtest(func): # noqa: N805 """Wraps the subtests for logging and state assertions.""" + def func_wrapper(self, *args, **kwargs): self.log.info("Subtest: {} (Segwit active = {})".format(func.__name__, self.segwit_active)) func(self, *args, **kwargs) @@ -313,7 +323,8 @@ def test_witness_block_size(self): while additional_bytes > 0: # Add some more bytes to each input until we hit MAX_BLOCK_BASE_SIZE+1 extra_bytes = min(additional_bytes + 1, 55) - block.vtx[-1].wit.vtxinwit[int(i / (2 * NUM_DROPS))].scriptWitness.stack[i % (2 * NUM_DROPS)] = b'a' * (filler_size + extra_bytes) + block.vtx[-1].wit.vtxinwit[int(i / (2 * NUM_DROPS))].scriptWitness.stack[i % (2 * NUM_DROPS)] = b'a' * ( + filler_size + extra_bytes) additional_bytes -= extra_bytes i += 1 diff --git a/test/functional/p2p_sendheaders.py b/test/functional/p2p_sendheaders.py index fedb5b1b7b..090bd887f2 100755 --- a/test/functional/p2p_sendheaders.py +++ b/test/functional/p2p_sendheaders.py @@ -110,6 +110,7 @@ DIRECT_FETCH_RESPONSE_TIME = 0.05 + class BaseNode(P2PInterface): def __init__(self): super().__init__() @@ -150,7 +151,8 @@ def wait_for_getdata(self, hash_list, timeout=60): if hash_list == []: return - test_function = lambda: "getdata" in self.last_message and [x.hash for x in self.last_message["getdata"].inv] == hash_list + test_function = lambda: "getdata" in self.last_message and [x.hash for x in + self.last_message["getdata"].inv] == hash_list wait_until(test_function, timeout=timeout, lock=mininode_lock) def wait_for_block_announcement(self, block_hash, timeout=60): @@ -162,12 +164,12 @@ def on_message(self, message): with mininode_lock: try: command = message.command.decode('ascii') - if command == 'inv' and message.inv[-1].type == 5: # 'anchorauth' - ignore anchor auths!!!! + if command == 'inv' and message.inv[-1].type == 5: # 'anchorauth' - ignore anchor auths!!!! return self.message_count[command] += 1 self.last_message[command] = message getattr(self, 'on_' + command)(message) - except: + except Exception: print("ERROR delivering %s (%s)" % (repr(message), sys.exc_info()[0])) raise @@ -191,7 +193,6 @@ def clear_block_announcements(self): self.last_message.pop("headers", None) self.recent_headers_announced = [] - def check_last_headers_announcement(self, headers): """Test whether the last headers announcements received are right. Headers may be announced across more than one message.""" @@ -218,6 +219,7 @@ def check_last_inv_announcement(self, inv): self.block_announced = False self.last_message.pop("inv", None) + class SendHeadersTest(DefiTestFramework): def set_test_params(self): self.setup_clean_chain = True @@ -228,7 +230,7 @@ def mine_blocks(self, count): # Clear out block announcements from each p2p listener [x.clear_block_announcements() for x in self.nodes[0].p2ps] - self.nodes[0].pullup_mocktime() # Need to! Cause 'generate' interleaved with manual block's creation/sending + self.nodes[0].pullup_mocktime() # Need to! Cause 'generate' interleaved with manual block's creation/sending self.nodes[0].generate(count) return int(self.nodes[0].getbestblockhash(), 16) @@ -395,7 +397,8 @@ def test_nonnull_locators(self, test_node, inv_node): self.log.info("Part 2: success!") - self.log.info("Part 3: headers announcements can stop after large reorg, and resume after headers/inv from peer...") + self.log.info( + "Part 3: headers announcements can stop after large reorg, and resume after headers/inv from peer...") # PART 3. Headers announcements can stop after large reorg, and resume after # getheaders or inv from peer. @@ -618,5 +621,6 @@ def test_nonnull_locators(self, test_node, inv_node): # throughout the test assert "getdata" not in inv_node.last_message + if __name__ == '__main__': SendHeadersTest().main() diff --git a/test/functional/p2p_timeouts.py b/test/functional/p2p_timeouts.py index e5636791f2..2417427894 100755 --- a/test/functional/p2p_timeouts.py +++ b/test/functional/p2p_timeouts.py @@ -27,11 +27,13 @@ from test_framework.mininode import P2PInterface from test_framework.test_framework import DefiTestFramework + class TestP2PConn(P2PInterface): def on_version(self, message): # Don't send a verack in response pass + class TimeoutsTest(DefiTestFramework): def set_test_params(self): self.setup_clean_chain = True @@ -81,5 +83,6 @@ def run_test(self): assert not no_version_node.is_connected assert not no_send_node.is_connected + if __name__ == '__main__': TimeoutsTest().main() diff --git a/test/functional/p2p_tx_download.py b/test/functional/p2p_tx_download.py index 00dfa50b3f..eea87d9f58 100755 --- a/test/functional/p2p_tx_download.py +++ b/test/functional/p2p_tx_download.py @@ -122,7 +122,7 @@ def test_inv_block(self): # * the first time it is re-requested from the outbound peer, plus # * 2 seconds to avoid races timeout = 2 + (MAX_GETDATA_RANDOM_DELAY + INBOUND_PEER_TX_DELAY) + ( - GETDATA_TX_INTERVAL + MAX_GETDATA_RANDOM_DELAY) + GETDATA_TX_INTERVAL + MAX_GETDATA_RANDOM_DELAY) self.log.info("Tx should be received at node 1 after {} seconds".format(timeout)) self.sync_mempools(timeout=timeout) diff --git a/test/functional/p2p_unrequested_blocks.py b/test/functional/p2p_unrequested_blocks.py index 551da113e8..2c60446eab 100755 --- a/test/functional/p2p_unrequested_blocks.py +++ b/test/functional/p2p_unrequested_blocks.py @@ -143,7 +143,7 @@ def run_test(self): self.log.info("Second height 2 block accepted, but not reorg'ed to") # 4b. Now send another block that builds on the forking chain. - block_h3 = create_block(block_h2f.sha256, create_coinbase(3), block_h2f.nTime+1) + block_h3 = create_block(block_h2f.sha256, create_coinbase(3), block_h2f.nTime + 1) block_h3.solve() test_node.send_message(msg_block(block_h3)) @@ -167,7 +167,7 @@ def run_test(self): tip = block_h3 all_blocks = [] for i in range(288): - next_block = create_block(tip.sha256, create_coinbase(i + 4), tip.nTime+1) + next_block = create_block(tip.sha256, create_coinbase(i + 4), tip.nTime + 1) next_block.solve() all_blocks.append(next_block) tip = next_block @@ -242,16 +242,16 @@ def run_test(self): # 8. Create a chain which is invalid at a height longer than the # current chain, but which has more blocks on top of that - block_289f = create_block(all_blocks[284].sha256, create_coinbase(289), all_blocks[284].nTime+1) + block_289f = create_block(all_blocks[284].sha256, create_coinbase(289), all_blocks[284].nTime + 1) block_289f.solve() - block_290f = create_block(block_289f.sha256, create_coinbase(290), block_289f.nTime+1) + block_290f = create_block(block_289f.sha256, create_coinbase(290), block_289f.nTime + 1) block_290f.solve() - block_291 = create_block(block_290f.sha256, create_coinbase(291), block_290f.nTime+1) + block_291 = create_block(block_290f.sha256, create_coinbase(291), block_290f.nTime + 1) # block_291 spends a coinbase below maturity! block_291.vtx.append(create_tx_with_script(block_290f.vtx[0], 0, script_sig=b"42", amount=1)) block_291.hashMerkleRoot = block_291.calc_merkle_root() block_291.solve() - block_292 = create_block(block_291.sha256, create_coinbase(292), block_291.nTime+1) + block_292 = create_block(block_291.sha256, create_coinbase(292), block_291.nTime + 1) block_292.solve() # Now send all the headers on the chain and enough blocks to trigger reorg @@ -298,7 +298,7 @@ def run_test(self): assert_equal(self.nodes[0].getblock(block_291.hash)["confirmations"], -1) # Now send a new header on the invalid chain, indicating we're forked off, and expect to get disconnected - block_293 = create_block(block_292.sha256, create_coinbase(293), block_292.nTime+1) + block_293 = create_block(block_292.sha256, create_coinbase(293), block_292.nTime + 1) block_293.solve() headers_message = msg_headers() headers_message.headers.append(CBlockHeader(block_293)) @@ -310,5 +310,6 @@ def run_test(self): self.sync_blocks([self.nodes[0], self.nodes[1]]) self.log.info("Successfully synced nodes 1 and 0") + if __name__ == '__main__': AcceptBlockTest().main() diff --git a/test/functional/rpc_bind.py b/test/functional/rpc_bind.py index 4710329057..ad78d29b01 100755 --- a/test/functional/rpc_bind.py +++ b/test/functional/rpc_bind.py @@ -10,6 +10,7 @@ from test_framework.test_framework import DefiTestFramework, SkipTest from test_framework.util import assert_equal, assert_raises_rpc_error, get_rpc_proxy, rpc_port, rpc_url + class RPCBindTest(DefiTestFramework): def set_test_params(self): self.setup_clean_chain = True @@ -22,7 +23,8 @@ def setup_network(self): def add_options(self, parser): parser.add_argument("--ipv4", action='store_true', dest="run_ipv4", help="Run ipv4 tests only", default=False) parser.add_argument("--ipv6", action='store_true', dest="run_ipv6", help="Run ipv6 tests only", default=False) - parser.add_argument("--nonloopback", action='store_true', dest="run_nonloopback", help="Run non-loopback tests only", default=False) + parser.add_argument("--nonloopback", action='store_true', dest="run_nonloopback", + help="Run non-loopback tests only", default=False) def run_bind_test(self, allow_ips, connect_to, addresses, expected): ''' @@ -35,7 +37,7 @@ def run_bind_test(self, allow_ips, connect_to, addresses, expected): base_args = ['-disablewallet', '-nolisten'] if allow_ips: base_args += ['-rpcallowip=' + x for x in allow_ips] - binds = ['-rpcbind='+addr for addr in addresses] + binds = ['-rpcbind=' + addr for addr in addresses] self.nodes[0].rpchost = connect_to self.start_node(0, base_args + binds) pid = self.nodes[0].process.pid @@ -50,12 +52,14 @@ def run_allowip_test(self, allow_ips, rpchost, rpcport): self.log.info("Allow IP test for %s:%d" % (rpchost, rpcport)) node_args = \ ['-disablewallet', '-nolisten'] + \ - ['-rpcallowip='+x for x in allow_ips] + \ - ['-rpcbind='+addr for addr in ['127.0.0.1', "%s:%d" % (rpchost, rpcport)]] # Bind to localhost as well so start_nodes doesn't hang + ['-rpcallowip=' + x for x in allow_ips] + \ + ['-rpcbind=' + addr for addr in + ['127.0.0.1', "%s:%d" % (rpchost, rpcport)]] # Bind to localhost as well so start_nodes doesn't hang self.nodes[0].rpchost = None self.start_nodes([node_args]) # connect to node through non-loopback interface - node = get_rpc_proxy(rpc_url(self.nodes[0].datadir, 0, self.chain, "%s:%d" % (rpchost, rpcport)), 0, coveragedir=self.options.coveragedir) + node = get_rpc_proxy(rpc_url(self.nodes[0].datadir, 0, self.chain, "%s:%d" % (rpchost, rpcport)), 0, + coveragedir=self.options.coveragedir) node.getnetworkinfo() self.stop_nodes() @@ -75,7 +79,7 @@ def run_test(self): self.log.info("Check for non-loopback interface") self.non_loopback_ip = None - for name,ip in all_interfaces(): + for name, ip in all_interfaces(): if ip != '127.0.0.1': self.non_loopback_ip = ip break @@ -93,37 +97,39 @@ def _run_loopback_tests(self): if self.options.run_ipv4: # check only IPv4 localhost (explicit) self.run_bind_test(['127.0.0.1'], '127.0.0.1', ['127.0.0.1'], - [('127.0.0.1', self.defaultport)]) + [('127.0.0.1', self.defaultport)]) # check only IPv4 localhost (explicit) with alternative port self.run_bind_test(['127.0.0.1'], '127.0.0.1:32171', ['127.0.0.1:32171'], - [('127.0.0.1', 32171)]) + [('127.0.0.1', 32171)]) # check only IPv4 localhost (explicit) with multiple alternative ports on same host self.run_bind_test(['127.0.0.1'], '127.0.0.1:32171', ['127.0.0.1:32171', '127.0.0.1:32172'], - [('127.0.0.1', 32171), ('127.0.0.1', 32172)]) + [('127.0.0.1', 32171), ('127.0.0.1', 32172)]) else: # check default without rpcallowip (IPv4 and IPv6 localhost) self.run_bind_test(None, '127.0.0.1', [], - [('127.0.0.1', self.defaultport), ('::1', self.defaultport)]) + [('127.0.0.1', self.defaultport), ('::1', self.defaultport)]) # check default with rpcallowip (IPv4 and IPv6 localhost) self.run_bind_test(['127.0.0.1'], '127.0.0.1', [], - [('127.0.0.1', self.defaultport), ('::1', self.defaultport)]) + [('127.0.0.1', self.defaultport), ('::1', self.defaultport)]) # check only IPv6 localhost (explicit) self.run_bind_test(['[::1]'], '[::1]', ['[::1]'], - [('::1', self.defaultport)]) + [('::1', self.defaultport)]) # check both IPv4 and IPv6 localhost (explicit) self.run_bind_test(['127.0.0.1'], '127.0.0.1', ['127.0.0.1', '[::1]'], - [('127.0.0.1', self.defaultport), ('::1', self.defaultport)]) + [('127.0.0.1', self.defaultport), ('::1', self.defaultport)]) def _run_nonloopback_tests(self): self.log.info("Using interface %s for testing" % self.non_loopback_ip) # check only non-loopback interface self.run_bind_test([self.non_loopback_ip], self.non_loopback_ip, [self.non_loopback_ip], - [(self.non_loopback_ip, self.defaultport)]) + [(self.non_loopback_ip, self.defaultport)]) # Check that with invalid rpcallowip, we are denied self.run_allowip_test([self.non_loopback_ip], self.non_loopback_ip, self.defaultport) - assert_raises_rpc_error(-342, "non-JSON HTTP response with '403 Forbidden' from server", self.run_allowip_test, ['1.1.1.1'], self.non_loopback_ip, self.defaultport) + assert_raises_rpc_error(-342, "non-JSON HTTP response with '403 Forbidden' from server", self.run_allowip_test, + ['1.1.1.1'], self.non_loopback_ip, self.defaultport) + if __name__ == '__main__': RPCBindTest().main() diff --git a/test/functional/rpc_blockchain.py b/test/functional/rpc_blockchain.py index 688b71cc04..b467bf76b7 100755 --- a/test/functional/rpc_blockchain.py +++ b/test/functional/rpc_blockchain.py @@ -19,7 +19,7 @@ """ from decimal import Decimal -# import http.client +import http.client import subprocess from test_framework.test_framework import DefiTestFramework @@ -52,7 +52,8 @@ def set_test_params(self): def run_test(self): self.mine_chain() - self.restart_node(0, extra_args=['-stopatheight=207', '-prune=1']) # Set extra args with pruning after rescan is complete + self.restart_node(0, extra_args=['-stopatheight=207', + '-prune=1']) # Set extra args with pruning after rescan is complete self._test_getblockchaininfo() self._test_getchaintxstats() @@ -67,7 +68,7 @@ def run_test(self): def mine_chain(self): self.log.info('Create some old blocks') address = self.nodes[0].get_genesis_keys().ownerAuthAddress - for t in range(TIME_GENESIS_BLOCK+1, TIME_GENESIS_BLOCK + 200 * 600 +1, 600): + for t in range(TIME_GENESIS_BLOCK + 1, TIME_GENESIS_BLOCK + 200 * 600 + 1, 600): # ten-minute steps from genesis block time self.nodes[0].setmocktime(t) self.nodes[0].generatetoaddress(1, address) @@ -169,14 +170,22 @@ def _test_getchaintxstats(self): # Test `getchaintxstats` invalid `nblocks` assert_raises_rpc_error(-1, "JSON value is not an integer as expected", self.nodes[0].getchaintxstats, '') - assert_raises_rpc_error(-8, "Invalid block count: should be between 0 and the block's height - 1", self.nodes[0].getchaintxstats, -1) - assert_raises_rpc_error(-8, "Invalid block count: should be between 0 and the block's height - 1", self.nodes[0].getchaintxstats, self.nodes[0].getblockcount()) + assert_raises_rpc_error(-8, "Invalid block count: should be between 0 and the block's height - 1", + self.nodes[0].getchaintxstats, -1) + assert_raises_rpc_error(-8, "Invalid block count: should be between 0 and the block's height - 1", + self.nodes[0].getchaintxstats, self.nodes[0].getblockcount()) # Test `getchaintxstats` invalid `blockhash` - assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[0].getchaintxstats, blockhash=0) - assert_raises_rpc_error(-8, "blockhash must be of length 64 (not 1, for '0')", self.nodes[0].getchaintxstats, blockhash='0') - assert_raises_rpc_error(-8, "blockhash must be hexadecimal string (not 'ZZZ0000000000000000000000000000000000000000000000000000000000000')", self.nodes[0].getchaintxstats, blockhash='ZZZ0000000000000000000000000000000000000000000000000000000000000') - assert_raises_rpc_error(-5, "Block not found", self.nodes[0].getchaintxstats, blockhash='0000000000000000000000000000000000000000000000000000000000000000') + assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[0].getchaintxstats, + blockhash=0) + assert_raises_rpc_error(-8, "blockhash must be of length 64 (not 1, for '0')", self.nodes[0].getchaintxstats, + blockhash='0') + assert_raises_rpc_error(-8, + "blockhash must be hexadecimal string (not 'ZZZ0000000000000000000000000000000000000000000000000000000000000')", + self.nodes[0].getchaintxstats, + blockhash='ZZZ0000000000000000000000000000000000000000000000000000000000000') + assert_raises_rpc_error(-5, "Block not found", self.nodes[0].getchaintxstats, + blockhash='0000000000000000000000000000000000000000000000000000000000000000') blockhash = self.nodes[0].getblockhash(200) self.nodes[0].invalidateblock(blockhash) assert_raises_rpc_error(-8, "Block is not in main chain", self.nodes[0].getchaintxstats, blockhash=blockhash) @@ -184,7 +193,7 @@ def _test_getchaintxstats(self): chaintxstats = self.nodes[0].getchaintxstats(nblocks=1) # 200 txs plus genesis tx - assert_equal(chaintxstats['txcount'], 201 +8) # +8 due to genesis mn txs + assert_equal(chaintxstats['txcount'], 201 + 8) # +8 due to genesis mn txs # tx rate should be 1 per 10 minutes, or 1/600 # we have to round because of binary math assert_equal(round(chaintxstats['txrate'] * 600, 10), Decimal(1)) @@ -197,7 +206,7 @@ def _test_getchaintxstats(self): chaintxstats = self.nodes[0].getchaintxstats() assert_equal(chaintxstats['time'], b200['time']) - assert_equal(chaintxstats['txcount'], 201 +8) # +8 due to genesis mn txs + assert_equal(chaintxstats['txcount'], 201 + 8) # +8 due to genesis mn txs assert_equal(chaintxstats['window_final_block_hash'], b200_hash) assert_equal(chaintxstats['window_final_block_height'], 200) assert_equal(chaintxstats['window_block_count'], 199) @@ -207,7 +216,7 @@ def _test_getchaintxstats(self): chaintxstats = self.nodes[0].getchaintxstats(blockhash=b1_hash) assert_equal(chaintxstats['time'], b1['time']) - assert_equal(chaintxstats['txcount'], 2 +8) # +8 due to genesis mn txs + assert_equal(chaintxstats['txcount'], 2 + 8) # +8 due to genesis mn txs assert_equal(chaintxstats['window_final_block_hash'], b1_hash) assert_equal(chaintxstats['window_final_block_height'], 1) assert_equal(chaintxstats['window_block_count'], 0) @@ -220,11 +229,11 @@ def _test_gettxoutsetinfo(self): res = node.gettxoutsetinfo() # genesis txs are now taken into account too!!! - assert_equal(res['total_amount'], Decimal('8855.00000000')) # old value '8725.00000000' - assert_equal(res['transactions'], 209) # old value 200 + assert_equal(res['total_amount'], Decimal('8855.00000000')) # old value '8725.00000000' + assert_equal(res['transactions'], 209) # old value 200 assert_equal(res['height'], 200) - assert_equal(res['txouts'], 209) # old value 200 - assert_equal(res['bogosize'], 15669) # old value 15000 + assert_equal(res['txouts'], 209) # old value 200 + assert_equal(res['bogosize'], 15669) # old value 15000 assert_equal(res['bestblock'], node.getblockhash(200)) size = res['disk_size'] assert size > 6400 @@ -237,11 +246,11 @@ def _test_gettxoutsetinfo(self): node.invalidateblock(b1hash) res2 = node.gettxoutsetinfo() - assert_equal(res2['transactions'], 9) # old value 0 - assert_equal(res2['total_amount'], Decimal('130')) # old value 0 + assert_equal(res2['transactions'], 9) # old value 0 + assert_equal(res2['total_amount'], Decimal('130')) # old value 0 assert_equal(res2['height'], 0) - assert_equal(res2['txouts'], 9) # old value 0 - assert_equal(res2['bogosize'], 669), # old value 0 + assert_equal(res2['txouts'], 9) # old value 0 + assert_equal(res2['bogosize'], 669), # old value 0 assert_equal(res2['bestblock'], node.getblockhash(0)) assert_equal(len(res2['hash_serialized_2']), 64) @@ -257,9 +266,13 @@ def _test_gettxoutsetinfo(self): def _test_getblockheader(self): node = self.nodes[0] - assert_raises_rpc_error(-8, "hash must be of length 64 (not 8, for 'nonsense')", node.getblockheader, "nonsense") - assert_raises_rpc_error(-8, "hash must be hexadecimal string (not 'ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844')", node.getblockheader, "ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844") - assert_raises_rpc_error(-5, "Block not found", node.getblockheader, "0cf7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844") + assert_raises_rpc_error(-8, "hash must be of length 64 (not 8, for 'nonsense')", node.getblockheader, + "nonsense") + assert_raises_rpc_error(-8, + "hash must be hexadecimal string (not 'ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844')", + node.getblockheader, "ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844") + assert_raises_rpc_error(-5, "Block not found", node.getblockheader, + "0cf7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844") besthash = node.getbestblockhash() secondbesthash = node.getblockhash(199) @@ -286,7 +299,7 @@ def _test_getdifficulty(self): difficulty = self.nodes[0].getdifficulty() # 1 hash in 2 should be valid, so difficulty should be 1/2**31 # binary => decimal => binary math is why we do this check - assert abs(difficulty * 2**31 - 1) < 0.0001 + assert abs(difficulty * 2 ** 31 - 1) < 0.0001 def _test_getnetworkhashps(self): hashes_per_second = self.nodes[0].getnetworkhashps() @@ -301,7 +314,7 @@ def _test_stopatheight(self): assert_raises(subprocess.TimeoutExpired, lambda: self.nodes[0].process.wait(timeout=3)) try: self.nodes[0].generate(1) - except: # (ConnectionError, http.client.BadStatusLine): # pass on ANY exception + except (ConnectionError, http.client.BadStatusLine): pass # The node already shut down before response self.log.debug('Node should stop at this height...') self.nodes[0].wait_until_stopped() diff --git a/test/functional/rpc_createmultisig.py b/test/functional/rpc_createmultisig.py index 60c8fa1736..371dc341e3 100755 --- a/test/functional/rpc_createmultisig.py +++ b/test/functional/rpc_createmultisig.py @@ -15,6 +15,7 @@ import decimal import itertools + class RpcCreateMultiSigTest(DefiTestFramework): def set_test_params(self): self.setup_clean_chain = True @@ -75,11 +76,13 @@ def run_test(self): def check_addmultisigaddress_errors(self): self.log.info('Check that addmultisigaddress fails when the private keys are missing') addresses = [self.nodes[1].getnewaddress(address_type='legacy') for _ in range(2)] - assert_raises_rpc_error(-5, 'no full public key for address', lambda: self.nodes[0].addmultisigaddress(nrequired=1, keys=addresses)) + assert_raises_rpc_error(-5, 'no full public key for address', + lambda: self.nodes[0].addmultisigaddress(nrequired=1, keys=addresses)) for a in addresses: # Importing all addresses should not change the result self.nodes[0].importaddress(a) - assert_raises_rpc_error(-5, 'no full public key for address', lambda: self.nodes[0].addmultisigaddress(nrequired=1, keys=addresses)) + assert_raises_rpc_error(-5, 'no full public key for address', + lambda: self.nodes[0].addmultisigaddress(nrequired=1, keys=addresses)) def checkbalances(self): node0, node1, node2 = self.nodes @@ -132,7 +135,8 @@ def do_multisig(self): prevtx_err = dict(prevtxs[0]) del prevtx_err["redeemScript"] - assert_raises_rpc_error(-8, "Missing redeemScript/witnessScript", node2.signrawtransactionwithkey, rawtx, self.priv[0:self.nsigs-1], [prevtx_err]) + assert_raises_rpc_error(-8, "Missing redeemScript/witnessScript", node2.signrawtransactionwithkey, rawtx, + self.priv[0:self.nsigs - 1], [prevtx_err]) rawtx2 = node2.signrawtransactionwithkey(rawtx, self.priv[0:self.nsigs - 1], prevtxs) rawtx3 = node2.signrawtransactionwithkey(rawtx2["hex"], [self.priv[-1]], prevtxs) @@ -143,7 +147,8 @@ def do_multisig(self): assert tx in node0.getblock(blk)["tx"] txinfo = node0.getrawtransaction(tx, True, blk) - self.log.info("n/m=%d/%d %s size=%d vsize=%d weight=%d" % (self.nsigs, self.nkeys, self.output_type, txinfo["size"], txinfo["vsize"], txinfo["weight"])) + self.log.info("n/m=%d/%d %s size=%d vsize=%d weight=%d" % ( + self.nsigs, self.nkeys, self.output_type, txinfo["size"], txinfo["vsize"], txinfo["weight"])) if __name__ == '__main__': diff --git a/test/functional/rpc_decodescript.py b/test/functional/rpc_decodescript.py index 2742bd08e6..e2410e2937 100755 --- a/test/functional/rpc_decodescript.py +++ b/test/functional/rpc_decodescript.py @@ -10,6 +10,7 @@ from io import BytesIO + class DecodeScriptTest(DefiTestFramework): def set_test_params(self): self.setup_clean_chain = True @@ -79,7 +80,7 @@ def decodescript_script_pub_key(self): # for our purposes here it does not matter that they are the same even though it is unrealistic. multisig_script = '52' + push_public_key + push_public_key + push_public_key + '53ae' rpc_result = self.nodes[0].decodescript(multisig_script) - assert_equal('2 ' + public_key + ' ' + public_key + ' ' + public_key + ' 3 OP_CHECKMULTISIG', rpc_result['asm']) + assert_equal('2 ' + public_key + ' ' + public_key + ' ' + public_key + ' 3 OP_CHECKMULTISIG', rpc_result['asm']) # multisig in P2WSH multisig_script_hash = sha256(hex_str_to_bytes(multisig_script)).hex() assert_equal('0 ' + multisig_script_hash, rpc_result['segwit']['asm']) @@ -117,7 +118,9 @@ def decodescript_script_pub_key(self): # lock until block 500,000 cltv_script = '63' + push_public_key + 'ad670320a107b17568' + push_public_key + 'ac' rpc_result = self.nodes[0].decodescript(cltv_script) - assert_equal('OP_IF ' + public_key + ' OP_CHECKSIGVERIFY OP_ELSE 500000 OP_CHECKLOCKTIMEVERIFY OP_DROP OP_ENDIF ' + public_key + ' OP_CHECKSIG', rpc_result['asm']) + assert_equal( + 'OP_IF ' + public_key + ' OP_CHECKSIGVERIFY OP_ELSE 500000 OP_CHECKLOCKTIMEVERIFY OP_DROP OP_ENDIF ' + public_key + ' OP_CHECKSIG', + rpc_result['asm']) # CLTV script in P2WSH cltv_script_hash = sha256(hex_str_to_bytes(cltv_script)).hex() assert_equal('0 ' + cltv_script_hash, rpc_result['segwit']['asm']) @@ -135,7 +138,7 @@ def decodescript_script_pub_key(self): # just imagine that the pub keys used below are different. # the purpose of this test is to check that a segwit script is not returned for bare multisig scripts # with an uncompressed pubkey in them. - rpc_result = self.nodes[0].decodescript('52' + push_public_key + push_uncompressed_public_key +'52ae') + rpc_result = self.nodes[0].decodescript('52' + push_public_key + push_uncompressed_public_key + '52ae') assert_equal('2 ' + public_key + ' ' + uncompressed_public_key + ' 2 OP_CHECKMULTISIG', rpc_result['asm']) # uncompressed pubkeys are invalid for checksigs in segwit scripts. # decodescript should not return a P2WPKH equivalent. @@ -168,7 +171,9 @@ def decoderawtransaction_asm_sighashtype(self): # this test case uses a random plain vanilla mainnet transaction with a single P2PKH input and output tx = '0100000001696a20784a2c70143f634e95227dbdfdf0ecd51647052e70854512235f5986ca010000008a47304402207174775824bec6c2700023309a168231ec80b82c6069282f5133e6f11cbb04460220570edc55c7c5da2ca687ebd0372d3546ebc3f810516a002350cac72dfe192dfb014104d3f898e6487787910a690410b7a917ef198905c27fb9d3b0a42da12aceae0544fc7088d239d9a48f2828a15a09e84043001f27cc80d162cb95404e1210161536ffffffff0100e1f505000000001976a914eb6c6e0cdb2d256a32d97b8df1fc75d1920d9bca88ac00000000' rpc_result = self.nodes[0].decoderawtransaction(tx) - assert_equal('304402207174775824bec6c2700023309a168231ec80b82c6069282f5133e6f11cbb04460220570edc55c7c5da2ca687ebd0372d3546ebc3f810516a002350cac72dfe192dfb[ALL] 04d3f898e6487787910a690410b7a917ef198905c27fb9d3b0a42da12aceae0544fc7088d239d9a48f2828a15a09e84043001f27cc80d162cb95404e1210161536', rpc_result['vin'][0]['scriptSig']['asm']) + assert_equal( + '304402207174775824bec6c2700023309a168231ec80b82c6069282f5133e6f11cbb04460220570edc55c7c5da2ca687ebd0372d3546ebc3f810516a002350cac72dfe192dfb[ALL] 04d3f898e6487787910a690410b7a917ef198905c27fb9d3b0a42da12aceae0544fc7088d239d9a48f2828a15a09e84043001f27cc80d162cb95404e1210161536', + rpc_result['vin'][0]['scriptSig']['asm']) # this test case uses a mainnet transaction that has a P2SH input and both P2PKH and P2SH outputs. # it's from James D'Angelo's awesome introductory videos about multisig: https://www.youtube.com/watch?v=zIbUSaZBJgU and https://www.youtube.com/watch?v=OSA1pwlaypc @@ -176,9 +181,13 @@ def decoderawtransaction_asm_sighashtype(self): tx = '01000000018d1f5635abd06e2c7e2ddf58dc85b3de111e4ad6e0ab51bb0dcf5e84126d927300000000fdfe0000483045022100ae3b4e589dfc9d48cb82d41008dc5fa6a86f94d5c54f9935531924602730ab8002202f88cf464414c4ed9fa11b773c5ee944f66e9b05cc1e51d97abc22ce098937ea01483045022100b44883be035600e9328a01b66c7d8439b74db64187e76b99a68f7893b701d5380220225bf286493e4c4adcf928c40f785422572eb232f84a0b83b0dea823c3a19c75014c695221020743d44be989540d27b1b4bbbcfd17721c337cb6bc9af20eb8a32520b393532f2102c0120a1dda9e51a938d39ddd9fe0ebc45ea97e1d27a7cbd671d5431416d3dd87210213820eb3d5f509d7438c9eeecb4157b2f595105e7cd564b3cdbb9ead3da41eed53aeffffffff02611e0000000000001976a914dc863734a218bfe83ef770ee9d41a27f824a6e5688acee2a02000000000017a9142a5edea39971049a540474c6a99edf0aa4074c588700000000' rpc_result = self.nodes[0].decoderawtransaction(tx) assert_equal('8e3730608c3b0bb5df54f09076e196bc292a8e39a78e73b44b6ba08c78f5cbb0', rpc_result['txid']) - assert_equal('0 3045022100ae3b4e589dfc9d48cb82d41008dc5fa6a86f94d5c54f9935531924602730ab8002202f88cf464414c4ed9fa11b773c5ee944f66e9b05cc1e51d97abc22ce098937ea[ALL] 3045022100b44883be035600e9328a01b66c7d8439b74db64187e76b99a68f7893b701d5380220225bf286493e4c4adcf928c40f785422572eb232f84a0b83b0dea823c3a19c75[ALL] 5221020743d44be989540d27b1b4bbbcfd17721c337cb6bc9af20eb8a32520b393532f2102c0120a1dda9e51a938d39ddd9fe0ebc45ea97e1d27a7cbd671d5431416d3dd87210213820eb3d5f509d7438c9eeecb4157b2f595105e7cd564b3cdbb9ead3da41eed53ae', rpc_result['vin'][0]['scriptSig']['asm']) - assert_equal('OP_DUP OP_HASH160 dc863734a218bfe83ef770ee9d41a27f824a6e56 OP_EQUALVERIFY OP_CHECKSIG', rpc_result['vout'][0]['scriptPubKey']['asm']) - assert_equal('OP_HASH160 2a5edea39971049a540474c6a99edf0aa4074c58 OP_EQUAL', rpc_result['vout'][1]['scriptPubKey']['asm']) + assert_equal( + '0 3045022100ae3b4e589dfc9d48cb82d41008dc5fa6a86f94d5c54f9935531924602730ab8002202f88cf464414c4ed9fa11b773c5ee944f66e9b05cc1e51d97abc22ce098937ea[ALL] 3045022100b44883be035600e9328a01b66c7d8439b74db64187e76b99a68f7893b701d5380220225bf286493e4c4adcf928c40f785422572eb232f84a0b83b0dea823c3a19c75[ALL] 5221020743d44be989540d27b1b4bbbcfd17721c337cb6bc9af20eb8a32520b393532f2102c0120a1dda9e51a938d39ddd9fe0ebc45ea97e1d27a7cbd671d5431416d3dd87210213820eb3d5f509d7438c9eeecb4157b2f595105e7cd564b3cdbb9ead3da41eed53ae', + rpc_result['vin'][0]['scriptSig']['asm']) + assert_equal('OP_DUP OP_HASH160 dc863734a218bfe83ef770ee9d41a27f824a6e56 OP_EQUALVERIFY OP_CHECKSIG', + rpc_result['vout'][0]['scriptPubKey']['asm']) + assert_equal('OP_HASH160 2a5edea39971049a540474c6a99edf0aa4074c58 OP_EQUAL', + rpc_result['vout'][1]['scriptPubKey']['asm']) txSave = CTransaction() txSave.deserialize(BytesIO(hex_str_to_bytes(tx))) @@ -190,13 +199,15 @@ def decoderawtransaction_asm_sighashtype(self): # verify that we have not altered scriptPubKey processing even of a specially crafted P2PKH pubkeyhash and P2SH redeem script hash that is made to pass the der signature checks tx = '01000000018d1f5635abd06e2c7e2ddf58dc85b3de111e4ad6e0ab51bb0dcf5e84126d927300000000fdfe0000483045022100ae3b4e589dfc9d48cb82d41008dc5fa6a86f94d5c54f9935531924602730ab8002202f88cf464414c4ed9fa11b773c5ee944f66e9b05cc1e51d97abc22ce098937ea01483045022100b44883be035600e9328a01b66c7d8439b74db64187e76b99a68f7893b701d5380220225bf286493e4c4adcf928c40f785422572eb232f84a0b83b0dea823c3a19c75014c695221020743d44be989540d27b1b4bbbcfd17721c337cb6bc9af20eb8a32520b393532f2102c0120a1dda9e51a938d39ddd9fe0ebc45ea97e1d27a7cbd671d5431416d3dd87210213820eb3d5f509d7438c9eeecb4157b2f595105e7cd564b3cdbb9ead3da41eed53aeffffffff02611e0000000000001976a914301102070101010101010102060101010101010188acee2a02000000000017a91430110207010101010101010206010101010101018700000000' rpc_result = self.nodes[0].decoderawtransaction(tx) - assert_equal('OP_DUP OP_HASH160 3011020701010101010101020601010101010101 OP_EQUALVERIFY OP_CHECKSIG', rpc_result['vout'][0]['scriptPubKey']['asm']) - assert_equal('OP_HASH160 3011020701010101010101020601010101010101 OP_EQUAL', rpc_result['vout'][1]['scriptPubKey']['asm']) + assert_equal('OP_DUP OP_HASH160 3011020701010101010101020601010101010101 OP_EQUALVERIFY OP_CHECKSIG', + rpc_result['vout'][0]['scriptPubKey']['asm']) + assert_equal('OP_HASH160 3011020701010101010101020601010101010101 OP_EQUAL', + rpc_result['vout'][1]['scriptPubKey']['asm']) # some more full transaction tests of varying specific scriptSigs. used instead of # tests in decodescript_script_sig because the decodescript RPC is specifically # for working on scriptPubKeys (argh!). - push_signature = txSave.vin[0].scriptSig.hex()[2:(0x48*2+4)] + push_signature = txSave.vin[0].scriptSig.hex()[2:(0x48 * 2 + 4)] signature = push_signature[2:] der_signature = signature[:-2] signature_sighash_decoded = der_signature + '[ALL]' @@ -217,7 +228,8 @@ def decoderawtransaction_asm_sighashtype(self): # 2) multisig scriptSig txSave.vin[0].scriptSig = hex_str_to_bytes('00' + push_signature + push_signature_2) rpc_result = self.nodes[0].decoderawtransaction(txSave.serialize().hex()) - assert_equal('0 ' + signature_sighash_decoded + ' ' + signature_2_sighash_decoded, rpc_result['vin'][0]['scriptSig']['asm']) + assert_equal('0 ' + signature_sighash_decoded + ' ' + signature_2_sighash_decoded, + rpc_result['vin'][0]['scriptSig']['asm']) # 3) test a scriptSig that contains more than push operations. # in fact, it contains an OP_RETURN with data specially crafted to cause improper decode if the code does not catch it. @@ -230,5 +242,6 @@ def run_test(self): self.decodescript_script_pub_key() self.decoderawtransaction_asm_sighashtype() + if __name__ == '__main__': DecodeScriptTest().main() diff --git a/test/functional/rpc_deprecated.py b/test/functional/rpc_deprecated.py index 511c60e0ac..cb10861bc6 100755 --- a/test/functional/rpc_deprecated.py +++ b/test/functional/rpc_deprecated.py @@ -4,6 +4,8 @@ # file LICENSE or http://www.opensource.org/licenses/mit-license.php. """Test deprecation of RPC calls.""" from test_framework.test_framework import DefiTestFramework + + # from test_framework.util import assert_raises_rpc_error class DeprecatedRpcTest(DefiTestFramework): @@ -25,5 +27,6 @@ def run_test(self): # self.nodes[1].generate(1) self.log.info("No tested deprecated RPC methods") + if __name__ == '__main__': DeprecatedRpcTest().main() diff --git a/test/functional/rpc_deriveaddresses.py b/test/functional/rpc_deriveaddresses.py index 7d95be653e..d6b8374ebd 100755 --- a/test/functional/rpc_deriveaddresses.py +++ b/test/functional/rpc_deriveaddresses.py @@ -7,6 +7,7 @@ from test_framework.descriptors import descsum_create from test_framework.util import assert_equal, assert_raises_rpc_error + class DeriveaddressesTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 @@ -27,29 +28,55 @@ def run_test(self): assert_equal(self.nodes[0].deriveaddresses(descriptor_pubkey), [address]) ranged_descriptor = "wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)#kft60nuy" - assert_equal(self.nodes[0].deriveaddresses(ranged_descriptor, [1, 2]), ["bcrt1qhku5rq7jz8ulufe2y6fkcpnlvpsta7rq4442dy", "bcrt1qpgptk2gvshyl0s9lqshsmx932l9ccsv265tvaq"]) - assert_equal(self.nodes[0].deriveaddresses(ranged_descriptor, 2), [address, "bcrt1qhku5rq7jz8ulufe2y6fkcpnlvpsta7rq4442dy", "bcrt1qpgptk2gvshyl0s9lqshsmx932l9ccsv265tvaq"]) - - assert_raises_rpc_error(-8, "Range should not be specified for an un-ranged descriptor", self.nodes[0].deriveaddresses, descsum_create("wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/0)"), [0, 2]) - - assert_raises_rpc_error(-8, "Range must be specified for a ranged descriptor", self.nodes[0].deriveaddresses, descsum_create("wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)")) - - assert_raises_rpc_error(-8, "End of range is too high", self.nodes[0].deriveaddresses, descsum_create("wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)"), 10000000000) - - assert_raises_rpc_error(-8, "Range is too large", self.nodes[0].deriveaddresses, descsum_create("wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)"), [1000000000, 2000000000]) - - assert_raises_rpc_error(-8, "Range specified as [begin,end] must not have begin after end", self.nodes[0].deriveaddresses, descsum_create("wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)"), [2, 0]) - - assert_raises_rpc_error(-8, "Range should be greater or equal than 0", self.nodes[0].deriveaddresses, descsum_create("wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)"), [-1, 0]) - - combo_descriptor = descsum_create("combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/0)") - assert_equal(self.nodes[0].deriveaddresses(combo_descriptor), ["mtfUoUax9L4tzXARpw1oTGxWyoogp52KhJ", "mtfUoUax9L4tzXARpw1oTGxWyoogp52KhJ", address, "2NDvEwGfpEqJWfybzpKPHF2XH3jwoQV3D7x"]) - - hardened_without_privkey_descriptor = descsum_create("wpkh(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1'/1/0)") - assert_raises_rpc_error(-5, "Cannot derive script without private keys", self.nodes[0].deriveaddresses, hardened_without_privkey_descriptor) + assert_equal(self.nodes[0].deriveaddresses(ranged_descriptor, [1, 2]), + ["bcrt1qhku5rq7jz8ulufe2y6fkcpnlvpsta7rq4442dy", "bcrt1qpgptk2gvshyl0s9lqshsmx932l9ccsv265tvaq"]) + assert_equal(self.nodes[0].deriveaddresses(ranged_descriptor, 2), + [address, "bcrt1qhku5rq7jz8ulufe2y6fkcpnlvpsta7rq4442dy", + "bcrt1qpgptk2gvshyl0s9lqshsmx932l9ccsv265tvaq"]) + + assert_raises_rpc_error(-8, "Range should not be specified for an un-ranged descriptor", + self.nodes[0].deriveaddresses, descsum_create( + "wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/0)"), + [0, 2]) + + assert_raises_rpc_error(-8, "Range must be specified for a ranged descriptor", self.nodes[0].deriveaddresses, + descsum_create( + "wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)")) + + assert_raises_rpc_error(-8, "End of range is too high", self.nodes[0].deriveaddresses, descsum_create( + "wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)"), + 10000000000) + + assert_raises_rpc_error(-8, "Range is too large", self.nodes[0].deriveaddresses, descsum_create( + "wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)"), + [1000000000, 2000000000]) + + assert_raises_rpc_error(-8, "Range specified as [begin,end] must not have begin after end", + self.nodes[0].deriveaddresses, descsum_create( + "wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)"), + [2, 0]) + + assert_raises_rpc_error(-8, "Range should be greater or equal than 0", self.nodes[0].deriveaddresses, + descsum_create( + "wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)"), + [-1, 0]) + + combo_descriptor = descsum_create( + "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/0)") + assert_equal(self.nodes[0].deriveaddresses(combo_descriptor), + ["mtfUoUax9L4tzXARpw1oTGxWyoogp52KhJ", "mtfUoUax9L4tzXARpw1oTGxWyoogp52KhJ", address, + "2NDvEwGfpEqJWfybzpKPHF2XH3jwoQV3D7x"]) + + hardened_without_privkey_descriptor = descsum_create( + "wpkh(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1'/1/0)") + assert_raises_rpc_error(-5, "Cannot derive script without private keys", self.nodes[0].deriveaddresses, + hardened_without_privkey_descriptor) + + bare_multisig_descriptor = descsum_create( + "multi(1,tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/0,tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/1)") + assert_raises_rpc_error(-5, "Descriptor does not have a corresponding address", self.nodes[0].deriveaddresses, + bare_multisig_descriptor) - bare_multisig_descriptor = descsum_create("multi(1,tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/0,tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/1)") - assert_raises_rpc_error(-5, "Descriptor does not have a corresponding address", self.nodes[0].deriveaddresses, bare_multisig_descriptor) if __name__ == '__main__': DeriveaddressesTest().main() diff --git a/test/functional/rpc_fundrawtransaction.py b/test/functional/rpc_fundrawtransaction.py index 507afe72a1..b70a1b8ba1 100755 --- a/test/functional/rpc_fundrawtransaction.py +++ b/test/functional/rpc_fundrawtransaction.py @@ -24,6 +24,7 @@ def get_unspent(listunspent, amount): return utx raise AssertionError('Could not find unspent with amount={}'.format(amount)) + class RawTransactionsTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 4 @@ -91,8 +92,8 @@ def run_test(self): def test_change_position(self): # ensure that setting changePosition in fundraw with an exact match is handled properly - rawmatch = self.nodes[2].createrawtransaction([], {self.nodes[2].getnewaddress():50}) - rawmatch = self.nodes[2].fundrawtransaction(rawmatch, {"changePosition":1, "subtractFeeFromOutputs":[0]}) + rawmatch = self.nodes[2].createrawtransaction([], {self.nodes[2].getnewaddress(): 50}) + rawmatch = self.nodes[2].fundrawtransaction(rawmatch, {"changePosition": 1, "subtractFeeFromOutputs": [0]}) assert_equal(rawmatch["changepos"], -1) watchonly_address = self.nodes[0].getnewaddress() @@ -118,39 +119,39 @@ def test_simple(self): ############### # simple test # ############### - inputs = [ ] - outputs = { self.nodes[0].getnewaddress() : 1.0 } - rawtx = self.nodes[2].createrawtransaction(inputs, outputs) - dec_tx = self.nodes[2].decoderawtransaction(rawtx) + inputs = [] + outputs = {self.nodes[0].getnewaddress(): 1.0} + rawtx = self.nodes[2].createrawtransaction(inputs, outputs) + dec_tx = self.nodes[2].decoderawtransaction(rawtx) rawtxfund = self.nodes[2].fundrawtransaction(rawtx) - dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) - assert len(dec_tx['vin']) > 0 #test that we have enough inputs + dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) + assert len(dec_tx['vin']) > 0 # test that we have enough inputs def test_simple_two_coins(self): ############################## # simple test with two coins # ############################## - inputs = [ ] - outputs = { self.nodes[0].getnewaddress() : 2.2 } - rawtx = self.nodes[2].createrawtransaction(inputs, outputs) - dec_tx = self.nodes[2].decoderawtransaction(rawtx) + inputs = [] + outputs = {self.nodes[0].getnewaddress(): 2.2} + rawtx = self.nodes[2].createrawtransaction(inputs, outputs) + dec_tx = self.nodes[2].decoderawtransaction(rawtx) rawtxfund = self.nodes[2].fundrawtransaction(rawtx) - dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) - assert len(dec_tx['vin']) > 0 #test if we have enough inputs + dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) + assert len(dec_tx['vin']) > 0 # test if we have enough inputs assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '') def test_simple_two_outputs(self): ################################ # simple test with two outputs # ################################ - inputs = [ ] - outputs = { self.nodes[0].getnewaddress() : 2.6, self.nodes[1].getnewaddress() : 2.5 } - rawtx = self.nodes[2].createrawtransaction(inputs, outputs) - dec_tx = self.nodes[2].decoderawtransaction(rawtx) + inputs = [] + outputs = {self.nodes[0].getnewaddress(): 2.6, self.nodes[1].getnewaddress(): 2.5} + rawtx = self.nodes[2].createrawtransaction(inputs, outputs) + dec_tx = self.nodes[2].decoderawtransaction(rawtx) rawtxfund = self.nodes[2].fundrawtransaction(rawtx) - dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) + dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) totalOut = 0 for out in dec_tx['vout']: totalOut += out['value'] @@ -164,21 +165,21 @@ def test_change(self): ######################################################################### utx = get_unspent(self.nodes[2].listunspent(), 5) - inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}] - outputs = { self.nodes[0].getnewaddress() : 1.0 } - rawtx = self.nodes[2].createrawtransaction(inputs, outputs) - dec_tx = self.nodes[2].decoderawtransaction(rawtx) + inputs = [{'txid': utx['txid'], 'vout': utx['vout']}] + outputs = {self.nodes[0].getnewaddress(): 1.0} + rawtx = self.nodes[2].createrawtransaction(inputs, outputs) + dec_tx = self.nodes[2].decoderawtransaction(rawtx) assert_equal(utx['txid'], dec_tx['vin'][0]['txid']) rawtxfund = self.nodes[2].fundrawtransaction(rawtx) fee = rawtxfund['fee'] self.test_no_change_fee = fee # Use the same fee for the next tx - dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) + dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) totalOut = 0 for out in dec_tx['vout']: totalOut += out['value'] - assert_equal(fee + totalOut, utx['amount']) #compare vin total and totalout+fee + assert_equal(fee + totalOut, utx['amount']) # compare vin total and totalout+fee def test_no_change(self): ##################################################################### @@ -186,21 +187,21 @@ def test_no_change(self): ##################################################################### utx = get_unspent(self.nodes[2].listunspent(), 5) - inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}] + inputs = [{'txid': utx['txid'], 'vout': utx['vout']}] outputs = {self.nodes[0].getnewaddress(): Decimal(5.0) - self.test_no_change_fee - self.fee_tolerance} - rawtx = self.nodes[2].createrawtransaction(inputs, outputs) - dec_tx = self.nodes[2].decoderawtransaction(rawtx) + rawtx = self.nodes[2].createrawtransaction(inputs, outputs) + dec_tx = self.nodes[2].decoderawtransaction(rawtx) assert_equal(utx['txid'], dec_tx['vin'][0]['txid']) rawtxfund = self.nodes[2].fundrawtransaction(rawtx) fee = rawtxfund['fee'] - dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) + dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) totalOut = 0 for out in dec_tx['vout']: totalOut += out['value'] assert_equal(rawtxfund['changepos'], -1) - assert_equal(fee + totalOut, utx['amount']) #compare vin total and totalout+fee + assert_equal(fee + totalOut, utx['amount']) # compare vin total and totalout+fee def test_invalid_option(self): #################################################### @@ -208,16 +209,18 @@ def test_invalid_option(self): #################################################### utx = get_unspent(self.nodes[2].listunspent(), 5) - inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ] - outputs = { self.nodes[0].getnewaddress() : Decimal(4.0) } - rawtx = self.nodes[2].createrawtransaction(inputs, outputs) - dec_tx = self.nodes[2].decoderawtransaction(rawtx) + inputs = [{'txid': utx['txid'], 'vout': utx['vout']}] + outputs = {self.nodes[0].getnewaddress(): Decimal(4.0)} + rawtx = self.nodes[2].createrawtransaction(inputs, outputs) + dec_tx = self.nodes[2].decoderawtransaction(rawtx) assert_equal(utx['txid'], dec_tx['vin'][0]['txid']) - assert_raises_rpc_error(-3, "Unexpected key foo", self.nodes[2].fundrawtransaction, rawtx, {'foo':'bar'}) + assert_raises_rpc_error(-3, "Unexpected key foo", self.nodes[2].fundrawtransaction, rawtx, {'foo': 'bar'}) # reserveChangeKey was deprecated and is now removed - assert_raises_rpc_error(-3, "Unexpected key reserveChangeKey", lambda: self.nodes[2].fundrawtransaction(hexstring=rawtx, options={'reserveChangeKey': True})) + assert_raises_rpc_error(-3, "Unexpected key reserveChangeKey", + lambda: self.nodes[2].fundrawtransaction(hexstring=rawtx, + options={'reserveChangeKey': True})) def test_invalid_change_address(self): ############################################################ @@ -225,13 +228,14 @@ def test_invalid_change_address(self): ############################################################ utx = get_unspent(self.nodes[2].listunspent(), 5) - inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ] - outputs = { self.nodes[0].getnewaddress() : Decimal(4.0) } - rawtx = self.nodes[2].createrawtransaction(inputs, outputs) - dec_tx = self.nodes[2].decoderawtransaction(rawtx) + inputs = [{'txid': utx['txid'], 'vout': utx['vout']}] + outputs = {self.nodes[0].getnewaddress(): Decimal(4.0)} + rawtx = self.nodes[2].createrawtransaction(inputs, outputs) + dec_tx = self.nodes[2].decoderawtransaction(rawtx) assert_equal(utx['txid'], dec_tx['vin'][0]['txid']) - assert_raises_rpc_error(-5, "changeAddress must be a valid defi address", self.nodes[2].fundrawtransaction, rawtx, {'changeAddress':'foobar'}) + assert_raises_rpc_error(-5, "changeAddress must be a valid defi address", self.nodes[2].fundrawtransaction, + rawtx, {'changeAddress': 'foobar'}) def test_valid_change_address(self): ############################################################ @@ -239,16 +243,17 @@ def test_valid_change_address(self): ############################################################ utx = get_unspent(self.nodes[2].listunspent(), 5) - inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ] - outputs = { self.nodes[0].getnewaddress() : Decimal(4.0) } - rawtx = self.nodes[2].createrawtransaction(inputs, outputs) - dec_tx = self.nodes[2].decoderawtransaction(rawtx) + inputs = [{'txid': utx['txid'], 'vout': utx['vout']}] + outputs = {self.nodes[0].getnewaddress(): Decimal(4.0)} + rawtx = self.nodes[2].createrawtransaction(inputs, outputs) + dec_tx = self.nodes[2].decoderawtransaction(rawtx) assert_equal(utx['txid'], dec_tx['vin'][0]['txid']) change = self.nodes[2].getnewaddress() - assert_raises_rpc_error(-8, "changePosition out of bounds", self.nodes[2].fundrawtransaction, rawtx, {'changeAddress':change, 'changePosition':2}) + assert_raises_rpc_error(-8, "changePosition out of bounds", self.nodes[2].fundrawtransaction, rawtx, + {'changeAddress': change, 'changePosition': 2}) rawtxfund = self.nodes[2].fundrawtransaction(rawtx, {'changeAddress': change, 'changePosition': 0}) - dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) + dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) out = dec_tx['vout'][0] assert_equal(change, out['scriptPubKey']['addresses'][0]) @@ -258,11 +263,13 @@ def test_change_type(self): ######################################################### utx = get_unspent(self.nodes[2].listunspent(), 5) - inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ] - outputs = { self.nodes[0].getnewaddress() : Decimal(4.0) } - rawtx = self.nodes[2].createrawtransaction(inputs, outputs) - assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[2].fundrawtransaction, rawtx, {'change_type': None}) - assert_raises_rpc_error(-5, "Unknown change type ''", self.nodes[2].fundrawtransaction, rawtx, {'change_type': ''}) + inputs = [{'txid': utx['txid'], 'vout': utx['vout']}] + outputs = {self.nodes[0].getnewaddress(): Decimal(4.0)} + rawtx = self.nodes[2].createrawtransaction(inputs, outputs) + assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[2].fundrawtransaction, rawtx, + {'change_type': None}) + assert_raises_rpc_error(-5, "Unknown change type ''", self.nodes[2].fundrawtransaction, rawtx, + {'change_type': ''}) rawtx = self.nodes[2].fundrawtransaction(rawtx, {'change_type': 'bech32'}) dec_tx = self.nodes[2].decoderawtransaction(rawtx['hex']) assert_equal('witness_v0_keyhash', dec_tx['vout'][rawtx['changepos']]['scriptPubKey']['type']) @@ -273,25 +280,25 @@ def test_coin_selection(self): ######################################################################### utx = get_unspent(self.nodes[2].listunspent(), 1) - inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}] - outputs = { self.nodes[0].getnewaddress() : 1.0 } - rawtx = self.nodes[2].createrawtransaction(inputs, outputs) + inputs = [{'txid': utx['txid'], 'vout': utx['vout']}] + outputs = {self.nodes[0].getnewaddress(): 1.0} + rawtx = self.nodes[2].createrawtransaction(inputs, outputs) # 4-byte version + 1-byte vin count + 36-byte prevout then script_len rawtx = rawtx[:82] + "0100" + rawtx[84:] - dec_tx = self.nodes[2].decoderawtransaction(rawtx) + dec_tx = self.nodes[2].decoderawtransaction(rawtx) assert_equal(utx['txid'], dec_tx['vin'][0]['txid']) assert_equal("00", dec_tx['vin'][0]['scriptSig']['hex']) rawtxfund = self.nodes[2].fundrawtransaction(rawtx) - dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) + dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) totalOut = 0 matchingOuts = 0 for i, out in enumerate(dec_tx['vout']): totalOut += out['value'] if out['scriptPubKey']['addresses'][0] in outputs: - matchingOuts+=1 + matchingOuts += 1 else: assert_equal(i, rawtxfund['changepos']) @@ -308,20 +315,20 @@ def test_two_vin(self): utx = get_unspent(self.nodes[2].listunspent(), 1) utx2 = get_unspent(self.nodes[2].listunspent(), 5) - inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']},{'txid' : utx2['txid'], 'vout' : utx2['vout']} ] - outputs = { self.nodes[0].getnewaddress() : 6.0 } - rawtx = self.nodes[2].createrawtransaction(inputs, outputs) - dec_tx = self.nodes[2].decoderawtransaction(rawtx) + inputs = [{'txid': utx['txid'], 'vout': utx['vout']}, {'txid': utx2['txid'], 'vout': utx2['vout']}] + outputs = {self.nodes[0].getnewaddress(): 6.0} + rawtx = self.nodes[2].createrawtransaction(inputs, outputs) + dec_tx = self.nodes[2].decoderawtransaction(rawtx) assert_equal(utx['txid'], dec_tx['vin'][0]['txid']) rawtxfund = self.nodes[2].fundrawtransaction(rawtx) - dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) + dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) totalOut = 0 matchingOuts = 0 for out in dec_tx['vout']: totalOut += out['value'] if out['scriptPubKey']['addresses'][0] in outputs: - matchingOuts+=1 + matchingOuts += 1 assert_equal(matchingOuts, 1) assert_equal(len(dec_tx['vout']), 2) @@ -330,9 +337,9 @@ def test_two_vin(self): for vinOut in dec_tx['vin']: for vinIn in inputs: if vinIn['txid'] == vinOut['txid']: - matchingIns+=1 + matchingIns += 1 - assert_equal(matchingIns, 2) #we now must see two vins identical to vins given as params + assert_equal(matchingIns, 2) # we now must see two vins identical to vins given as params def test_two_vin_two_vout(self): ######################################################### @@ -341,20 +348,20 @@ def test_two_vin_two_vout(self): utx = get_unspent(self.nodes[2].listunspent(), 1) utx2 = get_unspent(self.nodes[2].listunspent(), 5) - inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']},{'txid' : utx2['txid'], 'vout' : utx2['vout']} ] - outputs = { self.nodes[0].getnewaddress() : 6.0, self.nodes[0].getnewaddress() : 1.0 } - rawtx = self.nodes[2].createrawtransaction(inputs, outputs) - dec_tx = self.nodes[2].decoderawtransaction(rawtx) + inputs = [{'txid': utx['txid'], 'vout': utx['vout']}, {'txid': utx2['txid'], 'vout': utx2['vout']}] + outputs = {self.nodes[0].getnewaddress(): 6.0, self.nodes[0].getnewaddress(): 1.0} + rawtx = self.nodes[2].createrawtransaction(inputs, outputs) + dec_tx = self.nodes[2].decoderawtransaction(rawtx) assert_equal(utx['txid'], dec_tx['vin'][0]['txid']) rawtxfund = self.nodes[2].fundrawtransaction(rawtx) - dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) + dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) totalOut = 0 matchingOuts = 0 for out in dec_tx['vout']: totalOut += out['value'] if out['scriptPubKey']['addresses'][0] in outputs: - matchingOuts+=1 + matchingOuts += 1 assert_equal(matchingOuts, 2) assert_equal(len(dec_tx['vout']), 3) @@ -363,47 +370,50 @@ def test_invalid_input(self): ############################################## # test a fundrawtransaction with invalid vin # ############################################## - inputs = [ {'txid' : "1c7f966dab21119bac53213a2bc7532bff1fa844c124fd750a7d0b1332440bd1", 'vout' : 0} ] #invalid vin! - outputs = { self.nodes[0].getnewaddress() : 1.0} - rawtx = self.nodes[2].createrawtransaction(inputs, outputs) + inputs = [ + {'txid': "1c7f966dab21119bac53213a2bc7532bff1fa844c124fd750a7d0b1332440bd1", 'vout': 0}] # invalid vin! + outputs = {self.nodes[0].getnewaddress(): 1.0} + rawtx = self.nodes[2].createrawtransaction(inputs, outputs) assert_raises_rpc_error(-4, "Insufficient funds", self.nodes[2].fundrawtransaction, rawtx) def test_fee_p2pkh(self): ############################################################ - #compare fee of a standard pubkeyhash transaction + # compare fee of a standard pubkeyhash transaction inputs = [] - outputs = {self.nodes[1].getnewaddress():1.1} + outputs = {self.nodes[1].getnewaddress(): 1.1} rawtx = self.nodes[0].createrawtransaction(inputs, outputs) fundedTx = self.nodes[0].fundrawtransaction(rawtx) - #create same transaction over sendtoaddress + # create same transaction over sendtoaddress txId = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1.1) signedFee = self.nodes[0].getrawmempool(True)[txId]['fee'] - #compare fee + # compare fee feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee) assert feeDelta >= 0 and feeDelta <= self.fee_tolerance ############################################################ def test_fee_p2pkh_multi_out(self): ############################################################ - #compare fee of a standard pubkeyhash transaction with multiple outputs + # compare fee of a standard pubkeyhash transaction with multiple outputs inputs = [] - outputs = {self.nodes[1].getnewaddress():1.1,self.nodes[1].getnewaddress():1.2,self.nodes[1].getnewaddress():0.1,self.nodes[1].getnewaddress():1.3,self.nodes[1].getnewaddress():0.2,self.nodes[1].getnewaddress():0.3} + outputs = {self.nodes[1].getnewaddress(): 1.1, self.nodes[1].getnewaddress(): 1.2, + self.nodes[1].getnewaddress(): 0.1, self.nodes[1].getnewaddress(): 1.3, + self.nodes[1].getnewaddress(): 0.2, self.nodes[1].getnewaddress(): 0.3} rawtx = self.nodes[0].createrawtransaction(inputs, outputs) fundedTx = self.nodes[0].fundrawtransaction(rawtx) - #create same transaction over sendtoaddress + # create same transaction over sendtoaddress txId = self.nodes[0].sendmany("", outputs) signedFee = self.nodes[0].getrawmempool(True)[txId]['fee'] - #compare fee + # compare fee feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee) assert feeDelta >= 0 and feeDelta <= self.fee_tolerance ############################################################ def test_fee_p2sh(self): ############################################################ - #compare fee of a 2of2 multisig p2sh transaction + # compare fee of a 2of2 multisig p2sh transaction # create 2of2 addr addr1 = self.nodes[1].getnewaddress() @@ -415,22 +425,22 @@ def test_fee_p2sh(self): mSigObj = self.nodes[1].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address'] inputs = [] - outputs = {mSigObj:1.1} + outputs = {mSigObj: 1.1} rawtx = self.nodes[0].createrawtransaction(inputs, outputs) fundedTx = self.nodes[0].fundrawtransaction(rawtx) - #create same transaction over sendtoaddress + # create same transaction over sendtoaddress txId = self.nodes[0].sendtoaddress(mSigObj, 1.1) signedFee = self.nodes[0].getrawmempool(True)[txId]['fee'] - #compare fee + # compare fee feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee) assert feeDelta >= 0 and feeDelta <= self.fee_tolerance ############################################################ def test_fee_4of5(self): ############################################################ - #compare fee of a standard pubkeyhash transaction + # compare fee of a standard pubkeyhash transaction # create 4of5 addr addr1 = self.nodes[1].getnewaddress() @@ -445,18 +455,19 @@ def test_fee_4of5(self): addr4Obj = self.nodes[1].getaddressinfo(addr4) addr5Obj = self.nodes[1].getaddressinfo(addr5) - mSigObj = self.nodes[1].addmultisigaddress(4, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey'], addr4Obj['pubkey'], addr5Obj['pubkey']])['address'] + mSigObj = self.nodes[1].addmultisigaddress(4, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey'], + addr4Obj['pubkey'], addr5Obj['pubkey']])['address'] inputs = [] - outputs = {mSigObj:1.1} + outputs = {mSigObj: 1.1} rawtx = self.nodes[0].createrawtransaction(inputs, outputs) fundedTx = self.nodes[0].fundrawtransaction(rawtx) - #create same transaction over sendtoaddress + # create same transaction over sendtoaddress txId = self.nodes[0].sendtoaddress(mSigObj, 1.1) signedFee = self.nodes[0].getrawmempool(True)[txId]['fee'] - #compare fee + # compare fee feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee) assert feeDelta >= 0 and feeDelta <= self.fee_tolerance ############################################################ @@ -474,7 +485,6 @@ def test_spend_2of2(self): mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address'] - # send 1.2 BTC to msig addr self.nodes[0].sendtoaddress(mSigObj, 1.2) self.sync_mempools() @@ -483,7 +493,7 @@ def test_spend_2of2(self): oldBalance = self.nodes[1].getbalance() inputs = [] - outputs = {self.nodes[1].getnewaddress():1.1} + outputs = {self.nodes[1].getnewaddress(): 1.1} rawtx = self.nodes[2].createrawtransaction(inputs, outputs) fundedTx = self.nodes[2].fundrawtransaction(rawtx) @@ -494,7 +504,7 @@ def test_spend_2of2(self): self.sync_blocks() # make sure funds are received at node1 - assert_equal(oldBalance+Decimal('1.10000000'), self.nodes[1].getbalance()) + assert_equal(oldBalance + Decimal('1.10000000'), self.nodes[1].getbalance()) def test_locked_wallet(self): ############################################################ @@ -508,10 +518,10 @@ def test_locked_wallet(self): for node in self.nodes: node.settxfee(self.min_relay_tx_fee) - connect_nodes_bi(self.nodes,0,1) - connect_nodes_bi(self.nodes,1,2) - connect_nodes_bi(self.nodes,0,2) - connect_nodes_bi(self.nodes,0,3) + connect_nodes_bi(self.nodes, 0, 1) + connect_nodes_bi(self.nodes, 1, 2) + connect_nodes_bi(self.nodes, 0, 2) + connect_nodes_bi(self.nodes, 0, 3) # Again lock the watchonly UTXO or nodes[0] may spend it, because # lockunspent is memory-only and thus lost on restart self.nodes[0].lockunspent(False, [{"txid": self.watchonly_txid, "vout": self.watchonly_vout}]) @@ -521,27 +531,29 @@ def test_locked_wallet(self): self.nodes[1].getnewaddress() self.nodes[1].getrawchangeaddress() inputs = [] - outputs = {self.nodes[0].getnewaddress():1.1} + outputs = {self.nodes[0].getnewaddress(): 1.1} rawtx = self.nodes[1].createrawtransaction(inputs, outputs) # fund a transaction that requires a new key for the change output # creating the key must be impossible because the wallet is locked - assert_raises_rpc_error(-4, "Keypool ran out, please call keypoolrefill first", self.nodes[1].fundrawtransaction, rawtx) + assert_raises_rpc_error(-4, "Keypool ran out, please call keypoolrefill first", + self.nodes[1].fundrawtransaction, rawtx) - #refill the keypool + # refill the keypool self.nodes[1].walletpassphrase("test", 100) - self.nodes[1].keypoolrefill(8) #need to refill the keypool to get an internal change address + self.nodes[1].keypoolrefill(8) # need to refill the keypool to get an internal change address self.nodes[1].walletlock() - assert_raises_rpc_error(-13, "walletpassphrase", self.nodes[1].sendtoaddress, self.nodes[0].getnewaddress(), 1.2) + assert_raises_rpc_error(-13, "walletpassphrase", self.nodes[1].sendtoaddress, self.nodes[0].getnewaddress(), + 1.2) oldBalance = self.nodes[0].getbalance() inputs = [] - outputs = {self.nodes[0].getnewaddress():1.1} + outputs = {self.nodes[0].getnewaddress(): 1.1} rawtx = self.nodes[1].createrawtransaction(inputs, outputs) fundedTx = self.nodes[1].fundrawtransaction(rawtx) - #now we need to unlock + # now we need to unlock self.nodes[1].walletpassphrase("test", 600) signedTx = self.nodes[1].signrawtransactionwithwallet(fundedTx['hex']) self.nodes[1].sendrawtransaction(signedTx['hex']) @@ -549,59 +561,59 @@ def test_locked_wallet(self): self.sync_blocks() # make sure funds are received at node1 - assert_equal(oldBalance+Decimal('51.10000000'), self.nodes[0].getbalance()) + assert_equal(oldBalance + Decimal('51.10000000'), self.nodes[0].getbalance()) def test_many_inputs_fee(self): ############################################### # multiple (~19) inputs tx test | Compare fee # ############################################### - #empty node1, send some small coins from node0 to node1 + # empty node1, send some small coins from node0 to node1 self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), self.nodes[1].getbalance(), "", "", True) self.sync_mempools() self.nodes[0].generate(1) self.sync_blocks() - for i in range(0,20): + for i in range(0, 20): self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.01) self.nodes[0].generate(1) self.sync_blocks() - #fund a tx with ~20 small inputs + # fund a tx with ~20 small inputs inputs = [] - outputs = {self.nodes[0].getnewaddress():0.15,self.nodes[0].getnewaddress():0.04} + outputs = {self.nodes[0].getnewaddress(): 0.15, self.nodes[0].getnewaddress(): 0.04} rawtx = self.nodes[1].createrawtransaction(inputs, outputs) fundedTx = self.nodes[1].fundrawtransaction(rawtx) - #create same transaction over sendtoaddress + # create same transaction over sendtoaddress txId = self.nodes[1].sendmany("", outputs) signedFee = self.nodes[1].getrawmempool(True)[txId]['fee'] - #compare fee + # compare fee feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee) - assert feeDelta >= 0 and feeDelta <= self.fee_tolerance * 19 #~19 inputs + assert feeDelta >= 0 and feeDelta <= self.fee_tolerance * 19 # ~19 inputs def test_many_inputs_send(self): ############################################# # multiple (~19) inputs tx test | sign/send # ############################################# - #again, empty node1, send some small coins from node0 to node1 + # again, empty node1, send some small coins from node0 to node1 self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), self.nodes[1].getbalance(), "", "", True) self.sync_mempools() self.nodes[0].generate(1) self.sync_blocks() - for i in range(0,20): + for i in range(0, 20): self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.01) self.nodes[0].generate(1) self.sync_blocks() - #fund a tx with ~20 small inputs + # fund a tx with ~20 small inputs oldBalance = self.nodes[0].getbalance() inputs = [] - outputs = {self.nodes[0].getnewaddress():0.15,self.nodes[0].getnewaddress():0.04} + outputs = {self.nodes[0].getnewaddress(): 0.15, self.nodes[0].getnewaddress(): 0.04} rawtx = self.nodes[1].createrawtransaction(inputs, outputs) fundedTx = self.nodes[1].fundrawtransaction(rawtx) fundedAndSignedTx = self.nodes[1].signrawtransactionwithwallet(fundedTx['hex']) @@ -609,24 +621,24 @@ def test_many_inputs_send(self): self.sync_mempools() self.nodes[0].generate(1) self.sync_blocks() - assert_equal(oldBalance+Decimal('50.19000000'), self.nodes[0].getbalance()) #0.19+block reward + assert_equal(oldBalance + Decimal('50.19000000'), self.nodes[0].getbalance()) # 0.19+block reward def test_op_return(self): ##################################################### # test fundrawtransaction with OP_RETURN and no vin # ##################################################### - rawtx = "0100000000010000000000000000066a047465737400000000" - dec_tx = self.nodes[2].decoderawtransaction(rawtx) + rawtx = "0100000000010000000000000000066a047465737400000000" + dec_tx = self.nodes[2].decoderawtransaction(rawtx) assert_equal(len(dec_tx['vin']), 0) assert_equal(len(dec_tx['vout']), 1) rawtxfund = self.nodes[2].fundrawtransaction(rawtx) - dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) + dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) - assert_greater_than(len(dec_tx['vin']), 0) # at least one vin - assert_equal(len(dec_tx['vout']), 2) # one change output added + assert_greater_than(len(dec_tx['vin']), 0) # at least one vin + assert_equal(len(dec_tx['vout']), 2) # one change output added def test_watchonly(self): ################################################## @@ -637,7 +649,7 @@ def test_watchonly(self): outputs = {self.nodes[2].getnewaddress(): self.watchonly_amount / 2} rawtx = self.nodes[3].createrawtransaction(inputs, outputs) - result = self.nodes[3].fundrawtransaction(rawtx, {'includeWatching': True }) + result = self.nodes[3].fundrawtransaction(rawtx, {'includeWatching': True}) res_dec = self.nodes[0].decoderawtransaction(result["hex"]) assert_equal(len(res_dec["vin"]), 1) assert_equal(res_dec["vin"][0]["txid"], self.watchonly_txid) @@ -681,12 +693,13 @@ def test_option_feerate(self): assert_equal(len(self.nodes[3].listunspent(1)), 1) inputs = [] - outputs = {self.nodes[3].getnewaddress() : 1} + outputs = {self.nodes[3].getnewaddress(): 1} rawtx = self.nodes[3].createrawtransaction(inputs, outputs) result = self.nodes[3].fundrawtransaction(rawtx) # uses self.min_relay_tx_fee (set by settxfee) result2 = self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 2 * self.min_relay_tx_fee}) result3 = self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 10 * self.min_relay_tx_fee}) - assert_raises_rpc_error(-4, "Fee exceeds maximum configured by -maxtxfee", self.nodes[3].fundrawtransaction, rawtx, {"feeRate": 1}) + assert_raises_rpc_error(-4, "Fee exceeds maximum configured by -maxtxfee", self.nodes[3].fundrawtransaction, + rawtx, {"feeRate": 1}) result_fee_rate = result['fee'] * 1000 / count_bytes(result['hex']) assert_fee_amount(result2['fee'], count_bytes(result2['hex']), 2 * result_fee_rate) assert_fee_amount(result3['fee'], count_bytes(result3['hex']), 10 * result_fee_rate) @@ -721,10 +734,12 @@ def test_option_subtract_fee_from_outputs(self): rawtx = self.nodes[3].createrawtransaction(inputs, outputs) result = [self.nodes[3].fundrawtransaction(rawtx), # uses self.min_relay_tx_fee (set by settxfee) - self.nodes[3].fundrawtransaction(rawtx, {"subtractFeeFromOutputs": []}), # empty subtraction list - self.nodes[3].fundrawtransaction(rawtx, {"subtractFeeFromOutputs": [0]}), # uses self.min_relay_tx_fee (set by settxfee) - self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 2 * self.min_relay_tx_fee}), - self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 2 * self.min_relay_tx_fee, "subtractFeeFromOutputs": [0]}),] + self.nodes[3].fundrawtransaction(rawtx, {"subtractFeeFromOutputs": []}), # empty subtraction list + self.nodes[3].fundrawtransaction(rawtx, {"subtractFeeFromOutputs": [0]}), + # uses self.min_relay_tx_fee (set by settxfee) + self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 2 * self.min_relay_tx_fee}), + self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 2 * self.min_relay_tx_fee, + "subtractFeeFromOutputs": [0]}), ] dec_tx = [self.nodes[3].decoderawtransaction(tx_['hex']) for tx_ in result] output = [d['vout'][1 - r['changepos']]['value'] for d, r in zip(dec_tx, result)] @@ -778,5 +793,6 @@ def test_option_subtract_fee_from_outputs(self): # the total subtracted from the outputs is equal to the fee assert_equal(share[0] + share[2] + share[3], result[0]['fee']) + if __name__ == '__main__': RawTransactionsTest().main() diff --git a/test/functional/rpc_getaccounthistory.py b/test/functional/rpc_getaccounthistory.py index 06c8eadb6d..df4cbee7d7 100755 --- a/test/functional/rpc_getaccounthistory.py +++ b/test/functional/rpc_getaccounthistory.py @@ -53,27 +53,27 @@ def run_test(self): # Get node 0 results # test amount@id format - results = self.nodes[0].listaccounthistory(collateral_a, {"format": "id"} ) + results = self.nodes[0].listaccounthistory(collateral_a, {"format": "id"}) # test token ids match token symbol for result in results: for amount in result["amounts"]: symbol = amount.split('@')[1] - assert(symbol.isnumeric()) + assert (symbol.isnumeric()) # test amount@symbol format - results = self.nodes[0].listaccounthistory(collateral_a, {"format": "symbol"} ) + results = self.nodes[0].listaccounthistory(collateral_a, {"format": "symbol"}) # test token ids match token symbol for result in results: for amount in result["amounts"]: symbol = amount.split('@')[1] - assert(symbol.isnumeric() == False) + assert (symbol.isnumeric() == False) # test amount@symbol format try: - results = self.nodes[0].listaccounthistory(collateral_a, {"format": "combined"} ) + results = self.nodes[0].listaccounthistory(collateral_a, {"format": "combined"}) except JSONRPCException as e: errorString = e.error['message'] - assert("format must be one of the following: \"id\", \"symbol\"" in errorString) + assert ("format must be one of the following: \"id\", \"symbol\"" in errorString) # An account history from listaccounthistory and gettaccounthistory must be matched expected = results[0] @@ -98,5 +98,6 @@ def run_test(self): assert_equal(history['txn'], expected['txn']) assert_equal(history['type'], expected['type']) + if __name__ == '__main__': - TokensRPCGetAccountHistory().main () + TokensRPCGetAccountHistory().main() diff --git a/test/functional/rpc_getblockfilter.py b/test/functional/rpc_getblockfilter.py index 602bac995c..ba7dfb4ec6 100755 --- a/test/functional/rpc_getblockfilter.py +++ b/test/functional/rpc_getblockfilter.py @@ -8,10 +8,11 @@ from test_framework.util import ( assert_equal, assert_is_hex_string, assert_raises_rpc_error, connect_nodes, disconnect_nodes, sync_blocks - ) +) FILTER_TYPES = ["basic"] + class GetBlockFilterTest(DefiTestFramework): def set_test_params(self): self.setup_clean_chain = True @@ -55,5 +56,6 @@ def run_test(self): genesis_hash = self.nodes[0].getblockhash(0) assert_raises_rpc_error(-5, "Unknown filtertype", self.nodes[0].getblockfilter, genesis_hash, "unknown") + if __name__ == '__main__': GetBlockFilterTest().main() diff --git a/test/functional/rpc_getblockstats.py b/test/functional/rpc_getblockstats.py index 54496375b5..9613110596 100755 --- a/test/functional/rpc_getblockstats.py +++ b/test/functional/rpc_getblockstats.py @@ -17,8 +17,8 @@ TESTSDIR = os.path.dirname(os.path.realpath(__file__)) -class GetblockstatsTest(DefiTestFramework): +class GetblockstatsTest(DefiTestFramework): start_height = 101 max_stat_pos = 2 @@ -36,10 +36,10 @@ def set_test_params(self): self.setup_clean_chain = True def get_stats(self): - return [self.nodes[0].getblockstats(hash_or_height=self.start_height + i) for i in range(self.max_stat_pos+1)] + return [self.nodes[0].getblockstats(hash_or_height=self.start_height + i) for i in range(self.max_stat_pos + 1)] def generate_test_data(self, filename): - mocktime = TIME_GENESIS_BLOCK+1 + mocktime = TIME_GENESIS_BLOCK + 1 self.nodes[0].setmocktime(mocktime) self.nodes[0].generate(101) @@ -85,7 +85,6 @@ def load_test_data(self, filename): for b in blocks: self.nodes[0].submitblock(b) - def run_test(self): test_data = os.path.join(TESTSDIR, self.options.test_data) if self.options.gen_test_data: @@ -102,7 +101,7 @@ def run_test(self): assert_equal(stats[0]['height'], self.start_height) assert_equal(stats[self.max_stat_pos]['height'], self.start_height + self.max_stat_pos) - for i in range(self.max_stat_pos+1): + for i in range(self.max_stat_pos + 1): self.log.info('Checking block %d\n' % (i)) assert_equal(stats[i], self.expected_stats[i]) @@ -113,7 +112,7 @@ def run_test(self): # Make sure each stat can be queried on its own for stat in expected_keys: - for i in range(self.max_stat_pos+1): + for i in range(self.max_stat_pos + 1): result = self.nodes[0].getblockstats(hash_or_height=self.start_height + i, stats=[stat]) assert_equal(list(result.keys()), [stat]) if result[stat] != self.expected_stats[i][stat]: @@ -128,8 +127,8 @@ def run_test(self): # Test invalid parameters raise the proper json exceptions tip = self.start_height + self.max_stat_pos - assert_raises_rpc_error(-8, 'Target block height %d after current tip %d' % (tip+1, tip), - self.nodes[0].getblockstats, hash_or_height=tip+1) + assert_raises_rpc_error(-8, 'Target block height %d after current tip %d' % (tip + 1, tip), + self.nodes[0].getblockstats, hash_or_height=tip + 1) assert_raises_rpc_error(-8, 'Target block height %d is negative' % (-1), self.nodes[0].getblockstats, hash_or_height=-1) @@ -137,7 +136,7 @@ def run_test(self): inv_sel_stat = 'asdfghjkl' inv_stats = [ [inv_sel_stat], - ['minfee' , inv_sel_stat], + ['minfee', inv_sel_stat], [inv_sel_stat, 'minfee'], ['minfee', inv_sel_stat, 'maxfee'], ] @@ -147,7 +146,7 @@ def run_test(self): # Make sure we aren't always returning inv_sel_stat as the culprit stat assert_raises_rpc_error(-8, 'Invalid selected statistic aaa%s' % inv_sel_stat, - self.nodes[0].getblockstats, hash_or_height=1, stats=['minfee' , 'aaa%s' % inv_sel_stat]) + self.nodes[0].getblockstats, hash_or_height=1, stats=['minfee', 'aaa%s' % inv_sel_stat]) # Mainchain's genesis block shouldn't be found on regtest assert_raises_rpc_error(-5, 'Block not found', self.nodes[0].getblockstats, hash_or_height='000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f') diff --git a/test/functional/rpc_getchaintips.py b/test/functional/rpc_getchaintips.py index c4416210ea..4135d7f001 100755 --- a/test/functional/rpc_getchaintips.py +++ b/test/functional/rpc_getchaintips.py @@ -13,7 +13,8 @@ from test_framework.test_framework import DefiTestFramework from test_framework.util import assert_equal -class GetChainTipsTest (DefiTestFramework): + +class GetChainTipsTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 4 @@ -31,33 +32,34 @@ def run_test(self): self.sync_blocks(self.nodes[:2]) self.sync_blocks(self.nodes[2:]) - tips = self.nodes[1].getchaintips () - assert_equal (len (tips), 1) + tips = self.nodes[1].getchaintips() + assert_equal(len(tips), 1) shortTip = tips[0] - assert_equal (shortTip['branchlen'], 0) - assert_equal (shortTip['height'], 210) - assert_equal (tips[0]['status'], 'active') + assert_equal(shortTip['branchlen'], 0) + assert_equal(shortTip['height'], 210) + assert_equal(tips[0]['status'], 'active') - tips = self.nodes[3].getchaintips () - assert_equal (len (tips), 1) + tips = self.nodes[3].getchaintips() + assert_equal(len(tips), 1) longTip = tips[0] - assert_equal (longTip['branchlen'], 0) - assert_equal (longTip['height'], 220) - assert_equal (tips[0]['status'], 'active') + assert_equal(longTip['branchlen'], 0) + assert_equal(longTip['height'], 220) + assert_equal(tips[0]['status'], 'active') # Join the network halves and check that we now have two tips # (at least at the nodes that previously had the short chain). - self.join_network () + self.join_network() - tips = self.nodes[0].getchaintips () - assert_equal (len (tips), 2) - assert_equal (tips[0], longTip) + tips = self.nodes[0].getchaintips() + assert_equal(len(tips), 2) + assert_equal(tips[0], longTip) - assert_equal (tips[1]['branchlen'], 10) - assert_equal (tips[1]['status'], 'valid-fork') + assert_equal(tips[1]['branchlen'], 10) + assert_equal(tips[1]['status'], 'valid-fork') tips[1]['branchlen'] = 0 tips[1]['status'] = 'active' - assert_equal (tips[1], shortTip) + assert_equal(tips[1], shortTip) + if __name__ == '__main__': - GetChainTipsTest ().main () + GetChainTipsTest().main() diff --git a/test/functional/rpc_getcustomtx.py b/test/functional/rpc_getcustomtx.py index 36aa876db7..9b8a44f951 100755 --- a/test/functional/rpc_getcustomtx.py +++ b/test/functional/rpc_getcustomtx.py @@ -13,13 +13,21 @@ import calendar import time + class TokensRPCGetCustomTX(DefiTestFramework): def set_test_params(self): self.num_nodes = 3 self.setup_clean_chain = True - self.extra_args = [['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=50', '-dakotaheight=120', '-eunosheight=120', '-eunospayaheight=120', '-fortcanningheight=120', '-fortcanninghillheight=122', '-grandcentralheight=189'], # Wallet TXs - ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=50', '-dakotaheight=120', '-eunosheight=120', '-eunospayaheight=120', '-fortcanningheight=120', '-fortcanninghillheight=122', '-grandcentralheight=189', '-txindex=1'], # Transaction index - ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=50', '-dakotaheight=120', '-eunosheight=120', '-fortcanningheight=120', '-fortcanninghillheight=122', '-grandcentralheight=189']] # Will not find historical TXs + self.extra_args = [ + ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=50', '-dakotaheight=120', + '-eunosheight=120', '-eunospayaheight=120', '-fortcanningheight=120', '-fortcanninghillheight=122', + '-grandcentralheight=189'], # Wallet TXs + ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=50', '-dakotaheight=120', + '-eunosheight=120', '-eunospayaheight=120', '-fortcanningheight=120', '-fortcanninghillheight=122', + '-grandcentralheight=189', '-txindex=1'], # Transaction index + ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=50', '-dakotaheight=120', + '-eunosheight=120', '-fortcanningheight=120', '-fortcanninghillheight=122', + '-grandcentralheight=189']] # Will not find historical TXs def check_result(self, result): # Get block hash and height @@ -100,7 +108,7 @@ def run_test(self): assert (False) except JSONRPCException as e: errorString = e.error['message'] - assert("No such mempool or wallet transaction. Use -txindex or provide a block hash." in errorString) + assert ("No such mempool or wallet transaction. Use -txindex or provide a block hash." in errorString) # Try and get history node 2 using block hash result = self.nodes[2].getcustomtx(minttx, self.nodes[0].getblockhash(self.nodes[0].getblockcount())) @@ -113,7 +121,8 @@ def run_test(self): disconnect_nodes(self.nodes[1], 2) # Update token - updatetx = self.nodes[0].updatetoken(token_silver, {"symbol":"SILVER","name":"silver","mintable":False,"tradeable":False}) + updatetx = self.nodes[0].updatetoken(token_silver, {"symbol": "SILVER", "name": "silver", "mintable": False, + "tradeable": False}) self.nodes[0].generate(1) self.sync_blocks(self.nodes[0:2]) @@ -231,7 +240,7 @@ def run_test(self): pool_share = self.nodes[0].getnewaddress("", "legacy") add_liquidity_tx = self.nodes[0].addpoolliquidity({ collateral_a: ['100@' + token_silver, '100@' + token_gold] - }, pool_share) + }, pool_share) self.nodes[0].generate(1) self.sync_blocks(self.nodes[0:2]) @@ -328,12 +337,11 @@ def run_test(self): assert_equal(list(result['results']['to'].keys())[0], collateral_b) assert_equal(list(result['results']['to'].values())[0], "1.00000000@0") - # Test send tokens to address TX self.nodes[0].utxostoaccount({collateral_a: "1@0"}) self.nodes[0].generate(1) - tokenstoaddress_tx = self.nodes[0].sendtokenstoaddress({collateral_a:"1@0"}, {collateral_b:"1@0"}) + tokenstoaddress_tx = self.nodes[0].sendtokenstoaddress({collateral_a: "1@0"}, {collateral_b: "1@0"}) self.nodes[0].generate(1) self.sync_blocks(self.nodes[0:2]) @@ -347,7 +355,7 @@ def run_test(self): assert_equal(list(result['results']['to'].values())[0], "1.00000000@0") # Test setgox TX - setgov_tx = self.nodes[0].setgov({ "LP_DAILY_DFI_REWARD": 35}) + setgov_tx = self.nodes[0].setgov({"LP_DAILY_DFI_REWARD": 35}) self.nodes[0].generate(1) self.sync_blocks(self.nodes[0:2]) @@ -433,7 +441,9 @@ def run_test(self): # Test appoint oracle new_oracle_address = self.nodes[0].getnewaddress("", "legacy") - update_oracle_tx = self.nodes[0].updateoracle(appoint_oracle_tx, new_oracle_address, [{"currency": "USD", "token": "DFI"},{"currency": "USD", "token": "TSLA"}], 10) + update_oracle_tx = self.nodes[0].updateoracle(appoint_oracle_tx, new_oracle_address, + [{"currency": "USD", "token": "DFI"}, + {"currency": "USD", "token": "TSLA"}], 10) self.nodes[0].generate(1) self.sync_blocks(self.nodes[0:2]) @@ -444,10 +454,12 @@ def run_test(self): assert_equal(result['results']['oracleId'], appoint_oracle_tx) assert_equal(result['results']['oracleAddress'], new_oracle_address) assert_equal(result['results']['weightage'], 10) - assert_equal(result['results']['availablePairs'], [{'token': 'DFI', 'currency': 'USD'}, {'token': 'TSLA', 'currency': 'USD'}]) + assert_equal(result['results']['availablePairs'], + [{'token': 'DFI', 'currency': 'USD'}, {'token': 'TSLA', 'currency': 'USD'}]) # Test set oracle data - oracle_prices = [{"currency": "USD", "tokenAmount": "100.00000000@DFI"},{"currency": "USD", "tokenAmount": "100.00000000@TSLA"}] + oracle_prices = [{"currency": "USD", "tokenAmount": "100.00000000@DFI"}, + {"currency": "USD", "tokenAmount": "100.00000000@TSLA"}] timestamp = calendar.timegm(time.gmtime()) oracle_data_tx = self.nodes[0].setoracledata(appoint_oracle_tx, timestamp, oracle_prices) self.nodes[0].generate(1) @@ -489,7 +501,7 @@ def run_test(self): self.nodes[0].addpoolliquidity({ collateral_a: ['100@' + token_silver, '100@' + token_googl] - }, pool_share) + }, pool_share) self.nodes[0].generate(1) self.nodes[0].updatepoolpair({ @@ -525,7 +537,7 @@ def run_test(self): assert_equal(result['results']['compositeDex'], 'SILVGOOGL/SILVGOLD') # Test set Governanace variable by height - setgov_height_tx = self.nodes[0].setgovheight({ "ORACLE_DEVIATION": Decimal('0.04000000')}, 1000) + setgov_height_tx = self.nodes[0].setgovheight({"ORACLE_DEVIATION": Decimal('0.04000000')}, 1000) self.nodes[0].generate(1) self.sync_blocks(self.nodes[0:2]) @@ -553,11 +565,11 @@ def run_test(self): # Test set loan token loan_token_tx = self.nodes[0].setloantoken({ - 'symbol': 'TSLA', - 'name': "TSLA", - 'fixedIntervalPriceId': "TSLA/USD", - 'mintable': False, - 'interest': 5}) + 'symbol': 'TSLA', + 'name': "TSLA", + 'fixedIntervalPriceId': "TSLA/USD", + 'mintable': False, + 'interest': 5}) self.nodes[0].generate(1) self.sync_blocks(self.nodes[0:2]) @@ -571,10 +583,10 @@ def run_test(self): assert_equal(result['results']['interest'], Decimal('5.00000000')) # Test update loan token - update_token_tx = self.nodes[0].updateloantoken(loan_token_tx ,{ - 'name': "Tesla stock token", - 'mintable': True, - 'interest': 1}) + update_token_tx = self.nodes[0].updateloantoken(loan_token_tx, { + 'name': "Tesla stock token", + 'mintable': True, + 'interest': 1}) self.nodes[0].generate(1) self.sync_blocks(self.nodes[0:2]) @@ -616,19 +628,19 @@ def run_test(self): self.nodes[0].addpoolliquidity({ self.nodes[0].get_genesis_keys().ownerAuthAddress: ['100@TSLA', '100@DUSD'] - }, pool_share) + }, pool_share) self.nodes[0].generate(1) self.nodes[0].addpoolliquidity({ self.nodes[0].get_genesis_keys().ownerAuthAddress: ['100@DUSD', '100@DFI'] - }, pool_share) + }, pool_share) self.nodes[0].generate(1) # Test set collateral token collateral_toke_tx = self.nodes[0].setcollateraltoken({ - 'token': "DFI", - 'factor': 1, - 'fixedIntervalPriceId': "DFI/USD"}) + 'token': "DFI", + 'factor': 1, + 'fixedIntervalPriceId': "DFI/USD"}) self.nodes[0].generate(1) # Get custom TX @@ -659,7 +671,8 @@ def run_test(self): # Test update vault new_vault_owner = self.nodes[0].getnewaddress("", "legacy") - update_vault_tx = self.nodes[0].updatevault(create_vault_tx, {'ownerAddress':new_vault_owner,'loanSchemeId': 'LOAN0001'}) + update_vault_tx = self.nodes[0].updatevault(create_vault_tx, + {'ownerAddress': new_vault_owner, 'loanSchemeId': 'LOAN0001'}) self.nodes[0].generate(1) self.sync_blocks(self.nodes[0:2]) @@ -685,7 +698,7 @@ def run_test(self): assert_equal(result['results']['amount'], '10.00000000@0') # Test take loan - take_loan_tx = self.nodes[0].takeloan({'vaultId':create_vault_tx,'amounts': "1@TSLA"}) + take_loan_tx = self.nodes[0].takeloan({'vaultId': create_vault_tx, 'amounts': "1@TSLA"}) self.nodes[0].generate(1) self.sync_blocks(self.nodes[0:2]) @@ -703,10 +716,10 @@ def run_test(self): # Test pay back loan vault = self.nodes[0].getvault(create_vault_tx) payback_loan_tx = self.nodes[0].paybackloan({ - 'vaultId':create_vault_tx, - 'from':new_vault_owner, - 'amounts':vault['loanAmounts'] - }) + 'vaultId': create_vault_tx, + 'from': new_vault_owner, + 'amounts': vault['loanAmounts'] + }) self.nodes[0].generate(1) self.sync_blocks(self.nodes[0:2]) @@ -750,11 +763,12 @@ def run_test(self): self.nodes[0].deposittovault(new_vault, new_vault_owner, '10@DFI') self.nodes[0].generate(1) - self.nodes[0].takeloan({'vaultId': new_vault,'amounts': '6.68896@TSLA'}) + self.nodes[0].takeloan({'vaultId': new_vault, 'amounts': '6.68896@TSLA'}) self.nodes[0].generate(5) # Test auction bid - auction_tx = self.nodes[0].placeauctionbid(new_vault, 0, self.nodes[0].get_genesis_keys().ownerAuthAddress, '7.1@TSLA') + auction_tx = self.nodes[0].placeauctionbid(new_vault, 0, self.nodes[0].get_genesis_keys().ownerAuthAddress, + '7.1@TSLA') self.nodes[0].generate(1) self.sync_blocks(self.nodes[0:2]) @@ -777,7 +791,9 @@ def run_test(self): assert_equal(result['type'], "RemoveOracleAppoint") assert_equal(result['results']['oracleId'], appoint_oracle_tx) - setgov_tx = self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/dfip2201/active':'true','v0/params/dfip2201/minswap':'0.001','v0/params/dfip2201/premium':'0.025'}}) + setgov_tx = self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/dfip2201/active': 'true', + 'v0/params/dfip2201/minswap': '0.001', + 'v0/params/dfip2201/premium': '0.025'}}) self.nodes[0].generate(1) self.sync_blocks(self.nodes[0:2]) @@ -791,5 +807,6 @@ def run_test(self): assert_equal(attributes['v0/params/dfip2201/premium'], '0.025') assert_equal(attributes['v0/params/dfip2201/minswap'], '0.001') + if __name__ == '__main__': - TokensRPCGetCustomTX().main () + TokensRPCGetCustomTX().main() diff --git a/test/functional/rpc_getmininginfo.py b/test/functional/rpc_getmininginfo.py index 45ce1b5807..b48cf93bec 100755 --- a/test/functional/rpc_getmininginfo.py +++ b/test/functional/rpc_getmininginfo.py @@ -10,6 +10,7 @@ connect_nodes_bi, ) + class GetMiningInfoRPCTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 @@ -35,7 +36,7 @@ def run_test(self): self.log.info("Restart nodes...") self.restart_node(0, ['-gen', '-dummypos=0', '-masternode_operator=' + operators[0]]) self.restart_node(1, ['-gen', '-dummypos=0', '-rewardaddress=' + operators[1]] + - ['-masternode_operator=' + x for x in operators]) + ['-masternode_operator=' + x for x in operators]) connect_nodes_bi(self.nodes, 0, 1) @@ -62,11 +63,11 @@ def run_test(self): assert_equal(resp1['masternodes'][0]['lastblockcreationattempt'] != "0", True) assert_greater_than(resp1['masternodes'][0]['mintedblocks'], 0) - assert_equal(resp1['masternodes'][1]['state'], "ENABLED") assert_equal(resp1['masternodes'][1]['generate'], True) assert_equal(resp1['masternodes'][1]['lastblockcreationattempt'] != "0", True) assert_greater_than(resp1['masternodes'][1]['mintedblocks'], 0) + if __name__ == '__main__': GetMiningInfoRPCTest().main() diff --git a/test/functional/rpc_getstoredinterest.py b/test/functional/rpc_getstoredinterest.py index f2e15cb958..81fa61cb1c 100755 --- a/test/functional/rpc_getstoredinterest.py +++ b/test/functional/rpc_getstoredinterest.py @@ -29,21 +29,20 @@ def set_test_params(self): self.fortcanninggreatworldheight = 700 self.extra_args = [ ['-txnotokens=0', - '-amkheight=1', - '-bayfrontheight=1', - '-eunosheight=1', - '-fortcanningheight=1', - '-fortcanningmuseumheight=1', - '-fortcanningparkheight=1', - '-fortcanninghillheight=1', - '-fortcanningroadheight=1', - '-fortcanningcrunchheight=1', - '-fortcanningspringheight=1', - f'-fortcanninggreatworldheight={self.fortcanninggreatworldheight}', - '-jellyfish_regtest=1', '-txindex=1', '-simulatemainnet=1'] + '-amkheight=1', + '-bayfrontheight=1', + '-eunosheight=1', + '-fortcanningheight=1', + '-fortcanningmuseumheight=1', + '-fortcanningparkheight=1', + '-fortcanninghillheight=1', + '-fortcanningroadheight=1', + '-fortcanningcrunchheight=1', + '-fortcanningspringheight=1', + f'-fortcanninggreatworldheight={self.fortcanninggreatworldheight}', + '-jellyfish_regtest=1', '-txindex=1', '-simulatemainnet=1'] ] - def new_vault(self, loan_scheme, deposit=10): vaultId = self.nodes[0].createvault(self.account0, loan_scheme) self.nodes[0].generate(1) @@ -1258,5 +1257,6 @@ def run_test(self): self.payback_loan_IPB_negative_and_ITH_positive(do_revert=rollback) self.payback_loan_IPB_negative_and_ITH_negative(do_revert=rollback) + if __name__ == '__main__': GetStoredInterestTest().main() diff --git a/test/functional/rpc_help.py b/test/functional/rpc_help.py index d27d7c4b9b..98dc0fd4be 100755 --- a/test/functional/rpc_help.py +++ b/test/functional/rpc_help.py @@ -33,7 +33,9 @@ def test_categories(self): # command titles titles = [line[3:-3] for line in node.help().splitlines() if line.startswith('==')] - components = ['Accounts', 'Blockchain', 'Control', 'Generating', 'Icxorderbook', 'Loan', 'Masternodes', 'Mining', 'Network', 'Oracles', 'Poolpair', 'Proposals', 'Rawtransactions', 'Spv', 'Stats', 'Tokens', 'Util', 'Vault'] + components = ['Accounts', 'Blockchain', 'Control', 'Generating', 'Icxorderbook', 'Loan', 'Masternodes', + 'Mining', 'Network', 'Oracles', 'Poolpair', 'Proposals', 'Rawtransactions', 'Spv', 'Stats', + 'Tokens', 'Util', 'Vault'] if self.is_wallet_compiled(): components.append('Wallet') @@ -46,7 +48,8 @@ def test_categories(self): def dump_help(self): dump_dir = os.path.join(self.options.tmpdir, 'rpc_help_dump') os.mkdir(dump_dir) - calls = [line.split(' ', 1)[0] for line in self.nodes[0].help().splitlines() if line and not line.startswith('==')] + calls = [line.split(' ', 1)[0] for line in self.nodes[0].help().splitlines() if + line and not line.startswith('==')] for call in calls: with open(os.path.join(dump_dir, call), 'w', encoding='utf-8') as f: # Make sure the node can generate the help at runtime without crashing diff --git a/test/functional/rpc_listaccounthistory.py b/test/functional/rpc_listaccounthistory.py index 60af58c64a..867e74729a 100755 --- a/test/functional/rpc_listaccounthistory.py +++ b/test/functional/rpc_listaccounthistory.py @@ -50,7 +50,7 @@ def run_test(self): # Get token ID list_tokens = self.nodes[0].listtokens() for idx, token in list_tokens.items(): - if (token["symbol"] == "GOLD"): + if token["symbol"] == "GOLD": token_a = idx # Mint some tokens diff --git a/test/functional/rpc_listgovproposals.py b/test/functional/rpc_listgovproposals.py index 0c1c09bd57..b9e6960ab8 100755 --- a/test/functional/rpc_listgovproposals.py +++ b/test/functional/rpc_listgovproposals.py @@ -13,15 +13,28 @@ from decimal import Decimal + class ListGovProposalsTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 4 self.setup_clean_chain = True self.extra_args = [ - ['-dummypos=0', '-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', '-fortcanninghillheight=1', '-fortcanningroadheight=1', '-fortcanningcrunchheight=1', '-fortcanningspringheight=1', '-fortcanninggreatworldheight=1', '-fortcanningepilogueheight=1', '-grandcentralheight=1', '-subsidytest=1', '-txindex=1'], - ['-dummypos=0', '-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', '-fortcanninghillheight=1', '-fortcanningroadheight=1', '-fortcanningcrunchheight=1', '-fortcanningspringheight=1', '-fortcanninggreatworldheight=1', '-fortcanningepilogueheight=1', '-grandcentralheight=1', '-subsidytest=1'], - ['-dummypos=0', '-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', '-fortcanninghillheight=1', '-fortcanningroadheight=1', '-fortcanningcrunchheight=1', '-fortcanningspringheight=1', '-fortcanninggreatworldheight=1', '-fortcanningepilogueheight=1', '-grandcentralheight=1', '-subsidytest=1'], - ['-dummypos=0', '-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-fortcanningheight=1', '-fortcanninghillheight=1', '-fortcanningroadheight=1', '-fortcanningcrunchheight=1', '-fortcanningspringheight=1', '-fortcanninggreatworldheight=1', '-fortcanningepilogueheight=1', '-grandcentralheight=1', '-subsidytest=1'] + ['-dummypos=0', '-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', + '-fortcanningheight=1', '-fortcanninghillheight=1', '-fortcanningroadheight=1', + '-fortcanningcrunchheight=1', '-fortcanningspringheight=1', '-fortcanninggreatworldheight=1', + '-fortcanningepilogueheight=1', '-grandcentralheight=1', '-subsidytest=1', '-txindex=1'], + ['-dummypos=0', '-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', + '-fortcanningheight=1', '-fortcanninghillheight=1', '-fortcanningroadheight=1', + '-fortcanningcrunchheight=1', '-fortcanningspringheight=1', '-fortcanninggreatworldheight=1', + '-fortcanningepilogueheight=1', '-grandcentralheight=1', '-subsidytest=1'], + ['-dummypos=0', '-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', + '-fortcanningheight=1', '-fortcanninghillheight=1', '-fortcanningroadheight=1', + '-fortcanningcrunchheight=1', '-fortcanningspringheight=1', '-fortcanninggreatworldheight=1', + '-fortcanningepilogueheight=1', '-grandcentralheight=1', '-subsidytest=1'], + ['-dummypos=0', '-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', + '-fortcanningheight=1', '-fortcanninghillheight=1', '-fortcanningroadheight=1', + '-fortcanningcrunchheight=1', '-fortcanningspringheight=1', '-fortcanninggreatworldheight=1', + '-fortcanningepilogueheight=1', '-grandcentralheight=1', '-subsidytest=1'] ] def setup(self): @@ -52,7 +65,8 @@ def setup(self): def create_proposal(self, title="default title", context="default", amount=100, cycles=1): payoutAddress = self.nodes[0].getnewaddress() - tx = self.nodes[0].creategovcfp({"title": title, "context": context, "amount": amount, "cycles": cycles, "payoutAddress": payoutAddress}) + tx = self.nodes[0].creategovcfp( + {"title": title, "context": context, "amount": amount, "cycles": cycles, "payoutAddress": payoutAddress}) self.nodes[0].generate(1) self.sync_blocks() @@ -61,15 +75,15 @@ def create_proposal(self, title="default title", context="default", amount=100, return proposal def activate_onchain_gov_attributes(self): - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/feature/gov':'true'}}) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/gov/proposals/fee_redistribution':'true'}}) - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/feature/gov-payout':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/feature/gov': 'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/gov/proposals/fee_redistribution': 'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/feature/gov-payout': 'true'}}) # VOC emergency Attributes - self.nodes[0].setgov({"ATTRIBUTES":{ - 'v0/params/feature/gov-payout':'true', + self.nodes[0].setgov({"ATTRIBUTES": { + 'v0/params/feature/gov-payout': 'true', 'v0/gov/proposals/voc_emergency_period': '25', - 'v0/gov/proposals/voc_emergency_fee':'20.00000000', - 'v0/gov/proposals/voc_approval_threshold':'50.00%' + 'v0/gov/proposals/voc_emergency_fee': '20.00000000', + 'v0/gov/proposals/voc_approval_threshold': '50.00%' }}) self.nodes[0].generate(1) self.sync_blocks() @@ -195,7 +209,7 @@ def create_10_proposals_and_aprove_half(self): for prop in tmp_proposals: assert_equal(prop["cycleEndHeight"], tmp_end_cycle_height) - self.vote_on_proposals(tmp_proposals[0 : int(len(tmp_proposals)/2)], vote="yes") + self.vote_on_proposals(tmp_proposals[0: int(len(tmp_proposals) / 2)], vote="yes") prop_list = self.nodes[0].listgovproposals() assert_equal(len(prop_list), 40) @@ -296,5 +310,6 @@ def run_test(self): self.create_10_proposals_go_to_end_cycle_2() self.create_10_proposals_and_aprove_half() + if __name__ == '__main__': ListGovProposalsTest().main() diff --git a/test/functional/rpc_listvaulthistory.py b/test/functional/rpc_listvaulthistory.py index f2a86aee58..2772e70e7d 100755 --- a/test/functional/rpc_listvaulthistory.py +++ b/test/functional/rpc_listvaulthistory.py @@ -11,11 +11,15 @@ from decimal import Decimal import time + class TokensRPCGetVaultHistory(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True - self.extra_args = [['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=50', '-dakotaheight=100', '-eunosheight=100', '-eunospayaheight=100', '-fortcanningheight=100', '-fortcanninghillheight=200', '-fortcanningepilogueheight=200', '-vaultindex=1']] + self.extra_args = [ + ['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=50', '-dakotaheight=100', + '-eunosheight=100', '-eunospayaheight=100', '-fortcanningheight=100', '-fortcanninghillheight=200', + '-fortcanningepilogueheight=200', '-vaultindex=1']] def run_test(self): self.nodes[0].generate(101) @@ -25,11 +29,13 @@ def run_test(self): # Appoint oracle oracle_address = self.nodes[0].getnewaddress("", "legacy") - appoint_oracle_tx = self.nodes[0].appointoracle(oracle_address, [{"currency": "USD", "token": "DFI"},{"currency": "USD", "token": "TSLA"}], 10) + appoint_oracle_tx = self.nodes[0].appointoracle(oracle_address, [{"currency": "USD", "token": "DFI"}, + {"currency": "USD", "token": "TSLA"}], 10) self.nodes[0].generate(1) # Test set oracle data - oracle_prices = [{"currency": "USD", "tokenAmount": "100.00000000@DFI"},{"currency": "USD", "tokenAmount": "100.00000000@TSLA"}] + oracle_prices = [{"currency": "USD", "tokenAmount": "100.00000000@DFI"}, + {"currency": "USD", "tokenAmount": "100.00000000@TSLA"}] self.nodes[0].setoracledata(appoint_oracle_tx, int(time.time()), oracle_prices) self.nodes[0].generate(1) self.sync_blocks(self.nodes[0:2]) @@ -55,11 +61,11 @@ def run_test(self): # Set loan token self.nodes[0].setloantoken({ - 'symbol': 'TSLA', - 'name': "Tesla stock token", - 'fixedIntervalPriceId': "TSLA/USD", - 'mintable': True, - 'interest': 1}) + 'symbol': 'TSLA', + 'name': "Tesla stock token", + 'fixedIntervalPriceId': "TSLA/USD", + 'mintable': True, + 'interest': 1}) self.nodes[0].generate(1) # Create pool pairs @@ -96,19 +102,19 @@ def run_test(self): pool_share = self.nodes[0].getnewaddress("", "legacy") self.nodes[0].addpoolliquidity({ self.nodes[0].get_genesis_keys().ownerAuthAddress: ['100@TSLA', '100@DUSD'] - }, pool_share) + }, pool_share) self.nodes[0].generate(1) self.nodes[0].addpoolliquidity({ self.nodes[0].get_genesis_keys().ownerAuthAddress: ['100@DUSD', '100@DFI'] - }, pool_share) + }, pool_share) self.nodes[0].generate(1) # Set collateral token self.nodes[0].setcollateraltoken({ - 'token': "DFI", - 'factor': 1, - 'fixedIntervalPriceId': "DFI/USD"}) + 'token': "DFI", + 'factor': 1, + 'fixedIntervalPriceId': "DFI/USD"}) self.nodes[0].generate(1) self.nodes[0].setcollateraltoken({ @@ -189,7 +195,7 @@ def run_test(self): self.nodes[0].generate(1) # Take loan - takeloan_tx = self.nodes[0].takeloan({'vaultId':create_vault_tx,'amounts': "1@TSLA"}) + takeloan_tx = self.nodes[0].takeloan({'vaultId': create_vault_tx, 'amounts': "1@TSLA"}) self.nodes[0].generate(1) # Update loan scheme @@ -199,10 +205,10 @@ def run_test(self): # Pay back loan vault = self.nodes[0].getvault(create_vault_tx) payback_tx = self.nodes[0].paybackloan({ - 'vaultId':create_vault_tx, - 'from':self.nodes[0].get_genesis_keys().ownerAuthAddress, - 'amounts':vault['loanAmounts'] - }) + 'vaultId': create_vault_tx, + 'from': self.nodes[0].get_genesis_keys().ownerAuthAddress, + 'amounts': vault['loanAmounts'] + }) self.nodes[0].generate(1) # Withdraw from vault @@ -273,7 +279,7 @@ def run_test(self): assert_equal(result[11]['txid'], create_vault_tx) # Test listvaulthistory block height and depth - result = self.nodes[0].listvaulthistory(create_vault_tx, {'maxBlockHeight':withdraw_height,'depth':1}) + result = self.nodes[0].listvaulthistory(create_vault_tx, {'maxBlockHeight': withdraw_height, 'depth': 1}) assert_equal(len(result), 4) assert_equal(result[0]['type'], 'WithdrawFromVault') assert_equal(result[0]['address'], 'vaultCollateral') @@ -293,7 +299,7 @@ def run_test(self): assert_equal(result[3]['txid'], payback_tx) # Test listvaulthistory token type - result = self.nodes[0].listvaulthistory(create_vault_tx, {'token':'TSLA'}) + result = self.nodes[0].listvaulthistory(create_vault_tx, {'token': 'TSLA'}) assert_equal(len(result), 2) assert_equal(result[0]['type'], 'PaybackLoan') assert_equal(result[0]['address'], self.nodes[0].get_genesis_keys().ownerAuthAddress) @@ -305,7 +311,7 @@ def run_test(self): assert_equal(result[1]['txid'], takeloan_tx) # Test listvaulthistory TX type - result = self.nodes[0].listvaulthistory(create_vault_tx, {'txtype':'J'}) + result = self.nodes[0].listvaulthistory(create_vault_tx, {'txtype': 'J'}) assert_equal(len(result), 2) assert_equal(result[0]['type'], 'WithdrawFromVault') assert_equal(result[0]['address'], 'vaultCollateral') @@ -317,7 +323,7 @@ def run_test(self): assert_equal(result[1]['txid'], withdraw_tx) # Test listvaulthistory limit - result = self.nodes[0].listvaulthistory(create_vault_tx, {'limit':1}) + result = self.nodes[0].listvaulthistory(create_vault_tx, {'limit': 1}) assert_equal(len(result), 1) assert_equal(result[0]['type'], 'CloseVault') assert_equal(result[0]['address'], close_address) @@ -350,7 +356,7 @@ def run_test(self): self.nodes[0].generate(1) # Take loan - takeloan_tx = self.nodes[0].takeloan({'vaultId': new_vault,'amounts': '6.68896@TSLA'}) + takeloan_tx = self.nodes[0].takeloan({'vaultId': new_vault, 'amounts': '6.68896@TSLA'}) self.nodes[0].generate(2) # Test state change @@ -367,11 +373,13 @@ def run_test(self): # Fund another bidding address new_bidding_address = self.nodes[0].getnewaddress("", "legacy") - self.nodes[0].accounttoaccount(self.nodes[0].get_genesis_keys().ownerAuthAddress, {new_bidding_address: "10@TSLA"}) + self.nodes[0].accounttoaccount(self.nodes[0].get_genesis_keys().ownerAuthAddress, + {new_bidding_address: "10@TSLA"}) self.nodes[0].generate(1) # Place bids - bid1_tx = self.nodes[0].placeauctionbid(new_vault, 0, self.nodes[0].get_genesis_keys().ownerAuthAddress, '8@TSLA') + bid1_tx = self.nodes[0].placeauctionbid(new_vault, 0, self.nodes[0].get_genesis_keys().ownerAuthAddress, + '8@TSLA') self.nodes[0].generate(1) bid2_tx = self.nodes[0].placeauctionbid(new_vault, 0, new_bidding_address, '9@TSLA') self.nodes[0].generate(35) @@ -397,7 +405,7 @@ def run_test(self): assert_equal(result[2]['address'], new_bidding_address) assert_equal(result[2]['amounts'], ['-9.00000000@TSLA']) else: - assert('Expected address not found in results') + assert ('Expected address not found in results') assert_equal(result[3]['type'], 'AuctionBid') assert_equal(result[3]['address'], self.nodes[0].get_genesis_keys().ownerAuthAddress) @@ -433,7 +441,7 @@ def run_test(self): self.nodes[0].generate(200 - self.nodes[0].getblockcount()) # Enable collateral payback - self.nodes[0].setgov({"ATTRIBUTES":{'v0/token/' + self.idDUSD + '/loan_payback_collateral':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/token/' + self.idDUSD + '/loan_payback_collateral': 'true'}}) self.nodes[0].generate(1) # Create vault @@ -451,7 +459,7 @@ def run_test(self): self.nodes[0].generate(1) # Take DUSD loan - self.nodes[0].takeloan({ "vaultId": vault_id, "amounts": f"1@DUSD"}) + self.nodes[0].takeloan({"vaultId": vault_id, "amounts": f"1@DUSD"}) self.nodes[0].generate(10) # Payback with collateral @@ -470,5 +478,6 @@ def run_test(self): assert_equal(result[1]['amounts'], ['0.00001142@DUSD']) assert_equal(result[1]['txid'], payback_tx) + if __name__ == '__main__': TokensRPCGetVaultHistory().main() diff --git a/test/functional/rpc_misc.py b/test/functional/rpc_misc.py index d769117335..128bc435a0 100755 --- a/test/functional/rpc_misc.py +++ b/test/functional/rpc_misc.py @@ -42,7 +42,8 @@ def run_test(self): assert_equal(tree.tag, 'malloc') except JSONRPCException: self.log.info('getmemoryinfo(mode="mallocinfo") not available') - assert_raises_rpc_error(-8, 'mallocinfo is only available when compiled with glibc 2.10+', node.getmemoryinfo, mode="mallocinfo") + assert_raises_rpc_error(-8, 'mallocinfo is only available when compiled with glibc 2.10+', + node.getmemoryinfo, mode="mallocinfo") assert_raises_rpc_error(-8, "unknown mode foobar", node.getmemoryinfo, mode="foobar") diff --git a/test/functional/rpc_mn_basic.py b/test/functional/rpc_mn_basic.py index 6a13598e1f..145f50c921 100755 --- a/test/functional/rpc_mn_basic.py +++ b/test/functional/rpc_mn_basic.py @@ -17,13 +17,18 @@ assert_raises_rpc_error, ) -class MasternodesRpcBasicTest (DefiTestFramework): + +class MasternodesRpcBasicTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 3 self.setup_clean_chain = True - self.extra_args = [['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=50', '-dakotaheight=136', '-eunosheight=140', '-eunospayaheight=140'], - ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=50', '-dakotaheight=136', '-eunosheight=140', '-eunospayaheight=140'], - ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=50', '-dakotaheight=136', '-eunosheight=140', '-eunospayaheight=140']] + self.extra_args = [ + ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=50', + '-dakotaheight=136', '-eunosheight=140', '-eunospayaheight=140'], + ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=50', + '-dakotaheight=136', '-eunosheight=140', '-eunospayaheight=140'], + ['-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-bayfrontgardensheight=50', + '-dakotaheight=136', '-eunosheight=140', '-eunospayaheight=140']] def run_test(self): assert_equal(len(self.nodes[0].listmasternodes()), 8) @@ -34,7 +39,7 @@ def run_test(self): self.stop_node(2) # CREATION: - #======================== + # ======================== collateral0 = self.nodes[0].getnewaddress("", "legacy") @@ -45,12 +50,13 @@ def run_test(self): ) except JSONRPCException as e: errorString = e.error['message'] - assert("Insufficient funds" in errorString) + assert ("Insufficient funds" in errorString) # Create node0 self.nodes[0].generate(1) collateral1 = self.nodes[1].getnewaddress("", "legacy") - assert_raises_rpc_error(-8, "Address ({}) is not owned by the wallet".format(collateral1), self.nodes[0].createmasternode, collateral1) + assert_raises_rpc_error(-8, "Address ({}) is not owned by the wallet".format(collateral1), + self.nodes[0].createmasternode, collateral1) idnode0 = self.nodes[0].createmasternode( collateral0 @@ -59,7 +65,7 @@ def run_test(self): rawTx0 = self.nodes[0].getrawtransaction(idnode0) decodeTx0 = self.nodes[0].decoderawtransaction(rawTx0) # Create and sign (only) collateral spending tx - spendTx = self.nodes[0].createrawtransaction([{'txid':idnode0, 'vout':1}],[{collateral0:9.999}]) + spendTx = self.nodes[0].createrawtransaction([{'txid': idnode0, 'vout': 1}], [{collateral0: 9.999}]) signedTx = self.nodes[0].signrawtransactionwithwallet(spendTx) assert_equal(signedTx['complete'], True) @@ -68,7 +74,7 @@ def run_test(self): self.nodes[0].sendrawtransaction(signedTx['hex']) except JSONRPCException as e: errorString = e.error['message'] - assert("collateral-locked-in-mempool," in errorString) + assert ("collateral-locked-in-mempool," in errorString) balance_before_creation = self.nodes[0].getbalance() self.nodes[0].generate(1) @@ -88,11 +94,10 @@ def run_test(self): self.nodes[0].sendrawtransaction(signedTx['hex']) except JSONRPCException as e: errorString = e.error['message'] - assert("collateral-locked," in errorString) - + assert ("collateral-locked," in errorString) # RESIGNING: - #======================== + # ======================== # Fail to resign: Have no money on ownerauth address # Deprecated due to auth automation @@ -120,9 +125,8 @@ def run_test(self): # Don't mine here, check mempool after reorg! # self.nodes[0].generate(1) - # REVERTING: - #======================== + # ======================== # Revert resign! self.start_node(1) @@ -151,14 +155,14 @@ def run_test(self): assert_equal(len(self.nodes[0].listmasternodes()), 8) mempool = self.nodes[0].getrawmempool() - assert_equal(len(mempool), 1) # auto auth + assert_equal(len(mempool), 1) # auto auth collateral0 = self.nodes[0].getnewaddress("", "legacy") self.nodes[0].createmasternode(collateral0) balance_before_creation = self.nodes[0].getbalance() self.nodes[0].generate(1) # At this point, mn was created - assert_equal(self.nodes[0].getblockcount(), 136) # Dakota height + assert_equal(self.nodes[0].getblockcount(), 136) # Dakota height assert_equal(balance_before_creation - 2 + 50, self.nodes[0].getbalance()) self.nodes[0].generate(3) @@ -169,15 +173,16 @@ def run_test(self): if outputs['scriptPubKey']['addresses'][0] == collateral0: vout = outputs['n'] - assert_equal(self.nodes[0].getblockcount(), 140) # Eunos height + assert_equal(self.nodes[0].getblockcount(), 140) # Eunos height # get createmasternode data data = decodeTx0['vout'][0]['scriptPubKey']['hex'][4:] - cmTx = self.nodes[0].createrawtransaction([{'txid':colTx,'vout':vout}], [{'data':data},{collateral1:2}]) + cmTx = self.nodes[0].createrawtransaction([{'txid': colTx, 'vout': vout}], [{'data': data}, {collateral1: 2}]) # HACK replace vout 0 to 1DFI cmTx = cmTx.replace('020000000000000000', '0200e1f50500000000') signedTx = self.nodes[0].signrawtransactionwithwallet(cmTx) assert_equal(signedTx['complete'], True) - assert_raises_rpc_error(-26, 'masternode creation needs owner auth', self.nodes[0].sendrawtransaction, signedTx['hex']) + assert_raises_rpc_error(-26, 'masternode creation needs owner auth', self.nodes[0].sendrawtransaction, + signedTx['hex']) # Test new register delay mnAddress = self.nodes[0].getnewaddress("", "legacy") @@ -201,7 +206,7 @@ def run_test(self): self.nodes[0].resignmasternode(mnTx) except JSONRPCException as e: errorString = e.error['message'] - assert("state is not 'ENABLED'" in errorString) + assert ("state is not 'ENABLED'" in errorString) # Check end of PRE_ENABLED range self.nodes[0].generate(19) @@ -212,7 +217,7 @@ def run_test(self): assert_equal(self.nodes[0].listmasternodes({}, False)[mnTx], "ENABLED") blocks = self.nodes[0].getmasternodeblocks({'ownerAddress': mnAddress}) - assert_equal(len(blocks), 0) # there is no minted blocks yet + assert_equal(len(blocks), 0) # there is no minted blocks yet # test getmasternodeblocks self.nodes[0].generate(1) @@ -244,5 +249,6 @@ def run_test(self): self.nodes[0].generate(1) assert_equal(self.nodes[0].listmasternodes()[mnTx]['state'], "RESIGNED") + if __name__ == '__main__': - MasternodesRpcBasicTest ().main () + MasternodesRpcBasicTest().main() diff --git a/test/functional/rpc_named_arguments.py b/test/functional/rpc_named_arguments.py index 55b268636a..1fb6b8b76d 100755 --- a/test/functional/rpc_named_arguments.py +++ b/test/functional/rpc_named_arguments.py @@ -10,6 +10,7 @@ assert_raises_rpc_error, ) + class NamedArgumentTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 @@ -25,10 +26,11 @@ def run_test(self): node.getblock(blockhash=h) assert_equal(node.echo(), []) - assert_equal(node.echo(arg0=0,arg9=9), [0] + [None]*8 + [9]) + assert_equal(node.echo(arg0=0, arg9=9), [0] + [None] * 8 + [9]) assert_equal(node.echo(arg1=1), [None, 1]) - assert_equal(node.echo(arg9=None), [None]*10) - assert_equal(node.echo(arg0=0,arg3=3,arg9=9), [0] + [None]*2 + [3] + [None]*5 + [9]) + assert_equal(node.echo(arg9=None), [None] * 10) + assert_equal(node.echo(arg0=0, arg3=3, arg9=9), [0] + [None] * 2 + [3] + [None] * 5 + [9]) + if __name__ == '__main__': NamedArgumentTest().main() diff --git a/test/functional/rpc_net.py b/test/functional/rpc_net.py index 741ba80244..10bd4000b8 100755 --- a/test/functional/rpc_net.py +++ b/test/functional/rpc_net.py @@ -22,11 +22,12 @@ from test_framework.mininode import P2PInterface from test_framework.messages import CAddress, msg_addr, NODE_NETWORK, NODE_WITNESS + class NetTest(DefiTestFramework): def set_test_params(self): self.setup_clean_chain = True self.num_nodes = 2 - self.extra_args = [["-minrelaytxfee=0.00001000"],["-minrelaytxfee=0.00000500"]] + self.extra_args = [["-minrelaytxfee=0.00001000"], ["-minrelaytxfee=0.00000500"]] def run_test(self): self._test_connection_count() @@ -62,13 +63,19 @@ def _test_getnettotals(self): # the bytes sent/received should change # note ping and pong are 32 bytes each self.nodes[0].ping() - wait_until(lambda: (self.nodes[0].getnettotals()['totalbytessent'] >= net_totals_after['totalbytessent'] + 32 * 2), timeout=1) - wait_until(lambda: (self.nodes[0].getnettotals()['totalbytesrecv'] >= net_totals_after['totalbytesrecv'] + 32 * 2), timeout=1) + wait_until( + lambda: (self.nodes[0].getnettotals()['totalbytessent'] >= net_totals_after['totalbytessent'] + 32 * 2), + timeout=1) + wait_until( + lambda: (self.nodes[0].getnettotals()['totalbytesrecv'] >= net_totals_after['totalbytesrecv'] + 32 * 2), + timeout=1) peer_info_after_ping = self.nodes[0].getpeerinfo() for before, after in zip(peer_info, peer_info_after_ping): - assert_greater_than_or_equal(after['bytesrecv_per_msg'].get('pong', 0), before['bytesrecv_per_msg'].get('pong', 0) + 32) - assert_greater_than_or_equal(after['bytessent_per_msg'].get('ping', 0), before['bytessent_per_msg'].get('ping', 0) + 32) + assert_greater_than_or_equal(after['bytesrecv_per_msg'].get('pong', 0), + before['bytesrecv_per_msg'].get('pong', 0) + 32) + assert_greater_than_or_equal(after['bytessent_per_msg'].get('ping', 0), + before['bytessent_per_msg'].get('ping', 0) + 32) def _test_getnetworkinginfo(self): assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], True) @@ -127,7 +134,7 @@ def _test_getnodeaddresses(self): node_addresses = self.nodes[0].getnodeaddresses(REQUEST_COUNT) assert_equal(len(node_addresses), REQUEST_COUNT) for a in node_addresses: - assert_greater_than(a["time"], 1527811200) # 1st June 2018 + assert_greater_than(a["time"], 1527811200) # 1st June 2018 assert_equal(a["services"], NODE_NETWORK | NODE_WITNESS) assert a["address"] in imported_addrs assert_equal(a["port"], 8555) @@ -140,5 +147,6 @@ def _test_getnodeaddresses(self): node_addresses = self.nodes[0].getnodeaddresses(LARGE_REQUEST_COUNT) assert_greater_than(LARGE_REQUEST_COUNT, len(node_addresses)) + if __name__ == '__main__': NetTest().main() diff --git a/test/functional/rpc_preciousblock.py b/test/functional/rpc_preciousblock.py index 7f03f5ef49..0892a8cefd 100755 --- a/test/functional/rpc_preciousblock.py +++ b/test/functional/rpc_preciousblock.py @@ -4,12 +4,13 @@ # file LICENSE or http://www.opensource.org/licenses/mit-license.php. """Test the preciousblock RPC.""" -from test_framework.test_framework import DefiTestFramework +from test_framework.test_framework import DefiTestFramework, JSONRPCException from test_framework.util import ( assert_equal, connect_nodes_bi, ) + def unidirectional_node_sync_via_rpc(node_src, node_dest): blocks_to_copy = [] blockhash = node_src.getbestblockhash() @@ -17,7 +18,7 @@ def unidirectional_node_sync_via_rpc(node_src, node_dest): try: assert len(node_dest.getblock(blockhash, False)) > 0 break - except: + except JSONRPCException: blocks_to_copy.append(blockhash) blockhash = node_src.getblockheader(blockhash, True)['previousblockhash'] blocks_to_copy.reverse() @@ -25,6 +26,7 @@ def unidirectional_node_sync_via_rpc(node_src, node_dest): blockdata = node_src.getblock(blockhash, False) assert node_dest.submitblock(blockdata) in (None, 'inconclusive') + def node_sync_via_rpc(nodes): for node_src in nodes: for node_dest in nodes: @@ -32,6 +34,7 @@ def node_sync_via_rpc(nodes): continue unidirectional_node_sync_via_rpc(node_src, node_dest) + class PreciousTest(DefiTestFramework): def set_test_params(self): self.setup_clean_chain = True @@ -60,7 +63,7 @@ def run_test(self): self.log.info("Connect nodes and check no reorg occurs") # Submit competing blocks via RPC so any reorg should occur before we proceed (no way to wait on inaction for p2p sync) node_sync_via_rpc(self.nodes[0:2]) - connect_nodes_bi(self.nodes,0,1) + connect_nodes_bi(self.nodes, 0, 1) assert_equal(self.nodes[0].getbestblockhash(), hashC) assert_equal(self.nodes[1].getbestblockhash(), hashG) self.log.info("Make Node0 prefer block G") @@ -97,8 +100,8 @@ def run_test(self): hashL = self.nodes[2].getbestblockhash() self.log.info("Connect nodes and check no reorg occurs") node_sync_via_rpc(self.nodes[1:3]) - connect_nodes_bi(self.nodes,1,2) - connect_nodes_bi(self.nodes,0,2) + connect_nodes_bi(self.nodes, 1, 2) + connect_nodes_bi(self.nodes, 0, 2) assert_equal(self.nodes[0].getbestblockhash(), hashH) assert_equal(self.nodes[1].getbestblockhash(), hashH) assert_equal(self.nodes[2].getbestblockhash(), hashL) @@ -109,5 +112,6 @@ def run_test(self): self.nodes[2].preciousblock(hashH) assert_equal(self.nodes[2].getbestblockhash(), hashH) + if __name__ == '__main__': PreciousTest().main() diff --git a/test/functional/rpc_psbt.py b/test/functional/rpc_psbt.py index d1771d9c4a..4bdcb7d71d 100755 --- a/test/functional/rpc_psbt.py +++ b/test/functional/rpc_psbt.py @@ -21,6 +21,7 @@ MAX_BIP125_RBF_SEQUENCE = 0xfffffffd + # Create one-input, one-output, no-fee transaction: class PSBTTest(DefiTestFramework): @@ -57,7 +58,8 @@ def test_utxo_conversion(self): # Construct an unsigned PSBT on the online node (who doesn't know the output is Segwit, so will include a non-witness UTXO) utxos = online_node.listunspent(addresses=[offline_addr]) - raw = online_node.createrawtransaction([{"txid":utxos[0]["txid"], "vout":utxos[0]["vout"]}],[{online_addr:0.9999}]) + raw = online_node.createrawtransaction([{"txid": utxos[0]["txid"], "vout": utxos[0]["vout"]}], + [{online_addr: 0.9999}]) psbt = online_node.walletprocesspsbt(online_node.converttopsbt(raw))["psbt"] assert "non_witness_utxo" in mining_node.decodepsbt(psbt)["inputs"][0] @@ -69,7 +71,7 @@ def test_utxo_conversion(self): txid = mining_node.sendrawtransaction(mining_node.finalizepsbt(signed_psbt)["hex"]) mining_node.generate(1) self.sync_blocks([mining_node, online_node]) - assert_equal(online_node.gettxout(txid,0)["confirmations"], 1) + assert_equal(online_node.gettxout(txid, 0)["confirmations"], 1) # Reconnect connect_nodes_bi(self.nodes, 0, 1) @@ -77,7 +79,7 @@ def test_utxo_conversion(self): def run_test(self): # Create and fund a raw tx for sending 10 BTC - psbtx1 = self.nodes[0].walletcreatefundedpsbt([], {self.nodes[2].getnewaddress():10})['psbt'] + psbtx1 = self.nodes[0].walletcreatefundedpsbt([], {self.nodes[2].getnewaddress(): 10})['psbt'] # Node 1 should not be able to add anything to it but still return the psbtx same as before psbtx = self.nodes[1].walletprocesspsbt(psbtx1)['psbt'] @@ -100,8 +102,10 @@ def run_test(self): p2sh_p2wpkh = self.nodes[1].getnewaddress("", "p2sh-segwit") # fund those addresses - rawtx = self.nodes[0].createrawtransaction([], {p2sh:10, p2wsh:10, p2wpkh:10, p2sh_p2wsh:10, p2sh_p2wpkh:10, p2pkh:10}) - rawtx = self.nodes[0].fundrawtransaction(rawtx, {"changePosition":3}) + rawtx = self.nodes[0].createrawtransaction([], + {p2sh: 10, p2wsh: 10, p2wpkh: 10, p2sh_p2wsh: 10, p2sh_p2wpkh: 10, + p2pkh: 10}) + rawtx = self.nodes[0].fundrawtransaction(rawtx, {"changePosition": 3}) signed_tx = self.nodes[0].signrawtransactionwithwallet(rawtx['hex'])['hex'] txid = self.nodes[0].sendrawtransaction(signed_tx) self.nodes[0].generate(6) @@ -130,22 +134,31 @@ def run_test(self): p2pkh_pos = out['n'] # spend single key from node 1 - rawtx = self.nodes[1].walletcreatefundedpsbt([{"txid":txid,"vout":p2wpkh_pos},{"txid":txid,"vout":p2sh_p2wpkh_pos},{"txid":txid,"vout":p2pkh_pos}], {self.nodes[1].getnewaddress():29.99})['psbt'] + rawtx = self.nodes[1].walletcreatefundedpsbt( + [{"txid": txid, "vout": p2wpkh_pos}, {"txid": txid, "vout": p2sh_p2wpkh_pos}, + {"txid": txid, "vout": p2pkh_pos}], {self.nodes[1].getnewaddress(): 29.99})['psbt'] walletprocesspsbt_out = self.nodes[1].walletprocesspsbt(rawtx) assert_equal(walletprocesspsbt_out['complete'], True) self.nodes[1].sendrawtransaction(self.nodes[1].finalizepsbt(walletprocesspsbt_out['psbt'])['hex']) # feeRate of 0.1 BTC / KB produces a total fee slightly below -maxtxfee (~0.05280000): - res = self.nodes[1].walletcreatefundedpsbt([{"txid":txid,"vout":p2wpkh_pos},{"txid":txid,"vout":p2sh_p2wpkh_pos},{"txid":txid,"vout":p2pkh_pos}], {self.nodes[1].getnewaddress():29.99}, 0, {"feeRate": 0.1}) + res = self.nodes[1].walletcreatefundedpsbt( + [{"txid": txid, "vout": p2wpkh_pos}, {"txid": txid, "vout": p2sh_p2wpkh_pos}, + {"txid": txid, "vout": p2pkh_pos}], {self.nodes[1].getnewaddress(): 29.99}, 0, {"feeRate": 0.1}) assert_greater_than(res["fee"], 0.05) assert_greater_than(0.06, res["fee"]) # feeRate of 10 BTC / KB produces a total fee well above -maxtxfee # previously this was silently capped at -maxtxfee - assert_raises_rpc_error(-4, "Fee exceeds maximum configured by -maxtxfee", self.nodes[1].walletcreatefundedpsbt, [{"txid":txid,"vout":p2wpkh_pos},{"txid":txid,"vout":p2sh_p2wpkh_pos},{"txid":txid,"vout":p2pkh_pos}], {self.nodes[1].getnewaddress():29.99}, 0, {"feeRate": 10}) + assert_raises_rpc_error(-4, "Fee exceeds maximum configured by -maxtxfee", self.nodes[1].walletcreatefundedpsbt, + [{"txid": txid, "vout": p2wpkh_pos}, {"txid": txid, "vout": p2sh_p2wpkh_pos}, + {"txid": txid, "vout": p2pkh_pos}], {self.nodes[1].getnewaddress(): 29.99}, 0, + {"feeRate": 10}) # partially sign multisig things with node 1 - psbtx = self.nodes[1].walletcreatefundedpsbt([{"txid":txid,"vout":p2wsh_pos},{"txid":txid,"vout":p2sh_pos},{"txid":txid,"vout":p2sh_p2wsh_pos}], {self.nodes[1].getnewaddress():29.99})['psbt'] + psbtx = self.nodes[1].walletcreatefundedpsbt( + [{"txid": txid, "vout": p2wsh_pos}, {"txid": txid, "vout": p2sh_pos}, + {"txid": txid, "vout": p2sh_p2wsh_pos}], {self.nodes[1].getnewaddress(): 29.99})['psbt'] walletprocesspsbt_out = self.nodes[1].walletprocesspsbt(psbtx) psbtx = walletprocesspsbt_out['psbt'] assert_equal(walletprocesspsbt_out['complete'], False) @@ -156,11 +169,12 @@ def run_test(self): self.nodes[2].sendrawtransaction(self.nodes[2].finalizepsbt(walletprocesspsbt_out['psbt'])['hex']) # check that walletprocesspsbt fails to decode a non-psbt - rawtx = self.nodes[1].createrawtransaction([{"txid":txid,"vout":p2wpkh_pos}], {self.nodes[1].getnewaddress():9.99}) + rawtx = self.nodes[1].createrawtransaction([{"txid": txid, "vout": p2wpkh_pos}], + {self.nodes[1].getnewaddress(): 9.99}) assert_raises_rpc_error(-22, "TX decode failed", self.nodes[1].walletprocesspsbt, rawtx) # Convert a non-psbt to psbt and make sure we can decode it - rawtx = self.nodes[0].createrawtransaction([], {self.nodes[1].getnewaddress():10}) + rawtx = self.nodes[0].createrawtransaction([], {self.nodes[1].getnewaddress(): 10}) rawtx = self.nodes[0].fundrawtransaction(rawtx) new_psbt = self.nodes[0].converttopsbt(rawtx['hex']) self.nodes[0].decodepsbt(new_psbt) @@ -170,7 +184,8 @@ def run_test(self): # We must set iswitness=True because the serialized transaction has inputs and is therefore a witness transaction signedtx = self.nodes[0].signrawtransactionwithwallet(rawtx['hex']) assert_raises_rpc_error(-22, "", self.nodes[0].converttopsbt, hexstring=signedtx['hex'], iswitness=True) - assert_raises_rpc_error(-22, "", self.nodes[0].converttopsbt, hexstring=signedtx['hex'], permitsigdata=False, iswitness=True) + assert_raises_rpc_error(-22, "", self.nodes[0].converttopsbt, hexstring=signedtx['hex'], permitsigdata=False, + iswitness=True) # Unless we allow it to convert and strip signatures self.nodes[0].converttopsbt(signedtx['hex'], True) @@ -189,7 +204,8 @@ def run_test(self): vout2 = find_output(self.nodes[2], txid2, 13, blockhash=blockhash) # Create a psbt spending outputs from nodes 1 and 2 - psbt_orig = self.nodes[0].createpsbt([{"txid":txid1, "vout":vout1}, {"txid":txid2, "vout":vout2}], {self.nodes[0].getnewaddress():25.999}) + psbt_orig = self.nodes[0].createpsbt([{"txid": txid1, "vout": vout1}, {"txid": txid2, "vout": vout2}], + {self.nodes[0].getnewaddress(): 25.999}) # Update psbts, should only have data for one input and not the other psbt1 = self.nodes[1].walletprocesspsbt(psbt_orig)['psbt'] @@ -212,15 +228,19 @@ def run_test(self): # replaceable arg block_height = self.nodes[0].getblockcount() unspent = self.nodes[0].listunspent()[0] - psbtx_info = self.nodes[0].walletcreatefundedpsbt([{"txid":unspent["txid"], "vout":unspent["vout"]}], [{self.nodes[2].getnewaddress():unspent["amount"]+1}], block_height+2, {"replaceable": False}, False) + psbtx_info = self.nodes[0].walletcreatefundedpsbt([{"txid": unspent["txid"], "vout": unspent["vout"]}], + [{self.nodes[2].getnewaddress(): unspent["amount"] + 1}], + block_height + 2, {"replaceable": False}, False) decoded_psbt = self.nodes[0].decodepsbt(psbtx_info["psbt"]) for tx_in, psbt_in in zip(decoded_psbt["tx"]["vin"], decoded_psbt["inputs"]): assert_greater_than(tx_in["sequence"], MAX_BIP125_RBF_SEQUENCE) assert "bip32_derivs" not in psbt_in - assert_equal(decoded_psbt["tx"]["locktime"], block_height+2) + assert_equal(decoded_psbt["tx"]["locktime"], block_height + 2) # Same construction with only locktime set and RBF explicitly enabled - psbtx_info = self.nodes[0].walletcreatefundedpsbt([{"txid":unspent["txid"], "vout":unspent["vout"]}], [{self.nodes[2].getnewaddress():unspent["amount"]+1}], block_height, {"replaceable": True}, True) + psbtx_info = self.nodes[0].walletcreatefundedpsbt([{"txid": unspent["txid"], "vout": unspent["vout"]}], + [{self.nodes[2].getnewaddress(): unspent["amount"] + 1}], + block_height, {"replaceable": True}, True) decoded_psbt = self.nodes[0].decodepsbt(psbtx_info["psbt"]) for tx_in, psbt_in in zip(decoded_psbt["tx"]["vin"], decoded_psbt["inputs"]): assert_equal(tx_in["sequence"], MAX_BIP125_RBF_SEQUENCE) @@ -228,7 +248,8 @@ def run_test(self): assert_equal(decoded_psbt["tx"]["locktime"], block_height) # Same construction without optional arguments - psbtx_info = self.nodes[0].walletcreatefundedpsbt([{"txid":unspent["txid"], "vout":unspent["vout"]}], [{self.nodes[2].getnewaddress():unspent["amount"]+1}]) + psbtx_info = self.nodes[0].walletcreatefundedpsbt([{"txid": unspent["txid"], "vout": unspent["vout"]}], + [{self.nodes[2].getnewaddress(): unspent["amount"] + 1}]) decoded_psbt = self.nodes[0].decodepsbt(psbtx_info["psbt"]) for tx_in in decoded_psbt["tx"]["vin"]: assert_equal(tx_in["sequence"], MAX_BIP125_RBF_SEQUENCE) @@ -236,17 +257,21 @@ def run_test(self): # Same construction without optional arguments, for a node with -walletrbf=0 unspent1 = self.nodes[1].listunspent()[0] - psbtx_info = self.nodes[1].walletcreatefundedpsbt([{"txid":unspent1["txid"], "vout":unspent1["vout"]}], [{self.nodes[2].getnewaddress():unspent1["amount"]+1}], block_height) + psbtx_info = self.nodes[1].walletcreatefundedpsbt([{"txid": unspent1["txid"], "vout": unspent1["vout"]}], + [{self.nodes[2].getnewaddress(): unspent1["amount"] + 1}], + block_height) decoded_psbt = self.nodes[1].decodepsbt(psbtx_info["psbt"]) for tx_in in decoded_psbt["tx"]["vin"]: assert_greater_than(tx_in["sequence"], MAX_BIP125_RBF_SEQUENCE) # Make sure change address wallet does not have P2SH innerscript access to results in success # when attempting BnB coin selection - self.nodes[0].walletcreatefundedpsbt([], [{self.nodes[2].getnewaddress():unspent["amount"]+1}], block_height+2, {"changeAddress":self.nodes[1].getnewaddress()}, False) + self.nodes[0].walletcreatefundedpsbt([], [{self.nodes[2].getnewaddress(): unspent["amount"] + 1}], + block_height + 2, {"changeAddress": self.nodes[1].getnewaddress()}, False) # Regression test for 14473 (mishandling of already-signed witness transaction): - psbtx_info = self.nodes[0].walletcreatefundedpsbt([{"txid":unspent["txid"], "vout":unspent["vout"]}], [{self.nodes[2].getnewaddress():unspent["amount"]+1}]) + psbtx_info = self.nodes[0].walletcreatefundedpsbt([{"txid": unspent["txid"], "vout": unspent["vout"]}], + [{self.nodes[2].getnewaddress(): unspent["amount"] + 1}]) complete_psbt = self.nodes[0].walletprocesspsbt(psbtx_info["psbt"]) double_processed_psbt = self.nodes[0].walletprocesspsbt(complete_psbt["psbt"]) assert_equal(complete_psbt, double_processed_psbt) @@ -261,7 +286,8 @@ def run_test(self): assert_equal(unknown_psbt, unknown_out) # Open the data file - with open(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data/rpc_psbt.json'), encoding='utf-8') as f: + with open(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data/rpc_psbt.json'), + encoding='utf-8') as f: d = json.load(f) invalids = d['invalid'] valids = d['valid'] @@ -319,11 +345,12 @@ def run_test(self): # Test that psbts with p2pkh outputs are created properly p2pkh = self.nodes[0].getnewaddress(address_type='legacy') - psbt = self.nodes[1].walletcreatefundedpsbt([], [{p2pkh : 1}], 0, {"includeWatching" : True}, True) + psbt = self.nodes[1].walletcreatefundedpsbt([], [{p2pkh: 1}], 0, {"includeWatching": True}, True) self.nodes[0].decodepsbt(psbt['psbt']) # Test decoding error: invalid base64 - assert_raises_rpc_error(-22, "TX decode failed invalid base64", self.nodes[0].decodepsbt, ";definitely not base64;") + assert_raises_rpc_error(-22, "TX decode failed invalid base64", self.nodes[0].decodepsbt, + ";definitely not base64;") # Send to all types of addresses addr1 = self.nodes[1].getnewaddress("", "bech32") @@ -342,7 +369,9 @@ def test_psbt_input_keys(psbt_input, keys): assert_equal(set(keys), set(psbt_input.keys())) # Create a PSBT. None of the inputs are filled initially - psbt = self.nodes[1].createpsbt([{"txid":txid1, "vout":vout1},{"txid":txid2, "vout":vout2},{"txid":txid3, "vout":vout3}], {self.nodes[0].getnewaddress():32.999}) + psbt = self.nodes[1].createpsbt( + [{"txid": txid1, "vout": vout1}, {"txid": txid2, "vout": vout2}, {"txid": txid3, "vout": vout3}], + {self.nodes[0].getnewaddress(): 32.999}) decoded = self.nodes[1].decodepsbt(psbt) test_psbt_input_keys(decoded['inputs'][0], []) test_psbt_input_keys(decoded['inputs'][1], []) @@ -357,7 +386,7 @@ def test_psbt_input_keys(psbt_input, keys): test_psbt_input_keys(decoded['inputs'][2], []) # Try again, now while providing descriptors, making P2SH-segwit work, and causing bip32_derivs and redeem_script to be filled in - descs = [self.nodes[1].getaddressinfo(addr)['desc'] for addr in [addr1,addr2,addr3]] + descs = [self.nodes[1].getaddressinfo(addr)['desc'] for addr in [addr1, addr2, addr3]] updated = self.nodes[1].utxoupdatepsbt(psbt=psbt, descriptors=descs) decoded = self.nodes[1].decodepsbt(updated) test_psbt_input_keys(decoded['inputs'][0], ['witness_utxo', 'bip32_derivs']) @@ -365,7 +394,8 @@ def test_psbt_input_keys(psbt_input, keys): test_psbt_input_keys(decoded['inputs'][2], ['witness_utxo', 'bip32_derivs', 'redeem_script']) # Two PSBTs with a common input should not be joinable - psbt1 = self.nodes[1].createpsbt([{"txid":txid1, "vout":vout1}], {self.nodes[0].getnewaddress():Decimal('10.999')}) + psbt1 = self.nodes[1].createpsbt([{"txid": txid1, "vout": vout1}], + {self.nodes[0].getnewaddress(): Decimal('10.999')}) assert_raises_rpc_error(-8, "exists in multiple PSBTs", self.nodes[1].joinpsbts, [psbt1, updated]) # Join two distinct PSBTs @@ -374,13 +404,16 @@ def test_psbt_input_keys(psbt_input, keys): vout4 = find_output(self.nodes[0], txid4, 5) self.nodes[0].generate(6) self.sync_blocks() - psbt2 = self.nodes[1].createpsbt([{"txid":txid4, "vout":vout4}], {self.nodes[0].getnewaddress():Decimal('4.999')}) + psbt2 = self.nodes[1].createpsbt([{"txid": txid4, "vout": vout4}], + {self.nodes[0].getnewaddress(): Decimal('4.999')}) psbt2 = self.nodes[1].walletprocesspsbt(psbt2)['psbt'] psbt2_decoded = self.nodes[0].decodepsbt(psbt2) assert "final_scriptwitness" in psbt2_decoded['inputs'][0] and "final_scriptSig" in psbt2_decoded['inputs'][0] joined = self.nodes[0].joinpsbts([psbt, psbt2]) joined_decoded = self.nodes[0].decodepsbt(joined) - assert len(joined_decoded['inputs']) == 4 and len(joined_decoded['outputs']) == 2 and "final_scriptwitness" not in joined_decoded['inputs'][3] and "final_scriptSig" not in joined_decoded['inputs'][3] + assert len(joined_decoded['inputs']) == 4 and len( + joined_decoded['outputs']) == 2 and "final_scriptwitness" not in joined_decoded['inputs'][ + 3] and "final_scriptSig" not in joined_decoded['inputs'][3] # Newly created PSBT needs UTXOs and updating addr = self.nodes[1].getnewaddress("", "p2sh-segwit") @@ -389,22 +422,29 @@ def test_psbt_input_keys(psbt_input, keys): blockhash = self.nodes[0].generate(6)[0] self.sync_blocks() vout = find_output(self.nodes[0], txid, 7, blockhash=blockhash) - psbt = self.nodes[1].createpsbt([{"txid":txid, "vout":vout}], {self.nodes[0].getnewaddress("", "p2sh-segwit"):Decimal('6.999')}) + psbt = self.nodes[1].createpsbt([{"txid": txid, "vout": vout}], + {self.nodes[0].getnewaddress("", "p2sh-segwit"): Decimal('6.999')}) analyzed = self.nodes[0].analyzepsbt(psbt) - assert not analyzed['inputs'][0]['has_utxo'] and not analyzed['inputs'][0]['is_final'] and analyzed['inputs'][0]['next'] == 'updater' and analyzed['next'] == 'updater' + assert not analyzed['inputs'][0]['has_utxo'] and not analyzed['inputs'][0]['is_final'] and \ + analyzed['inputs'][0]['next'] == 'updater' and analyzed['next'] == 'updater' # After update with wallet, only needs signing updated = self.nodes[1].walletprocesspsbt(psbt, False, 'ALL', True)['psbt'] analyzed = self.nodes[0].analyzepsbt(updated) - assert analyzed['inputs'][0]['has_utxo'] and not analyzed['inputs'][0]['is_final'] and analyzed['inputs'][0]['next'] == 'signer' and analyzed['next'] == 'signer' and analyzed['inputs'][0]['missing']['signatures'][0] == addrinfo['embedded']['witness_program'] + assert analyzed['inputs'][0]['has_utxo'] and not analyzed['inputs'][0]['is_final'] and analyzed['inputs'][0][ + 'next'] == 'signer' and analyzed['next'] == 'signer' and analyzed['inputs'][0]['missing']['signatures'][ + 0] == addrinfo['embedded']['witness_program'] # Check fee and size things - assert analyzed['fee'] == Decimal('0.001') and analyzed['estimated_vsize'] == 134 and analyzed['estimated_feerate'] == Decimal('0.00746268') + assert analyzed['fee'] == Decimal('0.001') and analyzed['estimated_vsize'] == 134 and analyzed[ + 'estimated_feerate'] == Decimal('0.00746268') # After signing and finalizing, needs extracting signed = self.nodes[1].walletprocesspsbt(updated)['psbt'] analyzed = self.nodes[0].analyzepsbt(signed) - assert analyzed['inputs'][0]['has_utxo'] and analyzed['inputs'][0]['is_final'] and analyzed['next'] == 'extractor' + assert analyzed['inputs'][0]['has_utxo'] and analyzed['inputs'][0]['is_final'] and analyzed[ + 'next'] == 'extractor' + if __name__ == '__main__': PSBTTest().main() diff --git a/test/functional/rpc_rawtransaction.py b/test/functional/rpc_rawtransaction.py index e09326e6dd..cb0ed02005 100755 --- a/test/functional/rpc_rawtransaction.py +++ b/test/functional/rpc_rawtransaction.py @@ -19,6 +19,7 @@ from test_framework.test_framework import DefiTestFramework from test_framework.util import assert_equal, assert_raises_rpc_error, hex_str_to_bytes + class multidict(dict): """Dictionary that allows duplicate keys. @@ -57,9 +58,9 @@ def run_test(self): self.sync_blocks() self.nodes[0].generate(101) self.sync_blocks() - self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),1.5) - self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),1.0) - self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),5.0) + self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.5) + self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.0) + self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 5.0) self.sync_mempools() self.nodes[0].generate(5) self.sync_blocks() @@ -82,36 +83,56 @@ def run_test(self): # Test `createrawtransaction` invalid `inputs` txid = '1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000' assert_raises_rpc_error(-3, "Expected type array", self.nodes[0].createrawtransaction, 'foo', {}) - assert_raises_rpc_error(-1, "JSON value is not an object as expected", self.nodes[0].createrawtransaction, ['foo'], {}) - assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[0].createrawtransaction, [{}], {}) - assert_raises_rpc_error(-8, "txid must be of length 64 (not 3, for 'foo')", self.nodes[0].createrawtransaction, [{'txid': 'foo'}], {}) - assert_raises_rpc_error(-8, "txid must be hexadecimal string (not 'ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844')", self.nodes[0].createrawtransaction, [{'txid': 'ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844'}], {}) - assert_raises_rpc_error(-8, "Invalid parameter, missing vout key", self.nodes[0].createrawtransaction, [{'txid': txid}], {}) - assert_raises_rpc_error(-8, "Invalid parameter, missing vout key", self.nodes[0].createrawtransaction, [{'txid': txid, 'vout': 'foo'}], {}) - assert_raises_rpc_error(-8, "Invalid parameter, vout must be positive", self.nodes[0].createrawtransaction, [{'txid': txid, 'vout': -1}], {}) - assert_raises_rpc_error(-8, "Invalid parameter, sequence number is out of range", self.nodes[0].createrawtransaction, [{'txid': txid, 'vout': 0, 'sequence': -1}], {}) + assert_raises_rpc_error(-1, "JSON value is not an object as expected", self.nodes[0].createrawtransaction, + ['foo'], {}) + assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[0].createrawtransaction, [{}], + {}) + assert_raises_rpc_error(-8, "txid must be of length 64 (not 3, for 'foo')", self.nodes[0].createrawtransaction, + [{'txid': 'foo'}], {}) + assert_raises_rpc_error(-8, + "txid must be hexadecimal string (not 'ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844')", + self.nodes[0].createrawtransaction, + [{'txid': 'ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844'}], {}) + assert_raises_rpc_error(-8, "Invalid parameter, missing vout key", self.nodes[0].createrawtransaction, + [{'txid': txid}], {}) + assert_raises_rpc_error(-8, "Invalid parameter, missing vout key", self.nodes[0].createrawtransaction, + [{'txid': txid, 'vout': 'foo'}], {}) + assert_raises_rpc_error(-8, "Invalid parameter, vout must be positive", self.nodes[0].createrawtransaction, + [{'txid': txid, 'vout': -1}], {}) + assert_raises_rpc_error(-8, "Invalid parameter, sequence number is out of range", + self.nodes[0].createrawtransaction, [{'txid': txid, 'vout': 0, 'sequence': -1}], {}) # Test `createrawtransaction` invalid `outputs` address = self.nodes[0].getnewaddress() address2 = self.nodes[0].getnewaddress() - assert_raises_rpc_error(-1, "JSON value is not an array as expected", self.nodes[0].createrawtransaction, [], 'foo') + assert_raises_rpc_error(-1, "JSON value is not an array as expected", self.nodes[0].createrawtransaction, [], + 'foo') self.nodes[0].createrawtransaction(inputs=[], outputs={}) # Should not throw for backwards compatibility self.nodes[0].createrawtransaction(inputs=[], outputs=[]) - assert_raises_rpc_error(-8, "Data must be hexadecimal string", self.nodes[0].createrawtransaction, [], {'data': 'foo'}) + assert_raises_rpc_error(-8, "Data must be hexadecimal string", self.nodes[0].createrawtransaction, [], + {'data': 'foo'}) assert_raises_rpc_error(-5, "Invalid Defi address", self.nodes[0].createrawtransaction, [], {'foo': 0}) assert_raises_rpc_error(-3, "Invalid amount", self.nodes[0].createrawtransaction, [], {address: 'foo'}) assert_raises_rpc_error(-3, "Amount out of range", self.nodes[0].createrawtransaction, [], {address: -1}) - assert_raises_rpc_error(-8, "Invalid parameter, duplicated address: %s" % address, self.nodes[0].createrawtransaction, [], multidict([(address, 1), (address, 1)])) - assert_raises_rpc_error(-8, "Invalid parameter, duplicated address: %s" % address, self.nodes[0].createrawtransaction, [], [{address: 1}, {address: 1}]) - assert_raises_rpc_error(-8, "Invalid parameter, duplicate key: data", self.nodes[0].createrawtransaction, [], [{"data": 'aa'}, {"data": "bb"}]) - assert_raises_rpc_error(-8, "Invalid parameter, duplicate key: data", self.nodes[0].createrawtransaction, [], multidict([("data", 'aa'), ("data", "bb")])) - assert_raises_rpc_error(-8, "Invalid parameter, key-value pair must contain exactly one key", self.nodes[0].createrawtransaction, [], [{'a': 1, 'b': 2}]) - assert_raises_rpc_error(-8, "Invalid parameter, key-value pair not an object as expected", self.nodes[0].createrawtransaction, [], [['key-value pair1'], ['2']]) + assert_raises_rpc_error(-8, "Invalid parameter, duplicated address: %s" % address, + self.nodes[0].createrawtransaction, [], multidict([(address, 1), (address, 1)])) + assert_raises_rpc_error(-8, "Invalid parameter, duplicated address: %s" % address, + self.nodes[0].createrawtransaction, [], [{address: 1}, {address: 1}]) + assert_raises_rpc_error(-8, "Invalid parameter, duplicate key: data", self.nodes[0].createrawtransaction, [], + [{"data": 'aa'}, {"data": "bb"}]) + assert_raises_rpc_error(-8, "Invalid parameter, duplicate key: data", self.nodes[0].createrawtransaction, [], + multidict([("data", 'aa'), ("data", "bb")])) + assert_raises_rpc_error(-8, "Invalid parameter, key-value pair must contain exactly one key", + self.nodes[0].createrawtransaction, [], [{'a': 1, 'b': 2}]) + assert_raises_rpc_error(-8, "Invalid parameter, key-value pair not an object as expected", + self.nodes[0].createrawtransaction, [], [['key-value pair1'], ['2']]) # Test `createrawtransaction` invalid `locktime` assert_raises_rpc_error(-3, "Expected type number", self.nodes[0].createrawtransaction, [], {}, 'foo') - assert_raises_rpc_error(-8, "Invalid parameter, locktime out of range", self.nodes[0].createrawtransaction, [], {}, -1) - assert_raises_rpc_error(-8, "Invalid parameter, locktime out of range", self.nodes[0].createrawtransaction, [], {}, 4294967296) + assert_raises_rpc_error(-8, "Invalid parameter, locktime out of range", self.nodes[0].createrawtransaction, [], + {}, -1) + assert_raises_rpc_error(-8, "Invalid parameter, locktime out of range", self.nodes[0].createrawtransaction, [], + {}, 4294967296) # Test `createrawtransaction` invalid `replaceable` assert_raises_rpc_error(-3, "Expected type bool", self.nodes[0].createrawtransaction, [], {}, 0, 'foo') @@ -119,25 +140,33 @@ def run_test(self): self.log.info('Check that createrawtransaction accepts an array and object as outputs') tx = CTransaction() # One output - tx.deserialize(BytesIO(hex_str_to_bytes(self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs={address: 99})))) + tx.deserialize(BytesIO(hex_str_to_bytes( + self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs={address: 99})))) assert_equal(len(tx.vout), 1) assert_equal( tx.serialize().hex(), self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=[{address: 99}]), ) # Two outputs - tx.deserialize(BytesIO(hex_str_to_bytes(self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=OrderedDict([(address, 99), (address2, 99)]))))) + tx.deserialize(BytesIO(hex_str_to_bytes(self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], + outputs=OrderedDict([(address, 99), ( + address2, 99)]))))) assert_equal(len(tx.vout), 2) assert_equal( tx.serialize().hex(), - self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=[{address: 99}, {address2: 99}]), + self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], + outputs=[{address: 99}, {address2: 99}]), ) # Multiple mixed outputs - tx.deserialize(BytesIO(hex_str_to_bytes(self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=multidict([(address, 99), (address2, 99), ('data', '99')]))))) + tx.deserialize(BytesIO(hex_str_to_bytes(self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], + outputs=multidict( + [(address, 99), (address2, 99), + ('data', '99')]))))) assert_equal(len(tx.vout), 3) assert_equal( tx.serialize().hex(), - self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=[{address: 99}, {address2: 99}, {'data': '99'}]), + self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], + outputs=[{address: 99}, {address2: 99}, {'data': '99'}]), ) for type in ["bech32", "p2sh-segwit", "legacy"]: @@ -145,12 +174,12 @@ def run_test(self): addrinfo = self.nodes[0].getaddressinfo(addr) pubkey = addrinfo["scriptPubKey"] - self.log.info('sendrawtransaction with missing prevtx info (%s)' %(type)) + self.log.info('sendrawtransaction with missing prevtx info (%s)' % (type)) # Test `signrawtransactionwithwallet` invalid `prevtxs` - inputs = [ {'txid' : txid, 'vout' : 3, 'sequence' : 1000}] - outputs = { self.nodes[0].getnewaddress() : 1 } - rawtx = self.nodes[0].createrawtransaction(inputs, outputs) + inputs = [{'txid': txid, 'vout': 3, 'sequence': 1000}] + outputs = {self.nodes[0].getnewaddress(): 1} + rawtx = self.nodes[0].createrawtransaction(inputs, outputs) prevtx = dict(txid=txid, scriptPubKey=pubkey, vout=3, amount=1) succ = self.nodes[0].signrawtransactionwithwallet(rawtx, [prevtx]) @@ -196,10 +225,11 @@ def run_test(self): ######################################### self.log.info('sendrawtransaction with missing input') - inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1}] #won't exists - outputs = { self.nodes[0].getnewaddress() : 4.998 } - rawtx = self.nodes[2].createrawtransaction(inputs, outputs) - rawtx = self.nodes[2].signrawtransactionwithwallet(rawtx) + inputs = [ + {'txid': "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout': 1}] # won't exists + outputs = {self.nodes[0].getnewaddress(): 4.998} + rawtx = self.nodes[2].createrawtransaction(inputs, outputs) + rawtx = self.nodes[2].signrawtransactionwithwallet(rawtx) # This will raise an exception since there are missing inputs assert_raises_rpc_error(-25, "Missing inputs", self.nodes[2].sendrawtransaction, rawtx['hex']) @@ -223,11 +253,18 @@ def run_test(self): # We should not get the tx if we provide an unrelated block assert_raises_rpc_error(-5, "No such transaction found", self.nodes[0].getrawtransaction, tx, True, block2) # An invalid block hash should raise the correct errors - assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[0].getrawtransaction, tx, True, True) - assert_raises_rpc_error(-8, "parameter 3 must be of length 64 (not 6, for 'foobar')", self.nodes[0].getrawtransaction, tx, True, "foobar") - assert_raises_rpc_error(-8, "parameter 3 must be of length 64 (not 8, for 'abcd1234')", self.nodes[0].getrawtransaction, tx, True, "abcd1234") - assert_raises_rpc_error(-8, "parameter 3 must be hexadecimal string (not 'ZZZ0000000000000000000000000000000000000000000000000000000000000')", self.nodes[0].getrawtransaction, tx, True, "ZZZ0000000000000000000000000000000000000000000000000000000000000") - assert_raises_rpc_error(-5, "Block hash not found", self.nodes[0].getrawtransaction, tx, True, "0000000000000000000000000000000000000000000000000000000000000000") + assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[0].getrawtransaction, tx, True, + True) + assert_raises_rpc_error(-8, "parameter 3 must be of length 64 (not 6, for 'foobar')", + self.nodes[0].getrawtransaction, tx, True, "foobar") + assert_raises_rpc_error(-8, "parameter 3 must be of length 64 (not 8, for 'abcd1234')", + self.nodes[0].getrawtransaction, tx, True, "abcd1234") + assert_raises_rpc_error(-8, + "parameter 3 must be hexadecimal string (not 'ZZZ0000000000000000000000000000000000000000000000000000000000000')", + self.nodes[0].getrawtransaction, tx, True, + "ZZZ0000000000000000000000000000000000000000000000000000000000000") + assert_raises_rpc_error(-5, "Block hash not found", self.nodes[0].getrawtransaction, tx, True, + "0000000000000000000000000000000000000000000000000000000000000000") # Undo the blocks and check in_active_chain self.nodes[0].invalidateblock(block1) gottx = self.nodes[0].getrawtransaction(txid=tx, verbose=True, blockhash=block1) @@ -247,12 +284,14 @@ def run_test(self): # Tests for createmultisig and addmultisigaddress assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 1, ["01020304"]) - self.nodes[0].createmultisig(2, [addr1Obj['pubkey'], addr2Obj['pubkey']]) # createmultisig can only take public keys - assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 2, [addr1Obj['pubkey'], addr1]) # addmultisigaddress can take both pubkeys and addresses so long as they are in the wallet, which is tested here. + self.nodes[0].createmultisig(2, [addr1Obj['pubkey'], + addr2Obj['pubkey']]) # createmultisig can only take public keys + assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 2, [addr1Obj['pubkey'], + addr1]) # addmultisigaddress can take both pubkeys and addresses so long as they are in the wallet, which is tested here. mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr1])['address'] - #use balance deltas instead of absolute values + # use balance deltas instead of absolute values bal = self.nodes[2].getbalance() # send 1.2 BTC to msig adr @@ -260,8 +299,8 @@ def run_test(self): self.sync_mempools() self.nodes[0].generate(1) self.sync_blocks() - assert_equal(self.nodes[2].getbalance(), bal+Decimal('1.20000000')) #node2 has both keys of the 2of2 ms addr., tx should affect the balance - + assert_equal(self.nodes[2].getbalance(), bal + Decimal( + '1.20000000')) # node2 has both keys of the 2of2 ms addr., tx should affect the balance # 2of3 test from different nodes bal = self.nodes[2].getbalance() @@ -273,7 +312,8 @@ def run_test(self): addr2Obj = self.nodes[2].getaddressinfo(addr2) addr3Obj = self.nodes[2].getaddressinfo(addr3) - mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey']])['address'] + mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey']])[ + 'address'] txId = self.nodes[0].sendtoaddress(mSigObj, 2.2) decTx = self.nodes[0].gettransaction(txId) @@ -282,29 +322,32 @@ def run_test(self): self.nodes[0].generate(1) self.sync_blocks() - #THIS IS AN INCOMPLETE FEATURE - #NODE2 HAS TWO OF THREE KEY AND THE FUNDS SHOULD BE SPENDABLE AND COUNT AT BALANCE CALCULATION - assert_equal(self.nodes[2].getbalance(), bal) #for now, assume the funds of a 2of3 multisig tx are not marked as spendable + # THIS IS AN INCOMPLETE FEATURE + # NODE2 HAS TWO OF THREE KEY AND THE FUNDS SHOULD BE SPENDABLE AND COUNT AT BALANCE CALCULATION + assert_equal(self.nodes[2].getbalance(), + bal) # for now, assume the funds of a 2of3 multisig tx are not marked as spendable txDetails = self.nodes[0].gettransaction(txId, True) rawTx = self.nodes[0].decoderawtransaction(txDetails['hex']) vout = next(o for o in rawTx['vout'] if o['value'] == Decimal('2.20000000')) bal = self.nodes[0].getbalance() - inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex'], "amount" : vout['value']}] - outputs = { self.nodes[0].getnewaddress() : 2.19 } + inputs = [ + {"txid": txId, "vout": vout['n'], "scriptPubKey": vout['scriptPubKey']['hex'], "amount": vout['value']}] + outputs = {self.nodes[0].getnewaddress(): 2.19} rawTx = self.nodes[2].createrawtransaction(inputs, outputs) rawTxPartialSigned = self.nodes[1].signrawtransactionwithwallet(rawTx, inputs) - assert_equal(rawTxPartialSigned['complete'], False) #node1 only has one key, can't comp. sign the tx + assert_equal(rawTxPartialSigned['complete'], False) # node1 only has one key, can't comp. sign the tx rawTxSigned = self.nodes[2].signrawtransactionwithwallet(rawTx, inputs) - assert_equal(rawTxSigned['complete'], True) #node2 can sign the tx compl., own two of three keys + assert_equal(rawTxSigned['complete'], True) # node2 can sign the tx compl., own two of three keys self.nodes[2].sendrawtransaction(rawTxSigned['hex']) rawTx = self.nodes[0].decoderawtransaction(rawTxSigned['hex']) self.sync_mempools() self.nodes[0].generate(1) self.sync_blocks() - assert_equal(self.nodes[0].getbalance(), bal+Decimal('50.00000000')+Decimal('2.19000000')) #block reward + tx + assert_equal(self.nodes[0].getbalance(), + bal + Decimal('50.00000000') + Decimal('2.19000000')) # block reward + tx # 2of2 test for combining transactions bal = self.nodes[2].getbalance() @@ -325,23 +368,25 @@ def run_test(self): self.nodes[0].generate(1) self.sync_blocks() - assert_equal(self.nodes[2].getbalance(), bal) # the funds of a 2of2 multisig tx should not be marked as spendable + assert_equal(self.nodes[2].getbalance(), + bal) # the funds of a 2of2 multisig tx should not be marked as spendable txDetails = self.nodes[0].gettransaction(txId, True) rawTx2 = self.nodes[0].decoderawtransaction(txDetails['hex']) vout = next(o for o in rawTx2['vout'] if o['value'] == Decimal('2.20000000')) bal = self.nodes[0].getbalance() - inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex'], "redeemScript" : mSigObjValid['hex'], "amount" : vout['value']}] - outputs = { self.nodes[0].getnewaddress() : 2.19 } + inputs = [{"txid": txId, "vout": vout['n'], "scriptPubKey": vout['scriptPubKey']['hex'], + "redeemScript": mSigObjValid['hex'], "amount": vout['value']}] + outputs = {self.nodes[0].getnewaddress(): 2.19} rawTx2 = self.nodes[2].createrawtransaction(inputs, outputs) rawTxPartialSigned1 = self.nodes[1].signrawtransactionwithwallet(rawTx2, inputs) self.log.debug(rawTxPartialSigned1) - assert_equal(rawTxPartialSigned1['complete'], False) #node1 only has one key, can't comp. sign the tx + assert_equal(rawTxPartialSigned1['complete'], False) # node1 only has one key, can't comp. sign the tx rawTxPartialSigned2 = self.nodes[2].signrawtransactionwithwallet(rawTx2, inputs) self.log.debug(rawTxPartialSigned2) - assert_equal(rawTxPartialSigned2['complete'], False) #node2 only has one key, can't comp. sign the tx + assert_equal(rawTxPartialSigned2['complete'], False) # node2 only has one key, can't comp. sign the tx rawTxComb = self.nodes[2].combinerawtransaction([rawTxPartialSigned1['hex'], rawTxPartialSigned2['hex']]) self.log.debug(rawTxComb) self.nodes[2].sendrawtransaction(rawTxComb) @@ -349,17 +394,19 @@ def run_test(self): self.sync_mempools() self.nodes[0].generate(1) self.sync_blocks() - assert_equal(self.nodes[0].getbalance(), bal+Decimal('50.00000000')+Decimal('2.19000000')) #block reward + tx + assert_equal(self.nodes[0].getbalance(), + bal + Decimal('50.00000000') + Decimal('2.19000000')) # block reward + tx # decoderawtransaction tests # witness transaction encrawtx = "010000000001010000000000000072c1a6a246ae63f74f931e8365e15a089c68d61900000000000000000000ffffffff0100e1f50500000000000102616100000000" - decrawtx = self.nodes[0].decoderawtransaction(encrawtx, True) # decode as witness transaction + decrawtx = self.nodes[0].decoderawtransaction(encrawtx, True) # decode as witness transaction assert_equal(decrawtx['vout'][0]['value'], Decimal('1.00000000')) - assert_raises_rpc_error(-22, 'TX decode failed', self.nodes[0].decoderawtransaction, encrawtx, False) # force decode as non-witness transaction + assert_raises_rpc_error(-22, 'TX decode failed', self.nodes[0].decoderawtransaction, encrawtx, + False) # force decode as non-witness transaction # non-witness transaction encrawtx = "01000000010000000000000072c1a6a246ae63f74f931e8365e15a089c68d61900000000000000000000ffffffff0100e1f505000000000000000000" - decrawtx = self.nodes[0].decoderawtransaction(encrawtx, False) # decode as non-witness transaction + decrawtx = self.nodes[0].decoderawtransaction(encrawtx, False) # decode as non-witness transaction assert_equal(decrawtx['vout'][0]['value'], Decimal('1.00000000')) # getrawtransaction tests @@ -389,26 +436,32 @@ def run_test(self): # 8. invalid parameters - supply txid and empty dict assert_raises_rpc_error(-1, "not a boolean", self.nodes[0].getrawtransaction, txId, {}) - inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : 1000}] - outputs = { self.nodes[0].getnewaddress() : 1 } - rawtx = self.nodes[0].createrawtransaction(inputs, outputs) - decrawtx= self.nodes[0].decoderawtransaction(rawtx) + inputs = [ + {'txid': "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout': 1, 'sequence': 1000}] + outputs = {self.nodes[0].getnewaddress(): 1} + rawtx = self.nodes[0].createrawtransaction(inputs, outputs) + decrawtx = self.nodes[0].decoderawtransaction(rawtx) assert_equal(decrawtx['vin'][0]['sequence'], 1000) # 9. invalid parameters - sequence number out of range - inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : -1}] - outputs = { self.nodes[0].getnewaddress() : 1 } - assert_raises_rpc_error(-8, 'Invalid parameter, sequence number is out of range', self.nodes[0].createrawtransaction, inputs, outputs) + inputs = [ + {'txid': "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout': 1, 'sequence': -1}] + outputs = {self.nodes[0].getnewaddress(): 1} + assert_raises_rpc_error(-8, 'Invalid parameter, sequence number is out of range', + self.nodes[0].createrawtransaction, inputs, outputs) # 10. invalid parameters - sequence number out of range - inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : 4294967296}] - outputs = { self.nodes[0].getnewaddress() : 1 } - assert_raises_rpc_error(-8, 'Invalid parameter, sequence number is out of range', self.nodes[0].createrawtransaction, inputs, outputs) - - inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : 4294967294}] - outputs = { self.nodes[0].getnewaddress() : 1 } - rawtx = self.nodes[0].createrawtransaction(inputs, outputs) - decrawtx= self.nodes[0].decoderawtransaction(rawtx) + inputs = [{'txid': "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout': 1, + 'sequence': 4294967296}] + outputs = {self.nodes[0].getnewaddress(): 1} + assert_raises_rpc_error(-8, 'Invalid parameter, sequence number is out of range', + self.nodes[0].createrawtransaction, inputs, outputs) + + inputs = [{'txid': "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout': 1, + 'sequence': 4294967294}] + outputs = {self.nodes[0].getnewaddress(): 1} + rawtx = self.nodes[0].createrawtransaction(inputs, outputs) + decrawtx = self.nodes[0].decoderawtransaction(rawtx) assert_equal(decrawtx['vin'][0]['sequence'], 4294967294) #################################### @@ -436,8 +489,8 @@ def run_test(self): vout = next(o for o in rawTx['vout'] if o['value'] == Decimal('1.00000000')) self.sync_mempools() - inputs = [{ "txid" : txId, "vout" : vout['n'] }] - outputs = { self.nodes[0].getnewaddress() : Decimal("0.99999000") } # 1000 sat fee + inputs = [{"txid": txId, "vout": vout['n']}] + outputs = {self.nodes[0].getnewaddress(): Decimal("0.99999000")} # 1000 sat fee rawTx = self.nodes[2].createrawtransaction(inputs, outputs) rawTxSigned = self.nodes[2].signrawtransactionwithwallet(rawTx) assert_equal(rawTxSigned['complete'], True) @@ -447,7 +500,8 @@ def run_test(self): assert_equal(testres['allowed'], False) assert_equal(testres['reject-reason'], '256: absurdly-high-fee') # and sendrawtransaction should throw - assert_raises_rpc_error(-26, "absurdly-high-fee", self.nodes[2].sendrawtransaction, rawTxSigned['hex'], 0.00001000) + assert_raises_rpc_error(-26, "absurdly-high-fee", self.nodes[2].sendrawtransaction, rawTxSigned['hex'], + 0.00001000) # And below calls should both succeed testres = self.nodes[2].testmempoolaccept(rawtxs=[rawTxSigned['hex']], maxfeerate='0.00070000')[0] assert_equal(testres['allowed'], True) diff --git a/test/functional/rpc_scantxoutset.py b/test/functional/rpc_scantxoutset.py index 380bce615d..d2af2d220d 100755 --- a/test/functional/rpc_scantxoutset.py +++ b/test/functional/rpc_scantxoutset.py @@ -10,9 +10,11 @@ import shutil import os + def descriptors(out): return sorted(u['desc'] for u in out['unspents']) + class ScantxoutsetTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 @@ -35,20 +37,19 @@ def run_test(self): self.nodes[0].sendtoaddress(addr_LEGACY, 0.002) self.nodes[0].sendtoaddress(addr_BECH32, 0.004) - #send to child keys of tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK - self.nodes[0].sendtoaddress("mkHV1C6JLheLoUSSZYk7x3FH5tnx9bu7yc", 0.008) # (m/0'/0'/0') - self.nodes[0].sendtoaddress("mipUSRmJAj2KrjSvsPQtnP8ynUon7FhpCR", 0.016) # (m/0'/0'/1') - self.nodes[0].sendtoaddress("n37dAGe6Mq1HGM9t4b6rFEEsDGq7Fcgfqg", 0.032) # (m/0'/0'/1500') - self.nodes[0].sendtoaddress("mqS9Rpg8nNLAzxFExsgFLCnzHBsoQ3PRM6", 0.064) # (m/0'/0'/0) - self.nodes[0].sendtoaddress("mnTg5gVWr3rbhHaKjJv7EEEc76ZqHgSj4S", 0.128) # (m/0'/0'/1) - self.nodes[0].sendtoaddress("mketCd6B9U9Uee1iCsppDJJBHfvi6U6ukC", 0.256) # (m/0'/0'/1500) - self.nodes[0].sendtoaddress("mj8zFzrbBcdaWXowCQ1oPZ4qioBVzLzAp7", 0.512) # (m/1/1/0') - self.nodes[0].sendtoaddress("mfnKpKQEftniaoE1iXuMMePQU3PUpcNisA", 1.024) # (m/1/1/1') - self.nodes[0].sendtoaddress("mou6cB1kaP1nNJM1sryW6YRwnd4shTbXYQ", 2.048) # (m/1/1/1500') - self.nodes[0].sendtoaddress("mtfUoUax9L4tzXARpw1oTGxWyoogp52KhJ", 4.096) # (m/1/1/0) - self.nodes[0].sendtoaddress("mxp7w7j8S1Aq6L8StS2PqVvtt4HGxXEvdy", 8.192) # (m/1/1/1) - self.nodes[0].sendtoaddress("mpQ8rokAhp1TAtJQR6F6TaUmjAWkAWYYBq", 16.384) # (m/1/1/1500) - + # send to child keys of tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK + self.nodes[0].sendtoaddress("mkHV1C6JLheLoUSSZYk7x3FH5tnx9bu7yc", 0.008) # (m/0'/0'/0') + self.nodes[0].sendtoaddress("mipUSRmJAj2KrjSvsPQtnP8ynUon7FhpCR", 0.016) # (m/0'/0'/1') + self.nodes[0].sendtoaddress("n37dAGe6Mq1HGM9t4b6rFEEsDGq7Fcgfqg", 0.032) # (m/0'/0'/1500') + self.nodes[0].sendtoaddress("mqS9Rpg8nNLAzxFExsgFLCnzHBsoQ3PRM6", 0.064) # (m/0'/0'/0) + self.nodes[0].sendtoaddress("mnTg5gVWr3rbhHaKjJv7EEEc76ZqHgSj4S", 0.128) # (m/0'/0'/1) + self.nodes[0].sendtoaddress("mketCd6B9U9Uee1iCsppDJJBHfvi6U6ukC", 0.256) # (m/0'/0'/1500) + self.nodes[0].sendtoaddress("mj8zFzrbBcdaWXowCQ1oPZ4qioBVzLzAp7", 0.512) # (m/1/1/0') + self.nodes[0].sendtoaddress("mfnKpKQEftniaoE1iXuMMePQU3PUpcNisA", 1.024) # (m/1/1/1') + self.nodes[0].sendtoaddress("mou6cB1kaP1nNJM1sryW6YRwnd4shTbXYQ", 2.048) # (m/1/1/1500') + self.nodes[0].sendtoaddress("mtfUoUax9L4tzXARpw1oTGxWyoogp52KhJ", 4.096) # (m/1/1/0) + self.nodes[0].sendtoaddress("mxp7w7j8S1Aq6L8StS2PqVvtt4HGxXEvdy", 8.192) # (m/1/1/1) + self.nodes[0].sendtoaddress("mpQ8rokAhp1TAtJQR6F6TaUmjAWkAWYYBq", 16.384) # (m/1/1/1500) self.nodes[0].generate(1) @@ -61,54 +62,134 @@ def run_test(self): self.restart_node(0, ['-nowallet']) self.log.info("Test if we have found the non HD unspent outputs.") - assert_equal(self.nodes[0].scantxoutset("start", [ "pkh(" + pubk1 + ")", "pkh(" + pubk2 + ")", "pkh(" + pubk3 + ")"])['total_amount'], Decimal("0.002")) - assert_equal(self.nodes[0].scantxoutset("start", [ "wpkh(" + pubk1 + ")", "wpkh(" + pubk2 + ")", "wpkh(" + pubk3 + ")"])['total_amount'], Decimal("0.004")) - assert_equal(self.nodes[0].scantxoutset("start", [ "sh(wpkh(" + pubk1 + "))", "sh(wpkh(" + pubk2 + "))", "sh(wpkh(" + pubk3 + "))"])['total_amount'], Decimal("0.001")) - assert_equal(self.nodes[0].scantxoutset("start", [ "combo(" + pubk1 + ")", "combo(" + pubk2 + ")", "combo(" + pubk3 + ")"])['total_amount'], Decimal("0.007")) - assert_equal(self.nodes[0].scantxoutset("start", [ "addr(" + addr_P2SH_SEGWIT + ")", "addr(" + addr_LEGACY + ")", "addr(" + addr_BECH32 + ")"])['total_amount'], Decimal("0.007")) - assert_equal(self.nodes[0].scantxoutset("start", [ "addr(" + addr_P2SH_SEGWIT + ")", "addr(" + addr_LEGACY + ")", "combo(" + pubk3 + ")"])['total_amount'], Decimal("0.007")) + assert_equal( + self.nodes[0].scantxoutset("start", ["pkh(" + pubk1 + ")", "pkh(" + pubk2 + ")", "pkh(" + pubk3 + ")"])[ + 'total_amount'], Decimal("0.002")) + assert_equal( + self.nodes[0].scantxoutset("start", ["wpkh(" + pubk1 + ")", "wpkh(" + pubk2 + ")", "wpkh(" + pubk3 + ")"])[ + 'total_amount'], Decimal("0.004")) + assert_equal(self.nodes[0].scantxoutset("start", ["sh(wpkh(" + pubk1 + "))", "sh(wpkh(" + pubk2 + "))", + "sh(wpkh(" + pubk3 + "))"])['total_amount'], Decimal("0.001")) + assert_equal(self.nodes[0].scantxoutset("start", ["combo(" + pubk1 + ")", "combo(" + pubk2 + ")", + "combo(" + pubk3 + ")"])['total_amount'], Decimal("0.007")) + assert_equal(self.nodes[0].scantxoutset("start", ["addr(" + addr_P2SH_SEGWIT + ")", "addr(" + addr_LEGACY + ")", + "addr(" + addr_BECH32 + ")"])['total_amount'], + Decimal("0.007")) + assert_equal(self.nodes[0].scantxoutset("start", ["addr(" + addr_P2SH_SEGWIT + ")", "addr(" + addr_LEGACY + ")", + "combo(" + pubk3 + ")"])['total_amount'], Decimal("0.007")) self.log.info("Test range validation.") - assert_raises_rpc_error(-8, "End of range is too high", self.nodes[0].scantxoutset, "start", [ {"desc": "desc", "range": -1}]) - assert_raises_rpc_error(-8, "Range should be greater or equal than 0", self.nodes[0].scantxoutset, "start", [ {"desc": "desc", "range": [-1, 10]}]) - assert_raises_rpc_error(-8, "End of range is too high", self.nodes[0].scantxoutset, "start", [ {"desc": "desc", "range": [(2 << 31 + 1) - 1000000, (2 << 31 + 1)]}]) - assert_raises_rpc_error(-8, "Range specified as [begin,end] must not have begin after end", self.nodes[0].scantxoutset, "start", [ {"desc": "desc", "range": [2, 1]}]) - assert_raises_rpc_error(-8, "Range is too large", self.nodes[0].scantxoutset, "start", [ {"desc": "desc", "range": [0, 1000001]}]) + assert_raises_rpc_error(-8, "End of range is too high", self.nodes[0].scantxoutset, "start", + [{"desc": "desc", "range": -1}]) + assert_raises_rpc_error(-8, "Range should be greater or equal than 0", self.nodes[0].scantxoutset, "start", + [{"desc": "desc", "range": [-1, 10]}]) + assert_raises_rpc_error(-8, "End of range is too high", self.nodes[0].scantxoutset, "start", + [{"desc": "desc", "range": [(2 << 31 + 1) - 1000000, (2 << 31 + 1)]}]) + assert_raises_rpc_error(-8, "Range specified as [begin,end] must not have begin after end", + self.nodes[0].scantxoutset, "start", [{"desc": "desc", "range": [2, 1]}]) + assert_raises_rpc_error(-8, "Range is too large", self.nodes[0].scantxoutset, "start", + [{"desc": "desc", "range": [0, 1000001]}]) self.log.info("Test extended key derivation.") # Run various scans, and verify that the sum of the amounts of the matches corresponds to the expected subset. # Note that all amounts in the UTXO set are powers of 2 multiplied by 0.001 BTC, so each amounts uniquely identifies a subset. - assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0h/0h)"])['total_amount'], Decimal("0.008")) - assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0'/1h)"])['total_amount'], Decimal("0.016")) - assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0h/0'/1500')"])['total_amount'], Decimal("0.032")) - assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0h/0h/0)"])['total_amount'], Decimal("0.064")) - assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0h/1)"])['total_amount'], Decimal("0.128")) - assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0h/0'/1500)"])['total_amount'], Decimal("0.256")) - assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0h/*h)", "range": 1499}])['total_amount'], Decimal("0.024")) - assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0'/*h)", "range": 1500}])['total_amount'], Decimal("0.056")) - assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0h/0'/*)", "range": 1499}])['total_amount'], Decimal("0.192")) - assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0h/*)", "range": 1500}])['total_amount'], Decimal("0.448")) - assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/0')"])['total_amount'], Decimal("0.512")) - assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/1')"])['total_amount'], Decimal("1.024")) - assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/1500h)"])['total_amount'], Decimal("2.048")) - assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/0)"])['total_amount'], Decimal("4.096")) - assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/1)"])['total_amount'], Decimal("8.192")) - assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/1500)"])['total_amount'], Decimal("16.384")) - assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/0)"])['total_amount'], Decimal("4.096")) - assert_equal(self.nodes[0].scantxoutset("start", [ "combo([abcdef88/1/2'/3/4h]tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/1)"])['total_amount'], Decimal("8.192")) - assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/1500)"])['total_amount'], Decimal("16.384")) - assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*')", "range": 1499}])['total_amount'], Decimal("1.536")) - assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*')", "range": 1500}])['total_amount'], Decimal("3.584")) - assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)", "range": 1499}])['total_amount'], Decimal("12.288")) - assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)", "range": 1500}])['total_amount'], Decimal("28.672")) - assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/*)", "range": 1499}])['total_amount'], Decimal("12.288")) - assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/*)", "range": 1500}])['total_amount'], Decimal("28.672")) - assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/*)", "range": [1500,1500]}])['total_amount'], Decimal("16.384")) + assert_equal(self.nodes[0].scantxoutset("start", [ + "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0h/0h)"])[ + 'total_amount'], Decimal("0.008")) + assert_equal(self.nodes[0].scantxoutset("start", [ + "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0'/1h)"])[ + 'total_amount'], Decimal("0.016")) + assert_equal(self.nodes[0].scantxoutset("start", [ + "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0h/0'/1500')"])[ + 'total_amount'], Decimal("0.032")) + assert_equal(self.nodes[0].scantxoutset("start", [ + "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0h/0h/0)"])[ + 'total_amount'], Decimal("0.064")) + assert_equal(self.nodes[0].scantxoutset("start", [ + "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0h/1)"])[ + 'total_amount'], Decimal("0.128")) + assert_equal(self.nodes[0].scantxoutset("start", [ + "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0h/0'/1500)"])[ + 'total_amount'], Decimal("0.256")) + assert_equal(self.nodes[0].scantxoutset("start", [{ + "desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0h/*h)", + "range": 1499}])['total_amount'], Decimal("0.024")) + assert_equal(self.nodes[0].scantxoutset("start", [{ + "desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0'/*h)", + "range": 1500}])['total_amount'], Decimal("0.056")) + assert_equal(self.nodes[0].scantxoutset("start", [{ + "desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0h/0'/*)", + "range": 1499}])['total_amount'], Decimal("0.192")) + assert_equal(self.nodes[0].scantxoutset("start", [{ + "desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0h/*)", + "range": 1500}])['total_amount'], Decimal("0.448")) + assert_equal(self.nodes[0].scantxoutset("start", [ + "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/0')"])[ + 'total_amount'], Decimal("0.512")) + assert_equal(self.nodes[0].scantxoutset("start", [ + "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/1')"])[ + 'total_amount'], Decimal("1.024")) + assert_equal(self.nodes[0].scantxoutset("start", [ + "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/1500h)"])[ + 'total_amount'], Decimal("2.048")) + assert_equal(self.nodes[0].scantxoutset("start", [ + "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/0)"])[ + 'total_amount'], Decimal("4.096")) + assert_equal(self.nodes[0].scantxoutset("start", [ + "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/1)"])[ + 'total_amount'], Decimal("8.192")) + assert_equal(self.nodes[0].scantxoutset("start", [ + "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/1500)"])[ + 'total_amount'], Decimal("16.384")) + assert_equal(self.nodes[0].scantxoutset("start", [ + "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/0)"])[ + 'total_amount'], Decimal("4.096")) + assert_equal(self.nodes[0].scantxoutset("start", [ + "combo([abcdef88/1/2'/3/4h]tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/1)"])[ + 'total_amount'], Decimal("8.192")) + assert_equal(self.nodes[0].scantxoutset("start", [ + "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/1500)"])[ + 'total_amount'], Decimal("16.384")) + assert_equal(self.nodes[0].scantxoutset("start", [{ + "desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*')", + "range": 1499}])['total_amount'], Decimal("1.536")) + assert_equal(self.nodes[0].scantxoutset("start", [{ + "desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*')", + "range": 1500}])['total_amount'], Decimal("3.584")) + assert_equal(self.nodes[0].scantxoutset("start", [{ + "desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)", + "range": 1499}])['total_amount'], Decimal("12.288")) + assert_equal(self.nodes[0].scantxoutset("start", [{ + "desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)", + "range": 1500}])['total_amount'], Decimal("28.672")) + assert_equal(self.nodes[0].scantxoutset("start", [{ + "desc": "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/*)", + "range": 1499}])['total_amount'], Decimal("12.288")) + assert_equal(self.nodes[0].scantxoutset("start", [{ + "desc": "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/*)", + "range": 1500}])['total_amount'], Decimal("28.672")) + assert_equal(self.nodes[0].scantxoutset("start", [{ + "desc": "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/*)", + "range": [1500, 1500]}])['total_amount'], + Decimal("16.384")) # Test the reported descriptors for a few matches - assert_equal(descriptors(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0h/0'/*)", "range": 1499}])), ["pkh([0c5f9a1e/0'/0'/0]026dbd8b2315f296d36e6b6920b1579ca75569464875c7ebe869b536a7d9503c8c)#dzxw429x", "pkh([0c5f9a1e/0'/0'/1]033e6f25d76c00bedb3a8993c7d5739ee806397f0529b1b31dda31ef890f19a60c)#43rvceed"]) - assert_equal(descriptors(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/0)"])), ["pkh([0c5f9a1e/1/1/0]03e1c5b6e650966971d7e71ef2674f80222752740fc1dfd63bbbd220d2da9bd0fb)#cxmct4w8"]) - assert_equal(descriptors(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/*)", "range": 1500}])), ['pkh([0c5f9a1e/1/1/0]03e1c5b6e650966971d7e71ef2674f80222752740fc1dfd63bbbd220d2da9bd0fb)#cxmct4w8', 'pkh([0c5f9a1e/1/1/1500]03832901c250025da2aebae2bfb38d5c703a57ab66ad477f9c578bfbcd78abca6f)#vchwd07g', 'pkh([0c5f9a1e/1/1/1]030d820fc9e8211c4169be8530efbc632775d8286167afd178caaf1089b77daba7)#z2t3ypsa']) + assert_equal(descriptors(self.nodes[0].scantxoutset("start", [{ + "desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0h/0'/*)", + "range": 1499}])), [ + "pkh([0c5f9a1e/0'/0'/0]026dbd8b2315f296d36e6b6920b1579ca75569464875c7ebe869b536a7d9503c8c)#dzxw429x", + "pkh([0c5f9a1e/0'/0'/1]033e6f25d76c00bedb3a8993c7d5739ee806397f0529b1b31dda31ef890f19a60c)#43rvceed"]) + assert_equal(descriptors(self.nodes[0].scantxoutset("start", [ + "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/0)"])), + [ + "pkh([0c5f9a1e/1/1/0]03e1c5b6e650966971d7e71ef2674f80222752740fc1dfd63bbbd220d2da9bd0fb)#cxmct4w8"]) + assert_equal(descriptors(self.nodes[0].scantxoutset("start", [{ + "desc": "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/*)", + "range": 1500}])), [ + 'pkh([0c5f9a1e/1/1/0]03e1c5b6e650966971d7e71ef2674f80222752740fc1dfd63bbbd220d2da9bd0fb)#cxmct4w8', + 'pkh([0c5f9a1e/1/1/1500]03832901c250025da2aebae2bfb38d5c703a57ab66ad477f9c578bfbcd78abca6f)#vchwd07g', + 'pkh([0c5f9a1e/1/1/1]030d820fc9e8211c4169be8530efbc632775d8286167afd178caaf1089b77daba7)#z2t3ypsa']) + if __name__ == '__main__': ScantxoutsetTest().main() diff --git a/test/functional/rpc_setban.py b/test/functional/rpc_setban.py index 99c28d5569..3e1407e096 100755 --- a/test/functional/rpc_setban.py +++ b/test/functional/rpc_setban.py @@ -10,23 +10,24 @@ p2p_port ) + class SetBanTests(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 self.setup_clean_chain = True - self.extra_args = [[],[]] + self.extra_args = [[], []] def run_test(self): # Node 0 connects to Node 1, check that the noban permission is not granted connect_nodes(self.nodes[0], 1) peerinfo = self.nodes[1].getpeerinfo()[0] - assert(not 'noban' in peerinfo['permissions']) + assert (not 'noban' in peerinfo['permissions']) # Node 0 get banned by Node 1 self.nodes[1].setban("127.0.0.1", "add") # Node 0 should not be able to reconnect - with self.nodes[1].assert_debug_log(expected_msgs=['dropped (banned)\n'],timeout=5): + with self.nodes[1].assert_debug_log(expected_msgs=['dropped (banned)\n'], timeout=5): self.restart_node(1, []) self.nodes[0].addnode("127.0.0.1:" + str(p2p_port(1)), "onetry") @@ -34,14 +35,15 @@ def run_test(self): self.restart_node(1, ['-whitelist=127.0.0.1']) connect_nodes(self.nodes[0], 1) peerinfo = self.nodes[1].getpeerinfo()[0] - assert('noban' in peerinfo['permissions']) + assert ('noban' in peerinfo['permissions']) # If we remove the ban, Node 0 should be able to reconnect even without noban permission self.nodes[1].setban("127.0.0.1", "remove") self.restart_node(1, []) connect_nodes(self.nodes[0], 1) peerinfo = self.nodes[1].getpeerinfo()[0] - assert(not 'noban' in peerinfo['permissions']) + assert (not 'noban' in peerinfo['permissions']) + if __name__ == '__main__': SetBanTests().main() diff --git a/test/functional/rpc_signmessage.py b/test/functional/rpc_signmessage.py index cec64269f8..46965982e6 100755 --- a/test/functional/rpc_signmessage.py +++ b/test/functional/rpc_signmessage.py @@ -7,6 +7,7 @@ from test_framework.test_framework import DefiTestFramework from test_framework.util import assert_equal + class SignMessagesTest(DefiTestFramework): def set_test_params(self): self.setup_clean_chain = True @@ -38,5 +39,6 @@ def run_test(self): assert not self.nodes[0].verifymessage(other_address, signature, message) assert not self.nodes[0].verifymessage(address, other_signature, message) + if __name__ == '__main__': SignMessagesTest().main() diff --git a/test/functional/rpc_signrawtransaction.py b/test/functional/rpc_signrawtransaction.py index ae551491c9..d1a9a7d6d6 100755 --- a/test/functional/rpc_signrawtransaction.py +++ b/test/functional/rpc_signrawtransaction.py @@ -11,6 +11,7 @@ from decimal import Decimal + class SignRawTransactionsTest(DefiTestFramework): def set_test_params(self): self.setup_clean_chain = True @@ -26,7 +27,8 @@ def successful_signing_test(self): 1) The transaction has a complete set of signatures 2) No script verification error occurred""" - privKeys = ['cUeKHd5orzT3mz8P9pxyREHfsWtVfgsfDjiZZBcjUBAaGk1BTj7N', 'cVKpPfVKSJxKqVpE9awvXNWuLHCa5j5tiE7K6zbUSptFpTEtiFrA'] + privKeys = ['cUeKHd5orzT3mz8P9pxyREHfsWtVfgsfDjiZZBcjUBAaGk1BTj7N', + 'cVKpPfVKSJxKqVpE9awvXNWuLHCa5j5tiE7K6zbUSptFpTEtiFrA'] inputs = [ # Valid pay-to-pubkey scripts @@ -53,7 +55,8 @@ def test_with_lock_outputs(self): rawTx = '020000000156b958f78e3f24e0b2f4e4db1255426b0902027cb37e3ddadb52e37c3557dddb0000000000ffffffff01c0a6b929010000001600149a2ee8c77140a053f36018ac8124a6ececc1668a00000000' - assert_raises_rpc_error(-13, "Please enter the wallet passphrase with walletpassphrase first", self.nodes[0].signrawtransactionwithwallet, rawTx) + assert_raises_rpc_error(-13, "Please enter the wallet passphrase with walletpassphrase first", + self.nodes[0].signrawtransactionwithwallet, rawTx) def script_verification_error_test(self): """Create and sign a raw transaction with valid (vin 0), invalid (vin 1) and one missing (vin 2) input script. @@ -142,7 +145,9 @@ def script_verification_error_test(self): assert 'error' in rawTxSigned['errors'][0] # Non-empty witness checked here - assert_equal(rawTxSigned['errors'][1]['witness'], ["304402203609e17b84f6a7d30c80bfa610b5b4542f32a8a0d5447a12fb1366d7f01cc44a0220573a954c4518331561406f90300e8f3358f51928d43c212a8caed02de67eebee01", "025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357"]) + assert_equal(rawTxSigned['errors'][1]['witness'], [ + "304402203609e17b84f6a7d30c80bfa610b5b4542f32a8a0d5447a12fb1366d7f01cc44a0220573a954c4518331561406f90300e8f3358f51928d43c212a8caed02de67eebee01", + "025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357"]) assert not rawTxSigned['errors'][0]['witness'] def witness_script_test(self): @@ -162,7 +167,8 @@ def witness_script_test(self): p2sh_redeemScript = CScript([OP_0, sha256(hex_str_to_bytes(p2sh_p2wsh_address["redeemScript"]))]) assert_equal(unspent_output["redeemScript"], p2sh_redeemScript.hex()) # Now create and sign a transaction spending that output on node[0], which doesn't know the scripts or keys - spending_tx = self.nodes[0].createrawtransaction([unspent_output], {self.nodes[1].getnewaddress(): Decimal("49.998")}) + spending_tx = self.nodes[0].createrawtransaction([unspent_output], + {self.nodes[1].getnewaddress(): Decimal("49.998")}) spending_tx_signed = self.nodes[0].signrawtransactionwithkey(spending_tx, [embedded_privkey], [unspent_output]) # Check the signing completed successfully assert 'complete' in spending_tx_signed diff --git a/test/functional/rpc_txoutproof.py b/test/functional/rpc_txoutproof.py index 6a97399113..434550b97e 100755 --- a/test/functional/rpc_txoutproof.py +++ b/test/functional/rpc_txoutproof.py @@ -8,6 +8,7 @@ from test_framework.test_framework import DefiTestFramework from test_framework.util import assert_equal, assert_raises_rpc_error + class MerkleBlockTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 4 @@ -59,26 +60,38 @@ def run_test(self): txid_unspent = txid1 if txin_spent["txid"] != txid1 else txid2 # Invalid txids - assert_raises_rpc_error(-8, "txid must be of length 64 (not 32, for '00000000000000000000000000000000')", self.nodes[2].gettxoutproof, ["00000000000000000000000000000000"], blockhash) - assert_raises_rpc_error(-8, "txid must be hexadecimal string (not 'ZZZ0000000000000000000000000000000000000000000000000000000000000')", self.nodes[2].gettxoutproof, ["ZZZ0000000000000000000000000000000000000000000000000000000000000"], blockhash) + assert_raises_rpc_error(-8, "txid must be of length 64 (not 32, for '00000000000000000000000000000000')", + self.nodes[2].gettxoutproof, ["00000000000000000000000000000000"], blockhash) + assert_raises_rpc_error(-8, + "txid must be hexadecimal string (not 'ZZZ0000000000000000000000000000000000000000000000000000000000000')", + self.nodes[2].gettxoutproof, + ["ZZZ0000000000000000000000000000000000000000000000000000000000000"], blockhash) # Invalid blockhashes - assert_raises_rpc_error(-8, "blockhash must be of length 64 (not 32, for '00000000000000000000000000000000')", self.nodes[2].gettxoutproof, [txid_spent], "00000000000000000000000000000000") - assert_raises_rpc_error(-8, "blockhash must be hexadecimal string (not 'ZZZ0000000000000000000000000000000000000000000000000000000000000')", self.nodes[2].gettxoutproof, [txid_spent], "ZZZ0000000000000000000000000000000000000000000000000000000000000") + assert_raises_rpc_error(-8, "blockhash must be of length 64 (not 32, for '00000000000000000000000000000000')", + self.nodes[2].gettxoutproof, [txid_spent], "00000000000000000000000000000000") + assert_raises_rpc_error(-8, + "blockhash must be hexadecimal string (not 'ZZZ0000000000000000000000000000000000000000000000000000000000000')", + self.nodes[2].gettxoutproof, [txid_spent], + "ZZZ0000000000000000000000000000000000000000000000000000000000000") # We can't find the block from a fully-spent tx assert_raises_rpc_error(-5, "Transaction not yet in block", self.nodes[2].gettxoutproof, [txid_spent]) # We can get the proof if we specify the block assert_equal(self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof([txid_spent], blockhash)), [txid_spent]) # We can't get the proof if we specify a non-existent block - assert_raises_rpc_error(-5, "Block not found", self.nodes[2].gettxoutproof, [txid_spent], "0000000000000000000000000000000000000000000000000000000000000000") + assert_raises_rpc_error(-5, "Block not found", self.nodes[2].gettxoutproof, [txid_spent], + "0000000000000000000000000000000000000000000000000000000000000000") # We can get the proof if the transaction is unspent assert_equal(self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof([txid_unspent])), [txid_unspent]) # We can get the proof if we provide a list of transactions and one of them is unspent. The ordering of the list should not matter. - assert_equal(sorted(self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof([txid1, txid2]))), sorted(txlist)) - assert_equal(sorted(self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof([txid2, txid1]))), sorted(txlist)) + assert_equal(sorted(self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof([txid1, txid2]))), + sorted(txlist)) + assert_equal(sorted(self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof([txid2, txid1]))), + sorted(txlist)) # We can always get a proof if we have a -txindex assert_equal(self.nodes[2].verifytxoutproof(self.nodes[3].gettxoutproof([txid_spent])), [txid_spent]) # We can't get a proof if we specify transactions from different blocks - assert_raises_rpc_error(-5, "Not all transactions found in specified or retrieved block", self.nodes[2].gettxoutproof, [txid1, txid3]) + assert_raises_rpc_error(-5, "Not all transactions found in specified or retrieved block", + self.nodes[2].gettxoutproof, [txid1, txid3]) # Now we'll try tweaking a proof. proof = self.nodes[3].gettxoutproof([txid1, txid2]) @@ -94,7 +107,7 @@ def run_test(self): # single-transaction block tweaked_proof.txn.nTransactions = 1 tweaked_proof.txn.vHash = [tweaked_proof.header.hashMerkleRoot] - tweaked_proof.txn.vBits = [True] + [False]*7 + tweaked_proof.txn.vBits = [True] + [False] * 7 for n in self.nodes: assert not n.verifytxoutproof(ToHex(tweaked_proof)) @@ -102,5 +115,6 @@ def run_test(self): # TODO: try more variants, eg transactions at different depths, and # verify that the proofs are invalid + if __name__ == '__main__': MerkleBlockTest().main() diff --git a/test/functional/rpc_updatemasternode.py b/test/functional/rpc_updatemasternode.py index abfe0338d8..47ec84bad5 100755 --- a/test/functional/rpc_updatemasternode.py +++ b/test/functional/rpc_updatemasternode.py @@ -10,13 +10,16 @@ ) from decimal import Decimal + class TestForcedRewardAddress(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 self.setup_clean_chain = True self.extra_args = [ - ['-txindex=1', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-fortcanninghillheight=1', '-grandcentralheight=110'], - ['-txindex=1', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-fortcanninghillheight=1', '-grandcentralheight=110'], + ['-txindex=1', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-fortcanninghillheight=1', + '-grandcentralheight=110'], + ['-txindex=1', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-fortcanninghillheight=1', + '-grandcentralheight=110'], ] def skip_test_if_missing_module(self): @@ -64,25 +67,27 @@ def transfer_owner(self, mn_id): new_owner = self.nodes[0].getnewaddress("", "legacy") # Test update of owner address - mn_transfer_tx = self.nodes[0].updatemasternode(mn_id, {'ownerAddress':new_owner}) + mn_transfer_tx = self.nodes[0].updatemasternode(mn_id, {'ownerAddress': new_owner}) mn_transfer_rawtx = self.nodes[0].getrawtransaction(mn_transfer_tx, 1) self.nodes[0].generate(1) # Make sure new collateral is present assert_equal(mn_transfer_rawtx['vout'][1]['value'], Decimal('10.00000000')) - assert_equal(mn_transfer_rawtx['vout'][1]['scriptPubKey']['hex'], self.nodes[0].getaddressinfo(new_owner)['scriptPubKey']) + assert_equal(mn_transfer_rawtx['vout'][1]['scriptPubKey']['hex'], + self.nodes[0].getaddressinfo(new_owner)['scriptPubKey']) # Test spending of new collateral - rawtx = self.nodes[0].createrawtransaction([{"txid":mn_transfer_tx, "vout":1}], [{new_owner:9.9999}]) + rawtx = self.nodes[0].createrawtransaction([{"txid": mn_transfer_tx, "vout": 1}], [{new_owner: 9.9999}]) signed_rawtx = self.nodes[0].signrawtransactionwithwallet(rawtx) - assert_raises_rpc_error(-26, "tried to spend locked collateral for {}".format(mn_transfer_tx), self.nodes[0].sendrawtransaction, signed_rawtx['hex']) + assert_raises_rpc_error(-26, "tried to spend locked collateral for {}".format(mn_transfer_tx), + self.nodes[0].sendrawtransaction, signed_rawtx['hex']) # Make sure old collateral is set as input found = False for vin in mn_transfer_rawtx['vin']: if vin['txid'] == collateral and vin['vout'] == 1: found = True - assert(found) + assert (found) # Check new state is TRANSFERRING and owner is still the same result = self.nodes[0].getmasternode(mn_id)[mn_id] @@ -91,7 +96,8 @@ def transfer_owner(self, mn_id): assert_equal(result['ownerAuthAddress'], owner) # Test update while masternode is in TRANSFERRING state - assert_raises_rpc_error(-32600, "Masternode {} is not in 'ENABLED' state".format(mn_id), self.nodes[0].updatemasternode, mn_id, {'ownerAddress':new_owner}) + assert_raises_rpc_error(-32600, "Masternode {} is not in 'ENABLED' state".format(mn_id), + self.nodes[0].updatemasternode, mn_id, {'ownerAddress': new_owner}) # Test PRE_ENABLED state and owner change self.nodes[0].generate(10) @@ -101,7 +107,8 @@ def transfer_owner(self, mn_id): assert_equal(result['ownerAuthAddress'], new_owner) # Try another transfer during pre-enabled - assert_raises_rpc_error(-32600, "Masternode {} is not in 'ENABLED' state".format(mn_id), self.nodes[0].updatemasternode, mn_id, {'ownerAddress':new_owner}) + assert_raises_rpc_error(-32600, "Masternode {} is not in 'ENABLED' state".format(mn_id), + self.nodes[0].updatemasternode, mn_id, {'ownerAddress': new_owner}) # Test ENABLED state and owner change self.nodes[0].generate(10) @@ -132,37 +139,50 @@ def run_test(self): # Test call before for height operator_address = self.nodes[0].getnewaddress("", "legacy") - assert_raises_rpc_error(-32600, "called before GrandCentral height".format(mn_id), self.nodes[0].updatemasternode, mn_id, {'operatorAddress':operator_address}) - assert_raises_rpc_error(-32600, "Cannot be set before GrandCentralHeight", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/feature/mn-setowneraddress':'true'}}) - assert_raises_rpc_error(-32600, "Cannot be set before GrandCentralHeight", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/feature/mn-setoperatoraddress':'true'}}) - assert_raises_rpc_error(-32600, "Cannot be set before GrandCentralHeight", self.nodes[0].setgov, {"ATTRIBUTES":{'v0/params/feature/mn-setrewardaddress':'true'}}) + assert_raises_rpc_error(-32600, "called before GrandCentral height".format(mn_id), + self.nodes[0].updatemasternode, mn_id, {'operatorAddress': operator_address}) + assert_raises_rpc_error(-32600, "Cannot be set before GrandCentralHeight", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/feature/mn-setowneraddress': 'true'}}) + assert_raises_rpc_error(-32600, "Cannot be set before GrandCentralHeight", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/feature/mn-setoperatoraddress': 'true'}}) + assert_raises_rpc_error(-32600, "Cannot be set before GrandCentralHeight", self.nodes[0].setgov, + {"ATTRIBUTES": {'v0/params/feature/mn-setrewardaddress': 'true'}}) self.nodes[0].generate(4) # Test call before masternode active operator_address = self.nodes[0].getnewaddress("", "legacy") - assert_raises_rpc_error(-32600, "Masternode {} is not in 'ENABLED' state".format(mn_id), self.nodes[0].updatemasternode, mn_id, {'operatorAddress':operator_address}) + assert_raises_rpc_error(-32600, "Masternode {} is not in 'ENABLED' state".format(mn_id), + self.nodes[0].updatemasternode, mn_id, {'operatorAddress': operator_address}) self.nodes[0].generate(5) # Test calls before enablement - assert_raises_rpc_error(-32600, "Updating masternode operator address not currently enabled in attributes.", self.nodes[0].updatemasternode, mn_id, {'operatorAddress':mn_owner}) - assert_raises_rpc_error(-32600, "Updating masternode owner address not currently enabled in attributes.", self.nodes[0].updatemasternode, mn_id, {'ownerAddress':mn_owner}) - assert_raises_rpc_error(-32600, "Updating masternode reward address not currently enabled in attributes.", self.nodes[0].updatemasternode, mn_id, {'rewardAddress':mn_owner}) + assert_raises_rpc_error(-32600, "Updating masternode operator address not currently enabled in attributes.", + self.nodes[0].updatemasternode, mn_id, {'operatorAddress': mn_owner}) + assert_raises_rpc_error(-32600, "Updating masternode owner address not currently enabled in attributes.", + self.nodes[0].updatemasternode, mn_id, {'ownerAddress': mn_owner}) + assert_raises_rpc_error(-32600, "Updating masternode reward address not currently enabled in attributes.", + self.nodes[0].updatemasternode, mn_id, {'rewardAddress': mn_owner}) # Enable all new features - self.nodes[0].setgov({"ATTRIBUTES":{'v0/params/feature/mn-setowneraddress':'true','v0/params/feature/mn-setoperatoraddress':'true','v0/params/feature/mn-setrewardaddress':'true'}}) + self.nodes[0].setgov({"ATTRIBUTES": {'v0/params/feature/mn-setowneraddress': 'true', + 'v0/params/feature/mn-setoperatoraddress': 'true', + 'v0/params/feature/mn-setrewardaddress': 'true'}}) self.nodes[0].generate(1) - assert_raises_rpc_error(-32600, "Masternode with that operator address already exists", self.nodes[0].updatemasternode, mn_id, {'operatorAddress':mn_owner}) + assert_raises_rpc_error(-32600, "Masternode with that operator address already exists", + self.nodes[0].updatemasternode, mn_id, {'operatorAddress': mn_owner}) # node 1 try to update node 0 which should be rejected. - assert_raises_rpc_error(-5, "Incorrect authorization for {}".format(mn_owner), self.nodes[1].updatemasternode, mn_id, {'operatorAddress':operator_address}) + assert_raises_rpc_error(-5, "Incorrect authorization for {}".format(mn_owner), self.nodes[1].updatemasternode, + mn_id, {'operatorAddress': operator_address}) # Update operator address - self.nodes[0].updatemasternode(mn_id, {'operatorAddress':operator_address}) + self.nodes[0].updatemasternode(mn_id, {'operatorAddress': operator_address}) # Test updating another node to the same address - assert_raises_rpc_error(-26, "Masternode with that operator address already exists", self.nodes[0].updatemasternode, mn_id2, {'operatorAddress':operator_address}) + assert_raises_rpc_error(-26, "Masternode with that operator address already exists", + self.nodes[0].updatemasternode, mn_id2, {'operatorAddress': operator_address}) self.nodes[0].resignmasternode(mn_id2) self.nodes[0].generate(1) self.sync_all() @@ -181,15 +201,17 @@ def run_test(self): # Set forced address forced_reward_address = self.nodes[0].getnewaddress("", "legacy") assert_raises_rpc_error(-8, - "The masternode {} does not exist".format("some_bad_mn_id"), - self.nodes[0].updatemasternode, "some_bad_mn_id", {'rewardAddress':forced_reward_address} - ) + "The masternode {} does not exist".format("some_bad_mn_id"), + self.nodes[0].updatemasternode, "some_bad_mn_id", + {'rewardAddress': forced_reward_address} + ) assert_raises_rpc_error(-8, - "rewardAddress ({}) does not refer to a P2PKH or P2WPKH address".format("some_bad_address"), - self.nodes[0].updatemasternode, mn_id, {'rewardAddress':'some_bad_address'} - ) + "rewardAddress ({}) does not refer to a P2PKH or P2WPKH address".format( + "some_bad_address"), + self.nodes[0].updatemasternode, mn_id, {'rewardAddress': 'some_bad_address'} + ) - self.nodes[0].updatemasternode(mn_id, {'rewardAddress':forced_reward_address}) + self.nodes[0].updatemasternode(mn_id, {'rewardAddress': forced_reward_address}) self.nodes[0].generate(1) result = self.nodes[0].getmasternode(mn_id)[mn_id] @@ -204,7 +226,7 @@ def run_test(self): assert_equal(result['state'], 'ENABLED') # Remvoe reward address - self.nodes[0].updatemasternode(mn_id, {'rewardAddress':''}) + self.nodes[0].updatemasternode(mn_id, {'rewardAddress': ''}) self.nodes[0].generate(1) # Check state and reward address @@ -220,7 +242,7 @@ def run_test(self): assert_equal(result['state'], 'ENABLED') # Set reward address - self.nodes[0].updatemasternode(mn_id, {'rewardAddress':forced_reward_address}) + self.nodes[0].updatemasternode(mn_id, {'rewardAddress': forced_reward_address}) self.nodes[0].generate(11) fra_amount = self.unspent_amount(self.nodes[0], forced_reward_address) @@ -229,21 +251,25 @@ def run_test(self): assert_equal(fra_amount, 0) self.stop_node(1) - self.restart_node(0, ['-gen', '-masternode_operator='+operator_address, '-txindex=1', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-grandcentralheight=1']) + self.restart_node(0, ['-gen', '-masternode_operator=' + operator_address, '-txindex=1', '-txnotokens=0', + '-amkheight=50', '-bayfrontheight=50', '-grandcentralheight=1']) # Mine blocks self.nodes[0].generate(300) - self.nodes[0].updatemasternode(mn_id, {'rewardAddress':''}) + self.nodes[0].updatemasternode(mn_id, {'rewardAddress': ''}) self.nodes[0].generate(1) - assert(len(self.list_unspent_tx(self.nodes[0], forced_reward_address)) > len(fra_unspent)) - assert(self.unspent_amount(self.nodes[0], forced_reward_address) > fra_amount) + assert (len(self.list_unspent_tx(self.nodes[0], forced_reward_address)) > len(fra_unspent)) + assert (self.unspent_amount(self.nodes[0], forced_reward_address) > fra_amount) # CLI Reward address for test -rewardaddress cli_reward_address = self.nodes[0].getnewaddress("", "legacy") - self.restart_node(0, ['-gen', '-masternode_operator='+operator_address, '-rewardaddress='+cli_reward_address, '-txindex=1', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-grandcentralheight=1']) + self.restart_node(0, + ['-gen', '-masternode_operator=' + operator_address, '-rewardaddress=' + cli_reward_address, + '-txindex=1', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', + '-grandcentralheight=1']) cra_unspent = self.list_unspent_tx(self.nodes[0], cli_reward_address) cra_amount = self.unspent_amount(self.nodes[0], cli_reward_address) @@ -253,13 +279,14 @@ def run_test(self): # Mine blocks self.nodes[0].generate(400) - assert(len(self.list_unspent_tx(self.nodes[0], cli_reward_address)) > len(fra_unspent)) - assert(self.unspent_amount(self.nodes[0], cli_reward_address) > fra_amount) + assert (len(self.list_unspent_tx(self.nodes[0], cli_reward_address)) > len(fra_unspent)) + assert (self.unspent_amount(self.nodes[0], cli_reward_address) > fra_amount) # Test updating operator and reward address simultaniously new_operator_address = self.nodes[0].getnewaddress("", "legacy") new_reward_address = self.nodes[0].getnewaddress("", "legacy") - self.nodes[0].updatemasternode(mn_id, {'operatorAddress':new_operator_address,'rewardAddress':new_reward_address}) + self.nodes[0].updatemasternode(mn_id, + {'operatorAddress': new_operator_address, 'rewardAddress': new_reward_address}) self.nodes[0].generate(11) # Check results @@ -274,7 +301,7 @@ def run_test(self): # Test unknown update type while True: address = self.nodes[0].getnewaddress("", "legacy") - unknown_tx = self.nodes[0].updatemasternode(mn_id, {'rewardAddress':address}) + unknown_tx = self.nodes[0].updatemasternode(mn_id, {'rewardAddress': address}) unknown_rawtx = self.nodes[0].getrawtransaction(unknown_tx) self.nodes[0].clearmempool() if unknown_rawtx.count('01030114') == 1: @@ -287,12 +314,14 @@ def run_test(self): # Test incorrect owner address assert_raises_rpc_error(-8, - "ownerAddress ({}) does not refer to a P2PKH or P2WPKH address".format("some_bad_address"), - self.nodes[0].updatemasternode, mn_id, {'ownerAddress':'some_bad_address'} - ) + "ownerAddress ({}) does not refer to a P2PKH or P2WPKH address".format( + "some_bad_address"), + self.nodes[0].updatemasternode, mn_id, {'ownerAddress': 'some_bad_address'} + ) # Test update of owner address with existing address - assert_raises_rpc_error(-32600, "Masternode with collateral address as operator or owner already exists", self.nodes[0].updatemasternode, mn_id, {'ownerAddress':mn_owner}) + assert_raises_rpc_error(-32600, "Masternode with collateral address as operator or owner already exists", + self.nodes[0].updatemasternode, mn_id, {'ownerAddress': mn_owner}) # Set up input / output tests not_collateral = self.nodes[0].getnewaddress("", "legacy") @@ -302,19 +331,27 @@ def run_test(self): [owner_auth_tx, owner_auth_vout] = self.fund_tx(owner_address, 0.1) # Get TX to use OP_RETURN output - missing_tx = self.nodes[0].updatemasternode(mn_id, {'ownerAddress':owner_address}) + missing_tx = self.nodes[0].updatemasternode(mn_id, {'ownerAddress': owner_address}) missing_rawtx = self.nodes[0].getrawtransaction(missing_tx, 1) self.nodes[0].clearmempool() # Test owner update without collateral input - rawtx = self.nodes[0].createrawtransaction([{"txid":missing_auth_tx, "vout":missing_input_vout},{"txid":not_collateral_tx, "vout":not_collateral_vout}], [{"data":missing_rawtx['vout'][0]['scriptPubKey']['hex'][4:]},{owner_address:10}]) + rawtx = self.nodes[0].createrawtransaction([{"txid": missing_auth_tx, "vout": missing_input_vout}, + {"txid": not_collateral_tx, "vout": not_collateral_vout}], + [{"data": missing_rawtx['vout'][0]['scriptPubKey']['hex'][4:]}, + {owner_address: 10}]) signed_rawtx = self.nodes[0].signrawtransactionwithwallet(rawtx) - assert_raises_rpc_error(-26, "Missing previous collateral from transaction inputs", self.nodes[0].sendrawtransaction, signed_rawtx['hex']) + assert_raises_rpc_error(-26, "Missing previous collateral from transaction inputs", + self.nodes[0].sendrawtransaction, signed_rawtx['hex']) # Test incorrect new collateral amount - rawtx = self.nodes[0].createrawtransaction([{"txid":mn_id, "vout":1},{"txid":missing_auth_tx, "vout":missing_input_vout},{"txid":owner_auth_tx, "vout":owner_auth_vout}], [{"data":missing_rawtx['vout'][0]['scriptPubKey']['hex'][4:]},{owner_address:10.1}]) + rawtx = self.nodes[0].createrawtransaction( + [{"txid": mn_id, "vout": 1}, {"txid": missing_auth_tx, "vout": missing_input_vout}, + {"txid": owner_auth_tx, "vout": owner_auth_vout}], + [{"data": missing_rawtx['vout'][0]['scriptPubKey']['hex'][4:]}, {owner_address: 10.1}]) signed_rawtx = self.nodes[0].signrawtransactionwithwallet(rawtx) - assert_raises_rpc_error(-26, "bad-txns-collateral-locked, tried to spend locked collateral for", self.nodes[0].sendrawtransaction, signed_rawtx['hex']) + assert_raises_rpc_error(-26, "bad-txns-collateral-locked, tried to spend locked collateral for", + self.nodes[0].sendrawtransaction, signed_rawtx['hex']) # Test transfer of owner self.transfer_owner(mn_id) @@ -339,7 +376,8 @@ def run_test(self): assert_equal(result['state'], 'RESIGNED') # Test spending of transferred collateral after resignation - rawtx = self.nodes[0].createrawtransaction([{"txid":result['collateralTx'], "vout":1}], [{owner_address:9.9999}]) + rawtx = self.nodes[0].createrawtransaction([{"txid": result['collateralTx'], "vout": 1}], + [{owner_address: 9.9999}]) signed_rawtx = self.nodes[0].signrawtransactionwithwallet(rawtx) self.nodes[0].sendrawtransaction(signed_rawtx['hex']) @@ -380,21 +418,23 @@ def run_test(self): new_mn6_owner = self.nodes[0].getnewaddress("", "legacy") # Try updating two nodes to the same address - self.nodes[0].updatemasternode(mn1, {'ownerAddress':new_mn1_owner, 'operatorAddress':new_mn1_owner}) + self.nodes[0].updatemasternode(mn1, {'ownerAddress': new_mn1_owner, 'operatorAddress': new_mn1_owner}) self.nodes[0].generate(1) # Make sure we cannot update another MN with the pending address - assert_raises_rpc_error(-32600, "Masternode with collateral address as operator or owner already exists", self.nodes[0].updatemasternode, mn2, {'ownerAddress':new_mn1_owner}) + assert_raises_rpc_error(-32600, "Masternode with collateral address as operator or owner already exists", + self.nodes[0].updatemasternode, mn2, {'ownerAddress': new_mn1_owner}) # Try and create new MN with pending address - assert_raises_rpc_error(-32600, "Masternode exist with that owner address pending", self.nodes[0].createmasternode, new_mn1_owner) + assert_raises_rpc_error(-32600, "Masternode exist with that owner address pending", + self.nodes[0].createmasternode, new_mn1_owner) # Test updating several MNs owners in the same block - self.nodes[0].updatemasternode(mn2, {'ownerAddress':new_mn2_owner}) - self.nodes[0].updatemasternode(mn3, {'ownerAddress':new_mn3_owner}) - self.nodes[0].updatemasternode(mn4, {'ownerAddress':new_mn4_owner}) - self.nodes[0].updatemasternode(mn5, {'ownerAddress':new_mn5_owner}) - self.nodes[0].updatemasternode(mn6, {'ownerAddress':new_mn6_owner}) + self.nodes[0].updatemasternode(mn2, {'ownerAddress': new_mn2_owner}) + self.nodes[0].updatemasternode(mn3, {'ownerAddress': new_mn3_owner}) + self.nodes[0].updatemasternode(mn4, {'ownerAddress': new_mn4_owner}) + self.nodes[0].updatemasternode(mn5, {'ownerAddress': new_mn5_owner}) + self.nodes[0].updatemasternode(mn6, {'ownerAddress': new_mn6_owner}) self.nodes[0].generate(1) result = self.nodes[0].listmasternodes() @@ -443,7 +483,7 @@ def run_test(self): assert_equal(result[mn6]['ownerAuthAddress'], new_mn6_owner) # Update MN to address not owned in wallet - tx = self.nodes[0].updatemasternode(mn1, {'ownerAddress':foreign_owner}) + tx = self.nodes[0].updatemasternode(mn1, {'ownerAddress': foreign_owner}) self.nodes[0].generate(21) # Test new owner address @@ -456,6 +496,6 @@ def run_test(self): assert_equal(result['results']['id'], mn1) assert_equal(result['results']['ownerAddress'], foreign_owner) + if __name__ == '__main__': TestForcedRewardAddress().main() - diff --git a/test/functional/rpc_users.py b/test/functional/rpc_users.py index 2ee872dca4..fd2c3d9ae1 100755 --- a/test/functional/rpc_users.py +++ b/test/functional/rpc_users.py @@ -20,6 +20,7 @@ import configparser import sys + def call_with_auth(node, user, password): url = urllib.parse.urlparse(node.url) headers = {"Authorization": "Basic " + str_to_b64str('{}:{}'.format(user, password))} @@ -38,7 +39,7 @@ def set_test_params(self): def setup_chain(self): super().setup_chain() - #Append rpcauth to defi.conf before initialization + # Append rpcauth to defi.conf before initialization self.rtpassword = "cA773lm788buwYe4g4WT+05pKyNruVKjQ25x3n0DQcM=" rpcauth = "rpcauth=rt:93648e835a54c573682c2eb19f882535$7681e9c5b74bdd85e78166031d2058e1069b3ed7ed967c93fc63abba06f31144" @@ -51,7 +52,8 @@ def setup_chain(self): # Generate RPCAUTH with specified password self.rt2password = "8/F3uMDw4KSEbw96U3CA1C4X05dkHDN2BPFjTgZW4KI=" - p = subprocess.Popen([sys.executable, gen_rpcauth, 'rt2', self.rt2password], stdout=subprocess.PIPE, universal_newlines=True) + p = subprocess.Popen([sys.executable, gen_rpcauth, 'rt2', self.rt2password], stdout=subprocess.PIPE, + universal_newlines=True) lines = p.stdout.read().splitlines() rpcauth2 = lines[1] @@ -63,9 +65,9 @@ def setup_chain(self): self.password = lines[3] with open(os.path.join(get_datadir_path(self.options.tmpdir, 0), "defi.conf"), 'a', encoding='utf8') as f: - f.write(rpcauth+"\n") - f.write(rpcauth2+"\n") - f.write(rpcauth3+"\n") + f.write(rpcauth + "\n") + f.write(rpcauth2 + "\n") + f.write(rpcauth3 + "\n") with open(os.path.join(get_datadir_path(self.options.tmpdir, 1), "defi.conf"), 'a', encoding='utf8') as f: f.write("rpcuser={}\n".format(self.rpcuser)) f.write("rpcpassword={}\n".format(self.rpcpassword)) @@ -75,16 +77,15 @@ def test_auth(self, node, user, password): assert_equal(200, call_with_auth(node, user, password).status) self.log.info('Wrong...') - assert_equal(401, call_with_auth(node, user, password+'wrong').status) + assert_equal(401, call_with_auth(node, user, password + 'wrong').status) self.log.info('Wrong...') - assert_equal(401, call_with_auth(node, user+'wrong', password).status) + assert_equal(401, call_with_auth(node, user + 'wrong', password).status) self.log.info('Wrong...') - assert_equal(401, call_with_auth(node, user+'wrong', password+'wrong').status) + assert_equal(401, call_with_auth(node, user + 'wrong', password + 'wrong').status) def run_test(self): - ################################################## # Check correctness of the rpcauth config option # ################################################## @@ -102,5 +103,6 @@ def run_test(self): self.test_auth(self.nodes[1], self.rpcuser, self.rpcpassword) + if __name__ == '__main__': - HTTPBasicsTest ().main () + HTTPBasicsTest().main() diff --git a/test/functional/test_framework/address.py b/test/functional/test_framework/address.py index b2be641203..cdd92f8414 100644 --- a/test/functional/test_framework/address.py +++ b/test/functional/test_framework/address.py @@ -29,7 +29,7 @@ def byte_to_base58(b, version): str = chr(version).encode('latin-1').hex() + str checksum = hash256(hex_str_to_bytes(str)).hex() str += checksum[:8] - value = int('0x'+str,0) + value = int('0x' + str, 0) while value > 0: result = chars[value % 58] + result value //= 58 @@ -38,32 +38,38 @@ def byte_to_base58(b, version): str = str[2:] return result + # TODO: def base58_decode -def keyhash_to_p2pkh(hash, main = False): +def keyhash_to_p2pkh(hash, main=False): assert len(hash) == 20 version = 0 if main else 111 return byte_to_base58(hash, version) -def scripthash_to_p2sh(hash, main = False): + +def scripthash_to_p2sh(hash, main=False): assert len(hash) == 20 version = 5 if main else 196 return byte_to_base58(hash, version) -def key_to_p2pkh(key, main = False): + +def key_to_p2pkh(key, main=False): key = check_key(key) return keyhash_to_p2pkh(hash160(key), main) -def script_to_p2sh(script, main = False): + +def script_to_p2sh(script, main=False): script = check_script(script) return scripthash_to_p2sh(hash160(script), main) -def key_to_p2sh_p2wpkh(key, main = False): + +def key_to_p2sh_p2wpkh(key, main=False): key = check_key(key) p2shscript = CScript([OP_0, hash160(key)]) return script_to_p2sh(p2shscript, main) -def program_to_witness(version, program, main = False): + +def program_to_witness(version, program, main=False): if (type(program) is str): program = hex_str_to_bytes(program) assert 0 <= version <= 16 @@ -71,29 +77,34 @@ def program_to_witness(version, program, main = False): assert version > 0 or len(program) in [20, 32] return segwit_addr.encode("bc" if main else "bcrt", version, program) -def script_to_p2wsh(script, main = False): + +def script_to_p2wsh(script, main=False): script = check_script(script) return program_to_witness(0, sha256(script), main) -def key_to_p2wpkh(key, main = False): + +def key_to_p2wpkh(key, main=False): key = check_key(key) return program_to_witness(0, hash160(key), main) -def script_to_p2sh_p2wsh(script, main = False): + +def script_to_p2sh_p2wsh(script, main=False): script = check_script(script) p2shscript = CScript([OP_0, sha256(script)]) return script_to_p2sh(p2shscript, main) + def check_key(key): if (type(key) is str): - key = hex_str_to_bytes(key) # Assuming this is hex string + key = hex_str_to_bytes(key) # Assuming this is hex string if (type(key) is bytes and (len(key) == 33 or len(key) == 65)): return key assert False + def check_script(script): if (type(script) is str): - script = hex_str_to_bytes(script) # Assuming this is hex string + script = hex_str_to_bytes(script) # Assuming this is hex string if (type(script) is bytes or type(script) is CScript): return script assert False diff --git a/test/functional/test_framework/authproxy.py b/test/functional/test_framework/authproxy.py index 8486bf1e42..bfed8208e7 100644 --- a/test/functional/test_framework/authproxy.py +++ b/test/functional/test_framework/authproxy.py @@ -49,6 +49,7 @@ log = logging.getLogger("DefiRPC") + class JSONRPCException(Exception): def __init__(self, rpc_error, http_status=None): try: @@ -65,6 +66,7 @@ def EncodeDecimal(o): return str(o) raise TypeError(repr(o) + " is not JSON serializable") + class AuthServiceProxy(): __id_count = 0 @@ -177,20 +179,24 @@ def _get_response(self): content_type = http_response.getheader('Content-Type') if content_type != 'application/json': raise JSONRPCException( - {'code': -342, 'message': 'non-JSON HTTP response with \'%i %s\' from server' % (http_response.status, http_response.reason)}, + {'code': -342, 'message': 'non-JSON HTTP response with \'%i %s\' from server' % ( + http_response.status, http_response.reason)}, http_response.status) responsedata = http_response.read().decode('utf8') response = json.loads(responsedata, parse_float=decimal.Decimal) elapsed = time.time() - req_start_time if "error" in response and response["error"] is None: - log.debug("<-%s- [%.6f] %s" % (response["id"], elapsed, json.dumps(response["result"], default=EncodeDecimal, ensure_ascii=self.ensure_ascii))) + log.debug("<-%s- [%.6f] %s" % (response["id"], elapsed, + json.dumps(response["result"], default=EncodeDecimal, + ensure_ascii=self.ensure_ascii))) else: log.debug("<-- [%.6f] %s" % (elapsed, responsedata)) return response, http_response.status def __truediv__(self, relative_uri): - return AuthServiceProxy("{}/{}".format(self.__service_url, relative_uri), self._service_name, connection=self.__conn) + return AuthServiceProxy("{}/{}".format(self.__service_url, relative_uri), self._service_name, + connection=self.__conn) def _set_conn(self, connection=None): port = 80 if self.__url.port is None else self.__url.port diff --git a/test/functional/test_framework/bignum.py b/test/functional/test_framework/bignum.py index 91a15d5e75..ed968d7983 100644 --- a/test/functional/test_framework/bignum.py +++ b/test/functional/test_framework/bignum.py @@ -16,16 +16,18 @@ def bn_bytes(v, have_ext=False): ext = 0 if have_ext: ext = 1 - return ((v.bit_length()+7)//8) + ext + return ((v.bit_length() + 7) // 8) + ext + def bn2bin(v): s = bytearray() i = bn_bytes(v) while i > 0: - s.append((v >> ((i-1) * 8)) & 0xff) + s.append((v >> ((i - 1) * 8)) & 0xff) i -= 1 return s + def bn2mpi(v): have_ext = False if v.bit_length() > 0: @@ -48,11 +50,13 @@ def bn2mpi(v): v_bin[0] |= 0x80 return s + ext + v_bin + # defi-specific little endian format, with implicit size def mpi2vch(s): - r = s[4:] # strip size - r = r[::-1] # reverse string, converting BE->LE + r = s[4:] # strip size + r = r[::-1] # reverse string, converting BE->LE return r + def bn2vch(v): return bytes(mpi2vch(bn2mpi(v))) diff --git a/test/functional/test_framework/blocktools.py b/test/functional/test_framework/blocktools.py index d6681f3c3e..46dd1b0a99 100644 --- a/test/functional/test_framework/blocktools.py +++ b/test/functional/test_framework/blocktools.py @@ -67,11 +67,13 @@ def create_block(hashprev, coinbase, ntime=None, *, version=1): block.calc_sha256() return block + def get_witness_script(witness_root, witness_nonce): witness_commitment = uint256_from_str(hash256(ser_uint256(witness_root) + ser_uint256(witness_nonce))) output_data = WITNESS_COMMITMENT_HEADER + ser_uint256(witness_commitment) return CScript([OP_RETURN, output_data]) + def add_witness_commitment(block, nonce=0): """Add a witness commitment to the block's coinbase transaction. @@ -119,6 +121,7 @@ def create_coinbase(height, pubkey=None): coinbase.calc_sha256() return coinbase + def create_tx_with_script(prevtx, n, script_sig=b"", *, amount, script_pub_key=CScript()): """Return one-input, one-output transaction object spending the prevtx's n-th output with the given amount. @@ -132,6 +135,7 @@ def create_tx_with_script(prevtx, n, script_sig=b"", *, amount, script_pub_key=C tx.calc_sha256() return tx + def create_transaction(node, txid, to_address, *, amount): """ Return signed transaction spending the first output of the input txid. Note that the node must be able to sign for the @@ -143,6 +147,7 @@ def create_transaction(node, txid, to_address, *, amount): tx.deserialize(BytesIO(hex_str_to_bytes(raw_tx))) return tx + def create_raw_transaction(node, txid, to_address, *, amount): """ Return raw signed transaction spending the first output of the input txid. Note that the node must be able to sign for the @@ -154,12 +159,14 @@ def create_raw_transaction(node, txid, to_address, *, amount): assert_equal(signresult["complete"], True) return signresult['hex'] + def get_legacy_sigopcount_block(block, accurate=True): count = 0 for tx in block.vtx: count += get_legacy_sigopcount_tx(tx, accurate) return count + def get_legacy_sigopcount_tx(tx, accurate=True): count = 0 for i in tx.vout: @@ -169,6 +176,7 @@ def get_legacy_sigopcount_tx(tx, accurate=True): count += CScript(j.scriptSig).GetSigOpCount(accurate) return count + def witness_script(use_p2wsh, pubkey): """Create a scriptPubKey for a pay-to-witness TxOut. @@ -186,6 +194,7 @@ def witness_script(use_p2wsh, pubkey): pkscript = CScript([OP_0, scripthash]) return pkscript.hex() + def create_witness_tx(node, use_p2wsh, utxo, pubkey, encode_p2sh, amount): """Return a transaction (in hex) that spends the given utxo to a segwit output. @@ -199,6 +208,7 @@ def create_witness_tx(node, use_p2wsh, utxo, pubkey, encode_p2sh, amount): assert_equal(node.getaddressinfo(addr)['scriptPubKey'], witness_script(use_p2wsh, pubkey)) return node.createrawtransaction([utxo], {addr: amount}) + def send_to_witness(use_p2wsh, node, utxo, pubkey, encode_p2sh, amount, sign=True, insert_redeem_script=""): """Create a transaction spending a given utxo to a segwit output. diff --git a/test/functional/test_framework/coverage.py b/test/functional/test_framework/coverage.py index b039f338c9..537539aeec 100644 --- a/test/functional/test_framework/coverage.py +++ b/test/functional/test_framework/coverage.py @@ -10,7 +10,6 @@ import os - REFERENCE_FILENAME = 'rpc_interface.txt' @@ -19,6 +18,7 @@ class AuthServiceProxyWrapper(): An object that wraps AuthServiceProxy to record specific RPC calls. """ + def __init__(self, auth_service_proxy_instance, coverage_logfile=None): """ Kwargs: @@ -63,6 +63,7 @@ def get_request(self, *args, **kwargs): self._log_call() return self.auth_service_proxy_instance.get_request(*args, **kwargs) + def get_filename(dirname, n_node): """ Get a filename unique to the test process ID and node. diff --git a/test/functional/test_framework/descriptors.py b/test/functional/test_framework/descriptors.py index fa9efd6671..e7c5aca9ab 100644 --- a/test/functional/test_framework/descriptors.py +++ b/test/functional/test_framework/descriptors.py @@ -8,6 +8,7 @@ CHECKSUM_CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l" GENERATOR = [0xf5dee51989, 0xa9fdca3312, 0x1bab10e32d, 0x3706b1677a, 0x644d626ffd] + def descsum_polymod(symbols): """Internal function that computes the descriptor checksum.""" chk = 1 @@ -18,6 +19,7 @@ def descsum_polymod(symbols): chk ^= GENERATOR[i] if ((top >> i) & 1) else 0 return chk + def descsum_expand(s): """Internal function that does the character to symbol expansion""" groups = [] @@ -37,12 +39,14 @@ def descsum_expand(s): symbols.append(groups[0] * 3 + groups[1]) return symbols + def descsum_create(s): """Add a checksum to a descriptor without""" symbols = descsum_expand(s) + [0, 0, 0, 0, 0, 0, 0, 0] checksum = descsum_polymod(symbols) ^ 1 return s + '#' + ''.join(CHECKSUM_CHARSET[(checksum >> (5 * (7 - i))) & 31] for i in range(8)) + def descsum_check(s, require=True): """Verify that the checksum is correct in a descriptor""" if not '#' in s: diff --git a/test/functional/test_framework/key.py b/test/functional/test_framework/key.py index 7db8d6a2f5..a94a73310d 100644 --- a/test/functional/test_framework/key.py +++ b/test/functional/test_framework/key.py @@ -8,6 +8,7 @@ anything but tests.""" import random + def modinv(a, n): """Compute the modular inverse of a modulo n @@ -25,6 +26,7 @@ def modinv(a, n): t1 += n return t1 + def jacobi_symbol(n, k): """Compute the Jacobi symbol of n modulo k @@ -46,6 +48,7 @@ def jacobi_symbol(n, k): return -1 if t else 1 return 0 + def modsqrt(a, p): """Compute the square root of a modulo p when p % 4 = 3. @@ -59,11 +62,12 @@ def modsqrt(a, p): """ if p % 4 != 3: raise NotImplementedError("modsqrt only implemented for p % 4 = 3") - sqrt = pow(a, (p + 1)//4, p) + sqrt = pow(a, (p + 1) // 4, p) if pow(sqrt, 2, p) == a % p: return sqrt return None + class EllipticCurve: def __init__(self, p, a, b): """Initialize elliptic curve y^2 = x^3 + a*x + b over GF(p).""" @@ -79,7 +83,7 @@ def affine(self, p1): if z1 == 0: return None inv = modinv(z1, self.p) - inv_2 = (inv**2) % self.p + inv_2 = (inv ** 2) % self.p inv_3 = (inv_2 * inv) % self.p return ((inv_2 * x1) % self.p, (inv_3 * y1) % self.p, 1) @@ -116,17 +120,17 @@ def double(self, p1): x1, y1, z1 = p1 if z1 == 0: return (0, 1, 0) - y1_2 = (y1**2) % self.p - y1_4 = (y1_2**2) % self.p - x1_2 = (x1**2) % self.p - s = (4*x1*y1_2) % self.p - m = 3*x1_2 + y1_2 = (y1 ** 2) % self.p + y1_4 = (y1_2 ** 2) % self.p + x1_2 = (x1 ** 2) % self.p + s = (4 * x1 * y1_2) % self.p + m = 3 * x1_2 if self.a: m += self.a * pow(z1, 4, self.p) m = m % self.p - x2 = (m**2 - 2*s) % self.p - y2 = (m*(s - x2) - 8*y1_4) % self.p - z2 = (2*y1*z1) % self.p + x2 = (m ** 2 - 2 * s) % self.p + y2 = (m * (s - x2) - 8 * y1_4) % self.p + z2 = (2 * y1 * z1) % self.p return (x2, y2, z2) def add_mixed(self, p1, p2): @@ -135,11 +139,11 @@ def add_mixed(self, p1, p2): See https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates - Point Addition (with affine point)""" x1, y1, z1 = p1 x2, y2, z2 = p2 - assert(z2 == 1) + assert (z2 == 1) # Adding to the point at infinity is a no-op if z1 == 0: return p2 - z1_2 = (z1**2) % self.p + z1_2 = (z1 ** 2) % self.p z1_3 = (z1_2 * z1) % self.p u2 = (x2 * z1_2) % self.p s2 = (y2 * z1_3) % self.p @@ -151,12 +155,12 @@ def add_mixed(self, p1, p2): return self.double(p1) h = u2 - x1 r = s2 - y1 - h_2 = (h**2) % self.p + h_2 = (h ** 2) % self.p h_3 = (h_2 * h) % self.p u1_h_2 = (x1 * h_2) % self.p - x3 = (r**2 - h_3 - 2*u1_h_2) % self.p - y3 = (r*(u1_h_2 - x3) - y1*h_3) % self.p - z3 = (h*z1) % self.p + x3 = (r ** 2 - h_3 - 2 * u1_h_2) % self.p + y3 = (r * (u1_h_2 - x3) - y1 * h_3) % self.p + z3 = (h * z1) % self.p return (x3, y3, z3) def add(self, p1, p2): @@ -175,9 +179,9 @@ def add(self, p1, p2): return self.add_mixed(p2, p1) if z2 == 1: return self.add_mixed(p1, p2) - z1_2 = (z1**2) % self.p + z1_2 = (z1 ** 2) % self.p z1_3 = (z1_2 * z1) % self.p - z2_2 = (z2**2) % self.p + z2_2 = (z2 ** 2) % self.p z2_3 = (z2_2 * z2) % self.p u1 = (x1 * z2_2) % self.p u2 = (x2 * z1_2) % self.p @@ -191,12 +195,12 @@ def add(self, p1, p2): return self.double(p1) h = u2 - u1 r = s2 - s1 - h_2 = (h**2) % self.p + h_2 = (h ** 2) % self.p h_3 = (h_2 * h) % self.p u1_h_2 = (u1 * h_2) % self.p - x3 = (r**2 - h_3 - 2*u1_h_2) % self.p - y3 = (r*(u1_h_2 - x3) - s1*h_3) % self.p - z3 = (h*z1*z2) % self.p + x3 = (r ** 2 - h_3 - 2 * u1_h_2) % self.p + y3 = (r * (u1_h_2 - x3) - s1 * h_3) % self.p + z3 = (h * z1 * z2) % self.p return (x3, y3, z3) def mul(self, ps): @@ -212,11 +216,14 @@ def mul(self, ps): r = self.add(r, p) return r -SECP256K1 = EllipticCurve(2**256 - 2**32 - 977, 0, 7) -SECP256K1_G = (0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798, 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8, 1) + +SECP256K1 = EllipticCurve(2 ** 256 - 2 ** 32 - 977, 0, 7) +SECP256K1_G = (0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798, + 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8, 1) SECP256K1_ORDER = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 SECP256K1_ORDER_HALF = SECP256K1_ORDER // 2 + class ECPubKey(): """A secp256k1 public key""" @@ -257,7 +264,7 @@ def is_valid(self): return self.valid def get_bytes(self): - assert(self.valid) + assert (self.valid) p = SECP256K1.affine(self.p) if p is None: return None @@ -271,7 +278,7 @@ def verify_ecdsa(self, sig, msg, low_s=True): See https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm for the ECDSA verifier algorithm""" - assert(self.valid) + assert (self.valid) # Extract r and s from the DER formatted signature. Return false for # any DER encoding errors. @@ -292,19 +299,19 @@ def verify_ecdsa(self, sig, msg, low_s=True): return False if (rlen > 1 and (sig[4] == 0) and not (sig[5] & 0x80)): return False - r = int.from_bytes(sig[4:4+rlen], 'big') - if (sig[4+rlen] != 0x02): + r = int.from_bytes(sig[4:4 + rlen], 'big') + if (sig[4 + rlen] != 0x02): return False - slen = sig[5+rlen] + slen = sig[5 + rlen] if slen < 1 or slen > 33: return False if (len(sig) != 6 + rlen + slen): return False - if sig[6+rlen] >= 0x80: + if sig[6 + rlen] >= 0x80: return False - if (slen > 1 and (sig[6+rlen] == 0) and not (sig[7+rlen] & 0x80)): + if (slen > 1 and (sig[6 + rlen] == 0) and not (sig[7 + rlen] & 0x80)): return False - s = int.from_bytes(sig[6+rlen:6+rlen+slen], 'big') + s = int.from_bytes(sig[6 + rlen:6 + rlen + slen], 'big') # Verify that r and s are within the group order if r < 1 or s < 1 or r >= SECP256K1_ORDER or s >= SECP256K1_ORDER: @@ -315,13 +322,14 @@ def verify_ecdsa(self, sig, msg, low_s=True): # Run verifier algorithm on r, s w = modinv(s, SECP256K1_ORDER) - u1 = z*w % SECP256K1_ORDER - u2 = r*w % SECP256K1_ORDER + u1 = z * w % SECP256K1_ORDER + u2 = r * w % SECP256K1_ORDER R = SECP256K1.affine(SECP256K1.mul([(SECP256K1_G, u1), (self.p, u2)])) if R is None or R[0] != r: return False return True + class ECKey(): """A secp256k1 private key""" @@ -330,7 +338,7 @@ def __init__(self): def set(self, secret, compressed): """Construct a private key object with given 32-byte secret and compressed flag.""" - assert(len(secret) == 32) + assert (len(secret) == 32) secret = int.from_bytes(secret, 'big') self.valid = (secret > 0 and secret < SECP256K1_ORDER) if self.valid: @@ -343,7 +351,7 @@ def generate(self, compressed=True): def get_bytes(self): """Retrieve the 32-byte representation of this key.""" - assert(self.valid) + assert (self.valid) return self.secret.to_bytes(32, 'big') @property @@ -356,7 +364,7 @@ def is_compressed(self): def get_pubkey(self): """Compute an ECPubKey object for this secret key.""" - assert(self.valid) + assert (self.valid) ret = ECPubKey() p = SECP256K1.mul([(SECP256K1_G, self.secret)]) ret.p = p @@ -369,7 +377,7 @@ def sign_ecdsa(self, msg, low_s=True): See https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm for the ECDSA signer algorithm.""" - assert(self.valid) + assert (self.valid) z = int.from_bytes(msg, 'big') # Note: no RFC6979, but a simple random nonce (some tests rely on distinct transactions for the same operation) k = random.randrange(1, SECP256K1_ORDER) diff --git a/test/functional/test_framework/messages.py b/test/functional/test_framework/messages.py index 07c49a76a2..397ffd4e33 100755 --- a/test/functional/test_framework/messages.py +++ b/test/functional/test_framework/messages.py @@ -33,13 +33,13 @@ MIN_VERSION_SUPPORTED = 60001 MY_VERSION = 70024 # past bip-31 for ping/pong MY_SUBVERSION = b"/python-mininode-tester:0.0.3/" -MY_RELAY = 1 # from version 70001 onwards, fRelay should be appended to version messages (BIP37) +MY_RELAY = 1 # from version 70001 onwards, fRelay should be appended to version messages (BIP37) MAX_LOCATOR_SZ = 101 MAX_BLOCK_BASE_SIZE = 1000000 * 16 COIN = 100000000 # 1 btc in satoshis -MAXMONEY = 1200000000 * COIN # old value 21000000 * 4 +MAXMONEY = 1200000000 * COIN # old value 21000000 * 4 BIP125_SEQUENCE_NUMBER = 0xfffffffd # Sequence number that is BIP 125 opt-in and BIP 68-opt-out @@ -54,13 +54,16 @@ MSG_WITNESS_FLAG = 1 << 30 MSG_TYPE_MASK = 0xffffffff >> 2 + # Serialization/deserialization tools def sha256(s): return hashlib.new('sha256', s).digest() + def hash256(s): return sha256(sha256(s)) + def ser_compact_size(l): r = b"" if l < 253: @@ -73,6 +76,7 @@ def ser_compact_size(l): r = struct.pack(" 1: newhashes = [] for i in range(0, len(hashes), 2): - i2 = min(i+1, len(hashes)-1) + i2 = min(i + 1, len(hashes) - 1) newhashes.append(hash256(hashes[i] + hashes[i2])) hashes = newhashes return uint256_from_str(hashes[0]) @@ -733,13 +746,14 @@ def solve(self): def __repr__(self): return "CBlock(nVersion=%i hashPrevBlock=%064x hashMerkleRoot=%064x nTime=%s nBits=%08x stakeModifier=%064x nHeight=%i nMintedBlocks=%i sig=%s vtx=%s)" \ % (self.nVersion, self.hashPrevBlock, self.hashMerkleRoot, - time.ctime(self.nTime), self.nBits, self.stakeModifier, self.nHeight, self.nMintedBlocks, "0x".join("{:02x}".format(c) for c in self.sig), repr(self.vtx)) + time.ctime(self.nTime), self.nBits, self.stakeModifier, self.nHeight, self.nMintedBlocks, + "0x".join("{:02x}".format(c) for c in self.sig), repr(self.vtx)) class PrefilledTransaction: __slots__ = ("index", "tx") - def __init__(self, index=0, tx = None): + def __init__(self, index=0, tx=None): self.index = index self.tx = tx @@ -807,16 +821,20 @@ def serialize(self, with_witness=False): return r def __repr__(self): - return "P2PHeaderAndShortIDs(header=%s, nonce=%d, shortids_length=%d, shortids=%s, prefilled_txn_length=%d, prefilledtxn=%s" % (repr(self.header), self.nonce, self.shortids_length, repr(self.shortids), self.prefilled_txn_length, repr(self.prefilled_txn)) + return "P2PHeaderAndShortIDs(header=%s, nonce=%d, shortids_length=%d, shortids=%s, prefilled_txn_length=%d, prefilledtxn=%s" % ( + repr(self.header), self.nonce, self.shortids_length, repr(self.shortids), self.prefilled_txn_length, + repr(self.prefilled_txn)) # P2P version of the above that will use witness serialization (for compact # block version 2) class P2PHeaderAndShortWitnessIDs(P2PHeaderAndShortIDs): __slots__ = () + def serialize(self): return super(P2PHeaderAndShortWitnessIDs, self).serialize(with_witness=True) + # Calculate the BIP 152-compact blocks shortid for a given transaction hash def calculate_shortid(k0, k1, tx_hash): expected_shortid = siphash256(k0, k1, tx_hash) @@ -829,7 +847,7 @@ def calculate_shortid(k0, k1, tx_hash): class HeaderAndShortIDs: __slots__ = ("header", "nonce", "prefilled_txn", "shortids", "use_witness") - def __init__(self, p2pheaders_and_shortids = None): + def __init__(self, p2pheaders_and_shortids=None): self.header = CBlockHeader() self.nonce = 0 self.shortids = [] @@ -868,7 +886,7 @@ def get_siphash_keys(self): hash_header_nonce_as_str = sha256(header_nonce) key0 = struct.unpack("= MIN_VERSION_SUPPORTED, "Version {} received. Test framework only supports versions greater than {}".format(message.nVersion, MIN_VERSION_SUPPORTED) + assert message.nVersion >= MIN_VERSION_SUPPORTED, "Version {} received. Test framework only supports versions greater than {}".format( + message.nVersion, MIN_VERSION_SUPPORTED) self.send_message(msg_verack()) self.nServices = message.nServices @@ -429,8 +473,8 @@ def wait_for_inv(self, expected_inv, timeout=60): def test_function(): assert self.is_connected return self.last_message.get("inv") and \ - self.last_message["inv"].inv[0].type == expected_inv[0].type and \ - self.last_message["inv"].inv[0].hash == expected_inv[0].hash + self.last_message["inv"].inv[0].type == expected_inv[0].type and \ + self.last_message["inv"].inv[0].hash == expected_inv[0].hash wait_until(test_function, timeout=timeout, lock=mininode_lock) @@ -545,7 +589,8 @@ def on_getheaders(self, message): if response is not None: self.send_message(response) - def send_blocks_and_test(self, blocks, node, *, success=True, force_send=False, reject_reason=None, expect_disconnect=False, timeout=60): + def send_blocks_and_test(self, blocks, node, *, success=True, force_send=False, reject_reason=None, + expect_disconnect=False, timeout=60): """Send blocks to test node and test whether the tip advances. - add all blocks to our block_store diff --git a/test/functional/test_framework/netutil.py b/test/functional/test_framework/netutil.py index e415a9aeb0..40a3c8faf2 100644 --- a/test/functional/test_framework/netutil.py +++ b/test/functional/test_framework/netutil.py @@ -24,6 +24,8 @@ # STATE_CLOSE_WAIT = '08' # STATE_LAST_ACK = '09' STATE_LISTEN = '0A' + + # STATE_CLOSING = '0B' def get_socket_inodes(pid): @@ -38,19 +40,22 @@ def get_socket_inodes(pid): inodes.append(int(target[8:-1])) return inodes + def _remove_empty(array): - return [x for x in array if x !=''] + return [x for x in array if x != ''] + def _convert_ip_port(array): - host,port = array.split(':') + host, port = array.split(':') # convert host from mangled-per-four-bytes form as used by kernel host = unhexlify(host) host_out = '' for x in range(0, len(host) // 4): - (val,) = struct.unpack('=I', host[x*4:(x+1)*4]) + (val,) = struct.unpack('=I', host[x * 4:(x + 1) * 4]) host_out += '%08x' % val - return host_out,int(port,16) + return host_out, int(port, 16) + def netstat(typ='tcp'): ''' @@ -58,21 +63,22 @@ def netstat(typ='tcp'): To get pid of all network process running on system, you must run this script as superuser ''' - with open('/proc/net/'+typ,'r',encoding='utf8') as f: + with open('/proc/net/' + typ, 'r', encoding='utf8') as f: content = f.readlines() content.pop(0) result = [] for line in content: - line_array = _remove_empty(line.split(' ')) # Split lines and remove empty spaces. + line_array = _remove_empty(line.split(' ')) # Split lines and remove empty spaces. tcp_id = line_array[0] l_addr = _convert_ip_port(line_array[1]) r_addr = _convert_ip_port(line_array[2]) state = line_array[3] - inode = int(line_array[9]) # Need the inode to match with process pid. + inode = int(line_array[9]) # Need the inode to match with process pid. nline = [tcp_id, l_addr, r_addr, state, inode] result.append(nline) return result + def get_bind_addrs(pid): ''' Get bind addresses as (host,port) tuples for process pid. @@ -84,6 +90,7 @@ def get_bind_addrs(pid): bind_addrs.append(conn[1]) return bind_addrs + # from: http://code.activestate.com/recipes/439093/ def all_interfaces(): ''' @@ -91,10 +98,10 @@ def all_interfaces(): ''' import fcntl # Linux only, so only import when required - is_64bits = sys.maxsize > 2**32 + is_64bits = sys.maxsize > 2 ** 32 struct_size = 40 if is_64bits else 32 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - max_possible = 8 # initial value + max_possible = 8 # initial value while True: bytes = max_possible * struct_size names = array.array('B', b'\0' * bytes) @@ -108,29 +115,30 @@ def all_interfaces(): else: break namestr = names.tobytes() - return [(namestr[i:i+16].split(b'\0', 1)[0], - socket.inet_ntoa(namestr[i+20:i+24])) + return [(namestr[i:i + 16].split(b'\0', 1)[0], + socket.inet_ntoa(namestr[i + 20:i + 24])) for i in range(0, outbytes, struct_size)] + def addr_to_hex(addr): ''' Convert string IPv4 or IPv6 address to binary address as returned by get_bind_addrs. Very naive implementation that certainly doesn't work for all IPv6 variants. ''' - if '.' in addr: # IPv4 + if '.' in addr: # IPv4 addr = [int(x) for x in addr.split('.')] - elif ':' in addr: # IPv6 - sub = [[], []] # prefix, suffix + elif ':' in addr: # IPv6 + sub = [[], []] # prefix, suffix x = 0 addr = addr.split(':') - for i,comp in enumerate(addr): + for i, comp in enumerate(addr): if comp == '': - if i == 0 or i == (len(addr)-1): # skip empty component at beginning or end + if i == 0 or i == (len(addr) - 1): # skip empty component at beginning or end continue - x += 1 # :: skips to suffix + x += 1 # :: skips to suffix assert x < 2 - else: # two bytes per component + else: # two bytes per component val = int(comp, 16) sub[x].append(val >> 8) sub[x].append(val & 0xff) @@ -141,6 +149,7 @@ def addr_to_hex(addr): raise ValueError('Could not parse address %s' % addr) return bytearray(addr).hex() + def test_ipv6_local(): ''' Check for (local) IPv6 support. diff --git a/test/functional/test_framework/ripemd160.py b/test/functional/test_framework/ripemd160.py index 12801364b4..4e283f977e 100644 --- a/test/functional/test_framework/ripemd160.py +++ b/test/functional/test_framework/ripemd160.py @@ -76,7 +76,7 @@ def compress(h0, h1, h2, h3, h4, block): # Right path variables. ar, br, cr, dr, er = h0, h1, h2, h3, h4 # Message variables. - x = [int.from_bytes(block[4*i:4*(i+1)], 'little') for i in range(16)] + x = [int.from_bytes(block[4 * i:4 * (i + 1)], 'little') for i in range(16)] # Iterate over the 80 rounds of the compression. for j in range(80): @@ -98,13 +98,13 @@ def ripemd160(data): state = (0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0) # Process full 64-byte blocks in the input. for b in range(len(data) >> 6): - state = compress(*state, data[64*b:64*(b+1)]) + state = compress(*state, data[64 * b:64 * (b + 1)]) # Construct final blocks (with padding and size). pad = b"\x80" + b"\x00" * ((119 - len(data)) & 63) fin = data[len(data) & ~63:] + pad + (8 * len(data)).to_bytes(8, 'little') # Process final blocks. for b in range(len(fin) >> 6): - state = compress(*state, fin[64*b:64*(b+1)]) + state = compress(*state, fin[64 * b:64 * (b + 1)]) # Produce output. return b"".join((h & 0xffffffff).to_bytes(4, 'little') for h in state) @@ -119,11 +119,11 @@ def test_ripemd160(self): (b"abc", "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"), (b"message digest", "5d0689ef49d2fae572b881b123a85ffa21595f36"), (b"abcdefghijklmnopqrstuvwxyz", - "f71c27109c692c1b56bbdceb5b9d2865b3708dbc"), + "f71c27109c692c1b56bbdceb5b9d2865b3708dbc"), (b"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - "12a053384a9c0c88e405a06c27dcf49ada62eb2b"), + "12a053384a9c0c88e405a06c27dcf49ada62eb2b"), (b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", - "b0e20b6e3116640286ed3a87a5713079b21f5189"), + "b0e20b6e3116640286ed3a87a5713079b21f5189"), (b"1234567890" * 8, "9b752e45573d4b39f4dbd3323cab82bf63326bfb"), (b"a" * 1000000, "52783243c1697bdbe16d37f97f68f08325dc1528") ]: diff --git a/test/functional/test_framework/script.py b/test/functional/test_framework/script.py index 83856df8fd..02c13e3fe7 100644 --- a/test/functional/test_framework/script.py +++ b/test/functional/test_framework/script.py @@ -18,11 +18,14 @@ OPCODE_NAMES = {} + def hash160(s): return ripemd160(sha256(s)) _opcode_instances = [] + + class CScriptOp(int): """A single script opcode""" __slots__ = () @@ -31,13 +34,13 @@ class CScriptOp(int): def encode_op_pushdata(d): """Encode a PUSHDATA op, returning bytes""" if len(d) < 0x4c: - return b'' + bytes([len(d)]) + d # OP_PUSHDATA + return b'' + bytes([len(d)]) + d # OP_PUSHDATA elif len(d) <= 0xff: - return b'\x4c' + bytes([len(d)]) + d # OP_PUSHDATA1 + return b'\x4c' + bytes([len(d)]) + d # OP_PUSHDATA1 elif len(d) <= 0xffff: - return b'\x4d' + struct.pack(b'= 0x80: # Mask for all but the highest result bit - num_mask = (2**(len(value)*8) - 1) >> 1 + num_mask = (2 ** (len(value) * 8) - 1) >> 1 result &= num_mask result *= -1 return result @@ -456,6 +462,7 @@ def __new__(cls, value=b''): def coerce_iterable(iterable): for instance in iterable: yield cls.__coerce_instance(instance) + # Annoyingly on both python2 and python3 bytes.join() always # returns a bytes instance even when subclassed. return super(CScript, cls).__new__(cls, b''.join(coerce_iterable(value))) @@ -493,21 +500,20 @@ def raw_iter(self): pushdata_type = 'PUSHDATA2' if i + 1 >= len(self): raise CScriptInvalidError('PUSHDATA2: missing data length') - datasize = self[i] + (self[i+1] << 8) + datasize = self[i] + (self[i + 1] << 8) i += 2 elif opcode == OP_PUSHDATA4: pushdata_type = 'PUSHDATA4' if i + 3 >= len(self): raise CScriptInvalidError('PUSHDATA4: missing data length') - datasize = self[i] + (self[i+1] << 8) + (self[i+2] << 16) + (self[i+3] << 24) + datasize = self[i] + (self[i + 1] << 8) + (self[i + 2] << 16) + (self[i + 3] << 24) i += 4 else: - assert False # shouldn't happen - + assert False # shouldn't happen - data = bytes(self[i:i+datasize]) + data = bytes(self[i:i + datasize]) # Check for truncation if len(data) < datasize: @@ -590,6 +596,7 @@ def GetSigOpCount(self, fAccurate): SIGHASH_SINGLE = 3 SIGHASH_ANYONECANPAY = 0x80 + def FindAndDelete(script, sig): """Consensus critical, see FindAndDelete() in Satoshi codebase""" r = b'' @@ -658,12 +665,12 @@ def SignatureHash(script, txTo, inIdx, hashtype): return (hash, None) + # TODO: Allow cached hashPrevouts/hashSequence/hashOutputs to be provided. # Performance optimization probably not necessary for python tests, however. # Note that this corresponds to sigversion == 1 in EvalScript, which is used # for version 0 witnesses. def SegwitVersion1SignatureHash(script, txTo, inIdx, hashtype, amount): - hashPrevouts = 0 hashSequence = 0 hashOutputs = 0 @@ -674,7 +681,8 @@ def SegwitVersion1SignatureHash(script, txTo, inIdx, hashtype, amount): serialize_prevouts += i.prevout.serialize() hashPrevouts = uint256_from_str(hash256(serialize_prevouts)) - if (not (hashtype & SIGHASH_ANYONECANPAY) and (hashtype & 0x1f) != SIGHASH_SINGLE and (hashtype & 0x1f) != SIGHASH_NONE): + if (not (hashtype & SIGHASH_ANYONECANPAY) and (hashtype & 0x1f) != SIGHASH_SINGLE and ( + hashtype & 0x1f) != SIGHASH_NONE): serialize_sequence = bytes() for i in txTo.vin: serialize_sequence += struct.pack(" len(bech) or len(bech) > 90: return (None, None) - if not all(x in CHARSET for x in bech[pos+1:]): + if not all(x in CHARSET for x in bech[pos + 1:]): return (None, None) hrp = bech[:pos] - data = [CHARSET.find(x) for x in bech[pos+1:]] + data = [CHARSET.find(x) for x in bech[pos + 1:]] if not bech32_verify_checksum(hrp, data): return (None, None) return (hrp, data[:-6]) diff --git a/test/functional/test_framework/siphash.py b/test/functional/test_framework/siphash.py index 7e694d5656..8b50579cd9 100644 --- a/test/functional/test_framework/siphash.py +++ b/test/functional/test_framework/siphash.py @@ -7,9 +7,11 @@ This implements SipHash-2-4 for 256-bit integers. """ + def rotl64(n, b): return n >> (64 - b) | (n & ((1 << (64 - b)) - 1)) << b + def siphash_round(v0, v1, v2, v3): v0 = (v0 + v1) & ((1 << 64) - 1) v1 = rotl64(v1, 13) @@ -27,6 +29,7 @@ def siphash_round(v0, v1, v2, v3): v2 = rotl64(v2, 32) return (v0, v1, v2, v3) + def siphash256(k0, k1, h): n0 = h & ((1 << 64) - 1) n1 = (h >> 64) & ((1 << 64) - 1) diff --git a/test/functional/test_framework/socks5.py b/test/functional/test_framework/socks5.py index fe1aef1279..f2196bd0e5 100644 --- a/test/functional/test_framework/socks5.py +++ b/test/functional/test_framework/socks5.py @@ -11,15 +11,18 @@ logger = logging.getLogger("TestFramework.socks5") + # Protocol constants class Command: CONNECT = 0x01 + class AddressType: IPV4 = 0x01 DOMAINNAME = 0x03 IPV6 = 0x04 + # Utility functions def recvall(s, n): """Receive n bytes from a socket, or fail.""" @@ -32,26 +35,33 @@ def recvall(s, n): n -= len(d) return rv + # Implementation classes class Socks5Configuration(): """Proxy configuration.""" + def __init__(self): - self.addr = None # Bind address (must be set) - self.af = socket.AF_INET # Bind address family + self.addr = None # Bind address (must be set) + self.af = socket.AF_INET # Bind address family self.unauth = False # Support unauthenticated self.auth = False # Support authentication + class Socks5Command(): """Information about an incoming socks5 command.""" + def __init__(self, cmd, atyp, addr, port, username, password): - self.cmd = cmd # Command (one of Command.*) - self.atyp = atyp # Address type (one of AddressType.*) - self.addr = addr # Address - self.port = port # Port to connect to + self.cmd = cmd # Command (one of Command.*) + self.atyp = atyp # Address type (one of AddressType.*) + self.addr = addr # Address + self.port = port # Port to connect to self.username = username self.password = password + def __repr__(self): - return 'Socks5Command(%s,%s,%s,%s,%s,%s)' % (self.cmd, self.atyp, self.addr, self.port, self.username, self.password) + return 'Socks5Command(%s,%s,%s,%s,%s,%s)' % ( + self.cmd, self.atyp, self.addr, self.port, self.username, self.password) + class Socks5Connection(): def __init__(self, serv, conn): @@ -70,9 +80,9 @@ def handle(self): methods = bytearray(recvall(self.conn, nmethods)) method = None if 0x02 in methods and self.serv.conf.auth: - method = 0x02 # username/password + method = 0x02 # username/password elif 0x00 in methods and self.serv.conf.unauth: - method = 0x00 # unauthenticated + method = 0x00 # unauthenticated if method is None: raise IOError('No supported authentication method was offered') # Send response @@ -107,7 +117,7 @@ def handle(self): addr = recvall(self.conn, 16) else: raise IOError('Unknown address type %i' % atyp) - port_hi,port_lo = recvall(self.conn, 2) + port_hi, port_lo = recvall(self.conn, 2) port = (port_hi << 8) | port_lo # Send dummy response @@ -123,6 +133,7 @@ def handle(self): finally: self.conn.close() + class Socks5Server(): def __init__(self, conf): self.conf = conf @@ -132,7 +143,7 @@ def __init__(self, conf): self.s.listen(5) self.running = False self.thread = None - self.queue = queue.Queue() # report connections and exceptions to client + self.queue = queue.Queue() # report connections and exceptions to client def run(self): while self.running: @@ -157,4 +168,3 @@ def stop(self): s.connect(self.conf.addr) s.close() self.thread.join() - diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index a4dc40f5dc..3ff739a24a 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -42,6 +42,7 @@ class TestStatus(Enum): FAILED = 2 SKIPPED = 3 + TEST_EXIT_PASSED = 0 TEST_EXIT_FAILED = 1 TEST_EXIT_SKIPPED = 77 @@ -113,16 +114,17 @@ def _check_rollback(self, func, *args, **kwargs): self.rollback_to(init_height) final_data = self._get_chain_data() final_height = self.nodes[0].getblockcount() - assert(init_data == final_data) - assert(init_height == final_height) + assert (init_data == final_data) + assert (init_height == final_height) return result # WARNING: This decorator uses _get_chain_data() internally which can be an expensive call if used in large test scenarios. @classmethod def capture_rollback_verify(cls, func): - def wrapper(self, *args, **kwargs): - return self._check_rollback(func, *args, **kwargs) - return wrapper + def wrapper(self, *args, **kwargs): + return self._check_rollback(func, *args, **kwargs) + + return wrapper def main(self): """Main function. This should not be overridden by the subclass test scripts.""" @@ -132,7 +134,8 @@ def main(self): help="Leave defids and test.* datadir on exit or error") parser.add_argument("--noshutdown", dest="noshutdown", default=False, action="store_true", help="Don't stop defids after the test execution") - parser.add_argument("--cachedir", dest="cachedir", default=os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/../../cache"), + parser.add_argument("--cachedir", dest="cachedir", + default=os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/../../cache"), help="Directory for caching pregenerated datadirs (default: %(default)s)") parser.add_argument("--tmpdir", dest="tmpdir", help="Root directory for datadirs") parser.add_argument("-l", "--loglevel", dest="loglevel", default="INFO", @@ -168,8 +171,11 @@ def main(self): config = configparser.ConfigParser() config.read_file(open(self.options.configfile)) self.config = config - self.options.defid = os.getenv("DEFID", default=config["environment"]["BUILDDIR"] + '/src/defid' + config["environment"]["EXEEXT"]) - self.options.deficli = os.getenv("DEFICLI", default=config["environment"]["BUILDDIR"] + '/src/defi-cli' + config["environment"]["EXEEXT"]) + self.options.defid = os.getenv("DEFID", + default=config["environment"]["BUILDDIR"] + '/src/defid' + config["environment"][ + "EXEEXT"]) + self.options.deficli = os.getenv("DEFICLI", default=config["environment"]["BUILDDIR"] + '/src/defi-cli' + + config["environment"]["EXEEXT"]) os.environ['PATH'] = os.pathsep.join([ os.path.join(config['environment']['BUILDDIR'], 'src'), @@ -247,10 +253,10 @@ def main(self): self.log.info("Note: defids were not stopped and may still be running") should_clean_up = ( - not self.options.nocleanup and - not self.options.noshutdown and - success != TestStatus.FAILED and - not self.options.perf + not self.options.nocleanup and + not self.options.noshutdown and + success != TestStatus.FAILED and + not self.options.perf ) if should_clean_up: self.log.info("Cleaning up {} on exit".format(self.options.tmpdir)) @@ -270,7 +276,9 @@ def main(self): exit_code = TEST_EXIT_SKIPPED else: self.log.error("Test failed. Test logging available at %s/test_framework.log", self.options.tmpdir) - self.log.error("Hint: Call {} '{}' to consolidate all logs".format(os.path.normpath(os.path.dirname(os.path.realpath(__file__)) + "/../combine_logs.py"), self.options.tmpdir)) + self.log.error("Hint: Call {} '{}' to consolidate all logs".format( + os.path.normpath(os.path.dirname(os.path.realpath(__file__)) + "/../combine_logs.py"), + self.options.tmpdir)) exit_code = TEST_EXIT_FAILED logging.shutdown() if cleanup_tree_on_exit: @@ -344,10 +352,10 @@ def get_id_token(self, symbol): if (token["symbol"] == symbol): return str(idx) - def setup_tokens(self, my_tokens = None): - assert(self.setup_clean_chain == True) - assert('-txnotokens=0' in self.extra_args[0]) - assert('-txnotokens=0' in self.extra_args[1]) + def setup_tokens(self, my_tokens=None): + assert (self.setup_clean_chain == True) + assert ('-txnotokens=0' in self.extra_args[0]) + assert ('-txnotokens=0' in self.extra_args[1]) self.nodes[0].generate(25) self.nodes[1].generate(25) self.sync_blocks() @@ -390,14 +398,14 @@ def setup_tokens(self, my_tokens = None): self.nodes[0].createtoken({ "symbol": "GOLD", "name": "shiny gold", - "collateralAddress": self.nodes[0].get_genesis_keys().ownerAuthAddress # collateralGold + "collateralAddress": self.nodes[0].get_genesis_keys().ownerAuthAddress # collateralGold }) self.nodes[0].generate(1) self.sync_blocks() self.nodes[1].createtoken({ "symbol": "SILVER", "name": "just silver", - "collateralAddress": self.nodes[1].get_genesis_keys().ownerAuthAddress # collateralSilver + "collateralAddress": self.nodes[1].get_genesis_keys().ownerAuthAddress # collateralSilver }) self.nodes[1].generate(1) self.sync_blocks() @@ -542,7 +550,7 @@ def start_nodes(self, extra_args=None, *args, **kwargs): node.start(extra_args[i], *args, **kwargs) for node in self.nodes: node.wait_for_rpc_connection() - except: + except Exception: # If one node failed to start, stop the others self.stop_nodes() raise @@ -615,7 +623,8 @@ def _start_logging(self): ll = int(self.options.loglevel) if self.options.loglevel.isdigit() else self.options.loglevel.upper() ch.setLevel(ll) # Format logs the same as defid's debug.log with microprecision (so log files can be concatenated and sorted) - formatter = logging.Formatter(fmt='%(asctime)s.%(msecs)03d000Z %(name)s (%(levelname)s): %(message)s', datefmt='%Y-%m-%dT%H:%M:%S') + formatter = logging.Formatter(fmt='%(asctime)s.%(msecs)03d000Z %(name)s (%(levelname)s): %(message)s', + datefmt='%Y-%m-%dT%H:%M:%S') formatter.converter = time.gmtime fh.setFormatter(formatter) ch.setFormatter(formatter) @@ -664,8 +673,10 @@ def _initialize_chain(self): # Wait for RPC connections to be ready self.nodes[CACHE_NODE_ID].wait_for_rpc_connection() - self.nodes[CACHE_NODE_ID].importprivkey(privkey=self.nodes[CACHE_NODE_ID].get_genesis_keys().ownerPrivKey, label='coinbase') - self.nodes[CACHE_NODE_ID].importprivkey(privkey=self.nodes[CACHE_NODE_ID].get_genesis_keys().operatorPrivKey, label='coinbase') + self.nodes[CACHE_NODE_ID].importprivkey(privkey=self.nodes[CACHE_NODE_ID].get_genesis_keys().ownerPrivKey, + label='coinbase') + self.nodes[CACHE_NODE_ID].importprivkey( + privkey=self.nodes[CACHE_NODE_ID].get_genesis_keys().operatorPrivKey, label='coinbase') # Create a 199-block-long chain; each of the 4 first nodes # gets 25 mature blocks and 25 immature. @@ -696,7 +707,8 @@ def cache_path(*paths): shutil.rmtree(cache_path('burn')) for entry in os.listdir(cache_path()): - if entry not in ['chainstate', 'blocks', 'enhancedcs', 'anchors', 'history']: # Only keep chainstate and blocks folder + if entry not in ['chainstate', 'blocks', 'enhancedcs', 'anchors', + 'history']: # Only keep chainstate and blocks folder os.remove(cache_path(entry)) for i in range(self.num_nodes): diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py index 09fc50d0e3..121ea6477d 100755 --- a/test/functional/test_framework/test_node.py +++ b/test/functional/test_framework/test_node.py @@ -58,7 +58,8 @@ class TestNode(): To make things easier for the test writer, any unrecognised messages will be dispatched to the RPC connection.""" - def __init__(self, i, datadir, *, chain, rpchost, timewait, defid, defi_cli, coverage_dir, cwd, extra_conf=None, extra_args=None, use_cli=False, start_perf=False, use_valgrind=False): + def __init__(self, i, datadir, *, chain, rpchost, timewait, defid, defi_cli, coverage_dir, cwd, extra_conf=None, + extra_args=None, use_cli=False, start_perf=False, use_valgrind=False): """ Kwargs: start_perf (bool): If True, begin profiling the node with `perf` as soon as @@ -95,7 +96,7 @@ def __init__(self, i, datadir, *, chain, rpchost, timewait, defid, defi_cli, cov "-debugexclude=leveldb", "-debugexclude=accountchange", "-uacomment=testnode%d" % i, - "-masternode_operator="+self.get_genesis_keys().operatorAuthAddress, + "-masternode_operator=" + self.get_genesis_keys().operatorAuthAddress, "-dummypos=1", "-txnotokens=1", ] @@ -119,24 +120,34 @@ def __init__(self, i, datadir, *, chain, rpchost, timewait, defid, defi_cli, cov self.rpc = None self.url = None self.log = logging.getLogger('TestFramework.node%d' % i) - self.cleanup_on_exit = True # Whether to kill the node when this object goes away + self.cleanup_on_exit = True # Whether to kill the node when this object goes away # Cache perf subprocesses here by their data output filename. self.perf_subprocesses = {} self.p2ps = [] - MnKeys = collections.namedtuple('MnKeys', ['ownerAuthAddress', 'ownerPrivKey', 'operatorAuthAddress', 'operatorPrivKey']) - PRIV_KEYS = [ # at least node0&1 operator should be non-witness!!! (feature_bip68_sequence.py,interface_zmq,rpc_psbt fails) + MnKeys = collections.namedtuple('MnKeys', + ['ownerAuthAddress', 'ownerPrivKey', 'operatorAuthAddress', 'operatorPrivKey']) + PRIV_KEYS = [ + # at least node0&1 operator should be non-witness!!! (feature_bip68_sequence.py,interface_zmq,rpc_psbt fails) # legacy: - MnKeys("mwsZw8nF7pKxWH8eoKL9tPxTpaFkz7QeLU", "cRiRQ9cHmy5evDqNDdEV8f6zfbK6epi9Fpz4CRZsmLEmkwy54dWz", "mswsMVsyGMj1FzDMbbxw2QW3KvQAv2FKiy", "cPGEaz8AGiM71NGMRybbCqFNRcuUhg3uGvyY4TFE1BZC26EW2PkC"), - MnKeys("msER9bmJjyEemRpQoS8YYVL21VyZZrSgQ7", "cSCmN1tjcR2yR1eaQo9WmjTMR85SjEoNPqMPWGAApQiTLJH8JF7W", "mps7BdmwEF2vQ9DREDyNPibqsuSRZ8LuwQ", "cVNTRYV43guugJoDgaiPZESvNtnfnUW19YEjhybihwDbLKjyrZNV"), - MnKeys("myF3aHuxtEuqqTw44EurtVs6mjyc1QnGUS", "cSXiqwTiYzECugcvCT4PyPKz2yKaTST8HowFVBBjccZCPkX6wsE9", "mtbWisYQmw9wcaecvmExeuixG7rYGqKEU4", "cPh5YaousYQ92tNd9FkiiS26THjSVBDHUMHZzUiBFbtGNS4Uw9AD"), - MnKeys("mwyaBGGE7ka58F7aavH5hjMVdJENP9ZEVz", "cVA52y8ABsUYNuXVJ17d44N1wuSmeyPtke9urw4LchTyKsaGDMbY", "n1n6Z5Zdoku4oUnrXeQ2feLz3t7jmVLG9t", "cV9tJBgAnSfFmPaC6fWWvA9StLKkU3DKV7eXJHjWMUENQ8cKJDkL"), - MnKeys("mgsE1SqrcfUhvuYuRjqy6rQCKmcCVKNhMu", "cRJyBuQPuUhYzN5F2Uf35958oK9AzZ5UscRfVmaRr8ktWq6Ac23u", "mzqdipBJcKX9rXXxcxw2kTHC3Xjzd3siKg", "cQYJ87qk39i3uFsXBZ2EkwdX1h72q1RQcX9V8X7PPydFPgujxrCy"), - MnKeys("mud4VMfbBqXNpbt8ur33KHKx8pk3npSq8c", "cPjeCNka7omVbKKfywPVQyBig9eopBHy6eJqLzrdJqMP4DXApkcb", "mk5DkY4qcV6CUpuxDVyD3AHzRq5XK9kbRN", "cV6Hjhutf11RvFHaERkp52QNynm2ifNmtUfP8EwRRMg6NaaQsHTe"), + MnKeys("mwsZw8nF7pKxWH8eoKL9tPxTpaFkz7QeLU", "cRiRQ9cHmy5evDqNDdEV8f6zfbK6epi9Fpz4CRZsmLEmkwy54dWz", + "mswsMVsyGMj1FzDMbbxw2QW3KvQAv2FKiy", "cPGEaz8AGiM71NGMRybbCqFNRcuUhg3uGvyY4TFE1BZC26EW2PkC"), + MnKeys("msER9bmJjyEemRpQoS8YYVL21VyZZrSgQ7", "cSCmN1tjcR2yR1eaQo9WmjTMR85SjEoNPqMPWGAApQiTLJH8JF7W", + "mps7BdmwEF2vQ9DREDyNPibqsuSRZ8LuwQ", "cVNTRYV43guugJoDgaiPZESvNtnfnUW19YEjhybihwDbLKjyrZNV"), + MnKeys("myF3aHuxtEuqqTw44EurtVs6mjyc1QnGUS", "cSXiqwTiYzECugcvCT4PyPKz2yKaTST8HowFVBBjccZCPkX6wsE9", + "mtbWisYQmw9wcaecvmExeuixG7rYGqKEU4", "cPh5YaousYQ92tNd9FkiiS26THjSVBDHUMHZzUiBFbtGNS4Uw9AD"), + MnKeys("mwyaBGGE7ka58F7aavH5hjMVdJENP9ZEVz", "cVA52y8ABsUYNuXVJ17d44N1wuSmeyPtke9urw4LchTyKsaGDMbY", + "n1n6Z5Zdoku4oUnrXeQ2feLz3t7jmVLG9t", "cV9tJBgAnSfFmPaC6fWWvA9StLKkU3DKV7eXJHjWMUENQ8cKJDkL"), + MnKeys("mgsE1SqrcfUhvuYuRjqy6rQCKmcCVKNhMu", "cRJyBuQPuUhYzN5F2Uf35958oK9AzZ5UscRfVmaRr8ktWq6Ac23u", + "mzqdipBJcKX9rXXxcxw2kTHC3Xjzd3siKg", "cQYJ87qk39i3uFsXBZ2EkwdX1h72q1RQcX9V8X7PPydFPgujxrCy"), + MnKeys("mud4VMfbBqXNpbt8ur33KHKx8pk3npSq8c", "cPjeCNka7omVbKKfywPVQyBig9eopBHy6eJqLzrdJqMP4DXApkcb", + "mk5DkY4qcV6CUpuxDVyD3AHzRq5XK9kbRN", "cV6Hjhutf11RvFHaERkp52QNynm2ifNmtUfP8EwRRMg6NaaQsHTe"), # bech32: - MnKeys("bcrt1qyrfrpadwgw7p5eh3e9h3jmu4kwlz4prx73cqny", "cR4qgUdPhANDVF3bprcp5N9PNW2zyogDx6DGu2wHh2qtJB1L1vQj", "bcrt1qmfvw3dp3u6fdvqkdc0y3lr0e596le9cf22vtsv", "cVsa2wQvCjZZ54jGteQ8qiQbQLJQmZSBWriYUYyXbcaqUJFqK5HR"), - MnKeys("bcrt1qyeuu9rvq8a67j86pzvh5897afdmdjpyankp4mu", "cUX8AEUZYsZxNUh5fTS7ZGnF6SPQuTeTDTABGrp5dbPftCga2zcp", "bcrt1qurwyhta75n2g75u2u5nds9p6w9v62y8wr40d2r", "cUp5EVEjuAGpemSuejP36TWWuFKzuCbUJ4QAKJTiSSB2vXzDLsJW"), + MnKeys("bcrt1qyrfrpadwgw7p5eh3e9h3jmu4kwlz4prx73cqny", "cR4qgUdPhANDVF3bprcp5N9PNW2zyogDx6DGu2wHh2qtJB1L1vQj", + "bcrt1qmfvw3dp3u6fdvqkdc0y3lr0e596le9cf22vtsv", "cVsa2wQvCjZZ54jGteQ8qiQbQLJQmZSBWriYUYyXbcaqUJFqK5HR"), + MnKeys("bcrt1qyeuu9rvq8a67j86pzvh5897afdmdjpyankp4mu", "cUX8AEUZYsZxNUh5fTS7ZGnF6SPQuTeTDTABGrp5dbPftCga2zcp", + "bcrt1qurwyhta75n2g75u2u5nds9p6w9v62y8wr40d2r", "cUp5EVEjuAGpemSuejP36TWWuFKzuCbUJ4QAKJTiSSB2vXzDLsJW"), ] Mocktime = None @@ -171,7 +182,8 @@ def generate(self, nblocks, maxtries=1000000, address=None): minted += 1 self.pullup_mocktime() # mintedHashes.append(self.getblockhash(height+minted)) - mintedHashes.append(self.getblockhash(self.getblockcount())) # always "tip" due to chain switching (possibly wrong) + mintedHashes.append( + self.getblockhash(self.getblockcount())) # always "tip" due to chain switching (possibly wrong) return mintedHashes def _node_msg(self, msg: str) -> str: @@ -224,7 +236,8 @@ def start(self, extra_args=None, *, cwd=None, stdout=None, stderr=None, **kwargs # add environment variable LIBC_FATAL_STDERR_=1 so that libc errors are written to stderr and not the terminal subp_env = dict(os.environ, LIBC_FATAL_STDERR_="1") - self.process = subprocess.Popen(self.args + extra_args, env=subp_env, stdout=stdout, stderr=stderr, cwd=cwd, **kwargs) + self.process = subprocess.Popen(self.args + extra_args, env=subp_env, stdout=stdout, stderr=stderr, cwd=cwd, + **kwargs) self.running = True self.log.debug("defid started, waiting for RPC to come up") @@ -241,7 +254,8 @@ def wait_for_rpc_connection(self): raise FailedToStartError(self._node_msg( 'defid exited with status {} during initialization'.format(self.process.returncode))) try: - rpc = get_rpc_proxy(rpc_url(self.datadir, self.index, self.chain, self.rpchost), self.index, timeout=self.rpc_timeout, coveragedir=self.coverage_dir) + rpc = get_rpc_proxy(rpc_url(self.datadir, self.index, self.chain, self.rpchost), self.index, + timeout=self.rpc_timeout, coveragedir=self.coverage_dir) rpc.getblockcount() # If the call to getblockcount() succeeds then the RPC connection is up self.log.debug("RPC successfully started") @@ -347,7 +361,8 @@ def assert_debug_log(self, expected_msgs, timeout=2): if time.time() >= time_end: break time.sleep(0.05) - self._raise_assertion_error('Expected messages "{}" does not partially match log:\n\n{}\n\n'.format(str(expected_msgs), print_log)) + self._raise_assertion_error( + 'Expected messages "{}" does not partially match log:\n\n{}\n\n'.format(str(expected_msgs), print_log)) @contextlib.contextmanager def profile_with_perf(self, profile_name): @@ -399,9 +414,9 @@ def test_success(cmd): cmd = [ 'perf', 'record', - '-g', # Record the callgraph. + '-g', # Record the callgraph. '--call-graph', 'dwarf', # Compatibility for gcc's --fomit-frame-pointer. - '-F', '101', # Sampling frequency in Hz. + '-F', '101', # Sampling frequency in Hz. '-p', str(self.process.pid), '-o', output_path, ] @@ -427,7 +442,8 @@ def _stop_perf(self, profile_name): report_cmd = "perf report -i {}".format(output_path) self.log.info("See perf output by running '{}'".format(report_cmd)) - def assert_start_raises_init_error(self, extra_args=None, expected_msg=None, match=ErrorMatch.FULL_TEXT, *args, **kwargs): + def assert_start_raises_init_error(self, extra_args=None, expected_msg=None, match=ErrorMatch.FULL_TEXT, *args, + **kwargs): """Attempt to start the node and expect it to raise an error. extra_args: extra arguments to pass through to defid @@ -436,7 +452,7 @@ def assert_start_raises_init_error(self, extra_args=None, expected_msg=None, mat Will throw if defid starts without an error. Will throw if an expected_msg is provided and it does not match defid's stdout.""" with tempfile.NamedTemporaryFile(dir=self.stderr_dir, delete=False) as log_stderr, \ - tempfile.NamedTemporaryFile(dir=self.stdout_dir, delete=False) as log_stdout: + tempfile.NamedTemporaryFile(dir=self.stdout_dir, delete=False) as log_stdout: try: self.start(extra_args, stdout=log_stdout, stderr=log_stderr, *args, **kwargs) self.wait_for_rpc_connection() @@ -453,7 +469,8 @@ def assert_start_raises_init_error(self, extra_args=None, expected_msg=None, mat if match == ErrorMatch.PARTIAL_REGEX: if re.search(expected_msg, stderr, flags=re.MULTILINE) is None: self._raise_assertion_error( - 'Expected message "{}" does not partially match stderr:\n"{}"'.format(expected_msg, stderr)) + 'Expected message "{}" does not partially match stderr:\n"{}"'.format(expected_msg, + stderr)) elif match == ErrorMatch.FULL_REGEX: if re.fullmatch(expected_msg, stderr) is None: self._raise_assertion_error( @@ -501,6 +518,7 @@ def disconnect_p2ps(self): p.peer_disconnect() del self.p2ps[:] + class TestNodeCLIAttr: def __init__(self, cli, command): self.cli = cli @@ -512,6 +530,7 @@ def __call__(self, *args, **kwargs): def get_request(self, *args, **kwargs): return lambda: self(*args, **kwargs) + def arg_to_cli(arg): if isinstance(arg, bool): return str(arg).lower() @@ -520,6 +539,7 @@ def arg_to_cli(arg): else: return str(arg) + class TestNodeCLI(): """Interface to defi-cli for an individual node""" @@ -553,7 +573,8 @@ def send_cli(self, command=None, *args, **kwargs): """Run defi-cli command. Deserializes returned string as python object.""" pos_args = [arg_to_cli(arg) for arg in args] named_args = [str(key) + "=" + arg_to_cli(value) for (key, value) in kwargs.items()] - assert not (pos_args and named_args), "Cannot use positional arguments and named arguments in the same defi-cli call" + assert not ( + pos_args and named_args), "Cannot use positional arguments and named arguments in the same defi-cli call" p_args = [self.binary, "-datadir=" + self.datadir] + self.options if named_args: p_args += ["-named"] @@ -561,7 +582,8 @@ def send_cli(self, command=None, *args, **kwargs): p_args += [command] p_args += pos_args + named_args self.log.debug("Running defi-cli command: %s" % command) - process = subprocess.Popen(p_args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) + process = subprocess.Popen(p_args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, + universal_newlines=True) cli_stdout, cli_stderr = process.communicate(input=self.input) returncode = process.poll() if returncode: diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py index 6de07ba6d2..126a811ac8 100644 --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -22,6 +22,7 @@ logger = logging.getLogger("TestFramework.utils") + # Assert functions ################## @@ -34,24 +35,30 @@ def assert_fee_amount(fee, tx_size, fee_per_kB): if fee > (tx_size + 2) * fee_per_kB / 1000: raise AssertionError("Fee of %s BTC too high! (Should be %s BTC)" % (str(fee), str(target_fee))) + def assert_equal(thing1, thing2, *args): if thing1 != thing2 or any(thing1 != arg for arg in args): raise AssertionError("not(%s)" % " == ".join(str(arg) for arg in (thing1, thing2) + args)) + def assert_greater_than(thing1, thing2): if thing1 <= thing2: raise AssertionError("%s <= %s" % (str(thing1), str(thing2))) + def assert_greater_than_or_equal(thing1, thing2): if thing1 < thing2: raise AssertionError("%s < %s" % (str(thing1), str(thing2))) + def almost_equal(x, y, threshold=0.0001): - return abs(x-y) < threshold + return abs(x - y) < threshold + def assert_raises(exc, fun, *args, **kwds): assert_raises_message(exc, None, fun, *args, **kwds) + def assert_raises_message(exc, message, fun, *args, **kwds): try: fun(*args, **kwds) @@ -65,6 +72,7 @@ def assert_raises_message(exc, message, fun, *args, **kwds): else: raise AssertionError("No exception raised") + def assert_raises_process_error(returncode, output, fun, *args, **kwds): """Execute a process and asserts the process return code and output. @@ -89,6 +97,7 @@ def assert_raises_process_error(returncode, output, fun, *args, **kwds): else: raise AssertionError("No exception raised") + def assert_raises_rpc_error(code, message, fun, *args, **kwds): """Run an RPC and verify that a specific JSONRPC exception code and message is raised. @@ -107,6 +116,7 @@ def assert_raises_rpc_error(code, message, fun, *args, **kwds): """ assert try_rpc(code, message, fun, *args, **kwds), "No exception raised" + def try_rpc(code, message, fun, *args, **kwds): """Tries to run an rpc command. @@ -126,6 +136,7 @@ def try_rpc(code, message, fun, *args, **kwds): else: return False + def assert_is_hex_string(string): try: int(string, 16) @@ -133,6 +144,7 @@ def assert_is_hex_string(string): raise AssertionError( "Couldn't interpret %r as hexadecimal; raised: %s" % (string, e)) + def assert_is_hash_string(string, length=64): if not isinstance(string, str): raise AssertionError("Expected a string, got type %r" % type(string)) @@ -143,6 +155,7 @@ def assert_is_hash_string(string, length=64): raise AssertionError( "String %r contains invalid characters for a hash." % string) + def assert_array_result(object_array, to_match, expected, should_not_find=False): """ Pass in array of JSON objects, a dictionary with key/value pairs @@ -172,6 +185,7 @@ def assert_array_result(object_array, to_match, expected, should_not_find=False) if num_matched > 0 and should_not_find: raise AssertionError("Objects were found %s" % (str(to_match))) + # Utility functions ################### @@ -182,6 +196,7 @@ def check_json_precision(): if satoshis != 2000000000000003: raise RuntimeError("JSON encode/decode loses precision") + def count_bytes(hex_string): return len(bytearray.fromhex(hex_string)) @@ -189,12 +204,15 @@ def count_bytes(hex_string): def hex_str_to_bytes(hex_str): return unhexlify(hex_str.encode('ascii')) + def str_to_b64str(string): return b64encode(string.encode('utf-8')).decode('ascii') + def satoshi_round(amount): return Decimal(amount).quantize(Decimal('0.00000001'), rounding=ROUND_DOWN) + def wait_until(predicate, *, attempts=float('inf'), timeout=float('inf'), lock=None): if attempts == float('inf') and timeout == float('inf'): timeout = 60 @@ -221,6 +239,7 @@ def wait_until(predicate, *, attempts=float('inf'), timeout=float('inf'), lock=N raise AssertionError("Predicate {} not true after {} seconds".format(predicate_source, timeout)) raise RuntimeError('Unreachable') + # RPC/P2P connection constants and functions ############################################ @@ -231,10 +250,12 @@ def wait_until(predicate, *, attempts=float('inf'), timeout=float('inf'), lock=N # The number of ports to "reserve" for p2p and rpc, each PORT_RANGE = 5000 + class PortSeed: # Must be initialized with a unique integer for each process n = None + def get_rpc_proxy(url, node_number, timeout=None, coveragedir=None): """ Args: @@ -260,13 +281,16 @@ def get_rpc_proxy(url, node_number, timeout=None, coveragedir=None): return coverage.AuthServiceProxyWrapper(proxy, coverage_logfile) + def p2p_port(n): assert n <= MAX_NODES return PORT_MIN + n + (MAX_NODES * PortSeed.n) % (PORT_RANGE - 1 - MAX_NODES) + def rpc_port(n): return PORT_MIN + PORT_RANGE + n + (MAX_NODES * PortSeed.n) % (PORT_RANGE - 1 - MAX_NODES) + def rpc_url(datadir, i, chain, rpchost): rpc_u, rpc_p = get_auth_cookie(datadir, chain) host = '127.0.0.1' @@ -279,6 +303,7 @@ def rpc_url(datadir, i, chain, rpchost): host = rpchost return "http://%s:%s@%s:%d" % (rpc_u, rpc_p, host, int(port)) + # Node functions ################ @@ -301,14 +326,17 @@ def initialize_datadir(dirname, n, chain): os.makedirs(os.path.join(datadir, 'stdout'), exist_ok=True) return datadir + def get_datadir_path(dirname, n): return os.path.join(dirname, "node" + str(n)) + def append_config(datadir, options): with open(os.path.join(datadir, "defi.conf"), 'a', encoding='utf8') as f: for option in options: f.write(option + "\n") + def get_auth_cookie(datadir, chain): user = None password = None @@ -333,16 +361,19 @@ def get_auth_cookie(datadir, chain): raise ValueError("No RPC credentials") return user, password + # If a cookie file exists in the given datadir, delete it. def delete_cookie_file(datadir, chain): if os.path.isfile(os.path.join(datadir, chain, ".cookie")): logger.debug("Deleting leftover cookie file") os.remove(os.path.join(datadir, chain, ".cookie")) + def set_node_times(nodes, t): for node in nodes: node.setmocktime(t) + def disconnect_nodes(from_connection, node_num): for peer_id in [peer['id'] for peer in from_connection.getpeerinfo() if "testnode%d" % node_num in peer['subver']]: try: @@ -351,23 +382,27 @@ def disconnect_nodes(from_connection, node_num): # If this node is disconnected between calculating the peer id # and issuing the disconnect, don't worry about it. # This avoids a race condition if we're mass-disconnecting peers. - if e.error['code'] != -29: # RPC_CLIENT_NODE_NOT_CONNECTED + if e.error['code'] != -29: # RPC_CLIENT_NODE_NOT_CONNECTED raise # wait to disconnect - wait_until(lambda: [peer['id'] for peer in from_connection.getpeerinfo() if "testnode%d" % node_num in peer['subver']] == [], timeout=5) + wait_until(lambda: [peer['id'] for peer in from_connection.getpeerinfo() if + "testnode%d" % node_num in peer['subver']] == [], timeout=5) + def connect_nodes(from_connection, node_num): ip_port = "127.0.0.1:" + str(p2p_port(node_num)) from_connection.addnode(ip_port, "onetry") # poll until version handshake complete to avoid race conditions # with transaction relaying - wait_until(lambda: all(peer['version'] != 0 for peer in from_connection.getpeerinfo())) + wait_until(lambda: all(peer['version'] != 0 for peer in from_connection.getpeerinfo())) + def connect_nodes_bi(nodes, a, b): connect_nodes(nodes[a], b) connect_nodes(nodes[b], a) + def sync_blocks(rpc_connections, *, wait=1, timeout=60): """ Wait until everybody has the same tip. @@ -384,6 +419,7 @@ def sync_blocks(rpc_connections, *, wait=1, timeout=60): time.sleep(wait) raise AssertionError("Block sync timed out:{}".format("".join("\n {!r}".format(b) for b in best_hash))) + def sync_mempools(rpc_connections, *, wait=1, timeout=60, flush_scheduler=True): """ Wait until everybody has the same transactions in their memory @@ -400,6 +436,7 @@ def sync_mempools(rpc_connections, *, wait=1, timeout=60, flush_scheduler=True): time.sleep(wait) raise AssertionError("Mempool sync timed out:{}".format("".join("\n {!r}".format(m) for m in pool))) + # Transaction/Block functions ############################# @@ -414,6 +451,7 @@ def find_output(node, txid, amount, *, blockhash=None): return i raise RuntimeError("find_output txid %s : %s not found" % (txid, str(amount))) + def gather_inputs(from_node, amount_needed, confirmations_required=1): """ Return a random set of unspent txouts that are enough to pay amount_needed @@ -431,6 +469,7 @@ def gather_inputs(from_node, amount_needed, confirmations_required=1): raise RuntimeError("Insufficient funds: need %d, have %d" % (amount_needed, total_in)) return (total_in, inputs) + def make_change(from_node, amount_in, amount_out, fee): """ Create change output(s), return them @@ -448,6 +487,7 @@ def make_change(from_node, amount_in, amount_out, fee): outputs[from_node.getnewaddress()] = change return outputs + def random_transaction(nodes, amount, min_fee, fee_increment, fee_variants): """ Create a random transaction. @@ -467,6 +507,7 @@ def random_transaction(nodes, amount, min_fee, fee_increment, fee_variants): return (txid, signresult["hex"], fee) + # Helper to create at least "count" utxos # Pass in a fee that is sufficient for relay and mining new transactions. def create_confirmed_utxos(fee, node, count): @@ -499,6 +540,7 @@ def create_confirmed_utxos(fee, node, count): assert len(utxos) >= count return utxos + # Create large OP_RETURN txouts that can be appended to a transaction # to make it large (helper for constructing large transactions). def gen_return_txouts(): @@ -516,6 +558,7 @@ def gen_return_txouts(): txouts.append(txout) return txouts + # Create a spend of each passed-in utxo, splicing in "txouts" to each raw # transaction to make it large. See gen_return_txouts() above. def create_lots_of_big_transactions(node, txouts, utxos, num, fee): @@ -539,10 +582,11 @@ def create_lots_of_big_transactions(node, txouts, utxos, num, fee): txids.append(txid) return txids + def mine_large_block(node, utxos=None): # generate a ~1M transaction, # and 16 of them is close to the 16MB block limit - num = 16 # old value 14 + num = 16 # old value 14 from .messages import CTxOut from .script import CScript, OP_RETURN, OP_NOP @@ -557,6 +601,7 @@ def mine_large_block(node, utxos=None): create_lots_of_big_transactions(node, [big_txout], utxos, num, fee=fee) node.generate(1) + def find_vout_for_address(node, txid, addr): """ Locate the vout index of the given transaction sending to the diff --git a/test/functional/test_framework/wallet_util.py b/test/functional/test_framework/wallet_util.py index 31f5bf1634..dbcbf11db7 100755 --- a/test/functional/test_framework/wallet_util.py +++ b/test/functional/test_framework/wallet_util.py @@ -49,6 +49,7 @@ 'p2sh_p2wsh_script', 'p2sh_p2wsh_addr']) + def get_key(node): """Generate a fresh key on node @@ -66,6 +67,7 @@ def get_key(node): p2sh_p2wpkh_redeem_script=CScript([OP_0, pkh]).hex(), p2sh_p2wpkh_addr=key_to_p2sh_p2wpkh(pubkey)) + def get_multisig(node): """Generate a fresh 2-of-3 multisig on node @@ -88,6 +90,7 @@ def get_multisig(node): p2sh_p2wsh_script=CScript([OP_HASH160, witness_script, OP_EQUAL]).hex(), p2sh_p2wsh_addr=script_to_p2sh_p2wsh(script_code)) + def test_address(node, address, **kwargs): """Get address info for `address` and test whether the returned values are as expected.""" addr_info = node.getaddressinfo(address) diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index f7cc843775..d63e0579da 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -42,6 +42,7 @@ if os.name != 'nt' or sys.getwindowsversion() >= (10, 0, 14393): if os.name == 'nt': import ctypes + kernel32 = ctypes.windll.kernel32 ENABLE_VIRTUAL_TERMINAL_PROCESSING = 4 STD_OUTPUT_HANDLE = -11 @@ -72,10 +73,10 @@ 'example_block_hash.py', 'feature_pruning.py', 'feature_dbcrash.py', - 'feature_block.py', # moved to ext due to heavy load for trevis - 'wallet_hd.py', # moved to ext due to heavy load for trevis - 'mempool_accept.py',# moved to ext due to heavy load for trevis - 'wallet_backup.py', # moved to ext due to heavy load for trevis + 'feature_block.py', # moved to ext due to heavy load for trevis + 'wallet_hd.py', # moved to ext due to heavy load for trevis + 'mempool_accept.py', # moved to ext due to heavy load for trevis + 'wallet_backup.py', # moved to ext due to heavy load for trevis 'feature_on_chain_government_govvar_update.py', ] @@ -239,7 +240,7 @@ 'rpc_signmessage.py', 'wallet_balance.py', 'feature_nulldummy.py', - 'wallet_import_rescan.py', # nodes = 6 + 'wallet_import_rescan.py', # nodes = 6 'wallet_import_with_label.py', 'rpc_bind.py --ipv4', 'rpc_bind.py --ipv6', @@ -282,7 +283,7 @@ 'rpc_listvaulthistory.py', 'feature_logging.py', 'feature_loan_scheme.py', - #'feature_forced_reward_address.py', + # 'feature_forced_reward_address.py', 'feature_loan_vault.py', 'feature_loan_deposittovault.py', 'feature_loan_interest.py', @@ -335,6 +336,7 @@ "test_runner.py", ] + def main(): # Parse arguments and pass through unrecognised args parser = argparse.ArgumentParser(add_help=False, @@ -343,15 +345,22 @@ def main(): epilog=''' Help text and arguments for individual test script:''', formatter_class=argparse.RawTextHelpFormatter) - parser.add_argument('--ansi', action='store_true', default=sys.stdout.isatty(), help="Use ANSI colors and dots in output (enabled by default when standard output is a TTY)") - parser.add_argument('--combinedlogslen', '-c', type=int, default=0, metavar='n', help='On failure, print a log (of length n lines) to the console, combined from the test framework and all test nodes.') - parser.add_argument('--coverage', action='store_true', help='generate a basic coverage report for the RPC interface') - parser.add_argument('--ci', action='store_true', help='Run checks and code that are usually only enabled in a continuous integration environment') + parser.add_argument('--ansi', action='store_true', default=sys.stdout.isatty(), + help="Use ANSI colors and dots in output (enabled by default when standard output is a TTY)") + parser.add_argument('--combinedlogslen', '-c', type=int, default=0, metavar='n', + help='On failure, print a log (of length n lines) to the console, combined from the test framework and all test nodes.') + parser.add_argument('--coverage', action='store_true', + help='generate a basic coverage report for the RPC interface') + parser.add_argument('--ci', action='store_true', + help='Run checks and code that are usually only enabled in a continuous integration environment') parser.add_argument('--exclude', '-x', help='specify a comma-separated-list of scripts to exclude.') - parser.add_argument('--extended', action='store_true', help='run the extended test suite in addition to the basic tests') + parser.add_argument('--extended', action='store_true', + help='run the extended test suite in addition to the basic tests') parser.add_argument('--help', '-h', '-?', action='store_true', help='print help text and exit') - parser.add_argument('--jobs', '-j', type=int, default=4, help='how many test scripts to run in parallel. Default=4.') - parser.add_argument('--keepcache', '-k', action='store_true', help='the default behavior is to flush the cache directory on startup. --keepcache retains the cache from the previous testrun.') + parser.add_argument('--jobs', '-j', type=int, default=4, + help='how many test scripts to run in parallel. Default=4.') + parser.add_argument('--keepcache', '-k', action='store_true', + help='the default behavior is to flush the cache directory on startup. --keepcache retains the cache from the previous testrun.') parser.add_argument('--quiet', '-q', action='store_true', help='only print dots, results summary and failure logs') parser.add_argument('--tmpdirprefix', '-t', default=tempfile.gettempdir(), help="Root directory for datadirs") parser.add_argument('--failfast', action='store_true', help='stop execution after the first test failure') @@ -445,7 +454,8 @@ def main(): if args.help: # Print help for test_runner.py, then print help of the first script (with args removed) and exit. parser.print_help() - subprocess.check_call([sys.executable, os.path.join(config["environment"]["SRCDIR"], 'test', 'functional', test_list[0].split()[0]), '-h']) + subprocess.check_call([sys.executable, os.path.join(config["environment"]["SRCDIR"], 'test', 'functional', + test_list[0].split()[0]), '-h']) sys.exit(0) check_script_list(src_dir=config["environment"]["SRCDIR"], fail_on_warn=args.ci) @@ -468,20 +478,26 @@ def main(): use_term_control=args.ansi, ) -def run_tests(*, test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage=False, args=None, combined_logs_len=0, failfast=False, runs_ci, use_term_control): + +def run_tests(*, test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage=False, args=None, combined_logs_len=0, + failfast=False, runs_ci, use_term_control): args = args or [] # Warn if defid is already running (unix only) try: if subprocess.check_output(["pidof", "defid"]) is not None: - print("%sWARNING!%s There is already a defid process running on this system. Tests may fail unexpectedly due to resource contention!" % (BOLD[1], BOLD[0])) + print( + "%sWARNING!%s There is already a defid process running on this system. Tests may fail unexpectedly due to resource contention!" % ( + BOLD[1], BOLD[0])) except (OSError, subprocess.SubprocessError): pass # Warn if there is a cache directory cache_dir = "%s/test/cache" % build_dir if os.path.isdir(cache_dir): - print("%sWARNING!%s There is a cache directory here: %s. If tests fail unexpectedly, try deleting the cache directory." % (BOLD[1], BOLD[0], cache_dir)) + print( + "%sWARNING!%s There is a cache directory here: %s. If tests fail unexpectedly, try deleting the cache directory." % ( + BOLD[1], BOLD[0], cache_dir)) tests_dir = src_dir + '/test/functional/' @@ -497,12 +513,13 @@ def run_tests(*, test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage= if len(test_list) > 1 and jobs > 1: # Populate cache try: - subprocess.check_output([sys.executable, tests_dir + 'create_cache.py'] + flags + ["--tmpdir=%s/cache" % tmpdir]) + subprocess.check_output( + [sys.executable, tests_dir + 'create_cache.py'] + flags + ["--tmpdir=%s/cache" % tmpdir]) except subprocess.CalledProcessError as e: sys.stdout.buffer.write(e.output) raise - #Run Tests + # Run Tests job_queue = TestHandler( num_tests_parallel=jobs, tests_dir=tests_dir, @@ -531,14 +548,16 @@ def run_tests(*, test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage= print(BOLD[1] + 'stderr:\n' + BOLD[0] + stderr + '\n') if combined_logs_len and os.path.isdir(testdir): # Print the final `combinedlogslen` lines of the combined logs - print('{}Combine the logs and print the last {} lines ...{}'.format(BOLD[1], combined_logs_len, BOLD[0])) + print( + '{}Combine the logs and print the last {} lines ...{}'.format(BOLD[1], combined_logs_len, BOLD[0])) print('\n============') print('{}Combined log for {}:{}'.format(BOLD[1], testdir, BOLD[0])) print('============\n') combined_logs_args = [sys.executable, os.path.join(tests_dir, 'combine_logs.py'), testdir] if BOLD[0]: combined_logs_args += ['--color'] - combined_logs, _ = subprocess.Popen(combined_logs_args, universal_newlines=True, stdout=subprocess.PIPE).communicate() + combined_logs, _ = subprocess.Popen(combined_logs_args, universal_newlines=True, + stdout=subprocess.PIPE).communicate() print("\n".join(deque(combined_logs.splitlines(), combined_logs_len))) if failfast: @@ -567,6 +586,7 @@ def run_tests(*, test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage= sys.exit(not all_passed) + def print_results(test_results, max_len_name, runtime): results = "\n" + BOLD[1] + "%s | %s | %s\n\n" % ("TEST".ljust(max_len_name), "STATUS ", "DURATION") + BOLD[0] @@ -583,12 +603,14 @@ def print_results(test_results, max_len_name, runtime): status = TICK + "Passed" if all_passed else CROSS + "Failed" if not all_passed: results += RED[1] - results += BOLD[1] + "\n%s | %s | %s s (accumulated) \n" % ("ALL".ljust(max_len_name), status.ljust(9), time_sum) + BOLD[0] + results += BOLD[1] + "\n%s | %s | %s s (accumulated) \n" % ("ALL".ljust(max_len_name), status.ljust(9), time_sum) + \ + BOLD[0] if not all_passed: results += RED[0] results += "Runtime: %s s\n" % (runtime) print(results) + class TestHandler: """ Trigger the test scripts passed in via the list. @@ -613,14 +635,15 @@ def get_next(self): test = self.test_list.pop(0) portseed = len(self.test_list) portseed_arg = ["--portseed={}".format(portseed)] - log_stdout = tempfile.SpooledTemporaryFile(max_size=2**16) - log_stderr = tempfile.SpooledTemporaryFile(max_size=2**16) + log_stdout = tempfile.SpooledTemporaryFile(max_size=2 ** 16) + log_stderr = tempfile.SpooledTemporaryFile(max_size=2 ** 16) test_argv = test.split() testdir = "{}/{}_{}".format(self.tmpdir, re.sub(".py$", "", test_argv[0]), portseed) tmpdir_arg = ["--tmpdir={}".format(testdir)] self.jobs.append((test, time.time(), - subprocess.Popen([sys.executable, self.tests_dir + test_argv[0]] + test_argv[1:] + self.flags + portseed_arg + tmpdir_arg, + subprocess.Popen([sys.executable, self.tests_dir + test_argv[0]] + test_argv[ + 1:] + self.flags + portseed_arg + tmpdir_arg, universal_newlines=True, stdout=log_stdout, stderr=log_stderr), @@ -702,7 +725,8 @@ def __repr__(self): color = GREY glyph = CIRCLE - return color[1] + "%s | %s%s | %s s\n" % (self.name.ljust(self.padding), glyph, self.status.ljust(7), self.time) + color[0] + return color[1] + "%s | %s%s | %s s\n" % ( + self.name.ljust(self.padding), glyph, self.status.ljust(7), self.time) + color[0] @property def was_successful(self): @@ -730,7 +754,8 @@ def check_script_list(*, src_dir, fail_on_warn): python_files = set([test_file for test_file in os.listdir(script_dir) if test_file.endswith(".py")]) missed_tests = list(python_files - set(map(lambda x: x.split()[0], ALL_SCRIPTS + NON_SCRIPTS))) if len(missed_tests) != 0: - print("%sWARNING!%s The following scripts are not being run: %s. Check the test lists in test_runner.py." % (BOLD[1], BOLD[0], str(missed_tests))) + print("%sWARNING!%s The following scripts are not being run: %s. Check the test lists in test_runner.py." % ( + BOLD[1], BOLD[0], str(missed_tests))) if fail_on_warn: # On CI this warning is an error to prevent merging incomplete commits into master sys.exit(1) @@ -751,6 +776,7 @@ class RPCCoverage(): See also: test/functional/test_framework/coverage.py """ + def __init__(self): self.dir = tempfile.mkdtemp(prefix="coverage") self.flag = '--coveragedir=%s' % self.dir diff --git a/test/functional/tool_wallet.py b/test/functional/tool_wallet.py index 40135caffc..ee4afa247a 100755 --- a/test/functional/tool_wallet.py +++ b/test/functional/tool_wallet.py @@ -15,6 +15,7 @@ BUFFER_SIZE = 16 * 1024 + class ToolWalletTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 @@ -26,7 +27,8 @@ def skip_test_if_missing_module(self): def defi_wallet_process(self, *args): binary = self.config["environment"]["BUILDDIR"] + '/src/defi-wallet' + self.config["environment"]["EXEEXT"] args = ['-datadir={}'.format(self.nodes[0].datadir), '-regtest'] + list(args) - return subprocess.Popen([binary] + args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) + return subprocess.Popen([binary] + args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, + universal_newlines=True) def assert_raises_tool_error(self, error, *args): p = self.defi_wallet_process(*args) @@ -46,7 +48,7 @@ def wallet_shasum(self): h = hashlib.sha1() mv = memoryview(bytearray(BUFFER_SIZE)) with open(self.wallet_path, 'rb', buffering=0) as f: - for n in iter(lambda : f.readinto(mv), 0): + for n in iter(lambda: f.readinto(mv), 0): h.update(mv[:n]) return h.hexdigest() @@ -65,9 +67,11 @@ def test_invalid_tool_commands_and_args(self): self.assert_raises_tool_error('Invalid command: foo', 'foo') # `defi-wallet help` raises an error. Use `defi-wallet -help`. self.assert_raises_tool_error('Invalid command: help', 'help') - self.assert_raises_tool_error('Error: two methods provided (info and create). Only one method should be provided.', 'info', 'create') + self.assert_raises_tool_error( + 'Error: two methods provided (info and create). Only one method should be provided.', 'info', 'create') self.assert_raises_tool_error('Error parsing command line arguments: Invalid parameter -foo', '-foo') - self.assert_raises_tool_error('Error loading wallet.dat. Is wallet being used by other process?', '-wallet=wallet.dat', 'info') + self.assert_raises_tool_error('Error loading wallet.dat. Is wallet being used by other process?', + '-wallet=wallet.dat', 'info') self.assert_raises_tool_error('Error: no wallet file at nonexistent.dat', '-wallet=nonexistent.dat', 'info') def test_tool_wallet_info(self): @@ -101,7 +105,7 @@ def test_tool_wallet_info(self): self.log_wallet_timestamp_comparison(timestamp_before, timestamp_after) self.log.debug('Setting wallet file permissions back to 600 (read/write)') os.chmod(self.wallet_path, stat.S_IRUSR | stat.S_IWUSR) - assert(self.wallet_permissions() in ['600', '666']) # Sanity check. 666 because Appveyor. + assert (self.wallet_permissions() in ['600', '666']) # Sanity check. 666 because Appveyor. # # TODO: Wallet tool info should not write to the wallet file. # The following lines should be uncommented and the tests still succeed: @@ -116,7 +120,8 @@ def test_tool_wallet_info_after_transaction(self): Mutate the wallet with a transaction to verify that the info command output changes accordingly. """ - self.start_node(0, ['-regtest', '-txnotokens=0']) # looks like we ought to enforce back "normal" serialization here + self.start_node(0, ['-regtest', + '-txnotokens=0']) # looks like we ought to enforce back "normal" serialization here self.log.info('Generating transaction to mutate wallet') self.nodes[0].generate(1) self.stop_node(0) @@ -172,7 +177,8 @@ def test_tool_wallet_create_on_existing_wallet(self): def test_getwalletinfo_on_different_wallet(self): self.log.info('Starting node with arg -wallet=foo') - self.start_node(0, ['-wallet=foo', '-regtest', '-txnotokens=0']) # looks like we ought to enforce back "normal" serialization here + self.start_node(0, ['-wallet=foo', '-regtest', + '-txnotokens=0']) # looks like we ought to enforce back "normal" serialization here self.log.info('Calling getwalletinfo on a different wallet ("foo"), testing output') shasum_before = self.wallet_shasum() diff --git a/test/functional/wallet_abandonconflict.py b/test/functional/wallet_abandonconflict.py index ed2232f4c7..9d10fa0138 100755 --- a/test/functional/wallet_abandonconflict.py +++ b/test/functional/wallet_abandonconflict.py @@ -40,22 +40,27 @@ def run_test(self): self.nodes[1].generate(1) # Can not abandon non-wallet transaction - assert_raises_rpc_error(-5, 'Invalid or non-wallet transaction id', lambda: self.nodes[0].abandontransaction(txid='ff' * 32)) + assert_raises_rpc_error(-5, 'Invalid or non-wallet transaction id', + lambda: self.nodes[0].abandontransaction(txid='ff' * 32)) # Can not abandon confirmed transaction - assert_raises_rpc_error(-5, 'Transaction not eligible for abandonment', lambda: self.nodes[0].abandontransaction(txid=txA)) + assert_raises_rpc_error(-5, 'Transaction not eligible for abandonment', + lambda: self.nodes[0].abandontransaction(txid=txA)) self.sync_blocks() newbalance = self.nodes[0].getbalance() - assert balance - newbalance < Decimal("0.001") #no more than fees lost + assert balance - newbalance < Decimal("0.001") # no more than fees lost balance = newbalance # Disconnect nodes so node0's transactions don't get into node1's mempool disconnect_nodes(self.nodes[0], 1) # Identify the 10btc outputs - nA = next(tx_out["vout"] for tx_out in self.nodes[0].gettransaction(txA)["details"] if tx_out["amount"] == Decimal("10")) - nB = next(tx_out["vout"] for tx_out in self.nodes[0].gettransaction(txB)["details"] if tx_out["amount"] == Decimal("10")) - nC = next(tx_out["vout"] for tx_out in self.nodes[0].gettransaction(txC)["details"] if tx_out["amount"] == Decimal("10")) + nA = next(tx_out["vout"] for tx_out in self.nodes[0].gettransaction(txA)["details"] if + tx_out["amount"] == Decimal("10")) + nB = next(tx_out["vout"] for tx_out in self.nodes[0].gettransaction(txB)["details"] if + tx_out["amount"] == Decimal("10")) + nC = next(tx_out["vout"] for tx_out in self.nodes[0].gettransaction(txC)["details"] if + tx_out["amount"] == Decimal("10")) inputs = [] # spend 10btc outputs from txA and txB @@ -69,9 +74,10 @@ def run_test(self): txAB1 = self.nodes[0].sendrawtransaction(signed["hex"]) # Identify the 14.99998btc output - nAB = next(tx_out["vout"] for tx_out in self.nodes[0].gettransaction(txAB1)["details"] if tx_out["amount"] == Decimal("14.99998")) + nAB = next(tx_out["vout"] for tx_out in self.nodes[0].gettransaction(txAB1)["details"] if + tx_out["amount"] == Decimal("14.99998")) - #Create a child tx spending AB1 and C + # Create a child tx spending AB1 and C inputs = [] inputs.append({"txid": txAB1, "vout": nAB}) inputs.append({"txid": txC, "vout": nC}) @@ -173,8 +179,9 @@ def run_test(self): # Don't think C's should either self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash()) newbalance = self.nodes[0].getbalance() - #assert_equal(newbalance, balance - Decimal("10")) - self.log.info("If balance has not declined after invalidateblock then out of mempool wallet tx which is no longer") + # assert_equal(newbalance, balance - Decimal("10")) + self.log.info( + "If balance has not declined after invalidateblock then out of mempool wallet tx which is no longer") self.log.info("conflicted has not resumed causing its inputs to be seen as spent. See Issue #7315") self.log.info(str(balance) + " -> " + str(newbalance) + " ?") diff --git a/test/functional/wallet_address_types.py b/test/functional/wallet_address_types.py index d1c6dc5b44..d4fc6e5c54 100755 --- a/test/functional/wallet_address_types.py +++ b/test/functional/wallet_address_types.py @@ -160,7 +160,7 @@ def test_desc(self, node, address, multisig, typ, utxo): # Use a ridiculously roundabout way to find the key origin info through # the PSBT logic. However, this does test consistency between the PSBT reported # fingerprints/paths and the descriptor logic. - psbt = self.nodes[node].createpsbt([{'txid':utxo['txid'], 'vout':utxo['vout']}],[{address:0.00010000}]) + psbt = self.nodes[node].createpsbt([{'txid': utxo['txid'], 'vout': utxo['vout']}], [{address: 0.00010000}]) psbt = self.nodes[node].walletprocesspsbt(psbt, False, "ALL", True) decode = self.nodes[node].decodepsbt(psbt['psbt']) key_descs = {} @@ -191,13 +191,16 @@ def test_desc(self, node, address, multisig, typ, utxo): assert_equal(info['desc'], descsum_create("wpkh(%s)" % key_descs[info['pubkey']])) elif typ == 'legacy': # P2SH-multisig - assert_equal(info['desc'], descsum_create("sh(multi(2,%s,%s))" % (key_descs[info['pubkeys'][0]], key_descs[info['pubkeys'][1]]))) + assert_equal(info['desc'], descsum_create( + "sh(multi(2,%s,%s))" % (key_descs[info['pubkeys'][0]], key_descs[info['pubkeys'][1]]))) elif typ == 'p2sh-segwit': # P2SH-P2WSH-multisig - assert_equal(info['desc'], descsum_create("sh(wsh(multi(2,%s,%s)))" % (key_descs[info['embedded']['pubkeys'][0]], key_descs[info['embedded']['pubkeys'][1]]))) + assert_equal(info['desc'], descsum_create("sh(wsh(multi(2,%s,%s)))" % ( + key_descs[info['embedded']['pubkeys'][0]], key_descs[info['embedded']['pubkeys'][1]]))) elif typ == 'bech32': # P2WSH-multisig - assert_equal(info['desc'], descsum_create("wsh(multi(2,%s,%s))" % (key_descs[info['pubkeys'][0]], key_descs[info['pubkeys'][1]]))) + assert_equal(info['desc'], descsum_create( + "wsh(multi(2,%s,%s))" % (key_descs[info['pubkeys'][0]], key_descs[info['pubkeys'][1]]))) else: # Unknown type assert False @@ -231,14 +234,21 @@ def run_test(self): # addmultisigaddress with at least 1 uncompressed key should return a legacy address. for node in range(4): - self.test_address(node, self.nodes[node].addmultisigaddress(2, [uncompressed_1, uncompressed_2])['address'], True, 'legacy') - self.test_address(node, self.nodes[node].addmultisigaddress(2, [compressed_1, uncompressed_2])['address'], True, 'legacy') - self.test_address(node, self.nodes[node].addmultisigaddress(2, [uncompressed_1, compressed_2])['address'], True, 'legacy') + self.test_address(node, self.nodes[node].addmultisigaddress(2, [uncompressed_1, uncompressed_2])['address'], + True, 'legacy') + self.test_address(node, self.nodes[node].addmultisigaddress(2, [compressed_1, uncompressed_2])['address'], + True, 'legacy') + self.test_address(node, self.nodes[node].addmultisigaddress(2, [uncompressed_1, compressed_2])['address'], + True, 'legacy') # addmultisigaddress with all compressed keys should return the appropriate address type (even when the keys are not ours). - self.test_address(0, self.nodes[0].addmultisigaddress(2, [compressed_1, compressed_2])['address'], True, 'legacy') - self.test_address(1, self.nodes[1].addmultisigaddress(2, [compressed_1, compressed_2])['address'], True, 'p2sh-segwit') - self.test_address(2, self.nodes[2].addmultisigaddress(2, [compressed_1, compressed_2])['address'], True, 'p2sh-segwit') - self.test_address(3, self.nodes[3].addmultisigaddress(2, [compressed_1, compressed_2])['address'], True, 'bech32') + self.test_address(0, self.nodes[0].addmultisigaddress(2, [compressed_1, compressed_2])['address'], True, + 'legacy') + self.test_address(1, self.nodes[1].addmultisigaddress(2, [compressed_1, compressed_2])['address'], True, + 'p2sh-segwit') + self.test_address(2, self.nodes[2].addmultisigaddress(2, [compressed_1, compressed_2])['address'], True, + 'p2sh-segwit') + self.test_address(3, self.nodes[3].addmultisigaddress(2, [compressed_1, compressed_2])['address'], True, + 'bech32') for explicit_type, multisig, from_node in itertools.product([False, True], [False, True], range(4)): address_type = None @@ -249,7 +259,10 @@ def run_test(self): address_type = 'p2sh-segwit' else: address_type = 'legacy' - self.log.info("Sending from node {} ({}) with{} multisig using {}".format(from_node, self.extra_args[from_node], "" if multisig else "out", "default" if address_type is None else address_type)) + self.log.info( + "Sending from node {} ({}) with{} multisig using {}".format(from_node, self.extra_args[from_node], + "" if multisig else "out", + "default" if address_type is None else address_type)) old_balances = self.get_balances() self.log.debug("Old balances are {}".format(old_balances)) to_send = (old_balances[from_node] / 101).quantize(Decimal("0.00000001")) @@ -336,7 +349,8 @@ def run_test(self): self.log.info("Nodes with addresstype=legacy never use a P2WPKH change output") self.test_change_output_type(0, [to_address_bech32_1], 'legacy') - self.log.info("Nodes with addresstype=p2sh-segwit only use a P2WPKH change output if any destination address is bech32:") + self.log.info( + "Nodes with addresstype=p2sh-segwit only use a P2WPKH change output if any destination address is bech32:") self.test_change_output_type(1, [to_address_p2sh], 'p2sh-segwit') self.test_change_output_type(1, [to_address_bech32_1], 'bech32') self.test_change_output_type(1, [to_address_p2sh, to_address_bech32_1], 'bech32') @@ -346,7 +360,8 @@ def run_test(self): self.test_change_output_type(2, [to_address_bech32_1], 'bech32') self.test_change_output_type(2, [to_address_p2sh], 'bech32') - self.log.info("Nodes with addresstype=bech32 always use a P2WPKH change output (unless changetype is set otherwise):") + self.log.info( + "Nodes with addresstype=bech32 always use a P2WPKH change output (unless changetype is set otherwise):") self.test_change_output_type(3, [to_address_bech32_1], 'bech32') self.test_change_output_type(3, [to_address_p2sh], 'bech32') @@ -354,7 +369,8 @@ def run_test(self): self.test_address(3, self.nodes[3].getrawchangeaddress(), multisig=False, typ='bech32') self.log.info('test invalid address type arguments') - assert_raises_rpc_error(-5, "Unknown address type ''", self.nodes[3].addmultisigaddress, 2, [compressed_1, compressed_2], None, '') + assert_raises_rpc_error(-5, "Unknown address type ''", self.nodes[3].addmultisigaddress, 2, + [compressed_1, compressed_2], None, '') assert_raises_rpc_error(-5, "Unknown address type ''", self.nodes[3].getnewaddress, None, '') assert_raises_rpc_error(-5, "Unknown address type ''", self.nodes[3].getrawchangeaddress, '') assert_raises_rpc_error(-5, "Unknown address type 'bech23'", self.nodes[3].getrawchangeaddress, 'bech23') @@ -366,5 +382,6 @@ def run_test(self): self.test_address(4, self.nodes[4].getrawchangeaddress(), multisig=False, typ='p2sh-segwit') self.test_address(4, self.nodes[4].getrawchangeaddress('bech32'), multisig=False, typ='bech32') + if __name__ == '__main__': AddressTypeTest().main() diff --git a/test/functional/wallet_avoidreuse.py b/test/functional/wallet_avoidreuse.py index 5961e2b558..b00d7c6391 100755 --- a/test/functional/wallet_avoidreuse.py +++ b/test/functional/wallet_avoidreuse.py @@ -11,6 +11,7 @@ connect_nodes_bi, ) + # TODO: Copied from wallet_groups.py -- should perhaps move into util.py def assert_approx(v, vexp, vspan=0.00001): if v < vexp - vspan: @@ -18,12 +19,14 @@ def assert_approx(v, vexp, vspan=0.00001): if v > vexp + vspan: raise AssertionError("%s > [%s..%s]" % (str(v), str(vexp - vspan), str(vexp + vspan))) + def reset_balance(node, discardaddr): '''Throw away all owned coins by the node so it gets a balance of 0.''' balance = node.getbalance(avoid_reuse=False) if balance > 0.5: node.sendtoaddress(address=discardaddr, amount=balance, subtractfeefromamount=True, avoid_reuse=False) + def count_unspent(node): '''Count the unspent outputs for the given node and return various statistics''' r = { @@ -49,6 +52,7 @@ def count_unspent(node): r["reused"]["supported"] = supports_reused return r + def assert_unspent(node, total_count=None, total_sum=None, reused_supported=None, reused_count=None, reused_sum=None): '''Make assertions about a node's unspent output statistics''' stats = count_unspent(node) @@ -63,12 +67,14 @@ def assert_unspent(node, total_count=None, total_sum=None, reused_supported=None if reused_sum is not None: assert_approx(stats["reused"]["sum"], reused_sum, 0.001) + def assert_balances(node, mine): '''Make assertions about a node's getbalances output''' got = node.getbalances()["mine"] - for k,v in mine.items(): + for k, v in mine.items(): assert_approx(got[k], v, 0.001) + class AvoidReuseTest(DefiTestFramework): def set_test_params(self): @@ -112,8 +118,10 @@ def test_persistence(self): assert_equal(self.nodes[1].getwalletinfo()["avoid_reuse"], True) # Attempting to set flag to its current state should throw - assert_raises_rpc_error(-8, "Wallet flag is already set to false", self.nodes[0].setwalletflag, 'avoid_reuse', False) - assert_raises_rpc_error(-8, "Wallet flag is already set to true", self.nodes[1].setwalletflag, 'avoid_reuse', True) + assert_raises_rpc_error(-8, "Wallet flag is already set to false", self.nodes[0].setwalletflag, 'avoid_reuse', + False) + assert_raises_rpc_error(-8, "Wallet flag is already set to true", self.nodes[1].setwalletflag, 'avoid_reuse', + True) def test_immutable(self): '''Test immutable wallet flags''' @@ -151,7 +159,7 @@ def test_fund_send_fund_senddirty(self): # getbalances should show no used, 10 btc trusted assert_balances(self.nodes[1], mine={"used": 0, "trusted": 10}) # node 0 should not show a used entry, as it does not enable avoid_reuse - assert("used" not in self.nodes[0].getbalances()["mine"]) + assert ("used" not in self.nodes[0].getbalances()["mine"]) self.nodes[1].sendtoaddress(retaddr, 5) self.nodes[0].generate(1) @@ -239,5 +247,6 @@ def test_fund_send_fund_send(self): assert_approx(self.nodes[1].getbalance(), 1, 0.001) assert_approx(self.nodes[1].getbalance(avoid_reuse=False), 11, 0.001) + if __name__ == '__main__': AvoidReuseTest().main() diff --git a/test/functional/wallet_backup.py b/test/functional/wallet_backup.py index fe1671f8ae..900ecdc7b7 100755 --- a/test/functional/wallet_backup.py +++ b/test/functional/wallet_backup.py @@ -63,8 +63,8 @@ def setup_network(self): connect_nodes(self.nodes[2], 0) def one_send(self, from_node, to_address): - if (randint(1,2) == 1): - amount = Decimal(randint(1,10)) / Decimal(10) + if (randint(1, 2) == 1): + amount = Decimal(randint(1, 10)) / Decimal(10) self.nodes[from_node].sendtoaddress(to_address, amount) def do_one_round(self): @@ -81,10 +81,10 @@ def do_one_round(self): # Have the miner (node3) mine a block. # Must sync mempools before mining. - print ("bef mempool", TestNode.Mocktime) + print("bef mempool", TestNode.Mocktime) set_node_times(self.nodes, 0) self.sync_mempools() - print (TestNode.Mocktime) + print(TestNode.Mocktime) self.nodes[3].generate(1) self.sync_blocks() @@ -170,9 +170,12 @@ def run_test(self): shutil.rmtree(os.path.join(self.nodes[2].datadir, 'regtest', 'anchors')) # Restore wallets from backup - shutil.copyfile(os.path.join(self.nodes[0].datadir, 'wallet.bak'), os.path.join(self.nodes[0].datadir, 'regtest', 'wallets', 'wallet.dat')) - shutil.copyfile(os.path.join(self.nodes[1].datadir, 'wallet.bak'), os.path.join(self.nodes[1].datadir, 'regtest', 'wallets', 'wallet.dat')) - shutil.copyfile(os.path.join(self.nodes[2].datadir, 'wallet.bak'), os.path.join(self.nodes[2].datadir, 'regtest', 'wallets', 'wallet.dat')) + shutil.copyfile(os.path.join(self.nodes[0].datadir, 'wallet.bak'), + os.path.join(self.nodes[0].datadir, 'regtest', 'wallets', 'wallet.dat')) + shutil.copyfile(os.path.join(self.nodes[1].datadir, 'wallet.bak'), + os.path.join(self.nodes[1].datadir, 'regtest', 'wallets', 'wallet.dat')) + shutil.copyfile(os.path.join(self.nodes[2].datadir, 'wallet.bak'), + os.path.join(self.nodes[2].datadir, 'regtest', 'wallets', 'wallet.dat')) self.log.info("Re-starting nodes") self.start_three() @@ -186,7 +189,7 @@ def run_test(self): self.stop_three() self.erase_three() - #start node2 with no chain + # start node2 with no chain shutil.rmtree(os.path.join(self.nodes[2].datadir, 'regtest', 'blocks')) shutil.rmtree(os.path.join(self.nodes[2].datadir, 'regtest', 'chainstate')) shutil.rmtree(os.path.join(self.nodes[2].datadir, 'regtest', 'enhancedcs')) diff --git a/test/functional/wallet_balance.py b/test/functional/wallet_balance.py index c1f3fb826b..53e843a5b0 100755 --- a/test/functional/wallet_balance.py +++ b/test/functional/wallet_balance.py @@ -46,12 +46,14 @@ def create_transactions(node, address, amt, fees): return txs + class WalletTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 self.setup_clean_chain = True self.extra_args = [ - ['-limitdescendantcount=3'], # Limit mempool descendants as a hack to have wallet txs rejected from the mempool + ['-limitdescendantcount=3'], + # Limit mempool descendants as a hack to have wallet txs rejected from the mempool [], ] @@ -105,7 +107,8 @@ def run_test(self): self.sync_mempools() # First argument of getbalance must be set to "*" - assert_raises_rpc_error(-32, "dummy first argument must be excluded or set to \"*\"", self.nodes[1].getbalance, "") + assert_raises_rpc_error(-32, "dummy first argument must be excluded or set to \"*\"", self.nodes[1].getbalance, + "") self.log.info("Test getbalance and getunconfirmedbalance with unconfirmed inputs") @@ -125,7 +128,8 @@ def test_balances(*, fee_node_1=0): assert_equal(self.nodes[0].getbalances()['mine']['untrusted_pending'], Decimal('60')) assert_equal(self.nodes[0].getwalletinfo()["unconfirmed_balance"], Decimal('60')) - assert_equal(self.nodes[1].getunconfirmedbalance(), Decimal('0')) # Doesn't include output of node 0's send since it was spent + assert_equal(self.nodes[1].getunconfirmedbalance(), + Decimal('0')) # Doesn't include output of node 0's send since it was spent assert_equal(self.nodes[1].getbalances()['mine']['untrusted_pending'], Decimal('0')) assert_equal(self.nodes[1].getwalletinfo()["unconfirmed_balance"], Decimal('0')) @@ -186,8 +190,8 @@ def test_balances(*, fee_node_1=0): tx_orig = self.nodes[0].gettransaction(txid)['hex'] # Increase fee by 1 coin tx_replace = tx_orig.replace( - struct.pack(" vexp + vspan: raise AssertionError("%s > [%s..%s]" % (str(v), str(vexp - vspan), str(vexp + vspan))) + class WalletGroupTest(DefiTestFramework): def set_test_params(self): self.setup_clean_chain = True @@ -69,14 +71,15 @@ def run_test(self): assert_approx(v[1], 1.3, 0.0001) # Empty out node2's wallet - self.nodes[2].sendtoaddress(address=self.nodes[0].getnewaddress(), amount=self.nodes[2].getbalance(), subtractfeefromamount=True) + self.nodes[2].sendtoaddress(address=self.nodes[0].getnewaddress(), amount=self.nodes[2].getbalance(), + subtractfeefromamount=True) self.sync_all() self.nodes[0].generate(1) # Fill node2's wallet with 10000 outputs corresponding to the same # scriptPubKey for i in range(5): - raw_tx = self.nodes[0].createrawtransaction([{"txid":"0"*64, "vout":0}], [{addr2[0]: 0.05}]) + raw_tx = self.nodes[0].createrawtransaction([{"txid": "0" * 64, "vout": 0}], [{addr2[0]: 0.05}]) tx = FromHex(CTransaction(), raw_tx) tx.vin = [] tx.vout = [tx.vout[0]] * 2000 @@ -92,5 +95,6 @@ def run_test(self): # is way too big. assert self.nodes[2].sendtoaddress(address=addr2[0], amount=5) + if __name__ == '__main__': - WalletGroupTest().main () + WalletGroupTest().main() diff --git a/test/functional/wallet_hd.py b/test/functional/wallet_hd.py index 3dd7b37245..e72e590a11 100755 --- a/test/functional/wallet_hd.py +++ b/test/functional/wallet_hd.py @@ -31,8 +31,8 @@ def run_test(self): # create an internal key change_addr = self.nodes[1].getrawchangeaddress() - change_addrV= self.nodes[1].getaddressinfo(change_addr) - assert_equal(change_addrV["hdkeypath"], "m/0'/1'/0'") #first internal child key + change_addrV = self.nodes[1].getaddressinfo(change_addr) + assert_equal(change_addrV["hdkeypath"], "m/0'/1'/0'") # first internal child key # Import a non-HD private key in the HD wallet non_hd_add = self.nodes[0].getnewaddress() @@ -40,7 +40,7 @@ def run_test(self): # This should be enough to keep the master key and the non-HD key self.nodes[1].backupwallet(os.path.join(self.nodes[1].datadir, "hd.bak")) - #self.nodes[1].dumpwallet(os.path.join(self.nodes[1].datadir, "hd.dump")) + # self.nodes[1].dumpwallet(os.path.join(self.nodes[1].datadir, "hd.dump")) # Derive some HD addresses and remember the last # Also send funds to each add @@ -50,7 +50,7 @@ def run_test(self): for i in range(NUM_HD_ADDS): hd_add = self.nodes[1].getnewaddress() hd_info = self.nodes[1].getaddressinfo(hd_add) - assert_equal(hd_info["hdkeypath"], "m/0'/0'/"+str(i)+"'") + assert_equal(hd_info["hdkeypath"], "m/0'/0'/" + str(i) + "'") assert_equal(hd_info["hdseedid"], masterkeyid) self.nodes[0].sendtoaddress(hd_add, 1) self.nodes[0].generate(1) @@ -59,8 +59,8 @@ def run_test(self): # create an internal key (again) change_addr = self.nodes[1].getrawchangeaddress() - change_addrV= self.nodes[1].getaddressinfo(change_addr) - assert_equal(change_addrV["hdkeypath"], "m/0'/1'/1'") #second internal child key + change_addrV = self.nodes[1].getaddressinfo(change_addr) + assert_equal(change_addrV["hdkeypath"], "m/0'/1'/1'") # second internal child key self.sync_blocks() assert_equal(self.nodes[1].getbalance(), NUM_HD_ADDS + 1) @@ -73,7 +73,8 @@ def run_test(self): shutil.rmtree(os.path.join(self.nodes[1].datadir, "regtest", "chainstate")) shutil.rmtree(os.path.join(self.nodes[1].datadir, 'regtest', 'enhancedcs')) shutil.rmtree(os.path.join(self.nodes[1].datadir, 'regtest', 'anchors')) - shutil.copyfile(os.path.join(self.nodes[1].datadir, "hd.bak"), os.path.join(self.nodes[1].datadir, "regtest", "wallets", "wallet.dat")) + shutil.copyfile(os.path.join(self.nodes[1].datadir, "hd.bak"), + os.path.join(self.nodes[1].datadir, "regtest", "wallets", "wallet.dat")) self.start_node(1) # Assert that derivation is deterministic @@ -81,7 +82,7 @@ def run_test(self): for i in range(NUM_HD_ADDS): hd_add_2 = self.nodes[1].getnewaddress() hd_info_2 = self.nodes[1].getaddressinfo(hd_add_2) - assert_equal(hd_info_2["hdkeypath"], "m/0'/0'/"+str(i)+"'") + assert_equal(hd_info_2["hdkeypath"], "m/0'/0'/" + str(i) + "'") assert_equal(hd_info_2["hdseedid"], masterkeyid) assert_equal(hd_add, hd_add_2) connect_nodes_bi(self.nodes, 0, 1) @@ -98,7 +99,8 @@ def run_test(self): shutil.rmtree(os.path.join(self.nodes[1].datadir, "regtest", "chainstate")) shutil.rmtree(os.path.join(self.nodes[1].datadir, 'regtest', 'enhancedcs')) shutil.rmtree(os.path.join(self.nodes[1].datadir, 'regtest', 'anchors')) - shutil.copyfile(os.path.join(self.nodes[1].datadir, "hd.bak"), os.path.join(self.nodes[1].datadir, "regtest", "wallets", "wallet.dat")) + shutil.copyfile(os.path.join(self.nodes[1].datadir, "hd.bak"), + os.path.join(self.nodes[1].datadir, "regtest", "wallets", "wallet.dat")) self.start_node(1, extra_args=self.extra_args[1]) connect_nodes_bi(self.nodes, 0, 1) self.sync_blocks() @@ -128,8 +130,9 @@ def run_test(self): new_masterkeyid = self.nodes[1].getwalletinfo()['hdseedid'] assert orig_masterkeyid != new_masterkeyid addr = self.nodes[1].getnewaddress() - assert_equal(self.nodes[1].getaddressinfo(addr)['hdkeypath'], 'm/0\'/0\'/0\'') # Make sure the new address is the first from the keypool - self.nodes[1].keypoolrefill(1) # Fill keypool with 1 key + assert_equal(self.nodes[1].getaddressinfo(addr)['hdkeypath'], + 'm/0\'/0\'/0\'') # Make sure the new address is the first from the keypool + self.nodes[1].keypoolrefill(1) # Fill keypool with 1 key # Set a new HD seed on node 1 without flushing the keypool new_seed = self.nodes[0].dumpprivkey(self.nodes[0].getnewaddress()) @@ -139,13 +142,15 @@ def run_test(self): assert orig_masterkeyid != new_masterkeyid addr = self.nodes[1].getnewaddress() assert_equal(orig_masterkeyid, self.nodes[1].getaddressinfo(addr)['hdseedid']) - assert_equal(self.nodes[1].getaddressinfo(addr)['hdkeypath'], 'm/0\'/0\'/1\'') # Make sure the new address continues previous keypool + assert_equal(self.nodes[1].getaddressinfo(addr)['hdkeypath'], + 'm/0\'/0\'/1\'') # Make sure the new address continues previous keypool # Check that the next address is from the new seed self.nodes[1].keypoolrefill(1) next_addr = self.nodes[1].getnewaddress() assert_equal(new_masterkeyid, self.nodes[1].getaddressinfo(next_addr)['hdseedid']) - assert_equal(self.nodes[1].getaddressinfo(next_addr)['hdkeypath'], 'm/0\'/0\'/0\'') # Make sure the new address is not from previous keypool + assert_equal(self.nodes[1].getaddressinfo(next_addr)['hdkeypath'], + 'm/0\'/0\'/0\'') # Make sure the new address is not from previous keypool assert next_addr != addr # Sethdseed parameter validity @@ -154,7 +159,9 @@ def run_test(self): assert_raises_rpc_error(-1, "JSON value is not a boolean as expected", self.nodes[1].sethdseed, "Not_bool") assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[1].sethdseed, False, True) assert_raises_rpc_error(-5, "Already have this key", self.nodes[1].sethdseed, False, new_seed) - assert_raises_rpc_error(-5, "Already have this key", self.nodes[1].sethdseed, False, self.nodes[1].dumpprivkey(self.nodes[1].getnewaddress())) + assert_raises_rpc_error(-5, "Already have this key", self.nodes[1].sethdseed, False, + self.nodes[1].dumpprivkey(self.nodes[1].getnewaddress())) + if __name__ == '__main__': - WalletHDTest().main () + WalletHDTest().main() diff --git a/test/functional/wallet_import_rescan.py b/test/functional/wallet_import_rescan.py index 03ba7e5dbf..6653110f39 100755 --- a/test/functional/wallet_import_rescan.py +++ b/test/functional/wallet_import_rescan.py @@ -88,7 +88,8 @@ def check(self, txid=None, amount=None, confirmation_height=None): current_height = self.node.getblockcount() assert_equal(len(txs), self.expected_txs) - addresses = self.node.listreceivedbyaddress(minconf=0, include_watchonly=True, address_filter=self.address['address']) + addresses = self.node.listreceivedbyaddress(minconf=0, include_watchonly=True, + address_filter=self.address['address']) if self.expected_txs: assert_equal(len(addresses[0]["txids"]), self.expected_txs) @@ -144,7 +145,7 @@ def get_rand_amount(): class ImportRescanTest(DefiTestFramework): def set_test_params(self): - self.num_nodes = 2 + len(IMPORT_NODES) # 6 + self.num_nodes = 2 + len(IMPORT_NODES) # 6 def skip_test_if_missing_module(self): self.skip_if_no_wallet() @@ -190,7 +191,7 @@ def run_test(self): self.nodes, self.nodes[0].getblockheader(self.nodes[0].getbestblockhash())["time"] + TIMESTAMP_WINDOW + 1, ) - self.nodes[0].reset_mocktime() # reset generate's inner Mocktime to mint with those from set_node_times() + self.nodes[0].reset_mocktime() # reset generate's inner Mocktime to mint with those from set_node_times() self.nodes[0].generate(1) self.sync_blocks() @@ -227,5 +228,6 @@ def run_test(self): variant.expected_txs += 1 variant.check(variant.sent_txid, variant.sent_amount, variant.confirmation_height) + if __name__ == "__main__": ImportRescanTest().main() diff --git a/test/functional/wallet_importmulti.py b/test/functional/wallet_importmulti.py index 8554b40b8c..af45a9f301 100755 --- a/test/functional/wallet_importmulti.py +++ b/test/functional/wallet_importmulti.py @@ -32,6 +32,7 @@ test_address, ) + class ImportMultiTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 @@ -51,7 +52,7 @@ def test_importmulti(self, req, success, error_code=None, error_message=None, wa result = self.nodes[1].importmulti([req]) observed_warnings = [] if 'warnings' in result[0]: - observed_warnings = result[0]['warnings'] + observed_warnings = result[0]['warnings'] assert_equal("\n".join(sorted(warnings)), "\n".join(sorted(observed_warnings))) assert_equal(result[0]['success'], success) if error_code is not None: @@ -149,7 +150,8 @@ def run_test(self): "pubkeys": [key.pubkey], "internal": False}, success=True, - warnings=["Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) + warnings=[ + "Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) test_address(self.nodes[1], key.p2pkh_addr, iswatchonly=True, @@ -164,7 +166,8 @@ def run_test(self): "pubkeys": [key.pubkey], "internal": True}, success=True, - warnings=["Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) + warnings=[ + "Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) test_address(self.nodes[1], key.p2pkh_addr, iswatchonly=True, @@ -215,7 +218,8 @@ def run_test(self): "keys": [key.privkey], "watchonly": True}, success=True, - warnings=["All private keys are provided, outputs will be considered spendable. If this is intentional, do not specify the watchonly flag."]) + warnings=[ + "All private keys are provided, outputs will be considered spendable. If this is intentional, do not specify the watchonly flag."]) test_address(self.nodes[1], key.p2pkh_addr, iswatchonly=False, @@ -283,7 +287,8 @@ def run_test(self): "timestamp": "now", "redeemscript": multisig.redeem_script}, success=True, - warnings=["Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) + warnings=[ + "Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) test_address(self.nodes[1], multisig.p2sh_addr, timestamp=timestamp, iswatchonly=True, ismine=False, solvable=True) @@ -304,7 +309,8 @@ def run_test(self): "redeemscript": multisig.redeem_script, "keys": multisig.privkeys[0:2]}, success=True, - warnings=["Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) + warnings=[ + "Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) test_address(self.nodes[1], multisig.p2sh_addr, timestamp=timestamp, @@ -345,7 +351,9 @@ def run_test(self): "timestamp": "now", "pubkeys": [wrong_key]}, success=True, - warnings=["Importing as non-solvable: some required keys are missing. If this is intentional, don't provide any keys, pubkeys, witnessscript, or redeemscript.", "Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) + warnings=[ + "Importing as non-solvable: some required keys are missing. If this is intentional, don't provide any keys, pubkeys, witnessscript, or redeemscript.", + "Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) test_address(self.nodes[1], key.p2pkh_addr, iswatchonly=True, @@ -362,7 +370,9 @@ def run_test(self): "pubkeys": [wrong_key], "internal": True}, success=True, - warnings=["Importing as non-solvable: some required keys are missing. If this is intentional, don't provide any keys, pubkeys, witnessscript, or redeemscript.", "Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) + warnings=[ + "Importing as non-solvable: some required keys are missing. If this is intentional, don't provide any keys, pubkeys, witnessscript, or redeemscript.", + "Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) test_address(self.nodes[1], key.p2pkh_addr, iswatchonly=True, @@ -377,8 +387,10 @@ def run_test(self): self.test_importmulti({"scriptPubKey": {"address": key.p2pkh_addr}, "timestamp": "now", "keys": [wrong_privkey]}, - success=True, - warnings=["Importing as non-solvable: some required keys are missing. If this is intentional, don't provide any keys, pubkeys, witnessscript, or redeemscript.", "Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) + success=True, + warnings=[ + "Importing as non-solvable: some required keys are missing. If this is intentional, don't provide any keys, pubkeys, witnessscript, or redeemscript.", + "Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) test_address(self.nodes[1], key.p2pkh_addr, iswatchonly=True, @@ -395,7 +407,9 @@ def run_test(self): "keys": [wrong_privkey], "internal": True}, success=True, - warnings=["Importing as non-solvable: some required keys are missing. If this is intentional, don't provide any keys, pubkeys, witnessscript, or redeemscript.", "Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) + warnings=[ + "Importing as non-solvable: some required keys are missing. If this is intentional, don't provide any keys, pubkeys, witnessscript, or redeemscript.", + "Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) test_address(self.nodes[1], key.p2pkh_addr, iswatchonly=True, @@ -431,9 +445,9 @@ def run_test(self): self.nodes[1].importmulti, [{"scriptPubKey": key.p2pkh_script}]) assert_raises_rpc_error(-3, 'Expected number or "now" timestamp value for key. got type string', self.nodes[1].importmulti, [{ - "scriptPubKey": key.p2pkh_script, - "timestamp": "" - }]) + "scriptPubKey": key.p2pkh_script, + "timestamp": "" + }]) # Import P2WPKH address as watch only self.log.info("Should import a P2WPKH address as watch only") @@ -453,7 +467,8 @@ def run_test(self): "timestamp": "now", "pubkeys": [key.pubkey]}, success=True, - warnings=["Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) + warnings=[ + "Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) test_address(self.nodes[1], key.p2wpkh_addr, ismine=False, @@ -512,7 +527,8 @@ def run_test(self): "redeemscript": key.p2sh_p2wpkh_redeem_script, "pubkeys": [key.pubkey]}, success=True, - warnings=["Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) + warnings=[ + "Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) test_address(self.nodes[1], key.p2sh_p2wpkh_addr, solvable=True, @@ -539,7 +555,8 @@ def run_test(self): "redeemscript": multisig.p2wsh_script, "witnessscript": multisig.redeem_script}, success=True, - warnings=["Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) + warnings=[ + "Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) test_address(self.nodes[1], multisig.p2sh_p2wsh_addr, solvable=True, @@ -572,8 +589,10 @@ def run_test(self): # Test ranged descriptor fails if range is not specified xpriv = "tprv8ZgxMBicQKsPeuVhWwi6wuMQGfPKi9Li5GtX35jVNknACgqe3CY4g5xgkfDDJcmtF7o1QnxWDRYw4H5P26PXq7sbcUkEqeR4fg3Kxp2tigg" - addresses = ["2N7yv4p8G8yEaPddJxY41kPihnWvs39qCMf", "2MsHxyb2JS3pAySeNUsJ7mNnurtpeenDzLA"] # hdkeypath=m/0'/0'/0' and 1' - addresses += ["bcrt1qrd3n235cj2czsfmsuvqqpr3lu6lg0ju7scl8gn", "bcrt1qfqeppuvj0ww98r6qghmdkj70tv8qpchehegrg8"] # wpkh subscripts corresponding to the above addresses + addresses = ["2N7yv4p8G8yEaPddJxY41kPihnWvs39qCMf", + "2MsHxyb2JS3pAySeNUsJ7mNnurtpeenDzLA"] # hdkeypath=m/0'/0'/0' and 1' + addresses += ["bcrt1qrd3n235cj2czsfmsuvqqpr3lu6lg0ju7scl8gn", + "bcrt1qfqeppuvj0ww98r6qghmdkj70tv8qpchehegrg8"] # wpkh subscripts corresponding to the above addresses desc = "sh(wpkh(" + xpriv + "/0'/0'/*'" + "))" self.log.info("Ranged descriptor import should fail without a specified range") self.test_importmulti({"desc": descsum_create(desc), @@ -600,11 +619,13 @@ def run_test(self): self.test_importmulti({"desc": descsum_create(desc), "timestamp": "now", "range": [-1, 10]}, success=False, error_code=-8, error_message='Range should be greater or equal than 0') - self.test_importmulti({"desc": descsum_create(desc), "timestamp": "now", "range": [(2 << 31 + 1) - 1000000, (2 << 31 + 1)]}, - success=False, error_code=-8, error_message='End of range is too high') + self.test_importmulti( + {"desc": descsum_create(desc), "timestamp": "now", "range": [(2 << 31 + 1) - 1000000, (2 << 31 + 1)]}, + success=False, error_code=-8, error_message='End of range is too high') self.test_importmulti({"desc": descsum_create(desc), "timestamp": "now", "range": [2, 1]}, - success=False, error_code=-8, error_message='Range specified as [begin,end] must not have begin after end') + success=False, error_code=-8, + error_message='Range specified as [begin,end] must not have begin after end') self.test_importmulti({"desc": descsum_create(desc), "timestamp": "now", "range": [0, 1000001]}, success=False, error_code=-8, error_message='Range is too large') @@ -633,7 +654,8 @@ def run_test(self): "timestamp": "now", "label": "Descriptor import test"}, True, - warnings=["Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) + warnings=[ + "Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) test_address(self.nodes[1], key.p2pkh_addr, solvable=True, @@ -665,7 +687,8 @@ def run_test(self): self.test_importmulti({"desc": descsum_create("multi(1," + key1.pubkey + "," + key2.pubkey + ")"), "timestamp": "now"}, success=True, - warnings=["Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) + warnings=[ + "Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) self.log.info("Should not treat individual keys from the imported bare multisig as watchonly") test_address(self.nodes[1], key1.p2pkh_addr, @@ -682,7 +705,7 @@ def run_test(self): pub_fpr = info['hdmasterfingerprint'] result = self.nodes[0].importmulti( [{ - 'desc' : descsum_create("wpkh([" + pub_fpr + pub_keypath[1:] +"]" + pub + ")"), + 'desc': descsum_create("wpkh([" + pub_fpr + pub_keypath[1:] + "]" + pub + ")"), "timestamp": "now", }] ) @@ -700,7 +723,7 @@ def run_test(self): priv_fpr = info['hdmasterfingerprint'] result = self.nodes[0].importmulti( [{ - 'desc' : descsum_create("wpkh([" + priv_fpr + priv_keypath[1:] + "]" + priv + ")"), + 'desc': descsum_create("wpkh([" + priv_fpr + priv_keypath[1:] + "]" + priv + ")"), "timestamp": "now", }] ) @@ -752,11 +775,11 @@ def run_test(self): 'keypool': True, "timestamp": "now", }, - { - 'desc': descsum_create('wpkh(' + pub2 + ')'), - 'keypool': True, - "timestamp": "now", - }] + { + 'desc': descsum_create('wpkh(' + pub2 + ')'), + 'keypool': True, + "timestamp": "now", + }] ) assert result[0]['success'] assert result[1]['success'] @@ -779,12 +802,12 @@ def run_test(self): 'internal': True, "timestamp": "now", }, - { - 'desc': descsum_create('wpkh(' + pub2 + ')'), - 'keypool': True, - 'internal': True, - "timestamp": "now", - }] + { + 'desc': descsum_create('wpkh(' + pub2 + ')'), + 'keypool': True, + 'internal': True, + "timestamp": "now", + }] ) assert result[0]['success'] assert result[1]['success'] @@ -822,7 +845,8 @@ def run_test(self): }] ) assert_equal(result[0]['error']['code'], -8) - assert_equal(result[0]['error']['message'], "Keys can only be imported to the keypool when private keys are disabled") + assert_equal(result[0]['error']['message'], + "Keys can only be imported to the keypool when private keys are disabled") # Make sure ranged imports import keys in order self.log.info('Key ranges should be imported in order') @@ -831,23 +855,24 @@ def run_test(self): assert_equal(wrpc.getwalletinfo()["private_keys_enabled"], False) xpub = "tpubDAXcJ7s7ZwicqjprRaEWdPoHKrCS215qxGYxpusRLLmJuT69ZSicuGdSfyvyKpvUNYBW1s2U3NSrT6vrCYB9e6nZUEvrqnwXPF8ArTCRXMY" addresses = [ - 'bcrt1qtmp74ayg7p24uslctssvjm06q5phz4yrxucgnv', # m/0'/0'/0 - 'bcrt1q8vprchan07gzagd5e6v9wd7azyucksq2xc76k8', # m/0'/0'/1 - 'bcrt1qtuqdtha7zmqgcrr26n2rqxztv5y8rafjp9lulu', # m/0'/0'/2 - 'bcrt1qau64272ymawq26t90md6an0ps99qkrse58m640', # m/0'/0'/3 - 'bcrt1qsg97266hrh6cpmutqen8s4s962aryy77jp0fg0', # m/0'/0'/4 + 'bcrt1qtmp74ayg7p24uslctssvjm06q5phz4yrxucgnv', # m/0'/0'/0 + 'bcrt1q8vprchan07gzagd5e6v9wd7azyucksq2xc76k8', # m/0'/0'/1 + 'bcrt1qtuqdtha7zmqgcrr26n2rqxztv5y8rafjp9lulu', # m/0'/0'/2 + 'bcrt1qau64272ymawq26t90md6an0ps99qkrse58m640', # m/0'/0'/3 + 'bcrt1qsg97266hrh6cpmutqen8s4s962aryy77jp0fg0', # m/0'/0'/4 ] result = wrpc.importmulti( [{ 'desc': descsum_create('wpkh([80002067/0h/0h]' + xpub + '/*)'), 'keypool': True, 'timestamp': 'now', - 'range' : [0, 4], + 'range': [0, 4], }] ) for i in range(0, 5): addr = wrpc.getnewaddress('', 'bech32') assert_equal(addr, addresses[i]) + if __name__ == '__main__': ImportMultiTest().main() diff --git a/test/functional/wallet_importprunedfunds.py b/test/functional/wallet_importprunedfunds.py index 04fa36e029..19b869b17c 100755 --- a/test/functional/wallet_importprunedfunds.py +++ b/test/functional/wallet_importprunedfunds.py @@ -11,6 +11,7 @@ assert_raises_rpc_error, ) + class ImportPrunedFundsTest(DefiTestFramework): def set_test_params(self): self.setup_clean_chain = True @@ -110,5 +111,6 @@ def run_test(self): self.nodes[1].removeprunedfunds(txnid3) assert not [tx for tx in self.nodes[1].listtransactions(include_watchonly=True) if tx['txid'] == txnid3] + if __name__ == '__main__': ImportPrunedFundsTest().main() diff --git a/test/functional/wallet_keypool.py b/test/functional/wallet_keypool.py index fbf149ac4c..055514111b 100755 --- a/test/functional/wallet_keypool.py +++ b/test/functional/wallet_keypool.py @@ -9,6 +9,7 @@ from test_framework.test_framework import DefiTestFramework from test_framework.util import assert_equal, assert_raises_rpc_error + class KeyPoolTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 @@ -82,5 +83,6 @@ def run_test(self): assert_equal(wi['keypoolsize_hd_internal'], 100) assert_equal(wi['keypoolsize'], 100) + if __name__ == '__main__': KeyPoolTest().main() diff --git a/test/functional/wallet_keypool_topup.py b/test/functional/wallet_keypool_topup.py index b23bfcf4f5..8ec5882dab 100755 --- a/test/functional/wallet_keypool_topup.py +++ b/test/functional/wallet_keypool_topup.py @@ -45,7 +45,7 @@ def run_test(self): for i, output_type in enumerate(["legacy", "p2sh-segwit", "bech32"]): self.log.info("Generate keys for wallet with address type: {}".format(output_type)) - idx = i+1 + idx = i + 1 for _ in range(90): addr_oldpool = self.nodes[idx].getnewaddress(address_type=output_type) for _ in range(20): @@ -60,7 +60,6 @@ def run_test(self): else: assert not address_details["isscript"] and address_details["iswitness"] - self.log.info("Send funds to wallet") self.nodes[0].sendtoaddress(addr_oldpool, 10) self.nodes[0].generate(1) @@ -77,7 +76,7 @@ def run_test(self): self.log.info("Verify keypool is restored and balance is correct") assert_equal(self.nodes[idx].getbalance(), 15) - assert_equal(self.nodes[idx].listtransactions()[1]['category'], "receive") # cause [0] is genesis mn tx + assert_equal(self.nodes[idx].listtransactions()[1]['category'], "receive") # cause [0] is genesis mn tx assert_equal(self.nodes[idx].listtransactions()[2]['category'], "receive") # Check that we have marked all keys up to the used keypool key as used assert_equal(self.nodes[idx].getaddressinfo(self.nodes[idx].getnewaddress())['hdkeypath'], "m/0'/0'/110'") diff --git a/test/functional/wallet_labels.py b/test/functional/wallet_labels.py index bf19f9cbea..915bd1e263 100755 --- a/test/functional/wallet_labels.py +++ b/test/functional/wallet_labels.py @@ -14,6 +14,7 @@ from test_framework.test_framework import DefiTestFramework from test_framework.util import assert_equal, assert_raises_rpc_error + class WalletLabelsTest(DefiTestFramework): def set_test_params(self): self.setup_clean_chain = True @@ -35,8 +36,8 @@ def run_test(self): # there should be 2 address groups # each with 1 address with a balance of 50 Defis - address_groups = node.listaddressgroupings() # TODO: may be remove genesis (or all) mn_creation txs from listaddressgroupings? - assert_equal(len(address_groups), 3) # +1 mn genesis + address_groups = node.listaddressgroupings() # TODO: may be remove genesis (or all) mn_creation txs from listaddressgroupings? + assert_equal(len(address_groups), 3) # +1 mn genesis # the addresses aren't linked now, but will be after we send to the # common address linked_addresses = set() @@ -57,10 +58,10 @@ def run_test(self): # there should be 1 address group, with the previously # unlinked addresses now linked (they both have 0 balance) address_groups = node.listaddressgroupings() - assert_equal(len(address_groups), 1+1) - assert_equal(len(address_groups[0+1]), 2) - assert_equal(set([a[0] for a in address_groups[0+1]]), linked_addresses) - assert_equal([a[1] for a in address_groups[0+1]], [0, 0]) + assert_equal(len(address_groups), 1 + 1) + assert_equal(len(address_groups[0 + 1]), 2) + assert_equal(set([a[0] for a in address_groups[0 + 1]]), linked_addresses) + assert_equal([a[1] for a in address_groups[0 + 1]], [0, 0]) node.generate(1) @@ -131,6 +132,7 @@ def run_test(self): # in the label. This is a no-op. change_label(node, labels[2].addresses[0], labels[2], labels[2]) + class Label: def __init__(self, name): # Label name @@ -164,6 +166,7 @@ def verify(self, node): node.getaddressesbylabel(self.name), {address: {"purpose": self.purpose[address]} for address in self.addresses}) + def change_label(node, address, old_label, new_label): assert_equal(address in old_label.addresses, True) node.setlabel(address, new_label.name) @@ -174,5 +177,6 @@ def change_label(node, address, old_label, new_label): old_label.verify(node) new_label.verify(node) + if __name__ == '__main__': WalletLabelsTest().main() diff --git a/test/functional/wallet_listreceivedby.py b/test/functional/wallet_listreceivedby.py index 80c75df014..feb036ca07 100755 --- a/test/functional/wallet_listreceivedby.py +++ b/test/functional/wallet_listreceivedby.py @@ -26,7 +26,8 @@ def run_test(self): self.sync_blocks() # save the number of coinbase reward addresses so far - num_cb_reward_addresses = len(self.nodes[1].listreceivedbyaddress(minconf=0, include_empty=True, include_watchonly=True)) + num_cb_reward_addresses = len( + self.nodes[1].listreceivedbyaddress(minconf=0, include_empty=True, include_watchonly=True)) self.log.info("listreceivedbyaddress Test") @@ -45,11 +46,13 @@ def run_test(self): self.sync_blocks() assert_array_result(self.nodes[1].listreceivedbyaddress(), {"address": addr}, - {"address": addr, "label": "", "amount": Decimal("0.1"), "confirmations": 10, "txids": [txid, ]}) + {"address": addr, "label": "", "amount": Decimal("0.1"), "confirmations": 10, + "txids": [txid, ]}) # With min confidence < 10 assert_array_result(self.nodes[1].listreceivedbyaddress(5), {"address": addr}, - {"address": addr, "label": "", "amount": Decimal("0.1"), "confirmations": 10, "txids": [txid, ]}) + {"address": addr, "label": "", "amount": Decimal("0.1"), "confirmations": 10, + "txids": [txid, ]}) # With min confidence > 10, should not find Tx assert_array_result(self.nodes[1].listreceivedbyaddress(11), {"address": addr}, {}, True) @@ -62,7 +65,8 @@ def run_test(self): # Test Address filtering # Only on addr expected = {"address": addr, "label": "", "amount": Decimal("0.1"), "confirmations": 10, "txids": [txid, ]} - res = self.nodes[1].listreceivedbyaddress(minconf=0, include_empty=True, include_watchonly=True, address_filter=addr) + res = self.nodes[1].listreceivedbyaddress(minconf=0, include_empty=True, include_watchonly=True, + address_filter=addr) assert_array_result(res, {"address": addr}, expected) assert_equal(len(res), 1) # Test for regression on CLI calls with address string (#14173) @@ -70,7 +74,8 @@ def run_test(self): assert_array_result(cli_res, {"address": addr}, expected) assert_equal(len(cli_res), 1) # Error on invalid address - assert_raises_rpc_error(-4, "address_filter parameter was invalid", self.nodes[1].listreceivedbyaddress, minconf=0, include_empty=True, include_watchonly=True, address_filter="bamboozling") + assert_raises_rpc_error(-4, "address_filter parameter was invalid", self.nodes[1].listreceivedbyaddress, + minconf=0, include_empty=True, include_watchonly=True, address_filter="bamboozling") # Another address receive money res = self.nodes[1].listreceivedbyaddress(0, True, True) assert_equal(len(res), 2 + num_cb_reward_addresses) # Right now 2 entries @@ -84,7 +89,8 @@ def run_test(self): assert_array_result(res, {"address": addr}, expected) assert_equal(len(res), 1) # Same test as above but with other_addr should still pass - expected = {"address": other_addr, "label": "", "amount": Decimal("0.1"), "confirmations": 1, "txids": [txid2, ]} + expected = {"address": other_addr, "label": "", "amount": Decimal("0.1"), "confirmations": 1, + "txids": [txid2, ]} res = self.nodes[1].listreceivedbyaddress(0, True, True, other_addr) assert_array_result(res, {"address": other_addr}, expected) assert_equal(len(res), 1) @@ -147,7 +153,8 @@ def run_test(self): # listreceivedbylabel should return updated received list assert_array_result(self.nodes[1].listreceivedbylabel(), {"label": label}, - {"label": received_by_label_json["label"], "amount": (received_by_label_json["amount"] + Decimal("0.1"))}) + {"label": received_by_label_json["label"], + "amount": (received_by_label_json["amount"] + Decimal("0.1"))}) # getreceivedbylabel should return updated receive total balance = self.nodes[1].getreceivedbylabel(label) @@ -156,7 +163,8 @@ def run_test(self): # Create a new label named "mynewlabel" that has a 0 balance address = self.nodes[1].getnewaddress() self.nodes[1].setlabel(address, "mynewlabel") - received_by_label_json = [r for r in self.nodes[1].listreceivedbylabel(0, True) if r["label"] == "mynewlabel"][0] + received_by_label_json = [r for r in self.nodes[1].listreceivedbylabel(0, True) if r["label"] == "mynewlabel"][ + 0] # Test includeempty of listreceivedbylabel assert_equal(received_by_label_json["amount"], Decimal("0.0")) @@ -165,5 +173,6 @@ def run_test(self): balance = self.nodes[1].getreceivedbylabel("mynewlabel") assert_equal(balance, Decimal("0.0")) + if __name__ == '__main__': ReceivedByTest().main() diff --git a/test/functional/wallet_listsinceblock.py b/test/functional/wallet_listsinceblock.py index 27adeaf695..5b9614c212 100755 --- a/test/functional/wallet_listsinceblock.py +++ b/test/functional/wallet_listsinceblock.py @@ -7,7 +7,8 @@ from test_framework.test_framework import DefiTestFramework from test_framework.util import assert_equal, assert_array_result, assert_raises_rpc_error -class ListSinceBlockTest (DefiTestFramework): + +class ListSinceBlockTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 4 self.setup_clean_chain = True @@ -40,22 +41,25 @@ def test_no_blockhash(self): assert_equal( sorted(self.nodes[0].listsinceblock()), sorted({"lastblock": blockhash, - "removed": [], - "transactions": txs})) + "removed": [], + "transactions": txs})) assert_equal( sorted(self.nodes[0].listsinceblock("")), sorted({"lastblock": blockhash, - "removed": [], - "transactions": txs})) + "removed": [], + "transactions": txs})) def test_invalid_blockhash(self): assert_raises_rpc_error(-5, "Block not found", self.nodes[0].listsinceblock, "42759cde25462784395a337460bde75f58e73d3f08bd31fdc3507cbac856a2c4") assert_raises_rpc_error(-5, "Block not found", self.nodes[0].listsinceblock, "0000000000000000000000000000000000000000000000000000000000000000") - assert_raises_rpc_error(-8, "blockhash must be of length 64 (not 11, for 'invalid-hex')", self.nodes[0].listsinceblock, + assert_raises_rpc_error(-8, "blockhash must be of length 64 (not 11, for 'invalid-hex')", + self.nodes[0].listsinceblock, "invalid-hex") - assert_raises_rpc_error(-8, "blockhash must be hexadecimal string (not 'Z000000000000000000000000000000000000000000000000000000000000000')", self.nodes[0].listsinceblock, + assert_raises_rpc_error(-8, + "blockhash must be hexadecimal string (not 'Z000000000000000000000000000000000000000000000000000000000000000')", + self.nodes[0].listsinceblock, "Z000000000000000000000000000000000000000000000000000000000000000") def test_reorg(self): @@ -282,5 +286,6 @@ def test_double_send(self): if tx['txid'] == txid1: assert_equal(tx['confirmations'], 2) + if __name__ == '__main__': ListSinceBlockTest().main() diff --git a/test/functional/wallet_listtransactions.py b/test/functional/wallet_listtransactions.py index fc64df21da..64a850012c 100755 --- a/test/functional/wallet_listtransactions.py +++ b/test/functional/wallet_listtransactions.py @@ -14,12 +14,14 @@ hex_str_to_bytes, ) + def tx_from_hex(hexstring): tx = CTransaction() f = BytesIO(hex_str_to_bytes(hexstring)) tx.deserialize(f) return tx + class ListTransactionsTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 2 @@ -205,5 +207,6 @@ def get_unconfirmed_utxo_entry(node, txid_to_match): assert_equal(self.nodes[0].gettransaction(txid_3b)["bip125-replaceable"], "no") assert_equal(self.nodes[0].gettransaction(txid_4)["bip125-replaceable"], "unknown") + if __name__ == '__main__': ListTransactionsTest().main() diff --git a/test/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py index 4e27b956ff..b2fb67f08b 100755 --- a/test/functional/wallet_multiwallet.py +++ b/test/functional/wallet_multiwallet.py @@ -39,7 +39,7 @@ def wallet_file(name): return wallet_dir(name, "wallet.dat") return wallet_dir(name) - assert_equal(self.nodes[0].listwalletdir(), { 'wallets': [{ 'name': '' }] }) + assert_equal(self.nodes[0].listwalletdir(), {'wallets': [{'name': ''}]}) # check wallet.dat is created self.stop_nodes() @@ -68,10 +68,12 @@ def wallet_file(name): # w7_symlink - to verify symlinked wallet path is initialized correctly # w8 - to verify existing wallet file is loaded correctly # '' - to verify default wallet file is created correctly - wallet_names = ['w1', 'w2', 'w3', 'w', 'sub/w5', os.path.join(self.options.tmpdir, 'extern/w6'), 'w7_symlink', 'w8', ''] + wallet_names = ['w1', 'w2', 'w3', 'w', 'sub/w5', os.path.join(self.options.tmpdir, 'extern/w6'), 'w7_symlink', + 'w8', ''] extra_args = ['-wallet={}'.format(n) for n in wallet_names] self.start_node(0, extra_args) - assert_equal(sorted(map(lambda w: w['name'], self.nodes[0].listwalletdir()['wallets'])), ['', os.path.join('sub', 'w5'), 'w', 'w1', 'w2', 'w3', 'w7', 'w7_symlink', 'w8']) + assert_equal(sorted(map(lambda w: w['name'], self.nodes[0].listwalletdir()['wallets'])), + ['', os.path.join('sub', 'w5'), 'w', 'w1', 'w2', 'w3', 'w7', 'w7_symlink', 'w8']) assert_equal(set(node.listwallets()), set(wallet_names)) @@ -82,43 +84,62 @@ def wallet_file(name): # should not initialize if wallet path can't be created exp_stderr = "boost::filesystem::create_directory:" - self.nodes[0].assert_start_raises_init_error(['-wallet=wallet.dat/bad'], exp_stderr, match=ErrorMatch.PARTIAL_REGEX) - - self.nodes[0].assert_start_raises_init_error(['-walletdir=wallets'], 'Error: Specified -walletdir "wallets" does not exist') - self.nodes[0].assert_start_raises_init_error(['-walletdir=wallets'], 'Error: Specified -walletdir "wallets" is a relative path', cwd=data_dir()) - self.nodes[0].assert_start_raises_init_error(['-walletdir=debug.log'], 'Error: Specified -walletdir "debug.log" is not a directory', cwd=data_dir()) + self.nodes[0].assert_start_raises_init_error(['-wallet=wallet.dat/bad'], exp_stderr, + match=ErrorMatch.PARTIAL_REGEX) + + self.nodes[0].assert_start_raises_init_error(['-walletdir=wallets'], + 'Error: Specified -walletdir "wallets" does not exist') + self.nodes[0].assert_start_raises_init_error(['-walletdir=wallets'], + 'Error: Specified -walletdir "wallets" is a relative path', + cwd=data_dir()) + self.nodes[0].assert_start_raises_init_error(['-walletdir=debug.log'], + 'Error: Specified -walletdir "debug.log" is not a directory', + cwd=data_dir()) # should not initialize if there are duplicate wallets - self.nodes[0].assert_start_raises_init_error(['-wallet=w1', '-wallet=w1'], 'Error: Error loading wallet w1. Duplicate -wallet filename specified.') + self.nodes[0].assert_start_raises_init_error(['-wallet=w1', '-wallet=w1'], + 'Error: Error loading wallet w1. Duplicate -wallet filename specified.') # should not initialize if one wallet is a copy of another shutil.copyfile(wallet_dir('w8'), wallet_dir('w8_copy')) - exp_stderr = "BerkeleyBatch: Can't open database w8_copy \(duplicates fileid \w+ from w8\)" - self.nodes[0].assert_start_raises_init_error(['-wallet=w8', '-wallet=w8_copy'], exp_stderr, match=ErrorMatch.PARTIAL_REGEX) + exp_stderr = r"BerkeleyBatch: Can't open database w8_copy \(duplicates fileid \w+ from w8\)" + self.nodes[0].assert_start_raises_init_error(['-wallet=w8', '-wallet=w8_copy'], exp_stderr, + match=ErrorMatch.PARTIAL_REGEX) # should not initialize if wallet file is a symlink os.symlink('w8', wallet_dir('w8_symlink')) - self.nodes[0].assert_start_raises_init_error(['-wallet=w8_symlink'], 'Error: Invalid -wallet path \'w8_symlink\'\. .*', match=ErrorMatch.FULL_REGEX) + self.nodes[0].assert_start_raises_init_error(['-wallet=w8_symlink'], + r"Error: Invalid -wallet path \'w8_symlink'\. .*", + match=ErrorMatch.FULL_REGEX) # should not initialize if the specified walletdir does not exist - self.nodes[0].assert_start_raises_init_error(['-walletdir=bad'], 'Error: Specified -walletdir "bad" does not exist') + self.nodes[0].assert_start_raises_init_error(['-walletdir=bad'], + 'Error: Specified -walletdir "bad" does not exist') # should not initialize if the specified walletdir is not a directory not_a_dir = wallet_dir('notadir') open(not_a_dir, 'a', encoding="utf8").close() - self.nodes[0].assert_start_raises_init_error(['-walletdir=' + not_a_dir], 'Error: Specified -walletdir "' + not_a_dir + '" is not a directory') + self.nodes[0].assert_start_raises_init_error(['-walletdir=' + not_a_dir], + 'Error: Specified -walletdir "' + not_a_dir + '" is not a directory') self.log.info("Do not allow -zapwallettxes with multiwallet") - self.nodes[0].assert_start_raises_init_error(['-zapwallettxes', '-wallet=w1', '-wallet=w2'], "Error: -zapwallettxes is only allowed with a single wallet file") - self.nodes[0].assert_start_raises_init_error(['-zapwallettxes=1', '-wallet=w1', '-wallet=w2'], "Error: -zapwallettxes is only allowed with a single wallet file") - self.nodes[0].assert_start_raises_init_error(['-zapwallettxes=2', '-wallet=w1', '-wallet=w2'], "Error: -zapwallettxes is only allowed with a single wallet file") + self.nodes[0].assert_start_raises_init_error(['-zapwallettxes', '-wallet=w1', '-wallet=w2'], + "Error: -zapwallettxes is only allowed with a single wallet file") + self.nodes[0].assert_start_raises_init_error(['-zapwallettxes=1', '-wallet=w1', '-wallet=w2'], + "Error: -zapwallettxes is only allowed with a single wallet file") + self.nodes[0].assert_start_raises_init_error(['-zapwallettxes=2', '-wallet=w1', '-wallet=w2'], + "Error: -zapwallettxes is only allowed with a single wallet file") self.log.info("Do not allow -salvagewallet with multiwallet") - self.nodes[0].assert_start_raises_init_error(['-salvagewallet', '-wallet=w1', '-wallet=w2'], "Error: -salvagewallet is only allowed with a single wallet file") - self.nodes[0].assert_start_raises_init_error(['-salvagewallet=1', '-wallet=w1', '-wallet=w2'], "Error: -salvagewallet is only allowed with a single wallet file") + self.nodes[0].assert_start_raises_init_error(['-salvagewallet', '-wallet=w1', '-wallet=w2'], + "Error: -salvagewallet is only allowed with a single wallet file") + self.nodes[0].assert_start_raises_init_error(['-salvagewallet=1', '-wallet=w1', '-wallet=w2'], + "Error: -salvagewallet is only allowed with a single wallet file") self.log.info("Do not allow -upgradewallet with multiwallet") - self.nodes[0].assert_start_raises_init_error(['-upgradewallet', '-wallet=w1', '-wallet=w2'], "Error: -upgradewallet is only allowed with a single wallet file") - self.nodes[0].assert_start_raises_init_error(['-upgradewallet=1', '-wallet=w1', '-wallet=w2'], "Error: -upgradewallet is only allowed with a single wallet file") + self.nodes[0].assert_start_raises_init_error(['-upgradewallet', '-wallet=w1', '-wallet=w2'], + "Error: -upgradewallet is only allowed with a single wallet file") + self.nodes[0].assert_start_raises_init_error(['-upgradewallet=1', '-wallet=w1', '-wallet=w2'], + "Error: -upgradewallet is only allowed with a single wallet file") # if wallets/ doesn't exist, datadir should be the default wallet dir wallet_dir2 = data_dir('walletdir') @@ -140,13 +161,15 @@ def wallet_file(name): competing_wallet_dir = os.path.join(self.options.tmpdir, 'competing_walletdir') os.mkdir(competing_wallet_dir) self.restart_node(0, ['-walletdir=' + competing_wallet_dir]) - exp_stderr = "Error: Error initializing wallet database environment \"\S+competing_walletdir\"!" - self.nodes[1].assert_start_raises_init_error(['-walletdir=' + competing_wallet_dir], exp_stderr, match=ErrorMatch.PARTIAL_REGEX) + exp_stderr = r"Error: Error initializing wallet database environment \"\S+competing_walletdir\"!" + self.nodes[1].assert_start_raises_init_error(['-walletdir=' + competing_wallet_dir], exp_stderr, + match=ErrorMatch.PARTIAL_REGEX) self.restart_node(0, extra_args) wallets = sorted(map(lambda w: w['name'], self.nodes[0].listwalletdir()['wallets'])) - assert_equal(wallets, ['', os.path.join('sub', 'w5'), 'w', 'w1', 'w2', 'w3', 'w7', 'w7_symlink', 'w8', 'w8_copy']) + assert_equal(wallets, + ['', os.path.join('sub', 'w5'), 'w', 'w1', 'w2', 'w3', 'w7', 'w7_symlink', 'w8', 'w8_copy']) wallets = [wallet(w) for w in wallet_names] wallet_bad = wallet("bad") @@ -223,24 +246,31 @@ def wallet_file(name): assert_raises_rpc_error(-18, 'Wallet wallets not found.', self.nodes[0].loadwallet, 'wallets') # Fail to load duplicate wallets - assert_raises_rpc_error(-4, 'Wallet file verification failed: Error loading wallet w1. Duplicate -wallet filename specified.', self.nodes[0].loadwallet, wallet_names[0]) + assert_raises_rpc_error(-4, + 'Wallet file verification failed: Error loading wallet w1. Duplicate -wallet filename specified.', + self.nodes[0].loadwallet, wallet_names[0]) # Fail to load duplicate wallets by different ways (directory and filepath) - assert_raises_rpc_error(-4, "Wallet file verification failed: Error loading wallet wallet.dat. Duplicate -wallet filename specified.", self.nodes[0].loadwallet, 'wallet.dat') + assert_raises_rpc_error(-4, + "Wallet file verification failed: Error loading wallet wallet.dat. Duplicate -wallet filename specified.", + self.nodes[0].loadwallet, 'wallet.dat') # Fail to load if one wallet is a copy of another - assert_raises_rpc_error(-1, "BerkeleyBatch: Can't open database w8_copy (duplicates fileid", self.nodes[0].loadwallet, 'w8_copy') + assert_raises_rpc_error(-1, "BerkeleyBatch: Can't open database w8_copy (duplicates fileid", + self.nodes[0].loadwallet, 'w8_copy') # Fail to load if one wallet is a copy of another, test this twice to make sure that we don't re-introduce #14304 - assert_raises_rpc_error(-1, "BerkeleyBatch: Can't open database w8_copy (duplicates fileid", self.nodes[0].loadwallet, 'w8_copy') - + assert_raises_rpc_error(-1, "BerkeleyBatch: Can't open database w8_copy (duplicates fileid", + self.nodes[0].loadwallet, 'w8_copy') # Fail to load if wallet file is a symlink - assert_raises_rpc_error(-4, "Wallet file verification failed: Invalid -wallet path 'w8_symlink'", self.nodes[0].loadwallet, 'w8_symlink') + assert_raises_rpc_error(-4, "Wallet file verification failed: Invalid -wallet path 'w8_symlink'", + self.nodes[0].loadwallet, 'w8_symlink') # Fail to load if a directory is specified that doesn't contain a wallet os.mkdir(wallet_dir('empty_wallet_dir')) - assert_raises_rpc_error(-18, "Directory empty_wallet_dir does not contain a wallet.dat file", self.nodes[0].loadwallet, 'empty_wallet_dir') + assert_raises_rpc_error(-18, "Directory empty_wallet_dir does not contain a wallet.dat file", + self.nodes[0].loadwallet, 'empty_wallet_dir') self.log.info("Test dynamic wallet creation.") @@ -269,8 +299,10 @@ def wallet_file(name): # Test `unloadwallet` errors assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[0].unloadwallet) - assert_raises_rpc_error(-18, "Requested wallet does not exist or is not loaded", self.nodes[0].unloadwallet, "dummy") - assert_raises_rpc_error(-18, "Requested wallet does not exist or is not loaded", node.get_wallet_rpc("dummy").unloadwallet) + assert_raises_rpc_error(-18, "Requested wallet does not exist or is not loaded", self.nodes[0].unloadwallet, + "dummy") + assert_raises_rpc_error(-18, "Requested wallet does not exist or is not loaded", + node.get_wallet_rpc("dummy").unloadwallet) assert_raises_rpc_error(-8, "Cannot unload the requested wallet", w1.unloadwallet, "w2"), # Successfully unload the specified wallet name @@ -289,14 +321,16 @@ def wallet_file(name): for wallet_name in self.nodes[0].listwallets(): self.nodes[0].unloadwallet(wallet_name) assert_equal(self.nodes[0].listwallets(), []) - assert_raises_rpc_error(-32601, "Method not found (wallet method is disabled because no wallet is loaded)", self.nodes[0].getwalletinfo) + assert_raises_rpc_error(-32601, "Method not found (wallet method is disabled because no wallet is loaded)", + self.nodes[0].getwalletinfo) # Successfully load a previously unloaded wallet self.nodes[0].loadwallet('w1') assert_equal(self.nodes[0].listwallets(), ['w1']) assert_equal(w1.getwalletinfo()['walletname'], 'w1') - assert_equal(sorted(map(lambda w: w['name'], self.nodes[0].listwalletdir()['wallets'])), ['', os.path.join('sub', 'w5'), 'w', 'w1', 'w2', 'w3', 'w7', 'w7_symlink', 'w8', 'w8_copy', 'w9']) + assert_equal(sorted(map(lambda w: w['name'], self.nodes[0].listwalletdir()['wallets'])), + ['', os.path.join('sub', 'w5'), 'w', 'w1', 'w2', 'w3', 'w7', 'w7_symlink', 'w8', 'w8_copy', 'w9']) # Test backing up and restoring wallets self.log.info("Test wallet backup") diff --git a/test/functional/wallet_resendwallettransactions.py b/test/functional/wallet_resendwallettransactions.py index 52c559242f..0677b0d23f 100755 --- a/test/functional/wallet_resendwallettransactions.py +++ b/test/functional/wallet_resendwallettransactions.py @@ -12,6 +12,7 @@ from test_framework.test_framework import DefiTestFramework from test_framework.util import assert_equal, wait_until + class P2PStoreTxInvs(P2PInterface): def __init__(self): super().__init__() @@ -24,6 +25,7 @@ def on_inv(self, message): # save txid self.tx_invs_received[i.hash] += 1 + class ResendWalletTransactionsTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 1 @@ -72,5 +74,6 @@ def run_test(self): node.setmocktime(rebroadcast_time) wait_until(lambda: node.p2ps[1].tx_invs_received[txid] >= 1, lock=mininode_lock) + if __name__ == '__main__': ResendWalletTransactionsTest().main() diff --git a/test/functional/wallet_txn_clone.py b/test/functional/wallet_txn_clone.py index b5f94e2941..ab82f27799 100755 --- a/test/functional/wallet_txn_clone.py +++ b/test/functional/wallet_txn_clone.py @@ -13,6 +13,7 @@ ) from test_framework.messages import CTransaction, COIN + class TxnMallTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 4 @@ -66,7 +67,8 @@ def run_test(self): # Construct a clone of tx1, to be malleated rawtx1 = self.nodes[0].getrawtransaction(txid1, 1) - clone_inputs = [{"txid": rawtx1["vin"][0]["txid"], "vout": rawtx1["vin"][0]["vout"], "sequence": rawtx1["vin"][0]["sequence"]}] + clone_inputs = [{"txid": rawtx1["vin"][0]["txid"], "vout": rawtx1["vin"][0]["vout"], + "sequence": rawtx1["vin"][0]["sequence"]}] clone_outputs = {rawtx1["vout"][0]["scriptPubKey"]["addresses"][0]: rawtx1["vout"][0]["value"], rawtx1["vout"][1]["scriptPubKey"]["addresses"][0]: rawtx1["vout"][1]["value"]} clone_locktime = rawtx1["locktime"] @@ -75,7 +77,8 @@ def run_test(self): # createrawtransaction randomizes the order of its outputs, so swap them if necessary. clone_tx = CTransaction() clone_tx.deserialize(io.BytesIO(bytes.fromhex(clone_raw))) - if (rawtx1["vout"][0]["value"] == 40 and clone_tx.vout[0].nValue != 40*COIN or rawtx1["vout"][0]["value"] != 40 and clone_tx.vout[0].nValue == 40*COIN): + if (rawtx1["vout"][0]["value"] == 40 and clone_tx.vout[0].nValue != 40 * COIN or rawtx1["vout"][0][ + "value"] != 40 and clone_tx.vout[0].nValue == 40 * COIN): (clone_tx.vout[0], clone_tx.vout[1]) = (clone_tx.vout[1], clone_tx.vout[0]) # Use a different signature hash type to sign. This creates an equivalent but malleated clone. @@ -141,5 +144,6 @@ def run_test(self): expected -= 50 assert_equal(self.nodes[0].getbalance(), expected) + if __name__ == '__main__': TxnMallTest().main() diff --git a/test/functional/wallet_txn_doublespend.py b/test/functional/wallet_txn_doublespend.py index 8426fdb45d..7b584de59e 100755 --- a/test/functional/wallet_txn_doublespend.py +++ b/test/functional/wallet_txn_doublespend.py @@ -13,6 +13,7 @@ find_output, ) + class TxnMallTest(DefiTestFramework): def set_test_params(self): self.num_nodes = 4 @@ -138,5 +139,6 @@ def run_test(self): # Node1's balance should be its initial balance (1250 for 25 block rewards) plus the doublespend: assert_equal(self.nodes[1].getbalance(), 1250 + 1240) + if __name__ == '__main__': TxnMallTest().main() diff --git a/test/functional/wallet_watchonly.py b/test/functional/wallet_watchonly.py index edff751a46..93c00b978b 100755 --- a/test/functional/wallet_watchonly.py +++ b/test/functional/wallet_watchonly.py @@ -93,7 +93,8 @@ def run_test(self): result = wo_wallet.walletcreatefundedpsbt(inputs=inputs, outputs=outputs, options=options) assert_equal("psbt" in result, True) - assert_raises_rpc_error(-4, "Insufficient funds", wo_wallet.walletcreatefundedpsbt, inputs, outputs, 0, no_wo_options) + assert_raises_rpc_error(-4, "Insufficient funds", wo_wallet.walletcreatefundedpsbt, inputs, outputs, 0, + no_wo_options) self.log.info('Testing fundrawtransaction watch-only defaults') rawtx = wo_wallet.createrawtransaction(inputs=inputs, outputs=outputs) @@ -102,6 +103,5 @@ def run_test(self): assert_raises_rpc_error(-4, "Insufficient funds", wo_wallet.fundrawtransaction, rawtx, no_wo_options) - if __name__ == '__main__': CreateWalletWatchonlyTest().main() diff --git a/test/functional/wallet_zapwallettxes.py b/test/functional/wallet_zapwallettxes.py index 6de50dc4da..5d5c635458 100755 --- a/test/functional/wallet_zapwallettxes.py +++ b/test/functional/wallet_zapwallettxes.py @@ -21,7 +21,8 @@ wait_until, ) -class ZapWalletTXesTest (DefiTestFramework): + +class ZapWalletTXesTest(DefiTestFramework): def set_test_params(self): self.setup_clean_chain = True self.num_nodes = 2 @@ -79,5 +80,6 @@ def run_test(self): # This will raise an exception because the unconfirmed transaction has been zapped assert_raises_rpc_error(-5, 'Invalid or non-wallet transaction id', self.nodes[0].gettransaction, txid2) + if __name__ == '__main__': ZapWalletTXesTest().main() diff --git a/test/fuzz/test_runner.py b/test/fuzz/test_runner.py index c8fb7270f3..3bbac5cd1b 100755 --- a/test/fuzz/test_runner.py +++ b/test/fuzz/test_runner.py @@ -55,7 +55,8 @@ def main(): sys.exit(1) # Build list of tests - test_list_all = parse_test_list(makefile=os.path.join(config["environment"]["SRCDIR"], 'src', 'Makefile.test.include')) + test_list_all = parse_test_list( + makefile=os.path.join(config["environment"]["SRCDIR"], 'src', 'Makefile.test.include')) if not test_list_all: logging.error("No fuzz targets found") diff --git a/test/lint/README.md b/test/lint/README.md index 15974a3598..c2b3a5b66e 100644 --- a/test/lint/README.md +++ b/test/lint/README.md @@ -15,6 +15,7 @@ the commit it claims to have been updated to. To use, make sure that you have fetched the upstream repository branch in which the subtree is maintained: + * for `src/secp256k1`: https://github.com/bitcoin-core/secp256k1.git (branch master) * for `src/leveldb`: https://github.com/bitcoin-core/leveldb.git (branch bitcoin-fork) * for `src/univalue`: https://github.com/bitcoin-core/univalue.git (branch master) diff --git a/test/lint/check-doc.py b/test/lint/check-doc.py index bbf57f706b..fd1c0eae46 100755 --- a/test/lint/check-doc.py +++ b/test/lint/check-doc.py @@ -15,12 +15,14 @@ FOLDER_GREP = 'src' FOLDER_TEST = 'src/test/' -REGEX_ARG = '(?:ForceSet|SoftSet|Get|Is)(?:Bool)?Args?(?:Set)?\("(-[^"]+)"' -REGEX_DOC = 'AddArg\("(-[^"=]+?)(?:=|")' +REGEX_ARG = r'(?:ForceSet|SoftSet|Get|Is)(?:Bool)?Args?(?:Set)?\("(-[^"]+)"' +REGEX_DOC = r'AddArg\("(-[^"=]+?)(?:=|")' CMD_ROOT_DIR = '$(git rev-parse --show-toplevel)/{}'.format(FOLDER_GREP) CMD_GREP_ARGS = r"git grep --perl-regexp '{}' -- {} ':(exclude){}'".format(REGEX_ARG, CMD_ROOT_DIR, FOLDER_TEST) -CMD_GREP_WALLET_ARGS = r"git grep --function-context 'void WalletInit::AddWalletOptions' -- {} | grep AddArg".format(CMD_ROOT_DIR) -CMD_GREP_WALLET_HIDDEN_ARGS = r"git grep --function-context 'void DummyWalletInit::AddWalletOptions' -- {}".format(CMD_ROOT_DIR) +CMD_GREP_WALLET_ARGS = r"git grep --function-context 'void WalletInit::AddWalletOptions' -- {} | grep AddArg".format( + CMD_ROOT_DIR) +CMD_GREP_WALLET_HIDDEN_ARGS = r"git grep --function-context 'void DummyWalletInit::AddWalletOptions' -- {}".format( + CMD_ROOT_DIR) CMD_GREP_DOCS = r"git grep --perl-regexp '{}' {}".format(REGEX_DOC, CMD_ROOT_DIR) # list unsupported, deprecated and duplicate args as they need no documentation SET_DOC_OPTIONAL = set([ @@ -36,7 +38,7 @@ '-mocknet-blocktime', '-checkpoints-file', '-negativeinterest', - ]) +]) def lint_missing_argument_documentation(): diff --git a/test/lint/check-rpc-mappings.py b/test/lint/check-rpc-mappings.py index 457e29aabc..ef0bef9e29 100755 --- a/test/lint/check-rpc-mappings.py +++ b/test/lint/check-rpc-mappings.py @@ -36,22 +36,26 @@ # Argument names that should be ignored in consistency checks IGNORE_DUMMY_ARGS = {'dummy', 'arg0', 'arg1', 'arg2', 'arg3', 'arg4', 'arg5', 'arg6', 'arg7', 'arg8', 'arg9'} + class RPCCommand: def __init__(self, name, args): self.name = name self.args = args + class RPCArgument: def __init__(self, names, idx): self.names = names self.idx = idx self.convert = False + def parse_string(s): assert s[0] == '"' assert s[-1] == '"' return s[1:-1] + def process_commands(fname): """Find and parse dispatch table in implementation file `fname`.""" cmds = [] @@ -60,7 +64,7 @@ def process_commands(fname): for line in f: line = line.rstrip() if not in_rpcs: - if re.match("static const CRPCCommand .*\[\] =", line): + if re.match(r"static const CRPCCommand .*\[\] =", line): in_rpcs = True else: if line.startswith('};'): @@ -71,13 +75,15 @@ def process_commands(fname): name = parse_string(m.group(2)) args_str = m.group(4).strip() if args_str: - args = [RPCArgument(parse_string(x.strip()).split('|'), idx) for idx, x in enumerate(args_str.split(','))] + args = [RPCArgument(parse_string(x.strip()).split('|'), idx) for idx, x in + enumerate(args_str.split(','))] else: args = [] cmds.append(RPCCommand(name, args)) assert not in_rpcs and cmds, "Something went wrong with parsing the C++ file: update the regexps" return cmds + def process_mapping(fname): """Find and parse conversion table in implementation file `fname`.""" cmds = [] @@ -101,6 +107,7 @@ def process_mapping(fname): assert not in_rpcs and cmds return cmds + def main(): if len(sys.argv) != 2: print('Usage: {} ROOT-DIR'.format(sys.argv[0]), file=sys.stderr) @@ -129,11 +136,13 @@ def main(): try: rargnames = cmds_by_name[cmdname].args[argidx].names except IndexError: - print('ERROR: %s argument %i (named %s in vRPCConvertParams) is not defined in dispatch table' % (cmdname, argidx, argname)) + print('ERROR: %s argument %i (named %s in vRPCConvertParams) is not defined in dispatch table' % ( + cmdname, argidx, argname)) errors += 1 continue if argname not in rargnames: - print('ERROR: %s argument %i is named %s in vRPCConvertParams but %s in dispatch table' % (cmdname, argidx, argname, rargnames), file=sys.stderr) + print('ERROR: %s argument %i is named %s in vRPCConvertParams but %s in dispatch table' % ( + cmdname, argidx, argname, rargnames), file=sys.stderr) errors += 1 # Check for conflicts in vRPCConvertParams conversion @@ -144,7 +153,8 @@ def main(): for arg in cmd.args: convert = [((cmd.name, arg.idx, argname) in mapping) for argname in arg.names] if any(convert) != all(convert): - print('ERROR: %s argument %s has conflicts in vRPCConvertParams conversion specifier %s' % (cmd.name, arg.names, convert)) + print('ERROR: %s argument %s has conflicts in vRPCConvertParams conversion specifier %s' % ( + cmd.name, arg.names, convert)) errors += 1 arg.convert = all(convert) diff --git a/test/lint/lint-format-strings.py b/test/lint/lint-format-strings.py index 76f20f6162..3bb5ad95e8 100755 --- a/test/lint/lint-format-strings.py +++ b/test/lint/lint-format-strings.py @@ -17,7 +17,7 @@ ("src/index/base.cpp", "FatalError(const char* fmt, const Args&... args)"), ("src/netbase.cpp", "LogConnectFailure(bool manual_connection, const char* fmt, const Args&... args)"), ("src/util/system.cpp", "strprintf(_(COPYRIGHT_HOLDERS).translated, COPYRIGHT_HOLDERS_SUBSTITUTION)"), - ("src/wallet/wallet.h", "WalletLogPrintf(std::string fmt, Params... parameters)"), + ("src/wallet/wallet.h", "WalletLogPrintf(std::string fmt, Params... parameters)"), ("src/wallet/wallet.h", "LogPrintf((\"%s \" + fmt).c_str(), GetDisplayName(), parameters...)"), ("src/logging.h", "LogPrintf(const char* fmt, const Args&... args)"), ] @@ -55,7 +55,7 @@ def normalize(s): assert type(s) is str s = s.replace("\n", " ") s = s.replace("\t", " ") - s = re.sub("/\*.*?\*/", " ", s) + s = re.sub(r"/\*.*?\*/", " ", s) s = re.sub(" {2,}", " ", s) return s.strip() @@ -183,7 +183,8 @@ def parse_function_call_and_arguments(function_name, function_call): if char == "<" and next_char not in [" ", "<", "="] and prev_char not in [" ", "<"]: open_template_arguments += 1 continue - if char == ">" and next_char not in [" ", ">", "="] and prev_char not in [" ", ">"] and open_template_arguments > 0: + if char == ">" and next_char not in [" ", ">", "="] and prev_char not in [" ", + ">"] and open_template_arguments > 0: open_template_arguments -= 1 if open_template_arguments > 0: continue @@ -256,10 +257,10 @@ def count_format_specifiers(format_string): def main(): parser = argparse.ArgumentParser(description="This program checks that the number of arguments passed " - "to a variadic format string function matches the number of format " - "specifiers in the format string.") + "to a variadic format string function matches the number of format " + "specifiers in the format string.") parser.add_argument("--skip-arguments", type=int, help="number of arguments before the format string " - "argument (e.g. 1 in the case of fprintf)", default=0) + "argument (e.g. 1 in the case of fprintf)", default=0) parser.add_argument("function_name", help="function name (e.g. fprintf)", default=None) parser.add_argument("file", nargs="*", help="C++ source code file (e.g. foo.cpp)") args = parser.parse_args() @@ -273,14 +274,18 @@ def main(): continue if len(parts) < 3 + args.skip_arguments: exit_code = 1 - print("{}: Could not parse function call string \"{}(...)\": {}".format(f.name, args.function_name, relevant_function_call_str)) + print("{}: Could not parse function call string \"{}(...)\": {}".format(f.name, args.function_name, + relevant_function_call_str)) continue argument_count = len(parts) - 3 - args.skip_arguments format_str = parse_string_content(parts[1 + args.skip_arguments]) format_specifier_count = count_format_specifiers(format_str) if format_specifier_count != argument_count: exit_code = 1 - print("{}: Expected {} argument(s) after format string but found {} argument(s): {}".format(f.name, format_specifier_count, argument_count, relevant_function_call_str)) + print("{}: Expected {} argument(s) after format string but found {} argument(s): {}".format(f.name, + format_specifier_count, + argument_count, + relevant_function_call_str)) continue sys.exit(exit_code) diff --git a/test/lint/lint-python.sh b/test/lint/lint-python.sh index 565d73513c..8c6ff13f43 100755 --- a/test/lint/lint-python.sh +++ b/test/lint/lint-python.sh @@ -9,77 +9,77 @@ export LC_ALL=C enabled=( - E101 # indentation contains mixed spaces and tabs - E112 # expected an indented block - E113 # unexpected indentation - E115 # expected an indented block (comment) - E116 # unexpected indentation (comment) - E125 # continuation line with same indent as next logical line - E129 # visually indented line with same indent as next logical line - E131 # continuation line unaligned for hanging indent - E133 # closing bracket is missing indentation - E223 # tab before operator - E224 # tab after operator - E242 # tab after ',' - E266 # too many leading '#' for block comment - E271 # multiple spaces after keyword - E272 # multiple spaces before keyword - E273 # tab after keyword - E274 # tab before keyword - E275 # missing whitespace after keyword - E304 # blank lines found after function decorator - E306 # expected 1 blank line before a nested definition - E401 # multiple imports on one line - E402 # module level import not at top of file - E502 # the backslash is redundant between brackets - E701 # multiple statements on one line (colon) - E702 # multiple statements on one line (semicolon) - E703 # statement ends with a semicolon - E711 # comparison to None should be 'if cond is None:' - E714 # test for object identity should be "is not" - E721 # do not compare types, use "isinstance()" - E741 # do not use variables named "l", "O", or "I" - E742 # do not define classes named "l", "O", or "I" - E743 # do not define functions named "l", "O", or "I" - E901 # SyntaxError: invalid syntax - E902 # TokenError: EOF in multi-line string - F401 # module imported but unused - F402 # import module from line N shadowed by loop variable - F403 # 'from foo_module import *' used; unable to detect undefined names - F404 # future import(s) name after other statements - F405 # foo_function may be undefined, or defined from star imports: bar_module - F406 # "from module import *" only allowed at module level - F407 # an undefined __future__ feature name was imported - F601 # dictionary key name repeated with different values - F602 # dictionary key variable name repeated with different values - F621 # too many expressions in an assignment with star-unpacking - F622 # two or more starred expressions in an assignment (a, *b, *c = d) - F631 # assertion test is a tuple, which are always True - F701 # a break statement outside of a while or for loop - F702 # a continue statement outside of a while or for loop - F703 # a continue statement in a finally block in a loop - F704 # a yield or yield from statement outside of a function - F705 # a return statement with arguments inside a generator - F706 # a return statement outside of a function/method - F707 # an except: block as not the last exception handler - F811 # redefinition of unused name from line N - F812 # list comprehension redefines 'foo' from line N - F821 # undefined name 'Foo' - F822 # undefined name name in __all__ - F823 # local variable name … referenced before assignment - F831 # duplicate argument name in function definition - F841 # local variable 'foo' is assigned to but never used - W191 # indentation contains tabs - W291 # trailing whitespace - W292 # no newline at end of file - W293 # blank line contains whitespace - W504 # line break after binary operator - W601 # .has_key() is deprecated, use "in" - W602 # deprecated form of raising exception - W603 # "<>" is deprecated, use "!=" - W604 # backticks are deprecated, use "repr()" - W605 # invalid escape sequence "x" - W606 # 'async' and 'await' are reserved keywords starting with Python 3.7 + E101 # indentation contains mixed spaces and tabs + E112 # expected an indented block + E113 # unexpected indentation + E115 # expected an indented block (comment) + E116 # unexpected indentation (comment) + E125 # continuation line with same indent as next logical line + E129 # visually indented line with same indent as next logical line + E131 # continuation line unaligned for hanging indent + E133 # closing bracket is missing indentation + E223 # tab before operator + E224 # tab after operator + E242 # tab after ',' + E266 # too many leading '#' for block comment + E271 # multiple spaces after keyword + E272 # multiple spaces before keyword + E273 # tab after keyword + E274 # tab before keyword + E275 # missing whitespace after keyword + E304 # blank lines found after function decorator + E306 # expected 1 blank line before a nested definition + E401 # multiple imports on one line + E402 # module level import not at top of file + E502 # the backslash is redundant between brackets + E701 # multiple statements on one line (colon) + E702 # multiple statements on one line (semicolon) + E703 # statement ends with a semicolon + E711 # comparison to None should be 'if cond is None:' + E714 # test for object identity should be "is not" + E721 # do not compare types, use "isinstance()" + E722 # do not use bare 'except' + E742 # do not define classes named "l", "O", or "I" + E743 # do not define functions named "l", "O", or "I" + E901 # SyntaxError: invalid syntax + E902 # TokenError: EOF in multi-line string + F401 # module imported but unused + F402 # import module from line N shadowed by loop variable + F403 # 'from foo_module import *' used; unable to detect undefined names + F404 # future import(s) name after other statements + F405 # foo_function may be undefined, or defined from star imports: bar_module + F406 # "from module import *" only allowed at module level + F407 # an undefined __future__ feature name was imported + F601 # dictionary key name repeated with different values + F602 # dictionary key variable name repeated with different values + F621 # too many expressions in an assignment with star-unpacking + F622 # two or more starred expressions in an assignment (a, *b, *c = d) + F631 # assertion test is a tuple, which are always True + F632 # use ==/!= to compare str, bytes, and int literals + F701 # a break statement outside of a while or for loop + F702 # a continue statement outside of a while or for loop + F703 # a continue statement in a finally block in a loop + F704 # a yield or yield from statement outside of a function + F705 # a return statement with arguments inside a generator + F706 # a return statement outside of a function/method + F707 # an except: block as not the last exception handler + F811 # redefinition of unused name from line N + F812 # list comprehension redefines 'foo' from line N + F821 # undefined name 'Foo' + F822 # undefined name name in __all__ + F823 # local variable name … referenced before assignment + F831 # duplicate argument name in function definition + F841 # local variable 'foo' is assigned to but never used + W191 # indentation contains tabs + W291 # trailing whitespace + W292 # no newline at end of file + W293 # blank line contains whitespace + W601 # .has_key() is deprecated, use "in" + W602 # deprecated form of raising exception + W603 # "<>" is deprecated, use "!=" + W604 # backticks are deprecated, use "repr()" + W605 # invalid escape sequence "x" + W606 # 'async' and 'await' are reserved keywords starting with Python 3.7 ) if ! command -v flake8 > /dev/null; then diff --git a/test/util/data/blanktxv1.json b/test/util/data/blanktxv1.json index 3d5a1cccae..6c53dfb7d6 100644 --- a/test/util/data/blanktxv1.json +++ b/test/util/data/blanktxv1.json @@ -1,14 +1,14 @@ { - "txid": "d21633ba23f70118185227be58a63527675641ad37967e2aa461559f577aec43", - "hash": "d21633ba23f70118185227be58a63527675641ad37967e2aa461559f577aec43", - "version": 1, - "size": 10, - "vsize": 10, - "weight": 40, - "locktime": 0, - "vin": [ - ], - "vout": [ - ], - "hex": "01000000000000000000" + "txid": "d21633ba23f70118185227be58a63527675641ad37967e2aa461559f577aec43", + "hash": "d21633ba23f70118185227be58a63527675641ad37967e2aa461559f577aec43", + "version": 1, + "size": 10, + "vsize": 10, + "weight": 40, + "locktime": 0, + "vin": [ + ], + "vout": [ + ], + "hex": "01000000000000000000" } diff --git a/test/util/data/blanktxv2.json b/test/util/data/blanktxv2.json index 8374a34adc..52e8ed2e5a 100644 --- a/test/util/data/blanktxv2.json +++ b/test/util/data/blanktxv2.json @@ -1,14 +1,14 @@ { - "txid": "4ebd325a4b394cff8c57e8317ccf5a8d0e2bdf1b8526f8aad6c8e43d8240621a", - "hash": "4ebd325a4b394cff8c57e8317ccf5a8d0e2bdf1b8526f8aad6c8e43d8240621a", - "version": 2, - "size": 10, - "vsize": 10, - "weight": 40, - "locktime": 0, - "vin": [ - ], - "vout": [ - ], - "hex": "02000000000000000000" + "txid": "4ebd325a4b394cff8c57e8317ccf5a8d0e2bdf1b8526f8aad6c8e43d8240621a", + "hash": "4ebd325a4b394cff8c57e8317ccf5a8d0e2bdf1b8526f8aad6c8e43d8240621a", + "version": 2, + "size": 10, + "vsize": 10, + "weight": 40, + "locktime": 0, + "vin": [ + ], + "vout": [ + ], + "hex": "02000000000000000000" } diff --git a/test/util/data/defi-util-test.json b/test/util/data/defi-util-test.json index 35a9cb034f..2c9ea1940b 100644 --- a/test/util/data/defi-util-test.json +++ b/test/util/data/defi-util-test.json @@ -1,523 +1,799 @@ [ - { "exec": "./defi-tx", - "args": ["-create", "nversion=1"], + { + "exec": "./defi-tx", + "args": [ + "-create", + "nversion=1" + ], "output_cmp": "blanktxv1.hex", "description": "Creates a blank v1 transaction" }, - { "exec": "./defi-tx", - "args": ["-json","-create", "nversion=1"], + { + "exec": "./defi-tx", + "args": [ + "-json", + "-create", + "nversion=1" + ], "output_cmp": "blanktxv1.json", "description": "Creates a blank v1 transaction (output in json)" }, - { "exec": "./defi-tx", - "args": ["-"], + { + "exec": "./defi-tx", + "args": [ + "-" + ], "input": "blanktxv2.hex", "output_cmp": "blanktxv2.hex", "description": "Creates a blank transaction when nothing is piped into defi-tx" }, - { "exec": "./defi-tx", - "args": ["-json","-create"], + { + "exec": "./defi-tx", + "args": [ + "-json", + "-create" + ], "output_cmp": "blanktxv2.json", "description": "Creates a blank transaction (output in json)" }, - { "exec": "./defi-tx", - "args": ["-json","-"], + { + "exec": "./defi-tx", + "args": [ + "-json", + "-" + ], "input": "blanktxv2.hex", "output_cmp": "blanktxv2.json", "description": "Creates a blank transaction when nothing is piped into defi-tx (output in json)" }, - { "exec": "./defi-tx", - "args": ["-create", "nversion=1foo"], + { + "exec": "./defi-tx", + "args": [ + "-create", + "nversion=1foo" + ], "return_code": 1, "error_txt": "error: Invalid TX version requested", "description": "Tests the check for invalid nversion value" }, - { "exec": "./defi-tx", - "args": ["-", "delin=1"], + { + "exec": "./defi-tx", + "args": [ + "-", + "delin=1" + ], "input": "tx394b54bb.hex", "output_cmp": "tt-delin1-out.hex", "description": "Deletes a single input from a transaction" }, - { "exec": "./defi-tx", - "args": ["-json", "-", "delin=1"], + { + "exec": "./defi-tx", + "args": [ + "-json", + "-", + "delin=1" + ], "input": "tx394b54bb.hex", "output_cmp": "tt-delin1-out.json", "description": "Deletes a single input from a transaction (output in json)" }, - { "exec": "./defi-tx", - "args": ["-", "delin=31"], + { + "exec": "./defi-tx", + "args": [ + "-", + "delin=31" + ], "input": "tx394b54bb.hex", "return_code": 1, "error_txt": "error: Invalid TX input index '31'", "description": "Attempts to delete an input with a bad index from a transaction. Expected to fail." }, - { "exec": "./defi-tx", - "args": ["-", "delin=1foo"], + { + "exec": "./defi-tx", + "args": [ + "-", + "delin=1foo" + ], "input": "tx394b54bb.hex", "return_code": 1, "error_txt": "error: Invalid TX input index", "description": "Tests the check for an invalid input index with delin" }, - { "exec": "./defi-tx", - "args": ["-", "delout=1"], + { + "exec": "./defi-tx", + "args": [ + "-", + "delout=1" + ], "input": "tx394b54bb.hex", "output_cmp": "tt-delout1-out.hex", "description": "Deletes a single output from a transaction" }, - { "exec": "./defi-tx", - "args": ["-json", "-", "delout=1"], + { + "exec": "./defi-tx", + "args": [ + "-json", + "-", + "delout=1" + ], "input": "tx394b54bb.hex", "output_cmp": "tt-delout1-out.json", "description": "Deletes a single output from a transaction (output in json)" }, - { "exec": "./defi-tx", - "args": ["-", "delout=2"], + { + "exec": "./defi-tx", + "args": [ + "-", + "delout=2" + ], "input": "tx394b54bb.hex", "return_code": 1, "error_txt": "error: Invalid TX output index '2'", "description": "Attempts to delete an output with a bad index from a transaction. Expected to fail." }, - { "exec": "./defi-tx", - "args": ["-", "delout=1foo"], + { + "exec": "./defi-tx", + "args": [ + "-", + "delout=1foo" + ], "input": "tx394b54bb.hex", "return_code": 1, "error_txt": "error: Invalid TX output index", "description": "Tests the check for an invalid output index with delout" }, - { "exec": "./defi-tx", - "args": ["-", "locktime=317000"], + { + "exec": "./defi-tx", + "args": [ + "-", + "locktime=317000" + ], "input": "tx394b54bb.hex", "output_cmp": "tt-locktime317000-out.hex", "description": "Adds an nlocktime to a transaction" }, - { "exec": "./defi-tx", - "args": ["-json", "-", "locktime=317000"], + { + "exec": "./defi-tx", + "args": [ + "-json", + "-", + "locktime=317000" + ], "input": "tx394b54bb.hex", "output_cmp": "tt-locktime317000-out.json", "description": "Adds an nlocktime to a transaction (output in json)" }, - { "exec": "./defi-tx", - "args": ["-create", "locktime=317000foo"], + { + "exec": "./defi-tx", + "args": [ + "-create", + "locktime=317000foo" + ], "return_code": 1, "error_txt": "error: Invalid TX locktime requested", "description": "Tests the check for invalid locktime value" }, - { "exec": "./defi-tx", - "args": - ["-create", - "in=Z897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0"], + { + "exec": "./defi-tx", + "args": [ + "-create", + "in=Z897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0" + ], "return_code": 1, "error_txt": "error: invalid TX input txid", "description": "Tests the check for an invalid txid invalid hex" }, - { "exec": "./defi-tx", - "args": - ["-create", - "in=5897de6bd6:0"], + { + "exec": "./defi-tx", + "args": [ + "-create", + "in=5897de6bd6:0" + ], "return_code": 1, "error_txt": "error: invalid TX input txid", "description": "Tests the check for an invalid txid valid hex but too short" }, - { "exec": "./defi-tx", - "args": - ["-create", - "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f12:0"], + { + "exec": "./defi-tx", + "args": [ + "-create", + "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f12:0" + ], "return_code": 1, "error_txt": "error: invalid TX input txid", "description": "Tests the check for an invalid txid valid hex but too long" }, - { "exec": "./defi-tx", - "args": - ["-create", - "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0", - "replaceable=0foo"], + { + "exec": "./defi-tx", + "args": [ + "-create", + "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0", + "replaceable=0foo" + ], "return_code": 1, "error_txt": "error: Invalid TX input index", "description": "Tests the check for an invalid input index with replaceable" }, - { "exec": "./defi-tx", - "args": - ["-create", - "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0x"], + { + "exec": "./defi-tx", + "args": [ + "-create", + "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0x" + ], "return_code": 1, "error_txt": "error: invalid TX input vout", "description": "Tests the check for an invalid vout value when adding an input" }, - { "exec": "./defi-tx", - "args": - ["-create", - "outaddr=1"], + { + "exec": "./defi-tx", + "args": [ + "-create", + "outaddr=1" + ], "return_code": 1, "error_txt": "error: TX output missing or too many separators", "description": "Malformed outaddr argument (no address specified). Expected to fail." }, - { "exec": "./defi-tx", - "args": - ["-create", - "outaddr=1:13tuJJDR2RgArmgfv6JScSdreahzgc4T6o:garbage"], + { + "exec": "./defi-tx", + "args": [ + "-create", + "outaddr=1:13tuJJDR2RgArmgfv6JScSdreahzgc4T6o:garbage" + ], "return_code": 1, "error_txt": "error: TX output missing or too many separators", "description": "Malformed outaddr argument (too many separators). Expected to fail." }, - { "exec": "./defi-tx", - "args": - ["-create", - "outpubkey=0"], + { + "exec": "./defi-tx", + "args": [ + "-create", + "outpubkey=0" + ], "return_code": 1, "error_txt": "error: TX output missing or too many separators", "description": "Malformed outpubkey argument (no pubkey specified). Expected to fail." }, - { "exec": "./defi-tx", - "args": - ["-create", - "outpubkey=0:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:W:non53nse"], + { + "exec": "./defi-tx", + "args": [ + "-create", + "outpubkey=0:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:W:non53nse" + ], "return_code": 1, "error_txt": "error: TX output missing or too many separators", "description": "Malformed outpubkey argument (too many separators). Expected to fail." }, - { "exec": "./defi-tx", - "args": - ["-create", - "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0", - "in=bf829c6bcf84579331337659d31f89dfd138f7f7785802d5501c92333145ca7c:18", - "in=22a6f904655d53ae2ff70e701a0bbd90aa3975c0f40bfc6cc996a9049e31cdfc:1", - "outaddr=0.18:13tuJJDR2RgArmgfv6JScSdreahzgc4T6o", - "outaddr=4:1P8yWvZW8jVihP1bzHeqfE4aoXNX8AVa46"], + { + "exec": "./defi-tx", + "args": [ + "-create", + "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0", + "in=bf829c6bcf84579331337659d31f89dfd138f7f7785802d5501c92333145ca7c:18", + "in=22a6f904655d53ae2ff70e701a0bbd90aa3975c0f40bfc6cc996a9049e31cdfc:1", + "outaddr=0.18:13tuJJDR2RgArmgfv6JScSdreahzgc4T6o", + "outaddr=4:1P8yWvZW8jVihP1bzHeqfE4aoXNX8AVa46" + ], "output_cmp": "txcreate1.hex", "description": "Creates a new transaction with three inputs and two outputs" }, - { "exec": "./defi-tx", - "args": - ["-json", - "-create", - "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0", - "in=bf829c6bcf84579331337659d31f89dfd138f7f7785802d5501c92333145ca7c:18", - "in=22a6f904655d53ae2ff70e701a0bbd90aa3975c0f40bfc6cc996a9049e31cdfc:1", - "outaddr=0.18:13tuJJDR2RgArmgfv6JScSdreahzgc4T6o", - "outaddr=4:1P8yWvZW8jVihP1bzHeqfE4aoXNX8AVa46"], + { + "exec": "./defi-tx", + "args": [ + "-json", + "-create", + "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0", + "in=bf829c6bcf84579331337659d31f89dfd138f7f7785802d5501c92333145ca7c:18", + "in=22a6f904655d53ae2ff70e701a0bbd90aa3975c0f40bfc6cc996a9049e31cdfc:1", + "outaddr=0.18:13tuJJDR2RgArmgfv6JScSdreahzgc4T6o", + "outaddr=4:1P8yWvZW8jVihP1bzHeqfE4aoXNX8AVa46" + ], "output_cmp": "txcreate1.json", "description": "Creates a new transaction with three inputs and two outputs (output in json)" }, - { "exec": "./defi-tx", - "args": ["-create", "outscript=0:"], + { + "exec": "./defi-tx", + "args": [ + "-create", + "outscript=0:" + ], "output_cmp": "txcreate2.hex", "description": "Creates a new transaction with a single empty output script" }, - { "exec": "./defi-tx", - "args": ["-json", "-create", "outscript=0:"], + { + "exec": "./defi-tx", + "args": [ + "-json", + "-create", + "outscript=0:" + ], "output_cmp": "txcreate2.json", "description": "Creates a new transaction with a single empty output script (output in json)" }, - { "exec": "./defi-tx", - "args": ["02000000000100000000000000000000000000"], + { + "exec": "./defi-tx", + "args": [ + "02000000000100000000000000000000000000" + ], "output_cmp": "txcreate2.hex", "description": "Parses a transaction with no inputs and a single output script" }, - { "exec": "./defi-tx", - "args": ["-json", "02000000000100000000000000000000000000"], + { + "exec": "./defi-tx", + "args": [ + "-json", + "02000000000100000000000000000000000000" + ], "output_cmp": "txcreate2.json", "description": "Parses a transaction with no inputs and a single output script (output in json)" }, - { "exec": "./defi-tx", - "args": ["-create", "outscript=0:OP_DROP", "nversion=1"], + { + "exec": "./defi-tx", + "args": [ + "-create", + "outscript=0:OP_DROP", + "nversion=1" + ], "output_cmp": "txcreatescript1.hex", "description": "Create a new transaction with a single output script (OP_DROP)" }, - { "exec": "./defi-tx", - "args": ["-json", "-create", "outscript=0:OP_DROP", "nversion=1"], + { + "exec": "./defi-tx", + "args": [ + "-json", + "-create", + "outscript=0:OP_DROP", + "nversion=1" + ], "output_cmp": "txcreatescript1.json", "description": "Create a new transaction with a single output script (OP_DROP) (output as json)" }, - { "exec": "./defi-tx", - "args": ["-create", "outscript=0:OP_DROP:S", "nversion=1"], + { + "exec": "./defi-tx", + "args": [ + "-create", + "outscript=0:OP_DROP:S", + "nversion=1" + ], "output_cmp": "txcreatescript2.hex", "description": "Create a new transaction with a single output script (OP_DROP) in a P2SH" }, - { "exec": "./defi-tx", - "args": ["-json", "-create", "outscript=0:OP_DROP:S", "nversion=1"], + { + "exec": "./defi-tx", + "args": [ + "-json", + "-create", + "outscript=0:OP_DROP:S", + "nversion=1" + ], "output_cmp": "txcreatescript2.json", "description": "Create a new transaction with a single output script (OP_DROP) in a P2SH (output as json)" }, - { "exec": "./defi-tx", - "args": ["-create", "outscript=0:OP_DROP:W", "nversion=1"], + { + "exec": "./defi-tx", + "args": [ + "-create", + "outscript=0:OP_DROP:W", + "nversion=1" + ], "output_cmp": "txcreatescript3.hex", "description": "Create a new transaction with a single output script (OP_DROP) in a P2WSH" }, - { "exec": "./defi-tx", - "args": ["-json", "-create", "outscript=0:OP_DROP:W", "nversion=1"], + { + "exec": "./defi-tx", + "args": [ + "-json", + "-create", + "outscript=0:OP_DROP:W", + "nversion=1" + ], "output_cmp": "txcreatescript3.json", "description": "Create a new transaction with a single output script (OP_DROP) in a P2WSH (output as json)" }, - { "exec": "./defi-tx", - "args": ["-create", "outscript=0:OP_DROP:WS", "nversion=1"], + { + "exec": "./defi-tx", + "args": [ + "-create", + "outscript=0:OP_DROP:WS", + "nversion=1" + ], "output_cmp": "txcreatescript4.hex", "description": "Create a new transaction with a single output script (OP_DROP) in a P2WSH, wrapped in a P2SH" }, - { "exec": "./defi-tx", - "args": ["-json", "-create", "outscript=0:OP_DROP:WS", "nversion=1"], + { + "exec": "./defi-tx", + "args": [ + "-json", + "-create", + "outscript=0:OP_DROP:WS", + "nversion=1" + ], "output_cmp": "txcreatescript4.json", "description": "Create a new transaction with a single output script (OP_DROP) in a P2SH, wrapped in a P2SH (output as json)" }, - { "exec": "./defi-tx", - "args": - ["-create", "nversion=1", - "in=4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485:0", - "set=privatekeys:[\"5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf\"]", - "set=prevtxs:[{\"txid\":\"4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485\",\"vout\":0,\"scriptPubKey\":\"76a91491b24bf9f5288532960ac687abb035127b1d28a588ac\"}]", - "sign=ALL", - "outaddr=0.001:193P6LtvS4nCnkDvM9uXn1gsSRqh4aDAz7"], + { + "exec": "./defi-tx", + "args": [ + "-create", + "nversion=1", + "in=4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485:0", + "set=privatekeys:[\"5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf\"]", + "set=prevtxs:[{\"txid\":\"4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485\",\"vout\":0,\"scriptPubKey\":\"76a91491b24bf9f5288532960ac687abb035127b1d28a588ac\"}]", + "sign=ALL", + "outaddr=0.001:193P6LtvS4nCnkDvM9uXn1gsSRqh4aDAz7" + ], "output_cmp": "txcreatesignv1.hex", "description": "Creates a new v1 transaction with a single input and a single output, and then signs the transaction" }, - { "exec": "./defi-tx", - "args": - ["-json", - "-create", "nversion=1", - "in=4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485:0", - "set=privatekeys:[\"5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf\"]", - "set=prevtxs:[{\"txid\":\"4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485\",\"vout\":0,\"scriptPubKey\":\"76a91491b24bf9f5288532960ac687abb035127b1d28a588ac\"}]", - "sign=ALL", - "outaddr=0.001:193P6LtvS4nCnkDvM9uXn1gsSRqh4aDAz7"], + { + "exec": "./defi-tx", + "args": [ + "-json", + "-create", + "nversion=1", + "in=4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485:0", + "set=privatekeys:[\"5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf\"]", + "set=prevtxs:[{\"txid\":\"4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485\",\"vout\":0,\"scriptPubKey\":\"76a91491b24bf9f5288532960ac687abb035127b1d28a588ac\"}]", + "sign=ALL", + "outaddr=0.001:193P6LtvS4nCnkDvM9uXn1gsSRqh4aDAz7" + ], "output_cmp": "txcreatesignv1.json", "description": "Creates a new v1 transaction with a single input and a single output, and then signs the transaction (output in json)" }, - { "exec": "./defi-tx", - "args": - ["-create", + { + "exec": "./defi-tx", + "args": [ + "-create", "in=4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485:0", "set=privatekeys:[\"5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf\"]", "set=prevtxs:[{\"txid\":\"4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485\",\"vout\":0,\"scriptPubKey\":\"76a91491b24bf9f5288532960ac687abb035127b1d28a588ac\"}]", "sign=ALL", - "outaddr=0.001:193P6LtvS4nCnkDvM9uXn1gsSRqh4aDAz7"], + "outaddr=0.001:193P6LtvS4nCnkDvM9uXn1gsSRqh4aDAz7" + ], "output_cmp": "txcreatesignv2.hex", "description": "Creates a new transaction with a single input and a single output, and then signs the transaction" }, - { "exec": "./defi-tx", - "args": - ["-create", + { + "exec": "./defi-tx", + "args": [ + "-create", "in=4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485:0", "set=privatekeys:[\"5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf\"]", "set=prevtxs:[{\"txid\":\"4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485\",\"vout\":\"0foo\",\"scriptPubKey\":\"76a91491b24bf9f5288532960ac687abb035127b1d28a588ac\"}]", "sign=ALL", - "outaddr=0.001:193P6LtvS4nCnkDvM9uXn1gsSRqh4aDAz7"], + "outaddr=0.001:193P6LtvS4nCnkDvM9uXn1gsSRqh4aDAz7" + ], "return_code": 1, "error_txt": "error: prevtxs internal object typecheck fail", "description": "Tests the check for invalid vout index in prevtxs for sign" }, - { "exec": "./defi-tx", - "args": - ["-create", + { + "exec": "./defi-tx", + "args": [ + "-create", "in=4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485:0", "set=privatekeys:[\"5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf\"]", "set=prevtxs:[{\"txid\":\"Zd49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59412\",\"vout\":0,\"scriptPubKey\":\"76a91491b24bf9f5288532960ac687abb035127b1d28a588ac\"}]", "sign=ALL", - "outaddr=0.001:193P6LtvS4nCnkDvM9uXn1gsSRqh4aDAz7"], + "outaddr=0.001:193P6LtvS4nCnkDvM9uXn1gsSRqh4aDAz7" + ], "return_code": 1, "error_txt": "error: txid must be hexadecimal string (not 'Zd49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59412')", "description": "Tests the check for invalid txid due to invalid hex" }, - { "exec": "./defi-tx", - "args": - ["-create", + { + "exec": "./defi-tx", + "args": [ + "-create", "in=4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485:0", "set=privatekeys:[\"5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf\"]", "set=prevtxs:[{\"txid\":\"4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc594\",\"vout\":0,\"scriptPubKey\":\"76a91491b24bf9f5288532960ac687abb035127b1d28a588ac\"}]", "sign=ALL", - "outaddr=0.001:193P6LtvS4nCnkDvM9uXn1gsSRqh4aDAz7"], + "outaddr=0.001:193P6LtvS4nCnkDvM9uXn1gsSRqh4aDAz7" + ], "return_code": 1, "error_txt": "error: txid must be hexadecimal string (not '4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc594')", "description": "Tests the check for invalid txid valid hex, but too short" }, - { "exec": "./defi-tx", - "args": - ["-create", + { + "exec": "./defi-tx", + "args": [ + "-create", "in=4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485:0", "set=privatekeys:[\"5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf\"]", "set=prevtxs:[{\"txid\":\"4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc5948512\",\"vout\":0,\"scriptPubKey\":\"76a91491b24bf9f5288532960ac687abb035127b1d28a588ac\"}]", "sign=ALL", - "outaddr=0.001:193P6LtvS4nCnkDvM9uXn1gsSRqh4aDAz7"], + "outaddr=0.001:193P6LtvS4nCnkDvM9uXn1gsSRqh4aDAz7" + ], "return_code": 1, "error_txt": "error: txid must be hexadecimal string (not '4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc5948512')", "description": "Tests the check for invalid txid valid hex, but too long" }, - { "exec": "./defi-tx", - "args": - ["-create", "outpubkey=0:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397", "nversion=1"], + { + "exec": "./defi-tx", + "args": [ + "-create", + "outpubkey=0:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397", + "nversion=1" + ], "output_cmp": "txcreateoutpubkey1.hex", "description": "Creates a new transaction with a single pay-to-pubkey output" }, - { "exec": "./defi-tx", - "args": - ["-json", "-create", "outpubkey=0:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397", "nversion=1"], + { + "exec": "./defi-tx", + "args": [ + "-json", + "-create", + "outpubkey=0:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397", + "nversion=1" + ], "output_cmp": "txcreateoutpubkey1.json", "description": "Creates a new transaction with a single pay-to-pubkey output (output as json)" }, - { "exec": "./defi-tx", - "args": - ["-create", "outpubkey=0:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:W", "nversion=1"], + { + "exec": "./defi-tx", + "args": [ + "-create", + "outpubkey=0:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:W", + "nversion=1" + ], "output_cmp": "txcreateoutpubkey2.hex", "description": "Creates a new transaction with a single pay-to-witness-pubkey output" }, - { "exec": "./defi-tx", - "args": - ["-json", "-create", "outpubkey=0:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:W", "nversion=1"], + { + "exec": "./defi-tx", + "args": [ + "-json", + "-create", + "outpubkey=0:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:W", + "nversion=1" + ], "output_cmp": "txcreateoutpubkey2.json", "description": "Creates a new transaction with a single pay-to-witness-pubkey output (output as json)" }, - { "exec": "./defi-tx", - "args": - ["-create", "outpubkey=0:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:WS", "nversion=1"], + { + "exec": "./defi-tx", + "args": [ + "-create", + "outpubkey=0:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:WS", + "nversion=1" + ], "output_cmp": "txcreateoutpubkey3.hex", "description": "Creates a new transaction with a single pay-to-witness-pubkey, wrapped in P2SH output" }, - { "exec": "./defi-tx", - "args": - ["-json", "-create", "outpubkey=0:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:WS", "nversion=1"], + { + "exec": "./defi-tx", + "args": [ + "-json", + "-create", + "outpubkey=0:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:WS", + "nversion=1" + ], "output_cmp": "txcreateoutpubkey3.json", "description": "Creates a new transaction with a single pay-to-pub-key output, wrapped in P2SH (output as json)" }, - { "exec": "./defi-tx", - "args": - ["-json", "-create", "outpubkey=0:047d1368ba7ae01c94bc32293efd70bd7e3be7aa7912d07d0b1c659c1008d179b8642f5fb90f47580feb29f045e216ff5a4716d3a0fed36da414d332046303c44a:WS", "nversion=1"], + { + "exec": "./defi-tx", + "args": [ + "-json", + "-create", + "outpubkey=0:047d1368ba7ae01c94bc32293efd70bd7e3be7aa7912d07d0b1c659c1008d179b8642f5fb90f47580feb29f045e216ff5a4716d3a0fed36da414d332046303c44a:WS", + "nversion=1" + ], "return_code": 1, "error_txt": "error: Uncompressed pubkeys are not useable for SegWit outputs", "description": "Creates a new transaction with a single pay-to-pub-key output, wrapped in P2SH (output as json)" }, - { "exec": "./defi-tx", - "args": - ["-create", - "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0", - "outdata=4:badhexdata"], + { + "exec": "./defi-tx", + "args": [ + "-create", + "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0", + "outdata=4:badhexdata" + ], "return_code": 1, "error_txt": "error: invalid TX output data", "description": "Attempts to create a new transaction with one input and an output with malformed hex data. Expected to fail" }, - { "exec": "./defi-tx", - "args": - ["-create", - "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0", - "outdata=badhexdata"], + { + "exec": "./defi-tx", + "args": [ + "-create", + "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0", + "outdata=badhexdata" + ], "return_code": 1, "error_txt": "error: invalid TX output data", "description": "Attempts to create a new transaction with one input and an output with no value and malformed hex data. Expected to fail" }, - { "exec": "./defi-tx", - "args": - ["-create", - "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0", - "outaddr=0.18:13tuJJDR2RgArmgfv6JScSdreahzgc4T6o", - "outdata=4:54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e"], + { + "exec": "./defi-tx", + "args": [ + "-create", + "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0", + "outaddr=0.18:13tuJJDR2RgArmgfv6JScSdreahzgc4T6o", + "outdata=4:54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e" + ], "output_cmp": "txcreatedata1.hex", "description": "Creates a new transaction with one input, one address output and one data output" }, - { "exec": "./defi-tx", - "args": - ["-json", - "-create", "nversion=1", - "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0", - "outaddr=0.18:13tuJJDR2RgArmgfv6JScSdreahzgc4T6o", - "outdata=4:54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e"], + { + "exec": "./defi-tx", + "args": [ + "-json", + "-create", + "nversion=1", + "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0", + "outaddr=0.18:13tuJJDR2RgArmgfv6JScSdreahzgc4T6o", + "outdata=4:54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e" + ], "output_cmp": "txcreatedata1.json", "description": "Creates a new v1 transaction with one input, one address output and one data output (output in json)" }, - { "exec": "./defi-tx", - "args": - ["-create", - "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0", - "outaddr=0.18:13tuJJDR2RgArmgfv6JScSdreahzgc4T6o", - "outdata=54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e"], + { + "exec": "./defi-tx", + "args": [ + "-create", + "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0", + "outaddr=0.18:13tuJJDR2RgArmgfv6JScSdreahzgc4T6o", + "outdata=54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e" + ], "output_cmp": "txcreatedata2.hex", "description": "Creates a new transaction with one input, one address output and one data (zero value) output" }, - { "exec": "./defi-tx", - "args": - ["-json", - "-create", - "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0", - "outaddr=0.18:13tuJJDR2RgArmgfv6JScSdreahzgc4T6o", - "outdata=54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e"], + { + "exec": "./defi-tx", + "args": [ + "-json", + "-create", + "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0", + "outaddr=0.18:13tuJJDR2RgArmgfv6JScSdreahzgc4T6o", + "outdata=54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e" + ], "output_cmp": "txcreatedata2.json", "description": "Creates a new transaction with one input, one address output and one data (zero value) output (output in json)" }, - { "exec": "./defi-tx", - "args": - ["-create", - "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0:4294967293", - "outaddr=0.18:13tuJJDR2RgArmgfv6JScSdreahzgc4T6o"], + { + "exec": "./defi-tx", + "args": [ + "-create", + "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0:4294967293", + "outaddr=0.18:13tuJJDR2RgArmgfv6JScSdreahzgc4T6o" + ], "output_cmp": "txcreatedata_seq0.hex", "description": "Creates a new transaction with one input with sequence number and one address output" }, - { "exec": "./defi-tx", - "args": - ["-json", - "-create", - "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0:4294967293", - "outaddr=0.18:13tuJJDR2RgArmgfv6JScSdreahzgc4T6o"], + { + "exec": "./defi-tx", + "args": [ + "-json", + "-create", + "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0:4294967293", + "outaddr=0.18:13tuJJDR2RgArmgfv6JScSdreahzgc4T6o" + ], "output_cmp": "txcreatedata_seq0.json", "description": "Creates a new transaction with one input with sequence number and one address output (output in json)" }, - { "exec": "./defi-tx", - "args": - ["01000000011f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000fdffffff0180a81201000000001976a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac00000000", - "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0:1"], + { + "exec": "./defi-tx", + "args": [ + "01000000011f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000fdffffff0180a81201000000001976a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac00000000", + "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0:1" + ], "output_cmp": "txcreatedata_seq1.hex", "description": "Adds a new input with sequence number to a transaction" }, - { "exec": "./defi-tx", - "args": - ["-json", - "01000000011f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000fdffffff0180a81201000000001976a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac00000000", - "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0:1"], + { + "exec": "./defi-tx", + "args": [ + "-json", + "01000000011f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000fdffffff0180a81201000000001976a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac00000000", + "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0:1" + ], "output_cmp": "txcreatedata_seq1.json", "description": "Adds a new input with sequence number to a transaction (output in json)" }, - { "exec": "./defi-tx", - "args": ["-create", "outmultisig=1:2:3:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d:02df2089105c77f266fa11a9d33f05c735234075f2e8780824c6b709415f9fb485", "nversion=1"], + { + "exec": "./defi-tx", + "args": [ + "-create", + "outmultisig=1:2:3:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d:02df2089105c77f266fa11a9d33f05c735234075f2e8780824c6b709415f9fb485", + "nversion=1" + ], "output_cmp": "txcreatemultisig1.hex", "description": "Creates a new transaction with a single 2-of-3 multisig output" }, - { "exec": "./defi-tx", - "args": ["-json", "-create", "outmultisig=1:2:3:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d:02df2089105c77f266fa11a9d33f05c735234075f2e8780824c6b709415f9fb485", "nversion=1"], + { + "exec": "./defi-tx", + "args": [ + "-json", + "-create", + "outmultisig=1:2:3:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d:02df2089105c77f266fa11a9d33f05c735234075f2e8780824c6b709415f9fb485", + "nversion=1" + ], "output_cmp": "txcreatemultisig1.json", "description": "Creates a new transaction with a single 2-of-3 multisig output (output in json)" }, - { "exec": "./defi-tx", - "args": ["-create", "outmultisig=1:2:3:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d:02df2089105c77f266fa11a9d33f05c735234075f2e8780824c6b709415f9fb485:S", "nversion=1"], + { + "exec": "./defi-tx", + "args": [ + "-create", + "outmultisig=1:2:3:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d:02df2089105c77f266fa11a9d33f05c735234075f2e8780824c6b709415f9fb485:S", + "nversion=1" + ], "output_cmp": "txcreatemultisig2.hex", "description": "Creates a new transaction with a single 2-of-3 multisig in a P2SH output" }, - { "exec": "./defi-tx", - "args": ["-json", "-create", "outmultisig=1:2:3:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d:02df2089105c77f266fa11a9d33f05c735234075f2e8780824c6b709415f9fb485:S", "nversion=1"], + { + "exec": "./defi-tx", + "args": [ + "-json", + "-create", + "outmultisig=1:2:3:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d:02df2089105c77f266fa11a9d33f05c735234075f2e8780824c6b709415f9fb485:S", + "nversion=1" + ], "output_cmp": "txcreatemultisig2.json", "description": "Creates a new transaction with a single 2-of-3 multisig in a P2SH output (output in json)" }, - { "exec": "./defi-tx", - "args": ["-create", "outmultisig=1:2:3:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d:02df2089105c77f266fa11a9d33f05c735234075f2e8780824c6b709415f9fb485:W", "nversion=1"], + { + "exec": "./defi-tx", + "args": [ + "-create", + "outmultisig=1:2:3:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d:02df2089105c77f266fa11a9d33f05c735234075f2e8780824c6b709415f9fb485:W", + "nversion=1" + ], "output_cmp": "txcreatemultisig3.hex", "description": "Creates a new transaction with a single 2-of-3 multisig in a P2WSH output" }, - { "exec": "./defi-tx", - "args": ["-json", "-create", "outmultisig=1:2:3:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d:02df2089105c77f266fa11a9d33f05c735234075f2e8780824c6b709415f9fb485:W", "nversion=1"], + { + "exec": "./defi-tx", + "args": [ + "-json", + "-create", + "outmultisig=1:2:3:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d:02df2089105c77f266fa11a9d33f05c735234075f2e8780824c6b709415f9fb485:W", + "nversion=1" + ], "output_cmp": "txcreatemultisig3.json", "description": "Creates a new transaction with a single 2-of-3 multisig in a P2WSH output (output in json)" }, - { "exec": "./defi-tx", - "args": ["-create", "outmultisig=1:2:3:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d:02df2089105c77f266fa11a9d33f05c735234075f2e8780824c6b709415f9fb485:WS", "nversion=1"], + { + "exec": "./defi-tx", + "args": [ + "-create", + "outmultisig=1:2:3:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d:02df2089105c77f266fa11a9d33f05c735234075f2e8780824c6b709415f9fb485:WS", + "nversion=1" + ], "output_cmp": "txcreatemultisig4.hex", "description": "Creates a new transaction with a single 2-of-3 multisig in a P2WSH output, wrapped in P2SH" }, - { "exec": "./defi-tx", - "args": ["-json", "-create", "outmultisig=1:2:3:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d:02df2089105c77f266fa11a9d33f05c735234075f2e8780824c6b709415f9fb485:WS", "nversion=1"], + { + "exec": "./defi-tx", + "args": [ + "-json", + "-create", + "outmultisig=1:2:3:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d:02df2089105c77f266fa11a9d33f05c735234075f2e8780824c6b709415f9fb485:WS", + "nversion=1" + ], "output_cmp": "txcreatemultisig4.json", "description": "Creates a new transaction with a single 2-of-3 multisig in a P2WSH output, wrapped in P2SH (output in json)" }, - { "exec": "./defi-tx", - "args": ["-json", "-create", "outmultisig=1:2:3:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d:047d1368ba7ae01c94bc32293efd70bd7e3be7aa7912d07d0b1c659c1008d179b8642f5fb90f47580feb29f045e216ff5a4716d3a0fed36da414d332046303c44a:S"], + { + "exec": "./defi-tx", + "args": [ + "-json", + "-create", + "outmultisig=1:2:3:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d:047d1368ba7ae01c94bc32293efd70bd7e3be7aa7912d07d0b1c659c1008d179b8642f5fb90f47580feb29f045e216ff5a4716d3a0fed36da414d332046303c44a:S" + ], "output_cmp": "txcreatemultisig5.json", "description": "Uncompressed pubkeys should work just fine for non-witness outputs" }, - { "exec": "./defi-tx", - "args": ["-json", "-create", "outmultisig=1:2:3:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d:047d1368ba7ae01c94bc32293efd70bd7e3be7aa7912d07d0b1c659c1008d179b8642f5fb90f47580feb29f045e216ff5a4716d3a0fed36da414d332046303c44a:WS"], + { + "exec": "./defi-tx", + "args": [ + "-json", + "-create", + "outmultisig=1:2:3:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d:047d1368ba7ae01c94bc32293efd70bd7e3be7aa7912d07d0b1c659c1008d179b8642f5fb90f47580feb29f045e216ff5a4716d3a0fed36da414d332046303c44a:WS" + ], "return_code": 1, "error_txt": "error: Uncompressed pubkeys are not useable for SegWit outputs", "description": "Ensure adding witness outputs with uncompressed pubkeys fails" diff --git a/test/util/data/tt-delin1-out.json b/test/util/data/tt-delin1-out.json index 871f0642e8..2bd4a589ab 100644 --- a/test/util/data/tt-delin1-out.json +++ b/test/util/data/tt-delin1-out.json @@ -1,220 +1,220 @@ { - "txid": "81b2035be1da1abe745c6141174a73d151009ec17b3d5ebffa2e177408c50dfd", - "hash": "81b2035be1da1abe745c6141174a73d151009ec17b3d5ebffa2e177408c50dfd", - "version": 1, - "size": 3040, - "vsize": 3040, - "weight": 12160, - "locktime": 0, - "vin": [ - { - "txid": "27871a1a27d833e99cd392a502a647beaaeda6da535417501c76312d52235cfd", - "vout": 332, - "scriptSig": { - "asm": "3046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", - "hex": "493046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" - }, - "sequence": 4294967295 - }, - { - "txid": "752f7f69b915637dc1c2f7aed1466ad676f6f3e24cf922809705f664e97ab3c1", - "vout": 1, - "scriptSig": { - "asm": "3044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba[ALL] 027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34", - "hex": "473044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34" - }, - "sequence": 4294967295 - }, - { - "txid": "b0ac9cca2e69cd02410e31b1f4402a25758e71abd1ab06c265ef9077dc05d0ed", - "vout": 209, - "scriptSig": { - "asm": "304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", - "hex": "48304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" - }, - "sequence": 4294967295 - }, - { - "txid": "a135eafb595eaf4c1ea59ccb111cdc0eae1b2c979b226a1e5aa8b76fe2d628df", - "vout": 0, - "scriptSig": { - "asm": "3045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374[ALL] 03a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52", - "hex": "483045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52" - }, - "sequence": 4294967295 - }, - { - "txid": "a5d6bf53ba21140b8a4d554feb00fe8bb9a62430ff9e4624aa2f58a120232aae", - "vout": 1, - "scriptSig": { - "asm": "3046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", - "hex": "493046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" - }, - "sequence": 4294967295 - }, - { - "txid": "1b299cf14f1a22e81ea56d71b7affbd7cf386807bf2b4d4b79a18a54125accb3", - "vout": 0, - "scriptSig": { - "asm": "3045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967[ALL] 03a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52", - "hex": "483045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52" - }, - "sequence": 4294967295 - }, - { - "txid": "071df1cdcb3f0070f9d6af7b0274f02d0be2324a274727cfd288383167531485", - "vout": 21, - "scriptSig": { - "asm": "3045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", - "hex": "483045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" - }, - "sequence": 4294967295 - }, - { - "txid": "b012e500eb7adf7a13ed332dd6ece849f94f7a62bb3eac5babab356d1fc19282", - "vout": 9, - "scriptSig": { - "asm": "304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", - "hex": "48304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" - }, - "sequence": 4294967295 - }, - { - "txid": "58840fee9c833f2f2d40575842f30f4b8d2553094d06ad88b03d06869acf3d88", - "vout": 30, - "scriptSig": { - "asm": "30440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", - "hex": "4730440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" - }, - "sequence": 4294967295 - }, - { - "txid": "e69f9cd16946e570a665245354428a3f507ea69f4568b581e4af98edb3db9766", - "vout": 114, - "scriptSig": { - "asm": "304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", - "hex": "47304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" - }, - "sequence": 4294967295 - }, - { - "txid": "595d1257f654ed2cbe5a65421e8aefd2b4d70b5b6c89a03f1d7e518221fc3f02", - "vout": 103, - "scriptSig": { - "asm": "3046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", - "hex": "493046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" - }, - "sequence": 4294967295 - }, - { - "txid": "06fc818f9555a261248ecd7aad0993eafb5a82ceb2b5c87c3ddfb06671c7f816", - "vout": 1, - "scriptSig": { - "asm": "3045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec7669018[ALL] 0234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd", - "hex": "483045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec766901801210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd" - }, - "sequence": 4294967295 - }, - { - "txid": "fb416c8155d6bb1d43f9395466ca90a638a7c2dd3ff617aadf3a7ac8f3967b19", - "vout": 0, - "scriptSig": { - "asm": "304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a[ALL] 027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34", - "hex": "49304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34" - }, - "sequence": 4294967295 - }, - { - "txid": "3940b9683bd6104ad24c978e640ba4095993cafdb27d2ed91baa27ee61a2d920", - "vout": 221, - "scriptSig": { - "asm": "3045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", - "hex": "483045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" - }, - "sequence": 4294967295 - }, - { - "txid": "711b5714d3b5136147c02194cd95bde94a4648c4263ca6f972d86cd1d579f150", - "vout": 1, - "scriptSig": { - "asm": "3045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba9074[ALL] 0234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd", - "hex": "483045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba907401210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd" - }, - "sequence": 4294967295 - }, - { - "txid": "6364b5c5efe018430789e7fb4e338209546cae5d9c5f5e300aac68155d861b55", - "vout": 27, - "scriptSig": { - "asm": "304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", - "hex": "48304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" - }, - "sequence": 4294967295 - }, - { - "txid": "0bb57f6e38012c86d4c5a28c904f2675082859147921a707d48961015a3e5057", - "vout": 1095, - "scriptSig": { - "asm": "304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", - "hex": "48304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" - }, - "sequence": 4294967295 - }, - { - "txid": "9b34274814a2540bb062107117f8f3e75ef85d953e9372d8261a3e9dfbc1163f", - "vout": 37, - "scriptSig": { - "asm": "3045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", - "hex": "483045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" - }, - "sequence": 4294967295 - }, - { - "txid": "b86b5cc0d8a7374d94e277850b0a249cb26a7b42ddf014f28a49b8859da64241", - "vout": 20, - "scriptSig": { - "asm": "304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", - "hex": "48304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" - }, - "sequence": 4294967295 - }, - { - "txid": "3d0a2353eeec44d3c10aed259038db321912122cd4150048f7bfa4c0ecfee236", - "vout": 242, - "scriptSig": { - "asm": "3046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", - "hex": "493046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" - }, - "sequence": 4294967295 - } - ], - "vout": [ - { - "value": 1.37820000, - "n": 0, - "scriptPubKey": { - "asm": "OP_DUP OP_HASH160 8fd139bb39ced713f231c58a4d07bf6954d1c201 OP_EQUALVERIFY OP_CHECKSIG", - "hex": "76a9148fd139bb39ced713f231c58a4d07bf6954d1c20188ac", - "reqSigs": 1, - "type": "pubkeyhash", - "addresses": [ - "8UCHzdXk2SczWJ4uLyVTFJae73TLT4Jitj" - ] - } - }, - { - "value": 0.01000001, - "n": 1, - "scriptPubKey": { - "asm": "OP_DUP OP_HASH160 6c772e9cf96371bba3da8cb733da70a2fcf20078 OP_EQUALVERIFY OP_CHECKSIG", - "hex": "76a9146c772e9cf96371bba3da8cb733da70a2fcf2007888ac", - "reqSigs": 1, - "type": "pubkeyhash", - "addresses": [ - "8QyNUb8rYo61aGWf4bKHi1CdvKT8ASb7M7" - ] - } - } - ], - "hex": "0100000014fd5c23522d31761c50175453daa6edaabe47a602a592d39ce933d8271a1a87274c0100006c493046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffc1b37ae964f605978022f94ce2f3f676d66a46d1aef7c2c17d6315b9697f2f75010000006a473044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34ffffffffedd005dc7790ef65c206abd1ab718e75252a40f4b1310e4102cd692eca9cacb0d10000006b48304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffdf28d6e26fb7a85a1e6a229b972c1bae0edc1c11cb9ca51e4caf5e59fbea35a1000000006b483045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52ffffffffae2a2320a1582faa24469eff3024a6b98bfe00eb4f554d8a0b1421ba53bfd6a5010000006c493046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffb3cc5a12548aa1794b4d2bbf076838cfd7fbafb7716da51ee8221a4ff19c291b000000006b483045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52ffffffff85145367313888d2cf2747274a32e20b2df074027bafd6f970003fcbcdf11d07150000006b483045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff8292c11f6d35abab5bac3ebb627a4ff949e8ecd62d33ed137adf7aeb00e512b0090000006b48304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff883dcf9a86063db088ad064d0953258d4b0ff3425857402d2f3f839cee0f84581e0000006a4730440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff6697dbb3ed98afe481b568459fa67e503f8a4254532465a670e54669d19c9fe6720000006a47304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff023ffc2182517e1d3fa0896c5b0bd7b4d2ef8a1e42655abe2ced54f657125d59670000006c493046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff16f8c77166b0df3d7cc8b5b2ce825afbea9309ad7acd8e2461a255958f81fc06010000006b483045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec766901801210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cdffffffff197b96f3c87a3adfaa17f63fddc2a738a690ca665439f9431dbbd655816c41fb000000006c49304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34ffffffff20d9a261ee27aa1bd92e7db2fdca935909a40b648e974cd24a10d63b68b94039dd0000006b483045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff50f179d5d16cd872f9a63c26c448464ae9bd95cd9421c0476113b5d314571b71010000006b483045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba907401210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cdffffffff551b865d1568ac0a305e5f9c5dae6c540982334efbe789074318e0efc5b564631b0000006b48304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff57503e5a016189d407a721791459280875264f908ca2c5d4862c01386e7fb50b470400006b48304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff3f16c1fb9d3e1a26d872933e955df85ee7f3f817711062b00b54a2144827349b250000006b483045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff4142a69d85b8498af214f0dd427b6ab29c240a0b8577e2944d37a7d8c05c6bb8140000006b48304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff36e2feecc0a4bff7480015d42c12121932db389025ed0ac1d344ecee53230a3df20000006c493046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff0260f73608000000001976a9148fd139bb39ced713f231c58a4d07bf6954d1c20188ac41420f00000000001976a9146c772e9cf96371bba3da8cb733da70a2fcf2007888ac00000000" + "txid": "81b2035be1da1abe745c6141174a73d151009ec17b3d5ebffa2e177408c50dfd", + "hash": "81b2035be1da1abe745c6141174a73d151009ec17b3d5ebffa2e177408c50dfd", + "version": 1, + "size": 3040, + "vsize": 3040, + "weight": 12160, + "locktime": 0, + "vin": [ + { + "txid": "27871a1a27d833e99cd392a502a647beaaeda6da535417501c76312d52235cfd", + "vout": 332, + "scriptSig": { + "asm": "3046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "752f7f69b915637dc1c2f7aed1466ad676f6f3e24cf922809705f664e97ab3c1", + "vout": 1, + "scriptSig": { + "asm": "3044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba[ALL] 027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34", + "hex": "473044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34" + }, + "sequence": 4294967295 + }, + { + "txid": "b0ac9cca2e69cd02410e31b1f4402a25758e71abd1ab06c265ef9077dc05d0ed", + "vout": 209, + "scriptSig": { + "asm": "304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "48304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "a135eafb595eaf4c1ea59ccb111cdc0eae1b2c979b226a1e5aa8b76fe2d628df", + "vout": 0, + "scriptSig": { + "asm": "3045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374[ALL] 03a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52", + "hex": "483045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52" + }, + "sequence": 4294967295 + }, + { + "txid": "a5d6bf53ba21140b8a4d554feb00fe8bb9a62430ff9e4624aa2f58a120232aae", + "vout": 1, + "scriptSig": { + "asm": "3046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "1b299cf14f1a22e81ea56d71b7affbd7cf386807bf2b4d4b79a18a54125accb3", + "vout": 0, + "scriptSig": { + "asm": "3045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967[ALL] 03a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52", + "hex": "483045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52" + }, + "sequence": 4294967295 + }, + { + "txid": "071df1cdcb3f0070f9d6af7b0274f02d0be2324a274727cfd288383167531485", + "vout": 21, + "scriptSig": { + "asm": "3045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "483045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "b012e500eb7adf7a13ed332dd6ece849f94f7a62bb3eac5babab356d1fc19282", + "vout": 9, + "scriptSig": { + "asm": "304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "58840fee9c833f2f2d40575842f30f4b8d2553094d06ad88b03d06869acf3d88", + "vout": 30, + "scriptSig": { + "asm": "30440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "4730440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "e69f9cd16946e570a665245354428a3f507ea69f4568b581e4af98edb3db9766", + "vout": 114, + "scriptSig": { + "asm": "304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "47304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "595d1257f654ed2cbe5a65421e8aefd2b4d70b5b6c89a03f1d7e518221fc3f02", + "vout": 103, + "scriptSig": { + "asm": "3046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "06fc818f9555a261248ecd7aad0993eafb5a82ceb2b5c87c3ddfb06671c7f816", + "vout": 1, + "scriptSig": { + "asm": "3045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec7669018[ALL] 0234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd", + "hex": "483045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec766901801210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd" + }, + "sequence": 4294967295 + }, + { + "txid": "fb416c8155d6bb1d43f9395466ca90a638a7c2dd3ff617aadf3a7ac8f3967b19", + "vout": 0, + "scriptSig": { + "asm": "304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a[ALL] 027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34", + "hex": "49304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34" + }, + "sequence": 4294967295 + }, + { + "txid": "3940b9683bd6104ad24c978e640ba4095993cafdb27d2ed91baa27ee61a2d920", + "vout": 221, + "scriptSig": { + "asm": "3045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "483045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "711b5714d3b5136147c02194cd95bde94a4648c4263ca6f972d86cd1d579f150", + "vout": 1, + "scriptSig": { + "asm": "3045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba9074[ALL] 0234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd", + "hex": "483045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba907401210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd" + }, + "sequence": 4294967295 + }, + { + "txid": "6364b5c5efe018430789e7fb4e338209546cae5d9c5f5e300aac68155d861b55", + "vout": 27, + "scriptSig": { + "asm": "304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "0bb57f6e38012c86d4c5a28c904f2675082859147921a707d48961015a3e5057", + "vout": 1095, + "scriptSig": { + "asm": "304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "9b34274814a2540bb062107117f8f3e75ef85d953e9372d8261a3e9dfbc1163f", + "vout": 37, + "scriptSig": { + "asm": "3045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "483045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "b86b5cc0d8a7374d94e277850b0a249cb26a7b42ddf014f28a49b8859da64241", + "vout": 20, + "scriptSig": { + "asm": "304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "3d0a2353eeec44d3c10aed259038db321912122cd4150048f7bfa4c0ecfee236", + "vout": 242, + "scriptSig": { + "asm": "3046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + } + ], + "vout": [ + { + "value": 1.37820000, + "n": 0, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 8fd139bb39ced713f231c58a4d07bf6954d1c201 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9148fd139bb39ced713f231c58a4d07bf6954d1c20188ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "8UCHzdXk2SczWJ4uLyVTFJae73TLT4Jitj" + ] + } + }, + { + "value": 0.01000001, + "n": 1, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 6c772e9cf96371bba3da8cb733da70a2fcf20078 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9146c772e9cf96371bba3da8cb733da70a2fcf2007888ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "8QyNUb8rYo61aGWf4bKHi1CdvKT8ASb7M7" + ] + } + } + ], + "hex": "0100000014fd5c23522d31761c50175453daa6edaabe47a602a592d39ce933d8271a1a87274c0100006c493046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffc1b37ae964f605978022f94ce2f3f676d66a46d1aef7c2c17d6315b9697f2f75010000006a473044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34ffffffffedd005dc7790ef65c206abd1ab718e75252a40f4b1310e4102cd692eca9cacb0d10000006b48304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffdf28d6e26fb7a85a1e6a229b972c1bae0edc1c11cb9ca51e4caf5e59fbea35a1000000006b483045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52ffffffffae2a2320a1582faa24469eff3024a6b98bfe00eb4f554d8a0b1421ba53bfd6a5010000006c493046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffb3cc5a12548aa1794b4d2bbf076838cfd7fbafb7716da51ee8221a4ff19c291b000000006b483045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52ffffffff85145367313888d2cf2747274a32e20b2df074027bafd6f970003fcbcdf11d07150000006b483045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff8292c11f6d35abab5bac3ebb627a4ff949e8ecd62d33ed137adf7aeb00e512b0090000006b48304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff883dcf9a86063db088ad064d0953258d4b0ff3425857402d2f3f839cee0f84581e0000006a4730440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff6697dbb3ed98afe481b568459fa67e503f8a4254532465a670e54669d19c9fe6720000006a47304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff023ffc2182517e1d3fa0896c5b0bd7b4d2ef8a1e42655abe2ced54f657125d59670000006c493046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff16f8c77166b0df3d7cc8b5b2ce825afbea9309ad7acd8e2461a255958f81fc06010000006b483045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec766901801210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cdffffffff197b96f3c87a3adfaa17f63fddc2a738a690ca665439f9431dbbd655816c41fb000000006c49304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34ffffffff20d9a261ee27aa1bd92e7db2fdca935909a40b648e974cd24a10d63b68b94039dd0000006b483045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff50f179d5d16cd872f9a63c26c448464ae9bd95cd9421c0476113b5d314571b71010000006b483045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba907401210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cdffffffff551b865d1568ac0a305e5f9c5dae6c540982334efbe789074318e0efc5b564631b0000006b48304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff57503e5a016189d407a721791459280875264f908ca2c5d4862c01386e7fb50b470400006b48304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff3f16c1fb9d3e1a26d872933e955df85ee7f3f817711062b00b54a2144827349b250000006b483045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff4142a69d85b8498af214f0dd427b6ab29c240a0b8577e2944d37a7d8c05c6bb8140000006b48304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff36e2feecc0a4bff7480015d42c12121932db389025ed0ac1d344ecee53230a3df20000006c493046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff0260f73608000000001976a9148fd139bb39ced713f231c58a4d07bf6954d1c20188ac41420f00000000001976a9146c772e9cf96371bba3da8cb733da70a2fcf2007888ac00000000" } diff --git a/test/util/data/tt-delout1-out.json b/test/util/data/tt-delout1-out.json index 8704dfb160..a0b431db93 100644 --- a/test/util/data/tt-delout1-out.json +++ b/test/util/data/tt-delout1-out.json @@ -1,216 +1,216 @@ { - "txid": "c46ccd75b5050e942b2e86a3648f843f525fe6fc000bf0534ba5973063354493", - "hash": "c46ccd75b5050e942b2e86a3648f843f525fe6fc000bf0534ba5973063354493", - "version": 1, - "size": 3155, - "vsize": 3155, - "weight": 12620, - "locktime": 0, - "vin": [ - { - "txid": "27871a1a27d833e99cd392a502a647beaaeda6da535417501c76312d52235cfd", - "vout": 332, - "scriptSig": { - "asm": "3046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", - "hex": "493046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" - }, - "sequence": 4294967295 - }, - { - "txid": "a72ec96bd0d022d1b0c2f9078cdd46b3725b8eecdd001e17b21e3ababad14ecb", - "vout": 0, - "scriptSig": { - "asm": "3046022100a9b617843b68c284715d3e02fd120479cd0d96a6c43bf01e697fb0a460a21a3a022100ba0a12fbe8b993d4e7911fa3467615765dbe421ddf5c51b57a9c1ee19dcc00ba[ALL] 03e633b4fa4ceb705c2da712390767199be8ef2448b3095dc01652e11b2b751505", - "hex": "493046022100a9b617843b68c284715d3e02fd120479cd0d96a6c43bf01e697fb0a460a21a3a022100ba0a12fbe8b993d4e7911fa3467615765dbe421ddf5c51b57a9c1ee19dcc00ba012103e633b4fa4ceb705c2da712390767199be8ef2448b3095dc01652e11b2b751505" - }, - "sequence": 4294967295 - }, - { - "txid": "752f7f69b915637dc1c2f7aed1466ad676f6f3e24cf922809705f664e97ab3c1", - "vout": 1, - "scriptSig": { - "asm": "3044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba[ALL] 027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34", - "hex": "473044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34" - }, - "sequence": 4294967295 - }, - { - "txid": "b0ac9cca2e69cd02410e31b1f4402a25758e71abd1ab06c265ef9077dc05d0ed", - "vout": 209, - "scriptSig": { - "asm": "304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", - "hex": "48304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" - }, - "sequence": 4294967295 - }, - { - "txid": "a135eafb595eaf4c1ea59ccb111cdc0eae1b2c979b226a1e5aa8b76fe2d628df", - "vout": 0, - "scriptSig": { - "asm": "3045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374[ALL] 03a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52", - "hex": "483045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52" - }, - "sequence": 4294967295 - }, - { - "txid": "a5d6bf53ba21140b8a4d554feb00fe8bb9a62430ff9e4624aa2f58a120232aae", - "vout": 1, - "scriptSig": { - "asm": "3046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", - "hex": "493046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" - }, - "sequence": 4294967295 - }, - { - "txid": "1b299cf14f1a22e81ea56d71b7affbd7cf386807bf2b4d4b79a18a54125accb3", - "vout": 0, - "scriptSig": { - "asm": "3045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967[ALL] 03a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52", - "hex": "483045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52" - }, - "sequence": 4294967295 - }, - { - "txid": "071df1cdcb3f0070f9d6af7b0274f02d0be2324a274727cfd288383167531485", - "vout": 21, - "scriptSig": { - "asm": "3045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", - "hex": "483045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" - }, - "sequence": 4294967295 - }, - { - "txid": "b012e500eb7adf7a13ed332dd6ece849f94f7a62bb3eac5babab356d1fc19282", - "vout": 9, - "scriptSig": { - "asm": "304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", - "hex": "48304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" - }, - "sequence": 4294967295 - }, - { - "txid": "58840fee9c833f2f2d40575842f30f4b8d2553094d06ad88b03d06869acf3d88", - "vout": 30, - "scriptSig": { - "asm": "30440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", - "hex": "4730440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" - }, - "sequence": 4294967295 - }, - { - "txid": "e69f9cd16946e570a665245354428a3f507ea69f4568b581e4af98edb3db9766", - "vout": 114, - "scriptSig": { - "asm": "304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", - "hex": "47304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" - }, - "sequence": 4294967295 - }, - { - "txid": "595d1257f654ed2cbe5a65421e8aefd2b4d70b5b6c89a03f1d7e518221fc3f02", - "vout": 103, - "scriptSig": { - "asm": "3046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", - "hex": "493046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" - }, - "sequence": 4294967295 - }, - { - "txid": "06fc818f9555a261248ecd7aad0993eafb5a82ceb2b5c87c3ddfb06671c7f816", - "vout": 1, - "scriptSig": { - "asm": "3045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec7669018[ALL] 0234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd", - "hex": "483045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec766901801210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd" - }, - "sequence": 4294967295 - }, - { - "txid": "fb416c8155d6bb1d43f9395466ca90a638a7c2dd3ff617aadf3a7ac8f3967b19", - "vout": 0, - "scriptSig": { - "asm": "304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a[ALL] 027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34", - "hex": "49304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34" - }, - "sequence": 4294967295 - }, - { - "txid": "3940b9683bd6104ad24c978e640ba4095993cafdb27d2ed91baa27ee61a2d920", - "vout": 221, - "scriptSig": { - "asm": "3045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", - "hex": "483045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" - }, - "sequence": 4294967295 - }, - { - "txid": "711b5714d3b5136147c02194cd95bde94a4648c4263ca6f972d86cd1d579f150", - "vout": 1, - "scriptSig": { - "asm": "3045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba9074[ALL] 0234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd", - "hex": "483045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba907401210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd" - }, - "sequence": 4294967295 - }, - { - "txid": "6364b5c5efe018430789e7fb4e338209546cae5d9c5f5e300aac68155d861b55", - "vout": 27, - "scriptSig": { - "asm": "304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", - "hex": "48304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" - }, - "sequence": 4294967295 - }, - { - "txid": "0bb57f6e38012c86d4c5a28c904f2675082859147921a707d48961015a3e5057", - "vout": 1095, - "scriptSig": { - "asm": "304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", - "hex": "48304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" - }, - "sequence": 4294967295 - }, - { - "txid": "9b34274814a2540bb062107117f8f3e75ef85d953e9372d8261a3e9dfbc1163f", - "vout": 37, - "scriptSig": { - "asm": "3045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", - "hex": "483045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" - }, - "sequence": 4294967295 - }, - { - "txid": "b86b5cc0d8a7374d94e277850b0a249cb26a7b42ddf014f28a49b8859da64241", - "vout": 20, - "scriptSig": { - "asm": "304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", - "hex": "48304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" - }, - "sequence": 4294967295 - }, - { - "txid": "3d0a2353eeec44d3c10aed259038db321912122cd4150048f7bfa4c0ecfee236", - "vout": 242, - "scriptSig": { - "asm": "3046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", - "hex": "493046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" - }, - "sequence": 4294967295 - } - ], - "vout": [ - { - "value": 1.37820000, - "n": 0, - "scriptPubKey": { - "asm": "OP_DUP OP_HASH160 8fd139bb39ced713f231c58a4d07bf6954d1c201 OP_EQUALVERIFY OP_CHECKSIG", - "hex": "76a9148fd139bb39ced713f231c58a4d07bf6954d1c20188ac", - "reqSigs": 1, - "type": "pubkeyhash", - "addresses": [ - "8UCHzdXk2SczWJ4uLyVTFJae73TLT4Jitj" - ] - } - } - ], - "hex": "0100000015fd5c23522d31761c50175453daa6edaabe47a602a592d39ce933d8271a1a87274c0100006c493046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffcb4ed1baba3a1eb2171e00ddec8e5b72b346dd8c07f9c2b0d122d0d06bc92ea7000000006c493046022100a9b617843b68c284715d3e02fd120479cd0d96a6c43bf01e697fb0a460a21a3a022100ba0a12fbe8b993d4e7911fa3467615765dbe421ddf5c51b57a9c1ee19dcc00ba012103e633b4fa4ceb705c2da712390767199be8ef2448b3095dc01652e11b2b751505ffffffffc1b37ae964f605978022f94ce2f3f676d66a46d1aef7c2c17d6315b9697f2f75010000006a473044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34ffffffffedd005dc7790ef65c206abd1ab718e75252a40f4b1310e4102cd692eca9cacb0d10000006b48304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffdf28d6e26fb7a85a1e6a229b972c1bae0edc1c11cb9ca51e4caf5e59fbea35a1000000006b483045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52ffffffffae2a2320a1582faa24469eff3024a6b98bfe00eb4f554d8a0b1421ba53bfd6a5010000006c493046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffb3cc5a12548aa1794b4d2bbf076838cfd7fbafb7716da51ee8221a4ff19c291b000000006b483045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52ffffffff85145367313888d2cf2747274a32e20b2df074027bafd6f970003fcbcdf11d07150000006b483045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff8292c11f6d35abab5bac3ebb627a4ff949e8ecd62d33ed137adf7aeb00e512b0090000006b48304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff883dcf9a86063db088ad064d0953258d4b0ff3425857402d2f3f839cee0f84581e0000006a4730440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff6697dbb3ed98afe481b568459fa67e503f8a4254532465a670e54669d19c9fe6720000006a47304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff023ffc2182517e1d3fa0896c5b0bd7b4d2ef8a1e42655abe2ced54f657125d59670000006c493046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff16f8c77166b0df3d7cc8b5b2ce825afbea9309ad7acd8e2461a255958f81fc06010000006b483045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec766901801210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cdffffffff197b96f3c87a3adfaa17f63fddc2a738a690ca665439f9431dbbd655816c41fb000000006c49304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34ffffffff20d9a261ee27aa1bd92e7db2fdca935909a40b648e974cd24a10d63b68b94039dd0000006b483045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff50f179d5d16cd872f9a63c26c448464ae9bd95cd9421c0476113b5d314571b71010000006b483045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba907401210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cdffffffff551b865d1568ac0a305e5f9c5dae6c540982334efbe789074318e0efc5b564631b0000006b48304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff57503e5a016189d407a721791459280875264f908ca2c5d4862c01386e7fb50b470400006b48304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff3f16c1fb9d3e1a26d872933e955df85ee7f3f817711062b00b54a2144827349b250000006b483045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff4142a69d85b8498af214f0dd427b6ab29c240a0b8577e2944d37a7d8c05c6bb8140000006b48304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff36e2feecc0a4bff7480015d42c12121932db389025ed0ac1d344ecee53230a3df20000006c493046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff0160f73608000000001976a9148fd139bb39ced713f231c58a4d07bf6954d1c20188ac00000000" + "txid": "c46ccd75b5050e942b2e86a3648f843f525fe6fc000bf0534ba5973063354493", + "hash": "c46ccd75b5050e942b2e86a3648f843f525fe6fc000bf0534ba5973063354493", + "version": 1, + "size": 3155, + "vsize": 3155, + "weight": 12620, + "locktime": 0, + "vin": [ + { + "txid": "27871a1a27d833e99cd392a502a647beaaeda6da535417501c76312d52235cfd", + "vout": 332, + "scriptSig": { + "asm": "3046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "a72ec96bd0d022d1b0c2f9078cdd46b3725b8eecdd001e17b21e3ababad14ecb", + "vout": 0, + "scriptSig": { + "asm": "3046022100a9b617843b68c284715d3e02fd120479cd0d96a6c43bf01e697fb0a460a21a3a022100ba0a12fbe8b993d4e7911fa3467615765dbe421ddf5c51b57a9c1ee19dcc00ba[ALL] 03e633b4fa4ceb705c2da712390767199be8ef2448b3095dc01652e11b2b751505", + "hex": "493046022100a9b617843b68c284715d3e02fd120479cd0d96a6c43bf01e697fb0a460a21a3a022100ba0a12fbe8b993d4e7911fa3467615765dbe421ddf5c51b57a9c1ee19dcc00ba012103e633b4fa4ceb705c2da712390767199be8ef2448b3095dc01652e11b2b751505" + }, + "sequence": 4294967295 + }, + { + "txid": "752f7f69b915637dc1c2f7aed1466ad676f6f3e24cf922809705f664e97ab3c1", + "vout": 1, + "scriptSig": { + "asm": "3044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba[ALL] 027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34", + "hex": "473044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34" + }, + "sequence": 4294967295 + }, + { + "txid": "b0ac9cca2e69cd02410e31b1f4402a25758e71abd1ab06c265ef9077dc05d0ed", + "vout": 209, + "scriptSig": { + "asm": "304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "48304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "a135eafb595eaf4c1ea59ccb111cdc0eae1b2c979b226a1e5aa8b76fe2d628df", + "vout": 0, + "scriptSig": { + "asm": "3045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374[ALL] 03a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52", + "hex": "483045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52" + }, + "sequence": 4294967295 + }, + { + "txid": "a5d6bf53ba21140b8a4d554feb00fe8bb9a62430ff9e4624aa2f58a120232aae", + "vout": 1, + "scriptSig": { + "asm": "3046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "1b299cf14f1a22e81ea56d71b7affbd7cf386807bf2b4d4b79a18a54125accb3", + "vout": 0, + "scriptSig": { + "asm": "3045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967[ALL] 03a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52", + "hex": "483045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52" + }, + "sequence": 4294967295 + }, + { + "txid": "071df1cdcb3f0070f9d6af7b0274f02d0be2324a274727cfd288383167531485", + "vout": 21, + "scriptSig": { + "asm": "3045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "483045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "b012e500eb7adf7a13ed332dd6ece849f94f7a62bb3eac5babab356d1fc19282", + "vout": 9, + "scriptSig": { + "asm": "304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "58840fee9c833f2f2d40575842f30f4b8d2553094d06ad88b03d06869acf3d88", + "vout": 30, + "scriptSig": { + "asm": "30440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "4730440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "e69f9cd16946e570a665245354428a3f507ea69f4568b581e4af98edb3db9766", + "vout": 114, + "scriptSig": { + "asm": "304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "47304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "595d1257f654ed2cbe5a65421e8aefd2b4d70b5b6c89a03f1d7e518221fc3f02", + "vout": 103, + "scriptSig": { + "asm": "3046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "06fc818f9555a261248ecd7aad0993eafb5a82ceb2b5c87c3ddfb06671c7f816", + "vout": 1, + "scriptSig": { + "asm": "3045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec7669018[ALL] 0234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd", + "hex": "483045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec766901801210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd" + }, + "sequence": 4294967295 + }, + { + "txid": "fb416c8155d6bb1d43f9395466ca90a638a7c2dd3ff617aadf3a7ac8f3967b19", + "vout": 0, + "scriptSig": { + "asm": "304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a[ALL] 027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34", + "hex": "49304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34" + }, + "sequence": 4294967295 + }, + { + "txid": "3940b9683bd6104ad24c978e640ba4095993cafdb27d2ed91baa27ee61a2d920", + "vout": 221, + "scriptSig": { + "asm": "3045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "483045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "711b5714d3b5136147c02194cd95bde94a4648c4263ca6f972d86cd1d579f150", + "vout": 1, + "scriptSig": { + "asm": "3045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba9074[ALL] 0234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd", + "hex": "483045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba907401210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd" + }, + "sequence": 4294967295 + }, + { + "txid": "6364b5c5efe018430789e7fb4e338209546cae5d9c5f5e300aac68155d861b55", + "vout": 27, + "scriptSig": { + "asm": "304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "0bb57f6e38012c86d4c5a28c904f2675082859147921a707d48961015a3e5057", + "vout": 1095, + "scriptSig": { + "asm": "304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "9b34274814a2540bb062107117f8f3e75ef85d953e9372d8261a3e9dfbc1163f", + "vout": 37, + "scriptSig": { + "asm": "3045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "483045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "b86b5cc0d8a7374d94e277850b0a249cb26a7b42ddf014f28a49b8859da64241", + "vout": 20, + "scriptSig": { + "asm": "304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "3d0a2353eeec44d3c10aed259038db321912122cd4150048f7bfa4c0ecfee236", + "vout": 242, + "scriptSig": { + "asm": "3046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + } + ], + "vout": [ + { + "value": 1.37820000, + "n": 0, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 8fd139bb39ced713f231c58a4d07bf6954d1c201 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9148fd139bb39ced713f231c58a4d07bf6954d1c20188ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "8UCHzdXk2SczWJ4uLyVTFJae73TLT4Jitj" + ] + } + } + ], + "hex": "0100000015fd5c23522d31761c50175453daa6edaabe47a602a592d39ce933d8271a1a87274c0100006c493046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffcb4ed1baba3a1eb2171e00ddec8e5b72b346dd8c07f9c2b0d122d0d06bc92ea7000000006c493046022100a9b617843b68c284715d3e02fd120479cd0d96a6c43bf01e697fb0a460a21a3a022100ba0a12fbe8b993d4e7911fa3467615765dbe421ddf5c51b57a9c1ee19dcc00ba012103e633b4fa4ceb705c2da712390767199be8ef2448b3095dc01652e11b2b751505ffffffffc1b37ae964f605978022f94ce2f3f676d66a46d1aef7c2c17d6315b9697f2f75010000006a473044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34ffffffffedd005dc7790ef65c206abd1ab718e75252a40f4b1310e4102cd692eca9cacb0d10000006b48304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffdf28d6e26fb7a85a1e6a229b972c1bae0edc1c11cb9ca51e4caf5e59fbea35a1000000006b483045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52ffffffffae2a2320a1582faa24469eff3024a6b98bfe00eb4f554d8a0b1421ba53bfd6a5010000006c493046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffb3cc5a12548aa1794b4d2bbf076838cfd7fbafb7716da51ee8221a4ff19c291b000000006b483045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52ffffffff85145367313888d2cf2747274a32e20b2df074027bafd6f970003fcbcdf11d07150000006b483045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff8292c11f6d35abab5bac3ebb627a4ff949e8ecd62d33ed137adf7aeb00e512b0090000006b48304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff883dcf9a86063db088ad064d0953258d4b0ff3425857402d2f3f839cee0f84581e0000006a4730440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff6697dbb3ed98afe481b568459fa67e503f8a4254532465a670e54669d19c9fe6720000006a47304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff023ffc2182517e1d3fa0896c5b0bd7b4d2ef8a1e42655abe2ced54f657125d59670000006c493046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff16f8c77166b0df3d7cc8b5b2ce825afbea9309ad7acd8e2461a255958f81fc06010000006b483045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec766901801210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cdffffffff197b96f3c87a3adfaa17f63fddc2a738a690ca665439f9431dbbd655816c41fb000000006c49304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34ffffffff20d9a261ee27aa1bd92e7db2fdca935909a40b648e974cd24a10d63b68b94039dd0000006b483045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff50f179d5d16cd872f9a63c26c448464ae9bd95cd9421c0476113b5d314571b71010000006b483045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba907401210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cdffffffff551b865d1568ac0a305e5f9c5dae6c540982334efbe789074318e0efc5b564631b0000006b48304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff57503e5a016189d407a721791459280875264f908ca2c5d4862c01386e7fb50b470400006b48304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff3f16c1fb9d3e1a26d872933e955df85ee7f3f817711062b00b54a2144827349b250000006b483045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff4142a69d85b8498af214f0dd427b6ab29c240a0b8577e2944d37a7d8c05c6bb8140000006b48304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff36e2feecc0a4bff7480015d42c12121932db389025ed0ac1d344ecee53230a3df20000006c493046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff0160f73608000000001976a9148fd139bb39ced713f231c58a4d07bf6954d1c20188ac00000000" } diff --git a/test/util/data/tt-locktime317000-out.json b/test/util/data/tt-locktime317000-out.json index 375165477e..d020ae4615 100644 --- a/test/util/data/tt-locktime317000-out.json +++ b/test/util/data/tt-locktime317000-out.json @@ -1,229 +1,229 @@ { - "txid": "aded538f642c17e15f4d3306b8be7e1a4d1ae0c4616d641ab51ea09ba65e5cb5", - "hash": "aded538f642c17e15f4d3306b8be7e1a4d1ae0c4616d641ab51ea09ba65e5cb5", - "version": 1, - "size": 3189, - "vsize": 3189, - "weight": 12756, - "locktime": 317000, - "vin": [ - { - "txid": "27871a1a27d833e99cd392a502a647beaaeda6da535417501c76312d52235cfd", - "vout": 332, - "scriptSig": { - "asm": "3046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", - "hex": "493046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" - }, - "sequence": 4294967295 - }, - { - "txid": "a72ec96bd0d022d1b0c2f9078cdd46b3725b8eecdd001e17b21e3ababad14ecb", - "vout": 0, - "scriptSig": { - "asm": "3046022100a9b617843b68c284715d3e02fd120479cd0d96a6c43bf01e697fb0a460a21a3a022100ba0a12fbe8b993d4e7911fa3467615765dbe421ddf5c51b57a9c1ee19dcc00ba[ALL] 03e633b4fa4ceb705c2da712390767199be8ef2448b3095dc01652e11b2b751505", - "hex": "493046022100a9b617843b68c284715d3e02fd120479cd0d96a6c43bf01e697fb0a460a21a3a022100ba0a12fbe8b993d4e7911fa3467615765dbe421ddf5c51b57a9c1ee19dcc00ba012103e633b4fa4ceb705c2da712390767199be8ef2448b3095dc01652e11b2b751505" - }, - "sequence": 4294967295 - }, - { - "txid": "752f7f69b915637dc1c2f7aed1466ad676f6f3e24cf922809705f664e97ab3c1", - "vout": 1, - "scriptSig": { - "asm": "3044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba[ALL] 027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34", - "hex": "473044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34" - }, - "sequence": 4294967295 - }, - { - "txid": "b0ac9cca2e69cd02410e31b1f4402a25758e71abd1ab06c265ef9077dc05d0ed", - "vout": 209, - "scriptSig": { - "asm": "304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", - "hex": "48304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" - }, - "sequence": 4294967295 - }, - { - "txid": "a135eafb595eaf4c1ea59ccb111cdc0eae1b2c979b226a1e5aa8b76fe2d628df", - "vout": 0, - "scriptSig": { - "asm": "3045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374[ALL] 03a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52", - "hex": "483045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52" - }, - "sequence": 4294967295 - }, - { - "txid": "a5d6bf53ba21140b8a4d554feb00fe8bb9a62430ff9e4624aa2f58a120232aae", - "vout": 1, - "scriptSig": { - "asm": "3046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", - "hex": "493046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" - }, - "sequence": 4294967295 - }, - { - "txid": "1b299cf14f1a22e81ea56d71b7affbd7cf386807bf2b4d4b79a18a54125accb3", - "vout": 0, - "scriptSig": { - "asm": "3045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967[ALL] 03a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52", - "hex": "483045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52" - }, - "sequence": 4294967295 - }, - { - "txid": "071df1cdcb3f0070f9d6af7b0274f02d0be2324a274727cfd288383167531485", - "vout": 21, - "scriptSig": { - "asm": "3045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", - "hex": "483045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" - }, - "sequence": 4294967295 - }, - { - "txid": "b012e500eb7adf7a13ed332dd6ece849f94f7a62bb3eac5babab356d1fc19282", - "vout": 9, - "scriptSig": { - "asm": "304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", - "hex": "48304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" - }, - "sequence": 4294967295 - }, - { - "txid": "58840fee9c833f2f2d40575842f30f4b8d2553094d06ad88b03d06869acf3d88", - "vout": 30, - "scriptSig": { - "asm": "30440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", - "hex": "4730440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" - }, - "sequence": 4294967295 - }, - { - "txid": "e69f9cd16946e570a665245354428a3f507ea69f4568b581e4af98edb3db9766", - "vout": 114, - "scriptSig": { - "asm": "304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", - "hex": "47304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" - }, - "sequence": 4294967295 - }, - { - "txid": "595d1257f654ed2cbe5a65421e8aefd2b4d70b5b6c89a03f1d7e518221fc3f02", - "vout": 103, - "scriptSig": { - "asm": "3046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", - "hex": "493046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" - }, - "sequence": 4294967295 - }, - { - "txid": "06fc818f9555a261248ecd7aad0993eafb5a82ceb2b5c87c3ddfb06671c7f816", - "vout": 1, - "scriptSig": { - "asm": "3045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec7669018[ALL] 0234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd", - "hex": "483045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec766901801210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd" - }, - "sequence": 4294967295 - }, - { - "txid": "fb416c8155d6bb1d43f9395466ca90a638a7c2dd3ff617aadf3a7ac8f3967b19", - "vout": 0, - "scriptSig": { - "asm": "304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a[ALL] 027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34", - "hex": "49304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34" - }, - "sequence": 4294967295 - }, - { - "txid": "3940b9683bd6104ad24c978e640ba4095993cafdb27d2ed91baa27ee61a2d920", - "vout": 221, - "scriptSig": { - "asm": "3045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", - "hex": "483045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" - }, - "sequence": 4294967295 - }, - { - "txid": "711b5714d3b5136147c02194cd95bde94a4648c4263ca6f972d86cd1d579f150", - "vout": 1, - "scriptSig": { - "asm": "3045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba9074[ALL] 0234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd", - "hex": "483045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba907401210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd" - }, - "sequence": 4294967295 - }, - { - "txid": "6364b5c5efe018430789e7fb4e338209546cae5d9c5f5e300aac68155d861b55", - "vout": 27, - "scriptSig": { - "asm": "304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", - "hex": "48304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" - }, - "sequence": 4294967295 - }, - { - "txid": "0bb57f6e38012c86d4c5a28c904f2675082859147921a707d48961015a3e5057", - "vout": 1095, - "scriptSig": { - "asm": "304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", - "hex": "48304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" - }, - "sequence": 4294967295 - }, - { - "txid": "9b34274814a2540bb062107117f8f3e75ef85d953e9372d8261a3e9dfbc1163f", - "vout": 37, - "scriptSig": { - "asm": "3045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", - "hex": "483045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" - }, - "sequence": 4294967295 - }, - { - "txid": "b86b5cc0d8a7374d94e277850b0a249cb26a7b42ddf014f28a49b8859da64241", - "vout": 20, - "scriptSig": { - "asm": "304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", - "hex": "48304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" - }, - "sequence": 4294967295 - }, - { - "txid": "3d0a2353eeec44d3c10aed259038db321912122cd4150048f7bfa4c0ecfee236", - "vout": 242, - "scriptSig": { - "asm": "3046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", - "hex": "493046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" - }, - "sequence": 4294967295 - } - ], - "vout": [ - { - "value": 1.37820000, - "n": 0, - "scriptPubKey": { - "asm": "OP_DUP OP_HASH160 8fd139bb39ced713f231c58a4d07bf6954d1c201 OP_EQUALVERIFY OP_CHECKSIG", - "hex": "76a9148fd139bb39ced713f231c58a4d07bf6954d1c20188ac", - "reqSigs": 1, - "type": "pubkeyhash", - "addresses": [ - "8UCHzdXk2SczWJ4uLyVTFJae73TLT4Jitj" - ] - } - }, - { - "value": 0.01000001, - "n": 1, - "scriptPubKey": { - "asm": "OP_DUP OP_HASH160 6c772e9cf96371bba3da8cb733da70a2fcf20078 OP_EQUALVERIFY OP_CHECKSIG", - "hex": "76a9146c772e9cf96371bba3da8cb733da70a2fcf2007888ac", - "reqSigs": 1, - "type": "pubkeyhash", - "addresses": [ - "8QyNUb8rYo61aGWf4bKHi1CdvKT8ASb7M7" - ] - } - } - ], - "hex": "0100000015fd5c23522d31761c50175453daa6edaabe47a602a592d39ce933d8271a1a87274c0100006c493046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffcb4ed1baba3a1eb2171e00ddec8e5b72b346dd8c07f9c2b0d122d0d06bc92ea7000000006c493046022100a9b617843b68c284715d3e02fd120479cd0d96a6c43bf01e697fb0a460a21a3a022100ba0a12fbe8b993d4e7911fa3467615765dbe421ddf5c51b57a9c1ee19dcc00ba012103e633b4fa4ceb705c2da712390767199be8ef2448b3095dc01652e11b2b751505ffffffffc1b37ae964f605978022f94ce2f3f676d66a46d1aef7c2c17d6315b9697f2f75010000006a473044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34ffffffffedd005dc7790ef65c206abd1ab718e75252a40f4b1310e4102cd692eca9cacb0d10000006b48304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffdf28d6e26fb7a85a1e6a229b972c1bae0edc1c11cb9ca51e4caf5e59fbea35a1000000006b483045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52ffffffffae2a2320a1582faa24469eff3024a6b98bfe00eb4f554d8a0b1421ba53bfd6a5010000006c493046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffb3cc5a12548aa1794b4d2bbf076838cfd7fbafb7716da51ee8221a4ff19c291b000000006b483045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52ffffffff85145367313888d2cf2747274a32e20b2df074027bafd6f970003fcbcdf11d07150000006b483045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff8292c11f6d35abab5bac3ebb627a4ff949e8ecd62d33ed137adf7aeb00e512b0090000006b48304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff883dcf9a86063db088ad064d0953258d4b0ff3425857402d2f3f839cee0f84581e0000006a4730440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff6697dbb3ed98afe481b568459fa67e503f8a4254532465a670e54669d19c9fe6720000006a47304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff023ffc2182517e1d3fa0896c5b0bd7b4d2ef8a1e42655abe2ced54f657125d59670000006c493046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff16f8c77166b0df3d7cc8b5b2ce825afbea9309ad7acd8e2461a255958f81fc06010000006b483045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec766901801210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cdffffffff197b96f3c87a3adfaa17f63fddc2a738a690ca665439f9431dbbd655816c41fb000000006c49304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34ffffffff20d9a261ee27aa1bd92e7db2fdca935909a40b648e974cd24a10d63b68b94039dd0000006b483045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff50f179d5d16cd872f9a63c26c448464ae9bd95cd9421c0476113b5d314571b71010000006b483045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba907401210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cdffffffff551b865d1568ac0a305e5f9c5dae6c540982334efbe789074318e0efc5b564631b0000006b48304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff57503e5a016189d407a721791459280875264f908ca2c5d4862c01386e7fb50b470400006b48304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff3f16c1fb9d3e1a26d872933e955df85ee7f3f817711062b00b54a2144827349b250000006b483045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff4142a69d85b8498af214f0dd427b6ab29c240a0b8577e2944d37a7d8c05c6bb8140000006b48304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff36e2feecc0a4bff7480015d42c12121932db389025ed0ac1d344ecee53230a3df20000006c493046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff0260f73608000000001976a9148fd139bb39ced713f231c58a4d07bf6954d1c20188ac41420f00000000001976a9146c772e9cf96371bba3da8cb733da70a2fcf2007888ac48d60400" + "txid": "aded538f642c17e15f4d3306b8be7e1a4d1ae0c4616d641ab51ea09ba65e5cb5", + "hash": "aded538f642c17e15f4d3306b8be7e1a4d1ae0c4616d641ab51ea09ba65e5cb5", + "version": 1, + "size": 3189, + "vsize": 3189, + "weight": 12756, + "locktime": 317000, + "vin": [ + { + "txid": "27871a1a27d833e99cd392a502a647beaaeda6da535417501c76312d52235cfd", + "vout": 332, + "scriptSig": { + "asm": "3046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "a72ec96bd0d022d1b0c2f9078cdd46b3725b8eecdd001e17b21e3ababad14ecb", + "vout": 0, + "scriptSig": { + "asm": "3046022100a9b617843b68c284715d3e02fd120479cd0d96a6c43bf01e697fb0a460a21a3a022100ba0a12fbe8b993d4e7911fa3467615765dbe421ddf5c51b57a9c1ee19dcc00ba[ALL] 03e633b4fa4ceb705c2da712390767199be8ef2448b3095dc01652e11b2b751505", + "hex": "493046022100a9b617843b68c284715d3e02fd120479cd0d96a6c43bf01e697fb0a460a21a3a022100ba0a12fbe8b993d4e7911fa3467615765dbe421ddf5c51b57a9c1ee19dcc00ba012103e633b4fa4ceb705c2da712390767199be8ef2448b3095dc01652e11b2b751505" + }, + "sequence": 4294967295 + }, + { + "txid": "752f7f69b915637dc1c2f7aed1466ad676f6f3e24cf922809705f664e97ab3c1", + "vout": 1, + "scriptSig": { + "asm": "3044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba[ALL] 027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34", + "hex": "473044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34" + }, + "sequence": 4294967295 + }, + { + "txid": "b0ac9cca2e69cd02410e31b1f4402a25758e71abd1ab06c265ef9077dc05d0ed", + "vout": 209, + "scriptSig": { + "asm": "304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "48304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "a135eafb595eaf4c1ea59ccb111cdc0eae1b2c979b226a1e5aa8b76fe2d628df", + "vout": 0, + "scriptSig": { + "asm": "3045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374[ALL] 03a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52", + "hex": "483045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52" + }, + "sequence": 4294967295 + }, + { + "txid": "a5d6bf53ba21140b8a4d554feb00fe8bb9a62430ff9e4624aa2f58a120232aae", + "vout": 1, + "scriptSig": { + "asm": "3046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "1b299cf14f1a22e81ea56d71b7affbd7cf386807bf2b4d4b79a18a54125accb3", + "vout": 0, + "scriptSig": { + "asm": "3045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967[ALL] 03a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52", + "hex": "483045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52" + }, + "sequence": 4294967295 + }, + { + "txid": "071df1cdcb3f0070f9d6af7b0274f02d0be2324a274727cfd288383167531485", + "vout": 21, + "scriptSig": { + "asm": "3045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "483045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "b012e500eb7adf7a13ed332dd6ece849f94f7a62bb3eac5babab356d1fc19282", + "vout": 9, + "scriptSig": { + "asm": "304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "58840fee9c833f2f2d40575842f30f4b8d2553094d06ad88b03d06869acf3d88", + "vout": 30, + "scriptSig": { + "asm": "30440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "4730440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "e69f9cd16946e570a665245354428a3f507ea69f4568b581e4af98edb3db9766", + "vout": 114, + "scriptSig": { + "asm": "304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "47304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "595d1257f654ed2cbe5a65421e8aefd2b4d70b5b6c89a03f1d7e518221fc3f02", + "vout": 103, + "scriptSig": { + "asm": "3046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "06fc818f9555a261248ecd7aad0993eafb5a82ceb2b5c87c3ddfb06671c7f816", + "vout": 1, + "scriptSig": { + "asm": "3045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec7669018[ALL] 0234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd", + "hex": "483045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec766901801210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd" + }, + "sequence": 4294967295 + }, + { + "txid": "fb416c8155d6bb1d43f9395466ca90a638a7c2dd3ff617aadf3a7ac8f3967b19", + "vout": 0, + "scriptSig": { + "asm": "304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a[ALL] 027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34", + "hex": "49304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34" + }, + "sequence": 4294967295 + }, + { + "txid": "3940b9683bd6104ad24c978e640ba4095993cafdb27d2ed91baa27ee61a2d920", + "vout": 221, + "scriptSig": { + "asm": "3045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "483045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + }, + { + "txid": "711b5714d3b5136147c02194cd95bde94a4648c4263ca6f972d86cd1d579f150", + "vout": 1, + "scriptSig": { + "asm": "3045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba9074[ALL] 0234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd", + "hex": "483045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba907401210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cd" + }, + "sequence": 4294967295 + }, + { + "txid": "6364b5c5efe018430789e7fb4e338209546cae5d9c5f5e300aac68155d861b55", + "vout": 27, + "scriptSig": { + "asm": "304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "0bb57f6e38012c86d4c5a28c904f2675082859147921a707d48961015a3e5057", + "vout": 1095, + "scriptSig": { + "asm": "304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "9b34274814a2540bb062107117f8f3e75ef85d953e9372d8261a3e9dfbc1163f", + "vout": 37, + "scriptSig": { + "asm": "3045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "483045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "b86b5cc0d8a7374d94e277850b0a249cb26a7b42ddf014f28a49b8859da64241", + "vout": 20, + "scriptSig": { + "asm": "304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321[ALL] 03f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c", + "hex": "48304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64c" + }, + "sequence": 4294967295 + }, + { + "txid": "3d0a2353eeec44d3c10aed259038db321912122cd4150048f7bfa4c0ecfee236", + "vout": 242, + "scriptSig": { + "asm": "3046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68[ALL] 03091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc", + "hex": "493046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adc" + }, + "sequence": 4294967295 + } + ], + "vout": [ + { + "value": 1.37820000, + "n": 0, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 8fd139bb39ced713f231c58a4d07bf6954d1c201 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9148fd139bb39ced713f231c58a4d07bf6954d1c20188ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "8UCHzdXk2SczWJ4uLyVTFJae73TLT4Jitj" + ] + } + }, + { + "value": 0.01000001, + "n": 1, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 6c772e9cf96371bba3da8cb733da70a2fcf20078 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9146c772e9cf96371bba3da8cb733da70a2fcf2007888ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "8QyNUb8rYo61aGWf4bKHi1CdvKT8ASb7M7" + ] + } + } + ], + "hex": "0100000015fd5c23522d31761c50175453daa6edaabe47a602a592d39ce933d8271a1a87274c0100006c493046022100b4251ecd63778a3dde0155abe4cd162947620ae9ee45a874353551092325b116022100db307baf4ff3781ec520bd18f387948cedd15dc27bafe17c894b0fe6ffffcafa012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffcb4ed1baba3a1eb2171e00ddec8e5b72b346dd8c07f9c2b0d122d0d06bc92ea7000000006c493046022100a9b617843b68c284715d3e02fd120479cd0d96a6c43bf01e697fb0a460a21a3a022100ba0a12fbe8b993d4e7911fa3467615765dbe421ddf5c51b57a9c1ee19dcc00ba012103e633b4fa4ceb705c2da712390767199be8ef2448b3095dc01652e11b2b751505ffffffffc1b37ae964f605978022f94ce2f3f676d66a46d1aef7c2c17d6315b9697f2f75010000006a473044022079bd62ee09621a3be96b760c39e8ef78170101d46313923c6b07ae60a95c90670220238e51ea29fc70b04b65508450523caedbb11cb4dd5aa608c81487de798925ba0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34ffffffffedd005dc7790ef65c206abd1ab718e75252a40f4b1310e4102cd692eca9cacb0d10000006b48304502207722d6f9038673c86a1019b1c4de2d687ae246477cd4ca7002762be0299de385022100e594a11e3a313942595f7666dcf7078bcb14f1330f4206b95c917e7ec0e82fac012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffdf28d6e26fb7a85a1e6a229b972c1bae0edc1c11cb9ca51e4caf5e59fbea35a1000000006b483045022100a63a4788027b79b65c6f9d9e054f68cf3b4eed19efd82a2d53f70dcbe64683390220526f243671425b2bd05745fcf2729361f985cfe84ea80c7cfc817b93d8134374012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52ffffffffae2a2320a1582faa24469eff3024a6b98bfe00eb4f554d8a0b1421ba53bfd6a5010000006c493046022100b200ac6db16842f76dab9abe807ce423c992805879bc50abd46ed8275a59d9cf022100c0d518e85dd345b3c29dd4dc47b9a420d3ce817b18720e94966d2fe23413a408012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffffb3cc5a12548aa1794b4d2bbf076838cfd7fbafb7716da51ee8221a4ff19c291b000000006b483045022100ededc441c3103a6f2bd6cab7639421af0f6ec5e60503bce1e603cf34f00aee1c02205cb75f3f519a13fb348783b21db3085cb5ec7552c59e394fdbc3e1feea43f967012103a621f08be22d1bbdcbe4e527ee4927006aa555fc65e2aafa767d4ea2fe9dfa52ffffffff85145367313888d2cf2747274a32e20b2df074027bafd6f970003fcbcdf11d07150000006b483045022100d9eed5413d2a4b4b98625aa6e3169edc4fb4663e7862316d69224454e70cd8ca022061e506521d5ced51dd0ea36496e75904d756a4c4f9fb111568555075d5f68d9a012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff8292c11f6d35abab5bac3ebb627a4ff949e8ecd62d33ed137adf7aeb00e512b0090000006b48304502207e84b27139c4c19c828cb1e30c349bba88e4d9b59be97286960793b5ddc0a2af0221008cdc7a951e7f31c20953ed5635fbabf228e80b7047f32faaa0313e7693005177012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff883dcf9a86063db088ad064d0953258d4b0ff3425857402d2f3f839cee0f84581e0000006a4730440220426540dfed9c4ab5812e5f06df705b8bcf307dd7d20f7fa6512298b2a6314f420220064055096e3ca62f6c7352c66a5447767c53f946acdf35025ab3807ddb2fa404012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff6697dbb3ed98afe481b568459fa67e503f8a4254532465a670e54669d19c9fe6720000006a47304402200a5e673996f2fc88e21cc8613611f08a650bc0370338803591d85d0ec5663764022040b6664a0d1ec83a7f01975b8fde5232992b8ca58bf48af6725d2f92a936ab2e012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff023ffc2182517e1d3fa0896c5b0bd7b4d2ef8a1e42655abe2ced54f657125d59670000006c493046022100d93b30219c5735f673be5c3b4688366d96f545561c74cb62c6958c00f6960806022100ec8200adcb028f2184fa2a4f6faac7f8bb57cb4503bb7584ac11051fece31b3d012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff16f8c77166b0df3d7cc8b5b2ce825afbea9309ad7acd8e2461a255958f81fc06010000006b483045022100a13934e68d3f5b22b130c4cb33f4da468cffc52323a47fbfbe06b64858162246022047081e0a70ff770e64a2e2d31e5d520d9102268b57a47009a72fe73ec766901801210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cdffffffff197b96f3c87a3adfaa17f63fddc2a738a690ca665439f9431dbbd655816c41fb000000006c49304602210097f1f35d5bdc1a3a60390a1b015b8e7c4f916aa3847aafd969e04975e15bbe70022100a9052eb25517d481f1fda1b129eb1b534da50ea1a51f3ee012dca3601c11b86a0121027a759be8df971a6a04fafcb4f6babf75dc811c5cdaa0734cddbe9b942ce75b34ffffffff20d9a261ee27aa1bd92e7db2fdca935909a40b648e974cd24a10d63b68b94039dd0000006b483045022012b3138c591bf7154b6fef457f2c4a3c7162225003788ac0024a99355865ff13022100b71b125ae1ffb2e1d1571f580cd3ebc8cd049a2d7a8a41f138ba94aeb982106f012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff50f179d5d16cd872f9a63c26c448464ae9bd95cd9421c0476113b5d314571b71010000006b483045022100f834ccc8b22ee72712a3e5e6ef4acb8b2fb791b5385b70e2cd4332674d6667f4022024fbda0a997e0c253503f217501f508a4d56edce2c813ecdd9ad796dbeba907401210234b9d9413f247bb78cd3293b7b65a2c38018ba5621ea9ee737f3a6a3523fb4cdffffffff551b865d1568ac0a305e5f9c5dae6c540982334efbe789074318e0efc5b564631b0000006b48304502203b2fd1e39ae0e469d7a15768f262661b0de41470daf0fe8c4fd0c26542a0870002210081c57e331f9a2d214457d953e3542904727ee412c63028113635d7224da3dccc012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff57503e5a016189d407a721791459280875264f908ca2c5d4862c01386e7fb50b470400006b48304502206947a9c54f0664ece4430fd4ae999891dc50bb6126bc36b6a15a3189f29d25e9022100a86cfc4e2fdd9e39a20e305cfd1b76509c67b3e313e0f118229105caa0e823c9012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff3f16c1fb9d3e1a26d872933e955df85ee7f3f817711062b00b54a2144827349b250000006b483045022100c7128fe10b2d38744ae8177776054c29fc8ec13f07207723e70766ab7164847402201d2cf09009b9596de74c0183d1ab832e5edddb7a9965880bb400097e850850f8012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff4142a69d85b8498af214f0dd427b6ab29c240a0b8577e2944d37a7d8c05c6bb8140000006b48304502203b89a71628a28cc3703d170ca3be77786cff6b867e38a18b719705f8a326578f022100b2a9879e1acf621faa6466c207746a7f3eb4c8514c1482969aba3f2a957f1321012103f1575d6124ac78be398c25b31146d08313c6072d23a4d7df5ac6a9f87346c64cffffffff36e2feecc0a4bff7480015d42c12121932db389025ed0ac1d344ecee53230a3df20000006c493046022100ef794a8ef7fd6752d2a183c18866ff6e8dc0f5bd889a63e2c21cf303a6302461022100c1b09662d9e92988c3f9fcf17d1bcc79b5403647095d7212b9f8a1278a532d68012103091137f3ef23f4acfc19a5953a68b2074fae942ad3563ef28c33b0cac9a93adcffffffff0260f73608000000001976a9148fd139bb39ced713f231c58a4d07bf6954d1c20188ac41420f00000000001976a9146c772e9cf96371bba3da8cb733da70a2fcf2007888ac48d60400" } diff --git a/test/util/data/txcreate1.json b/test/util/data/txcreate1.json index ca9eacd546..671c375b0f 100644 --- a/test/util/data/txcreate1.json +++ b/test/util/data/txcreate1.json @@ -1,67 +1,67 @@ { - "txid": "fe7d174f42dce0cffa7a527e9bc8368956057619ec817648f6138b98f2533e8f", - "hash": "fe7d174f42dce0cffa7a527e9bc8368956057619ec817648f6138b98f2533e8f", - "version": 2, - "size": 201, - "vsize": 201, - "weight": 804, - "locktime": 0, - "vin": [ - { - "txid": "5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f", - "vout": 0, - "scriptSig": { - "asm": "", - "hex": "" - }, - "sequence": 4294967295 - }, - { - "txid": "bf829c6bcf84579331337659d31f89dfd138f7f7785802d5501c92333145ca7c", - "vout": 18, - "scriptSig": { - "asm": "", - "hex": "" - }, - "sequence": 4294967295 - }, - { - "txid": "22a6f904655d53ae2ff70e701a0bbd90aa3975c0f40bfc6cc996a9049e31cdfc", - "vout": 1, - "scriptSig": { - "asm": "", - "hex": "" - }, - "sequence": 4294967295 - } - ], - "vout": [ - { - "value": 0.18000000, - "n": 0, - "scriptPubKey": { - "asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG", - "hex": "76a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac", - "reqSigs": 1, - "type": "pubkeyhash", - "addresses": [ - "13tuJJDR2RgArmgfv6JScSdreahzgc4T6o" - ] - } - }, - { - "value": 4.00000000, - "n": 1, - "scriptPubKey": { - "asm": "OP_DUP OP_HASH160 f2d4db28cad6502226ee484ae24505c2885cb12d OP_EQUALVERIFY OP_CHECKSIG", - "hex": "76a914f2d4db28cad6502226ee484ae24505c2885cb12d88ac", - "reqSigs": 1, - "type": "pubkeyhash", - "addresses": [ - "1P8yWvZW8jVihP1bzHeqfE4aoXNX8AVa46" - ] - } - } - ], - "hex": "02000000031f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000ffffffff7cca453133921c50d5025878f7f738d1df891fd359763331935784cf6b9c82bf1200000000fffffffffccd319e04a996c96cfc0bf4c07539aa90bd0b1a700ef72fae535d6504f9a6220100000000ffffffff0280a81201000000001976a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac0084d717000000001976a914f2d4db28cad6502226ee484ae24505c2885cb12d88ac00000000" + "txid": "fe7d174f42dce0cffa7a527e9bc8368956057619ec817648f6138b98f2533e8f", + "hash": "fe7d174f42dce0cffa7a527e9bc8368956057619ec817648f6138b98f2533e8f", + "version": 2, + "size": 201, + "vsize": 201, + "weight": 804, + "locktime": 0, + "vin": [ + { + "txid": "5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f", + "vout": 0, + "scriptSig": { + "asm": "", + "hex": "" + }, + "sequence": 4294967295 + }, + { + "txid": "bf829c6bcf84579331337659d31f89dfd138f7f7785802d5501c92333145ca7c", + "vout": 18, + "scriptSig": { + "asm": "", + "hex": "" + }, + "sequence": 4294967295 + }, + { + "txid": "22a6f904655d53ae2ff70e701a0bbd90aa3975c0f40bfc6cc996a9049e31cdfc", + "vout": 1, + "scriptSig": { + "asm": "", + "hex": "" + }, + "sequence": 4294967295 + } + ], + "vout": [ + { + "value": 0.18000000, + "n": 0, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "13tuJJDR2RgArmgfv6JScSdreahzgc4T6o" + ] + } + }, + { + "value": 4.00000000, + "n": 1, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 f2d4db28cad6502226ee484ae24505c2885cb12d OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a914f2d4db28cad6502226ee484ae24505c2885cb12d88ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "1P8yWvZW8jVihP1bzHeqfE4aoXNX8AVa46" + ] + } + } + ], + "hex": "02000000031f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000ffffffff7cca453133921c50d5025878f7f738d1df891fd359763331935784cf6b9c82bf1200000000fffffffffccd319e04a996c96cfc0bf4c07539aa90bd0b1a700ef72fae535d6504f9a6220100000000ffffffff0280a81201000000001976a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac0084d717000000001976a914f2d4db28cad6502226ee484ae24505c2885cb12d88ac00000000" } diff --git a/test/util/data/txcreate2.json b/test/util/data/txcreate2.json index ee9b9c3c17..f56b176295 100644 --- a/test/util/data/txcreate2.json +++ b/test/util/data/txcreate2.json @@ -1,23 +1,23 @@ { - "txid": "0481afb29931341d0d7861d8a2f6f26456fa042abf54a23e96440ed7946e0715", - "hash": "0481afb29931341d0d7861d8a2f6f26456fa042abf54a23e96440ed7946e0715", - "version": 2, - "size": 19, - "vsize": 19, - "weight": 76, - "locktime": 0, - "vin": [ - ], - "vout": [ - { - "value": 0.00000000, - "n": 0, - "scriptPubKey": { - "asm": "", - "hex": "", - "type": "nonstandard" - } - } - ], - "hex": "02000000000100000000000000000000000000" + "txid": "0481afb29931341d0d7861d8a2f6f26456fa042abf54a23e96440ed7946e0715", + "hash": "0481afb29931341d0d7861d8a2f6f26456fa042abf54a23e96440ed7946e0715", + "version": 2, + "size": 19, + "vsize": 19, + "weight": 76, + "locktime": 0, + "vin": [ + ], + "vout": [ + { + "value": 0.00000000, + "n": 0, + "scriptPubKey": { + "asm": "", + "hex": "", + "type": "nonstandard" + } + } + ], + "hex": "02000000000100000000000000000000000000" } diff --git a/test/util/data/txcreatedata1.json b/test/util/data/txcreatedata1.json index 39909c2e3f..85784edfd1 100644 --- a/test/util/data/txcreatedata1.json +++ b/test/util/data/txcreatedata1.json @@ -1,45 +1,45 @@ { - "txid": "07894b4d12fe7853dd911402db1620920d261b9627c447f931417d330c25f06e", - "hash": "07894b4d12fe7853dd911402db1620920d261b9627c447f931417d330c25f06e", - "version": 1, - "size": 176, - "vsize": 176, - "weight": 704, - "locktime": 0, - "vin": [ - { - "txid": "5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f", - "vout": 0, - "scriptSig": { - "asm": "", - "hex": "" - }, - "sequence": 4294967295 - } - ], - "vout": [ - { - "value": 0.18000000, - "n": 0, - "scriptPubKey": { - "asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG", - "hex": "76a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac", - "reqSigs": 1, - "type": "pubkeyhash", - "addresses": [ - "13tuJJDR2RgArmgfv6JScSdreahzgc4T6o" - ] - } - }, - { - "value": 4.00000000, - "n": 1, - "scriptPubKey": { - "asm": "OP_RETURN 54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e", - "hex": "6a4c4f54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e", - "type": "nulldata" - } - } - ], - "hex": "01000000011f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000ffffffff0280a81201000000001976a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac0084d71700000000526a4c4f54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e00000000" + "txid": "07894b4d12fe7853dd911402db1620920d261b9627c447f931417d330c25f06e", + "hash": "07894b4d12fe7853dd911402db1620920d261b9627c447f931417d330c25f06e", + "version": 1, + "size": 176, + "vsize": 176, + "weight": 704, + "locktime": 0, + "vin": [ + { + "txid": "5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f", + "vout": 0, + "scriptSig": { + "asm": "", + "hex": "" + }, + "sequence": 4294967295 + } + ], + "vout": [ + { + "value": 0.18000000, + "n": 0, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "13tuJJDR2RgArmgfv6JScSdreahzgc4T6o" + ] + } + }, + { + "value": 4.00000000, + "n": 1, + "scriptPubKey": { + "asm": "OP_RETURN 54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e", + "hex": "6a4c4f54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e", + "type": "nulldata" + } + } + ], + "hex": "01000000011f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000ffffffff0280a81201000000001976a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac0084d71700000000526a4c4f54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e00000000" } diff --git a/test/util/data/txcreatedata2.json b/test/util/data/txcreatedata2.json index 2958006e58..e0e2912b5e 100644 --- a/test/util/data/txcreatedata2.json +++ b/test/util/data/txcreatedata2.json @@ -1,45 +1,45 @@ { - "txid": "c14b007fa3a6c1e7765919c1d14c1cfc2b8642c3a5d3be4b1fa8c4ccfec98bb0", - "hash": "c14b007fa3a6c1e7765919c1d14c1cfc2b8642c3a5d3be4b1fa8c4ccfec98bb0", - "version": 2, - "size": 176, - "vsize": 176, - "weight": 704, - "locktime": 0, - "vin": [ - { - "txid": "5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f", - "vout": 0, - "scriptSig": { - "asm": "", - "hex": "" - }, - "sequence": 4294967295 - } - ], - "vout": [ - { - "value": 0.18000000, - "n": 0, - "scriptPubKey": { - "asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG", - "hex": "76a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac", - "reqSigs": 1, - "type": "pubkeyhash", - "addresses": [ - "13tuJJDR2RgArmgfv6JScSdreahzgc4T6o" - ] - } - }, - { - "value": 0.00000000, - "n": 1, - "scriptPubKey": { - "asm": "OP_RETURN 54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e", - "hex": "6a4c4f54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e", - "type": "nulldata" - } - } - ], - "hex": "02000000011f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000ffffffff0280a81201000000001976a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac0000000000000000526a4c4f54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e00000000" + "txid": "c14b007fa3a6c1e7765919c1d14c1cfc2b8642c3a5d3be4b1fa8c4ccfec98bb0", + "hash": "c14b007fa3a6c1e7765919c1d14c1cfc2b8642c3a5d3be4b1fa8c4ccfec98bb0", + "version": 2, + "size": 176, + "vsize": 176, + "weight": 704, + "locktime": 0, + "vin": [ + { + "txid": "5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f", + "vout": 0, + "scriptSig": { + "asm": "", + "hex": "" + }, + "sequence": 4294967295 + } + ], + "vout": [ + { + "value": 0.18000000, + "n": 0, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "13tuJJDR2RgArmgfv6JScSdreahzgc4T6o" + ] + } + }, + { + "value": 0.00000000, + "n": 1, + "scriptPubKey": { + "asm": "OP_RETURN 54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e", + "hex": "6a4c4f54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e", + "type": "nulldata" + } + } + ], + "hex": "02000000011f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000ffffffff0280a81201000000001976a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac0000000000000000526a4c4f54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e00000000" } diff --git a/test/util/data/txcreatedata_seq0.json b/test/util/data/txcreatedata_seq0.json index a6656b5ad5..3db794c511 100644 --- a/test/util/data/txcreatedata_seq0.json +++ b/test/util/data/txcreatedata_seq0.json @@ -1,36 +1,36 @@ { - "txid": "8df6ed527472542dd5e137c242a7c5a9f337ac34f7b257ae4af886aeaebb51b0", - "hash": "8df6ed527472542dd5e137c242a7c5a9f337ac34f7b257ae4af886aeaebb51b0", - "version": 2, - "size": 85, - "vsize": 85, - "weight": 340, - "locktime": 0, - "vin": [ - { - "txid": "5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f", - "vout": 0, - "scriptSig": { - "asm": "", - "hex": "" - }, - "sequence": 4294967293 - } - ], - "vout": [ - { - "value": 0.18000000, - "n": 0, - "scriptPubKey": { - "asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG", - "hex": "76a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac", - "reqSigs": 1, - "type": "pubkeyhash", - "addresses": [ - "13tuJJDR2RgArmgfv6JScSdreahzgc4T6o" - ] - } - } - ], - "hex": "02000000011f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000fdffffff0180a81201000000001976a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac00000000" + "txid": "8df6ed527472542dd5e137c242a7c5a9f337ac34f7b257ae4af886aeaebb51b0", + "hash": "8df6ed527472542dd5e137c242a7c5a9f337ac34f7b257ae4af886aeaebb51b0", + "version": 2, + "size": 85, + "vsize": 85, + "weight": 340, + "locktime": 0, + "vin": [ + { + "txid": "5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f", + "vout": 0, + "scriptSig": { + "asm": "", + "hex": "" + }, + "sequence": 4294967293 + } + ], + "vout": [ + { + "value": 0.18000000, + "n": 0, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "13tuJJDR2RgArmgfv6JScSdreahzgc4T6o" + ] + } + } + ], + "hex": "02000000011f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000fdffffff0180a81201000000001976a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac00000000" } diff --git a/test/util/data/txcreatedata_seq1.json b/test/util/data/txcreatedata_seq1.json index 7f6ede6d76..d256c26f85 100644 --- a/test/util/data/txcreatedata_seq1.json +++ b/test/util/data/txcreatedata_seq1.json @@ -1,45 +1,45 @@ { - "txid": "c4dea671b0d7b48f8ab10bc46650e8329d3c5766931f548f513847a19f5ba75b", - "hash": "c4dea671b0d7b48f8ab10bc46650e8329d3c5766931f548f513847a19f5ba75b", - "version": 1, - "size": 126, - "vsize": 126, - "weight": 504, - "locktime": 0, - "vin": [ - { - "txid": "5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f", - "vout": 0, - "scriptSig": { - "asm": "", - "hex": "" - }, - "sequence": 4294967293 - }, - { - "txid": "5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f", - "vout": 0, - "scriptSig": { - "asm": "", - "hex": "" - }, - "sequence": 1 - } - ], - "vout": [ - { - "value": 0.18000000, - "n": 0, - "scriptPubKey": { - "asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG", - "hex": "76a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac", - "reqSigs": 1, - "type": "pubkeyhash", - "addresses": [ - "8Hym2Fabog1waaCEMeJBLhY1yfLyW8u3iP" - ] - } - } - ], - "hex": "01000000021f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000fdffffff1f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000010000000180a81201000000001976a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac00000000" + "txid": "c4dea671b0d7b48f8ab10bc46650e8329d3c5766931f548f513847a19f5ba75b", + "hash": "c4dea671b0d7b48f8ab10bc46650e8329d3c5766931f548f513847a19f5ba75b", + "version": 1, + "size": 126, + "vsize": 126, + "weight": 504, + "locktime": 0, + "vin": [ + { + "txid": "5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f", + "vout": 0, + "scriptSig": { + "asm": "", + "hex": "" + }, + "sequence": 4294967293 + }, + { + "txid": "5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f", + "vout": 0, + "scriptSig": { + "asm": "", + "hex": "" + }, + "sequence": 1 + } + ], + "vout": [ + { + "value": 0.18000000, + "n": 0, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "8Hym2Fabog1waaCEMeJBLhY1yfLyW8u3iP" + ] + } + } + ], + "hex": "01000000021f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000fdffffff1f5c38dfcf6f1a5f5a87c416076d392c87e6d41970d5ad5e477a02d66bde97580000000000010000000180a81201000000001976a9141fc11f39be1729bf973a7ab6a615ca4729d6457488ac00000000" } diff --git a/test/util/data/txcreatemultisig1.json b/test/util/data/txcreatemultisig1.json index 75f78ab288..4cd556b051 100644 --- a/test/util/data/txcreatemultisig1.json +++ b/test/util/data/txcreatemultisig1.json @@ -1,29 +1,29 @@ { - "txid": "0d1d4edfc217d9db3ab6a9298f26a52eae3c52f55a6cb8ccbc14f7c727572894", - "hash": "0d1d4edfc217d9db3ab6a9298f26a52eae3c52f55a6cb8ccbc14f7c727572894", - "version": 1, - "size": 124, - "vsize": 124, - "weight": 496, - "locktime": 0, - "vin": [ - ], - "vout": [ - { - "value": 1.00000000, - "n": 0, - "scriptPubKey": { - "asm": "2 02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397 021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d 02df2089105c77f266fa11a9d33f05c735234075f2e8780824c6b709415f9fb485 3 OP_CHECKMULTISIG", - "hex": "522102a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff39721021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d2102df2089105c77f266fa11a9d33f05c735234075f2e8780824c6b709415f9fb48553ae", - "reqSigs": 2, - "type": "multisig", - "addresses": [ - "8Vt7jzVH2WNet6wi2AMeSUmVJAkZ6oqqew", - "8Vcki6geuYiY82Ur5GEVoY7sVRYMwJ33b8", - "8JRmJsyNNmuK1tySRbbuCfdJmz3n8b1kXM" - ] - } - } - ], - "hex": "01000000000100e1f5050000000069522102a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff39721021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d2102df2089105c77f266fa11a9d33f05c735234075f2e8780824c6b709415f9fb48553ae00000000" + "txid": "0d1d4edfc217d9db3ab6a9298f26a52eae3c52f55a6cb8ccbc14f7c727572894", + "hash": "0d1d4edfc217d9db3ab6a9298f26a52eae3c52f55a6cb8ccbc14f7c727572894", + "version": 1, + "size": 124, + "vsize": 124, + "weight": 496, + "locktime": 0, + "vin": [ + ], + "vout": [ + { + "value": 1.00000000, + "n": 0, + "scriptPubKey": { + "asm": "2 02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397 021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d 02df2089105c77f266fa11a9d33f05c735234075f2e8780824c6b709415f9fb485 3 OP_CHECKMULTISIG", + "hex": "522102a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff39721021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d2102df2089105c77f266fa11a9d33f05c735234075f2e8780824c6b709415f9fb48553ae", + "reqSigs": 2, + "type": "multisig", + "addresses": [ + "8Vt7jzVH2WNet6wi2AMeSUmVJAkZ6oqqew", + "8Vcki6geuYiY82Ur5GEVoY7sVRYMwJ33b8", + "8JRmJsyNNmuK1tySRbbuCfdJmz3n8b1kXM" + ] + } + } + ], + "hex": "01000000000100e1f5050000000069522102a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff39721021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d2102df2089105c77f266fa11a9d33f05c735234075f2e8780824c6b709415f9fb48553ae00000000" } diff --git a/test/util/data/txcreatemultisig2.json b/test/util/data/txcreatemultisig2.json index 436bd8e0f7..2dbcab163e 100644 --- a/test/util/data/txcreatemultisig2.json +++ b/test/util/data/txcreatemultisig2.json @@ -1,27 +1,27 @@ { - "txid": "0d861f278a3b7bce7cb5a88d71e6e6a903336f95ad5a2c29b295b63835b6eee3", - "hash": "0d861f278a3b7bce7cb5a88d71e6e6a903336f95ad5a2c29b295b63835b6eee3", - "version": 1, - "size": 42, - "vsize": 42, - "weight": 168, - "locktime": 0, - "vin": [ - ], - "vout": [ - { - "value": 1.00000000, - "n": 0, - "scriptPubKey": { - "asm": "OP_HASH160 1c6fbaf46d64221e80cbae182c33ddf81b9294ac OP_EQUAL", - "hex": "a9141c6fbaf46d64221e80cbae182c33ddf81b9294ac87", - "reqSigs": 1, - "type": "scripthash", - "addresses": [ - "dG1ePJTHXXooGoELp8DbNxtL6nAsW8d6G8" - ] - } - } - ], - "hex": "01000000000100e1f5050000000017a9141c6fbaf46d64221e80cbae182c33ddf81b9294ac8700000000" + "txid": "0d861f278a3b7bce7cb5a88d71e6e6a903336f95ad5a2c29b295b63835b6eee3", + "hash": "0d861f278a3b7bce7cb5a88d71e6e6a903336f95ad5a2c29b295b63835b6eee3", + "version": 1, + "size": 42, + "vsize": 42, + "weight": 168, + "locktime": 0, + "vin": [ + ], + "vout": [ + { + "value": 1.00000000, + "n": 0, + "scriptPubKey": { + "asm": "OP_HASH160 1c6fbaf46d64221e80cbae182c33ddf81b9294ac OP_EQUAL", + "hex": "a9141c6fbaf46d64221e80cbae182c33ddf81b9294ac87", + "reqSigs": 1, + "type": "scripthash", + "addresses": [ + "dG1ePJTHXXooGoELp8DbNxtL6nAsW8d6G8" + ] + } + } + ], + "hex": "01000000000100e1f5050000000017a9141c6fbaf46d64221e80cbae182c33ddf81b9294ac8700000000" } diff --git a/test/util/data/txcreatemultisig3.json b/test/util/data/txcreatemultisig3.json index f7984127ca..922da72a83 100644 --- a/test/util/data/txcreatemultisig3.json +++ b/test/util/data/txcreatemultisig3.json @@ -1,27 +1,27 @@ { - "txid": "ccc552220b46a3b5140048b03395987ce4f0fa1ddf8c635bba1fa44e0f8c1d7f", - "hash": "ccc552220b46a3b5140048b03395987ce4f0fa1ddf8c635bba1fa44e0f8c1d7f", - "version": 1, - "size": 53, - "vsize": 53, - "weight": 212, - "locktime": 0, - "vin": [ - ], - "vout": [ - { - "value": 1.00000000, - "n": 0, - "scriptPubKey": { - "asm": "0 e15a86a23178f433d514dbbce042e87d72662b8b5edcacfd2e37ab7a2d135f05", - "hex": "0020e15a86a23178f433d514dbbce042e87d72662b8b5edcacfd2e37ab7a2d135f05", - "reqSigs": 1, - "type": "witness_v0_scripthash", - "addresses": [ - "df1qu9dgdg330r6r84g5mw7wqshg04exv2uttmw2elfwx74h5tgntuzskmjys3" - ] - } - } - ], - "hex": "01000000000100e1f50500000000220020e15a86a23178f433d514dbbce042e87d72662b8b5edcacfd2e37ab7a2d135f0500000000" + "txid": "ccc552220b46a3b5140048b03395987ce4f0fa1ddf8c635bba1fa44e0f8c1d7f", + "hash": "ccc552220b46a3b5140048b03395987ce4f0fa1ddf8c635bba1fa44e0f8c1d7f", + "version": 1, + "size": 53, + "vsize": 53, + "weight": 212, + "locktime": 0, + "vin": [ + ], + "vout": [ + { + "value": 1.00000000, + "n": 0, + "scriptPubKey": { + "asm": "0 e15a86a23178f433d514dbbce042e87d72662b8b5edcacfd2e37ab7a2d135f05", + "hex": "0020e15a86a23178f433d514dbbce042e87d72662b8b5edcacfd2e37ab7a2d135f05", + "reqSigs": 1, + "type": "witness_v0_scripthash", + "addresses": [ + "df1qu9dgdg330r6r84g5mw7wqshg04exv2uttmw2elfwx74h5tgntuzskmjys3" + ] + } + } + ], + "hex": "01000000000100e1f50500000000220020e15a86a23178f433d514dbbce042e87d72662b8b5edcacfd2e37ab7a2d135f0500000000" } diff --git a/test/util/data/txcreatemultisig4.json b/test/util/data/txcreatemultisig4.json index 769a78f406..63fbe70d3d 100644 --- a/test/util/data/txcreatemultisig4.json +++ b/test/util/data/txcreatemultisig4.json @@ -1,27 +1,27 @@ { - "txid": "5e8b1cc73234e208d4b7ca9075f136b908c34101be7a048df4ba9ac758b61567", - "hash": "5e8b1cc73234e208d4b7ca9075f136b908c34101be7a048df4ba9ac758b61567", - "version": 1, - "size": 42, - "vsize": 42, - "weight": 168, - "locktime": 0, - "vin": [ - ], - "vout": [ - { - "value": 1.00000000, - "n": 0, - "scriptPubKey": { - "asm": "OP_HASH160 6edf12858999f0dae74f9c692e6694ee3621b2ac OP_EQUAL", - "hex": "a9146edf12858999f0dae74f9c692e6694ee3621b2ac87", - "reqSigs": 1, - "type": "scripthash", - "addresses": [ - "dPXXBDLwFAzr8XKpdtPhQfn8CnSSWHokDx" - ] - } - } - ], - "hex": "01000000000100e1f5050000000017a9146edf12858999f0dae74f9c692e6694ee3621b2ac8700000000" + "txid": "5e8b1cc73234e208d4b7ca9075f136b908c34101be7a048df4ba9ac758b61567", + "hash": "5e8b1cc73234e208d4b7ca9075f136b908c34101be7a048df4ba9ac758b61567", + "version": 1, + "size": 42, + "vsize": 42, + "weight": 168, + "locktime": 0, + "vin": [ + ], + "vout": [ + { + "value": 1.00000000, + "n": 0, + "scriptPubKey": { + "asm": "OP_HASH160 6edf12858999f0dae74f9c692e6694ee3621b2ac OP_EQUAL", + "hex": "a9146edf12858999f0dae74f9c692e6694ee3621b2ac87", + "reqSigs": 1, + "type": "scripthash", + "addresses": [ + "dPXXBDLwFAzr8XKpdtPhQfn8CnSSWHokDx" + ] + } + } + ], + "hex": "01000000000100e1f5050000000017a9146edf12858999f0dae74f9c692e6694ee3621b2ac8700000000" } diff --git a/test/util/data/txcreatemultisig5.json b/test/util/data/txcreatemultisig5.json index a835171583..76e3d110af 100644 --- a/test/util/data/txcreatemultisig5.json +++ b/test/util/data/txcreatemultisig5.json @@ -1,27 +1,27 @@ { - "txid": "813cf75e1f08debd242ef7c8192b7d478fb651355209369499a0de779ba7eb2f", - "hash": "813cf75e1f08debd242ef7c8192b7d478fb651355209369499a0de779ba7eb2f", - "version": 2, - "size": 42, - "vsize": 42, - "weight": 168, - "locktime": 0, - "vin": [ - ], - "vout": [ - { - "value": 1.00000000, - "n": 0, - "scriptPubKey": { - "asm": "OP_HASH160 a4051c02398868af83f28f083208fae99a769263 OP_EQUAL", - "hex": "a914a4051c02398868af83f28f083208fae99a76926387", - "reqSigs": 1, - "type": "scripthash", - "addresses": [ - "dUNYZEymqHnTbPqGLJTbcUfb7uP3sNLHzh" - ] - } - } - ], - "hex": "02000000000100e1f5050000000017a914a4051c02398868af83f28f083208fae99a7692638700000000" + "txid": "813cf75e1f08debd242ef7c8192b7d478fb651355209369499a0de779ba7eb2f", + "hash": "813cf75e1f08debd242ef7c8192b7d478fb651355209369499a0de779ba7eb2f", + "version": 2, + "size": 42, + "vsize": 42, + "weight": 168, + "locktime": 0, + "vin": [ + ], + "vout": [ + { + "value": 1.00000000, + "n": 0, + "scriptPubKey": { + "asm": "OP_HASH160 a4051c02398868af83f28f083208fae99a769263 OP_EQUAL", + "hex": "a914a4051c02398868af83f28f083208fae99a76926387", + "reqSigs": 1, + "type": "scripthash", + "addresses": [ + "dUNYZEymqHnTbPqGLJTbcUfb7uP3sNLHzh" + ] + } + } + ], + "hex": "02000000000100e1f5050000000017a914a4051c02398868af83f28f083208fae99a7692638700000000" } diff --git a/test/util/data/txcreateoutpubkey1.json b/test/util/data/txcreateoutpubkey1.json index 812c02aa8a..4892754292 100644 --- a/test/util/data/txcreateoutpubkey1.json +++ b/test/util/data/txcreateoutpubkey1.json @@ -1,27 +1,27 @@ { - "txid": "f42b38ac12e3fafc96ba1a9ba70cbfe326744aef75df5fb9db5d6e2855ca415f", - "hash": "f42b38ac12e3fafc96ba1a9ba70cbfe326744aef75df5fb9db5d6e2855ca415f", - "version": 1, - "size": 54, - "vsize": 54, - "weight": 216, - "locktime": 0, - "vin": [ - ], - "vout": [ - { - "value": 0.00000000, - "n": 0, - "scriptPubKey": { - "asm": "02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397 OP_CHECKSIG", - "hex": "2102a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397ac", - "reqSigs": 1, - "type": "pubkey", - "addresses": [ - "8Vt7jzVH2WNet6wi2AMeSUmVJAkZ6oqqew" - ] - } - } - ], - "hex": "0100000000010000000000000000232102a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397ac00000000" + "txid": "f42b38ac12e3fafc96ba1a9ba70cbfe326744aef75df5fb9db5d6e2855ca415f", + "hash": "f42b38ac12e3fafc96ba1a9ba70cbfe326744aef75df5fb9db5d6e2855ca415f", + "version": 1, + "size": 54, + "vsize": 54, + "weight": 216, + "locktime": 0, + "vin": [ + ], + "vout": [ + { + "value": 0.00000000, + "n": 0, + "scriptPubKey": { + "asm": "02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397 OP_CHECKSIG", + "hex": "2102a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397ac", + "reqSigs": 1, + "type": "pubkey", + "addresses": [ + "8Vt7jzVH2WNet6wi2AMeSUmVJAkZ6oqqew" + ] + } + } + ], + "hex": "0100000000010000000000000000232102a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397ac00000000" } diff --git a/test/util/data/txcreateoutpubkey2.json b/test/util/data/txcreateoutpubkey2.json index 45854bd9cf..d89f387f8a 100644 --- a/test/util/data/txcreateoutpubkey2.json +++ b/test/util/data/txcreateoutpubkey2.json @@ -1,27 +1,27 @@ { - "txid": "70f2a088cde460e677415fa1fb71895e90c231e6ed38ed203a35b6f848e9cc73", - "hash": "70f2a088cde460e677415fa1fb71895e90c231e6ed38ed203a35b6f848e9cc73", - "version": 1, - "size": 41, - "vsize": 41, - "weight": 164, - "locktime": 0, - "vin": [ - ], - "vout": [ - { - "value": 0.00000000, - "n": 0, - "scriptPubKey": { - "asm": "0 a2516e770582864a6a56ed21a102044e388c62e3", - "hex": "0014a2516e770582864a6a56ed21a102044e388c62e3", - "reqSigs": 1, - "type": "witness_v0_keyhash", - "addresses": [ - "df1q5fgkuac9s2ry56jka5s6zqsyfcugcchrvs2qss" - ] - } - } - ], - "hex": "0100000000010000000000000000160014a2516e770582864a6a56ed21a102044e388c62e300000000" + "txid": "70f2a088cde460e677415fa1fb71895e90c231e6ed38ed203a35b6f848e9cc73", + "hash": "70f2a088cde460e677415fa1fb71895e90c231e6ed38ed203a35b6f848e9cc73", + "version": 1, + "size": 41, + "vsize": 41, + "weight": 164, + "locktime": 0, + "vin": [ + ], + "vout": [ + { + "value": 0.00000000, + "n": 0, + "scriptPubKey": { + "asm": "0 a2516e770582864a6a56ed21a102044e388c62e3", + "hex": "0014a2516e770582864a6a56ed21a102044e388c62e3", + "reqSigs": 1, + "type": "witness_v0_keyhash", + "addresses": [ + "df1q5fgkuac9s2ry56jka5s6zqsyfcugcchrvs2qss" + ] + } + } + ], + "hex": "0100000000010000000000000000160014a2516e770582864a6a56ed21a102044e388c62e300000000" } diff --git a/test/util/data/txcreateoutpubkey3.json b/test/util/data/txcreateoutpubkey3.json index 068eb1e1d9..26524f3f27 100644 --- a/test/util/data/txcreateoutpubkey3.json +++ b/test/util/data/txcreateoutpubkey3.json @@ -1,27 +1,27 @@ { - "txid": "bfc7e898ee9f6a9652d7b8cca147e2da134502e2ada0f279ed634fc8cf833f8c", - "hash": "bfc7e898ee9f6a9652d7b8cca147e2da134502e2ada0f279ed634fc8cf833f8c", - "version": 1, - "size": 42, - "vsize": 42, - "weight": 168, - "locktime": 0, - "vin": [ - ], - "vout": [ - { - "value": 0.00000000, - "n": 0, - "scriptPubKey": { - "asm": "OP_HASH160 a5ab14c9804d0d8bf02f1aea4e82780733ad0a83 OP_EQUAL", - "hex": "a914a5ab14c9804d0d8bf02f1aea4e82780733ad0a8387", - "reqSigs": 1, - "type": "scripthash", - "addresses": [ - "dUXG4MbL3Fvk4UZ6D2pBh36pznwf6C9eRB" - ] - } - } - ], - "hex": "010000000001000000000000000017a914a5ab14c9804d0d8bf02f1aea4e82780733ad0a838700000000" + "txid": "bfc7e898ee9f6a9652d7b8cca147e2da134502e2ada0f279ed634fc8cf833f8c", + "hash": "bfc7e898ee9f6a9652d7b8cca147e2da134502e2ada0f279ed634fc8cf833f8c", + "version": 1, + "size": 42, + "vsize": 42, + "weight": 168, + "locktime": 0, + "vin": [ + ], + "vout": [ + { + "value": 0.00000000, + "n": 0, + "scriptPubKey": { + "asm": "OP_HASH160 a5ab14c9804d0d8bf02f1aea4e82780733ad0a83 OP_EQUAL", + "hex": "a914a5ab14c9804d0d8bf02f1aea4e82780733ad0a8387", + "reqSigs": 1, + "type": "scripthash", + "addresses": [ + "dUXG4MbL3Fvk4UZ6D2pBh36pznwf6C9eRB" + ] + } + } + ], + "hex": "010000000001000000000000000017a914a5ab14c9804d0d8bf02f1aea4e82780733ad0a838700000000" } diff --git a/test/util/data/txcreatescript1.json b/test/util/data/txcreatescript1.json index af1c4c35e2..170d417fe9 100644 --- a/test/util/data/txcreatescript1.json +++ b/test/util/data/txcreatescript1.json @@ -1,23 +1,23 @@ { - "txid": "f0851b68202f736b792649cfc960259c2374badcb644ab20cac726b5f72f61c9", - "hash": "f0851b68202f736b792649cfc960259c2374badcb644ab20cac726b5f72f61c9", - "version": 1, - "size": 20, - "vsize": 20, - "weight": 80, - "locktime": 0, - "vin": [ - ], - "vout": [ - { - "value": 0.00000000, - "n": 0, - "scriptPubKey": { - "asm": "OP_DROP", - "hex": "75", - "type": "nonstandard" - } - } - ], - "hex": "0100000000010000000000000000017500000000" + "txid": "f0851b68202f736b792649cfc960259c2374badcb644ab20cac726b5f72f61c9", + "hash": "f0851b68202f736b792649cfc960259c2374badcb644ab20cac726b5f72f61c9", + "version": 1, + "size": 20, + "vsize": 20, + "weight": 80, + "locktime": 0, + "vin": [ + ], + "vout": [ + { + "value": 0.00000000, + "n": 0, + "scriptPubKey": { + "asm": "OP_DROP", + "hex": "75", + "type": "nonstandard" + } + } + ], + "hex": "0100000000010000000000000000017500000000" } diff --git a/test/util/data/txcreatescript2.json b/test/util/data/txcreatescript2.json index e965a3bae1..83e2a14ff8 100644 --- a/test/util/data/txcreatescript2.json +++ b/test/util/data/txcreatescript2.json @@ -1,27 +1,27 @@ { - "txid": "6e07a7cc075e0703f32ee8c4e5373fe654bfbc315148fda364e1be286ff290d0", - "hash": "6e07a7cc075e0703f32ee8c4e5373fe654bfbc315148fda364e1be286ff290d0", - "version": 1, - "size": 42, - "vsize": 42, - "weight": 168, - "locktime": 0, - "vin": [ - ], - "vout": [ - { - "value": 0.00000000, - "n": 0, - "scriptPubKey": { - "asm": "OP_HASH160 71ed53322d470bb96657deb786b94f97dd46fb15 OP_EQUAL", - "hex": "a91471ed53322d470bb96657deb786b94f97dd46fb1587", - "reqSigs": 1, - "type": "scripthash", - "addresses": [ - "dPogH5Zm3V47qS4f84uSsggFEfFzDBrgbo" - ] - } - } - ], - "hex": "010000000001000000000000000017a91471ed53322d470bb96657deb786b94f97dd46fb158700000000" + "txid": "6e07a7cc075e0703f32ee8c4e5373fe654bfbc315148fda364e1be286ff290d0", + "hash": "6e07a7cc075e0703f32ee8c4e5373fe654bfbc315148fda364e1be286ff290d0", + "version": 1, + "size": 42, + "vsize": 42, + "weight": 168, + "locktime": 0, + "vin": [ + ], + "vout": [ + { + "value": 0.00000000, + "n": 0, + "scriptPubKey": { + "asm": "OP_HASH160 71ed53322d470bb96657deb786b94f97dd46fb15 OP_EQUAL", + "hex": "a91471ed53322d470bb96657deb786b94f97dd46fb1587", + "reqSigs": 1, + "type": "scripthash", + "addresses": [ + "dPogH5Zm3V47qS4f84uSsggFEfFzDBrgbo" + ] + } + } + ], + "hex": "010000000001000000000000000017a91471ed53322d470bb96657deb786b94f97dd46fb158700000000" } diff --git a/test/util/data/txcreatescript3.json b/test/util/data/txcreatescript3.json index 7d6e853969..9396a5ae2a 100644 --- a/test/util/data/txcreatescript3.json +++ b/test/util/data/txcreatescript3.json @@ -1,27 +1,27 @@ { - "txid": "8a234037b088e987c877030efc83374a07441c321bf9dc6dd2f206bc26507df8", - "hash": "8a234037b088e987c877030efc83374a07441c321bf9dc6dd2f206bc26507df8", - "version": 1, - "size": 53, - "vsize": 53, - "weight": 212, - "locktime": 0, - "vin": [ - ], - "vout": [ - { - "value": 0.00000000, - "n": 0, - "scriptPubKey": { - "asm": "0 0bfe935e70c321c7ca3afc75ce0d0ca2f98b5422e008bb31c00c6d7f1f1c0ad6", - "hex": "00200bfe935e70c321c7ca3afc75ce0d0ca2f98b5422e008bb31c00c6d7f1f1c0ad6", - "reqSigs": 1, - "type": "witness_v0_scripthash", - "addresses": [ - "df1qp0lfxhnscvsu0j36l36uurgv5tuck4pzuqytkvwqp3kh78cupttq88y0d4" - ] - } - } - ], - "hex": "01000000000100000000000000002200200bfe935e70c321c7ca3afc75ce0d0ca2f98b5422e008bb31c00c6d7f1f1c0ad600000000" + "txid": "8a234037b088e987c877030efc83374a07441c321bf9dc6dd2f206bc26507df8", + "hash": "8a234037b088e987c877030efc83374a07441c321bf9dc6dd2f206bc26507df8", + "version": 1, + "size": 53, + "vsize": 53, + "weight": 212, + "locktime": 0, + "vin": [ + ], + "vout": [ + { + "value": 0.00000000, + "n": 0, + "scriptPubKey": { + "asm": "0 0bfe935e70c321c7ca3afc75ce0d0ca2f98b5422e008bb31c00c6d7f1f1c0ad6", + "hex": "00200bfe935e70c321c7ca3afc75ce0d0ca2f98b5422e008bb31c00c6d7f1f1c0ad6", + "reqSigs": 1, + "type": "witness_v0_scripthash", + "addresses": [ + "df1qp0lfxhnscvsu0j36l36uurgv5tuck4pzuqytkvwqp3kh78cupttq88y0d4" + ] + } + } + ], + "hex": "01000000000100000000000000002200200bfe935e70c321c7ca3afc75ce0d0ca2f98b5422e008bb31c00c6d7f1f1c0ad600000000" } diff --git a/test/util/data/txcreatescript4.json b/test/util/data/txcreatescript4.json index fbaa64744c..fc02a23222 100644 --- a/test/util/data/txcreatescript4.json +++ b/test/util/data/txcreatescript4.json @@ -1,27 +1,27 @@ { - "txid": "24225cf5e9391100d6b218134b9f03383ca4c880a1f634ac12990cf28b66adbc", - "hash": "24225cf5e9391100d6b218134b9f03383ca4c880a1f634ac12990cf28b66adbc", - "version": 1, - "size": 42, - "vsize": 42, - "weight": 168, - "locktime": 0, - "vin": [ - ], - "vout": [ - { - "value": 0.00000000, - "n": 0, - "scriptPubKey": { - "asm": "OP_HASH160 6a2c482f4985f57e702f325816c90e3723ca81ae OP_EQUAL", - "hex": "a9146a2c482f4985f57e702f325816c90e3723ca81ae87", - "reqSigs": 1, - "type": "scripthash", - "addresses": [ - "dP6gHsb8edepgp5KUbpV8W6Frje3dA3HgR" - ] - } - } - ], - "hex": "010000000001000000000000000017a9146a2c482f4985f57e702f325816c90e3723ca81ae8700000000" + "txid": "24225cf5e9391100d6b218134b9f03383ca4c880a1f634ac12990cf28b66adbc", + "hash": "24225cf5e9391100d6b218134b9f03383ca4c880a1f634ac12990cf28b66adbc", + "version": 1, + "size": 42, + "vsize": 42, + "weight": 168, + "locktime": 0, + "vin": [ + ], + "vout": [ + { + "value": 0.00000000, + "n": 0, + "scriptPubKey": { + "asm": "OP_HASH160 6a2c482f4985f57e702f325816c90e3723ca81ae OP_EQUAL", + "hex": "a9146a2c482f4985f57e702f325816c90e3723ca81ae87", + "reqSigs": 1, + "type": "scripthash", + "addresses": [ + "dP6gHsb8edepgp5KUbpV8W6Frje3dA3HgR" + ] + } + } + ], + "hex": "010000000001000000000000000017a9146a2c482f4985f57e702f325816c90e3723ca81ae8700000000" } diff --git a/test/util/data/txcreatesignv1.json b/test/util/data/txcreatesignv1.json index 7a06aa9ffe..dee686bce3 100644 --- a/test/util/data/txcreatesignv1.json +++ b/test/util/data/txcreatesignv1.json @@ -1,36 +1,36 @@ { - "txid": "ffc7e509ec3fd60a182eb712621d41a47dc7d4ff310a70826c2fb0e9afb3fa02", - "hash": "ffc7e509ec3fd60a182eb712621d41a47dc7d4ff310a70826c2fb0e9afb3fa02", - "version": 1, - "size": 223, - "vsize": 223, - "weight": 892, - "locktime": 0, - "vin": [ - { - "txid": "4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485", - "vout": 0, - "scriptSig": { - "asm": "30440220131432090a6af42da3e8335ff110831b41a44f4e9d18d88f5d50278380696c7202200fc2e48938f323ad13625890c0ea926c8a189c08b8efc38376b20c8a2188e96e[ALL] 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", - "hex": "4730440220131432090a6af42da3e8335ff110831b41a44f4e9d18d88f5d50278380696c7202200fc2e48938f323ad13625890c0ea926c8a189c08b8efc38376b20c8a2188e96e01410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8" - }, - "sequence": 4294967295 - } - ], - "vout": [ - { - "value": 0.00100000, - "n": 0, - "scriptPubKey": { - "asm": "OP_DUP OP_HASH160 5834479edbbe0539b31ffd3a8f8ebadc2165ed01 OP_EQUALVERIFY OP_CHECKSIG", - "hex": "76a9145834479edbbe0539b31ffd3a8f8ebadc2165ed0188ac", - "reqSigs": 1, - "type": "pubkeyhash", - "addresses": [ - "193P6LtvS4nCnkDvM9uXn1gsSRqh4aDAz7" - ] - } - } - ], - "hex": "01000000018594c5bdcaec8f06b78b596f31cd292a294fd031e24eec716f43dac91ea7494d000000008a4730440220131432090a6af42da3e8335ff110831b41a44f4e9d18d88f5d50278380696c7202200fc2e48938f323ad13625890c0ea926c8a189c08b8efc38376b20c8a2188e96e01410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ffffffff01a0860100000000001976a9145834479edbbe0539b31ffd3a8f8ebadc2165ed0188ac00000000" + "txid": "ffc7e509ec3fd60a182eb712621d41a47dc7d4ff310a70826c2fb0e9afb3fa02", + "hash": "ffc7e509ec3fd60a182eb712621d41a47dc7d4ff310a70826c2fb0e9afb3fa02", + "version": 1, + "size": 223, + "vsize": 223, + "weight": 892, + "locktime": 0, + "vin": [ + { + "txid": "4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485", + "vout": 0, + "scriptSig": { + "asm": "30440220131432090a6af42da3e8335ff110831b41a44f4e9d18d88f5d50278380696c7202200fc2e48938f323ad13625890c0ea926c8a189c08b8efc38376b20c8a2188e96e[ALL] 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", + "hex": "4730440220131432090a6af42da3e8335ff110831b41a44f4e9d18d88f5d50278380696c7202200fc2e48938f323ad13625890c0ea926c8a189c08b8efc38376b20c8a2188e96e01410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8" + }, + "sequence": 4294967295 + } + ], + "vout": [ + { + "value": 0.00100000, + "n": 0, + "scriptPubKey": { + "asm": "OP_DUP OP_HASH160 5834479edbbe0539b31ffd3a8f8ebadc2165ed01 OP_EQUALVERIFY OP_CHECKSIG", + "hex": "76a9145834479edbbe0539b31ffd3a8f8ebadc2165ed0188ac", + "reqSigs": 1, + "type": "pubkeyhash", + "addresses": [ + "193P6LtvS4nCnkDvM9uXn1gsSRqh4aDAz7" + ] + } + } + ], + "hex": "01000000018594c5bdcaec8f06b78b596f31cd292a294fd031e24eec716f43dac91ea7494d000000008a4730440220131432090a6af42da3e8335ff110831b41a44f4e9d18d88f5d50278380696c7202200fc2e48938f323ad13625890c0ea926c8a189c08b8efc38376b20c8a2188e96e01410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ffffffff01a0860100000000001976a9145834479edbbe0539b31ffd3a8f8ebadc2165ed0188ac00000000" } diff --git a/test/util/defi-util-test.py b/test/util/defi-util-test.py index 57efa64198..9ae39452e8 100755 --- a/test/util/defi-util-test.py +++ b/test/util/defi-util-test.py @@ -10,16 +10,17 @@ Can also be run manually.""" import argparse -#import binascii # TODO: (temp) it's used in bctest +# import binascii # TODO: (temp) it's used in bctest import configparser -#import difflib # TODO: (temp) it's used in bctest +# import difflib # TODO: (temp) it's used in bctest import json import logging import os import pprint -#import subprocess # TODO: (temp) it's used in bctest +# import subprocess # TODO: (temp) it's used in bctest import sys + def main(): config = configparser.ConfigParser() config.optionxform = str @@ -41,6 +42,7 @@ def main(): bctester(os.path.join(env_conf["SRCDIR"], "test", "util", "data"), "defi-util-test.json", env_conf) + def bctester(testDir, input_basename, buildenv): """ Loads and parses the input file, runs all tests and reports results""" input_filename = os.path.join(testDir, input_basename) @@ -53,7 +55,7 @@ def bctester(testDir, input_basename, buildenv): try: bctest(testDir, testObj, buildenv) logging.info("PASSED: " + testObj["description"]) - except: + except Exception: logging.info("FAILED: " + testObj["description"]) failed_testcases.append(testObj["description"]) @@ -65,6 +67,7 @@ def bctester(testDir, input_basename, buildenv): else: sys.exit(0) + def bctest(testDir, testObj, buildenv): """Runs a single test, comparing output and RC to expected output and RC. @@ -160,6 +163,8 @@ def bctest(testDir, testObj, buildenv): # if want_error not in outs[1]: # logging.error("Error mismatch:\n" + "Expected: " + want_error + "\nReceived: " + outs[1].rstrip()) # raise Exception + + # # def parse_output(a, fmt): # """Parse the output according to specified format. diff --git a/test/util/rpcauth-test.py b/test/util/rpcauth-test.py index 9cb7d31bd3..1cd3681e4f 100755 --- a/test/util/rpcauth-test.py +++ b/test/util/rpcauth-test.py @@ -12,12 +12,13 @@ import sys import unittest + class TestRPCAuth(unittest.TestCase): def setUp(self): config = configparser.ConfigParser() config_path = os.path.abspath( os.path.join(os.sep, os.path.abspath(os.path.dirname(__file__)), - "../config.ini")) + "../config.ini")) with open(config_path, encoding="utf8") as config_file: config.read_file(config_file) sys.path.insert(0, os.path.dirname(config['environment']['RPCAUTH'])) @@ -39,10 +40,11 @@ def test_check_password_hmac(self): password_hmac = self.rpcauth.password_to_hmac(salt, password) m = hmac.new(bytearray(salt, 'utf-8'), - bytearray(password, 'utf-8'), 'SHA256') + bytearray(password, 'utf-8'), 'SHA256') expected_password_hmac = m.hexdigest() self.assertEqual(expected_password_hmac, password_hmac) + if __name__ == '__main__': unittest.main()