1 /** 2 * Utilitty function for spawning neuewelle in mode0 3 **/ 4 module tagion.wave.mode0; 5 6 import std.array; 7 import std.file; 8 import std.algorithm; 9 import std.stdio; 10 import std.format; 11 import std.path; 12 import std.range; 13 14 import tagion.crypto.SecureNet; 15 import tagion.crypto.Types; 16 import tagion.dart.DART; 17 import tagion.services.options; 18 import tagion.services.supervisor; 19 import tagion.utils.Term; 20 import tagion.tools.Basic; 21 import tagion.gossip.AddressBook; 22 import std.range : zip; 23 import tagion.hibon.HiBONRecord; 24 import tagion.hibon.Document; 25 import tagion.script.common : Epoch, GenesisEpoch; 26 import tagion.actor; 27 28 // Checks if all nodes bullseyes are the same 29 bool isMode0BullseyeSame(const(Options[]) node_options, SecureNet __net) { 30 import std.typecons; 31 // extra check for mode0 32 // Check bullseyes 33 Fingerprint[] bullseyes; 34 foreach (node_opt; node_options) { 35 if (!node_opt.dart.dart_path.exists) { 36 stderr.writefln("Missing dartfile %s", node_opt.dart.dart_path); 37 return false; 38 } 39 Exception dart_exception; 40 DART db = new DART(__net, node_opt.dart.dart_path, dart_exception, Yes.read_only); 41 if (dart_exception !is null) { 42 throw dart_exception; 43 } 44 scope (exit) { 45 db.close(); 46 } 47 auto b = Fingerprint(db.bullseye); 48 bullseyes ~= b; 49 50 } 51 // check that all bullseyes are the same before boot 52 return bullseyes.all!(b => b == bullseyes[0]); 53 } 54 55 const(Options)[] getMode0Options(const(Options) options, bool monitor = false) { 56 const number_of_nodes = options.wave.number_of_nodes; 57 const prefix_f = options.wave.prefix_format; 58 Options[] all_opts; 59 foreach (node_n; 0 .. number_of_nodes) { 60 auto opt = Options(options); 61 opt.setPrefix(format(prefix_f, node_n)); 62 all_opts ~= opt; 63 } 64 65 if (monitor) { 66 all_opts[0].monitor.enable = true; 67 } 68 69 return all_opts; 70 } 71 72 struct Node { 73 immutable(Options) opts; 74 shared(StdSecureNet) net; 75 Pubkey pkey; 76 } 77 78 void spawnMode0( 79 const(Options)[] node_options, 80 ref ActorHandle[] supervisor_handles, 81 Node[] nodes, 82 Document epoch_head = Document.init) { 83 84 if (epoch_head is Document.init) { 85 foreach (n; zip(nodes, node_options)) { 86 addressbook[n[0].pkey] = NodeAddress(n[1].task_names.epoch_creator); 87 } 88 } 89 else { 90 Pubkey[] keys; 91 if (epoch_head.isRecord!Epoch) { 92 assert(0, "not supported to boot from epoch yet"); 93 keys = Epoch(epoch_head).active; 94 } 95 else { 96 auto genesis = GenesisEpoch(epoch_head); 97 98 keys = genesis.nodes; 99 check(equal(keys, keys.uniq), "Duplicate node public keys in the genesis epoch"); 100 check(keys.length == node_options.length, "There was not the same amount of configured nodes as in the genesis epoch"); 101 } 102 103 foreach (node_info; zip(keys, node_options)) { 104 verbose("adding addressbook ", node_info[0]); 105 addressbook[node_info[0]] = NodeAddress(node_info[1].task_names.epoch_creator); 106 } 107 } 108 109 /// spawn the nodes 110 foreach (n; nodes) { 111 verbose("spawning supervisor ", n.opts.task_names.supervisor); 112 supervisor_handles ~= spawn!Supervisor(n.opts.task_names.supervisor, n.opts, n.net); 113 } 114 }