better sighash support for the gui, plus bug fixes and testing
This commit is contained in:
parent
d12b9d9072
commit
1f9d9e97c2
4 changed files with 105 additions and 57 deletions
28
index.html
28
index.html
|
@ -884,6 +884,7 @@
|
|||
<div class="tab-pane tab-content" id="sign">
|
||||
<h2>Sign Transaction <small>once a transaction has been verified</small></h2>
|
||||
<p>Once you have <a href="#verify">verified</a> a transaction you can sign and then <a href="#broadcast">broadcast</a> it into the network.</p>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<label for="signPrivateKey">Private key</label>
|
||||
|
@ -905,6 +906,33 @@
|
|||
</div>
|
||||
<br>
|
||||
|
||||
<a href="javascript:;" id="signAdvancedCollapse">
|
||||
<div class="well well-sm"><span class="glyphicon glyphicon-collapse-down"></span> Advanced Options</div>
|
||||
</a>
|
||||
|
||||
<div id="signAdvanced" class="hidden">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<label for="sighashType">Sig Hash Type</label>
|
||||
|
||||
<select id="sighashType" class="form-control">
|
||||
<option value="1" rel="SIGHASH_ALL: Signs all the inputs and outputs, protecting everything against modification.">ALL (default)</option>
|
||||
<option value="2" rel="SIGHASH_NONE: Signs all of the inputs but none of the outputs, allowing anyone to change where the satoshis are going unless other signatures using other signature hash flags protect the outputs.">NONE</option>
|
||||
<option value="3" rel="SIGHASH_SINGLE: The only output signed is the one corresponding to this input, ensuring nobody can change your part of the transaction but allowing other signers to change their part of the transaction.">SINGLE</option>
|
||||
<option value="129" rel="SIGHASH_ALL|SIGHASH_ANYONECANPAY: Signs all of the outputs but only this one input, it allows anyone to add or remove other inputs, so anyone can contribute additional satoshis but they cannot change how many satoshis are sent nor where they go.">ALL|ANYONECANPAY</option>
|
||||
<option value="130" rel="SIGHASH_NONE|SIGHASH_ANYONECANPAY: Signs only this one input and allows anyone to add or remove other inputs or outputs, so anyone who gets a copy of this input can spend it however they'd like.">NONE|ANYONECANPAY</option>
|
||||
<option value="131" rel="SIGHASH_SINGLE|SIGHASH_ANYONECANPAY: Signs this one input and its corresponding output. Allows anyone to add or remove other inputs.">SINGLE|ANYONECANPAY</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<div class="alert alert-info" id="sighashTypeInfo">
|
||||
SIGHASH_ALL: The default, signs all the inputs and outputs, protecting everything except the signature scripts against modification.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-danger hidden" id="signedDataError">
|
||||
<span class="glyphicon glyphicon-exclamation-sign"></span> There is a problem with one or more of your inputs, please check and try again
|
||||
</div>
|
||||
|
|
107
js/coin.js
107
js/coin.js
|
@ -916,23 +916,26 @@
|
|||
var clone = coinjs.clone(this);
|
||||
var shType = sigHashType || 1;
|
||||
|
||||
/* black out all other ins, except this one */
|
||||
for (var i = 0; i < clone.ins.length; i++) {
|
||||
if(index!=i){
|
||||
clone.ins[i].script = coinjs.script();
|
||||
}
|
||||
}
|
||||
|
||||
var extract = this.extractScriptKey(index);
|
||||
clone.ins[index].script = coinjs.script(extract['script']);
|
||||
|
||||
if((clone.ins) && clone.ins[index]){
|
||||
|
||||
/* black out all other ins, except this one */
|
||||
for (var i = 0; i < clone.ins.length; i++) {
|
||||
if(index!=i){
|
||||
clone.ins[i].script = coinjs.script();
|
||||
}
|
||||
}
|
||||
|
||||
/* SIGHASH : For more info on sig hashs see https://en.bitcoin.it/wiki/OP_CHECKSIG
|
||||
and https://bitcoin.org/en/developer-guide#signature-hash-type */
|
||||
and https://bitcoin.org/en/developer-guide#signature-hash-type */
|
||||
|
||||
if(shType == 1){
|
||||
//SIGHASH_ALL 0x01 #t
|
||||
//SIGHASH_ALL 0x01
|
||||
|
||||
} else if(shType == 2){
|
||||
//SIGHASH_NONE 0x02 #t
|
||||
//SIGHASH_NONE 0x02
|
||||
clone.outs = [];
|
||||
for (var i = 0; i < clone.ins.length; i++) {
|
||||
if(index!=i){
|
||||
|
@ -941,39 +944,42 @@
|
|||
}
|
||||
|
||||
} else if(shType == 3){
|
||||
//SIGHASH_SINGLE 0x03 #t
|
||||
for (var i = 0; i < clone.outs.length; i++) {
|
||||
if(index!=i){
|
||||
clone.outs[i].value = new BigInteger('' + Math.round((0) * 1e8), 10);
|
||||
clone.outs[i].script = coinjs.script();
|
||||
}
|
||||
|
||||
//SIGHASH_SINGLE 0x03
|
||||
clone.outs.length = index + 1;
|
||||
|
||||
for(var i = 0; i < index; i++){
|
||||
clone.outs[i].value = -1;
|
||||
clone.outs[i].script.buffer = [];
|
||||
}
|
||||
|
||||
} else if(shType >= 128){
|
||||
//SIGHASH_ANYONECANPAY 0x80 #t
|
||||
clone.ins = [this.ins[index]];
|
||||
clone.ins[0].script = this.ins[index].script;
|
||||
if(shType>128){
|
||||
if(shType==129){
|
||||
// SIGHASH_ALL + SIGHASH_ANYONECANPAY
|
||||
} else if(shType==130){
|
||||
// SIGHASH_NONE + SIGHASH_ANYONECANPAY #t
|
||||
clone.outs = [];
|
||||
} else if(shType==131){
|
||||
// SIGHASH_SINGLE + SIGHASH_ANYONECANPAY
|
||||
for (var i = 0; i < clone.outs.length; i++) {
|
||||
if(index!=i){
|
||||
clone.outs[i].value = new BigInteger('' + Math.round((0) * 1e8), 10);
|
||||
clone.outs[i].script = coinjs.script();
|
||||
}
|
||||
for (var i = 0; i < clone.ins.length; i++) {
|
||||
if(index!=i){
|
||||
clone.ins[i].sequence = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (shType >= 128){
|
||||
//SIGHASH_ANYONECANPAY 0x80
|
||||
clone.ins = [clone.ins[index]];
|
||||
|
||||
if(shType==129){
|
||||
// SIGHASH_ALL + SIGHASH_ANYONECANPAY
|
||||
|
||||
} else if(shType==130){
|
||||
// SIGHASH_NONE + SIGHASH_ANYONECANPAY
|
||||
clone.outs = [];
|
||||
|
||||
} else if(shType==131){
|
||||
// SIGHASH_SINGLE + SIGHASH_ANYONECANPAY
|
||||
clone.outs.length = index + 1;
|
||||
for(var i = 0; i < index; i++){
|
||||
clone.outs[i].value = -1;
|
||||
clone.outs[i].script.buffer = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var extract = this.extractScriptKey(index);
|
||||
clone.ins[index].script = coinjs.script(extract['script']);
|
||||
|
||||
var buffer = Crypto.util.hexToBytes(clone.serialize());
|
||||
buffer = buffer.concat(coinjs.numToBytes(parseInt(shType), 4));
|
||||
var hash = Crypto.SHA256(buffer, {asBytes: true});
|
||||
|
@ -1185,29 +1191,28 @@
|
|||
}
|
||||
|
||||
var redeemScript = (this.ins[index].script.chunks[this.ins[index].script.chunks.length-1]==174) ? this.ins[index].script.buffer : this.ins[index].script.chunks[this.ins[index].script.chunks.length-1];
|
||||
|
||||
var pubkeyList = scriptListPubkey(coinjs.script(redeemScript));
|
||||
var sigsList = scriptListSigs(this.ins[index].script);
|
||||
|
||||
var shType = sigHashType || 1;
|
||||
var sighash = Crypto.util.hexToBytes(this.transactionHash(index, shType));
|
||||
var signature = Crypto.util.hexToBytes(this.transactionSig(index, wif, shType));
|
||||
|
||||
sigsList[coinjs.countObject(sigsList)+1] = signature;
|
||||
|
||||
var s = coinjs.script();
|
||||
|
||||
s.writeOp(0);
|
||||
|
||||
if(this.ins[index].script.chunks[this.ins[index].script.chunks.length-1]==174){
|
||||
s.writeBytes(signature);
|
||||
|
||||
} 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){
|
||||
var pubkeyList = scriptListPubkey(coinjs.script(redeemScript));
|
||||
var sigsList = scriptListSigs(this.ins[index].script);
|
||||
sigsList[coinjs.countObject(sigsList)+1] = signature;
|
||||
|
||||
for(x in pubkeyList){
|
||||
for(y in sigsList){
|
||||
if(coinjs.verifySignature(sighash, sigsList[y], pubkeyList[x])){
|
||||
s.writeBytes(sigsList[y]);
|
||||
}
|
||||
for(x in pubkeyList){
|
||||
for(y in sigsList){
|
||||
this.ins[index].script.buffer = redeemScript;
|
||||
sighash = Crypto.util.hexToBytes(this.transactionHash(index, sigsList[y].slice(-1)[0]*1));
|
||||
if(coinjs.verifySignature(sighash, sigsList[y], pubkeyList[x])){
|
||||
s.writeBytes(sigsList[y]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
s.writeBytes(redeemScript);
|
||||
|
@ -1505,6 +1510,8 @@
|
|||
if (typeof bytes === "undefined") bytes = 8;
|
||||
if (bytes == 0) {
|
||||
return [];
|
||||
} else if (num == -1){
|
||||
return Crypto.util.hexToBytes("ffffffffffffffff");
|
||||
} else {
|
||||
return [num % 256].concat(coinjs.numToBytes(Math.floor(num / 256),bytes-1));
|
||||
}
|
||||
|
|
|
@ -1488,7 +1488,7 @@ $(document).ready(function() {
|
|||
var tx = coinjs.transaction();
|
||||
var t = tx.deserialize(script.val());
|
||||
|
||||
var signed = t.sign(wifkey.val());
|
||||
var signed = t.sign(wifkey.val(), $("#sighashType option:selected").val());
|
||||
$("#signedData textarea").val(signed);
|
||||
$("#signedData .txSize").html(t.size());
|
||||
$("#signedData").removeClass('hidden').fadeIn();
|
||||
|
@ -1501,6 +1501,19 @@ $(document).ready(function() {
|
|||
}
|
||||
});
|
||||
|
||||
$("#sighashType").change(function(){
|
||||
$("#sighashTypeInfo").html($("option:selected",this).attr('rel')).fadeOut().fadeIn();
|
||||
});
|
||||
|
||||
$("#signAdvancedCollapse").click(function(){
|
||||
if($("#signAdvanced").hasClass('hidden')){
|
||||
$("span",this).removeClass('glyphicon-collapse-down').addClass('glyphicon-collapse-up');
|
||||
$("#signAdvanced").removeClass("hidden");
|
||||
} else {
|
||||
$("span",this).removeClass('glyphicon-collapse-up').addClass('glyphicon-collapse-down');
|
||||
$("#signAdvanced").addClass("hidden");
|
||||
}
|
||||
});
|
||||
|
||||
/* page load code */
|
||||
|
||||
|
|
8
sha1sum
8
sha1sum
|
@ -1,9 +1,9 @@
|
|||
---- Version 1.2 2017.02.10 ----
|
||||
---- Version 1.2 2017.02.17 ----
|
||||
77e4519962e2f6a9fc93342137dbb31c33b76b04 ./js/aes.js
|
||||
3a09a8fc0cfe828b57fc798d668234d0490ee1a6 ./js/bootstrap-datetimepicker.min.js
|
||||
253711c6d825de55a8360552573be950da180614 ./js/bootstrap.min.js
|
||||
bbc88d46bbc8a10def8336a5deb1902863539d46 ./js/coinbin.js
|
||||
c16f136373fb4df3d04bff0e65e07635fa1812b6 ./js/coin.js
|
||||
0ee30f1dc9e38c62e99022e185706969ccfd14f1 ./js/coinbin.js
|
||||
f23a41e5bf56b98790c68502feae569459a60341 ./js/coin.js
|
||||
988565bc2cb402d63ed5c5fd7ff47c4278efc2c5 ./js/collapse.js
|
||||
9ba5ede3d7f9d4c8fd623395f196adfdcf7e970f ./js/crypto-min.js
|
||||
f7c09f2f5a721371e7d478050119f7e2d58e3ef9 ./js/crypto-sha256-hmac.js
|
||||
|
@ -30,4 +30,4 @@ de51a8494180a6db074af2dee2383f0a363c5b08 ./fonts/glyphicons-halflings-regular.s
|
|||
278e49a86e634da6f2a02f3b47dd9d2a8f26210f ./fonts/glyphicons-halflings-regular.woff
|
||||
44bc1850f570972267b169ae18f1cb06b611ffa2 ./fonts/glyphicons-halflings-regular.ttf
|
||||
b4d3a33913a0877684909f7edf8b79bf9192b0a7 ./README.md
|
||||
e4f5289b5d3d626405bb071560e58d53622208b5 ./index.html
|
||||
3b0c0def7addfffad28a8d83f6a279ca7ceff5f7 ./index.html
|
||||
|
|
Loading…
Reference in a new issue