1 module tagion.testbench.genesis_test;
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.actor;
10 import tagion.basic.Types : FileExtension;
11 import tagion.behaviour.Behaviour;
12 import tagion.logger.Logger;
13 import tagion.services.options;
14 import tagion.testbench.services;
15 import tagion.testbench.tools.Environment;
16 import tagion.tools.Basic;
17 import neuewelle = tagion.tools.neuewelle;
18 import tagion.utils.pretend_safe_concurrency;
19 import tagion.hibon.BigNumber;
20 
21 mixin Main!(_main);
22 
23 void wrap_neuewelle(immutable(string)[] args) {
24     neuewelle._main(cast(string[]) args);
25 }
26 
27 int _main(string[] args) {
28 
29     auto module_path = env.bdd_log.buildPath(__MODULE__);
30 
31     if (module_path.exists) {
32         rmdirRecurse(module_path);
33     }
34     mkdirRecurse(module_path);
35     string config_file = buildPath(module_path, "tagionwave.json");
36 
37     scope Options local_options = Options.defaultOptions;
38     local_options.dart.folder_path = buildPath(module_path);
39     local_options.replicator.folder_path = buildPath(module_path, "recorders");
40     local_options.wave.prefix_format = "Genesis Node_%s_";
41     local_options.subscription.address = contract_sock_addr("GENESIS_SUBSCRIPTION");
42     local_options.save(config_file);
43 
44     import std.algorithm;
45     import std.array;
46     import std.format;
47     import std.range;
48     import std.stdio;
49     import tagion.crypto.SecureInterfaceNet;
50     import tagion.crypto.SecureNet : StdSecureNet;
51     import tagion.dart.DART;
52     import tagion.dart.DARTBasic;
53     import tagion.dart.DARTFile;
54     import tagion.dart.Recorder;
55     import tagion.hibon.Document;
56     import tagion.hibon.HiBON;
57     import tagion.script.TagionCurrency;
58     import tagion.script.common : TagionBill;
59     import tagion.testbench.services.genesis_test;
60     import tagion.wallet.SecureWallet;
61 
62     StdSecureWallet[] wallets;
63     // create the wallets
64     foreach (i; 0 .. 2) {
65         StdSecureWallet secure_wallet;
66         secure_wallet = StdSecureWallet(
67                 iota(0, 5).map!(n => format("%dquestion%d", i, n)).array,
68                 iota(0, 5).map!(n => format("%danswer%d", i, n)).array,
69                 4,
70                 format("%04d", i),
71         );
72         wallets ~= secure_wallet;
73     }
74 
75     // bills for the dart on startup
76 
77     TagionBill requestAndForce(ref StdSecureWallet w, TagionCurrency amount) {
78         auto b = w.requestBill(amount);
79         w.addBill(b);
80         return b;
81     }
82 
83     TagionBill[] bills;
84     BigNumber total_start_amount;
85     foreach (ref wallet; wallets) {
86         foreach (i; 0 .. 3) {
87             auto bill = requestAndForce(wallet, 1000.TGN);
88             bills ~= bill;
89             total_start_amount += bill.value.units; 
90         }
91     }
92 
93     SecureNet net = new StdSecureNet();
94     net.generateKeyPair("very_secret");
95 
96     auto factory = RecordFactory(net);
97     auto recorder = factory.recorder;
98     recorder.insert(bills, Archive.Type.ADD);
99 
100     // create the tagion head and genesis epoch
101     import tagion.crypto.Types;
102     import tagion.hibon.HiBON;
103     import tagion.hibon.HiBONtoText;
104     import tagion.script.common : GenesisEpoch, TagionGlobals, TagionHead;
105     import tagion.script.standardnames;
106     import tagion.utils.StdTime;
107 
108     // const total_amount = BigNumber(bills.map!(b => b.value).sum);
109     const number_of_bills = long(bills.length);
110 
111 
112 
113     Pubkey[] keys;
114     foreach (i; 0 .. local_options.wave.number_of_nodes) {
115         auto _net = new StdSecureNet();
116         const pswd = format(local_options.wave.prefix_format, i) ~ "supervisor";
117         writefln("bdd: %s", pswd);
118         _net.generateKeyPair(pswd);
119         keys ~= _net.pubkey;
120         writefln("pkey: %s", _net.pubkey.encodeBase64);
121     }
122 
123     HiBON testamony = new HiBON;
124     testamony["hola"] = "Hallo ich bin philip. VERY OFFICIAL TAGION GENESIS BLOCK; DO NOT ALTER IN ANY WAYS";
125 
126     auto globals = TagionGlobals(total_start_amount, const BigNumber(0), number_of_bills, const long(0));
127     const genesis_epoch = GenesisEpoch(0, keys, Document(testamony), currentTime, globals);
128     const tagion_head = TagionHead(TagionDomain, 0);
129     writefln("total start_amount: %s, HEAD: %s \n genesis_epoch: %s",total_start_amount, tagion_head.toPretty, genesis_epoch.toPretty);
130 
131     recorder.add(tagion_head);
132     recorder.add(genesis_epoch);
133 
134 
135     foreach (i; 0 .. local_options.wave.number_of_nodes) {
136         immutable prefix = format(local_options.wave.prefix_format, i);
137         const path = buildPath(local_options.dart.folder_path, prefix ~ local_options.dart.dart_filename);
138         writeln(path);
139         DARTFile.create(path, net);
140         auto db = new DART(net, path);
141         db.modify(recorder);
142     }
143 
144     immutable neuewelle_args = ["genesis_test", config_file, "--nodeopts", module_path]; // ~ args;
145     auto tid = spawn(&wrap_neuewelle, neuewelle_args);
146 
147     import tagion.utils.JSONCommon : load;
148 
149     Options[] node_opts;
150 
151     Thread.sleep(5.seconds);
152     foreach (i; 0 .. local_options.wave.number_of_nodes) {
153         const filename = buildPath(module_path, format(local_options.wave.prefix_format ~ "opts", i).setExtension(FileExtension
154                 .json));
155         writeln(filename);
156         Options node_opt = load!(Options)(filename);
157         node_opts ~= node_opt;
158     }
159 
160     Thread.sleep(15.seconds);
161     auto name = "genesis_testing";
162     register(name, thisTid);
163     log.registerSubscriptionTask(name);
164 
165 
166     auto feature = automation!(genesis_test);
167     feature.NetworkRunningWithGenesisBlockAndEpochChain(node_opts, wallets[0], genesis_epoch);
168     feature.run;
169 
170     stopsignal.set;
171     Thread.sleep(6.seconds);
172     return 0;
173 }