1 module tagion.testbench.spam_double_spend;
2 
3 import core.thread;
4 import core.time;
5 import std.file;
6 import std.path : buildPath, setExtension;
7 import std.stdio;
8 import tagion.GlobalSignals;
9 import tagion.basic.Types : FileExtension;
10 import tagion.behaviour.Behaviour;
11 import tagion.services.options;
12 import tagion.testbench.services;
13 import tagion.testbench.tools.Environment;
14 import tagion.tools.Basic;
15 import neuewelle = tagion.tools.neuewelle;
16 import tagion.utils.pretend_safe_concurrency;
17 
18 mixin Main!(_main);
19 
20 void wrap_neuewelle(immutable(string)[] args) {
21     neuewelle._main(cast(string[]) args);
22 }
23 
24 int _main(string[] args) {
25     auto module_path = env.bdd_log.buildPath(__MODULE__);
26 
27     if (module_path.exists) {
28         rmdirRecurse(module_path);
29     }
30     mkdirRecurse(module_path);
31     string config_file = buildPath(module_path, "tagionwave.json");
32 
33     scope Options local_options = Options.defaultOptions;
34     local_options.dart.folder_path = buildPath(module_path);
35     local_options.replicator.folder_path = buildPath(module_path, "recorders");
36     local_options.wave.prefix_format = "Spam_DoubleSpend_Node_%s_";
37     local_options.subscription.address = contract_sock_addr("SPAM_SUBSCRIPTION");
38 
39     local_options.save(config_file);
40 
41     import std.algorithm;
42     import std.array;
43     import std.format;
44     import std.range;
45     import std.stdio;
46     import tagion.crypto.SecureInterfaceNet;
47     import tagion.crypto.SecureNet : StdSecureNet;
48     import tagion.dart.DART;
49     import tagion.dart.DARTFile;
50     import tagion.dart.Recorder;
51     import tagion.script.TagionCurrency;
52     import tagion.script.common : TagionBill;
53     import tagion.testbench.services.sendcontract;
54     import tagion.wallet.SecureWallet;
55 
56     StdSecureWallet[] wallets;
57     // create the wallets
58     foreach (i; 0 .. 20) {
59         StdSecureWallet secure_wallet;
60         secure_wallet = StdSecureWallet(
61                 iota(0, 5).map!(n => format("%dquestion%d", i, n)).array,
62                 iota(0, 5).map!(n => format("%danswer%d", i, n)).array,
63                 4,
64                 format("%04d", i),
65         );
66         wallets ~= secure_wallet;
67     }
68 
69     // bills for the dart on startup
70 
71     TagionBill requestAndForce(ref StdSecureWallet w, TagionCurrency amount) {
72         auto b = w.requestBill(amount);
73         w.addBill(b);
74         return b;
75     }
76 
77     TagionBill[] bills;
78     foreach (ref wallet; wallets) {
79         foreach (i; 0 .. 3) {
80             bills ~= requestAndForce(wallet, 1000.TGN);
81         }
82     }
83 
84     SecureNet net = new StdSecureNet();
85     net.generateKeyPair("very_secret");
86 
87     auto factory = RecordFactory(net);
88     auto recorder = factory.recorder;
89     recorder.insert(bills, Archive.Type.ADD);
90 
91     foreach (i; 0 .. local_options.wave.number_of_nodes) {
92         immutable prefix = format(local_options.wave.prefix_format, i);
93         const path = buildPath(local_options.dart.folder_path, prefix ~ local_options.dart.dart_filename);
94         writeln(path);
95         DARTFile.create(path, net);
96         auto db = new DART(net, path);
97         db.modify(recorder);
98         db.close;
99     }
100 
101     immutable neuewelle_args = ["spam_double_spend_test", config_file, "--nodeopts", module_path]; // ~ args;
102     auto tid = spawn(&wrap_neuewelle, neuewelle_args);
103 
104     import tagion.utils.JSONCommon : load;
105 
106     Options[] node_opts;
107 
108     Thread.sleep(15.seconds);
109     foreach (i; 0 .. local_options.wave.number_of_nodes) {
110         const filename = buildPath(module_path, format(local_options.wave.prefix_format ~ "opts", i).setExtension(FileExtension
111                 .json));
112         writeln(filename);
113         Options node_opt = load!(Options)(filename);
114         node_opts ~= node_opt;
115     }
116 
117     writefln("INPUT SOCKET ADDRESS %s", node_opts[0].inputvalidator.sock_addr);
118 
119     auto feature = automation!(spam_double_spend);
120     feature.SpamOneNodeUntil10EpochsHaveOccured(node_opts, wallets[0], wallets[1]);
121     feature.SpamMultipleNodesUntil10EpochsHaveOccured(node_opts, wallets[2], wallets[3]);
122 
123     feature.run();
124 
125     stopsignal.set;
126     Thread.sleep(6.seconds);
127     return 0;
128 }