Fixed segwit/bech32 signing issues
- Fixed segwit/bech32 signing (transaction inputs) - Added verifyKey: verify the private key for address - sendTx: accepts privateKeyHex and WIF - Fixed: change amount bug (due to float aggregation)
This commit is contained in:
parent
361c1752a7
commit
842006cfc9
58
lib_btc.js
58
lib_btc.js
@ -2549,7 +2549,7 @@
|
|||||||
})();
|
})();
|
||||||
})(typeof global !== "undefined" ? global : window);
|
})(typeof global !== "undefined" ? global : window);
|
||||||
|
|
||||||
(function(EXPORTS) { //btc_api v1.0.2
|
(function(EXPORTS) { //btc_api v1.0.3
|
||||||
const btc_api = EXPORTS;
|
const btc_api = EXPORTS;
|
||||||
|
|
||||||
const URL = "https://chain.so/api/v2/";
|
const URL = "https://chain.so/api/v2/";
|
||||||
@ -2574,7 +2574,7 @@
|
|||||||
},
|
},
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
error: e => reject(e.responseJSON),
|
error: e => reject(e.responseJSON),
|
||||||
success: r => r.status === "success" ? resolve(r) : reject(r)
|
success: r => r.status === "success" ? resolve(r.data) : reject(r)
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -2601,6 +2601,21 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
coinjs.compressed = true;
|
||||||
|
|
||||||
|
const verifyKey = btc_api.verifyKey = function(addr, key) {
|
||||||
|
switch (coinjs.addressDecode(addr).type) {
|
||||||
|
case "standard":
|
||||||
|
return btc_api.address(key) === addr;
|
||||||
|
case "multisig":
|
||||||
|
return btc_api.segwitAddress(key) === addr;
|
||||||
|
case "bech32":
|
||||||
|
return btc_api.bech32Address(key) === addr;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const getUTXO = addr => fetch_api(`get_tx_unspent/BTC/${addr}`);
|
const getUTXO = addr => fetch_api(`get_tx_unspent/BTC/${addr}`);
|
||||||
|
|
||||||
const getBalance = btc_api.getBalance = addr => new Promise((resolve, reject) => {
|
const getBalance = btc_api.getBalance = addr => new Promise((resolve, reject) => {
|
||||||
@ -2609,10 +2624,27 @@
|
|||||||
.catch(error => reject(error))
|
.catch(error => reject(error))
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function getRedeemScript(addr, key) {
|
||||||
|
let decode = coinjs.addressDecode(addr);
|
||||||
|
switch (decode.type) {
|
||||||
|
case "standard":
|
||||||
|
return false;
|
||||||
|
case "multisig":
|
||||||
|
return coinjs.segwitAddress(btc_api.pubkey(key)).redeemscript;
|
||||||
|
case "bech32":
|
||||||
|
return decode.redeemscript;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
btc_api.sendTx = function(senderID, senderPrivKey, receiverID, amount, fee) {
|
btc_api.sendTx = function(senderID, senderPrivKey, receiverID, amount, fee) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (coinjs.wif2address(senderPrivKey).address !== senderID)
|
if (!verifyKey(senderID, senderPrivKey))
|
||||||
return reject("Invalid privateKey");
|
return reject("Invalid privateKey");
|
||||||
|
if (senderPrivKey.length === 64) //convert Hex to WIF if needed
|
||||||
|
senderPrivKey = coinjs.privkey2wif(key);
|
||||||
|
let redeemScript = getRedeemScript(senderID, senderPrivKey);
|
||||||
getBalance(senderID).then(balance => {
|
getBalance(senderID).then(balance => {
|
||||||
if (balance < amount + fee)
|
if (balance < amount + fee)
|
||||||
return reject("Insufficient Balance");
|
return reject("Insufficient Balance");
|
||||||
@ -2621,20 +2653,30 @@
|
|||||||
//var wif = coinjs.privkey2wif(privKeyHex); //privateKey: Hex to WIF
|
//var wif = coinjs.privkey2wif(privKeyHex); //privateKey: Hex to WIF
|
||||||
//var address1 = coinjs.scripthash2address(address0); //receiver: Hash to Hex
|
//var address1 = coinjs.scripthash2address(address0); //receiver: Hash to Hex
|
||||||
getUTXO(senderID).then(result => {
|
getUTXO(senderID).then(result => {
|
||||||
let utxos = result.data.txs;
|
let utxos = result.data.txs.reverse();
|
||||||
console.debug(balance, utxos);
|
console.debug(balance, utxos);
|
||||||
var input_total = 0;
|
var input_total = 0;
|
||||||
for (let i = 0; i < utxos.length && input_total < amount + fee; i++) {
|
for (let i = 0; i < utxos.length && input_total < amount + fee; i++) {
|
||||||
input_total += parseFloat(utxos[i].value);
|
input_total += parseFloat(utxos[i].value);
|
||||||
r.addinput(utxos[i].txid, utxos[i].output_no, utxos[i].script_hex, 0xffffffff /*sequence*/ );
|
let script = utxos[i].script_hex;
|
||||||
|
if (redeemScript) { //redeemScript for segwit/bech32
|
||||||
|
let s = coinjs.script();
|
||||||
|
s.writeBytes(Crypto.util.hexToBytes(redeemScript));
|
||||||
|
s.writeOp(0);
|
||||||
|
s.writeBytes(coinjs.numToBytes((utxos[i].value * 100000000).toFixed(0), 8));
|
||||||
|
script = Crypto.util.bytesToHex(s.buffer);
|
||||||
|
}
|
||||||
|
r.addinput(utxos[i].txid, utxos[i].output_no, script, 0xffffffff /*sequence*/ );
|
||||||
}
|
}
|
||||||
r.addoutput(receiverID, amount);
|
r.addoutput(receiverID, amount);
|
||||||
if (input_total > amount + fee)
|
let change = parseFloat((input_total - (amount + fee)).toFixed(8));
|
||||||
r.addoutput(senderID, input_total - (amount + fee));
|
if (change)
|
||||||
console.debug(input_total, amount, fee, input_total - (amount + fee));
|
r.addoutput(senderID, change);
|
||||||
|
console.debug(input_total, amount, fee, change);
|
||||||
console.debug("Unsigned:", r.serialize());
|
console.debug("Unsigned:", r.serialize());
|
||||||
r.sign(senderPrivKey, 1 /*sighashtype*/ ); //Sign the tx using private key WIF
|
r.sign(senderPrivKey, 1 /*sighashtype*/ ); //Sign the tx using private key WIF
|
||||||
console.debug("Signed:", r.serialize());
|
console.debug("Signed:", r.serialize());
|
||||||
|
debugger;
|
||||||
broadcast(r.serialize())
|
broadcast(r.serialize())
|
||||||
.then(result => resolve(result))
|
.then(result => resolve(result))
|
||||||
.catch(error => reject(error));
|
.catch(error => reject(error));
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user