1 module tagion.tools.signs; 2 import core.time; 3 import std.array : join; 4 import std.datetime; 5 import std.file : exists, readText, fwrite = write; 6 import std.format; 7 import std.getopt; 8 import std.path : extension, setExtension; 9 import std.stdio; 10 import tagion.basic.Types : FileExtension; 11 import tagion.basic.Types; 12 import tagion.crypto.SecureInterfaceNet : SecureNet; 13 import tagion.crypto.SecureNet : StdSecureNet; 14 import tagion.crypto.Types; 15 import tagion.dart.DARTBasic; 16 import tagion.hibon.Document; 17 import tagion.hibon.HiBONJSON : toPretty; 18 import tagion.hibon.HiBONRecord; 19 import tagion.hibon.HiBONFile : fread; 20 import tagion.hibon.HiBONtoText : decode, encodeBase64; 21 import tagion.script.TagionCurrency; 22 import tagion.script.standardnames; 23 import tagion.tools.Basic; 24 import tagion.tools.revision; 25 import tagion.utils.StdTime; 26 27 @recordType("DeliveryOrder") 28 struct DeliveryOrder { 29 30 string vaccineType; 31 string packageID; 32 int numberOfVaccines; 33 string destination; 34 string pickuppoint; 35 string startTime; 36 string endTime; 37 int payment; 38 @label(StdNames.owner) Pubkey owner; // new token owner 39 Pubkey finalReceiver; 40 41 mixin HiBONRecord!(q{ 42 this( 43 string vaccineType, 44 string packageID, 45 int numberOfVaccines, 46 string destination, 47 string pickuppoint, 48 string startTime, 49 string endTime, 50 int payment, 51 Pubkey owner, // new token owner 52 Pubkey finalReceiver, 53 ) { 54 this.vaccineType = vaccineType; 55 this.packageID = packageID; 56 this.numberOfVaccines = numberOfVaccines; 57 this.destination = destination; 58 this.pickuppoint = pickuppoint; 59 this.startTime = startTime; 60 this.endTime = endTime; 61 this.payment = payment; 62 this.owner = owner; 63 this.finalReceiver = finalReceiver; 64 } 65 }); 66 } 67 68 @recordType("DeliveryEvent") 69 struct DeliveryEvent { 70 Signature newSignature; // signature ex. from receiver or from sender when receiver has already signed 71 DARTIndex deliveryEvent; 72 string temp; 73 string timeStamp; 74 @label(StdNames.owner) Pubkey owner; // new token owner 75 76 mixin HiBONRecord!(q{ 77 this( 78 Signature newSignature, 79 DARTIndex deliveryEvent, 80 string temp, 81 string timeStamp, 82 Pubkey owner, 83 ) 84 { 85 this.newSignature = newSignature; 86 this.deliveryEvent = deliveryEvent; 87 this.temp = temp; 88 this.timeStamp = timeStamp; 89 this.owner = owner; 90 } 91 }); 92 } 93 94 mixin Main!_main; 95 int _main(string[] args) { 96 immutable program = args[0]; 97 auto logo = import("logo.txt"); 98 string password; 99 bool standard_output; 100 bool version_switch; 101 bool generate; 102 string inputfilename; 103 string outputfilename = "delivery_order.hibon"; 104 bool generate_pubkey; 105 string receiver_pubkey; 106 string final_receiver_pubkey; 107 108 GetoptResult main_args; 109 try { 110 main_args = getopt(args, 111 std.getopt.config.caseSensitive, 112 std.getopt.config.bundling, 113 "version", "display the version", &version_switch, 114 "f|filename", "file to sign", &inputfilename, 115 "p|password", "set the password for the signing", &password, 116 "c|stdout", "write the output to stdout", &standard_output, 117 "g|generate", "generates dummy delivery order", &generate, 118 "generate_pubkey", "generates public key to stdout", &generate_pubkey, 119 "r|receiver", "give the pubkey for the receiver", &receiver_pubkey, 120 "R|finalreceiver", "the final receiver only used for gen delivery order", &final_receiver_pubkey, 121 "o|outputfilename", "filename to write to", &outputfilename, 122 ); 123 } 124 catch (std.getopt.GetOptException e) { 125 writeln(e.msg); 126 return 1; 127 } 128 129 if (version_switch) { 130 revision_text.writeln; 131 return 0; 132 } 133 134 if (main_args.helpWanted) { 135 writeln(logo); 136 defaultGetoptPrinter( 137 [ 138 "Documentation: https://tagion.org/", 139 "", 140 "Usage:", 141 format("%s [<option>...] <in-file>", program), 142 "", 143 "Where:", 144 "<in-file> Is an input file in .json or .hibon format", 145 "", 146 147 "<option>:", 148 149 ].join("\n"), 150 main_args.options); 151 return 0; 152 } 153 154 SecureNet net = new StdSecureNet; 155 if (password.init) { 156 net.generateKeyPair("very secret"); 157 } 158 else { 159 net.generateKeyPair(password); 160 } 161 162 if (generate_pubkey) { 163 auto buf = cast(Buffer) net.pubkey; 164 writefln("%s", buf.encodeBase64); 165 return 0; 166 } 167 168 // if (args.length != 1) { 169 // stderr.writefln("inputfilename not specified!"); 170 // return 0; 171 // } 172 if (generate) { 173 writefln("generating delivery order"); 174 if (final_receiver_pubkey == final_receiver_pubkey.init) { 175 stderr.writefln("missing finalreceiver"); 176 return 1; 177 } 178 Pubkey final_receiver = decode(final_receiver_pubkey); 179 auto startTime = Clock.currTime(); 180 auto endTime = startTime + 2.days; 181 auto delivery_order = DeliveryOrder( 182 "Measels", 183 "43a3efd0se395", 184 200, 185 "Livingstone Pharmacy", 186 "Lusaka Warehouse", 187 startTime.toISOExtString, 188 endTime.toISOExtString, 189 100, 190 net.pubkey, 191 final_receiver, 192 ); 193 if (standard_output) { 194 stdout.rawWrite(delivery_order.toDoc.serialize); 195 return 0; 196 } 197 writefln("%s", delivery_order.toDoc.toPretty); 198 outputfilename.setExtension(FileExtension.hibon).fwrite(delivery_order.toDoc.serialize); 199 return 0; 200 201 } 202 203 if (receiver_pubkey == receiver_pubkey.init) { 204 stderr.writefln("Please supply pubkey of next receiver"); 205 return 1; 206 } 207 Pubkey receiver = decode(receiver_pubkey); 208 209 if (inputfilename.extension != FileExtension.hibon) { 210 stderr.writefln("Error: inputfilename not correct filetype. Must be %s", FileExtension.hibon); 211 return 1; 212 } 213 214 Document doc = fread(inputfilename); 215 216 if (!(DeliveryOrder.isRecord(doc) || DeliveryEvent.isRecord(doc))) { 217 stderr.writefln("Error: inputfilename not correct type. Must be DeliveryOrder or DeliveryEvent"); 218 return 1; 219 } 220 writefln("going to sign the doc!"); 221 222 Signature doc_signed = net.sign(doc).signature; 223 DARTIndex dart_index = net.dartIndex(doc); 224 225 auto signed_delivery_event = DeliveryEvent( 226 doc_signed, 227 dart_index, 228 "OK", 229 Clock.currTime.toISOExtString, 230 receiver, //new token owner 231 232 233 234 ); 235 236 if (standard_output) { 237 stdout.rawWrite(signed_delivery_event.toDoc.serialize); 238 return 0; 239 } 240 writefln("%s", signed_delivery_event.toDoc.toPretty); 241 outputfilename.setExtension(FileExtension.hibon).fwrite(signed_delivery_event.toDoc.serialize); 242 return 0; 243 }