mirror of https://gitlab.syncad.com/hive/hive.git
Methods needed to networks creation are inserted into newly created `shared_tools` package
This commit is contained in:
parent
85506512b9
commit
cd93185c44
|
@ -231,7 +231,7 @@ plugin_test:
|
|||
before_script:
|
||||
- python3 -m venv venv/
|
||||
- . venv/bin/activate
|
||||
- pip3 install pytest==${PYTEST_VERSION} pytest-xdist==${PYTEST_XDIST_VERSION} pytest-timeout==${PYTEST_TIMEOUT_VERSION} "$CI_PROJECT_DIR/tests/test_tools" "$CI_PROJECT_DIR/tests/schemas"
|
||||
- pip3 install pytest==${PYTEST_VERSION} pytest-xdist==${PYTEST_XDIST_VERSION} pytest-timeout==${PYTEST_TIMEOUT_VERSION} "$CI_PROJECT_DIR/tests/test_tools" "$CI_PROJECT_DIR/tests/schemas" "$CI_PROJECT_DIR/tests/shared_tools"
|
||||
artifacts:
|
||||
reports:
|
||||
junit: $JUNIT_REPORT
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
import datetime
|
||||
|
||||
import pytest
|
||||
|
||||
import test_tools as tt
|
||||
|
||||
from ..local_tools import parse_datetime
|
||||
|
||||
|
||||
def test_transaction(wallet):
|
||||
wallet.api.create_account('initminer', 'carol', '{}')
|
||||
|
@ -39,7 +35,7 @@ def test_transaction(wallet):
|
|||
|
||||
_expiration = response['expiration']
|
||||
|
||||
parsed_t = parse_datetime(_expiration)
|
||||
parsed_t = tt.Time.parse(_expiration)
|
||||
t_in_seconds = parsed_t.timestamp()
|
||||
tt.logger.info('_time: {} seconds:{}...'.format(_expiration, t_in_seconds))
|
||||
|
||||
|
@ -56,7 +52,7 @@ def test_transaction(wallet):
|
|||
|
||||
_expiration = response['expiration']
|
||||
|
||||
parsed_t = parse_datetime(_expiration)
|
||||
parsed_t = tt.Time.parse(_expiration)
|
||||
t_in_seconds = parsed_t.timestamp()
|
||||
tt.logger.info('_time: {} seconds:{}...'.format(_expiration, t_in_seconds))
|
||||
|
||||
|
|
|
@ -3,54 +3,22 @@ from typing import Dict
|
|||
|
||||
import pytest
|
||||
|
||||
import test_tools as tt
|
||||
from shared_tools.complex_networks import (allow_generate_block_log,
|
||||
prepare_network_with_many_witnesses,
|
||||
prepare_sub_networks)
|
||||
|
||||
from .local_tools import run_networks, display_info, prepare_sub_networks, allow_generate_block_log, create_block_log_directory_name
|
||||
|
||||
def create_block_log_directory_name(name : str):
|
||||
return str(Path(__file__).parent.absolute()) + '/' + name
|
||||
|
||||
@pytest.fixture
|
||||
def prepared_networks() -> Dict:
|
||||
"""
|
||||
Fixture consists of 1 init node, 8 witness nodes and 2 api nodes.
|
||||
After fixture creation there are 21 active witnesses, and last irreversible block
|
||||
is behind head block like in real network.
|
||||
"""
|
||||
|
||||
tt.logger.info('Preparing fixture prepared_networks')
|
||||
alpha_witness_names = [f'witness{i}-alpha' for i in range(10)]
|
||||
beta_witness_names = [f'witness{i}-beta' for i in range(10)]
|
||||
all_witness_names = alpha_witness_names + beta_witness_names
|
||||
|
||||
# Create first network
|
||||
alpha_net = tt.Network() # TODO: Add network name prefix, e.g. AlphaNetwork0 (Alpha- is custom prefix)
|
||||
init_node = tt.InitNode(network=alpha_net)
|
||||
tt.WitnessNode(witnesses=[f'witness{i}-alpha' for i in range(0, 3)], network=alpha_net)
|
||||
tt.WitnessNode(witnesses=[f'witness{i}-alpha' for i in range(3, 6)], network=alpha_net)
|
||||
tt.WitnessNode(witnesses=[f'witness{i}-alpha' for i in range(6, 8)], network=alpha_net)
|
||||
tt.WitnessNode(witnesses=[f'witness{i}-alpha' for i in range(8, 10)], network=alpha_net)
|
||||
alpha_api_node = tt.ApiNode(network=alpha_net)
|
||||
|
||||
# Create second network
|
||||
beta_net = tt.Network() # TODO: Add network name prefix, e.g. AlphaNetwork0 (Alpha- is custom prefix)
|
||||
tt.WitnessNode(witnesses=[f'witness{i}-beta' for i in range(0, 3)], network=beta_net)
|
||||
tt.WitnessNode(witnesses=[f'witness{i}-beta' for i in range(3, 6)], network=beta_net)
|
||||
tt.WitnessNode(witnesses=[f'witness{i}-beta' for i in range(6, 8)], network=beta_net)
|
||||
tt.WitnessNode(witnesses=[f'witness{i}-beta' for i in range(8, 10)], network=beta_net)
|
||||
tt.ApiNode(network=beta_net)
|
||||
|
||||
blocklog_directory = Path(__file__).parent / 'block_log'
|
||||
run_networks([alpha_net, beta_net], blocklog_directory)
|
||||
|
||||
wallet = tt.Wallet(attach_to=init_node)
|
||||
|
||||
display_info(wallet)
|
||||
|
||||
def prepare_basic_networks() -> Dict:
|
||||
alpha_net, beta_net = prepare_network_with_many_witnesses(create_block_log_directory_name('block_log'))
|
||||
yield {
|
||||
'Alpha': alpha_net,
|
||||
'Beta': beta_net,
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def prepare_sub_networks_10_11() -> Dict:
|
||||
yield { 'sub-networks-data': prepare_sub_networks([10, 11]) }
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import test_tools as tt
|
||||
|
||||
|
||||
def test_enum_virtual_ops(prepared_networks):
|
||||
def test_enum_virtual_ops(prepare_basic_networks):
|
||||
# Test enum_virtual_ops for head block returns only virtual ops
|
||||
api_node = prepared_networks['Alpha'].node('ApiNode0')
|
||||
api_node = prepare_basic_networks['Alpha'].node('ApiNode0')
|
||||
wallet = tt.Wallet(attach_to=api_node)
|
||||
|
||||
account_name = 'gamma-1'
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
from .local_tools import assert_no_duplicates, connect_sub_networks, disconnect_sub_networks, wait, fork_log, \
|
||||
get_last_head_block_number, get_last_irreversible_block_num, wait_for_final_block, lib_true_condition
|
||||
from shared_tools.complex_networks_helper_functions import *
|
||||
import test_tools as tt
|
||||
|
||||
def test_fork_2_sub_networks_00(prepare_fork_2_sub_networks_00):
|
||||
|
@ -21,8 +20,8 @@ def test_fork_2_sub_networks_00(prepare_fork_2_sub_networks_00):
|
|||
|
||||
logs = []
|
||||
|
||||
logs.append(fork_log("M", tt.Wallet(attach_to = majority_api_node)))
|
||||
logs.append(fork_log("m", tt.Wallet(attach_to = minority_api_node)))
|
||||
logs.append(NodeLog("M", tt.Wallet(attach_to = majority_api_node)))
|
||||
logs.append(NodeLog("m", tt.Wallet(attach_to = minority_api_node)))
|
||||
|
||||
_M = logs[0].collector
|
||||
_m = logs[1].collector
|
||||
|
@ -30,7 +29,7 @@ def test_fork_2_sub_networks_00(prepare_fork_2_sub_networks_00):
|
|||
blocks_before_disconnect = 10
|
||||
|
||||
tt.logger.info(f'Before disconnecting')
|
||||
cnt = 0
|
||||
cnt = 0
|
||||
while True:
|
||||
wait(1, logs, majority_api_node)
|
||||
|
||||
|
@ -56,4 +55,4 @@ def test_fork_2_sub_networks_00(prepare_fork_2_sub_networks_00):
|
|||
|
||||
wait_for_final_block(majority_api_node, logs, [_m, _M], True, lib_true_condition, False)
|
||||
|
||||
assert_no_duplicates(minority_api_node, majority_api_node)
|
||||
assert_no_duplicates(minority_api_node, majority_api_node)
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
from .local_tools import enable_witnesses, disable_witnesses, get_part_of_witness_details, assert_no_duplicates, connect_sub_networks, \
|
||||
disconnect_sub_networks, wait, fork_log, get_last_head_block_number, get_last_irreversible_block_num, wait_for_final_block, lib_custom_condition
|
||||
import test_tools as tt
|
||||
|
||||
from functools import partial
|
||||
|
||||
from shared_tools.complex_networks_helper_functions import *
|
||||
import test_tools as tt
|
||||
|
||||
def test_fork_2_sub_networks_01(prepare_fork_2_sub_networks_01):
|
||||
# start - A network (consists of a 'minority' network(6 witnesses) + a 'majority' network(17 witnesses)) produces blocks
|
||||
|
||||
|
@ -38,8 +38,8 @@ def test_fork_2_sub_networks_01(prepare_fork_2_sub_networks_01):
|
|||
|
||||
logs = []
|
||||
|
||||
logs.append(fork_log("M", tt.Wallet(attach_to = majority_api_node)))
|
||||
logs.append(fork_log("m", tt.Wallet(attach_to = minority_api_node)))
|
||||
logs.append(NodeLog("M", tt.Wallet(attach_to = majority_api_node)))
|
||||
logs.append(NodeLog("m", tt.Wallet(attach_to = minority_api_node)))
|
||||
|
||||
_M = logs[0].collector
|
||||
_m = logs[1].collector
|
||||
|
@ -54,7 +54,7 @@ def test_fork_2_sub_networks_01(prepare_fork_2_sub_networks_01):
|
|||
blocks_after_enable_witness = 5
|
||||
|
||||
tt.logger.info(f'Before disconnecting')
|
||||
cnt = 0
|
||||
cnt = 0
|
||||
while True:
|
||||
wait(1, logs, majority_api_node)
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
from .local_tools import enable_witnesses, disable_witnesses, get_part_of_witness_details, assert_no_duplicates, connect_sub_networks,\
|
||||
disconnect_sub_networks, wait, fork_log, get_last_head_block_number, get_last_irreversible_block_num, wait_for_final_block, lib_true_condition
|
||||
from shared_tools.complex_networks_helper_functions import *
|
||||
import test_tools as tt
|
||||
|
||||
def test_fork_2_sub_networks_02(prepare_fork_2_sub_networks_02):
|
||||
|
@ -38,8 +37,8 @@ def test_fork_2_sub_networks_02(prepare_fork_2_sub_networks_02):
|
|||
|
||||
logs = []
|
||||
|
||||
logs.append(fork_log("M", majority_witness_wallet))
|
||||
logs.append(fork_log("m", tt.Wallet(attach_to = minority_api_node)))
|
||||
logs.append(NodeLog("M", majority_witness_wallet))
|
||||
logs.append(NodeLog("m", tt.Wallet(attach_to = minority_api_node)))
|
||||
|
||||
_M = logs[0].collector
|
||||
_m = logs[1].collector
|
||||
|
@ -55,7 +54,7 @@ def test_fork_2_sub_networks_02(prepare_fork_2_sub_networks_02):
|
|||
blocks_after_reconnect = 5
|
||||
|
||||
tt.logger.info(f'Before disconnecting')
|
||||
cnt = 0
|
||||
cnt = 0
|
||||
while True:
|
||||
wait(1, logs, majority_api_node)
|
||||
|
||||
|
@ -98,4 +97,4 @@ def test_fork_2_sub_networks_02(prepare_fork_2_sub_networks_02):
|
|||
|
||||
wait_for_final_block(minority_api_node, logs, [_m, _M], True, lib_true_condition, False)
|
||||
|
||||
assert_no_duplicates(minority_api_node, majority_api_node)
|
||||
assert_no_duplicates(minority_api_node, majority_api_node)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
from .local_tools import enable_witnesses, disable_witnesses, get_part_of_witness_details, assert_no_duplicates, connect_sub_networks, \
|
||||
disconnect_sub_networks, wait, fork_log, get_last_head_block_number, get_last_irreversible_block_num, wait_for_final_block, lib_true_condition
|
||||
import test_tools as tt
|
||||
from time import sleep
|
||||
|
||||
from shared_tools.complex_networks_helper_functions import *
|
||||
import test_tools as tt
|
||||
|
||||
def test_fork_2_sub_networks_03(prepare_fork_2_sub_networks_03):
|
||||
# start - A network (consists of a 'minority' network(3 witnesses) + a 'majority' network(18 witnesses)) produces blocks
|
||||
|
||||
|
@ -40,8 +40,8 @@ def test_fork_2_sub_networks_03(prepare_fork_2_sub_networks_03):
|
|||
|
||||
logs = []
|
||||
|
||||
logs.append(fork_log("M", majority_witness_wallet))
|
||||
logs.append(fork_log("m", tt.Wallet(attach_to = minority_api_node)))
|
||||
logs.append(NodeLog("M", majority_witness_wallet))
|
||||
logs.append(NodeLog("m", tt.Wallet(attach_to = minority_api_node)))
|
||||
|
||||
_M = logs[0].collector
|
||||
_m = logs[1].collector
|
||||
|
@ -51,7 +51,7 @@ def test_fork_2_sub_networks_03(prepare_fork_2_sub_networks_03):
|
|||
blocks_after_disable_witness = 10
|
||||
|
||||
tt.logger.info(f'Before disconnecting')
|
||||
cnt = 0
|
||||
cnt = 0
|
||||
while True:
|
||||
wait(1, logs, majority_api_node)
|
||||
|
||||
|
@ -74,7 +74,7 @@ def test_fork_2_sub_networks_03(prepare_fork_2_sub_networks_03):
|
|||
|
||||
tt.logger.info(f'Reconnect sub networks')
|
||||
connect_sub_networks(sub_networks)
|
||||
|
||||
|
||||
sleep_seconds = 20
|
||||
tt.logger.info(f'Before sleep {sleep_seconds}')
|
||||
sleep(sleep_seconds)
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
from .local_tools import connect_sub_networks, disconnect_sub_networks, wait, fork_log, get_last_head_block_number, \
|
||||
get_last_irreversible_block_num, wait_for_final_block, lib_custom_condition
|
||||
|
||||
import test_tools as tt
|
||||
|
||||
from functools import partial
|
||||
|
||||
from shared_tools.complex_networks_helper_functions import *
|
||||
import test_tools as tt
|
||||
|
||||
def test_fork_3_sub_networks_00(prepare_fork_3_sub_networks_00):
|
||||
# start - A network consists of a 'minority_3' network(3 witnesses), a 'minority_4' network(4 witnesses), a 'majority' network(14 witnesses).
|
||||
|
||||
|
@ -23,9 +21,9 @@ def test_fork_3_sub_networks_00(prepare_fork_3_sub_networks_00):
|
|||
|
||||
logs = []
|
||||
|
||||
logs.append(fork_log("m3", tt.Wallet(attach_to = minority_api_node_3)))
|
||||
logs.append(fork_log("m4", tt.Wallet(attach_to = minority_api_node_4)))
|
||||
logs.append(fork_log("M", tt.Wallet(attach_to = majority_api_node)))
|
||||
logs.append(NodeLog("m3", tt.Wallet(attach_to = minority_api_node_3)))
|
||||
logs.append(NodeLog("m4", tt.Wallet(attach_to = minority_api_node_4)))
|
||||
logs.append(NodeLog("M", tt.Wallet(attach_to = majority_api_node)))
|
||||
|
||||
_m3 = logs[0].collector
|
||||
_m4 = logs[1].collector
|
||||
|
@ -35,7 +33,7 @@ def test_fork_3_sub_networks_00(prepare_fork_3_sub_networks_00):
|
|||
blocks_after_disconnect = 10
|
||||
|
||||
tt.logger.info(f'Before disconnecting')
|
||||
cnt = 0
|
||||
cnt = 0
|
||||
while True:
|
||||
wait(1, logs, majority_api_node)
|
||||
|
||||
|
@ -60,4 +58,4 @@ def test_fork_3_sub_networks_00(prepare_fork_3_sub_networks_00):
|
|||
tt.logger.info(f'Reconnect sub networks')
|
||||
connect_sub_networks(sub_networks)
|
||||
|
||||
wait_for_final_block(majority_api_node, logs, [_m3, _m4, _M], True, partial(lib_custom_condition, _M, last_lib), False)
|
||||
wait_for_final_block(majority_api_node, logs, [_m3, _m4, _M], True, partial(lib_custom_condition, _M, last_lib), False)
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
from .local_tools import connect_sub_networks, disconnect_sub_networks, wait, fork_log, get_last_head_block_number, get_last_irreversible_block_num, \
|
||||
wait_for_final_block, lib_custom_condition
|
||||
|
||||
import test_tools as tt
|
||||
|
||||
from functools import partial
|
||||
|
||||
from shared_tools.complex_networks_helper_functions import *
|
||||
import test_tools as tt
|
||||
|
||||
def test_fork_3_sub_networks_01(prepare_fork_3_sub_networks_01):
|
||||
# start - A network consists of a 'minority_7a' network(7 witnesses), a 'minority_7b' network(7 witnesses), a 'minority_7c' network(7 witnesses).
|
||||
|
||||
|
@ -23,9 +21,9 @@ def test_fork_3_sub_networks_01(prepare_fork_3_sub_networks_01):
|
|||
|
||||
logs = []
|
||||
|
||||
logs.append(fork_log("m7a", tt.Wallet(attach_to = minority_api_node_7a)))
|
||||
logs.append(fork_log("m7b", tt.Wallet(attach_to = minority_api_node_7b)))
|
||||
logs.append(fork_log("m7c", tt.Wallet(attach_to = minority_api_node_7c)))
|
||||
logs.append(NodeLog("m7a", tt.Wallet(attach_to = minority_api_node_7a)))
|
||||
logs.append(NodeLog("m7b", tt.Wallet(attach_to = minority_api_node_7b)))
|
||||
logs.append(NodeLog("m7c", tt.Wallet(attach_to = minority_api_node_7c)))
|
||||
|
||||
_m7a = logs[0].collector
|
||||
_m7b = logs[1].collector
|
||||
|
@ -35,7 +33,7 @@ def test_fork_3_sub_networks_01(prepare_fork_3_sub_networks_01):
|
|||
blocks_after_disconnect = 10
|
||||
|
||||
tt.logger.info(f'Before disconnecting')
|
||||
cnt = 0
|
||||
cnt = 0
|
||||
while True:
|
||||
wait(1, logs, minority_api_node_7a)
|
||||
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
import test_tools as tt
|
||||
|
||||
from .local_tools import assert_no_duplicates
|
||||
from shared_tools.complex_networks_helper_functions import *
|
||||
|
||||
|
||||
def test_no_duplicates_in_account_history_plugin_after_fork(prepared_networks):
|
||||
alpha_net = prepared_networks['Alpha']
|
||||
beta_net = prepared_networks['Beta']
|
||||
def test_no_duplicates_in_account_history_plugin_after_fork(prepare_basic_networks):
|
||||
alpha_net = prepare_basic_networks['Alpha']
|
||||
beta_net = prepare_basic_networks['Beta']
|
||||
|
||||
alpha_node = alpha_net.node('ApiNode0')
|
||||
beta_node = beta_net.node('ApiNode1')
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import test_tools as tt
|
||||
|
||||
from .local_tools import assert_no_duplicates
|
||||
from shared_tools.complex_networks_helper_functions import assert_no_duplicates
|
||||
|
||||
|
||||
def test_no_duplicates_in_account_history_plugin_after_restart(prepared_networks):
|
||||
def test_no_duplicates_in_account_history_plugin_after_restart(prepare_basic_networks):
|
||||
# TRIGGER
|
||||
# We restart one of nodes.
|
||||
api_node = prepared_networks['Alpha'].node('ApiNode0')
|
||||
api_node = prepare_basic_networks['Alpha'].node('ApiNode0')
|
||||
|
||||
head_block_num = api_node.api.condenser.get_dynamic_global_properties()['head_block_number']
|
||||
head_block_timestamp = api_node.api.block.get_block(block_num=head_block_num)['block']['timestamp']
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
from .local_tools import wait, fork_log, get_last_head_block_number, get_last_irreversible_block_num, wait_for_final_block, wait_for_specific_witnesses
|
||||
import test_tools as tt
|
||||
import time
|
||||
|
||||
from shared_tools.complex_networks_helper_functions import (
|
||||
wait,
|
||||
get_last_head_block_number,
|
||||
get_last_irreversible_block_num,
|
||||
wait_for_final_block,
|
||||
wait_for_specific_witnesses,
|
||||
NodeLog
|
||||
)
|
||||
|
||||
def test_obi_throw_exception_00(prepare_obi_throw_exception_00):
|
||||
# start - A network (consists of a 'A' network(10 witnesses) + a 'B' network(11 witnesses)) produces blocks
|
||||
|
@ -20,11 +27,11 @@ def test_obi_throw_exception_00(prepare_obi_throw_exception_00):
|
|||
|
||||
logs = []
|
||||
|
||||
logs.append(fork_log("a0", tt.Wallet(attach_to = api_node_0)))
|
||||
logs.append(fork_log("w0", tt.Wallet(attach_to = witness_node_0)))
|
||||
logs.append(NodeLog("a0", tt.Wallet(attach_to = api_node_0)))
|
||||
logs.append(NodeLog("w0", tt.Wallet(attach_to = witness_node_0)))
|
||||
|
||||
logs.append(fork_log("a1", tt.Wallet(attach_to = api_node_1)))
|
||||
logs.append(fork_log("w1", tt.Wallet(attach_to = witness_node_1)))
|
||||
logs.append(NodeLog("a1", tt.Wallet(attach_to = api_node_1)))
|
||||
logs.append(NodeLog("w1", tt.Wallet(attach_to = witness_node_1)))
|
||||
|
||||
blocks_after_exception = 5
|
||||
blocks_wait = 1
|
||||
|
@ -52,4 +59,4 @@ def test_obi_throw_exception_00(prepare_obi_throw_exception_00):
|
|||
|
||||
assert get_last_head_block_number(_a0) > last_lib_01
|
||||
|
||||
wait_for_final_block(witness_node_0, logs, [_a0, _w0, _a1, _w1])
|
||||
wait_for_final_block(witness_node_0, logs, [_a0, _w0, _a1, _w1])
|
||||
|
|
|
@ -1,7 +1,15 @@
|
|||
from .local_tools import wait, fork_log, get_last_head_block_number, get_last_irreversible_block_num, wait_for_specific_witnesses
|
||||
import test_tools as tt
|
||||
import time
|
||||
|
||||
import test_tools as tt
|
||||
|
||||
from shared_tools.complex_networks_helper_functions import (
|
||||
wait,
|
||||
get_last_head_block_number,
|
||||
get_last_irreversible_block_num,
|
||||
wait_for_specific_witnesses,
|
||||
NodeLog
|
||||
)
|
||||
|
||||
def test_obi_throw_exception_01(prepare_obi_throw_exception_01):
|
||||
# start - A network (consists of a 'A' network(10 witnesses) + a 'B' network(11 witnesses)) produces blocks
|
||||
|
||||
|
@ -49,11 +57,11 @@ def test_obi_throw_exception_01(prepare_obi_throw_exception_01):
|
|||
|
||||
logs = []
|
||||
|
||||
logs.append(fork_log("a0", tt.Wallet(attach_to = api_node_0)))
|
||||
logs.append(fork_log("w0", tt.Wallet(attach_to = witness_node_0)))
|
||||
logs.append(NodeLog("a0", tt.Wallet(attach_to = api_node_0)))
|
||||
logs.append(NodeLog("w0", tt.Wallet(attach_to = witness_node_0)))
|
||||
|
||||
logs.append(fork_log("a1", tt.Wallet(attach_to = api_node_1)))
|
||||
logs.append(fork_log("w1", tt.Wallet(attach_to = witness_node_1)))
|
||||
logs.append(NodeLog("a1", tt.Wallet(attach_to = api_node_1)))
|
||||
logs.append(NodeLog("w1", tt.Wallet(attach_to = witness_node_1)))
|
||||
|
||||
blocks_after_exception = 20
|
||||
delay_seconds = 5
|
||||
|
|
|
@ -1,7 +1,16 @@
|
|||
from .local_tools import wait, fork_log, get_last_head_block_number, get_last_irreversible_block_num, wait_for_final_block, wait_for_specific_witnesses
|
||||
import test_tools as tt
|
||||
import time
|
||||
|
||||
import test_tools as tt
|
||||
|
||||
from shared_tools.complex_networks_helper_functions import (
|
||||
wait,
|
||||
get_last_head_block_number,
|
||||
get_last_irreversible_block_num,
|
||||
wait_for_final_block,
|
||||
wait_for_specific_witnesses,
|
||||
NodeLog
|
||||
)
|
||||
|
||||
def test_obi_throw_exception_02(prepare_obi_throw_exception_02):
|
||||
# start - A network (consists of a 'A' network(10 witnesses) + a 'B' network(11 witnesses)) produces blocks
|
||||
|
||||
|
@ -22,11 +31,11 @@ def test_obi_throw_exception_02(prepare_obi_throw_exception_02):
|
|||
|
||||
logs = []
|
||||
|
||||
logs.append(fork_log("a0", tt.Wallet(attach_to = api_node_0)))
|
||||
logs.append(fork_log("w0", tt.Wallet(attach_to = witness_node_0)))
|
||||
logs.append(NodeLog("a0", tt.Wallet(attach_to = api_node_0)))
|
||||
logs.append(NodeLog("w0", tt.Wallet(attach_to = witness_node_0)))
|
||||
|
||||
logs.append(fork_log("a1", tt.Wallet(attach_to = api_node_1)))
|
||||
logs.append(fork_log("w1", tt.Wallet(attach_to = witness_node_1)))
|
||||
logs.append(NodeLog("a1", tt.Wallet(attach_to = api_node_1)))
|
||||
logs.append(NodeLog("w1", tt.Wallet(attach_to = witness_node_1)))
|
||||
|
||||
_a0 = logs[0].collector
|
||||
_w0 = logs[1].collector
|
||||
|
@ -57,4 +66,4 @@ def test_obi_throw_exception_02(prepare_obi_throw_exception_02):
|
|||
|
||||
assert get_last_head_block_number(_a0) > last_lib_01 + 1
|
||||
|
||||
wait_for_final_block(witness_node_0, logs, [_a0, _w0, _a1, _w1])
|
||||
wait_for_final_block(witness_node_0, logs, [_a0, _w0, _a1, _w1])
|
||||
|
|
|
@ -1,8 +1,15 @@
|
|||
from typing import Dict, Optional
|
||||
|
||||
import pytest
|
||||
|
||||
import test_tools as tt
|
||||
|
||||
from .local_tools import run_with_faketime, prepare_environment, prepare_environment_with_2_sub_networks
|
||||
from shared_tools.complex_networks import init_network
|
||||
|
||||
def run_with_faketime(node, time):
|
||||
#time example: '2020-01-01T00:00:00'
|
||||
requested_start_time = tt.Time.parse(time)
|
||||
node.run(time_offset=f'{tt.Time.serialize(requested_start_time, format_="@%Y-%m-%d %H:%M:%S")}')
|
||||
|
||||
@pytest.fixture
|
||||
def node_hf25() -> tt.InitNode:
|
||||
|
@ -28,6 +35,81 @@ def wallet_hf26(node_hf26) -> tt.Wallet:
|
|||
return tt.Wallet(attach_to=node_hf26)
|
||||
|
||||
|
||||
def prepare_network(
|
||||
witnesses_number: int, network_name: str, allow_create_init_node: bool, allow_create_api_node: bool
|
||||
):
|
||||
tt.logger.info(f'Prototypes of nodes(init, witness, api) are created...')
|
||||
|
||||
witness_names = [f'wit{i}-{network_name}' for i in range(witnesses_number)]
|
||||
|
||||
network = tt.Network()
|
||||
|
||||
init_node = None
|
||||
if allow_create_init_node:
|
||||
init_node = tt.InitNode(network=network)
|
||||
|
||||
tt.WitnessNode(witnesses=witness_names, network=network)
|
||||
|
||||
api_node = None
|
||||
if allow_create_api_node:
|
||||
api_node = tt.ApiNode(network=network)
|
||||
|
||||
return witness_names, network, init_node, api_node
|
||||
|
||||
|
||||
def prepare_environment(hard_fork_26_time):
|
||||
all_witness_names, alpha_net, init_node, api_node = prepare_network(
|
||||
witnesses_number=20, network_name='alpha', allow_create_init_node=True, allow_create_api_node=True
|
||||
)
|
||||
|
||||
# Run
|
||||
tt.logger.info('Running networks, waiting for live...')
|
||||
date_as_seconds = calculate_epoch_time(hard_fork_26_time)
|
||||
environment_variables: Optional[Dict] = {'HIVE_HF26_TIME': f'{date_as_seconds}'}
|
||||
alpha_net.run(environment_variables)
|
||||
|
||||
init_network(init_node, all_witness_names)
|
||||
|
||||
return alpha_net
|
||||
|
||||
|
||||
def prepare_environment_with_2_sub_networks(hard_fork_26_time_alpha, hard_fork_26_time_beta):
|
||||
#Because HIVE_HARDFORK_REQUIRED_WITNESSES = 17 // 17 of the 21 dpos witnesses (20 elected and 1 chosen) required for hardfork
|
||||
witness_names_alpha, alpha_net, init_node, api_node = prepare_network(
|
||||
witnesses_number=8, network_name='alpha', allow_create_init_node=True, allow_create_api_node=True
|
||||
)
|
||||
witness_names_beta, beta_net, init_node2, api_node2 = prepare_network(
|
||||
witnesses_number=12, network_name='beta', allow_create_init_node=False, allow_create_api_node=False
|
||||
)
|
||||
|
||||
all_witness_names = witness_names_alpha + witness_names_beta
|
||||
|
||||
alpha_net.connect_with(beta_net)
|
||||
|
||||
# Run
|
||||
tt.logger.info('Running networks, waiting for live...')
|
||||
|
||||
date_as_seconds = calculate_epoch_time(hard_fork_26_time_alpha)
|
||||
environment_variables_alpha: Optional[Dict] = {'HIVE_HF26_TIME': f'{date_as_seconds}'}
|
||||
|
||||
date_as_seconds = calculate_epoch_time(hard_fork_26_time_beta)
|
||||
environment_variables_beta: Optional[Dict] = {'HIVE_HF26_TIME': f'{date_as_seconds}'}
|
||||
|
||||
# June 20, 2032 9:45:38 AM
|
||||
alpha_net.run(environment_variables_alpha)
|
||||
|
||||
# June 1, 2022 7:41:41 AM
|
||||
beta_net.run(environment_variables_beta)
|
||||
|
||||
init_network(init_node, all_witness_names)
|
||||
|
||||
return alpha_net, beta_net
|
||||
|
||||
|
||||
def calculate_epoch_time(date):
|
||||
return int(tt.Time.parse(date).timestamp())
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def network_before_hf26():
|
||||
tt.logger.info('Preparing fixture network_before_hf26')
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
from datetime import timezone
|
||||
from datetime import datetime, timezone
|
||||
from typing import Dict, Optional
|
||||
|
||||
import pytest
|
||||
|
||||
import test_tools as tt
|
||||
|
||||
from ..local_tools import init_network, parse_datetime
|
||||
from shared_tools.complex_networks import init_network
|
||||
|
||||
def parse_datetime(datetime_: str) -> datetime:
|
||||
return datetime.strptime(datetime_, '%Y-%m-%dT%H:%M:%S')
|
||||
|
||||
def prepare_wallets(api_node):
|
||||
tt.logger.info( "Attaching legacy/hf26 wallets..." )
|
||||
|
|
|
@ -1,79 +0,0 @@
|
|||
from datetime import datetime
|
||||
|
||||
from typing import List
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import os
|
||||
|
||||
import test_tools as tt
|
||||
|
||||
def parse_datetime(datetime_: str) -> datetime:
|
||||
return datetime.strptime(datetime_, '%Y-%m-%dT%H:%M:%S')
|
||||
|
||||
def init_network( init_node, all_witness_names : List[str], key : str = None, block_log_directory_name : str = None):
|
||||
|
||||
tt.logger.info('Attaching wallets...')
|
||||
wallet = tt.Wallet(attach_to=init_node)
|
||||
# We are waiting here for block 43, because witness participation is counting
|
||||
# by dividing total produced blocks in last 128 slots by 128. When we were waiting
|
||||
# too short, for example 42 blocks, then participation equals 42 / 128 = 32.81%.
|
||||
# It is not enough, because 33% is required. 43 blocks guarantee, that this
|
||||
# requirement is always fulfilled (43 / 128 = 33.59%, which is greater than 33%).
|
||||
tt.logger.info('Wait for block 43 (to fulfill required 33% of witness participation)')
|
||||
init_node.wait_for_block_with_number(43)
|
||||
|
||||
# Prepare witnesses on blockchain
|
||||
with wallet.in_single_transaction():
|
||||
for name in all_witness_names:
|
||||
if key is None:
|
||||
wallet.api.create_account('initminer', name, '')
|
||||
else:
|
||||
wallet.api.create_account_with_keys('initminer', name, '', key, key, key, key)
|
||||
with wallet.in_single_transaction():
|
||||
for name in all_witness_names:
|
||||
wallet.api.transfer_to_vesting("initminer", name, tt.Asset.Test(1000))
|
||||
with wallet.in_single_transaction():
|
||||
for name in all_witness_names:
|
||||
wallet.api.update_witness(
|
||||
name, "https://" + name,
|
||||
tt.Account(name).public_key,
|
||||
{"account_creation_fee": tt.Asset.Test(3), "maximum_block_size": 65536, "sbd_interest_rate": 0}
|
||||
)
|
||||
|
||||
tt.logger.info('Wait 21 blocks to schedule newly created witnesses into future slate')
|
||||
init_node.wait_number_of_blocks(21)
|
||||
|
||||
future_witnesses = init_node.api.database.get_active_witnesses(include_future=True)["future_witnesses"]
|
||||
tt.logger.info(f"Future witnesses after voting: {future_witnesses}")
|
||||
assert len(future_witnesses) == 21
|
||||
|
||||
tt.logger.info('Wait 21 blocks for future slate to become active slate')
|
||||
init_node.wait_number_of_blocks(21)
|
||||
|
||||
active_witnesses = init_node.api.database.get_active_witnesses()["witnesses"]
|
||||
tt.logger.info(f"Witness state after voting: {active_witnesses}")
|
||||
assert len(active_witnesses) == 21
|
||||
|
||||
# Reason of this wait is to enable moving forward of irreversible block
|
||||
tt.logger.info('Wait 21 blocks (when every witness sign at least one block)')
|
||||
init_node.wait_number_of_blocks(21)
|
||||
|
||||
result = wallet.api.info()
|
||||
head_block_num = result['head_block_number']
|
||||
timestamp = init_node.api.block.get_block(block_num=head_block_num)['block']['timestamp']
|
||||
tt.logger.info(f'head block timestamp: {timestamp}')
|
||||
|
||||
if block_log_directory_name is not None:
|
||||
if os.path.exists(block_log_directory_name):
|
||||
Path(block_log_directory_name + '/block_log').unlink(missing_ok=True)
|
||||
else:
|
||||
os.mkdir(block_log_directory_name)
|
||||
|
||||
init_node.close()
|
||||
init_node.block_log.copy_to(block_log_directory_name)
|
||||
|
||||
with open(block_log_directory_name + '/timestamp', 'w') as f:
|
||||
f.write(f'{timestamp}')
|
||||
|
||||
return wallet
|
|
@ -0,0 +1,233 @@
|
|||
import os
|
||||
from pathlib import Path
|
||||
from typing import Dict, Iterable, List
|
||||
|
||||
import test_tools as tt
|
||||
from .complex_networks_helper_functions import connect_sub_networks
|
||||
|
||||
|
||||
def get_relative_time_offset_from_file(file: Path):
|
||||
with open(file, "r", encoding="UTF-8") as file:
|
||||
timestamp = file.read().strip()
|
||||
|
||||
delta = tt.Time.now(serialize=False) - tt.Time.parse(timestamp)
|
||||
delta += tt.Time.seconds(5) # Node starting and entering live mode takes some time to complete
|
||||
return f'-{delta.total_seconds():.3f}s'
|
||||
|
||||
|
||||
def init_network(init_node, all_witness_names: List[str], key: str = None, block_log_directory_name: str = None):
|
||||
|
||||
tt.logger.info("Attaching wallets...")
|
||||
wallet = tt.Wallet(attach_to=init_node)
|
||||
# We are waiting here for block 43, because witness participation is counting
|
||||
# by dividing total produced blocks in last 128 slots by 128. When we were waiting
|
||||
# too short, for example 42 blocks, then participation equals 42 / 128 = 32.81%.
|
||||
# It is not enough, because 33% is required. 43 blocks guarantee, that this
|
||||
# requirement is always fulfilled (43 / 128 = 33.59%, which is greater than 33%).
|
||||
tt.logger.info("Wait for block 43 (to fulfill required 33% of witness participation)")
|
||||
init_node.wait_for_block_with_number(43)
|
||||
|
||||
# Prepare witnesses on blockchain
|
||||
with wallet.in_single_transaction():
|
||||
for name in all_witness_names:
|
||||
if key is None:
|
||||
wallet.api.create_account("initminer", name, "")
|
||||
else:
|
||||
wallet.api.create_account_with_keys("initminer", name, "", key, key, key, key)
|
||||
with wallet.in_single_transaction():
|
||||
for name in all_witness_names:
|
||||
wallet.api.transfer_to_vesting("initminer", name, tt.Asset.Test(1000))
|
||||
with wallet.in_single_transaction():
|
||||
for name in all_witness_names:
|
||||
wallet.api.update_witness(
|
||||
name,
|
||||
"https://" + name,
|
||||
tt.Account(name).public_key,
|
||||
{"account_creation_fee": tt.Asset.Test(3), "maximum_block_size": 65536, "sbd_interest_rate": 0},
|
||||
)
|
||||
future_witnesses = init_node.api.database.get_active_witnesses(include_future=True)["future_witnesses"]
|
||||
tt.logger.info(f"Future witnesses after voting: {future_witnesses}")
|
||||
assert len(future_witnesses) == 21
|
||||
|
||||
tt.logger.info("Wait 21 blocks to schedule newly created witnesses into future slate")
|
||||
init_node.wait_number_of_blocks(21)
|
||||
tt.logger.info("Wait 21 blocks for future slate to become active slate")
|
||||
init_node.wait_number_of_blocks(21)
|
||||
|
||||
active_witnesses = init_node.api.database.get_active_witnesses()["witnesses"]
|
||||
tt.logger.info(f"Witness state after voting: {active_witnesses}")
|
||||
assert len(active_witnesses) == 21
|
||||
|
||||
# Reason of this wait is to enable moving forward of irreversible block
|
||||
tt.logger.info("Wait 21 blocks (when every witness sign at least one block)")
|
||||
init_node.wait_number_of_blocks(21)
|
||||
|
||||
result = wallet.api.info()
|
||||
head_block_num = result["head_block_number"]
|
||||
timestamp = init_node.api.block.get_block(block_num=head_block_num)["block"]["timestamp"]
|
||||
tt.logger.info(f"head block timestamp: {timestamp}")
|
||||
|
||||
# If a directory of `block_log` is given then it"s possible to save 2 files:
|
||||
# 1) "block_log" file that contains whole saved network
|
||||
# 2) "timestamp" file that contains information about time what should be set by `libfaketime` library
|
||||
if block_log_directory_name is not None:
|
||||
# Prepare dedicated directory
|
||||
if Path(block_log_directory_name).exists():
|
||||
Path(block_log_directory_name + "/block_log").unlink(missing_ok=True)
|
||||
else:
|
||||
Path.mkdir(block_log_directory_name)
|
||||
|
||||
# Copy newly created "block_log" into dedicated directory
|
||||
init_node.close()
|
||||
init_node.block_log.copy_to(block_log_directory_name)
|
||||
|
||||
# Create "timestamp file"
|
||||
with Path(block_log_directory_name + "/timestamp").open(mode="w", encoding="UTF-8") as file_handle:
|
||||
file_handle.write(f"{timestamp}")
|
||||
|
||||
return wallet
|
||||
|
||||
|
||||
def run_networks(networks: Iterable[tt.Network], blocklog_directory: Path):
|
||||
if blocklog_directory is not None:
|
||||
time_offset = get_relative_time_offset_from_file(blocklog_directory / "timestamp")
|
||||
block_log = tt.BlockLog(blocklog_directory / "block_log")
|
||||
tt.logger.info(f"block_log directory: {blocklog_directory}")
|
||||
|
||||
tt.logger.info("Running nodes...")
|
||||
|
||||
connect_sub_networks(networks)
|
||||
|
||||
nodes = [node for network in networks for node in network.nodes]
|
||||
|
||||
info_nodes = ", ".join(str(node) for node in nodes)
|
||||
tt.logger.info(f"Following nodes exist in whole network: {info_nodes}")
|
||||
|
||||
if blocklog_directory is not None:
|
||||
nodes[0].run(wait_for_live=False, replay_from=block_log, time_offset=time_offset)
|
||||
else:
|
||||
nodes[0].run(wait_for_live=False)
|
||||
init_node_p2p_endpoint = nodes[0].p2p_endpoint
|
||||
for node in nodes[1:]:
|
||||
node.config.p2p_seed_node.append(init_node_p2p_endpoint)
|
||||
if blocklog_directory is not None:
|
||||
node.run(wait_for_live=False, replay_from=block_log, time_offset=time_offset)
|
||||
else:
|
||||
node.run(wait_for_live=False)
|
||||
|
||||
for network in networks:
|
||||
network.is_running = True
|
||||
|
||||
for node in nodes:
|
||||
tt.logger.debug(f"Waiting for {node} to be live...")
|
||||
node.wait_for_live_mode(tt.InitNode.DEFAULT_WAIT_FOR_LIVE_TIMEOUT)
|
||||
|
||||
|
||||
def display_info(wallet):
|
||||
# Network should be set up at this time, with 21 active witnesses, enough participation rate
|
||||
# and irreversible block number lagging behind around 15-20 blocks head block number
|
||||
result = wallet.api.info()
|
||||
irreversible = result["last_irreversible_block_num"]
|
||||
head = result["head_block_num"]
|
||||
tt.logger.info(f"Network prepared, irreversible block: {irreversible}, head block: {head}")
|
||||
|
||||
|
||||
def prepare_network_with_many_witnesses(block_log_directory_name: str = None) -> Dict:
|
||||
"""
|
||||
Fixture consists of 1 init node, 8 witness nodes and 2 api nodes.
|
||||
After fixture creation there are 21 active witnesses, and last irreversible block
|
||||
is behind head block like in real network.
|
||||
"""
|
||||
|
||||
tt.logger.info("Preparing network with many witnesses")
|
||||
|
||||
# Create first network
|
||||
alpha_net = tt.Network()
|
||||
init_node = tt.InitNode(network=alpha_net)
|
||||
tt.WitnessNode(witnesses=[f"witness{i}-alpha" for i in range(0, 3)], network=alpha_net)
|
||||
tt.WitnessNode(witnesses=[f"witness{i}-alpha" for i in range(3, 6)], network=alpha_net)
|
||||
tt.WitnessNode(witnesses=[f"witness{i}-alpha" for i in range(6, 8)], network=alpha_net)
|
||||
tt.WitnessNode(witnesses=[f"witness{i}-alpha" for i in range(8, 10)], network=alpha_net)
|
||||
tt.ApiNode(network=alpha_net)
|
||||
|
||||
# Create second network
|
||||
beta_net = tt.Network()
|
||||
tt.WitnessNode(witnesses=[f"witness{i}-beta" for i in range(0, 3)], network=beta_net)
|
||||
tt.WitnessNode(witnesses=[f"witness{i}-beta" for i in range(3, 6)], network=beta_net)
|
||||
tt.WitnessNode(witnesses=[f"witness{i}-beta" for i in range(6, 8)], network=beta_net)
|
||||
tt.WitnessNode(witnesses=[f"witness{i}-beta" for i in range(8, 10)], network=beta_net)
|
||||
tt.ApiNode(network=beta_net)
|
||||
|
||||
run_networks([alpha_net, beta_net], Path(block_log_directory_name))
|
||||
|
||||
wallet = tt.Wallet(attach_to=init_node)
|
||||
|
||||
display_info(wallet)
|
||||
|
||||
return alpha_net, beta_net
|
||||
|
||||
|
||||
def prepare_nodes(sub_networks_sizes: list) -> list:
|
||||
assert len(sub_networks_sizes) > 0, "At least 1 sub-network is required"
|
||||
|
||||
cnt = 0
|
||||
all_witness_names = []
|
||||
sub_networks = []
|
||||
init_node = None
|
||||
|
||||
for sub_networks_size in sub_networks_sizes:
|
||||
tt.logger.info(f"Preparing sub-network nr: {cnt} that consists of {sub_networks_size} witnesses")
|
||||
|
||||
witness_names = [f"witness-{cnt}-{i}" for i in range(sub_networks_size)]
|
||||
all_witness_names += witness_names
|
||||
|
||||
sub_network = tt.Network()
|
||||
if cnt == 0:
|
||||
init_node = tt.InitNode(network=sub_network)
|
||||
sub_networks.append(sub_network)
|
||||
tt.WitnessNode(witnesses=witness_names, network=sub_network)
|
||||
tt.ApiNode(network=sub_network)
|
||||
|
||||
cnt += 1
|
||||
return sub_networks, init_node, all_witness_names
|
||||
|
||||
|
||||
def prepare_sub_networks_generation(sub_networks_sizes: list, block_log_directory_name: str = None) -> Dict:
|
||||
sub_networks, init_node, all_witness_names = prepare_nodes(sub_networks_sizes)
|
||||
|
||||
run_networks(sub_networks, None)
|
||||
|
||||
initminer_public_key = "TST6LLegbAgLAy28EHrffBVuANFWcFgmqRMW13wBmTExqFE9SCkg4"
|
||||
init_network(init_node, all_witness_names, initminer_public_key, block_log_directory_name)
|
||||
|
||||
return None, None, None
|
||||
|
||||
|
||||
def prepare_sub_networks_launch(sub_networks_sizes: list, block_log_directory_name: str = None) -> Dict:
|
||||
sub_networks, init_node, all_witness_names = prepare_nodes(sub_networks_sizes)
|
||||
|
||||
run_networks(sub_networks, Path(block_log_directory_name))
|
||||
|
||||
init_wallet = tt.Wallet(attach_to=init_node)
|
||||
|
||||
display_info(init_wallet)
|
||||
|
||||
return sub_networks, all_witness_names, init_wallet
|
||||
|
||||
|
||||
def prepare_sub_networks(
|
||||
sub_networks_sizes: list, allow_generate_block_log: bool = False, block_log_directory_name: str = None
|
||||
) -> Dict:
|
||||
assert block_log_directory_name is not None, "Name of directory with block_log file must be given"
|
||||
|
||||
if allow_generate_block_log:
|
||||
return prepare_sub_networks_generation(sub_networks_sizes, block_log_directory_name)
|
||||
|
||||
return prepare_sub_networks_launch(sub_networks_sizes, block_log_directory_name)
|
||||
|
||||
|
||||
def allow_generate_block_log():
|
||||
status = os.environ.get("GENERATE_FORK_BLOCK_LOG", None)
|
||||
if status is None:
|
||||
return False
|
||||
return int(status) == 1
|
|
@ -1,31 +1,22 @@
|
|||
import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
import time
|
||||
from typing import Dict, Iterable, List
|
||||
from typing import List
|
||||
|
||||
import test_tools as tt
|
||||
from test_tools.__private.init_node import InitNode
|
||||
from test_tools.__private.user_handles.get_implementation import get_implementation
|
||||
|
||||
from test_tools.__private.wait_for import wait_for_event
|
||||
|
||||
from ..local_tools import init_network
|
||||
|
||||
|
||||
def count_ops_by_type(node, op_type: str, start: int, limit: int = 50):
|
||||
"""
|
||||
:param op_type: type of operation (ex. 'producer_reward_operation')
|
||||
:param op_type: type of operation (ex. "producer_reward_operation")
|
||||
:param start: start queries with this block number
|
||||
:param limit: limit queries until start-limit+1
|
||||
"""
|
||||
count = {}
|
||||
for i in range(start, start-limit, -1):
|
||||
for i in range(start, start - limit, -1):
|
||||
response = node.api.account_history.get_ops_in_block(block_num=i, only_virtual=False)
|
||||
ops = response["ops"]
|
||||
count[i] = 0
|
||||
for op in ops:
|
||||
this_op_type = op["op"]["type"]
|
||||
for current_op in ops:
|
||||
this_op_type = current_op["op"]["type"]
|
||||
if this_op_type == op_type:
|
||||
count[i] += 1
|
||||
return count
|
||||
|
@ -33,19 +24,19 @@ def count_ops_by_type(node, op_type: str, start: int, limit: int = 50):
|
|||
|
||||
def check_account_history_duplicates(node, wallet):
|
||||
last_irreversible_block = wallet.api.info()["last_irreversible_block_num"]
|
||||
node_reward_operations = count_ops_by_type(node, 'producer_reward_operation', last_irreversible_block, limit=50)
|
||||
assert sum(i==1 for i in node_reward_operations.values()) == 50
|
||||
node_reward_operations = count_ops_by_type(node, "producer_reward_operation", last_irreversible_block, limit=50)
|
||||
assert sum(i == 1 for i in node_reward_operations.values()) == 50
|
||||
|
||||
|
||||
def assert_no_duplicates(node, *nodes):
|
||||
nodes = [node, *nodes]
|
||||
for node in nodes:
|
||||
wallet = tt.Wallet(attach_to=node)
|
||||
check_account_history_duplicates(node, wallet)
|
||||
node.wait_number_of_blocks(10)
|
||||
for node in nodes:
|
||||
wallet = tt.Wallet(attach_to=node)
|
||||
check_account_history_duplicates(node, wallet)
|
||||
_nodes = [node, *nodes]
|
||||
for _node in _nodes:
|
||||
wallet = tt.Wallet(attach_to=_node)
|
||||
check_account_history_duplicates(_node, wallet)
|
||||
_node.wait_number_of_blocks(10)
|
||||
for _node in _nodes:
|
||||
wallet = tt.Wallet(attach_to=_node)
|
||||
check_account_history_duplicates(_node, wallet)
|
||||
tt.logger.info("No there are no duplicates in account_history.get_ops_in_block...")
|
||||
|
||||
|
||||
|
@ -62,7 +53,7 @@ def connect_sub_networks(sub_networks : list):
|
|||
current_idx += 1
|
||||
|
||||
|
||||
def disconnect_sub_networks(sub_networks : list):
|
||||
def disconnect_sub_networks(sub_networks: list):
|
||||
assert len(sub_networks) > 1
|
||||
|
||||
current_idx = 0
|
||||
|
@ -75,36 +66,38 @@ def disconnect_sub_networks(sub_networks : list):
|
|||
current_idx += 1
|
||||
|
||||
|
||||
def enable_witnesses(wallet : tt.Wallet, witness_details : list):
|
||||
def enable_witnesses(wallet: tt.Wallet, witness_details: list):
|
||||
with wallet.in_single_transaction():
|
||||
for name in witness_details:
|
||||
wallet.api.update_witness(
|
||||
name, "https://" + name,
|
||||
name,
|
||||
"https://" + name,
|
||||
tt.Account(name).public_key,
|
||||
{"account_creation_fee": tt.Asset.Test(3), "maximum_block_size": 65536, "sbd_interest_rate": 0}
|
||||
{"account_creation_fee": tt.Asset.Test(3), "maximum_block_size": 65536, "sbd_interest_rate": 0},
|
||||
)
|
||||
|
||||
|
||||
def disable_witnesses(wallet : tt.Wallet, witness_details : list):
|
||||
key = 'TST5NUU7M7pmqMpMHUwscgUBMuwLQE56MYwCLF7q9ZGB6po1DMNoG'
|
||||
def disable_witnesses(wallet: tt.Wallet, witness_details: list):
|
||||
key = "TST5NUU7M7pmqMpMHUwscgUBMuwLQE56MYwCLF7q9ZGB6po1DMNoG"
|
||||
with wallet.in_single_transaction():
|
||||
for name in witness_details:
|
||||
wallet.api.update_witness(
|
||||
name, "https://" + name,
|
||||
name,
|
||||
"https://" + name,
|
||||
key,
|
||||
{"account_creation_fee": tt.Asset.Test(3), "maximum_block_size": 65536, "sbd_interest_rate": 0}
|
||||
{"account_creation_fee": tt.Asset.Test(3), "maximum_block_size": 65536, "sbd_interest_rate": 0},
|
||||
)
|
||||
|
||||
|
||||
def get_last_head_block_number(blocks : list):
|
||||
def get_last_head_block_number(blocks: list):
|
||||
return blocks[len(blocks) - 1][0]
|
||||
|
||||
|
||||
def get_last_irreversible_block_num(blocks : list):
|
||||
def get_last_irreversible_block_num(blocks: list):
|
||||
return blocks[len(blocks) - 1][1]
|
||||
|
||||
|
||||
def get_part_of_witness_details(witness_details : list, start, length : int):
|
||||
def get_part_of_witness_details(witness_details: list, start, length: int):
|
||||
assert start >= 0 and start + length <= len(witness_details)
|
||||
new_witness_details = []
|
||||
for i in range(start, start + length):
|
||||
|
@ -120,37 +113,38 @@ def info(msg : str, wallet : tt.Wallet):
|
|||
tt.logger.info(f'network: \'{msg}\' head: {hb} lib: {lib} current witness: {current_witness}')
|
||||
return hb, lib
|
||||
|
||||
class NodeLog:
|
||||
|
||||
class fork_log:
|
||||
def __init__(self, name, wallet):
|
||||
self.name = name
|
||||
self.collector = []
|
||||
self.wallet = wallet
|
||||
self.name = name
|
||||
self.collector = []
|
||||
self.wallet = wallet
|
||||
|
||||
def append(self):
|
||||
self.collector.append( info(self.name, self.wallet) )
|
||||
self.collector.append(info(self.name, self.wallet))
|
||||
|
||||
|
||||
def wait(blocks, log : List[fork_log], api_node):
|
||||
def wait(blocks, log: List[NodeLog], api_node):
|
||||
for i in range(blocks):
|
||||
|
||||
for current in log:
|
||||
current.append()
|
||||
|
||||
api_node.wait_number_of_blocks(1)
|
||||
tt.logger.info(f'{i+1}/{blocks} blocks')
|
||||
tt.logger.info(f"{i+1}/{blocks} blocks")
|
||||
|
||||
|
||||
def final_block_the_same(method, data : list):
|
||||
def final_block_the_same(method, data: list):
|
||||
current = None
|
||||
for item in data:
|
||||
if current is None:
|
||||
current = item
|
||||
else:
|
||||
if method( current ) != method( item ):
|
||||
if method(current) != method(item):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def lib_true_condition():
|
||||
return True
|
||||
|
||||
|
@ -159,22 +153,25 @@ def lib_custom_condition(compared_item1, compared_item2):
|
|||
return get_last_irreversible_block_num(compared_item1) > compared_item2
|
||||
|
||||
|
||||
def wait_for_final_block(witness_node, logs, data : list, allow_lib = True, lib_cond = lib_true_condition, allow_last_head = True):
|
||||
def wait_for_final_block(
|
||||
witness_node, logs, data: list, allow_lib=True, lib_cond=lib_true_condition, allow_last_head=True
|
||||
):
|
||||
assert allow_lib or allow_last_head
|
||||
|
||||
#Hard to say when all nodes would have the same HEAD's/LIB's. All nodes are connected together in common network
|
||||
#so sometimes one or two nodes are "delayed" - their LIB is lower than LIB others.
|
||||
#The best option is to wait until every node has the same data: it doesn't matter if such situation occurs after 5 or 25 blocks.
|
||||
#In case when nodes wouldn't have the same data, it's an obvious error and CI will finish this test.
|
||||
# Hard to say when all nodes would have the same HEAD"s/LIB"s. All nodes are connected together in common network
|
||||
# so sometimes one or two nodes are "delayed" - their LIB is lower than LIB others.
|
||||
# The best option is to wait until every node has the same data.
|
||||
# It doesn"t matter if such situation occurs after 5 or 25 blocks.
|
||||
# In case when nodes wouldn"t have the same data, it"s an obvious error and CI will finish this test.
|
||||
while True:
|
||||
wait(1, logs, witness_node)
|
||||
|
||||
#Veryfing if all nodes have the same last irreversible block number
|
||||
# Veryfing if all nodes have the same last irreversible block number
|
||||
if allow_lib:
|
||||
if lib_cond() and final_block_the_same(get_last_irreversible_block_num, data):
|
||||
return False
|
||||
|
||||
#Veryfing if all nodes have the same last head block number
|
||||
# Veryfing if all nodes have the same last head block number
|
||||
if allow_last_head:
|
||||
if final_block_the_same(get_last_head_block_number, data):
|
||||
return False
|
||||
|
@ -230,51 +227,6 @@ def wait_for_specific_witnesses(node, logs, witness_name_patterns):
|
|||
tt.logger.info("Witnesses patterns can't be processed in the same schedule. Still waiting...")
|
||||
|
||||
|
||||
def get_relative_time_offset_from_file(file: Path) -> str:
|
||||
with open(file, 'r') as f:
|
||||
timestamp = f.read().strip()
|
||||
|
||||
delta = tt.Time.now(serialize=False) - tt.Time.parse(timestamp)
|
||||
delta += tt.Time.seconds(5) # Node starting and entering live mode takes some time to complete
|
||||
return f'-{delta.total_seconds():.3f}s'
|
||||
|
||||
|
||||
def run_networks(networks: Iterable[tt.Network], blocklog_directory: Path):
|
||||
if blocklog_directory is not None:
|
||||
time_offset = get_relative_time_offset_from_file(blocklog_directory / 'timestamp')
|
||||
block_log = tt.BlockLog(blocklog_directory/'block_log')
|
||||
|
||||
tt.logger.info('Running nodes...')
|
||||
|
||||
connect_sub_networks(networks)
|
||||
|
||||
nodes = [node for network in networks for node in network.nodes]
|
||||
if blocklog_directory is not None:
|
||||
nodes[0].run(wait_for_live=False, replay_from=block_log, time_offset=time_offset)
|
||||
else:
|
||||
nodes[0].run(wait_for_live=False)
|
||||
init_node: InitNode = get_implementation(nodes[0])
|
||||
endpoint = init_node.get_p2p_endpoint()
|
||||
for node in nodes[1:]:
|
||||
node.config.p2p_seed_node.append(endpoint)
|
||||
if blocklog_directory is not None:
|
||||
node.run(wait_for_live=False, replay_from=block_log, time_offset=time_offset)
|
||||
else:
|
||||
node.run(wait_for_live=False)
|
||||
|
||||
for network in networks:
|
||||
network.is_running = True
|
||||
|
||||
deadline = time.time() + InitNode.DEFAULT_WAIT_FOR_LIVE_TIMEOUT
|
||||
for node in nodes:
|
||||
tt.logger.debug(f'Waiting for {node} to be live...')
|
||||
wait_for_event(
|
||||
get_implementation(node)._Node__notifications.live_mode_entered_event,
|
||||
deadline=deadline,
|
||||
exception_message='Live mode not activated on time.'
|
||||
)
|
||||
|
||||
|
||||
def display_info(wallet):
|
||||
# Network should be set up at this time, with 21 active witnesses, enough participation rate
|
||||
# and irreversible block number lagging behind around 15-20 blocks head block number
|
||||
|
@ -307,46 +259,3 @@ def prepare_nodes(sub_networks_sizes : list) -> list:
|
|||
|
||||
cnt += 1
|
||||
return sub_networks, init_node, all_witness_names
|
||||
|
||||
|
||||
def prepare_sub_networks_generation(sub_networks_sizes : list, block_log_directory_name : str = None) -> Dict:
|
||||
sub_networks, init_node, all_witness_names = prepare_nodes(sub_networks_sizes)
|
||||
|
||||
run_networks(sub_networks, None)
|
||||
|
||||
initminer_public_key = 'TST6LLegbAgLAy28EHrffBVuANFWcFgmqRMW13wBmTExqFE9SCkg4'
|
||||
init_network(init_node, all_witness_names, initminer_public_key, block_log_directory_name)
|
||||
|
||||
return None, None, None
|
||||
|
||||
|
||||
def prepare_sub_networks_launch(sub_networks_sizes : list, block_log_directory_name : str = None) -> Dict:
|
||||
sub_networks, init_node, all_witness_names = prepare_nodes(sub_networks_sizes)
|
||||
|
||||
run_networks(sub_networks, Path(block_log_directory_name))
|
||||
|
||||
init_wallet = tt.Wallet(attach_to=init_node)
|
||||
|
||||
display_info(init_wallet)
|
||||
|
||||
return sub_networks, all_witness_names, init_wallet
|
||||
|
||||
|
||||
def prepare_sub_networks(sub_networks_sizes : list, allow_generate_block_log : bool = False, block_log_directory_name : str = None) -> Dict:
|
||||
assert block_log_directory_name is not None, "Name of directory with block_log file must be given"
|
||||
|
||||
if allow_generate_block_log:
|
||||
return prepare_sub_networks_generation(sub_networks_sizes, block_log_directory_name)
|
||||
else:
|
||||
return prepare_sub_networks_launch(sub_networks_sizes, block_log_directory_name)
|
||||
|
||||
|
||||
def allow_generate_block_log():
|
||||
status = os.environ.get('GENERATE_FORK_BLOCK_LOG', None)
|
||||
if status is None:
|
||||
return False
|
||||
return int(status) == 1
|
||||
|
||||
|
||||
def create_block_log_directory_name(name : str):
|
||||
return str(Path(__file__).parent.absolute()) + '/' + name
|
|
@ -0,0 +1,8 @@
|
|||
package = []
|
||||
|
||||
[metadata]
|
||||
lock-version = "1.1"
|
||||
python-versions = "^3.8"
|
||||
content-hash = "935b488be9f11b23f14aa1ce3bed4013d88bd77462534b5e4fe5bb82b485bfe9"
|
||||
|
||||
[metadata.files]
|
|
@ -0,0 +1,17 @@
|
|||
[build-system]
|
||||
requires = ["poetry-core==1.1.0"]
|
||||
build-backend = "poetry.core.masonry.api"
|
||||
|
||||
|
||||
[tool.poetry]
|
||||
name = "shared-tools"
|
||||
version = "0.0.0"
|
||||
description = "Tools shared by tests in hive projects"
|
||||
authors = ["Mariusz Trela"]
|
||||
packages = [
|
||||
{ include = "shared_tools", from = "package" },
|
||||
]
|
||||
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.8"
|
Loading…
Reference in New Issue