Fixed: Sign-bug on multiple input-id

- now signing works for multiple input-ids for the following
  . all legacy
  . all segwit/bech32

- Adding change_addr optional parameter in sendTx (if entered sends the change to given address)
- ignore unconfirmed utxos
This commit is contained in:
sairajzero 2022-06-22 03:15:48 +05:30
parent ee642839fb
commit b28c0d86a2

View File

@ -1,4 +1,4 @@
(function(GLOBAL) { //lib_btc v1.0.0 (function(GLOBAL) { //lib_btc v1.0.1
/* Utility Libraries required /* Utility Libraries required
* All credits for these codes belong to their respective creators, moderators and owners. * All credits for these codes belong to their respective creators, moderators and owners.
* For more info (including license and terms of use), please visit respective source. * For more info (including license and terms of use), please visit respective source.
@ -1799,7 +1799,7 @@
}; };
} else if (this.ins[index].script.chunks[0] == 0 && this.ins[index].script.chunks[this.ins[index].script.chunks.length - 1][this.ins[index].script.chunks[this.ins[index].script.chunks.length - 1].length - 1] == 174) { // OP_CHECKMULTISIG } else if (this.ins[index].script.chunks[0] == 0 && this.ins[index].script.chunks[this.ins[index].script.chunks.length - 1][this.ins[index].script.chunks[this.ins[index].script.chunks.length - 1].length - 1] == 174) { // OP_CHECKMULTISIG
// multisig script, with signature(s) included // multisig script, with signature(s) included
sigcount = 0; var sigcount = 0;
for (i = 1; i < this.ins[index].script.chunks.length - 1; i++) { for (i = 1; i < this.ins[index].script.chunks.length - 1; i++) {
if (this.ins[index].script.chunks[i] != 0) { if (this.ins[index].script.chunks[i] != 0) {
sigcount++; sigcount++;
@ -1822,10 +1822,13 @@
}; };
} else if (this.ins[index].script.chunks.length == 0) { } else if (this.ins[index].script.chunks.length == 0) {
// empty // empty
//bech32 witness check
var signed = ((this.witness[index]) && this.witness[index].length == 2) ? 'true' : 'false';
var sigs = (signed == 'true') ? 1 : 0;
return { return {
'type': 'empty', 'type': 'empty',
'signed': 'false', 'signed': signed,
'signatures': 0, 'signatures': sigs,
'script': '' 'script': ''
}; };
} else { } else {
@ -2077,16 +2080,23 @@
this.ins[index].script = script; this.ins[index].script = script;
if (!coinjs.isArray(this.witness)) { if (!coinjs.isArray(this.witness)) {
this.witness = []; this.witness = new Array(this.ins.length);
this.witness.fill([]);
} }
this.witness.push([signature, wif2['pubkey']]); this.witness[index] = ([signature, wif2['pubkey']]);
// bech32, empty redeemscript
if (bech32['redeemscript'] == Crypto.util.bytesToHex(this.ins[index].script.chunks[0])) {
this.ins[index].script = coinjs.script();
}
/* attempt to reorder witness data as best as we can. /* attempt to reorder witness data as best as we can.
data can't be easily validated at this stage as data can't be easily validated at this stage as
we dont have access to the inputs value and we dont have access to the inputs value and
making a web call will be too slow. */ making a web call will be too slow. */
/*
var witness_order = []; var witness_order = [];
var witness_used = []; var witness_used = [];
for (var i = 0; i < this.ins.length; i++) { for (var i = 0; i < this.ins.length; i++) {
@ -2117,6 +2127,7 @@
} }
this.witness = witness_order; this.witness = witness_order;
*/
} }
} }
return true; return true;
@ -2261,12 +2272,12 @@
for (i = 0; i < ins; ++i) { for (i = 0; i < ins; ++i) {
var count = readVarInt(); var count = readVarInt();
var vector = []; var vector = [];
if (!coinjs.isArray(obj.witness[i])) {
obj.witness[i] = [];
}
for (var y = 0; y < count; y++) { for (var y = 0; y < count; y++) {
var slice = readVarInt(); var slice = readVarInt();
pos += slice; pos += slice;
if (!coinjs.isArray(obj.witness[i])) {
obj.witness[i] = [];
}
obj.witness[i].push(Crypto.util.bytesToHex(buffer.slice(pos - slice, pos))); obj.witness[i].push(Crypto.util.bytesToHex(buffer.slice(pos - slice, pos)));
} }
} }
@ -2549,7 +2560,7 @@
})(); })();
})(typeof global !== "undefined" ? global : window); })(typeof global !== "undefined" ? global : window);
(function(EXPORTS) { //btc_api v1.0.5 (function(EXPORTS) { //btc_api v1.0.5a
const btc_api = EXPORTS; const btc_api = EXPORTS;
const URL = "https://chain.so/api/v2/"; const URL = "https://chain.so/api/v2/";
@ -2659,6 +2670,8 @@
let utxos = result.data.txs; let utxos = result.data.txs;
console.debug("add-utxo", addr, rs, required_amount, utxos); console.debug("add-utxo", addr, rs, required_amount, utxos);
for (let i = 0; i < utxos.length && required_amount > 0; i++) { for (let i = 0; i < utxos.length && required_amount > 0; i++) {
if (!utxos[i].confirmations) //ignore unconfirmed utxo
continue;
required_amount -= parseFloat(utxos[i].value); required_amount -= parseFloat(utxos[i].value);
var script; var script;
if (rs) { //redeemScript for segwit/bech32 if (rs) { //redeemScript for segwit/bech32
@ -2678,7 +2691,7 @@
}) })
} }
btc_api.sendTx = function(senders, privkeys, receivers, amounts, fee) { btc_api.sendTx = function(senders, privkeys, receivers, amounts, fee, change_addr = null) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
//Add values into array (if single values are passed) //Add values into array (if single values are passed)
if (!Array.isArray(senders)) if (!Array.isArray(senders))
@ -2724,6 +2737,8 @@
} }
if (invalids.length) if (invalids.length)
return reject("Invalid amounts:" + invalids); return reject("Invalid amounts:" + invalids);
if (change_addr && !validateAddress(change_addr))
return reject("Invalid change_address:" + change_addr);
//create transaction //create transaction
var tx = coinjs.transaction(); var tx = coinjs.transaction();
@ -2735,7 +2750,7 @@
tx.addoutput(receivers[i], amounts[i]); tx.addoutput(receivers[i], amounts[i]);
let change = parseFloat(Math.abs(result).toFixed(8)); let change = parseFloat(Math.abs(result).toFixed(8));
if (change > 0) if (change > 0)
tx.addoutput(senders[0], change); tx.addoutput(change_addr || senders[0], change);
console.debug("amounts (total, fee, change):", total_amount, fee, change); console.debug("amounts (total, fee, change):", total_amount, fee, change);
console.debug("Unsigned:", tx.serialize()); console.debug("Unsigned:", tx.serialize());
new Set(privkeys).forEach(key => console.debug("Signing key:", key, tx.sign(key, 1 /*sighashtype*/ ))); //Sign the tx using private key WIF new Set(privkeys).forEach(key => console.debug("Signing key:", key, tx.sign(key, 1 /*sighashtype*/ ))); //Sign the tx using private key WIF