1 module tagion.testbench.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.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.services.double_spend; 16 import tagion.testbench.tools.Environment; 17 import tagion.tools.Basic; 18 import neuewelle = tagion.tools.neuewelle; 19 import tagion.utils.pretend_safe_concurrency; 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 auto module_path = env.bdd_log.buildPath(__MODULE__); 29 30 if (module_path.exists) { 31 rmdirRecurse(module_path); 32 } 33 mkdirRecurse(module_path); 34 string config_file = buildPath(module_path, "tagionwave.json"); 35 36 scope Options local_options = Options.defaultOptions; 37 local_options.dart.folder_path = buildPath(module_path); 38 local_options.replicator.folder_path = buildPath(module_path, "recorders"); 39 local_options.wave.prefix_format = "DoubleSpend_Node_%s_"; 40 local_options.subscription.address = contract_sock_addr("DOUBLE_SPEND_SUBSCRIPTION"); 41 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.DARTFile; 53 import tagion.dart.Recorder; 54 import tagion.script.TagionCurrency; 55 import tagion.script.common : TagionBill; 56 import tagion.testbench.services.sendcontract; 57 import tagion.wallet.SecureWallet; 58 59 StdSecureWallet[] wallets; 60 // create the wallets 61 foreach (i; 0 .. 20) { 62 StdSecureWallet secure_wallet; 63 secure_wallet = StdSecureWallet( 64 iota(0, 5).map!(n => format("%dquestion%d", i, n)).array, 65 iota(0, 5).map!(n => format("%danswer%d", i, n)).array, 66 4, 67 format("%04d", i), 68 ); 69 wallets ~= secure_wallet; 70 } 71 72 // bills for the dart on startup 73 74 TagionBill requestAndForce(ref StdSecureWallet w, TagionCurrency amount) { 75 auto b = w.requestBill(amount); 76 w.addBill(b); 77 return b; 78 } 79 80 TagionBill[] bills; 81 foreach (ref wallet; wallets) { 82 foreach (i; 0 .. 3) { 83 bills ~= requestAndForce(wallet, 1000.TGN); 84 } 85 } 86 87 SecureNet net = new StdSecureNet(); 88 net.generateKeyPair("very_secret"); 89 90 auto factory = RecordFactory(net); 91 auto recorder = factory.recorder; 92 recorder.insert(bills, Archive.Type.ADD); 93 94 foreach (i; 0 .. local_options.wave.number_of_nodes) { 95 immutable prefix = format(local_options.wave.prefix_format, i); 96 const path = buildPath(local_options.dart.folder_path, prefix ~ local_options.dart.dart_filename); 97 writeln(path); 98 DARTFile.create(path, net); 99 auto db = new DART(net, path); 100 db.modify(recorder); 101 db.close; 102 } 103 104 immutable neuewelle_args = ["double_spend", config_file, "--nodeopts", module_path]; // ~ args; 105 auto tid = spawn(&wrap_neuewelle, neuewelle_args); 106 107 import tagion.utils.JSONCommon : load; 108 109 Options[] node_opts; 110 111 Thread.sleep(5.seconds); 112 foreach (i; 0 .. local_options.wave.number_of_nodes) { 113 114 const filename = buildPath(module_path, format(local_options.wave.prefix_format ~ "opts", i).setExtension(FileExtension 115 .json)); 116 writeln(filename); 117 Options node_opt = load!(Options)(filename); 118 node_opts ~= node_opt; 119 } 120 121 writefln("INPUT SOCKET ADDRESS %s", node_opts[0].inputvalidator.sock_addr); 122 123 Thread.sleep(15.seconds); 124 auto name = "double_spend_testing"; 125 register(name, thisTid); 126 log.registerSubscriptionTask(name); 127 auto feature = automation!(double_spend); 128 feature.SameInputsSpendOnOneContract(node_opts[0], wallets[0], wallets[1]); 129 feature.OneContractWhereSomeBillsAreUsedTwice(node_opts[0], wallets[1], wallets[0]); 130 feature.DifferentContractsDifferentNodes(node_opts[0], node_opts[1], wallets[2], wallets[3]); 131 feature.SameContractDifferentNodes(node_opts[0], node_opts[1], wallets[4], wallets[5]); 132 feature.SameContractInDifferentEpochs(node_opts[0], wallets[6], wallets[7]); 133 feature.SameContractInDifferentEpochsDifferentNode(node_opts[2], node_opts[3], wallets[8], wallets[9]); 134 feature.TwoContractsSameOutput(node_opts[3], node_opts[4], wallets[10], wallets[11], wallets[12]); 135 feature.BillAge(node_opts[3], wallets[13], wallets[14]); 136 feature.run(); 137 138 stopsignal.set; 139 Thread.sleep(6.seconds); 140 return 0; 141 }