Skip to content

Commit 27fe616

Browse files
committed
templates: stricter type definitions
1 parent ed98be9 commit 27fe616

File tree

16 files changed

+394
-267
lines changed

16 files changed

+394
-267
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
"pushdata-bitcoin": "^1.0.1",
6464
"randombytes": "^2.0.1",
6565
"safe-buffer": "^5.0.1",
66-
"typeforce": "^1.11.3",
66+
"typeforce": "^1.11.4",
6767
"varuint-bitcoin": "^1.0.4",
6868
"wif": "^2.0.1"
6969
},

src/script.js

Lines changed: 69 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,7 @@ function fromASM (asm) {
157157
}))
158158
}
159159

160-
function toStack (chunks) {
161-
chunks = decompile(chunks)
160+
function toWitness (chunks) {
162161
typeforce(isPushOnly, chunks)
163162

164163
return chunks.map(function (op) {
@@ -169,6 +168,12 @@ function toStack (chunks) {
169168
})
170169
}
171170

171+
function toStack (chunks) {
172+
console.warn('toStack is deprecated, use toWitness')
173+
chunks = decompile(chunks)
174+
return toWitness(chunks)
175+
}
176+
172177
function isCanonicalPubKey (buffer) {
173178
if (!Buffer.isBuffer(buffer)) return false
174179
if (buffer.length < 33) return false
@@ -203,17 +208,76 @@ module.exports = {
203208
decompile: decompile,
204209
fromASM: fromASM,
205210
toASM: toASM,
206-
toStack: toStack,
211+
toWitness: toWitness,
207212

208213
number: require('./script_number'),
209214

210215
isCanonicalPubKey: isCanonicalPubKey,
211216
isCanonicalSignature: isCanonicalSignature,
217+
isDefinedHashType: isDefinedHashType,
212218
isPushOnly: isPushOnly,
213-
isDefinedHashType: isDefinedHashType
219+
220+
// TODO: remove in 4.0.0
221+
toStack: toStack
214222
}
215223

216224
var templates = require('./templates')
217225
for (var key in templates) {
218-
module.exports[key] = templates[key]
226+
var template = templates[key]
227+
228+
// TODO: remove the wrappers in 4.0.0???
229+
if (template.input) {
230+
var input = template.input
231+
232+
if (!input.checkWitness) {
233+
input.checkWitness = function checkWitness (witness, allowIncomplete) {
234+
typeforce(types.Witness, witness)
235+
return input.checkRaw(witness, allowIncomplete)
236+
}
237+
input.checkWitness.toJSON = input.checkRaw.toJSON
238+
}
239+
if (!input.check) {
240+
input.check = function check (script, allowIncomplete) {
241+
typeforce(types.Buffer, script)
242+
return input.checkRaw(decompile(script), allowIncomplete)
243+
}
244+
input.check.toJSON = input.checkRaw.toJSON
245+
}
246+
247+
if (!input.encodeWitness) {
248+
input.encodeWitness = function encodeWitness () {
249+
return toWitness(input.encodeRaw.apply(null, arguments))
250+
}
251+
}
252+
if (!input.noScript && !input.encode) {
253+
input.encode = function encode () {
254+
return compile(input.encodeRaw.apply(null, arguments))
255+
}
256+
}
257+
258+
if (!input.decodeWitness) {
259+
input.decode = function decodeWitness (witness, allowIncomplete) {
260+
typeforce(types.Witness, witness)
261+
return input.decodeRaw(decompile(witness), allowIncomplete)
262+
}
263+
}
264+
if (!input.noScript && !input.decode) {
265+
input.decode = function decode (script, allowIncomplete) {
266+
typeforce(types.Buffer, script)
267+
return input.decodeRaw(decompile(script), allowIncomplete)
268+
}
269+
}
270+
271+
// TODO: deprecated, remove in 4.0.0
272+
input.decodeStack = function decodeStack () {
273+
console.warn('decodeStack/encodeStack is deprecated, see #863')
274+
return input.decodeRaw.apply(null, arguments)
275+
}
276+
input.encodeStack = function encodeStack () {
277+
console.warn('decodeStack/encodeStack is deprecated, see #863')
278+
return input.encodeRaw.apply(null, arguments)
279+
}
280+
}
281+
282+
module.exports[key] = template
219283
}

src/templates/index.js

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
var decompile = require('../script').decompile
21
var multisig = require('./multisig')
32
var nullData = require('./nulldata')
43
var pubKey = require('./pubkey')
@@ -25,35 +24,26 @@ function classifyOutput (script) {
2524
if (witnessScriptHash.output.check(script)) return types.P2WSH
2625
if (pubKeyHash.output.check(script)) return types.P2PKH
2726
if (scriptHash.output.check(script)) return types.P2SH
28-
29-
// XXX: optimization, below functions .decompile before use
30-
var chunks = decompile(script)
31-
if (multisig.output.check(chunks)) return types.MULTISIG
32-
if (pubKey.output.check(chunks)) return types.P2PK
33-
if (witnessCommitment.output.check(chunks)) return types.WITNESS_COMMITMENT
34-
if (nullData.output.check(chunks)) return types.NULLDATA
27+
if (multisig.output.check(script)) return types.MULTISIG
28+
if (pubKey.output.check(script)) return types.P2PK
29+
if (witnessCommitment.output.check(script)) return types.WITNESS_COMMITMENT
30+
if (nullData.output.check(script)) return types.NULLDATA
3531

3632
return types.NONSTANDARD
3733
}
3834

3935
function classifyInput (script, allowIncomplete) {
40-
// XXX: optimization, below functions .decompile before use
41-
var chunks = decompile(script)
42-
43-
if (pubKeyHash.input.check(chunks)) return types.P2PKH
44-
if (scriptHash.input.check(chunks, allowIncomplete)) return types.P2SH
45-
if (multisig.input.check(chunks, allowIncomplete)) return types.MULTISIG
46-
if (pubKey.input.check(chunks)) return types.P2PK
36+
if (pubKeyHash.input.check(script)) return types.P2PKH
37+
if (scriptHash.input.check(script, allowIncomplete)) return types.P2SH
38+
if (multisig.input.check(script, allowIncomplete)) return types.MULTISIG
39+
if (pubKey.input.check(script)) return types.P2PK
4740

4841
return types.NONSTANDARD
4942
}
5043

51-
function classifyWitness (script, allowIncomplete) {
52-
// XXX: optimization, below functions .decompile before use
53-
var chunks = decompile(script)
54-
55-
if (witnessPubKeyHash.input.check(chunks)) return types.P2WPKH
56-
if (witnessScriptHash.input.check(chunks, allowIncomplete)) return types.P2WSH
44+
function classifyWitness (stack, allowIncomplete) {
45+
if (witnessPubKeyHash.input.checkStack(stack)) return types.P2WPKH
46+
if (witnessScriptHash.input.checkStack(stack, allowIncomplete)) return types.P2WSH
5747

5848
return types.NONSTANDARD
5949
}

src/templates/multisig/input.js

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
// OP_0 [signatures ...]
22

3-
var Buffer = require('safe-buffer').Buffer
43
var bscript = require('../../script')
4+
var types = require('../../types')
55
var typeforce = require('typeforce')
66
var OPS = require('bitcoin-ops')
77

88
function partialSignature (value) {
99
return value === OPS.OP_0 || bscript.isCanonicalSignature(value)
1010
}
1111

12-
function check (script, allowIncomplete) {
13-
var chunks = bscript.decompile(script)
12+
// check
13+
function checkRaw (chunks, allowIncomplete) {
14+
typeforce(types.Array, chunks)
1415
if (chunks.length < 2) return false
1516
if (chunks[0] !== OPS.OP_0) return false
1617

@@ -20,11 +21,9 @@ function check (script, allowIncomplete) {
2021

2122
return chunks.slice(1).every(bscript.isCanonicalSignature)
2223
}
23-
check.toJSON = function () { return 'multisig input' }
24+
checkRaw.toJSON = function () { return 'multisig input' }
2425

25-
var EMPTY_BUFFER = Buffer.allocUnsafe(0)
26-
27-
function encodeStack (signatures, scriptPubKey) {
26+
function encodeRaw (signatures, scriptPubKey) {
2827
typeforce([partialSignature], signatures)
2928

3029
if (scriptPubKey) {
@@ -39,27 +38,16 @@ function encodeStack (signatures, scriptPubKey) {
3938
}
4039
}
4140

42-
return [].concat(EMPTY_BUFFER, signatures)
43-
}
44-
45-
function encode (signatures, scriptPubKey) {
46-
return bscript.compile(encodeStack(signatures, scriptPubKey))
47-
}
48-
49-
function decodeStack (stack, allowIncomplete) {
50-
typeforce(check, stack, allowIncomplete)
51-
return stack.slice(1)
41+
return [].concat(OPS.OP_0, signatures)
5242
}
5343

54-
function decode (buffer, allowIncomplete) {
55-
var stack = bscript.decompile(buffer)
56-
return decodeStack(stack, allowIncomplete)
44+
function decodeRaw (chunks, allowIncomplete) {
45+
typeforce(checkRaw, chunks, allowIncomplete)
46+
return chunks.slice(1)
5747
}
5848

5949
module.exports = {
60-
check: check,
61-
decode: decode,
62-
decodeStack: decodeStack,
63-
encode: encode,
64-
encodeStack: encodeStack
50+
checkRaw: checkRaw,
51+
decodeRaw: decodeRaw,
52+
encodeRaw: encodeRaw
6553
}

src/templates/nulldata.js

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,19 @@ var typeforce = require('typeforce')
66
var OPS = require('bitcoin-ops')
77

88
function check (script) {
9-
var buffer = bscript.compile(script)
10-
11-
return buffer.length > 1 &&
12-
buffer[0] === OPS.OP_RETURN
9+
typeforce(types.Buffer, script)
10+
return script.length > 1 &&
11+
script[0] === OPS.OP_RETURN
1312
}
1413
check.toJSON = function () { return 'null data output' }
1514

1615
function encode (data) {
1716
typeforce(types.Buffer, data)
18-
1917
return bscript.compile([OPS.OP_RETURN, data])
2018
}
2119

2220
function decode (buffer) {
2321
typeforce(check, buffer)
24-
2522
return buffer.slice(2)
2623
}
2724

src/templates/pubkey/input.js

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,29 @@
11
// {signature}
22

33
var bscript = require('../../script')
4+
var types = require('../../types')
45
var typeforce = require('typeforce')
56

6-
function check (script) {
7-
var chunks = bscript.decompile(script)
8-
7+
function checkRaw (chunks) {
8+
typeforce(types.Array, chunks)
99
return chunks.length === 1 &&
1010
bscript.isCanonicalSignature(chunks[0])
1111
}
12-
check.toJSON = function () { return 'pubKey input' }
12+
checkRaw.toJSON = function () { return 'pubKey input' }
1313

14-
function encodeStack (signature) {
14+
// encode
15+
function encodeRaw (signature) {
1516
typeforce(bscript.isCanonicalSignature, signature)
1617
return [signature]
1718
}
1819

19-
function encode (signature) {
20-
return bscript.compile(encodeStack(signature))
21-
}
22-
23-
function decodeStack (stack) {
24-
typeforce(check, stack)
25-
return stack[0]
26-
}
27-
28-
function decode (buffer) {
29-
var stack = bscript.decompile(buffer)
30-
return decodeStack(stack)
20+
function decodeRaw (chunks) {
21+
typeforce(checkRaw, chunks)
22+
return chunks[0]
3123
}
3224

3325
module.exports = {
34-
check: check,
35-
decode: decode,
36-
decodeStack: decodeStack,
37-
encode: encode,
38-
encodeStack: encodeStack
26+
checkRaw: checkRaw,
27+
decodeRaw: decodeRaw,
28+
encodeRaw: encodeRaw
3929
}

src/templates/pubkeyhash/input.js

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
// {signature} {pubKey}
22

33
var bscript = require('../../script')
4+
var types = require('../../types')
45
var typeforce = require('typeforce')
56

6-
function check (script) {
7-
var chunks = bscript.decompile(script)
8-
7+
function checkRaw (chunks) {
8+
typeforce(types.Array, chunks)
99
return chunks.length === 2 &&
1010
bscript.isCanonicalSignature(chunks[0]) &&
1111
bscript.isCanonicalPubKey(chunks[1])
1212
}
13-
check.toJSON = function () { return 'pubKeyHash input' }
13+
checkRaw.toJSON = function () { return 'pubKeyHash input' }
1414

15-
function encodeStack (signature, pubKey) {
15+
function encodeRaw (signature, pubKey) {
1616
typeforce({
1717
signature: bscript.isCanonicalSignature,
1818
pubKey: bscript.isCanonicalPubKey
@@ -24,28 +24,16 @@ function encodeStack (signature, pubKey) {
2424
return [signature, pubKey]
2525
}
2626

27-
function encode (signature, pubKey) {
28-
return bscript.compile(encodeStack(signature, pubKey))
29-
}
30-
31-
function decodeStack (stack) {
32-
typeforce(check, stack)
33-
27+
function decodeRaw (chunks, allowIncomplete) {
28+
typeforce(checkRaw, chunks, allowIncomplete)
3429
return {
35-
signature: stack[0],
36-
pubKey: stack[1]
30+
signature: chunks[0],
31+
pubKey: chunks[1]
3732
}
3833
}
3934

40-
function decode (buffer) {
41-
var stack = bscript.decompile(buffer)
42-
return decodeStack(stack)
43-
}
44-
4535
module.exports = {
46-
check: check,
47-
decode: decode,
48-
decodeStack: decodeStack,
49-
encode: encode,
50-
encodeStack: encodeStack
36+
checkRaw: checkRaw,
37+
decodeRaw: decodeRaw,
38+
encodeRaw: encodeRaw
5139
}

0 commit comments

Comments
 (0)