From 1f9d9e97c2c9d275a522cfbbdfa096af99ff47e6 Mon Sep 17 00:00:00 2001 From: OutCast3k Date: Fri, 17 Feb 2017 15:38:24 +0000 Subject: [PATCH] better sighash support for the gui, plus bug fixes and testing --- index.html | 28 +++++++++++++ js/coin.js | 111 +++++++++++++++++++++++++++----------------------- js/coinbin.js | 15 ++++++- sha1sum | 8 ++-- 4 files changed, 105 insertions(+), 57 deletions(-) diff --git a/index.html b/index.html index df6daed..79c12f6 100644 --- a/index.html +++ b/index.html @@ -884,6 +884,7 @@

Sign Transaction once a transaction has been verified

Once you have verified a transaction you can sign and then broadcast it into the network.

+
@@ -905,6 +906,33 @@

+ +
Advanced Options
+
+ + + diff --git a/js/coin.js b/js/coin.js index 9f08faf..8a580ab 100644 --- a/js/coin.js +++ b/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 */ + /* 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 */ 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)); } diff --git a/js/coinbin.js b/js/coinbin.js index cf4a273..fd84e9e 100644 --- a/js/coinbin.js +++ b/js/coinbin.js @@ -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 */ diff --git a/sha1sum b/sha1sum index 25f211e..2902854 100644 --- a/sha1sum +++ b/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