Skip to content

Commit 6833aca

Browse files
committed
Merge pull request #152 from dcousens/p2shsign
Preliminary test for P2shsign
2 parents 355bc7e + 69c0497 commit 6833aca

File tree

3 files changed

+64
-36
lines changed

3 files changed

+64
-36
lines changed

src/script.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ Script.createMultisigOutputScript = function(m, pubKeys) {
419419
}
420420

421421
// {signature} {pubKey}
422-
Script.createInputScript = function(signature, pubKey) {
422+
Script.createPubKeyHashScriptSig = function(signature, pubKey) {
423423
var script = new Script()
424424
script.writeBytes(signature)
425425
script.writeBytes(pubKey.toBuffer())

src/transaction.js

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -312,15 +312,16 @@ Transaction.deserialize = function(buffer) {
312312
*/
313313
Transaction.prototype.sign = function(index, key, type, network) {
314314
assert(key instanceof ECKey)
315-
type = type || SIGHASH_ALL
316315
network = network || Network.bitcoin
317316

318317
var address = key.pub.getAddress(network.pubKeyHash)
318+
319+
// FIXME: Assumed prior TX was pay-to-pubkey-hash
319320
var script = Script.createOutputScript(address, network)
320-
var hash = this.hashTransactionForSignature(script, index, type)
321-
var sig = key.sign(hash).concat([type])
321+
var signature = this.signScriptSig(index, script, key, type)
322322

323-
this.ins[index].script = Script.createInputScript(sig, key.pub)
323+
var scriptSig = Script.createPubKeyHashScriptSig(signature, key.pub)
324+
this.setScriptSig(index, scriptSig)
324325
}
325326

326327
// Takes outputs of the form [{ output: 'txhash:index', address: 'address' },...]
@@ -357,29 +358,27 @@ Transaction.prototype.signWithKeys = function(keys, outputs, type) {
357358
}
358359
}
359360

360-
/**
361-
* Signs a P2SH output at some index with the given key
362-
*/
363-
Transaction.prototype.p2shsign = function(index, script, key, type) {
364-
script = new Script(script)
365-
key = new ECKey(key)
361+
Transaction.prototype.signScriptSig = function(index, script, key, type) {
366362
type = type || SIGHASH_ALL
367-
var hash = this.hashTransactionForSignature(script, index, type),
368-
sig = key.sign(hash).concat([type])
369-
return sig
370-
}
371363

372-
Transaction.prototype.multisign = Transaction.prototype.p2shsign
364+
assert(Number.isFinite(index) && (index >= 0), 'Invalid vin index')
365+
assert(script instanceof Script, 'Invalid Script object')
366+
assert(key instanceof ECKey, 'Invalid private key')
367+
// assert.equal(type & 0x7F, type, 'Invalid type') // TODO
373368

374-
Transaction.prototype.applyMultisigs = function(index, script, sigs/*, type*/) {
375-
this.ins[index].script = Script.createMultiSigInputScript(sigs, script)
369+
var hash = this.hashTransactionForSignature(script, index, type)
370+
return key.sign(hash).concat([type])
371+
}
372+
373+
Transaction.prototype.setScriptSig = function(index, script) {
374+
this.ins[index].script = script
376375
}
377376

378-
Transaction.prototype.validateSig = function(index, script, sig, pub) {
379-
script = new Script(script)
380-
var hash = this.hashTransactionForSignature(script,index,1)
381-
return ecdsa.verify(hash, convert.coerceToBytes(sig),
382-
convert.coerceToBytes(pub))
377+
Transaction.prototype.validateSig = function(index, script, pub, sig, type) {
378+
type = type || SIGHASH_ALL
379+
var hash = this.hashTransactionForSignature(script, index, type)
380+
381+
return pub.verify(hash, sig)
383382
}
384383

385384
Transaction.feePerKb = 20000

test/transaction.js

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
var assert = require('assert')
2-
var convert = require('../src/convert')
32

43
var Address = require('../src/address')
54
var ECKey = require('../src/eckey').ECKey
65
var T = require('../src/transaction')
76
var Transaction = T.Transaction
87
var TransactionOut = T.TransactionOut
98
var Script = require('../src/script')
9+
var network = require('..').network
1010

1111
var fixtureTxes = require('./fixtures/mainnet_tx')
1212
var fixtureTx1Hex = fixtureTxes.prevTx
1313
var fixtureTx2Hex = fixtureTxes.tx
1414
var fixtureTxBigHex = fixtureTxes.bigTx
1515

16+
function b2h(b) { return new Buffer(b).toString('hex') }
17+
function h2b(h) { return new Buffer(h, 'hex') }
18+
1619
describe('Transaction', function() {
1720
describe('deserialize', function() {
1821
var tx, serializedTx
@@ -30,8 +33,9 @@ describe('Transaction', function() {
3033

3134
it('returns the original after serialized again', function() {
3235
var actual = tx.serialize()
33-
var expected = convert.hexToBytes(serializedTx)
34-
assert.deepEqual(actual, expected)
36+
var expected = serializedTx
37+
38+
assert.equal(b2h(actual), expected)
3539
})
3640

3741
it('decodes version correctly', function(){
@@ -51,7 +55,7 @@ describe('Transaction', function() {
5155
assert.equal(input.outpoint.index, 0)
5256
assert.equal(input.outpoint.hash, "69d02fc05c4e0ddc87e796eee42693c244a3112fffe1f762c3fb61ffcb304634")
5357

54-
assert.equal(convert.bytesToHex(input.script.buffer),
58+
assert.equal(b2h(input.script.buffer),
5559
"493046022100ef89701f460e8660c80808a162bbf2d676f40a331a243592c36d6bd1f81d6bdf022100d29c072f1b18e59caba6e1f0b8cadeb373fd33a25feded746832ec179880c23901")
5660
})
5761

@@ -61,14 +65,14 @@ describe('Transaction', function() {
6165
var output = tx.outs[0]
6266

6367
assert.equal(output.value, 5000000000)
64-
assert.equal(convert.bytesToHex(output.script.toScriptHash()), "dd40dedd8f7e37466624c4dacc6362d8e7be23dd")
68+
assert.equal(b2h(output.script.toScriptHash()), "dd40dedd8f7e37466624c4dacc6362d8e7be23dd")
6569
// assert.equal(output.address.toString(), "n1gqLjZbRH1biT5o4qiVMiNig8wcCPQeB9")
6670
// TODO: address is wrong because it's a testnet transaction. Transaction needs to support testnet
6771
})
6872

6973
it('assigns hash to deserialized object', function(){
7074
var hashHex = "a9d4599e15b53f3eb531608ddb31f48c695c3d0b3538a6bda871e8b34f2f430c"
71-
assert.deepEqual(tx.hash, convert.hexToBytes(hashHex))
75+
assert.equal(b2h(tx.hash), hashHex)
7276
})
7377

7478
it('decodes large inputs correctly', function() {
@@ -158,7 +162,7 @@ describe('Transaction', function() {
158162

159163
var output = tx.outs[0]
160164
assert.equal(output.value, 40000)
161-
assert.deepEqual(convert.bytesToHex(output.script.buffer), "76a9143443bc45c560866cfeabf1d52f50a6ed358c69f288ac")
165+
assert.equal(b2h(output.script.buffer), "76a9143443bc45c560866cfeabf1d52f50a6ed358c69f288ac")
162166
}
163167
})
164168

@@ -171,11 +175,10 @@ describe('Transaction', function() {
171175
var key = ECKey.fromWIF('L44f7zxJ5Zw4EK9HZtyAnzCYz2vcZ5wiJf9AuwhJakiV4xVkxBeb')
172176
tx.sign(0, key)
173177

174-
var pub = key.pub.toBuffer()
175-
var script = prevTx.outs[0].script.buffer
178+
var script = prevTx.outs[0].script
176179
var sig = tx.ins[0].script.chunks[0]
177180

178-
assert.equal(tx.validateSig(0, script, sig, pub), true)
181+
assert.equal(tx.validateSig(0, script, key.pub, sig), true)
179182
})
180183
})
181184

@@ -188,11 +191,10 @@ describe('Transaction', function() {
188191

189192
it('returns true for valid signature', function(){
190193
var key = ECKey.fromWIF('L44f7zxJ5Zw4EK9HZtyAnzCYz2vcZ5wiJf9AuwhJakiV4xVkxBeb')
191-
var pub = key.pub.toBuffer()
192-
var script = prevTx.outs[0].script.buffer
194+
var script = prevTx.outs[0].script
193195
var sig = validTx.ins[0].script.chunks[0]
194196

195-
assert.equal(validTx.validateSig(0, script, sig, pub), true)
197+
assert.equal(validTx.validateSig(0, script, key.pub, sig), true)
196198
})
197199
})
198200

@@ -219,6 +221,33 @@ describe('Transaction', function() {
219221
})
220222
})
221223

224+
describe('signScriptSig', function() {
225+
var tx = new Transaction()
226+
tx.addInput('deadbeefcafe', 0)
227+
tx.addOutput('mrCDrCybB6J1vRfbwM5hemdJz73FwDBC8r', 1, network.testnet)
228+
229+
var privKeys = [
230+
'5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf',
231+
'5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAvUcVfH'
232+
].map(function(wif) {
233+
return ECKey.fromWIF(wif)
234+
})
235+
var pubKeys = privKeys.map(function(eck) { return eck.pub })
236+
var pubKeyBuffers = pubKeys.map(function(q) { return q.toBuffer() })
237+
var redeemScript = Script.createMultisigOutputScript(2, pubKeyBuffers)
238+
239+
var signatures = privKeys.map(function(privKey) {
240+
return tx.signScriptSig(0, redeemScript, privKey)
241+
})
242+
243+
var scriptSig = Script.createP2SHMultisigScriptSig(signatures, redeemScript)
244+
tx.setScriptSig(0, scriptSig)
245+
246+
var expected = '0100000001fecaefbeadde00000000fd1b0100483045022100a165904d2a3123ae887bd573b685e903a0ce158b1d21faba2ed4a42b3ca6126e02205f4e0e0cb333666d5b6b0b017fe0df0ac15a20f296a3fb8eab4e1572da2b3dea01473044022054e0cb54d62465a4003a2d0876048cde2b43dcab9385ffe173a2886bfa4d04b00220239811a8923887aa147d92987fa5c16f09a7fb7eea1d331c1a1d5303fd81f9c8014c8752410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a52aeffffffff0101000000000000001976a914751e76e8199196d454941c45d1b3a323f1433bd688ac00000000'
247+
248+
assert.equal(b2h(tx.serialize()), expected)
249+
})
250+
222251
describe('TransactionOut', function() {
223252
describe('scriptPubKey', function() {
224253
it('returns hex string', function() {

0 commit comments

Comments
 (0)