first stage of adding bech32 support added to coinb.in
This commit is contained in:
parent
abd2191c50
commit
90a309d4b4
5 changed files with 245 additions and 39 deletions
|
@ -1,7 +1,7 @@
|
||||||
coinbin
|
coinbin
|
||||||
=======
|
=======
|
||||||
|
|
||||||
A Open Source Browser Based Bitcoin Wallet. Version 1.3 beta by OutCast3k
|
A Open Source Browser Based Bitcoin Wallet. Version 1.4 beta by OutCast3k
|
||||||
|
|
||||||
Live version available at http://coinb.in/ or http://4zpinp6gdkjfplhk.onion
|
Live version available at http://coinb.in/ or http://4zpinp6gdkjfplhk.onion
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ Coinb.in supports a number of key features such as:
|
||||||
- Supports altcoins such as litecoin
|
- Supports altcoins such as litecoin
|
||||||
- Replace by fee (RBF) Support
|
- Replace by fee (RBF) Support
|
||||||
- Segwit Support
|
- Segwit Support
|
||||||
|
- Bech32 address support
|
||||||
- Fee calculator - https://coinb.in/#fees
|
- Fee calculator - https://coinb.in/#fees
|
||||||
|
|
||||||
Donate to 3K1oFZMks41C7qDYBsr72SYjapLqDuSYuN to see more development!
|
Donate to 3K1oFZMks41C7qDYBsr72SYjapLqDuSYuN to see more development!
|
||||||
|
|
27
index.html
27
index.html
|
@ -125,7 +125,7 @@
|
||||||
|
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<h3><span class="glyphicon glyphicon-globe"></span> Addresses</h3>
|
<h3><span class="glyphicon glyphicon-globe"></span> Addresses</h3>
|
||||||
<p>We support <a href="#newAddress">regular addresses</a>, <a href="#newMultiSig">multisig</a>, <a href="#newSegWit">segwit</a> and stealth all with access to your own private keys!</p>
|
<p>We support <a href="#newAddress">regular addresses</a>, <a href="#newMultiSig">multisig</a>, <a href="#newSegWit">segwit / bech32</a> and stealth all with access to your own private keys!</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
|
@ -371,6 +371,10 @@
|
||||||
<h3>Address Options</h3>
|
<h3>Address Options</h3>
|
||||||
<p>You can use the advanced options below to generate different kind of keys and addresses.</p>
|
<p>You can use the advanced options below to generate different kind of keys and addresses.</p>
|
||||||
|
|
||||||
|
<div class="checkbox">
|
||||||
|
<label><input type="checkbox" id="newSegWitBech32addr" class="checkbox-inline" checked> Enable <a href="https://en.bitcoin.it/wiki/Bech32" target="_blank">Bech32</a>?</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="checkbox">
|
<div class="checkbox">
|
||||||
<label><input type="checkbox" id="newSegWitBrainwallet" class="checkbox-inline"> Custom Seed or Brain Wallet</label>
|
<label><input type="checkbox" id="newSegWitBrainwallet" class="checkbox-inline"> Custom Seed or Brain Wallet</label>
|
||||||
<input type="text" class="form-control hidden" id="brainwalletSegWit">
|
<input type="text" class="form-control hidden" id="brainwalletSegWit">
|
||||||
|
@ -1090,13 +1094,26 @@
|
||||||
<hr>
|
<hr>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<p><b>Segwit Address</b>: <input type="text" class="form-control addressSegWit" readonly></p>
|
<p><b>P2SH Segwit Address</b>: <input type="text" class="form-control addressSegWit" readonly></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<p><b>Segwit Redeem Script</b>: <input type="text" class="form-control addressSegWitRedeemScript" readonly></p>
|
<p><b>P2SH Segwit Redeem Script</b>: <input type="text" class="form-control addressSegWitRedeemScript" readonly></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<p><b>Bech32 Address</b>: <input type="text" class="form-control addressBech32" readonly></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
<p><b>Bech32 Redeem Script</b>: <input type="text" class="form-control addressBech32RedeemScript" readonly></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -1286,7 +1303,7 @@
|
||||||
|
|
||||||
<div class="tab-pane tab-content" id="about">
|
<div class="tab-pane tab-content" id="about">
|
||||||
<h2>About <small>open source bitcoin wallet</small></h2>
|
<h2>About <small>open source bitcoin wallet</small></h2>
|
||||||
<p>Version 1.3</p>
|
<p>Version 1.4</p>
|
||||||
<p>Compatible with bitcoin core</p>
|
<p>Compatible with bitcoin core</p>
|
||||||
<p>Github <a href="https://github.com/OutCast3k/coinbin/">https://github.com/OutCast3k/coinbin/</a></p>
|
<p>Github <a href="https://github.com/OutCast3k/coinbin/">https://github.com/OutCast3k/coinbin/</a></p>
|
||||||
<p>TOR <a href="http://4zpinp6gdkjfplhk.onion">4zpinp6gdkjfplhk.onion</a></p>
|
<p>TOR <a href="http://4zpinp6gdkjfplhk.onion">4zpinp6gdkjfplhk.onion</a></p>
|
||||||
|
@ -1413,7 +1430,7 @@
|
||||||
|
|
||||||
<div id="footer">
|
<div id="footer">
|
||||||
<div class="container text-right">
|
<div class="container text-right">
|
||||||
<p class="text-muted">Version 1.3</p>
|
<p class="text-muted">Version 1.4</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
187
js/coin.js
187
js/coin.js
|
@ -14,6 +14,7 @@
|
||||||
coinjs.priv = 0x80;
|
coinjs.priv = 0x80;
|
||||||
coinjs.multisig = 0x05;
|
coinjs.multisig = 0x05;
|
||||||
coinjs.hdkey = {'prv':0x0488ade4, 'pub':0x0488b21e};
|
coinjs.hdkey = {'prv':0x0488ade4, 'pub':0x0488b21e};
|
||||||
|
coinjs.bech32 = {'charset':'qpzry9x8gf2tvdw0s3jn54khce6mua7l', 'version':0, 'hrp':'bc'};
|
||||||
|
|
||||||
coinjs.compressed = false;
|
coinjs.compressed = false;
|
||||||
|
|
||||||
|
@ -184,6 +185,24 @@
|
||||||
return {'address':address, 'type':'segwit', 'redeemscript':Crypto.util.bytesToHex(keyhash)};
|
return {'address':address, 'type':'segwit', 'redeemscript':Crypto.util.bytesToHex(keyhash)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* create a new segwit bech32 encoded address */
|
||||||
|
coinjs.bech32Address = function(pubkey){
|
||||||
|
var program = ripemd160(Crypto.SHA256(Crypto.util.hexToBytes(pubkey), {asBytes: true}), {asBytes: true});
|
||||||
|
var address = coinjs.bech32_encode(coinjs.bech32.hrp, [coinjs.bech32.version].concat(coinjs.bech32_convert(program, 8, 5, true)));
|
||||||
|
return {'address':address, 'type':'bech32', 'redeemscript':Crypto.util.bytesToHex(program)};
|
||||||
|
}
|
||||||
|
|
||||||
|
/* extract the redeemscript from a bech32 address */
|
||||||
|
coinjs.bech32redeemscript = function(address){
|
||||||
|
var r = false;
|
||||||
|
var decode = coinjs.bech32_decode(address);
|
||||||
|
if(decode){
|
||||||
|
decode.data.shift();
|
||||||
|
return Crypto.util.bytesToHex(coinjs.bech32_convert(decode.data, 5, 8, true));
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
/* provide a privkey and return an WIF */
|
/* provide a privkey and return an WIF */
|
||||||
coinjs.privkey2wif = function(h){
|
coinjs.privkey2wif = function(h){
|
||||||
var r = Crypto.util.hexToBytes(h);
|
var r = Crypto.util.hexToBytes(h);
|
||||||
|
@ -286,9 +305,14 @@
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
|
bech32rs = coinjs.bech32redeemscript(addr);
|
||||||
|
if(bech32rs){
|
||||||
|
return {'type':'bech32', 'redeemscript':bech32rs};
|
||||||
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* retreive the balance from a given address */
|
/* retreive the balance from a given address */
|
||||||
coinjs.addressBalance = function(address, callback){
|
coinjs.addressBalance = function(address, callback){
|
||||||
|
@ -316,6 +340,126 @@
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
coinjs.bech32_polymod = function(values) {
|
||||||
|
var chk = 1;
|
||||||
|
var BECH32_GENERATOR = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3];
|
||||||
|
for (var p = 0; p < values.length; ++p) {
|
||||||
|
var top = chk >> 25;
|
||||||
|
chk = (chk & 0x1ffffff) << 5 ^ values[p];
|
||||||
|
for (var i = 0; i < 5; ++i) {
|
||||||
|
if ((top >> i) & 1) {
|
||||||
|
chk ^= BECH32_GENERATOR[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return chk;
|
||||||
|
}
|
||||||
|
|
||||||
|
coinjs.bech32_hrpExpand = function(hrp) {
|
||||||
|
var ret = [];
|
||||||
|
var p;
|
||||||
|
for (p = 0; p < hrp.length; ++p) {
|
||||||
|
ret.push(hrp.charCodeAt(p) >> 5);
|
||||||
|
}
|
||||||
|
ret.push(0);
|
||||||
|
for (p = 0; p < hrp.length; ++p) {
|
||||||
|
ret.push(hrp.charCodeAt(p) & 31);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
coinjs. bech32_verifyChecksum = function(hrp, data) {
|
||||||
|
return coinjs.bech32_polymod(coinjs.bech32_hrpExpand(hrp).concat(data)) === 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
coinjs.bech32_createChecksum = function(hrp, data) {
|
||||||
|
var values = coinjs.bech32_hrpExpand(hrp).concat(data).concat([0, 0, 0, 0, 0, 0]);
|
||||||
|
var mod = coinjs.bech32_polymod(values) ^ 1;
|
||||||
|
var ret = [];
|
||||||
|
for (var p = 0; p < 6; ++p) {
|
||||||
|
ret.push((mod >> 5 * (5 - p)) & 31);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
coinjs.bech32_encode = function(hrp, data) {
|
||||||
|
var combined = data.concat(coinjs.bech32_createChecksum(hrp, data));
|
||||||
|
var ret = hrp + '1';
|
||||||
|
for (var p = 0; p < combined.length; ++p) {
|
||||||
|
ret += coinjs.bech32.charset.charAt(combined[p]);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
coinjs.bech32_decode = function(bechString) {
|
||||||
|
var p;
|
||||||
|
var has_lower = false;
|
||||||
|
var has_upper = false;
|
||||||
|
for (p = 0; p < bechString.length; ++p) {
|
||||||
|
if (bechString.charCodeAt(p) < 33 || bechString.charCodeAt(p) > 126) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (bechString.charCodeAt(p) >= 97 && bechString.charCodeAt(p) <= 122) {
|
||||||
|
has_lower = true;
|
||||||
|
}
|
||||||
|
if (bechString.charCodeAt(p) >= 65 && bechString.charCodeAt(p) <= 90) {
|
||||||
|
has_upper = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (has_lower && has_upper) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
bechString = bechString.toLowerCase();
|
||||||
|
var pos = bechString.lastIndexOf('1');
|
||||||
|
if (pos < 1 || pos + 7 > bechString.length || bechString.length > 90) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var hrp = bechString.substring(0, pos);
|
||||||
|
var data = [];
|
||||||
|
for (p = pos + 1; p < bechString.length; ++p) {
|
||||||
|
var d = coinjs.bech32.charset.indexOf(bechString.charAt(p));
|
||||||
|
if (d === -1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
data.push(d);
|
||||||
|
}
|
||||||
|
if (!coinjs.bech32_verifyChecksum(hrp, data)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
hrp: hrp,
|
||||||
|
data: data.slice(0, data.length - 6)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
coinjs.bech32_convert = function(data, inBits, outBits, pad) {
|
||||||
|
var value = 0;
|
||||||
|
var bits = 0;
|
||||||
|
var maxV = (1 << outBits) - 1;
|
||||||
|
|
||||||
|
var result = [];
|
||||||
|
for (var i = 0; i < data.length; ++i) {
|
||||||
|
value = (value << inBits) | data[i];
|
||||||
|
bits += inBits;
|
||||||
|
|
||||||
|
while (bits >= outBits) {
|
||||||
|
bits -= outBits;
|
||||||
|
result.push((value >> bits) & maxV);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pad) {
|
||||||
|
if (bits > 0) {
|
||||||
|
result.push((value << (outBits - bits)) & maxV);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (bits >= inBits) throw new Error('Excess padding');
|
||||||
|
if ((value << (outBits - bits)) & maxV) throw new Error('Non-zero padding');
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
coinjs.testdeterministicK = function() {
|
coinjs.testdeterministicK = function() {
|
||||||
// https://github.com/bitpay/bitcore/blob/9a5193d8e94b0bd5b8e7f00038e7c0b935405a03/test/crypto/ecdsa.js
|
// https://github.com/bitpay/bitcore/blob/9a5193d8e94b0bd5b8e7f00038e7c0b935405a03/test/crypto/ecdsa.js
|
||||||
// Line 21 and 22 specify digest hash and privkey for the first 2 test vectors.
|
// Line 21 and 22 specify digest hash and privkey for the first 2 test vectors.
|
||||||
|
@ -728,7 +872,10 @@
|
||||||
r.spendToScript = function(address){
|
r.spendToScript = function(address){
|
||||||
var addr = coinjs.addressDecode(address);
|
var addr = coinjs.addressDecode(address);
|
||||||
var s = coinjs.script();
|
var s = coinjs.script();
|
||||||
if(addr.version==coinjs.multisig){ // multisig address
|
if(addr.type == "bech32"){
|
||||||
|
s.writeOp(0);
|
||||||
|
s.writeBytes(Crypto.util.hexToBytes(addr.redeemscript));
|
||||||
|
} else if(addr.version==coinjs.multisig){ // multisig address
|
||||||
s.writeOp(169); //OP_HASH160
|
s.writeOp(169); //OP_HASH160
|
||||||
s.writeBytes(addr.bytes);
|
s.writeBytes(addr.bytes);
|
||||||
s.writeOp(135); //OP_EQUAL
|
s.writeOp(135); //OP_EQUAL
|
||||||
|
@ -1043,20 +1190,24 @@
|
||||||
return {'result':0, 'fail':'redeemscript', 'response':'redeemscript missing or not valid for segwit'};
|
return {'result':0, 'fail':'redeemscript', 'response':'redeemscript missing or not valid for segwit'};
|
||||||
}
|
}
|
||||||
|
|
||||||
var scriptcode = Crypto.util.hexToBytes(extract['script']);
|
|
||||||
if(scriptcode[0] != 0){
|
|
||||||
return {'result':0, 'fail':'scriptcode', 'response':'redeemscript is not valid'};
|
|
||||||
}
|
|
||||||
|
|
||||||
if(extract['value'] == -1){
|
if(extract['value'] == -1){
|
||||||
return {'result':0, 'fail':'value', 'response':'unable to generate a valid segwit hash without a value'};
|
return {'result':0, 'fail':'value', 'response':'unable to generate a valid segwit hash without a value'};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var scriptcode = Crypto.util.hexToBytes(extract['script']);
|
||||||
|
|
||||||
// end of redeem script check
|
// end of redeem script check
|
||||||
|
|
||||||
|
/* P2WPKH */
|
||||||
|
if(scriptcode.length == 20){
|
||||||
|
scriptcode = [0x00,0x14].concat(scriptcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(scriptcode.length == 22){
|
||||||
scriptcode = scriptcode.slice(1);
|
scriptcode = scriptcode.slice(1);
|
||||||
scriptcode.unshift(25, 118, 169);
|
scriptcode.unshift(25, 118, 169);
|
||||||
scriptcode.push(136, 172);
|
scriptcode.push(136, 172);
|
||||||
|
}
|
||||||
|
|
||||||
var value = coinjs.numToBytes(extract['value'], 8);
|
var value = coinjs.numToBytes(extract['value'], 8);
|
||||||
|
|
||||||
|
@ -1137,7 +1288,17 @@
|
||||||
} else if(this.ins[index].script.chunks.length == 5 && this.ins[index].script.chunks[1] == 177){//OP_CHECKLOCKTIMEVERIFY
|
} else if(this.ins[index].script.chunks.length == 5 && this.ins[index].script.chunks[1] == 177){//OP_CHECKLOCKTIMEVERIFY
|
||||||
// hodl script (not signed)
|
// hodl script (not signed)
|
||||||
return {'type':'hodl', 'signed':'false', 'signatures': 0, 'script': Crypto.util.bytesToHex(this.ins[index].script.buffer)};
|
return {'type':'hodl', 'signed':'false', 'signatures': 0, 'script': Crypto.util.bytesToHex(this.ins[index].script.buffer)};
|
||||||
} else if((this.ins[index].script.chunks.length <= 3 && this.ins[index].script.chunks.length > 0) && this.ins[index].script.chunks[0].length == 22 && this.ins[index].script.chunks[0][0] == 0){
|
} else if((this.ins[index].script.chunks.length <= 3 && this.ins[index].script.chunks.length > 0) && ((this.ins[index].script.chunks[0].length == 22 && this.ins[index].script.chunks[0][0] == 0) || (this.ins[index].script.chunks[0].length == 20 && this.ins[index].script.chunks[1] == 0))){
|
||||||
|
var signed = ((this.witness[index]) && this.witness[index].length==2) ? 'true' : 'false';
|
||||||
|
var sigs = (signed == 'true') ? 1 : 0;
|
||||||
|
var value = -1; // no value found
|
||||||
|
if((this.ins[index].script.chunks[2]) && this.ins[index].script.chunks[2].length==8){
|
||||||
|
value = coinjs.bytesToNum(this.ins[index].script.chunks[2]); // value found encoded in transaction (THIS IS NON STANDARD)
|
||||||
|
}
|
||||||
|
return {'type':'segwit', 'signed':signed, 'signatures': sigs, 'script': Crypto.util.bytesToHex(this.ins[index].script.chunks[0]), 'value': value};
|
||||||
|
|
||||||
|
/* } else if((this.ins[index].script.chunks.length <= 3 && this.ins[index].script.chunks.length > 0) && (this.ins[index].script.chunks[0].length == 22 && this.ins[index].script.chunks[0][0] == 0)){
|
||||||
|
alert('p2sh');
|
||||||
// segwit script
|
// segwit script
|
||||||
var signed = ((this.witness[index]) && this.witness[index].length==2) ? 'true' : 'false';
|
var signed = ((this.witness[index]) && this.witness[index].length==2) ? 'true' : 'false';
|
||||||
var sigs = (signed == 'true') ? 1 : 0;
|
var sigs = (signed == 'true') ? 1 : 0;
|
||||||
|
@ -1146,6 +1307,7 @@
|
||||||
value = coinjs.bytesToNum(this.ins[index].script.chunks[2]); // value found encoded in transaction (THIS IS NON STANDARD)
|
value = coinjs.bytesToNum(this.ins[index].script.chunks[2]); // value found encoded in transaction (THIS IS NON STANDARD)
|
||||||
}
|
}
|
||||||
return {'type':'segwit', 'signed':signed, 'signatures': sigs, 'script': Crypto.util.bytesToHex(this.ins[index].script.chunks[0]), 'value': value};
|
return {'type':'segwit', 'signed':signed, 'signatures': sigs, 'script': Crypto.util.bytesToHex(this.ins[index].script.chunks[0]), 'value': value};
|
||||||
|
*/
|
||||||
} 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
|
||||||
return {'type':'multisig', 'signed':'true', 'signatures':this.ins[index].script.chunks.length-2, 'script': Crypto.util.bytesToHex(this.ins[index].script.chunks[this.ins[index].script.chunks.length-1])};
|
return {'type':'multisig', 'signed':'true', 'signatures':this.ins[index].script.chunks.length-2, 'script': Crypto.util.bytesToHex(this.ins[index].script.chunks[this.ins[index].script.chunks.length-1])};
|
||||||
|
@ -1367,10 +1529,13 @@
|
||||||
|
|
||||||
var wif2 = coinjs.wif2pubkey(wif);
|
var wif2 = coinjs.wif2pubkey(wif);
|
||||||
var segwit = coinjs.segwitAddress(wif2['pubkey']);
|
var segwit = coinjs.segwitAddress(wif2['pubkey']);
|
||||||
|
var bech32 = coinjs.bech32Address(wif2['pubkey']);
|
||||||
|
|
||||||
if(segwit['redeemscript'] == Crypto.util.bytesToHex(this.ins[index].script.chunks[0])){
|
if((segwit['redeemscript'] == Crypto.util.bytesToHex(this.ins[index].script.chunks[0])) || (bech32['redeemscript'] == Crypto.util.bytesToHex(this.ins[index].script.chunks[0]))){
|
||||||
var txhash = this.transactionHashSegWitV0(index, shType);
|
var txhash = this.transactionHashSegWitV0(index, shType);
|
||||||
|
|
||||||
if(txhash.result == 1){
|
if(txhash.result == 1){
|
||||||
|
|
||||||
var segwitHash = Crypto.util.hexToBytes(txhash.hash);
|
var segwitHash = Crypto.util.hexToBytes(txhash.hash);
|
||||||
var signature = this.transactionSig(index, wif, shType, segwitHash);
|
var signature = this.transactionSig(index, wif, shType, segwitHash);
|
||||||
|
|
||||||
|
@ -1396,9 +1561,13 @@
|
||||||
for(var y = 0; y < this.witness.length; y++){
|
for(var y = 0; y < this.witness.length; y++){
|
||||||
if(!witness_used.includes(y)){
|
if(!witness_used.includes(y)){
|
||||||
var sw = coinjs.segwitAddress(this.witness[y][1]);
|
var sw = coinjs.segwitAddress(this.witness[y][1]);
|
||||||
if(sw['redeemscript'] == Crypto.util.bytesToHex(this.ins[i].script.chunks[0])){
|
var b32 = coinjs.bech32Address(this.witness[y][1]);
|
||||||
|
if((sw['redeemscript'] == Crypto.util.bytesToHex(this.ins[i].script.chunks[0])) || (b32['redeemscript'] == Crypto.util.bytesToHex(this.ins[i].script.chunks[0]))){
|
||||||
witness_order.push(this.witness[y]);
|
witness_order.push(this.witness[y]);
|
||||||
witness_used.push(y);
|
witness_used.push(y);
|
||||||
|
if(b32['redeemscript'] == Crypto.util.bytesToHex(this.ins[i].script.chunks[0])){
|
||||||
|
this.ins[index].script = coinjs.script();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,6 +170,7 @@ $(document).ready(function() {
|
||||||
var signed = txunspent.sign($("#walletKeys .privkey").val());
|
var signed = txunspent.sign($("#walletKeys .privkey").val());
|
||||||
|
|
||||||
// and finally broadcast!
|
// and finally broadcast!
|
||||||
|
|
||||||
tx2.broadcast(function(data){
|
tx2.broadcast(function(data){
|
||||||
if($(data).find("result").text()=="1"){
|
if($(data).find("result").text()=="1"){
|
||||||
$("#walletSendConfirmStatus").removeClass('hidden').addClass('alert-success').html('txid: <a href="https://coinb.in/tx/'+$(data).find("txid").text()+'" target="_blank">'+$(data).find("txid").text()+'</a>');
|
$("#walletSendConfirmStatus").removeClass('hidden').addClass('alert-success').html('txid: <a href="https://coinb.in/tx/'+$(data).find("txid").text()+'" target="_blank">'+$(data).find("txid").text()+'</a>');
|
||||||
|
@ -349,9 +350,16 @@ $(document).ready(function() {
|
||||||
$("#newSegWitKeysBtn").click(function(){
|
$("#newSegWitKeysBtn").click(function(){
|
||||||
var compressed = coinjs.compressed;
|
var compressed = coinjs.compressed;
|
||||||
coinjs.compressed = true;
|
coinjs.compressed = true;
|
||||||
|
|
||||||
var s = ($("#newSegWitBrainwallet").is(":checked")) ? $("#brainwalletSegWit").val() : null;
|
var s = ($("#newSegWitBrainwallet").is(":checked")) ? $("#brainwalletSegWit").val() : null;
|
||||||
var coin = coinjs.newKeys(s);
|
var coin = coinjs.newKeys(s);
|
||||||
|
|
||||||
|
if($("#newSegWitBech32addr").is(":checked")){
|
||||||
|
var sw = coinjs.bech32Address(coin.pubkey);
|
||||||
|
} else {
|
||||||
var sw = coinjs.segwitAddress(coin.pubkey);
|
var sw = coinjs.segwitAddress(coin.pubkey);
|
||||||
|
}
|
||||||
|
|
||||||
$("#newSegWitAddress").val(sw.address);
|
$("#newSegWitAddress").val(sw.address);
|
||||||
$("#newSegWitRedeemScript").val(sw.redeemscript);
|
$("#newSegWitRedeemScript").val(sw.redeemscript);
|
||||||
$("#newSegWitPubKey").val(coin.pubkey);
|
$("#newSegWitPubKey").val(coin.pubkey);
|
||||||
|
@ -621,7 +629,7 @@ $(document).ready(function() {
|
||||||
$.each($("#recipients .row"), function(i,o){
|
$.each($("#recipients .row"), function(i,o){
|
||||||
var a = ($(".address",o).val());
|
var a = ($(".address",o).val());
|
||||||
var ad = coinjs.addressDecode(a);
|
var ad = coinjs.addressDecode(a);
|
||||||
if(((a!="") && (ad.version == coinjs.pub || ad.version == coinjs.multisig)) && $(".amount",o).val()!=""){ // address
|
if(((a!="") && (ad.version == coinjs.pub || ad.version == coinjs.multisig || ad.type=="bech32")) && $(".amount",o).val()!=""){ // address
|
||||||
// P2SH output is 32, P2PKH is 34
|
// P2SH output is 32, P2PKH is 34
|
||||||
estimatedTxSize += (ad.version == coinjs.pub ? 34 : 32)
|
estimatedTxSize += (ad.version == coinjs.pub ? 34 : 32)
|
||||||
tx.addoutput(a, $(".amount",o).val());
|
tx.addoutput(a, $(".amount",o).val());
|
||||||
|
@ -831,7 +839,7 @@ $(document).ready(function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(redeem.from=='other'){
|
if(redeem.from=='other'){
|
||||||
$("#redeemFromStatus").removeClass('hidden').html('<span class="glyphicon glyphicon-exclamation-sign"></span> The address or multisig redeem script you have entered is invalid');
|
$("#redeemFromStatus").removeClass('hidden').html('<span class="glyphicon glyphicon-exclamation-sign"></span> The address or redeem script you have entered is invalid');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -871,28 +879,33 @@ $(document).ready(function() {
|
||||||
if(decode.version == coinjs.pub){ // regular address
|
if(decode.version == coinjs.pub){ // regular address
|
||||||
r.addr = string;
|
r.addr = string;
|
||||||
r.from = 'address';
|
r.from = 'address';
|
||||||
r.isMultisig = false;
|
r.redeemscript = false;
|
||||||
} else if (decode.version == coinjs.priv){ // wif key
|
} else if (decode.version == coinjs.priv){ // wif key
|
||||||
var a = coinjs.wif2address(string);
|
var a = coinjs.wif2address(string);
|
||||||
r.addr = a['address'];
|
r.addr = a['address'];
|
||||||
r.from = 'wif';
|
r.from = 'wif';
|
||||||
r.isMultisig = false;
|
r.redeemscript = false;
|
||||||
} else if (decode.version == coinjs.multisig){ // mulisig address
|
} else if (decode.version == coinjs.multisig){ // mulisig address
|
||||||
r.addr = '';
|
r.addr = '';
|
||||||
r.from = 'multisigAddress';
|
r.from = 'multisigAddress';
|
||||||
r.isMultisig = false;
|
r.redeemscript = false;
|
||||||
|
} else if(decode.type == 'bech32'){
|
||||||
|
r.addr = string;
|
||||||
|
r.from = 'bech32';
|
||||||
|
r.decodedRs = decode.redeemscript;
|
||||||
|
r.redeemscript = true;
|
||||||
} else {
|
} else {
|
||||||
var script = coinjs.script();
|
var script = coinjs.script();
|
||||||
var decodeRs = script.decodeRedeemScript(string);
|
var decodeRs = script.decodeRedeemScript(string);
|
||||||
if(decodeRs){ // redeem script
|
if(decodeRs){ // redeem script
|
||||||
r.addr = decodeRs['address'];
|
r.addr = decodeRs['address'];
|
||||||
r.from = 'redeemScript';
|
r.from = 'redeemScript';
|
||||||
r.decodedRs = decodeRs;
|
r.decodedRs = decodeRs.redeemscript;
|
||||||
r.isMultisig = true; // not quite, may be hodl
|
r.redeemscript = true;
|
||||||
} else { // something else
|
} else { // something else
|
||||||
r.addr = '';
|
r.addr = '';
|
||||||
r.from = 'other';
|
r.from = 'other';
|
||||||
r.isMultisig = false;
|
r.redeemscript = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
|
@ -947,7 +960,7 @@ $(document).ready(function() {
|
||||||
$("#inputs .txIdN:last").val(n);
|
$("#inputs .txIdN:last").val(n);
|
||||||
$("#inputs .txIdAmount:last").val(amount);
|
$("#inputs .txIdAmount:last").val(amount);
|
||||||
|
|
||||||
if(script.match(/^00/) && script.length==44){
|
if(((script.match(/^00/) && script.length==44)) || (script.length==40 && script.match(/^[a-f0-9]+$/gi))){
|
||||||
s = coinjs.script();
|
s = coinjs.script();
|
||||||
s.writeBytes(Crypto.util.hexToBytes(script));
|
s.writeBytes(Crypto.util.hexToBytes(script));
|
||||||
s.writeOp(0);
|
s.writeOp(0);
|
||||||
|
@ -969,7 +982,7 @@ $(document).ready(function() {
|
||||||
$.each($(data).find("unspent").children(), function(i,o){
|
$.each($(data).find("unspent").children(), function(i,o){
|
||||||
var tx = $(o).find("tx_hash").text();
|
var tx = $(o).find("tx_hash").text();
|
||||||
var n = $(o).find("tx_output_n").text();
|
var n = $(o).find("tx_output_n").text();
|
||||||
var script = (redeem.isMultisig==true) ? $("#redeemFrom").val() : $(o).find("script").text();
|
var script = (redeem.redeemscript==true) ? redeem.decodedRs : $(o).find("script").text();
|
||||||
var amount = (($(o).find("value").text()*1)/100000000).toFixed(8);
|
var amount = (($(o).find("value").text()*1)/100000000).toFixed(8);
|
||||||
|
|
||||||
addOutput(tx, n, script, amount);
|
addOutput(tx, n, script, amount);
|
||||||
|
@ -1000,7 +1013,7 @@ $(document).ready(function() {
|
||||||
var o = data.data.txs[i];
|
var o = data.data.txs[i];
|
||||||
var tx = ((o.txid).match(/.{1,2}/g).reverse()).join("")+'';
|
var tx = ((o.txid).match(/.{1,2}/g).reverse()).join("")+'';
|
||||||
var n = o.output_no;
|
var n = o.output_no;
|
||||||
var script = (redeem.isMultisig==true) ? $("#redeemFrom").val() : o.script_hex;
|
var script = (redeem.redeemscript==true) ? redeem.decodedRs : o.script_hex;
|
||||||
var amount = o.value;
|
var amount = o.value;
|
||||||
addOutput(tx, n, script, amount);
|
addOutput(tx, n, script, amount);
|
||||||
}
|
}
|
||||||
|
@ -1033,7 +1046,7 @@ $(document).ready(function() {
|
||||||
$.each($(data).find("unspent").children(), function(i,o){
|
$.each($(data).find("unspent").children(), function(i,o){
|
||||||
var tx = $(o).find("tx_hash").text();
|
var tx = $(o).find("tx_hash").text();
|
||||||
var n = $(o).find("tx_output_n").text();
|
var n = $(o).find("tx_output_n").text();
|
||||||
var script = (redeem.isMultisig==true) ? $("#redeemFrom").val() : o.script_hex;
|
var script = (redeem.redeemscript==true) ? redeem.decodedRs : o.script_hex;
|
||||||
var amount = (($(o).find("value").text()*1)/100000000).toFixed(8);
|
var amount = (($(o).find("value").text()*1)/100000000).toFixed(8);
|
||||||
addOutput(tx, n, script, amount);
|
addOutput(tx, n, script, amount);
|
||||||
});
|
});
|
||||||
|
@ -1067,7 +1080,7 @@ $(document).ready(function() {
|
||||||
var tx = ((""+o.txid).match(/.{1,2}/g).reverse()).join("")+'';
|
var tx = ((""+o.txid).match(/.{1,2}/g).reverse()).join("")+'';
|
||||||
if(tx.match(/^[a-f0-9]+$/)){
|
if(tx.match(/^[a-f0-9]+$/)){
|
||||||
var n = o.output_no;
|
var n = o.output_no;
|
||||||
var script = (redeem.isMultisig==true) ? $("#redeemFrom").val() : o.script_hex;
|
var script = (redeem.redeemscript==true) ? redeem.decodedRs : o.script_hex;
|
||||||
var amount = o.value;
|
var amount = o.value;
|
||||||
addOutput(tx, n, script, amount);
|
addOutput(tx, n, script, amount);
|
||||||
}
|
}
|
||||||
|
@ -1418,6 +1431,8 @@ $(document).ready(function() {
|
||||||
var addr = '';
|
var addr = '';
|
||||||
if(o.script.chunks.length==5){
|
if(o.script.chunks.length==5){
|
||||||
addr = coinjs.scripthash2address(Crypto.util.bytesToHex(o.script.chunks[2]));
|
addr = coinjs.scripthash2address(Crypto.util.bytesToHex(o.script.chunks[2]));
|
||||||
|
} else if((o.script.chunks.length==2) && o.script.chunks[0]==0){
|
||||||
|
addr = coinjs.bech32_encode(coinjs.bech32.hrp, [coinjs.bech32.version].concat(coinjs.bech32_convert(o.script.chunks[1], 8, 5, true)));
|
||||||
} else {
|
} else {
|
||||||
var pub = coinjs.pub;
|
var pub = coinjs.pub;
|
||||||
coinjs.pub = coinjs.multisig;
|
coinjs.pub = coinjs.multisig;
|
||||||
|
@ -1482,6 +1497,10 @@ $(document).ready(function() {
|
||||||
$("#verifyPubKey .addressSegWit").val(sw.address);
|
$("#verifyPubKey .addressSegWit").val(sw.address);
|
||||||
$("#verifyPubKey .addressSegWitRedeemScript").val(sw.redeemscript);
|
$("#verifyPubKey .addressSegWitRedeemScript").val(sw.redeemscript);
|
||||||
|
|
||||||
|
var b32 = coinjs.bech32Address(pubkey);
|
||||||
|
$("#verifyPubKey .addressBech32").val(b32.address);
|
||||||
|
$("#verifyPubKey .addressBech32RedeemScript").val(b32.redeemscript);
|
||||||
|
|
||||||
$("#verifyPubKey .verifyDataSw").removeClass('hidden');
|
$("#verifyPubKey .verifyDataSw").removeClass('hidden');
|
||||||
}
|
}
|
||||||
$("#verifyPubKey").removeClass("hidden");
|
$("#verifyPubKey").removeClass("hidden");
|
||||||
|
|
10
sha1sum
10
sha1sum
|
@ -1,9 +1,9 @@
|
||||||
---- Version 1.3 2018.01.15 ---
|
---- Version 1.4 2018.05.27 ---
|
||||||
77e4519962e2f6a9fc93342137dbb31c33b76b04 ./js/aes.js
|
77e4519962e2f6a9fc93342137dbb31c33b76b04 ./js/aes.js
|
||||||
3a09a8fc0cfe828b57fc798d668234d0490ee1a6 ./js/bootstrap-datetimepicker.min.js
|
3a09a8fc0cfe828b57fc798d668234d0490ee1a6 ./js/bootstrap-datetimepicker.min.js
|
||||||
253711c6d825de55a8360552573be950da180614 ./js/bootstrap.min.js
|
253711c6d825de55a8360552573be950da180614 ./js/bootstrap.min.js
|
||||||
106646cb21653e8eeaa36dbf7ba4c572efbef08c ./js/coinbin.js
|
dda26795fcd22541612067d44cf72ecae62f092b ./js/coinbin.js
|
||||||
2d48b86fe5c7d485c6613afcb0d52d5352ecf01b ./js/coin.js
|
d623019884867a13a55832cfb206606ff544e56a ./js/coin.js
|
||||||
988565bc2cb402d63ed5c5fd7ff47c4278efc2c5 ./js/collapse.js
|
988565bc2cb402d63ed5c5fd7ff47c4278efc2c5 ./js/collapse.js
|
||||||
9ba5ede3d7f9d4c8fd623395f196adfdcf7e970f ./js/crypto-min.js
|
9ba5ede3d7f9d4c8fd623395f196adfdcf7e970f ./js/crypto-min.js
|
||||||
f7c09f2f5a721371e7d478050119f7e2d58e3ef9 ./js/crypto-sha256-hmac.js
|
f7c09f2f5a721371e7d478050119f7e2d58e3ef9 ./js/crypto-sha256-hmac.js
|
||||||
|
@ -30,5 +30,5 @@ ca35b697d99cae4d1b60f2d60fcd37771987eb07 ./fonts/glyphicons-halflings-regular.w
|
||||||
de51a8494180a6db074af2dee2383f0a363c5b08 ./fonts/glyphicons-halflings-regular.svg
|
de51a8494180a6db074af2dee2383f0a363c5b08 ./fonts/glyphicons-halflings-regular.svg
|
||||||
278e49a86e634da6f2a02f3b47dd9d2a8f26210f ./fonts/glyphicons-halflings-regular.woff
|
278e49a86e634da6f2a02f3b47dd9d2a8f26210f ./fonts/glyphicons-halflings-regular.woff
|
||||||
44bc1850f570972267b169ae18f1cb06b611ffa2 ./fonts/glyphicons-halflings-regular.ttf
|
44bc1850f570972267b169ae18f1cb06b611ffa2 ./fonts/glyphicons-halflings-regular.ttf
|
||||||
177232f8f3eac41ec9402c581dd26c69e498874d ./README.md
|
c024021c71cba503979a859d23cbf7a88b570d82 ./README.md
|
||||||
2334df7122e15cae4f045a7e15bc24abbbe79aa7 ./index.html
|
208b64a1ef61aaceec82f06515e4f7cf046793f6 ./index.html
|
||||||
|
|
Loading…
Reference in a new issue