From 2f446286047557f8ac9356c068bf55797ace5f73 Mon Sep 17 00:00:00 2001
From: Daniel Cousens <github@dcousens.com>
Date: Thu, 29 May 2014 01:20:13 +1000
Subject: [PATCH] Transaction: refactor hashForSignature

Adds asserts to ensure only valid hashes are created (until the
implementation is complete).

Also uses `Script.without` to remove OP_CODESEPARATOR from the Scripts
as required by the protocol.
---
 src/transaction.js | 49 ++++++++++++++++------------------------------
 1 file changed, 17 insertions(+), 32 deletions(-)

diff --git a/src/transaction.js b/src/transaction.js
index 8090b3b..0135a1b 100644
--- a/src/transaction.js
+++ b/src/transaction.js
@@ -9,6 +9,7 @@ var convert = require('./convert')
 var crypto = require('./crypto')
 var ECKey = require('./eckey')
 var ecdsa = require('./ecdsa')
+var opcodes = require('./opcodes')
 
 var DEFAULT_SEQUENCE = 0xffffffff
 
@@ -196,49 +197,37 @@ var SIGHASH_ANYONECANPAY = 0x80
  * hashType, serializes and finally hashes the result. This hash can then be
  * used to sign the transaction input in question.
  */
-Transaction.prototype.hashForSignature =
-  function (connectedScript, inIndex, hashType)
-{
-  var txTmp = this.clone()
+Transaction.prototype.hashForSignature = function(scriptPubKey, inIndex, hashType) {
+  assert(inIndex >= 0, 'Invalid vin index')
+  assert(inIndex < this.ins.length, 'Invalid vin index')
+  assert(scriptPubKey instanceof Script, 'Invalid Script object')
 
-  // In case concatenating two scripts ends up with two codeseparators,
-  // or an extra one at the end, this prevents all those possible
-  // incompatibilities.
-  /*scriptCode = scriptCode.filter(function (val) {
-    return val !== OP_CODESEPARATOR
-    });*/
+  var txTmp = this.clone()
+  var hashScript = scriptPubKey.without(opcodes.OP_CODESEPARATOR)
 
   // Blank out other inputs' signatures
   txTmp.ins.forEach(function(txin) {
     txin.script = new Script()
   })
+  txTmp.ins[inIndex].script = hashScript
 
-  txTmp.ins[inIndex].script = connectedScript
+  var hashTypeModifier = hashType & 0x1f
+  if (hashTypeModifier === SIGHASH_NONE) {
+    assert(false, 'SIGHASH_NONE not yet supported')
 
-  // Blank out some of the outputs
-  if ((hashType & 0x1f) == SIGHASH_NONE) {
-    txTmp.outs = []
+  } else if (hashTypeModifier === SIGHASH_SINGLE) {
+    assert(false, 'SIGHASH_SINGLE not yet supported')
 
-    // Let the others update at will
-    txTmp.ins.forEach(function(txin, i) {
-      if (i != inIndex) {
-        txTmp.ins[i].sequence = 0
-      }
-    })
-
-  } else if ((hashType & 0x1f) == SIGHASH_SINGLE) {
-    // TODO: Implement
   }
 
-  // Blank out other inputs completely, not recommended for open transactions
   if (hashType & SIGHASH_ANYONECANPAY) {
-    txTmp.ins = [txTmp.ins[inIndex]]
+    assert(false, 'SIGHASH_ANYONECANPAY not yet supported')
   }
 
-  var htB = new Buffer(4)
-  htB.writeUInt32LE(hashType, 0)
+  var hashTypeBuffer = new Buffer(4)
+  hashTypeBuffer.writeInt32LE(hashType, 0)
 
-  var buffer = Buffer.concat([txTmp.toBuffer(), htB])
+  var buffer = Buffer.concat([txTmp.toBuffer(), hashTypeBuffer])
   return crypto.hash256(buffer)
 }
 
@@ -364,11 +353,7 @@ Transaction.prototype.sign = function(index, key, type) {
 
 Transaction.prototype.signScriptSig = function(index, scriptPubKey, key, type) {
   type = type || SIGHASH_ALL
-
-  assert((index >= 0), 'Invalid vin index')
-  assert(scriptPubKey instanceof Script, 'Invalid Script object')
   assert(key instanceof ECKey, 'Invalid private key')
-//  assert.equal(type & 0x7F, type, 'Invalid type') // TODO
 
   var hash = this.hashForSignature(scriptPubKey, index, type)
   var signature = key.sign(hash)