<commit_before>-module(aest_hard_fork_SUITE).

%=== EXPORTS ===================================================================

% Common Test exports
-export([all/0]).
-export([groups/0]).
-export([suite/0]).
-export([init_per_suite/1]).
-export([end_per_suite/1]).
-export([init_per_group/2]).
-export([end_per_group/2]).
-export([init_per_testcase/2]).
-export([end_per_testcase/2]).

% Test cases
-export([
         old_node_persisting_chain_and_not_mining_has_genesis_as_top/1,
         new_node_persisting_chain_and_not_mining_has_same_old_genesis_as_top/1,
         new_nodes_can_mine_and_sync_fast_minimal_chain_with_pow/1,
         restore_db_backup_on_old_node/1,
         old_node_can_receive_chain_from_other_old_node/1,
         new_node_accepts_long_old_chain_from_old_node_up_to_height_of_new_protocol/1,
         new_node_can_receive_short_old_chain_from_old_node/1,
         old_chain_has_no_contracts_in_top_block_state/1,
         new_node_can_mine_on_old_chain_using_old_protocol/1,
         new_node_can_mine_on_old_chain_using_new_protocol/1,
         new_node_can_mine_spend_tx_on_old_chain_using_old_protocol/1,
         new_node_can_mine_spend_tx_on_old_chain_using_new_protocol/1
        ]).

%=== INCLUDES ==================================================================

-include_lib("stdlib/include/assert.hrl").

%=== MACROS ====================================================================

-define(LATEST_DOCKER_IMAGE, "aeternity/epoch:v0.11.1").
-define(TESTED_DOCKER_IMAGE, "aeternity/epoch:local").

-define(DB_BACKUP_DEST_DIR, "/tmp/mnesia_backup").

-define(HEIGHT_OF_NEW_PROTOCOL(OldChainHeight),
        (2 + OldChainHeight)
       ).
-define(HEIGHT_OF_NEW_PROTOCOL_FOR_VALIDATING_BLOCKS(OldChainHeight),
        (- 3 + OldChainHeight)
       ).

-define(HEIGHT_OF_NEW_PROTOCOL_UNREACHABLE(OldChainHeight),
        (1000000000 + OldChainHeight)
       ).

-define(CUCKOO_MINER(N),
        #{ex => list_to_binary("mean" ++ integer_to_list(N) ++ "s-generic"),
          args => <<"-t 5">>,
          bits => N}
       ).

-define(OLD_NODE1, #{
          name    => old_node1,
          peers   => [],
          backend => aest_docker,
          source  => {pull, ?LATEST_DOCKER_IMAGE},
          mine_rate => default
         }).

-define(OLD_NODE2, #{
          name    => old_node2,
          peers   => [old_node1],
          backend => aest_docker,
          source  => {pull, ?LATEST_DOCKER_IMAGE},
          mine_rate => default
}).

-define(NEW_NODE1(Ps), #{
          name    => new_node1,
          peers   => [],
          backend => aest_docker,
          source  => {pull, ?TESTED_DOCKER_IMAGE},
          mine_rate => default,
          hard_forks => Ps
         }).

-define(NEW_NODE2(Ps), #{
          name    => new_node2,
          peers   => [old_node1],
          backend => aest_docker,
          source  => {pull, ?TESTED_DOCKER_IMAGE},
          mine_rate => default,
          hard_forks => Ps
         }).

-define(NEW_NODE3(Ps), #{
          name    => new_node3,
          peers   => [old_node1],
          backend => aest_docker,
          source  => {pull, ?TESTED_DOCKER_IMAGE},
          mine_rate => default,
          hard_forks => Ps
         }).

-define(NEW_NODE4(Ps), #{
          name    => new_node4,
          peers   => [new_node3],
          backend => aest_docker,
          source  => {pull, ?TESTED_DOCKER_IMAGE},
          mine_rate => default,
          hard_forks => Ps
         }).

-define(FAST_NEW_NODE1(Ps), #{
          name    => fast_new_node1,
          peers   => [],
          backend => aest_docker,
          source  => {pull, ?TESTED_DOCKER_IMAGE},
          mine_rate => 1000,
          cuckoo_miner => ?CUCKOO_MINER(16),
          hard_forks => Ps
         }).

-define(FAST_NEW_NODE2(Ps), #{
          name    => fast_new_node2,
          peers   => [fast_new_node1],
          backend => aest_docker,
          source  => {pull, ?TESTED_DOCKER_IMAGE},
          mine_rate => 1000,
          cuckoo_miner => ?CUCKOO_MINER(16),
          hard_forks => Ps
         }).

-define(is_testcase_in_group_assumptions(C),
        ( (C =:= old_node_persisting_chain_and_not_mining_has_genesis_as_top)
          or (C =:= new_node_persisting_chain_and_not_mining_has_same_old_genesis_as_top)
          or (C =:= new_nodes_can_mine_and_sync_fast_minimal_chain_with_pow)
        )).

%=== COMMON TEST FUNCTIONS =====================================================

all() ->
    [
     {group, assumptions},
     {group, hard_fork},
     {group, hard_fork_with_tx}
    ].

groups() ->
    [
     {assumptions,
      [
       {genesis,
        [sequence], %% Hard deps among tests.
        [
         old_node_persisting_chain_and_not_mining_has_genesis_as_top,
         new_node_persisting_chain_and_not_mining_has_same_old_genesis_as_top
        ]},
       new_nodes_can_mine_and_sync_fast_minimal_chain_with_pow
      ]},
     {hard_fork,
      [sequence], %% Hard deps among tests/groups.
      [
       restore_db_backup_on_old_node, %% Determines info of top of chain in DB backup.
       {group, hard_fork_all}
      ]},
     {hard_fork_all,
      [sequence], %% Soft deps among tests/groups: if a test/group fails better skipping the rest.
      [
       old_node_can_receive_chain_from_other_old_node,
       new_node_accepts_long_old_chain_from_old_node_up_to_height_of_new_protocol,
       {group, upgrade_flow_smoke_test}
      ]},
     {upgrade_flow_smoke_test,
      [sequence], %% Hard deps among tests/groups.
      [
       new_node_can_receive_short_old_chain_from_old_node,
       old_chain_has_no_contracts_in_top_block_state,
       new_node_can_mine_on_old_chain_using_old_protocol,
       new_node_can_mine_on_old_chain_using_new_protocol
      ]},
     {hard_fork_with_tx,
      [sequence],
      [
       restore_db_backup_on_old_node, %% Determines info of top of chain in DB backup.
       {group, hard_fork_all_with_tx}
      ]},
     {hard_fork_all_with_tx,
      [sequence],
      [
       {group, hard_fork_old_chain_with_tx},
       {group, hard_fork_new_chain_with_tx}
      ]},
     {hard_fork_old_chain_with_tx,
      [sequence],
      [
       new_node_can_receive_short_old_chain_from_old_node,
       new_node_can_mine_spend_tx_on_old_chain_using_old_protocol
      ]},
     {hard_fork_new_chain_with_tx,
      [sequence],
      [
       new_node_can_receive_short_old_chain_from_old_node,<commit_msg>Disable system test not applicable to master with new spend tx changes<commit_after>-module(aest_hard_fork_SUITE).

%=== EXPORTS ===================================================================

% Common Test exports
-export([all/0]).
-export([groups/0]).
-export([suite/0]).
-export([init_per_suite/1]).
-export([end_per_suite/1]).
-export([init_per_group/2]).
-export([end_per_group/2]).
-export([init_per_testcase/2]).
-export([end_per_testcase/2]).

% Test cases
-export([
         old_node_persisting_chain_and_not_mining_has_genesis_as_top/1,
         new_node_persisting_chain_and_not_mining_has_same_old_genesis_as_top/1,
         new_nodes_can_mine_and_sync_fast_minimal_chain_with_pow/1,
         restore_db_backup_on_old_node/1,
         old_node_can_receive_chain_from_other_old_node/1,
         new_node_accepts_long_old_chain_from_old_node_up_to_height_of_new_protocol/1,
         new_node_can_receive_short_old_chain_from_old_node/1,
         old_chain_has_no_contracts_in_top_block_state/1,
         new_node_can_mine_on_old_chain_using_old_protocol/1,
         new_node_can_mine_on_old_chain_using_new_protocol/1,
         new_node_can_mine_spend_tx_on_old_chain_using_old_protocol/1,
         new_node_can_mine_spend_tx_on_old_chain_using_new_protocol/1
        ]).

%=== INCLUDES ==================================================================

-include_lib("stdlib/include/assert.hrl").

%=== MACROS ====================================================================

-define(LATEST_DOCKER_IMAGE, "aeternity/epoch:v0.11.1").
-define(TESTED_DOCKER_IMAGE, "aeternity/epoch:local").

-define(DB_BACKUP_DEST_DIR, "/tmp/mnesia_backup").

-define(HEIGHT_OF_NEW_PROTOCOL(OldChainHeight),
        (2 + OldChainHeight)
       ).
-define(HEIGHT_OF_NEW_PROTOCOL_FOR_VALIDATING_BLOCKS(OldChainHeight),
        (- 3 + OldChainHeight)
       ).

-define(HEIGHT_OF_NEW_PROTOCOL_UNREACHABLE(OldChainHeight),
        (1000000000 + OldChainHeight)
       ).

-define(CUCKOO_MINER(N),
        #{ex => list_to_binary("mean" ++ integer_to_list(N) ++ "s-generic"),
          args => <<"-t 5">>,
          bits => N}
       ).

-define(OLD_NODE1, #{
          name    => old_node1,
          peers   => [],
          backend => aest_docker,
          source  => {pull, ?LATEST_DOCKER_IMAGE},
          mine_rate => default
         }).

-define(OLD_NODE2, #{
          name    => old_node2,
          peers   => [old_node1],
          backend => aest_docker,
          source  => {pull, ?LATEST_DOCKER_IMAGE},
          mine_rate => default
}).

-define(NEW_NODE1(Ps), #{
          name    => new_node1,
          peers   => [],
          backend => aest_docker,
          source  => {pull, ?TESTED_DOCKER_IMAGE},
          mine_rate => default,
          hard_forks => Ps
         }).

-define(NEW_NODE2(Ps), #{
          name    => new_node2,
          peers   => [old_node1],
          backend => aest_docker,
          source  => {pull, ?TESTED_DOCKER_IMAGE},
          mine_rate => default,
          hard_forks => Ps
         }).

-define(NEW_NODE3(Ps), #{
          name    => new_node3,
          peers   => [old_node1],
          backend => aest_docker,
          source  => {pull, ?TESTED_DOCKER_IMAGE},
          mine_rate => default,
          hard_forks => Ps
         }).

-define(NEW_NODE4(Ps), #{
          name    => new_node4,
          peers   => [new_node3],
          backend => aest_docker,
          source  => {pull, ?TESTED_DOCKER_IMAGE},
          mine_rate => default,
          hard_forks => Ps
         }).

-define(FAST_NEW_NODE1(Ps), #{
          name    => fast_new_node1,
          peers   => [],
          backend => aest_docker,
          source  => {pull, ?TESTED_DOCKER_IMAGE},
          mine_rate => 1000,
          cuckoo_miner => ?CUCKOO_MINER(16),
          hard_forks => Ps
         }).

-define(FAST_NEW_NODE2(Ps), #{
          name    => fast_new_node2,
          peers   => [fast_new_node1],
          backend => aest_docker,
          source  => {pull, ?TESTED_DOCKER_IMAGE},
          mine_rate => 1000,
          cuckoo_miner => ?CUCKOO_MINER(16),
          hard_forks => Ps
         }).

-define(is_testcase_in_group_assumptions(C),
        ( (C =:= old_node_persisting_chain_and_not_mining_has_genesis_as_top)
          or (C =:= new_node_persisting_chain_and_not_mining_has_same_old_genesis_as_top)
          or (C =:= new_nodes_can_mine_and_sync_fast_minimal_chain_with_pow)
        )).

%=== COMMON TEST FUNCTIONS =====================================================

all() ->
    [
     {group, assumptions},
     {group, hard_fork},
     {group, hard_fork_with_tx}
    ].

groups() ->
    [
     {assumptions,
      [
       {genesis,
        [sequence], %% Hard deps among tests.
        [
         old_node_persisting_chain_and_not_mining_has_genesis_as_top,
         new_node_persisting_chain_and_not_mining_has_same_old_genesis_as_top
        ]},
       new_nodes_can_mine_and_sync_fast_minimal_chain_with_pow
      ]},
     {hard_fork,
      [sequence], %% Hard deps among tests/groups.
      [
       restore_db_backup_on_old_node, %% Determines info of top of chain in DB backup.
       {group, hard_fork_all}
      ]},
     {hard_fork_all,
      [sequence], %% Soft deps among tests/groups: if a test/group fails better skipping the rest.
      [
       old_node_can_receive_chain_from_other_old_node,
       new_node_accepts_long_old_chain_from_old_node_up_to_height_of_new_protocol,
       {group, upgrade_flow_smoke_test}
      ]},
     {upgrade_flow_smoke_test,
      [sequence], %% Hard deps among tests/groups.
      [
       new_node_can_receive_short_old_chain_from_old_node,
       old_chain_has_no_contracts_in_top_block_state,
       new_node_can_mine_on_old_chain_using_old_protocol,
       new_node_can_mine_on_old_chain_using_new_protocol
      ]},
     {hard_fork_with_tx,
      [sequence],
      [
       restore_db_backup_on_old_node, %% Determines info of top of chain in DB backup.
       {group, hard_fork_all_with_tx}
      ]},
     {hard_fork_all_with_tx,
      [sequence],
      [
       %% {group, hard_fork_old_chain_with_tx}, Not applicable as is in 0.12.0 because new node's user API creates only new spend tx.
       {group, hard_fork_new_chain_with_tx}
      ]},
     {hard_fork_old_chain_with_tx,
      [sequence],
      [
       new_node_can_receive_short_old_chain_from_old_node,
       new_node_can_mine_spend_tx_on_old_chain_using_old_protocol
      ]},
     {hard_fork_new_chain_with_tx,
      [sequence],
      [
       new_node_can_receive_short_old_chain_from_old_node,
{'fraction_non_alphanumeric': 0.14116561586959864, 'fraction_numerical': 0.011225588190066124, 'mean_word_length': 2.774521183981428, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 113, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1542003', 'n_tokens_mistral': 4665, 'n_tokens_neox': 4470, 'n_words': 564}