anchor.diff:         ?NEW_NODE2(?HEIGHT_OF_NEW_PROTOCOL_FOR_VALIDATING_BLOCKS(TopHeight)),
          ?NEW_NODE3(?HEIGHT_OF_NEW_PROTOCOL(TopHeight)),
          ?NEW_NODE4(?HEIGHT_OF_NEW_PROTOCOL(TopHeight))], NewConfig),
  +    NewConfig;
  +init_per_group(hard_fork_old_chain_with_tx, Config) ->
  +    {_, TopHeight} = proplists:lookup(db_backup_top_height, Config),
  +    NewConfig = aest_nodes:ct_setup(Config),
  +    aest_nodes:setup_nodes(
  +      [?NEW_NODE1(?HEIGHT_OF_NEW_PROTOCOL_UNREACHABLE(TopHeight)),
  +       ?NEW_NODE3(?HEIGHT_OF_NEW_PROTOCOL_UNREACHABLE(TopHeight)),
  +       ?NEW_NODE4(?HEIGHT_OF_NEW_PROTOCOL_UNREACHABLE(TopHeight))], NewConfig),
  +    NewConfig;
  +init_per_group(hard_fork_new_chain_with_tx, Config) ->
  +    {_, TopHeight} = proplists:lookup(db_backup_top_height, Config),
  +    NewConfig = aest_nodes:ct_setup(Config),
  +    aest_nodes:setup_nodes(
  +      [?NEW_NODE1(?HEIGHT_OF_NEW_PROTOCOL(TopHeight)),
  +       ?NEW_NODE3(?HEIGHT_OF_NEW_PROTOCOL(TopHeight)),
  +       ?NEW_NODE4(?HEIGHT_OF_NEW_PROTOCOL(TopHeight))], NewConfig),
       NewConfig.
   
   end_per_group(assumptions, _) -> ok;
   end_per_group(genesis, _) -> ok;
   end_per_group(hard_fork, _) -> ok;
   end_per_group(hard_fork_all, _) -> ok;
  +end_per_group(hard_fork_with_tx, _) -> ok;
  +end_per_group(hard_fork_all_with_tx, _) -> ok;
   end_per_group(upgrade_flow_smoke_test, Config) ->
       aest_nodes:ct_cleanup(Config),
       ok;
  -end_per_group(hard_fork_with_tx, _) -> ok;
  -end_per_group(hard_fork_all_with_tx, _) -> ok.
  +end_per_group(hard_fork_old_chain_with_tx, Config) ->
  +    aest_nodes:ct_cleanup(Config),
  +    ok;
  +end_per_group(hard_fork_new_chain_with_tx, Config) ->
  +    aest_nodes:ct_cleanup(Config),
  +    ok.
   
   init_per_testcase(old_node_persisting_chain_and_not_mining_has_genesis_as_top, Config) ->
       aest_nodes:ct_setup(Config);
  
positive.code: 
  %% New node can sync the old chain from other new node and can start mining
  %% on the top of the old chain. The new node can mine blocks using the old
  %% protocol and include spend transaction in the blocks.
  new_node_can_mine_spend_tx_on_old_chain_using_old_protocol(Cfg) ->
      {_, TopHeight} = proplists:lookup(db_backup_top_height, Cfg),
      {_, TopHash} = proplists:lookup(db_backup_top_hash, Cfg),
      % Make sure the chain won't switch to the new protocol during the test.
      HeightOfNewProtocol = TopHeight + 10000000,
      aest_nodes:setup_nodes(
        [?NEW_NODE1(HeightOfNewProtocol),
         ?NEW_NODE2(HeightOfNewProtocol)], Cfg),
      % Start new node and restore the old chain.
      start_node(new_node1, Cfg),
      {ok, {TopHash, TopHeight}} = restore_db_backup_on_node(new_node1, Cfg),
      B1 = get_block_by_height(new_node1, TopHeight, Cfg),
      ?assertEqual(TopHash, maps:get(hash, B1)),
      %% Make sure balance of new_node1 is 0.
      PubKey1 = get_public_key(new_node1, Cfg),
      Balance1 = get_balance(new_node1, PubKey1, Cfg),
      ?assertEqual(0, Balance1),
      ct:log("Balance of node ~p with public key ~p is ~p", [new_node1, PubKey1, Balance1]),
      %% Sync the chain on new_node2 from new_node1.
      start_node(new_node2, Cfg),
      wait_for_height_syncing(TopHeight, [new_node2], {{45000, ms}, {200, blocks}}, Cfg),
      B2 = get_block_by_height(new_node2, TopHeight, Cfg),
      ?assertEqual(TopHash, maps:get(hash, B2)),
      %% Make sure balance of new_node2 is 0.
      PubKey2 = get_public_key(new_node2, Cfg),
      Balance2 = get_balance(new_node2, PubKey2, Cfg),
      ?assertEqual(0, Balance2),
      ct:log("Balance of node ~p with public key ~p is ~p", [new_node2, PubKey2, Balance2]),
      %% Start mining on new_node2.
      ok = mock_pow_on_node(new_node1, Cfg),
      ok = mock_pow_on_node(new_node2, Cfg),
      run_erl_cmd_on_node(new_node2, "aec_conductor:start_mining().", "ok", Cfg),
      %% Check that new_node2 got reward for mining.
      MinedReward = 100,
      aest_nodes:wait_for_value({balance, PubKey2, MinedReward}, [new_node2], 10000, Cfg),
      MinedBalance = get_balance(new_node2, PubKey2, Cfg),
      ?assertMatch(X when X >= MinedReward, MinedBalance),
      ct:log("Mined balance on ~p with public key ~p is ~p", [new_node2, PubKey2, MinedBalance]),
      %% Send spend transaction from new_node2 to new_node1.
      Fee = 5,
      BalanceToSpend = MinedBalance - Fee,
      ok = post_spend_tx(new_node2, PubKey1, BalanceToSpend, Fee, Cfg),
      ct:log("Sent spend tx with balance of ~p from node ~p with public key ~p to node ~p with public key ~p",
             [BalanceToSpend, new_node2, PubKey2, new_node1, PubKey1]),
      %% Make sure new_node1 received the balance.
      aest_nodes:wait_for_value({balance, PubKey1, BalanceToSpend}, [new_node2], 10000, Cfg),
      ReceivedBalance = get_balance(new_node2, PubKey1, Cfg),
      ct:log("Balance of node ~p with public key ~p is ~p", [new_node1, PubKey1, ReceivedBalance]),
      ?assertMatch(BalanceToSpend, ReceivedBalance),
      ok.
  
  %% New node can sync the old chain from other new node and can start mining
  %% on the top of the old chain until a certain height where it switches to the
  %% new protocol. The new node can mine blocks using the new protocol and include
  %% spend transaction in the blocks.
  new_node_can_mine_spend_tx_on_old_chain_using_new_protocol(Cfg) ->
      {_, TopHeight} = proplists:lookup(db_backup_top_height, Cfg),
      {_, TopHash} = proplists:lookup(db_backup_top_hash, Cfg),
      HeightOfNewProtocol = ?HEIGHT_OF_NEW_PROTOCOL(TopHeight),
      LastHeightOfOldProtocol = HeightOfNewProtocol - 1,
      aest_nodes:setup_nodes(
        [?NEW_NODE1(HeightOfNewProtocol),
         ?NEW_NODE2(HeightOfNewProtocol)], Cfg),
      %% Start new node and restore the old chain.
      start_node(new_node1, Cfg),
      {ok, {TopHash, TopHeight}} = restore_db_backup_on_node(new_node1, Cfg),
      B1 = get_block_by_height(new_node1, TopHeight, Cfg),
      ?assertEqual(TopHash, maps:get(hash, B1)),
      %% Make sure balance of new_node1 is 0.
      PubKey1 = get_public_key(new_node1, Cfg),
      Balance1 = get_balance(new_node1, PubKey1, Cfg),
      ?assertEqual(0, Balance1),
      ct:log("Balance of node ~p with public key ~p is ~p", [new_node1, PubKey1, Balance1]),
      %% Sync the chain on new_node2 from new_node1.
      start_node(new_node2, Cfg),
      wait_for_height_syncing(TopHeight, [new_node2], {{45000, ms}, {200, blocks}}, Cfg),
      B2 = get_block_by_height(new_node2, TopHeight, Cfg),
      ?assertEqual(TopHash, maps:get(hash, B2)),
      %% Make sure balance of new_node2 is 0.
      PubKey2 = get_public_key(new_node2, Cfg),
      Balance2 = get_balance(new_node2, PubKey2, Cfg),
      ?assertEqual(0, Balance2),
      ct:log("Balance of node ~p with public key ~p is ~p", [new_node2, PubKey2, Balance2]),
      %% Start mining on new_node2.
      ok = mock_pow_on_node(new_node1, Cfg),
      ok = mock_pow_on_node(new_node2, Cfg),
      run_erl_cmd_on_node(new_node2, "aec_conductor:start_mining().", "ok", Cfg),
      %% Check the last block of old protocol has genesis version.
      wait_for_height_syncing(LastHeightOfOldProtocol, [new_node2], {{10000, ms}, {1000, blocks}}, Cfg),
      B2OldProtocol = get_block_by_height(new_node2, LastHeightOfOldProtocol, Cfg),
      ?assertEqual(9, maps:get(version, B2OldProtocol)),
      %% Check the first block of new protocol has version of the new protocol.
      wait_for_height_syncing(HeightOfNewProtocol, [new_node2], {{10000, ms}, {1000, blocks}}, Cfg),
      B2NewProtocol = get_block_by_height(new_node2, HeightOfNewProtocol, Cfg),
      ?assertEqual(10, maps:get(version, B2NewProtocol)),
      %% Check that new_node2 got reward for mining.
      MinedReward = 100,
      aest_nodes:wait_for_value({balance, PubKey2, MinedReward}, [new_node2], 10000, Cfg),
      MinedBalance = get_balance(new_node2, PubKey2, Cfg),
      ?assertMatch(X when X >= MinedReward, MinedBalance),
      ct:log("Mined balance on ~p with public key ~p is ~p", [new_node2, PubKey2, MinedBalance]),
      %% Send spend transaction from new_node2 to new_node1.
      Fee = 5,
      BalanceToSpend = MinedBalance - Fee,
      ok = post_spend_tx(new_node2, PubKey1, BalanceToSpend, Fee, Cfg),
      ct:log("Sent spend tx with balance of ~p from node ~p with public key ~p to node ~p with public key ~p",
             [BalanceToSpend, new_node2, PubKey2, new_node1, PubKey1]),
      %% Make sure new_node1 received the balance.
      aest_nodes:wait_for_value({balance, PubKey1, BalanceToSpend}, [new_node2], 10000, Cfg),
      ReceivedBalance = get_balance(new_node2, PubKey1, Cfg),
      ct:log("Balance of node ~p with public key ~p is ~p", [new_node1, PubKey1, ReceivedBalance]),
      ?assertMatch(BalanceToSpend, ReceivedBalance),
      ok.
  
  %=== INTERNAL FUNCTIONS ========================================================
  
negative.code:        ).
  -define(HEIGHT_OF_NEW_PROTOCOL_FOR_VALIDATING_BLOCKS(OldChainHeight),
          (- 3 + OldChainHeight)
         ).
  
  -define(HEIGHT_OF_NEW_PROTOCOL_UNREACHABLE(OldChainHeight),
          (1000000000 + OldChainHeight)
         ).
  
  -define(CUCKOO_MINER(N),
  