· 5 years ago · Jun 17, 2020, 02:26 AM
1let ui = {
2 load: function()
3 {
4 let apiOpts = '';
5 for (const [id, api] of Object.entries(DOGE.services))
6 {
7 apiOpts += '<option value="' + id + '" title="' + id + '">' + api.name + '</option>'
8 }
9 document.getElementById('cmbAPI').innerHTML = apiOpts;
10 },
11 assembleTx: async function()
12 {
13 let apiID = document.getElementById('cmbAPI').value;
14 let fromList = [];
15 let toList = [];
16 fromList = document.getElementById('txtInputs').value.split('\n');
17 let sOutput = document.getElementById('txtOutput').value;
18 let sAmount = document.getElementById('txtAmount').value;
19 toList.push([sOutput, sAmount]);
20 let sChange = document.getElementById('txtChange').value;
21 toList.push([sChange, -1]);
22 let txData = await DOGE.buildTX(apiID, fromList, toList);
23 if (txData.substring(0, 1) === '!')
24 alert('Error Building Transaction:\n' + txData.substring(1));
25 else
26 document.getElementById('txtTX').value = txData;
27 },
28 sendTx: async function()
29 {
30 document.getElementById('lnkView').href = '';
31 document.getElementById('lnkView').innerHTML = '';
32 let apiID = document.getElementById('cmbAPI').value;
33 let txData = document.getElementById('txtTX').value;
34 if (txData === '')
35 {
36 alert('Please build a transaction first');
37 return;
38 }
39 if (confirm('Do you wish to broadcast this transaction?') === false)
40 return;
41 let txRet = await DOGE.sendTX(apiID, txData);
42 if (txRet === false)
43 alert('There was an error sending your transaction.');
44 else
45 alert('Your transaction has been broadcast. The Transaction ID is:\n' + txRet);
46
47 document.getElementById('lnkView').href = DOGE.services[apiID].url.view.replace(/%TXID%/g, txRet);
48 document.getElementById('lnkView').innerHTML = 'View Transaction ' + txRet;
49 }
50};
51
52let DOGE = {
53 services: {
54 'sochain.com': {
55 'name': 'SoChain',
56 'url': {
57 'addr': 'https://sochain.com/api/v2/get_tx_unspent/DOGE/%ADDR%',
58 'tx': 'https://sochain.com/api/v2/get_tx_outputs/DOGE/%TXID%',
59 'send': 'https://sochain.com/api/v2/send_tx/DOGE',
60 'view': 'https://sochain.com/tx/DOGE/%TXID%'
61 },
62 'function': 'getCSTxs',
63 'send': 'sendCSTx'
64 },
65 'blockcypher.com': {
66 'name': 'BlockCypher',
67 'url': {
68 'addr': 'https://api.blockcypher.com/v1/doge/main/addrs/%ADDR%',
69 'tx': 'https://api.blockcypher.com/v1/doge/main/txs/%TXID%',
70 'send': 'https://api.blockcypher.com/v1/doge/main/txs/push?token=%KEY%',
71 'view': 'https://live.blockcypher.com/doge/tx/%TXID%/'
72 },
73 'function': 'getBCTxs',
74 'send': 'sendBCTx'
75 },
76 'dogeblocks.com': {
77 'name': 'Dogesight',
78 'url': {
79 'addr': 'https://dogeblocks.com/api/v2/address/%ADDR%?details=txslight',
80 'tx': 'https://dogeblocks.com/api/v2/tx/%TXID%',
81 'send': 'https://dogeblocks.com/api/v2/sendtx',
82 'view': 'https://dogeblocks.com/tx/%TXID%'
83 },
84 'function': 'getDBTxs',
85 'send': 'sendDBTx'
86 }
87 },
88 buildTX: async function(apiID, fromList, toList)
89 {
90 var fnName = 'getCSTxs';
91 for (const [id, api] of Object.entries(DOGE.services))
92 {
93 if (id === apiID)
94 {
95 fnName = api.function;
96 break;
97 }
98 }
99 let txList = [];
100 for (let i = 0; i < fromList.length; i++)
101 {
102 let sWIF = fromList[i];
103 let sAddr = await DOGE.getPubAddr(sWIF);
104 if (sAddr === -1 || sAddr === -2 || sAddr === -3 || sAddr === -4 || sAddr === -5)
105 {
106 let dReason = 'Failed';
107 switch(sAddr)
108 {
109 case -1:
110 return '!BigInt not supported';
111 break;
112 case -2:
113 dReason = 'WIF not Base58';
114 break;
115 case -3:
116 dReason = 'WIF ID mismatch';
117 break;
118 case -4:
119 dReason = 'Checksum mismatch';
120 break;
121 case -5:
122 dReason = 'Invalid public point';
123 }
124 return '!' + sWIF + ' could not be decoded: ' + dReason;
125 }
126 let bAddr = await DOGE.base58D_Check(sAddr, 0x1E);
127 if (bAddr === -1 || bAddr === -2 || bAddr === -3 || bAddr === -4)
128 {
129 let dReason = 'Failed';
130 switch(bAddr)
131 {
132 case -1:
133 return '!BigInt not supported';
134 break;
135 case -2:
136 dReason = 'WIF not Base58';
137 break;
138 case -3:
139 dReason = 'WIF ID mismatch';
140 break;
141 case -4:
142 dReason = 'Checksum mismatch';
143 break;
144 }
145 return '!' + sAddr + ' could not be decoded: ' + dReason;
146 }
147 let getTxs = DOGE[fnName];
148 let txs = [];
149 txs = await getTxs(sAddr);
150 if (txs.length < 1)
151 continue;
152 for (let a = 0; a < txs.length; a++)
153 {
154 txs[a]['pub'] = bAddr;
155 txs[a]['priv'] = sWIF;
156 }
157 txList = txList.concat(txs);
158 }
159 let totalAmt = 0;
160 function Comparator(a, b)
161 {
162 if (a['amt'] < b['amt']) return -1;
163 if (a['amt'] > b['amt']) return 1;
164 return 0;
165 }
166 txList = txList.sort(Comparator);
167 console.log(txList);
168 for (let i = 0; i < txList.length; i++)
169 {
170 totalAmt += txList[i].amt;
171 }
172 let amt = 0;
173 for (let i = 0; i < toList.length; i++)
174 {
175 let iAmt = toList[i][1];
176 if (iAmt > -1)
177 amt += iAmt;
178 }
179 if (totalAmt < amt)
180 return '!Attempting to send ' + amt + 'DOGE with only ' + totalAmt + ' in all accounts';
181 let activeList = [];
182 let findAmt = amt;
183 totalAmt = 0;
184 for (let i = 0; i < txList.length; i++)
185 {
186 activeList.push(txList[i]);
187 totalAmt += txList[i].amt;
188 findAmt -= txList[i].amt;
189 if (findAmt <= 0)
190 break;
191 }
192 let changeAmt = totalAmt - amt;
193 let outList = [];
194 for (let i = 0; i < toList.length; i++)
195 {
196 let sAddr = toList[i][0];
197 let iAmt = toList[i][1];
198
199 let bAddr = await DOGE.base58D_Check(sAddr, 0x1E);
200 if (bAddr === -1 || bAddr === -2 || bAddr === -3 || bAddr === -4)
201 {
202 bAddr = await DOGE.base58D_Check(sAddr, 0x16);
203 if (bAddr === -1 || bAddr === -2 || bAddr === -3 || bAddr === -4)
204 {
205 let dReason = 'Failed';
206 switch(bAddr)
207 {
208 case -1:
209 return '!BigInt not supported';
210 break;
211 case -2:
212 dReason = 'WIF not Base58';
213 break;
214 case -3:
215 dReason = 'WIF ID mismatch';
216 break;
217 case -4:
218 dReason = 'Checksum mismatch';
219 break;
220 }
221 return '!' + sAddr + ' could not be decoded: ' + dReason;
222 }
223 let toData = [];
224 toData['type'] = 'p2sh';
225 toData['addr'] = bAddr;
226 if (iAmt > -1)
227 toData['amt'] = iAmt;
228 else
229 toData['amt'] = changeAmt;
230 if (toData['amt'] <= 0)
231 continue;
232 outList.push(toData);
233 }
234 else
235 {
236 let toData = [];
237 toData['type'] = 'p2pkh';
238 toData['addr'] = bAddr;
239 if (iAmt > -1)
240 toData['amt'] = iAmt;
241 else
242 toData['amt'] = changeAmt;
243 //if (toData['amt'] <= 0)
244 // continue;
245 outList.push(toData);
246 }
247 }
248 for (let i = 0; i < activeList.length; i++)
249 {
250 let toSign = DOGE.makeTxToSign(activeList, i, outList);
251 let hSign = await DOGE.doubleHash_SHA(toSign);
252 hSign = BigInt('0x' + tools.arrayBufferToHexString(hSign, true));
253 activeList[i].sig = await DOGE.signScript(hSign, activeList[i].priv);
254 }
255 let tx = DOGE.makeTx(activeList, outList);
256 return tx;
257 },
258 sendTX: async function(apiID, txData)
259 {
260 var fnName = 'sendCSTx';
261 for (const [id, api] of Object.entries(DOGE.services))
262 {
263 if (id === apiID)
264 {
265 fnName = api.send;
266 break;
267 }
268 }
269 let sendTx = DOGE[fnName];
270 return sendTx(txData);
271 },
272 getCSTxs: async function(addr)
273 {
274 let mySvc = DOGE.services['sochain.com'];
275 let sURL = mySvc.url.addr.replace(/%ADDR%/g, addr);
276 let jRet = await tools.getMsgTo(sURL).catch((err) => {
277 console.log('Error getting TX List: ', err);
278 });
279 if (jRet === undefined)
280 return false;
281 let txList = [];
282 if (jRet.status !== 'success')
283 return false;
284 if (jRet.data === undefined)
285 return false;
286 if (jRet.data.txs === undefined)
287 return false;
288 if (jRet.data.txs.length > 0)
289 {
290 for (let i = 0; i < jRet.data.txs.length; i++)
291 {
292 if (jRet.data.txs[i].output_no === undefined)
293 continue;
294 if (jRet.data.txs[i].output_no < 0)
295 continue;
296 if (jRet.data.txs[i].txid === undefined)
297 continue;
298 if (jRet.data.txs[i].value === undefined)
299 continue;
300 if (jRet.data.txs[i].confirmations === undefined)
301 continue;
302 if (parseInt(jRet.data.txs[i].confirmations) < 3)
303 continue;
304 let txData = [];
305 let tx = jRet.data.txs[i].txid;
306 txData['tx'] = tx;
307 txData['idx'] = jRet.data.txs[i].output_no;
308 txData['amt'] = parseFloat(jRet.data.txs[i].value);
309 txList.push(txData);
310 }
311 }
312 return txList;
313 },
314 sendCSTx: async function(txData)
315 {
316 let mySvc = DOGE.services['sochain.com'];
317 let sURL = mySvc.url.send;
318 let sParams = 'tx_hex=' + txData;
319 let jRet = await tools.postMsgTo(sURL, sParams, 'application/x-www-form-urlencoded').catch((err) => {
320 console.log('Error sending TX to sochain.com: ', err);
321 });
322 if (jRet === undefined)
323 return false;
324 if (jRet.data === undefined)
325 return false;
326 if (jRet.data.txid !== undefined)
327 return jRet.data.txid;
328 console.log(jRet);
329 return false;
330 },
331 getBCTxs: async function(addr)
332 {
333 let mySvc = DOGE.services['blockcypher.com'];
334 let sURL = mySvc.url.addr.replace(/%ADDR%/g, addr);
335 let jRet = await tools.getMsgTo(sURL).catch((err) => {
336 console.log('Error getting TX List: ', err);
337 });
338 if (jRet === undefined)
339 return false;
340 let txList = [];
341 if (jRet.txrefs === undefined)
342 return false;
343 if (jRet.txrefs.length > 0)
344 {
345 for (let i = 0; i < jRet.txrefs.length; i++)
346 {
347 if (jRet.txrefs[i].spent)
348 continue;
349 if (jRet.txrefs[i].tx_output_n === undefined)
350 continue;
351 if (jRet.txrefs[i].tx_output_n < 0)
352 continue;
353 if (jRet.txrefs[i].tx_hash === undefined)
354 continue;
355 if (jRet.txrefs[i].value === undefined)
356 continue;
357 if (jRet.txrefs[i].confirmations === undefined)
358 continue;
359 if (parseInt(jRet.txrefs[i].confirmations) < 3)
360 continue;
361 let txData = {};
362 let tx = jRet.txrefs[i].tx_hash;
363 txData['tx'] = tx;
364 txData['idx'] = jRet.txrefs[i].tx_output_n;
365 txData['amt'] = (jRet.txrefs[i].value / 100000000);
366 txList.push(txData);
367 }
368 }
369 return txList;
370 },
371 sendBCTx: async function(txData)
372 {
373 let myKey = '293cc5045692451483b376df89f2635a';
374 let mySvc = DOGE.services['blockcypher.com'];
375 let sURL = mySvc.url.send.replace(/%KEY%/g, myKey);
376 let sParams = '{"tx": "' + txData + '"}';
377 let jRet = await tools.postMsgTo(sURL, sParams, 'application/json').catch((err) => {
378 console.log('Error sending TX to blockcypher: ', err);
379 });
380 if (jRet === undefined)
381 return false;
382 if (jRet.tx === undefined)
383 return false;
384 if (jRet.tx.hash !== undefined)
385 return jRet.tx.hash;
386 console.log(jRet);
387 return false;
388 },
389 getDBTxs: async function(addr)
390 {
391 let mySvc = DOGE.services['dogeblocks.com'];
392 let sURL = mySvc.url.addr.replace(/%ADDR%/g, addr);
393 let jRet = await tools.getMsgTo(sURL).catch((err) => {
394 console.log('Error getting TX List: ', err);
395 });
396 if (jRet === undefined)
397 return false;
398 let txList = [];
399 if (jRet.transactions === undefined)
400 return false;
401 if (jRet.transactions.length > 0)
402 {
403 for (let i = 0; i < jRet.transactions.length; i++)
404 {
405 let jRetTx = jRet.transactions[i];
406 if (jRetTx.vout === undefined)
407 continue;
408 if (jRetTx.vout.length < 1)
409 continue;
410 if (jRetTx.confirmations === undefined)
411 continue;
412 if (parseInt(jRetTx.confirmations) < 2)
413 continue;
414 for (let o = 0; o < jRetTx.vout.length; o++)
415 {
416 if (jRetTx.vout[o].isAddress === false)
417 continue;
418 if (jRetTx.vout[o].spent === true)
419 continue;
420 if (jRetTx.vout[o].addresses === undefined)
421 continue;
422 if (jRetTx.vout[o].addresses.length < 1)
423 continue;
424 for (let a = 0; a < jRetTx.vout[o].addresses.length; a++)
425 {
426 if (jRetTx.vout[o].addresses[a] === addr)
427 {
428 let txData = {};
429 txData['tx'] = jRetTx.txid;
430 txData['idx'] = jRetTx.vout[o].n;
431 txData['amt'] = parseFloat(jRetTx.vout[o].value);
432 txList.push(txData);
433 }
434 }
435 }
436 }
437 }
438 return txList;
439 },
440 sendDBTx: async function(txData)
441 {
442 let mySvc = DOGE.services['dogeblocks.com'];
443 let sURL = mySvc.url.send;
444 let sParams = 'hex=' + txData;
445 let jRet = await tools.postMsgTo(sURL, sParams, 'application/x-www-form-urlencoded').catch((err) => {
446 console.log('Error sending TX to dogeblocks: ', err);
447 });
448 if (jRet === undefined)
449 return false;
450 if (jRet.result !== undefined)
451 return jRet.result;
452 console.log(jRet);
453 return false;
454 },
455 getPubPt: async function(wif)
456 {
457 let key = await DOGE.base58D_Check(wif, 0x9E);
458 if (key === -1 || key === -2 || key === -3 || key === -4)
459 return false;
460 if (key.slice(-1)[0] === 1)
461 key = key.slice(0, -1);
462 let k1 = new ecc_curve('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F', '00', '07');
463 let k1G = new ecc_point(k1, '79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798', '483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8', 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141');
464 let n = BigInt('0x' + tools.arrayBufferToHexString(key));
465 return ecc_point.mul(n, k1G);
466 },
467 getPubAddr: async function(wif)
468 {
469 let key = await DOGE.base58D_Check(wif, 0x9E);
470 if (key === -1 || key === -2 || key === -3 || key === -4)
471 return key;
472 let compress = false;
473 if (key.slice(-1)[0] === 1)
474 {
475 key = key.slice(0, -1);
476 compress = true;
477 }
478 let k1 = new ecc_curve('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F', '00', '07');
479 let k1G = new ecc_point(k1, '79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798', '483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8', 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141');
480 let n = BigInt('0x' + tools.arrayBufferToHexString(key));
481 let ptPub = ecc_point.mul(n, k1G);
482 if (ptPub === false)
483 return -5;
484 let toHash = '';
485 if (compress)
486 {
487 if (ptPub.Y % BigInt(2) === BigInt(0))
488 toHash = '02';
489 else
490 toHash = '03';
491 let sK = DOGE.padHex(ptPub.X, 32);
492 toHash += sK;
493 }
494 else
495 {
496 toHash = '04';
497 let sX = DOGE.padHex(ptPub.X, 32);
498 toHash += sX;
499 let sY = DOGE.padHex(ptPub.Y, 32);
500 toHash += sY;
501 }
502 let bRIPE = await DOGE.doubleHash_RIPE(toHash);
503 return await DOGE.base58E_Check(bRIPE, 0x1E);
504 },
505 makeTxToSign: function(inTxs, inIDX, outList)
506 {
507 let tx = '';
508 tx += DOGE.padHex(1, 4, true);
509 let inCt = inTxs.length.toString(16);
510 tx += DOGE.varInt(inTxs.length);
511 for (let i = 0; i < inTxs.length; i++)
512 {
513 let input = DOGE.swapEndian(inTxs[i].tx);
514 input += DOGE.padHex(inTxs[i].idx, 4, true);
515 let inSPK = '';
516 if (i === inIDX)
517 inSPK = '76a9' + DOGE.varInt(inTxs[i].pub.byteLength) + tools.arrayBufferToHexString(inTxs[i].pub.buffer) + '88ac';
518 let inLen = 0;
519 if (inSPK.length > 0)
520 inLen = inSPK.length / 2;
521 input += DOGE.varInt(inLen) + inSPK;
522 input += 'ffffffff';
523 tx += input;
524 }
525 let outCount = outList.length;
526 tx += DOGE.varInt(outCount);
527 for (let i = 0; i < outList.length; i++)
528 {
529 let output = DOGE.padHex(outList[i].amt * 100000000, 8, true);
530 let outSPK = '';
531 if (outList[i].type === 'p2pkh')
532 outSPK = '76a9' + DOGE.varInt(outList[i].addr.byteLength) + tools.arrayBufferToHexString(outList[i].addr.buffer) + '88ac';
533 else
534 outSPK = 'a9' + DOGE.varInt(outList[i].addr.byteLength) + tools.arrayBufferToHexString(outList[i].addr.buffer) + '87';
535 output += DOGE.varInt(outSPK.length / 2) + outSPK
536 tx += output;
537 }
538 tx += DOGE.padHex(0, 4, true);
539 tx += DOGE.padHex(1, 4, true);
540 return tx;
541 },
542 makeTx: function(inTxs, outList)
543 {
544 let tx = '';
545 tx += DOGE.padHex(1, 4, true);
546 let inCt = inTxs.length.toString(16);
547 tx += DOGE.varInt(inTxs.length);
548 for (let i = 0; i < inTxs.length; i++)
549 {
550 let input = DOGE.swapEndian(inTxs[i].tx);
551 input += DOGE.padHex(inTxs[i].idx, 4, true);
552 input += DOGE.varInt(inTxs[i].sig.length / 2) + inTxs[i].sig;
553 input += 'ffffffff';
554 tx += input;
555 }
556 let outCount = outList.length;
557 tx += DOGE.varInt(outCount);
558 for (let i = 0; i < outList.length; i++)
559 {
560 let output = DOGE.padHex(outList[i].amt * 100000000, 8, true);
561 let outSPK = '';
562 if (outList[i].type === 'p2pkh')
563 outSPK = '76a9' + DOGE.varInt(outList[i].addr.byteLength) + tools.arrayBufferToHexString(outList[i].addr.buffer) + '88ac';
564 else
565 outSPK = 'a9' + DOGE.varInt(outList[i].addr.byteLength) + tools.arrayBufferToHexString(outList[i].addr.buffer) + '87';
566 output += DOGE.varInt(outSPK.length / 2) + outSPK
567 tx += output;
568 }
569 tx += DOGE.padHex(0, 4, true);
570 return tx;
571 },
572 signScript: async function(data, priv)
573 {
574 let pub = await DOGE.getPubPt(priv);
575 if (pub === false)
576 return false;
577 let sig = '30';
578 let bPriv = await DOGE.base58D_Check(priv, 0x9E);
579 if (bPriv === -1 || bPriv === -2 || bPriv === -3 || bPriv === -4)
580 return false;
581 let sPriv = tools.arrayBufferToHexString(bPriv, true);
582 let compressed = false;
583 if (sPriv.substring(sPriv.length - 2) === '01')
584 {
585 sPriv = sPriv.substring(0, sPriv.length - 2);
586 compressed = true;
587 }
588 let sRet = ecc_math.sign(data, BigInt('0x' + sPriv));
589 let r = DOGE.padHex(sRet.r, 32);
590 if (r.substring(0, 2) === '00')
591 {
592 while (r.substring(0, 2) === '00')
593 r = r.substring(2);
594 }
595 if (parseInt(r.substring(0, 2), 16) >= 0x80)
596 r = '00' + r;
597 let s = DOGE.padHex(sRet.s, 32);
598 if (s.substring(0, 2) === '00')
599 {
600 while (s.substring(0, 2) === '00')
601 s = s.substring(2);
602 }
603 if (parseInt(s.substring(0, 2), 16) >= 0x80)
604 s = '00' + s;
605 let sigR = DOGE.padHex(r.length / 2, 1) + r;
606 let sigS = DOGE.padHex(s.length / 2, 1) + s;
607 let sBlock = '02' + sigR + '02' + sigS;
608 sig += DOGE.padHex(sBlock.length / 2, 1) + sBlock;
609 let sSig = DOGE.varInt((sig.length / 2) + 1) + sig + '01';
610 let sPub = '';
611 if (compressed)
612 {
613 if (pub.Y % BigInt(2) === BigInt(0))
614 sPub = '02';
615 else
616 sPub = '03';
617 let sK = DOGE.padHex(pub.X, 32);
618 sPub += sK;
619 }
620 else
621 {
622 sPub = '04' + DOGE.padHex(pub.X, 32) + DOGE.padHex(pub.Y, 32);
623 }
624 sSig += DOGE.varInt(sPub.length / 2) + sPub;
625 return sSig;
626 },
627 generateK: function()
628 {
629 let k = new Uint8Array(32);
630 let valid = true;
631 let minKey = BigInt(1);
632 let maxKey = BigInt('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140');
633 do
634 {
635 valid = true;
636 window.crypto.getRandomValues(k);
637 let bigKey = BigInt('0x' + tools.arrayBufferToHexString(k));
638 if (bigKey > maxKey)
639 valid = false;
640 if (bigKey < minKey)
641 valid = false;
642 } while(valid === false);
643 return k;
644 },
645 swapEndian: function(str)
646 {
647 if (typeof str !== 'string' && !(str instanceof String))
648 str = tools.arrayBufferToHexString(str);
649 var a = str.match(/../g);
650 a.reverse();
651 return a.join('');
652 },
653 padHex: function(val, bytes, little = false)
654 {
655 let sVal = val.toString(16);
656 if (sVal.length % 2 === 1)
657 sVal = '0' + sVal;
658 while (sVal.length < bytes * 2)
659 sVal = '00' + sVal;
660 if (little)
661 sVal = DOGE.swapEndian(sVal);
662 return sVal;
663 },
664 varInt: function(i)
665 {
666 if (i < 0xfd)
667 return DOGE.padHex(i, 1);
668 if (i <= 0xFFFF)
669 return 'FD' + DOGE.padHex(i, 2, true);
670 if (i <= 0xFFFFFFFF)
671 return 'FE' + DOGE.padHex(i, 4, true);
672 return 'FF' + DOGE.padHex(i, 8, true);
673 },
674 base58Encode: function(bin)
675 {
676 if (typeof bin === 'string' || bin instanceof String)
677 bin = tools.hexStringToArrayBuffer(bin);
678 let dictionary = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
679 let n = BigInt('0x' + tools.arrayBufferToHexString(bin));
680 let r = '';
681 let b58 = BigInt(58);
682 while (n >= b58)
683 {
684 let div = n / b58;
685 let mod = n % b58;
686 mod = parseInt(mod);
687 r = dictionary.substring(mod, mod + 1) + r;
688 n = div;
689 }
690 if (n !== BigInt(0))
691 {
692 n = parseInt(n);
693 r = dictionary.substring(n, n + 1) + r;
694 }
695 for (let i = 0; i < bin.length; i++)
696 {
697 if (bin[i] !== 0)
698 break;
699 r = dictionary.substring(0, 1) + r;
700 }
701 return r;
702 },
703 base58E_Check: async function(bin, id, suffix = -1)
704 {
705 if (typeof bin === 'string' || bin instanceof String)
706 bin = tools.hexStringToArrayBuffer(bin);
707 let sBIN = tools.arrayBufferToHexString(bin);
708 sBIN = DOGE.padHex(id, 1) + sBIN;
709 if (suffix > -1)
710 sBIN += DOGE.padHex(suffix, 1);
711 let bSum = await window.crypto.subtle.digest('SHA-256', tools.hexStringToArrayBuffer(sBIN));
712 bSum = await window.crypto.subtle.digest('SHA-256', bSum);
713 sBIN += tools.arrayBufferToHexString(bSum).substring(0, 8);
714 return DOGE.base58Encode(sBIN);
715 },
716 base58Decode: function(str)
717 {
718 let dictionary = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
719 let decoded = BigInt(0);
720 while(str)
721 {
722 let alphabetPosition = dictionary.indexOf(str[0]);
723 if (alphabetPosition < 0)
724 return false;
725 let powerOf = BigInt(str.length - 1);
726 let newVal = BigInt(alphabetPosition) * (BigInt(58) ** powerOf);
727 decoded = decoded + newVal;
728 str = str.substring(1);
729 }
730 let hexStr = decoded.toString(16);
731 if (hexStr === '')
732 return false;
733 for (let i = 0; i < str.length; i++)
734 {
735 if (str.substring(i, i + 1) !== dictionary.substring(0, 1))
736 break;
737 hexStr = '00' + hexStr;
738 }
739 if (hexStr.length % 2 === 1)
740 hexStr = '0' + hexStr;
741 return tools.hexStringToArrayBuffer(hexStr);
742 },
743 base58D_Check: async function(str, expectedID)
744 {
745 // -1 = BigInt not supported
746 // -2 = not base58
747 // -3 = ID is not expectedID
748 // -4 = Checksum mismatch
749
750 if (!('BigInt' in window))
751 return -1;
752 let aData = DOGE.base58Decode(str);
753 if (aData === false)
754 return -2;
755 let bAddr = new Uint8Array(aData);
756 let bID = bAddr.slice(0, 1);
757 let bSum = bAddr.slice(-4);
758 if (bID[0] !== expectedID)
759 return -3;
760 let kSum = await DOGE.doubleHash_SHA(bAddr.slice(0, -4));
761 kSum = kSum.slice(0, 4);
762 if (tools.arrayBufferToHexString(kSum) !== tools.arrayBufferToHexString(bSum))
763 return -4;
764 return bAddr.slice(1, -4);
765 },
766 doubleHash_SHA: async function(bin)
767 {
768 if (typeof bin === 'string' || bin instanceof String)
769 bin = tools.hexStringToArrayBuffer(bin);
770 let bSum = await window.crypto.subtle.digest('SHA-256', bin);
771 return await window.crypto.subtle.digest('SHA-256', bSum);
772 },
773 doubleHash_RIPE: async function(bin)
774 {
775 if (typeof bin === 'string' || bin instanceof String)
776 bin = tools.hexStringToArrayBuffer(bin);
777 let kSHA = await window.crypto.subtle.digest('SHA-256', bin);
778 let byteLen = kSHA.byteLength;
779 let arI = new Int32Array(kSHA);
780 let arD = [];
781 for (let i = 0; i < arI.length; i++)
782 {
783 arD.push(arI[i]);
784 }
785 let ripe = tools.ripemd160(arD, byteLen);
786 return new Uint8Array(new Int32Array(ripe).buffer);
787 }
788};
789
790let ecc_curve = class {
791 constructor(prime, a, b)
792 {
793 this.a = BigInt('0x' + a);
794 this.b = BigInt('0x' + b);
795 this.prime = BigInt('0x' + prime);
796 }
797 get A()
798 {
799 return this.a;
800 }
801 get B()
802 {
803 return this.b;
804 }
805 get Prime()
806 {
807 return this.prime;
808 }
809 contains(x, y)
810 {
811 if (this.a === BigInt(0))
812 {
813 if ((((y ** BigInt(2)) - ((x ** BigInt(3)) + this.b)) % this.prime) === BigInt(0))
814 return true;
815 }
816 else
817 {
818 if ((((y ** BigInt(2)) - (((x ** BigInt(3)) + (this.a * x)) + this.b)) % this.prime) === BigInt(0))
819 return true;
820 }
821 return false;
822 }
823 static cmp(curve1, curve2)
824 {
825 if (curve1.A === curve2.A && curve1.B === curve2.B && curve1.Prime === curve2.Prime)
826 return 0;
827 return 1;
828 }
829};
830
831let ecc_point = class {
832 constructor(curve, x, y, order = null)
833 {
834 this.curve = curve;
835 if (typeof x === 'string' || x instanceof String)
836 this.x = BigInt('0x' + x);
837 else
838 this.x = x;
839 if (typeof y === 'string' || y instanceof String)
840 this.y = BigInt('0x' + y);
841 else
842 this.y = y;
843 if (order === null)
844 this.order = null;
845 else
846 this.order = BigInt('0x' + order);
847 /*
848 if (this.curve !== null)
849 {
850 if (!this.curve.contains(this.x, this.y))
851 {
852 this.err = 'Curve does not contain point';
853 return;
854 }
855 if (this.order !== null)
856 {
857 if (this.cmp(this.mul(this.order, this), 'infinity') !== 0)
858 {
859 this.err = 'Order * Self must not equal Infinity';
860 return;
861 }
862 }
863 }
864 */
865 }
866 static cmp(p1, p2)
867 {
868 if (p1.X === p2.X && p1.y === p2.Y && ecc_curve.cmp(p1.Curve, p2.Curve) === 0)
869 return 0;
870 return 1;
871 }
872 static add(p1, p2)
873 {
874 if (ecc_curve.cmp(p1.Curve, p2.Curve) !== 0)
875 return false;
876 let xComp = 0;
877 if (p1.X > p2.X)
878 xComp = 1;
879 else if (p1.X < p2.X)
880 xComp = -1;
881 if (BigInt(xComp) % p1.Curve.Prime === BigInt(0))
882 {
883 if (p1.Y + p2.Y === p1.Curve.Prime)
884 return 'Infinity';
885 return ecc_point.double(p1);
886 }
887 let p = p1.Curve.Prime;
888 let invP = ecc_math.inverse_mod((p2.X - p1.X), p);
889 if (invP === false)
890 return false;
891 let l = ((p2.Y - p1.Y) * invP) % p;
892 let x3 = (((l ** BigInt(2)) - p1.X) - p2.X) % p;
893 let y3 = ((l * (p1.X - x3)) - p1.Y) % p;
894 if (y3 < 0)
895 y3 = p + y3;
896 let p3 = new ecc_point(p1.Curve, x3, y3);
897 return p3;
898 }
899 static mul(x2, p1)
900 {
901 let e = x2;
902 if (p1.Order !== null)
903 e = e % p1.Order;
904 if (e === BigInt(0))
905 return 'Infinity';
906 if (e < 0)
907 return 0;
908 let e3 = BigInt(3) * e;
909 let neg_self = new ecc_point(p1.Curve, p1.X, (BigInt(0) - p1.Y), p1.Order);
910 let i = ecc_point.leftmost_bit(e3) / BigInt(2);
911 let result = p1;
912 while (i > 1)
913 {
914 result = ecc_point.double(result);
915 let e3bit = ((e3 & BigInt(i)) === BigInt(0));
916 let ebit = ((e & BigInt(i)) === BigInt(0));
917 if (!e3bit && ebit)
918 result = ecc_point.add(result, p1);
919 else if (e3bit && !ebit)
920 result = ecc_point.add(result, neg_self);
921 i = i / BigInt(2);
922 }
923 return result;
924 }
925 static leftmost_bit(x)
926 {
927 if (x < 0)
928 return 0;
929 let result = BigInt(1);
930 while (result <= x)
931 {
932 result = BigInt(2) * result;
933 }
934 return result / BigInt(2);
935 }
936 static double(p1)
937 {
938 let big2 = BigInt(2);
939 let big3 = BigInt(3);
940 let p = p1.Curve.Prime;
941 let a = p1.Curve.A;
942 let inverse = ecc_math.inverse_mod(big2 * p1.Y, p);
943 let three_x2 = big3 * (p1.X ** big2);
944 let l = ((three_x2 + a) * inverse) % p;
945 let x3 = ((l ** big2) - (big2 * p1.X)) % p;
946 let y3 = ((l * (p1.X - x3)) - p1.Y) % p;
947 if (y3 < 0)
948 y3 = p + y3;
949 return new ecc_point(p1.Curve, x3, y3);
950 }
951 get X()
952 {
953 return this.x;
954 }
955 get Y()
956 {
957 return this.y;
958 }
959 get Curve()
960 {
961 return this.curve;
962 }
963 get Order()
964 {
965 return this.order;
966 }
967};
968
969let ecc_math = {
970 sign: function(bin, priv)
971 {
972 let random_k = DOGE.generateK();
973 let k1 = new ecc_curve('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F', '00', '07');
974 let k1G = new ecc_point(k1, '79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798', '483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8', 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141');
975 let n = k1G.Order;
976 let k = BigInt('0x' + tools.arrayBufferToHexString(random_k));
977 k = k % n;
978 let p1 = ecc_point.mul(k, k1G);
979 let r = p1.X;
980 if (r === BigInt(0))
981 return ecc_math.sign(bin, priv);
982
983 let s = (ecc_math.inverse_mod(k, n) * (bin + (priv * r) % n)) % n;
984 if (s === BigInt(0))
985 return ecc_math.sign(bin, priv);
986 if (s >= n / BigInt(2))
987 s = n - s;
988 let ret = {};
989 ret['r'] = r;
990 ret['s'] = s;
991 return ret;
992 },
993 inverse_mod: function(a, m)
994 {
995 while(a < 0)
996 {
997 a = m + a;
998 }
999 while (m < a)
1000 {
1001 a = a % m;
1002 }
1003 let c = a;
1004 let d = m;
1005 let uc = BigInt(1);
1006 let vc = BigInt(0);
1007 let ud = BigInt(0);
1008 let vd = BigInt(0);
1009 while (c !== BigInt(0))
1010 {
1011 let temp1 = c;
1012 let q = d / c;
1013 c = d % c;
1014 d = temp1;
1015 let temp2 = uc;
1016 let temp3 = vc;
1017 uc = ud - (q * uc);
1018 vc = vd - (q - vc);
1019 ud = temp2;
1020 vd = temp3;
1021 }
1022 if (d === BigInt(1))
1023 {
1024 if (ud === BigInt(0))
1025 return ud;
1026 return ud + m;
1027 }
1028 return false;
1029 }
1030};
1031
1032let tools = {
1033 sendPostTo: async function(addr, params, enc)
1034 {
1035 return new Promise((resolve, reject) => {
1036 let xmlhttp;
1037 if (window.XMLHttpRequest)
1038 xmlhttp = new XMLHttpRequest();
1039 else
1040 xmlhttp = new window.ActiveXObject('Microsoft.XMLHTTP');
1041 xmlhttp.onreadystatechange = function()
1042 {
1043 if (xmlhttp.readyState !== 4)
1044 return;
1045 if (xmlhttp.status < 200 || xmlhttp.status > 299)
1046 {
1047 if (xmlhttp.status === 0)
1048 reject('Empty Response');
1049 else
1050 reject('HTTP Error ' + xmlhttp.status);
1051 return;
1052 }
1053 if (xmlhttp.responseText === '')
1054 {
1055 reject('Empty Response');
1056 return;
1057 }
1058 try
1059 {
1060 let respData = JSON.parse(xmlhttp.responseText);
1061 if (respData.hasOwnProperty('error'))
1062 {
1063 reject(respData.err);
1064 return;
1065 }
1066 resolve(respData);
1067 }
1068 catch (ex)
1069 {
1070 reject(xmlhttp.responseText);
1071 return;
1072 }
1073 };
1074 xmlhttp.onerror= function(err)
1075 {
1076 reject('Connection Error');
1077 };
1078 xmlhttp.timeout = 5000;
1079 xmlhttp.open('POST', addr, true);
1080 xmlhttp.setRequestHeader('Content-type', enc);
1081 xmlhttp.send(params);
1082 });
1083 },
1084 postMsgTo: async function(addr, params, enc)
1085 {
1086 return new Promise((resolve, reject) => {
1087 let attempts = 3;
1088 const XHR = () => {
1089 if (attempts > 0)
1090 {
1091 attempts--;
1092 tools.sendPostTo(addr, params, enc).then
1093 (
1094 (res) => { resolve(res); }
1095 ).catch
1096 (
1097 (e) => {
1098 if (e !== 'Empty Response')
1099 {
1100 reject(e);
1101 return;
1102 }
1103 setTimeout(() => { XHR(); }, 2500);
1104 }
1105 );
1106 }
1107 };
1108 XHR();
1109 });
1110 },
1111 sendGetTo: async function(addr)
1112 {
1113 return new Promise((resolve, reject) => {
1114 let xmlhttp;
1115 if (window.XMLHttpRequest)
1116 xmlhttp = new XMLHttpRequest();
1117 else
1118 xmlhttp = new window.ActiveXObject('Microsoft.XMLHTTP');
1119 xmlhttp.onreadystatechange = function()
1120 {
1121 if (xmlhttp.readyState !== 4)
1122 return;
1123 if (xmlhttp.status < 200 || xmlhttp.status > 299)
1124 {
1125 if (xmlhttp.status === 0)
1126 reject('Empty Response');
1127 else
1128 reject('HTTP Error ' + xmlhttp.status);
1129 return;
1130 }
1131 if (xmlhttp.responseText === '')
1132 {
1133 reject('Empty Response');
1134 return;
1135 }
1136 try
1137 {
1138 let respData = JSON.parse(xmlhttp.responseText);
1139 if (respData.hasOwnProperty('error'))
1140 {
1141 reject(respData.err);
1142 return;
1143 }
1144 resolve(respData);
1145 }
1146 catch (ex)
1147 {
1148 reject(xmlhttp.responseText);
1149 return;
1150 }
1151 };
1152 xmlhttp.onerror= function(err)
1153 {
1154 reject('Connection Error');
1155 };
1156 xmlhttp.timeout = 5000;
1157 xmlhttp.open('GET', addr, true);
1158 xmlhttp.send();
1159 });
1160 },
1161 getMsgTo: async function(addr)
1162 {
1163 return new Promise((resolve, reject) => {
1164 let attempts = 3;
1165 const XHR = () => {
1166 if (attempts > 0)
1167 {
1168 attempts--;
1169 tools.sendGetTo(addr).then
1170 (
1171 (res) => { resolve(res); }
1172 ).catch
1173 (
1174 (e) => {
1175 if (e !== 'Empty Response')
1176 {
1177 reject(e);
1178 return;
1179 }
1180 setTimeout(() => { XHR(); }, 2500);
1181 }
1182 );
1183 }
1184 };
1185 XHR();
1186 });
1187 },
1188 padHex: function(d, unsigned)
1189 {
1190 unsigned = (typeof unsigned !== 'undefined') ? unsigned : false;
1191 let h = null;
1192 if (typeof d === 'number')
1193 {
1194 if (unsigned)
1195 {
1196 h = d.toString(16);
1197 return h.length % 2 ? '000' + h : '00' + h;
1198 }
1199 else
1200 {
1201 h = (d).toString(16);
1202 return h.length % 2 ? '0' + h : h;
1203 }
1204 }
1205 else if (typeof d === 'string')
1206 {
1207 h = (d.length / 2).toString(16);
1208 return h.length % 2 ? '0' + h : h;
1209 }
1210 },
1211 arrayBufferToHexString: function(arrayBuffer, signedHex = false)
1212 {
1213 let byteArray = new Uint8Array(arrayBuffer);
1214 let hexString = '';
1215 let nextHexByte;
1216 if (signedHex && byteArray[0] >= 0x80)
1217 hexString += '00';
1218 for (let i = 0; i < byteArray.byteLength; i++)
1219 {
1220 nextHexByte = byteArray[i].toString(16);
1221 if (nextHexByte.length < 2)
1222 nextHexByte = '0' + nextHexByte;
1223 hexString += nextHexByte;
1224 }
1225 return hexString;
1226 },
1227 hexStringToArrayBuffer: function(hexString)
1228 {
1229 if ((hexString.length % 2) !== 0)
1230 throw new RangeError('Expected string to be an even number of characters');
1231 let byteArray = new Uint8Array(hexString.length / 2);
1232 for (let i = 0; i < hexString.length; i += 2)
1233 {
1234 byteArray[i / 2] = parseInt(hexString.substring(i, i + 2), 16);
1235 }
1236 return byteArray.buffer;
1237 },
1238 ripemd160: function(bin, byteCt)
1239 {
1240 function binl_rmd160(x, len)
1241 {
1242 x[len >> 5] |= 0x80 << (len % 32);
1243 x[(((len + 64) >>> 9) << 4) + 14] = len;
1244 let h0 = 0x67452301;
1245 let h1 = 0xefcdab89;
1246 let h2 = 0x98badcfe;
1247 let h3 = 0x10325476;
1248 let h4 = 0xc3d2e1f0;
1249 for (let i = 0; i < x.length; i += 16)
1250 {
1251 let T;
1252 let A1 = h0, B1 = h1, C1 = h2, D1 = h3, E1 = h4;
1253 let A2 = h0, B2 = h1, C2 = h2, D2 = h3, E2 = h4;
1254 for (let j = 0; j <= 79; ++j)
1255 {
1256 T = safe_add(A1, rmd160_f(j, B1, C1, D1));
1257 T = safe_add(T, x[i + rmd160_r1[j]]);
1258 T = safe_add(T, rmd160_K1(j));
1259 T = safe_add(bit_rol(T, rmd160_s1[j]), E1);
1260 A1 = E1; E1 = D1; D1 = bit_rol(C1, 10); C1 = B1; B1 = T;
1261 T = safe_add(A2, rmd160_f(79-j, B2, C2, D2));
1262 T = safe_add(T, x[i + rmd160_r2[j]]);
1263 T = safe_add(T, rmd160_K2(j));
1264 T = safe_add(bit_rol(T, rmd160_s2[j]), E2);
1265 A2 = E2; E2 = D2; D2 = bit_rol(C2, 10); C2 = B2; B2 = T;
1266 }
1267 T = safe_add(h1, safe_add(C1, D2));
1268 h1 = safe_add(h2, safe_add(D1, E2));
1269 h2 = safe_add(h3, safe_add(E1, A2));
1270 h3 = safe_add(h4, safe_add(A1, B2));
1271 h4 = safe_add(h0, safe_add(B1, C2));
1272 h0 = T;
1273 }
1274 return [h0, h1, h2, h3, h4];
1275 }
1276 function rmd160_f(j, x, y, z)
1277 {
1278 return ( 0 <= j && j <= 15) ? (x ^ y ^ z) :
1279 (16 <= j && j <= 31) ? (x & y) | (~x & z) :
1280 (32 <= j && j <= 47) ? (x | ~y) ^ z :
1281 (48 <= j && j <= 63) ? (x & z) | (y & ~z) :
1282 (64 <= j && j <= 79) ? x ^ (y | ~z) :
1283 "rmd160_f: j out of range";
1284 }
1285 function rmd160_K1(j)
1286 {
1287 return ( 0 <= j && j <= 15) ? 0x00000000 :
1288 (16 <= j && j <= 31) ? 0x5a827999 :
1289 (32 <= j && j <= 47) ? 0x6ed9eba1 :
1290 (48 <= j && j <= 63) ? 0x8f1bbcdc :
1291 (64 <= j && j <= 79) ? 0xa953fd4e :
1292 "rmd160_K1: j out of range";
1293 }
1294 function rmd160_K2(j)
1295 {
1296 return ( 0 <= j && j <= 15) ? 0x50a28be6 :
1297 (16 <= j && j <= 31) ? 0x5c4dd124 :
1298 (32 <= j && j <= 47) ? 0x6d703ef3 :
1299 (48 <= j && j <= 63) ? 0x7a6d76e9 :
1300 (64 <= j && j <= 79) ? 0x00000000 :
1301 "rmd160_K2: j out of range";
1302 }
1303 let rmd160_r1 = [
1304 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
1305 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
1306 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
1307 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
1308 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13
1309 ];
1310 let rmd160_r2 = [
1311 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
1312 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
1313 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
1314 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
1315 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11
1316 ];
1317 let rmd160_s1 = [
1318 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
1319 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
1320 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
1321 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
1322 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6
1323 ];
1324 let rmd160_s2 = [
1325 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
1326 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
1327 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
1328 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
1329 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11
1330 ];
1331 function safe_add(x, y)
1332 {
1333 let lsw = (x & 0xFFFF) + (y & 0xFFFF);
1334 let msw = (x >> 16) + (y >> 16) + (lsw >> 16);
1335 return (msw << 16) | (lsw & 0xFFFF);
1336 }
1337 function bit_rol(num, cnt)
1338 {
1339 return (num << cnt) | (num >>> (32 - cnt));
1340 }
1341 return binl_rmd160(bin, byteCt * 8);
1342 },
1343 sleep: async function(ms)
1344 {
1345 return new Promise(resolve => setTimeout(resolve, ms));
1346 }
1347};