1 module tagion.betterC.mobile.WalletWrapperApi; 2 3 import tagion.betterC.hibon.Document; 4 import tagion.betterC.mobile.DocumentWrapperApi; 5 6 // import core.stdc.stdlib; 7 import std.stdint; 8 9 // import std.string : toStringz, fromStringz; 10 import std.array; 11 12 // import std.random; 13 import tagion.betterC.communication.HiRPC; 14 import tagion.betterC.funnel.TagionCurrency; 15 import tagion.betterC.hibon.HiBON; 16 import tagion.betterC.mobile.Recycle; 17 import tagion.betterC.utils.Memory; 18 import tagion.betterC.utils.Miscellaneous : xor; 19 import tagion.betterC.utils.StringHelper; 20 import tagion.betterC.wallet.Net : AES, SecureNet; 21 import tagion.betterC.wallet.SecureWallet; 22 import tagion.betterC.wallet.WalletRecords; 23 import hash = tagion.betterC.wallet.hash; 24 25 // import tagion.script.StandardRecords; 26 // import tagion.communication.HiRPC; 27 // import tagion.hibon.HiBON; 28 // import std.stdio; 29 // import tagion.hibon.HiBONJSON; 30 import tagion.basic.Types : Buffer; 31 import tagion.crypto.Types : Pubkey; 32 33 // // import tagion.crypto.aes.AESCrypto; 34 // // import tagion.crypto.SecureNet : SecureNet, BadSecureNet; 35 // // import tagion.betterC.wallet.KeyRecover; 36 37 // // import tagion.crypto.SecureNet : StdHashNet; 38 // import tagion.wallet.WalletRecords : RecoverGenerator, DevicePIN; 39 version (D_BETTERC) { 40 extern (C): 41 } 42 /// Used for describing the d-runtime status 43 enum drtStatus { 44 DEFAULT_STS, 45 STARTED, 46 TERMINATED 47 } 48 /// Variable, which repsresents the d-runtime status 49 __gshared drtStatus __runtimeStatus = drtStatus.DEFAULT_STS; 50 51 string[] parse_string(const char* str, const uint len) { 52 string[] result; 53 return result; 54 } 55 56 /// Functions called from d-lang through dart:ffi 57 /// Staritng d-runtime 58 export static int64_t start_rt() { 59 // recyclerDoc = create!(Recycle!Document); 60 return -1; 61 } 62 63 /// Terminating d-runtime 64 export static int64_t stop_rt() { 65 // recyclerDoc.dispose; 66 return -1; 67 } 68 69 export uint wallet_create(const uint8_t* pincodePtr, const uint32_t pincodeLen, const uint32_t aes_doc_id, 70 const char* questionsPtr, const uint32_t qestionslen, const char* answersPtr, 71 const uint32_t answerslen, uint32_t confidence) { 72 import core.stdc.stdio; 73 74 immutable pincode = cast(immutable)(pincodePtr[0 .. pincodeLen]); 75 76 // assert(recyclerDoc.exists(aes_doc_id)); 77 printf("%s\n", "AES_DOC_ID".ptr); 78 const aes_key_data = recyclerDoc(aes_doc_id); 79 80 immutable decr_pincode = decrypt(pincode, aes_key_data); 81 // Buffer tmp; 82 immutable questions = cast(immutable)(split_by_char(questionsPtr[0 .. qestionslen], ';')); 83 immutable answers = cast(immutable)(split_by_char(answersPtr[0 .. answerslen], ';')); 84 auto wallet = SecureWallet!(SecureNet).createWallet(questions, 85 answers, confidence, cast(immutable(char)[]) decr_pincode); 86 87 // auto recovery_id = recyclerDoc.create(Document(cast(HiBONT)wallet.wallet.toHiBON)); 88 // auto device_pin_id = recyclerDoc.create(Document(cast(HiBONT)wallet.pin.toHiBON)); 89 // auto account_id = recyclerDoc.create(Document(wallet.account.toHiBON)); 90 91 auto result = HiBON(); 92 // result["recovery"] = recovery_id; 93 // result["pin"] = device_pin_id; 94 // result["account"] = account_id; 95 96 // const doc_id = recyclerDoc.create(Document(result)); 97 // return doc_id; 98 return 1; 99 } 100 101 export uint invoice_create(const uint32_t doc_id, const uint32_t dev_pin_doc_id, 102 const uint8_t* pincodePtr, const uint32_t pincodeLen, 103 const uint32_t aes_doc_id, const uint64_t amount, 104 const char* labelPtr, const uint32_t labelLen) { 105 immutable device_pin_doc = recyclerDoc(dev_pin_doc_id); 106 immutable pincode = cast(immutable)(pincodePtr[0 .. pincodeLen]); 107 108 const aes_key_data = recyclerDoc(aes_doc_id); 109 110 immutable decr_pincode = cast(immutable(char)[]) decrypt(pincode, aes_key_data); 111 112 immutable label = cast(immutable)(labelPtr[0 .. labelLen]); 113 const doc = recyclerDoc(doc_id); 114 auto secure_wallet = SecureWallet!(SecureNet)(DevicePIN(device_pin_doc), 115 RecoverGenerator.init, AccountDetails(doc)); 116 117 // scope (success) 118 // { 119 // recyclerDoc.put(Document(secure_wallet.account.toHiBON), doc_id); 120 // } 121 if (secure_wallet.login(decr_pincode)) { 122 auto invoice = SecureWallet!(SecureNet).createInvoice(label, 123 (cast(ulong) amount).TGN); 124 secure_wallet.registerInvoice(invoice); 125 auto hibon = HiBON(); 126 hibon[0] = invoice.toDoc; 127 const invoiceDocId = recyclerDoc.create(Document(hibon)); 128 return invoiceDocId; 129 } 130 return BAD_RESULT; 131 } 132 133 export uint contract_create(const uint32_t doc_id, const uint32_t dev_pin_doc_id, const uint32_t invoice_doc_id, 134 const uint8_t* pincodePtr, const uint32_t pincodeLen, const uint32_t aes_doc_id) { 135 immutable device_pin_doc = recyclerDoc(dev_pin_doc_id); 136 immutable pincode = cast(immutable)(pincodePtr[0 .. pincodeLen]); 137 138 const aes_key_data = recyclerDoc(aes_doc_id); 139 140 immutable decr_pincode = cast(immutable(char)[]) decrypt(pincode, aes_key_data); 141 142 const wallet_doc = recyclerDoc(doc_id); 143 144 auto secure_wallet = SecureWallet!(SecureNet)(DevicePIN(device_pin_doc), 145 RecoverGenerator.init, AccountDetails(wallet_doc)); 146 147 if (secure_wallet.login(decr_pincode)) { 148 const invoice_doc = recyclerDoc(invoice_doc_id); 149 auto invoice = Invoice(invoice_doc["Invoice"].get!Document); 150 151 SignedContract signed_contract; 152 Invoice[1] orders = invoice; 153 if (secure_wallet.payment(orders, signed_contract)) { 154 HiRPC hirpc; 155 const sender = hirpc.action("transaction", signed_contract.toHiBON); 156 immutable data = Document(sender.toHiBON); 157 const contract_doc_id = recyclerDoc.create(data); 158 return contract_doc_id; 159 } 160 } 161 return BAD_RESULT; 162 } 163 164 /// TODO: Check amount. 165 export uint contract_create_with_amount(const uint32_t wallet_doc_id, 166 const uint32_t dev_pin_doc_id, const uint32_t invoice_doc_id, 167 const uint8_t* pincodePtr, const uint32_t pincodeLen, 168 const uint32_t aes_doc_id, const uint64_t amount) { 169 immutable device_pin_doc = recyclerDoc(dev_pin_doc_id); 170 immutable pincode = cast(immutable)(pincodePtr[0 .. pincodeLen]); 171 const aes_key_data = recyclerDoc(aes_doc_id); 172 immutable decr_pincode = cast(immutable(char)[]) decrypt(pincode, aes_key_data); 173 174 const wallet_doc = recyclerDoc(wallet_doc_id); 175 176 auto secure_wallet = SecureWallet!(SecureNet)(DevicePIN(device_pin_doc), 177 RecoverGenerator.init, AccountDetails(wallet_doc)); 178 179 if (secure_wallet.login(decr_pincode)) { 180 const invoice_doc = recyclerDoc(invoice_doc_id); 181 auto invoice = Invoice(invoice_doc["Invoice"].get!Document); 182 183 invoice.amount = TagionCurrency(amount); 184 185 SignedContract signed_contract; 186 187 // if (secure_wallet.payment([invoice], signed_contract)) 188 // { 189 HiRPC hirpc; 190 const sender = hirpc.action("transaction", signed_contract.toHiBON); 191 immutable data = Document(sender.toHiBON); 192 const contract_doc_id = recyclerDoc.create(data); 193 return contract_doc_id; 194 // } 195 } 196 return BAD_RESULT; 197 } 198 199 // // export uint dev_put_invoice_to_bills(const uint32_t wallet_doc_id, 200 // // const uint32_t invoice_doc_id, const uint8_t* pincodePtr, const uint32_t pincodeLen) 201 // // { 202 // // immutable pincode = cast(immutable(char)[])(pincodePtr[0 .. pincodeLen]); 203 // // const wallet_doc = recyclerDoc(wallet_doc_id); 204 // // auto secure_wallet = SecureWallet!(SecureNet)(wallet_doc); 205 206 // // scope (success) 207 // // { 208 // // recyclerDoc.put(Document(secure_wallet.wallet.toHiBON), wallet_doc_id); 209 // // } 210 211 // // if (secure_wallet.login(pincode)) 212 // // { 213 // // import std.stdio; 214 215 // // const invoice_doc = recyclerDoc(invoice_doc_id); 216 // // const invoice = Invoice(invoice_doc[0].get!Document); 217 218 // // secure_wallet.put_invoice_to_bills(invoice); 219 // // return 1; 220 // // } 221 // // return BAD_RESULT; 222 // // } 223 224 export ulong get_balance_available(const uint32_t doc_id) { 225 const wallet_doc = recyclerDoc(doc_id); 226 227 auto secure_wallet = SecureWallet!(SecureNet)(DevicePIN.init, 228 RecoverGenerator.init, AccountDetails(wallet_doc)); 229 230 const balance = secure_wallet.available_balance(); 231 return cast(ulong) balance.tagions; 232 } 233 234 export ulong get_balance_locked(const uint32_t wallet_doc_id) { 235 const wallet_doc = recyclerDoc(wallet_doc_id); 236 237 auto secure_wallet = SecureWallet!(SecureNet)(DevicePIN.init, 238 RecoverGenerator.init, AccountDetails(wallet_doc)); 239 240 const balance = secure_wallet.active_balance(); 241 return cast(ulong) balance.tagions; 242 } 243 244 // // export ulong get_lock_for_amount(const uint32_t wallet_doc_id, const uint64_t amount) 245 // // { 246 // // const wallet_doc = recyclerDoc(wallet_doc_id); 247 // // auto secure_wallet = SecureWallet!(SecureNet)(wallet_doc); 248 249 // // const bills = secure_wallet.get_payment_bills(amount); 250 // // const lock_amount = secure_wallet.calcTotal(bills); 251 // // return lock_amount; 252 // // } 253 254 export bool add_bill(const uint32_t wallet_doc_id, const uint32_t bill_doc_id) { 255 const wallet_doc = recyclerDoc(wallet_doc_id); 256 auto account = AccountDetails(wallet_doc); 257 258 const bill_doc = recyclerDoc(bill_doc_id); 259 auto bill = StandardBill(bill_doc); 260 261 account.add_bill(bill); 262 return 1; 263 } 264 265 export bool remove_bill(const uint32_t wallet_doc_id, const uint8_t* data_ptr, const uint32_t len) { 266 const wallet_doc = recyclerDoc(wallet_doc_id); 267 auto account = AccountDetails(wallet_doc); 268 269 ubyte[] data; 270 data.create(len); 271 for (int i = 0; i < len; i++) { 272 data[i] = data_ptr[i]; 273 } 274 275 Buffer buf = cast(immutable) data; 276 Pubkey pkey; 277 pkey = buf; 278 // auto pkey = Pubkey(cast(immutable)data); 279 const result = account.remove_bill(pkey); 280 return result; 281 } 282 283 // export uint get_request_update_wallet(const uint32_t doc_id) 284 // { 285 286 // const account_doc = recyclerDoc(doc_id); 287 288 // auto secure_wallet = SecureWallet!(SecureNet)(DevicePIN.init, 289 // RecoverGenerator.init, AccountDetails(account_doc)); 290 291 // const request = secure_wallet.get_request_update_wallet(); 292 // const request_doc_id = recyclerDoc.create(request.toDoc); 293 // return request_doc_id; 294 // } 295 296 // export uint set_response_update_wallet(const uint32_t doc_id, 297 // const uint32_t dev_pin_doc_id, const uint32_t response_doc_id, 298 // const uint8_t* pincodePtr, const uint32_t pincodeLen, const uint32_t aes_doc_id) 299 // { 300 301 // const doc = recyclerDoc(doc_id); 302 303 // immutable pincode = cast(immutable)(pincodePtr[0 .. pincodeLen]); 304 305 // const aes_key_data = recyclerDoc(aes_doc_id); 306 307 // immutable decr_pincode = cast(immutable(char)[]) decrypt(pincode, aes_key_data); 308 309 // immutable device_pin_doc = recyclerDoc(dev_pin_doc_id); 310 311 // auto secure_wallet = SecureWallet!(SecureNet)(DevicePIN(device_pin_doc), 312 // RecoverGenerator.init, AccountDetails(doc)); 313 314 // if (secure_wallet.login(decr_pincode)) 315 // { 316 // const response_doc = recyclerDoc(response_doc_id); 317 318 // HiRPC hirpc; 319 320 // auto receiver = hirpc.receive(response_doc); 321 322 // const result = secure_wallet.set_response_update_wallet(receiver); 323 // return cast(uint) result; 324 // } 325 326 // return BAD_RESULT; 327 // } 328 329 export uint generateAESKey(const(uint32_t) aes_key_doc_id) { 330 import core.stdc.stdio; 331 332 ubyte[] seed; 333 seed.create(32); 334 // scramble(seed); 335 assert(!recyclerDoc.exists(1)); 336 auto hibon = HiBON(); 337 hibon["seed"] = cast(immutable) seed; 338 if (aes_key_doc_id == 0) { 339 return recyclerDoc.create(Document(hibon.serialize)); 340 } 341 scope (exit) { 342 assert(recyclerDoc.exists(aes_key_doc_id)); 343 } 344 345 recyclerDoc.put(Document(hibon.serialize), aes_key_doc_id); 346 printf("%i\n", aes_key_doc_id); 347 return aes_key_doc_id; 348 } 349 350 export uint validate(const uint32_t doc_id, const uint32_t dev_pin_doc_id, 351 const uint8_t* pincodePtr, const uint32_t pincodeLen, const uint32_t aes_doc_id,) { 352 353 immutable pincode = cast(immutable)(pincodePtr[0 .. pincodeLen]); 354 355 const aes_key_data = recyclerDoc(aes_doc_id); 356 357 immutable decr_pincode = cast(immutable(char)[]) decrypt(pincode, aes_key_data); 358 359 immutable device_pin_doc = recyclerDoc(dev_pin_doc_id); 360 361 const doc = recyclerDoc(doc_id); 362 363 auto secure_wallet = SecureWallet!(SecureNet)(DevicePIN(device_pin_doc), 364 RecoverGenerator.init, AccountDetails(doc)); 365 366 if (secure_wallet.login(decr_pincode)) { 367 return 1; 368 } 369 return 0; 370 } 371 372 Buffer decrypt(Buffer encrypted_seed, Document aes_key_doc) { 373 // auto aes_key_hibon = new HiBON(aes_key_doc); 374 auto aes_seed = aes_key_doc["seed"].get!Buffer; 375 // alias AES = AESCrypto!256; 376 377 /// Key. 378 auto aes_key = hash.secp256k1_count_hash(aes_seed); 379 /// IV. 380 auto aes_iv = hash.secp256k1_count_hash(aes_seed)[4 .. 4 + AES.BLOCK_SIZE]; 381 382 ubyte[] result; 383 result.create(aes_key.length); 384 /// Generated AES key. 385 AES.decrypt(aes_key, aes_iv, encrypted_seed, result); 386 387 return cast(immutable) result; 388 } 389 // }