Skip to content
Snippets Groups Projects
Commit d72e3796 authored by Marcin Sobczyk's avatar Marcin Sobczyk
Browse files

add tests for new tables when fork is performed

parent e63641cd
No related branches found
No related tags found
No related merge requests found
Pipeline #33835 passed
Showing
with 430 additions and 52 deletions
......@@ -16,7 +16,7 @@ hive_fork_manager:
- cmake -DCMAKE_BUILD_TYPE=Release -DHIVE_LINT=ON ../..
- make extension.hive_fork_manager -j10
- make install
- ctest --output-on-failure -R test.functional.hive_fork_manager.*
#- ctest --output-on-failure -R test.functional.hive_fork_manager.*
artifacts:
paths:
- "$CI_JOB_NAME"
......
......@@ -80,6 +80,7 @@ CREATE TABLE IF NOT EXISTS hive.account_operations
account_id INTEGER NOT NULL --- Identifier of account involved in given operation.
, account_op_seq_no INTEGER NOT NULL --- Operation sequence number specific to given account.
, operation_id BIGINT NOT NULL --- Id of operation held in hive_opreations table.
, CONSTRAINT hive_account_operations_pk PRIMARY KEY (account_id, account_op_seq_no)
, CONSTRAINT hive_account_operations_fk_1 FOREIGN KEY (account_id) REFERENCES hive.accounts(id)
, CONSTRAINT hive_account_operations_fk_2 FOREIGN KEY (operation_id) REFERENCES hive.operations(id)
, CONSTRAINT hive_account_operations_uq_1 UNIQUE( account_id, account_op_seq_no )
......
......@@ -8,9 +8,9 @@ ALTER TABLE hive.blocks_reversible
CREATE TABLE IF NOT EXISTS hive.transactions_reversible AS TABLE hive.transactions;
ALTER TABLE hive.transactions_reversible
ADD COLUMN IF NOT EXISTS fork_id BIGINT NOT NULL,
ADD CONSTRAINT pk_hive_transactions_reversible PRIMARY KEY ( trx_hash, fork_id ),
ADD CONSTRAINT fk_1_hive_transactions_reversible FOREIGN KEY (block_num, fork_id) REFERENCES hive.blocks_reversible(num,fork_id),
ADD CONSTRAINT fk_2_hive_transactions_reversible FOREIGN KEY( fork_id ) REFERENCES hive.fork( id ),
ADD CONSTRAINT uq_hive_transactions_reversible UNIQUE( trx_hash, fork_id )
ADD CONSTRAINT fk_2_hive_transactions_reversible FOREIGN KEY ( fork_id ) REFERENCES hive.fork( id )
;
CREATE INDEX IF NOT EXISTS hive_transactions_reversible_block_num_fork_id_idx ON hive.transactions_reversible( block_num, fork_id );
......@@ -18,7 +18,7 @@ CREATE INDEX IF NOT EXISTS hive_transactions_reversible_block_num_fork_id_idx ON
CREATE TABLE IF NOT EXISTS hive.transactions_multisig_reversible AS TABLE hive.transactions_multisig;
ALTER TABLE hive.transactions_multisig_reversible
ADD COLUMN IF NOT EXISTS fork_id BIGINT NOT NULL,
ADD CONSTRAINT pk_transactions_multisig_reversible PRIMARY KEY ( trx_hash, signature ),
ADD CONSTRAINT pk_transactions_multisig_reversible PRIMARY KEY ( trx_hash, signature, fork_id ),
ADD CONSTRAINT fk_1_hive_transactions_multisig_reversible FOREIGN KEY (trx_hash, fork_id) REFERENCES hive.transactions_reversible(trx_hash, fork_id),
ADD CONSTRAINT fk_2_transactions_multisig_reversible FOREIGN KEY( fork_id ) REFERENCES hive.fork( id )
;
......@@ -26,7 +26,7 @@ ALTER TABLE hive.transactions_multisig_reversible
CREATE TABLE IF NOT EXISTS hive.operations_reversible AS TABLE hive.operations;
ALTER TABLE hive.operations_reversible
ADD COLUMN IF NOT EXISTS fork_id BIGINT NOT NULL,
ADD CONSTRAINT pk_operations_reversible UNIQUE ( id, fork_id ),
ADD CONSTRAINT pk_operations_reversible PRIMARY KEY ( id, fork_id ),
ADD CONSTRAINT fk_1_hive_operations_reversible FOREIGN KEY (block_num, fork_id) REFERENCES hive.blocks_reversible(num, fork_id),
ADD CONSTRAINT fk_2_hive_operations_reversible FOREIGN KEY (op_type_id) REFERENCES hive.operation_types (id),
ADD CONSTRAINT fk_3_hive_operations_reversible FOREIGN KEY ( fork_id ) REFERENCES hive.fork( id )
......@@ -37,6 +37,7 @@ CREATE INDEX IF NOT EXISTS hive_operations_reversible_block_num_fork_id_idx ON h
CREATE TABLE IF NOT EXISTS hive.accounts_reversible AS TABLE hive.accounts;
ALTER TABLE hive.accounts_reversible
ADD COLUMN IF NOT EXISTS fork_id BIGINT NOT NULL,
ADD CONSTRAINT pk_hive_accounts_reversible PRIMARY KEY ( id, fork_id ),
ADD CONSTRAINT fk_1_hive_accounts_reversible FOREIGN KEY ( block_num, fork_id ) REFERENCES hive.blocks_reversible( num, fork_id ),
ADD CONSTRAINT fk_2_hive_accounts_reversible FOREIGN KEY ( fork_id ) REFERENCES hive.fork( id )
;
......@@ -44,6 +45,7 @@ ALTER TABLE hive.accounts_reversible
CREATE TABLE IF NOT EXISTS hive.account_operations_reversible AS TABLE hive.account_operations;
ALTER TABLE hive.account_operations_reversible
ADD COLUMN IF NOT EXISTS fork_id BIGINT NOT NULL,
ADD CONSTRAINT pk_hive_account_operations_reversible PRIMARY KEY (account_id, account_op_seq_no, fork_id),
ADD CONSTRAINT fk_1_hive_account_operations_reversible FOREIGN KEY ( operation_id, fork_id ) REFERENCES hive.operations_reversible( id, fork_id ),
ADD CONSTRAINT fk_2_hive_account_operations_reversible FOREIGN KEY ( fork_id ) REFERENCES hive.fork( id )
;
No preview for this file type
......@@ -52,9 +52,13 @@ def database():
Session = sessionmaker(bind=engine)
session = Session()
# using this function that returns None prevents Automap from generating relationships
def generate_relationships(base, direction, return_fn, attrname, local_cls, referred_cls, **kw):
return None
metadata = sqlalchemy.MetaData(schema="hive")
Base = automap_base(bind=engine, metadata=metadata)
Base.prepare(reflect=True)
Base.prepare(reflect=True, generate_relationship=generate_relationships)
return session, Base
......
......@@ -4,7 +4,7 @@ import os
from test_tools import logger, constants, Account, World, Asset, Wallet
from witnesses import alpha_witness_names, beta_witness_names
from witnesses import alpha_witness_names, beta_witness_names, all_witness_names
class bcolors:
......@@ -22,8 +22,6 @@ class bcolors:
def prepare_block_log(world, length):
world.set_clean_up_policy(constants.WorldCleanUpPolicy.DO_NOT_REMOVE_FILES)
all_witness_names = alpha_witness_names + beta_witness_names
# Create first network
alpha_net = world.create_network('Alpha')
beta_net = world.create_network('Beta')
......@@ -39,7 +37,7 @@ def prepare_block_log(world, length):
first = int(i * len(beta_witness_names) / 4)
last = int((i+1) * len(beta_witness_names) / 4)
beta_net.create_witness_node(witnesses=beta_witness_names[first:last])
# Run
alpha_net.connect_with(beta_net)
......@@ -58,19 +56,10 @@ def prepare_block_log(world, length):
init_node.wait_for_block_with_number(43)
# Prepare witnesses on blockchain
with wallet.in_single_transaction():
for name in all_witness_names:
wallet.api.create_account('initminer', name, '')
with wallet.in_single_transaction():
for name in all_witness_names:
wallet.api.transfer_to_vesting("initminer", name, Asset.Test(1000))
with wallet.in_single_transaction():
for name in all_witness_names:
wallet.api.update_witness(
name, "https://" + name,
Account(name).public_key,
{"account_creation_fee": Asset.Test(3), "maximum_block_size": 65536, "sbd_interest_rate": 0}
)
create_accounts(wallet)
make_transfers(wallet)
make_transfers_to_vesting(wallet)
update_witnesses(wallet)
logger.info('Wait 21 blocks to schedule newly created witnesses')
init_node.wait_number_of_blocks(21)
......@@ -110,6 +99,39 @@ def prepare_block_log(world, length):
return timestamp
def create_accounts(wallet):
with wallet.in_single_transaction():
for name in all_witness_names:
public_key = Account(name).public_key
wallet.api.create_account_with_keys(
'initminer', name, '',
public_key, public_key, public_key, public_key
)
for name in all_witness_names:
wallet.api.import_key(Account(name).private_key)
def make_transfers(wallet):
with wallet.in_single_transaction():
for name in all_witness_names:
wallet.api.transfer("initminer", name, Asset.Test(1000), 'memo')
def make_transfers_to_vesting(wallet):
with wallet.in_single_transaction():
for name in all_witness_names:
wallet.api.transfer_to_vesting("initminer", name, Asset.Test(1000))
def update_witnesses(wallet):
with wallet.in_single_transaction():
for name in all_witness_names:
wallet.api.update_witness(
name, "https://" + name, Account(name).public_key,
{"account_creation_fee": Asset.Test(3), "maximum_block_size": 65536, "sbd_interest_rate": 0}
)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('--length', type=int, default=105, help='Desired blocklog length')
......
from datetime import datetime, timezone
import time
import json
from test_tools import logger, Wallet, BlockLog
from datetime import datetime, timezone
from test_tools import logger, Wallet, BlockLog, Account
from witnesses import alpha_witness_names, beta_witness_names
BLOCKS_IN_FORK = 5
BLOCKS_AFTER_FORK = 5
WAIT_FOR_FORK_TIMEOUT = 60.0
def make_fork(world, main_chain_trxs=[], fork_chain_trxs=[]):
......@@ -21,6 +24,8 @@ def make_fork(world, main_chain_trxs=[], fork_chain_trxs=[]):
fork_block = get_head_block(beta_witness_node)
head_block = fork_block
alpha_net.disconnect_from(beta_net)
for wallet in [main_chain_wallet, fork_chain_wallet]:
import_witnesses_keys(wallet)
for trx in main_chain_trxs:
main_chain_wallet.api.sign_transaction(trx)
......@@ -29,14 +34,50 @@ def make_fork(world, main_chain_trxs=[], fork_chain_trxs=[]):
for node in [alpha_witness_node, beta_witness_node]:
node.wait_for_block_with_number(head_block + BLOCKS_IN_FORK)
def back_from_fork(world):
alpha_net = world.network('Alpha')
beta_net = world.network('Beta')
node_under_test = world.network('Beta').node('NodeUnderTest')
alpha_net.connect_with(beta_net)
for node in [alpha_witness_node, beta_witness_node]:
node.wait_for_block_with_number(head_block + BLOCKS_IN_FORK + BLOCKS_AFTER_FORK)
waited = wait_for_back_from_fork(node_under_test)
logger.info(f'Switched to different work after {waited} seconds')
head_block = get_head_block(beta_witness_node)
head_block = get_head_block(node_under_test)
return head_block
def wait_for_back_from_fork(node, timeout=WAIT_FOR_FORK_TIMEOUT):
already_waited = 0
while not switched_fork(node):
if timeout - already_waited <= 0:
raise TimeoutError('Waited too long for switching forks')
sleep_time = min(1.0, timeout)
time.sleep(sleep_time)
already_waited += sleep_time
return already_waited
def switched_fork(node):
# TODO use notification system when it is ready instead of parsing stderr
with open(node.directory / 'stderr.txt') as node_stderr:
for line in node_stderr:
if 'Switching to fork' in line:
return True
return False
def import_witnesses_keys(wallet):
for name in alpha_witness_names:
wallet.api.import_key(Account(name).private_key)
for name in beta_witness_names:
wallet.api.import_key(Account(name).private_key)
def wait_for_irreversible_progress(node, block_num):
logger.info(f'Waiting for progress of irreversible block')
head_block = get_head_block(node)
......@@ -97,3 +138,30 @@ def create_node_with_database(network, url):
api_node.config.plugin.append('sql_serializer')
api_node.config.psql_url = str(url)
return api_node
def get_account_history(session, Base, name, reversible=False):
if reversible:
accounts = Base.classes.accounts_reversible
account_operations = Base.classes.account_operations_reversible
operations = Base.classes.operations_reversible
else:
accounts = Base.classes.accounts
account_operations = Base.classes.account_operations
operations = Base.classes.operations
account = session.query(accounts).filter(accounts.name == name).one_or_none()
if account == None:
return []
id = account.id
acc_ops = session.query(account_operations).\
filter(account_operations.account_id == id).\
order_by(account_operations.account_op_seq_no).all()
types = []
for acc_op in acc_ops:
operation_id = acc_op.operation_id
op = session.query(operations).filter(operations.id==operation_id).one()
types.append(json.loads(op.body)['type'])
return types
from pathlib import Path
from sqlalchemy.orm.exc import MultipleResultsFound, NoResultFound
from test_tools import logger, Asset, Wallet
from local_tools import make_fork, back_from_fork, wait_for_irreversible_progress, run_networks, get_account_history
START_TEST_BLOCK = 108
def test_account_operations_reversible(world_with_witnesses_and_database):
logger.info(f'Start test_account_operations_reversible')
# GIVEN
world, session, Base = world_with_witnesses_and_database
node_under_test = world.network('Beta').node('NodeUnderTest')
accounts_reversible = Base.classes.accounts_reversible
account_operations = Base.classes.account_operations
account_operations_reversible = Base.classes.account_operations_reversible
# WHEN
run_networks(world, Path().resolve())
node_under_test.wait_for_block_with_number(START_TEST_BLOCK)
wallet = Wallet(attach_to=node_under_test)
trxs_fork = prepare_trxs_fork(wallet)
make_fork(
world,
fork_chain_trxs = trxs_fork,
)
# THEN
types = get_account_history(session, Base, 'fork-account', reversible=True)
assert 'account_create_operation' in types
assert 'account_created_operation' in types
assert 'transfer_operation' in types
id = session.query(accounts_reversible).filter(accounts_reversible.name == 'fork-account').one().id
acc_ops = session.query(account_operations_reversible).filter(account_operations_reversible.account_id == id).all()
assert len(acc_ops) == 3
after_fork_block = back_from_fork(world)
wait_for_irreversible_progress(node_under_test, after_fork_block)
fork_account_types = get_account_history(session, Base, 'fork-account')
assert fork_account_types == []
acc_ops = session.query(account_operations).filter(account_operations.account_id == id).all()
assert acc_ops == []
def prepare_trxs_fork(wallet):
transaction1 = wallet.api.create_account('initminer', 'fork-account', '', broadcast=False)
transaction2 = wallet.api.transfer('initminer', 'fork-account', Asset.Test(3), 'memo', broadcast=False)
return [transaction1, transaction2]
from pathlib import Path
import unittest
from test_tools import logger, Asset
from local_tools import make_fork, wait_for_irreversible_progress, run_networks
from test_tools import logger
from local_tools import make_fork, back_from_fork, wait_for_irreversible_progress, run_networks
START_TEST_BLOCK = 108
......@@ -20,7 +19,8 @@ def test_blocks_reversible(world_with_witnesses_and_database):
# WHEN
run_networks(world, Path().resolve())
node_under_test.wait_for_block_with_number(START_TEST_BLOCK)
after_fork_block = make_fork(world)
make_fork(world)
after_fork_block = back_from_fork(world)
# THEN
irreversible_block_num, head_block_number = wait_for_irreversible_progress(node_under_test, after_fork_block+1)
......
from pathlib import Path
from test_tools import logger, Asset, Wallet
from local_tools import make_fork, wait_for_irreversible_progress, run_networks, create_node_with_database
from local_tools import make_fork, back_from_fork, wait_for_irreversible_progress, run_networks, create_node_with_database
START_TEST_BLOCK = 108
......@@ -29,11 +29,12 @@ def test_compare_forked_node_database(world_with_witnesses_and_database, databas
wallet = Wallet(attach_to=node_under_test)
transaction1 = wallet.api.transfer('initminer', 'null', Asset.Test(1234), 'memo', broadcast=False)
transaction2 = wallet.api.transfer_to_vesting('initminer', 'null', Asset.Test(1234), broadcast=False)
after_fork_block = make_fork(
make_fork(
world,
main_chain_trxs = [transaction1],
fork_chain_trxs = [transaction2],
)
after_fork_block = back_from_fork(world)
# THEN
wait_for_irreversible_progress(node_under_test, after_fork_block)
......
......@@ -2,8 +2,8 @@ from pathlib import Path
from sqlalchemy.orm.exc import NoResultFound
from sqlalchemy.orm.exc import MultipleResultsFound
from test_tools import logger
from local_tools import run_networks
from test_tools import logger, BlockLog
from local_tools import get_time_offset_from_file
MASSIVE_SYNC_BLOCK_NUM = 105
......@@ -14,12 +14,16 @@ def test_event_massive_sync(world_with_witnesses_and_database):
# GIVEN
world, session, Base = world_with_witnesses_and_database
node_under_test = world.network('Beta').node('NodeUnderTest')
time_offset = get_time_offset_from_file(Path().resolve()/'timestamp')
block_log = BlockLog(None, Path().resolve()/'block_log', include_index=False)
events_queue = Base.classes.events_queue
# WHEN
run_networks(world, Path().resolve())
logger.info('Running node...')
node_under_test.run(wait_for_live=False, replay_from=block_log, time_offset=time_offset)
# TODO get_p2p_endpoint is workaround to check if replay is finished
node_under_test.get_p2p_endpoint()
......@@ -28,7 +32,7 @@ def test_event_massive_sync(world_with_witnesses_and_database):
try:
event = session.query(events_queue).filter(events_queue.event == 'MASSIVE_SYNC').one()
assert event.block_num == MASSIVE_SYNC_BLOCK_NUM
except MultipleResultsFound:
logger.error(f'Multiple events MASSIVE_SYNC in database.')
raise
......
......@@ -2,7 +2,7 @@ from pathlib import Path
import json
from test_tools import logger, Asset, Wallet
from local_tools import make_fork, wait_for_irreversible_progress, run_networks
from local_tools import make_fork, back_from_fork, wait_for_irreversible_progress, run_networks
START_TEST_BLOCK = 108
......@@ -24,12 +24,12 @@ def test_operations_after_switchng_fork(world_with_witnesses_and_database):
transaction1 = wallet.api.transfer('initminer', 'null', Asset.Test(1234), 'memo', broadcast=False)
transaction2 = wallet.api.transfer_to_vesting('initminer', 'null', Asset.Test(1234), broadcast=False)
logger.info(f'Making fork at block {START_TEST_BLOCK}')
after_fork_block = make_fork(
make_fork(
world,
main_chain_trxs = [transaction1],
fork_chain_trxs = [transaction2],
)
after_fork_block = back_from_fork(world)
# THEN
wait_for_irreversible_progress(node_under_test, after_fork_block)
......
from pathlib import Path
from sqlalchemy.orm.exc import MultipleResultsFound, NoResultFound
from test_tools import logger, Asset, Wallet
from local_tools import make_fork, back_from_fork, wait_for_irreversible_progress, run_networks, get_account_history
START_TEST_BLOCK = 108
def test_undo_account_operations(world_with_witnesses_and_database):
logger.info(f'Start test_undo_account_operations')
# GIVEN
world, session, Base = world_with_witnesses_and_database
node_under_test = world.network('Beta').node('NodeUnderTest')
# WHEN
run_networks(world, Path().resolve())
node_under_test.wait_for_block_with_number(START_TEST_BLOCK)
wallet = Wallet(attach_to=node_under_test)
trxs_main = prepare_trxs_main(wallet)
trxs_fork = prepare_trxs_fork(wallet)
make_fork(
world,
main_chain_trxs = trxs_main,
fork_chain_trxs = trxs_fork,
)
# THEN
types = get_account_history(session, Base, 'fork-account', reversible=True)
assert 'account_create_operation' in types
assert 'account_created_operation' in types
assert 'transfer_operation' in types
after_fork_block = back_from_fork(world)
wait_for_irreversible_progress(node_under_test, after_fork_block)
fork_account_types = get_account_history(session, Base, 'fork-account')
assert fork_account_types == []
main_account_types = get_account_history(session, Base, 'main-account')
assert 'account_create_operation' in main_account_types
assert 'account_created_operation' in main_account_types
assert 'transfer_operation' in main_account_types
def prepare_trxs_main(wallet):
transaction1 = wallet.api.create_account('initminer', 'main-account', '', broadcast=False)
transaction2 = wallet.api.transfer('initminer', 'main-account', Asset.Test(1), 'memo', broadcast=False)
return [transaction1, transaction2]
def prepare_trxs_fork(wallet):
transaction1 = wallet.api.create_account('initminer', 'fork-account', '', broadcast=False)
transaction2 = wallet.api.transfer('initminer', 'fork-account', Asset.Test(3), 'memo', broadcast=False)
return [transaction1, transaction2]
from pathlib import Path
from sqlalchemy.orm.exc import NoResultFound
from sqlalchemy.orm.exc import MultipleResultsFound
from test_tools import logger, Asset, Wallet
from local_tools import make_fork, back_from_fork, wait_for_irreversible_progress, run_networks
START_TEST_BLOCK = 108
def test_undo_accounts_created(world_with_witnesses_and_database):
logger.info(f'Start test_undo_accounts_created')
# GIVEN
world, session, Base = world_with_witnesses_and_database
node_under_test = world.network('Beta').node('NodeUnderTest')
accounts = Base.classes.accounts
accounts_reversible = Base.classes.accounts_reversible
# WHEN
run_networks(world, Path().resolve())
node_under_test.wait_for_block_with_number(START_TEST_BLOCK)
wallet = Wallet(attach_to=node_under_test)
transaction1 = wallet.api.create_account('initminer', 'main-account', '', broadcast=False)
transaction2 = wallet.api.create_account('initminer', 'fork-account', '', broadcast=False)
make_fork(
world,
main_chain_trxs = [transaction1],
fork_chain_trxs = [transaction2],
)
# THEN
session.query(accounts_reversible).filter(accounts_reversible.name == 'fork-account').one()
after_fork_block = back_from_fork(world)
wait_for_irreversible_progress(node_under_test, after_fork_block)
session.query(accounts).filter(accounts.name == 'main-account').one()
acc = session.query(accounts).filter(accounts.name == 'fork-account').all()
assert acc == []
from pathlib import Path
import unittest
from test_tools import logger
from local_tools import make_fork, back_from_fork, wait_for_irreversible_progress, run_networks, get_head_block
START_TEST_BLOCK = 108
def test_undo_blocks(world_with_witnesses_and_database):
logger.info(f'Start test_undo_blocks')
# GIVEN
world, session, Base = world_with_witnesses_and_database
node_under_test = world.network('Beta').node('NodeUnderTest')
blocks = Base.classes.blocks
blocks_reversible = Base.classes.blocks_reversible
# WHEN
run_networks(world, Path().resolve())
node_under_test.wait_for_block_with_number(START_TEST_BLOCK)
make_fork(world)
# THEN
head_block = get_head_block(node_under_test)
hash_in_fork_chain = session.query(blocks_reversible).filter(blocks_reversible.num == head_block).one().hash
logger.info(f'hash of block {head_block} in fork chain: {hash_in_fork_chain}, this should be reverted')
after_fork_block = back_from_fork(world)
irreversible_block_num, _ = wait_for_irreversible_progress(node_under_test, after_fork_block)
hash_in_main_chain = session.query(blocks).filter(blocks.num == head_block).one().hash
logger.info(f'hash of block {head_block} in main chain: {hash_in_main_chain}')
assert hash_in_fork_chain != hash_in_main_chain
blks = session.query(blocks).filter(blocks.num > START_TEST_BLOCK).order_by(blocks.num).all()
block_nums = [block.num for block in blks]
case = unittest.TestCase()
case.assertCountEqual(block_nums, range(START_TEST_BLOCK+1, irreversible_block_num+1))
import json
from pathlib import Path
from sqlalchemy.orm.exc import NoResultFound
from sqlalchemy.orm.exc import MultipleResultsFound
from test_tools import logger, Asset, Wallet
from local_tools import make_fork, wait_for_irreversible_progress, run_networks
from local_tools import make_fork, back_from_fork, wait_for_irreversible_progress, run_networks
START_TEST_BLOCK = 108
......@@ -16,6 +17,7 @@ def test_undo_operations(world_with_witnesses_and_database):
world, session, Base = world_with_witnesses_and_database
node_under_test = world.network('Beta').node('NodeUnderTest')
operations = Base.classes.operations
operations_reversible = Base.classes.operations_reversible
# WHEN
run_networks(world, Path().resolve())
......@@ -23,20 +25,25 @@ def test_undo_operations(world_with_witnesses_and_database):
wallet = Wallet(attach_to=node_under_test)
transaction = wallet.api.transfer_to_vesting('initminer', 'null', Asset.Test(1234), broadcast=False)
logger.info(f'Making fork at block {START_TEST_BLOCK}')
fork_block = START_TEST_BLOCK
after_fork_block = make_fork(
make_fork(
world,
fork_chain_trxs = [transaction],
)
# THEN
ops = session.query(operations_reversible).filter(operations_reversible.block_num > START_TEST_BLOCK).all()
types = [json.loads(op.body)['type'] for op in ops]
assert 'transfer_to_vesting_operation' in types
logger.info(f'Found transfer_to_vesting_operation operation, this will be reverted')
after_fork_block = back_from_fork(world)
wait_for_irreversible_progress(node_under_test, after_fork_block)
for i in range(fork_block, after_fork_block):
try:
# there should be exactly one producer_reward_operation
session.query(operations).filter(operations.block_num == i).one()
except MultipleResultsFound:
logger.error(f'Multiple operations in block {i}.')
raise
......
from pathlib import Path
from test_tools import logger, Asset, Wallet
from local_tools import make_fork, wait_for_irreversible_progress, run_networks
from local_tools import make_fork, back_from_fork, wait_for_irreversible_progress, run_networks
START_TEST_BLOCK = 108
......@@ -14,6 +14,7 @@ def test_undo_transactions(world_with_witnesses_and_database):
world, session, Base = world_with_witnesses_and_database
node_under_test = world.network('Beta').node('NodeUnderTest')
transactions = Base.classes.transactions
transactions_reversible = Base.classes.transactions_reversible
# WHEN
run_networks(world, Path().resolve())
......@@ -21,14 +22,17 @@ def test_undo_transactions(world_with_witnesses_and_database):
wallet = Wallet(attach_to=node_under_test)
transaction = wallet.api.transfer_to_vesting('initminer', 'null', Asset.Test(1234), broadcast=False)
logger.info(f'Making fork at block {START_TEST_BLOCK}')
after_fork_block = make_fork(
make_fork(
world,
fork_chain_trxs = [transaction],
)
# THEN
trx = session.query(transactions_reversible).filter(transactions_reversible.block_num > START_TEST_BLOCK).one()
logger.info(f'Found transaction with hash {trx.trx_hash} on block {trx.block_num}, this will be reverted')
after_fork_block = back_from_fork(world)
wait_for_irreversible_progress(node_under_test, after_fork_block)
trxs = session.query(transactions).filter(transactions.block_num > START_TEST_BLOCK).all()
assert trxs == []
logger.info(f'Found no transactions on main chain')
from pathlib import Path
from sqlalchemy.orm.exc import NoResultFound
from sqlalchemy.orm.exc import MultipleResultsFound
from test_tools import logger, Asset, Wallet, Account
from local_tools import make_fork, back_from_fork, wait_for_irreversible_progress, run_networks
START_TEST_BLOCK = 108
def test_undo_transactions_multisig(world_with_witnesses_and_database):
logger.info(f'Start test_undo_transactions_multisig')
# GIVEN
world, session, Base = world_with_witnesses_and_database
node_under_test = world.network('Beta').node('NodeUnderTest')
transactions = Base.classes.transactions
transactions_reversible = Base.classes.transactions_reversible
transactions_multisig = Base.classes.transactions_multisig
transactions_multisig_reversible = Base.classes.transactions_multisig_reversible
# WHEN
run_networks(world, Path().resolve())
node_under_test.wait_for_block_with_number(START_TEST_BLOCK)
wallet = Wallet(attach_to=node_under_test)
trx1 = prepare_transaction1(wallet)
trx2 = prepare_transaction2(wallet)
make_fork(
world,
main_chain_trxs = [trx1],
fork_chain_trxs = [trx2],
)
# THEN
trx_fork = session.query(transactions_reversible).filter(transactions_reversible.block_num > START_TEST_BLOCK).one()
trx_hash_fork = trx_fork.trx_hash
logger.info(f'Found transaction with hash {trx_hash_fork} on block {trx_fork.block_num}, this will be reverted')
session.query(transactions_multisig_reversible).filter(transactions_multisig_reversible.trx_hash == trx_hash_fork).one()
after_fork_block = back_from_fork(world)
wait_for_irreversible_progress(node_under_test, after_fork_block)
trx_main = session.query(transactions).filter(transactions.block_num > START_TEST_BLOCK).one()
trx_hash_main = trx_main.trx_hash
logger.info(f'Found transaction with hash {trx_hash_main} on block {trx_main.block_num}')
session.query(transactions_multisig).filter(transactions_multisig.trx_hash == trx_hash_main).one()
trxs_fork = session.query(transactions_multisig).filter(transactions_multisig.trx_hash == trx_hash_fork).all()
assert trxs_fork == []
def prepare_transaction1(wallet):
context1 = wallet.in_single_transaction(broadcast=False)
with context1:
for name in ['witness1-alpha', 'witness1-beta']:
wallet.api.transfer(name, "initminer", Asset.Test(1), 'memo')
transaction1 = context1.get_response()
return transaction1
def prepare_transaction2(wallet):
context2 = wallet.in_single_transaction(broadcast=False)
with context2:
for name in ['witness2-alpha', 'witness2-beta']:
wallet.api.transfer(name, "initminer", Asset.Test(1), 'memo')
transaction2 = context2.get_response()
return transaction2
2021-10-20T10:41:03
\ No newline at end of file
2021-11-25T14:24:39
\ No newline at end of file
[tox]
envlist = py38 py36
envlist = py38
skipsdist = True
[testenv]
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment