1 module tagion.testbench.hashgraph.swap; 2 // Default import list for bdd 3 import std.algorithm; 4 import std.datetime; 5 import std.format; 6 import std.path : buildPath, extension, setExtension; 7 import std.stdio; 8 import std.typecons : Tuple; 9 import std.typecons; 10 import tagion.basic.Types : FileExtension; 11 import tagion.behaviour; 12 import tagion.crypto.SecureInterfaceNet : SecureNet; 13 import tagion.crypto.SecureNet : StdSecureNet; 14 import tagion.crypto.Types : Pubkey; 15 import tagion.hibon.Document; 16 import tagion.testbench.hashgraph.hashgraph_test_network; 17 import tagion.testbench.tools.Environment; 18 import tagion.utils.Miscellaneous : cutHex; 19 import tagion.utils.Miscellaneous : cutHex; 20 21 enum feature = Feature( 22 "Hashgraph Swapping", 23 ["This test is meant to test that a node can be swapped out at a specific epoch"]); 24 25 alias FeatureContext = Tuple!( 26 NodeSwap, "NodeSwap", 27 FeatureGroup*, "result" 28 ); 29 30 @safe @Scenario("node swap", 31 []) 32 class NodeSwap { 33 34 string[] node_names; 35 TestNetwork network; 36 string module_path; 37 uint MAX_CALLS; 38 Pubkey offline_key; 39 enum new_node = "NEW_NODE"; 40 41 this(string[] node_names, const uint calls, const string module_path) { 42 this.node_names = node_names; 43 this.module_path = module_path; 44 MAX_CALLS = cast(uint) node_names.length * calls; 45 } 46 47 @Given("i have a hashgraph testnetwork with n number of nodes.") 48 Document nodes() { 49 50 network = new TestNetwork(node_names); 51 network.networks.byValue.each!((ref _net) => _net._hashgraph.scrap_depth = 0); 52 network.random.seed(123456789); 53 writeln(network.random); 54 55 network.global_time = SysTime.fromUnixTime(1_614_355_286); 56 offline_key = Pubkey(network.channels[1]); 57 58 auto net = new StdSecureNet(); 59 net.generateKeyPair(format("very secret %s", new_node)); 60 TestRefinement.swap = TestRefinement.Swap(offline_key, net.pubkey, 10); 61 return result_ok; 62 } 63 64 @Given("that all nodes knows a node should be swapped.") 65 Document swapped() { 66 return result_ok; 67 } 68 69 @When("a node has created a specific amount of epochs, it swaps in the new node.") 70 Document node() { 71 foreach (i; 0 .. MAX_CALLS) { 72 const channel_number = network.random.value(0, network.channels.length); 73 const channel = network.channels[channel_number]; 74 network.current = Pubkey(channel); 75 auto current = network.networks[channel]; 76 77 if (TestRefinement.epoch_events.length == node_names.length && TestRefinement.epoch_events 78 .byValue 79 .map!((ep) => ep.length) 80 .all!((ep_length) => ep_length > 2)) { 81 break; 82 } 83 (() @trusted { current.call; })(); 84 } 85 86 TestNetwork.TestGossipNet.online_states[offline_key] = !TestNetwork.TestGossipNet.online_states[offline_key]; 87 // TestNetwork.TestGossipNet.online_states[offline_key] = false; 88 89 foreach (i; 0 .. MAX_CALLS) { 90 const channel_number = network.random.value(0, network.channels.length); 91 const channel = network.channels[channel_number]; 92 network.current = Pubkey(channel); 93 auto current = network.networks[channel]; 94 95 (() @trusted { current.call; })(); 96 } 97 98 writefln("ADDING NEW NODE"); 99 network.addNode(node_names.length, new_node, Yes.joining); 100 101 foreach (i; 0 .. MAX_CALLS) { 102 const channel_number = network.random.value(0, network.channels.length); 103 const channel = network.channels[channel_number]; 104 network.current = Pubkey(channel); 105 auto current = network.networks[channel]; 106 107 (() @trusted { current.call; })(); 108 } 109 110 return result_ok; 111 } 112 113 @Then("the new node should come in graph.") 114 Document graph() { 115 return result_ok; 116 } 117 118 @Then("compare the epochs created from the point of the swap.") 119 Document swap() { 120 return result_ok; 121 } 122 123 @Then("stop the network.") 124 Document _network() { 125 Pubkey[string] node_labels; 126 foreach (channel, _net; network.networks) { 127 node_labels[_net._hashgraph.name] = channel; 128 } 129 foreach (_net; network.networks) { 130 const filename = buildPath(module_path, "ripple-" ~ _net._hashgraph.name 131 .setExtension(FileExtension.hibon)); 132 writeln(filename); 133 _net 134 ._hashgraph.fwrite(filename, node_labels); 135 } 136 return result_ok; 137 } 138 139 }