Skip to content

Commit a59eecd

Browse files
authored
Merge pull request #1863 from bitcoinerlab/master
Resource Limitation Checks to Prevent Unspendable Scripts
2 parents cdb95a9 + e3c16e6 commit a59eecd

File tree

9 files changed

+72
-4
lines changed

9 files changed

+72
-4
lines changed

src/payments/p2sh.js

+8
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,14 @@ function p2sh(a, opts) {
138138
const decompile = bscript.decompile(redeem.output);
139139
if (!decompile || decompile.length < 1)
140140
throw new TypeError('Redeem.output too short');
141+
if (redeem.output.byteLength > 520)
142+
throw new TypeError(
143+
'Redeem.output unspendable if larger than 520 bytes',
144+
);
145+
if (bscript.countNonPushOnlyOPs(decompile) > 201)
146+
throw new TypeError(
147+
'Redeem.output unspendable with more than 201 non-push ops',
148+
);
141149
// match hash against other sources
142150
const hash2 = bcrypto.hash160(redeem.output);
143151
if (hash.length > 0 && !hash.equals(hash2))

src/payments/p2wsh.js

+11-2
Original file line numberDiff line numberDiff line change
@@ -166,10 +166,19 @@ function p2wsh(a, opts) {
166166
a.redeem.witness.length > 0
167167
)
168168
throw new TypeError('Ambiguous witness source');
169-
// is the redeem output non-empty?
169+
// is the redeem output non-empty/valid?
170170
if (a.redeem.output) {
171-
if (bscript.decompile(a.redeem.output).length === 0)
171+
const decompile = bscript.decompile(a.redeem.output);
172+
if (!decompile || decompile.length < 1)
172173
throw new TypeError('Redeem.output is invalid');
174+
if (a.redeem.output.byteLength > 3600)
175+
throw new TypeError(
176+
'Redeem.output unspendable if larger than 3600 bytes',
177+
);
178+
if (bscript.countNonPushOnlyOPs(decompile) > 201)
179+
throw new TypeError(
180+
'Redeem.output unspendable with more than 201 non-push ops',
181+
);
173182
// match hash against other sources
174183
const hash2 = bcrypto.sha256(a.redeem.output);
175184
if (hash.length > 0 && !hash.equals(hash2))

src/script.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import * as scriptNumber from './script_number';
55
import * as scriptSignature from './script_signature';
66
export { OPS };
77
export declare function isPushOnly(value: Stack): boolean;
8+
export declare function countNonPushOnlyOPs(value: Stack): number;
89
export declare function compile(chunks: Buffer | Stack): Buffer;
910
export declare function decompile(buffer: Buffer | Array<number | Buffer>): Array<number | Buffer> | null;
1011
export declare function toASM(chunks: Buffer | Array<number | Buffer>): string;

src/script.js

+5
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ exports.signature =
1010
exports.toASM =
1111
exports.decompile =
1212
exports.compile =
13+
exports.countNonPushOnlyOPs =
1314
exports.isPushOnly =
1415
exports.OPS =
1516
void 0;
@@ -42,6 +43,10 @@ function isPushOnly(value) {
4243
return types.Array(value) && value.every(isPushOnlyChunk);
4344
}
4445
exports.isPushOnly = isPushOnly;
46+
function countNonPushOnlyOPs(value) {
47+
return value.length - value.filter(isPushOnlyChunk).length;
48+
}
49+
exports.countNonPushOnlyOPs = countNonPushOnlyOPs;
4550
function asMinimalOP(buffer) {
4651
if (buffer.length === 0) return ops_1.OPS.OP_0;
4752
if (buffer.length !== 1) return;

test/fixtures/p2sh.json

+8
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,14 @@
294294
"input": "OP_0 OP_0"
295295
}
296296
},
297+
{
298+
"exception": "Redeem.output unspendable if larger than 520 bytes",
299+
"arguments": {
300+
"redeem": {
301+
"output": "OP_16 03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0 0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600 0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8 0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8 02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8 0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286 0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009 02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d 03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9 02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af 02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd 036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24 02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc 02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3 02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06 0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232 OP_16 OP_CHECKMULTISIG"
302+
}
303+
}
304+
},
297305
{
298306
"exception": "Input is invalid",
299307
"arguments": {

test/fixtures/p2wsh.json

+16
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,22 @@
264264
}
265265
}
266266
},
267+
{
268+
"exception": "Redeem.output unspendable with more than 201 non-push ops",
269+
"arguments": {
270+
"redeem": {
271+
"output": "OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP OP_0 OP_0 OP_2DROP 02c56aef124aa09836590fb858ce3517bf9d4b27e9d3fc81c2b00845f98ef87d9e OP_CHECKSIG"
272+
}
273+
}
274+
},
275+
{
276+
"exception": "Redeem.output unspendable if larger than 3600 bytes",
277+
"arguments": {
278+
"redeem": {
279+
"output": "02dfec67b1047f5ee7fcfc470565e07ce346fb89013f8e56b9e48a9af572f6cc9e OP_CHECKSIGVERIFY 034896ca85df092ac577480101193980c02b96a01533e7096858e696789c55b032 OP_CHECKSIGVERIFY 03365a5bd77cb355a5edefe0b47b64adf466d37c826c42332c8ea3bd2cb0fd2c0f OP_CHECKSIGVERIFY 0206c24e25bc5048bbb4723d701532db94366aa12bd080a8cf2cd35b41ea16b7e2 OP_CHECKSIGVERIFY 02e55fb5431a1c654cce06255befb4232600a94c4db57b4ab218a4ce04259c1145 OP_CHECKSIGVERIFY 02b4af93ac624e0f45e8577d828d0de343c595b9328958005baf6ab21a650ad39a OP_CHECKSIGVERIFY 03311744aa2a0d9b0af1c10f2eb4f4dd98b672fd61a575720298f334ebff3633fb OP_CHECKSIGVERIFY 0355b2ca92e66c250fafd45f3177b4a0fb48befc8b5911a37cdf3de5acc23b6e48 OP_CHECKSIGVERIFY 023e24b1d99ee02f08451af9e7e5d08db66db3e4ba04238bb4a484fc1bd66e4b89 OP_CHECKSIGVERIFY 03e0ece48ceb3c3bb566acbfda433662d2ce14f0b23bda0d0f065c5e0589ec8f1d OP_CHECKSIGVERIFY 02426aed062674081fe6e71ed130fc9b29329cef01204fe26b5ace638648b8d846 OP_CHECKSIGVERIFY 022960bc5bb274d8c963dbe6f77ef2cf59644f93f2dc3bf0d0036903656deaf0f3 OP_CHECKSIGVERIFY 03460e475689d3222710af5d3b8079bad3a12b248f61b300657b026c44c2b392b2 OP_CHECKSIGVERIFY 029d23671b573cbfb6272f5d197bbb88afa8fda9947affb5686c16a3e1f7592bb4 OP_CHECKSIGVERIFY 038bd4adeddfe560f8d9b1d1b7fc655c74fe605de09195c3f71e2fb8f68ecc4ca0 OP_CHECKSIGVERIFY 03a531c8795353c2a10f0e1619db468e5a87fd3303091662193c2701cfc1b1c4b0 OP_CHECKSIGVERIFY 02900a11b6b8ccc281dd7f1ab84b18358bfe2fef972967f0ca0ff1c71c5c72a8cb OP_CHECKSIGVERIFY 025e8d845e3f4d0d3afccb9c3a8368ccdcac14ff56b20706f534d7f81655715605 OP_CHECKSIGVERIFY 02646cce7f0159537815819139aad2e6d33f4398f8f502a0391491c7bf25bca4de OP_CHECKSIGVERIFY 03e852e9b853a26d7199a8772382bec56b9da7478b8037112c7d16d80d7c683568 OP_CHECKSIGVERIFY 0308d04709baf88bc6f5670d57c332ca872a8707207f3a5a59272940eb9ebc2936 OP_CHECKSIGVERIFY 0393cf1028583df1323f3b712edeb68078d412fabd1e5ccde839a500ddf506885a OP_CHECKSIGVERIFY 020edb22b296434cfe44b51f8dfc33579dd587e57a5f147470564ba9f817a586c8 OP_CHECKSIGVERIFY 0233de8260c26cba2851efc0ca2f695c37008929a2dc9244298c1990b36990083a OP_CHECKSIGVERIFY 02bcae3f6aecfd066ca029dfc833fc5f9f799760ab4baed6ef8c5ff94c002a7bc6 OP_CHECKSIGVERIFY 0285bb427b63bc8ed0890132d91a9283c7b82aa3f6d7fa7b3b27a74e7ffa41373c OP_CHECKSIGVERIFY 024e4c4f5ad562855256ba6380aba4bc93d7699939ace07c7c53fbecce044836c1 OP_CHECKSIGVERIFY 030895c63aebb5ce9e1ea2b3f30ebfd23f55fed7698757c1ec03154f1d581f0531 OP_CHECKSIGVERIFY 02070a7d5b57bf8c67ba34ed35108ba26579dbb84703c043886641e6482be0ae4a OP_CHECKSIGVERIFY 029c6ce3700ffe9b47b008c4cd849d4cd6ed1264eedebc0a4e1165dcbf5db503c6 OP_CHECKSIGVERIFY 02b1aa852b32f35e73a6aa070db64bc70329ec34f3ec13081b3859d45bb19e83b9 OP_CHECKSIGVERIFY 0375b9b9b287208cc57e49e15511f2c853bbb5562ed9fdd7b35e561d7e429018fc OP_CHECKSIGVERIFY 0355b3f1730e8eee06687bc128a86e3724dbe4da8a26fd3bfa54482ca25b247a99 OP_CHECKSIGVERIFY 03e9960ff1268abaff7190ba9f34f480b1279a6a52f96608313324c79214287bd1 OP_CHECKSIGVERIFY 036c8755595e5f3cfe45585237cbbec13737c9dab16ef90feca4b59cc20a3a5535 OP_CHECKSIGVERIFY 0228adcffece12cc99217f1d763aac469754fe3e49894a16a813443e29532e9651 OP_CHECKSIGVERIFY 03a0ea1dc9043e2f67450bb8ddccaa3af31964077a25b2baef62099fe0515fbd21 OP_CHECKSIGVERIFY 037de9ef6bee93474f6e02e377721543f8f4684e7074b45584fd751881aee96cf7 OP_CHECKSIGVERIFY 032874661d4c3802ad9913852a0271cb45cc90d981e662d831bd5290f2d6fe138d OP_CHECKSIGVERIFY 03e9242d1c7ed3ba76f8eba3e2fb4c5d33d667425222b95407de9209790e1b4bd3 OP_CHECKSIGVERIFY 02473773327552dc9f3652b513c68e133cc4d39202b348bbed359bc7b00f91bade OP_CHECKSIGVERIFY 03cebb99348541461de36106a68b0c7063bd4321021a21afbe90fa05d90a3444f0 OP_CHECKSIGVERIFY 03544a4accbdebb1bc0c62dfd3055dea9bd3c610c161a10afd53b4646d736a17db OP_CHECKSIGVERIFY 02baa91fc638c57fff9211334dc9c98b9937d75b7c534bdaeefcdeb56ca8f997e3 OP_CHECKSIGVERIFY 03bd8ea1948d869143f1fc0604ec8b54c95dd6cfc6cce11800bbe82b92ae9b5b74 OP_CHECKSIGVERIFY 0319ab36ae3727162c6699d6cfa76389a49d06a4bd4d4dad47606f8deec0376e75 OP_CHECKSIGVERIFY 0293003a1bca4ad83ac3bf5a2224ef782c8d7290f4f492e3588e644ffe02b3b35a OP_CHECKSIGVERIFY 0395248d8852d32e11f3288fa4f39a36fcc8225da9289fc3d0ad65f409821c4e17 OP_CHECKSIGVERIFY 02e3bee6809b08ab3b9fdbb4a7fcaa64cb602fdae173c6ce1c4042ca36f60e90fd OP_CHECKSIGVERIFY 034b74d1136c5422239d8c4a869e6cff7985204d9dedb2c3cca0b0b9afd589a35f OP_CHECKSIGVERIFY 0318e3f8941cf82c788d5dce82256bfe9522dd87f63a467e01c5004fec6667f0fe OP_CHECKSIGVERIFY 023fcda99ba2c461c65a3d95d03ab251d29ae9bd7b4d90a485aa6d075e35460e93 OP_CHECKSIGVERIFY 0329f7b047301f8f29725a9dd93e4742460e54b4c2ac9c08cfa9c4cd6a5e14a4ed OP_CHECKSIGVERIFY 0343a0c3f0fbbfd4ed0d1677c1a0cb3bb2a59dfcecdbc4af4386a6542cf349f437 OP_CHECKSIGVERIFY 02eae41bb436873f562629380ffdaf0fe5353cb5be07bd95343adf32ee984ef0ce OP_CHECKSIGVERIFY 02d71aa051ea95ba899d3e721f12a8ede4aebdd265a2ff31081128033bdd66befc OP_CHECKSIGVERIFY 029faa4411b3bc3a2778d6d3236396d2a81afefc792d07909e212de58e0765fa07 OP_CHECKSIGVERIFY 03eb3b7d5a44fcc754383ceca274a250b9a48a348ef166fad19981d5f37781d5dc OP_CHECKSIGVERIFY 03f3ccef99da37185f238f7643b7ff553e4f62fa376cf1852a49cd80cd856e444b OP_CHECKSIGVERIFY 03ba7b6f4ea978f9c5277c97d733ae0a2f55062555997971d6ed4b37d399b4f130 OP_CHECKSIGVERIFY 0217209004fa5e8b2277767caeac19a9c26c71655c917cf61aad6817f0717fcba0 OP_CHECKSIGVERIFY 0363f2e57f2ea1a49a39ed0542e1fdbc83e2d2317a2d29b058c7d82233f3c54e8a OP_CHECKSIGVERIFY 03dfd044cc08b325121055155e90f2955771f33f0e4d5462967dbeae431ac34e4b OP_CHECKSIGVERIFY 02aa29194b8666b1526b32e7b54cebe8305637837c7821399577ee95cf7bca6a36 OP_CHECKSIGVERIFY 02e11f095aa2730bfa6ab6a6d088d015e92204a70ad36c5fe6a6a97cf4be8fdc34 OP_CHECKSIGVERIFY 02d8a0b231ca61468d86abd8bf5169bd231243a4f75184f64a6946abb8eee17b9b OP_CHECKSIGVERIFY 034653d87fbdc8cff324a5f6e3220150749cff56f39f1bb378ae73301c15caca05 OP_CHECKSIGVERIFY 02b0e8830c020a01c31d8d211708ad1d04e7309bb584b8489d35fbcf12c09c84eb OP_CHECKSIGVERIFY 030b94559a4b54fc895f861bb2b5669736a709994ade45b08f9f6148ef25dc4eca OP_CHECKSIGVERIFY 02c1d4e3bd6651e273030a6d1f436a2455fa51b50390ba045c5e78bbef03eeb78f OP_CHECKSIGVERIFY 02b7d7f60abf61f50bcbaa0435f9a31a231b8f26def0f172578d0838091f7906eb OP_CHECKSIGVERIFY 02d410fbd6d899b21c3f6d380aeafea56a2e4e0e3b70f46734a716134fee793054 OP_CHECKSIGVERIFY 02bac3d71349f3dd83bc59c15c661d1520f43475f5fc0c38698b37de978419248b OP_CHECKSIGVERIFY 0277b4f24cc552577374909a853c1d570404e9072368d48310ed3ee597c9579e9d OP_CHECKSIGVERIFY 037ab3bd19731038c03bf4eec27e4e4788a8634b52c41e364dea45130b3ac8874b OP_CHECKSIGVERIFY 03102af5eb78a65b542b878e4e3eaa29f83f2efdae8838afe75cf2f85017b3f683 OP_CHECKSIGVERIFY 02452e8e88d61c0b206b9e4a319dc262662f4f98a5737e13b7abe2ceeae2bb8dcf OP_CHECKSIGVERIFY 0360d3d51bef5d6c5932e61b2ab44c7eea23a2d03cfed2422656ed1c873286a8e1 OP_CHECKSIGVERIFY 021eadd72a30b0ff9c2bc0f0b2815352fc789b85bf958ba36bde39092967968094 OP_CHECKSIGVERIFY 02631804ca57f694c27885d2d8c5e31e1f3b741a23d8c2e95a1ccd9ac8392c3c25 OP_CHECKSIGVERIFY 021ec0824b1594998ff91ddd2a7b53099ba60de84d447b13fddebf34533d111a3e OP_CHECKSIGVERIFY 039b386361ac56bd2b73186b66b77cb6de2fffbe05326dd2abf23d6b9d26b629ea OP_CHECKSIGVERIFY 0262efb44256f6ae1f1965aa24b57847e13f80a4283cb44a257572993845439a0e OP_CHECKSIGVERIFY 0283f818f966acc4894b54197eb7e94221851acfb6c986a7862ad86f961ab50a57 OP_CHECKSIGVERIFY 03a418b8eb7da20d694e257de6a9fc493676e1f98fef9f8165f69cd8d0f8099439 OP_CHECKSIGVERIFY 03697922030495b328ea3c101a1852ffd7818aa10fbedaf6c3a88b6fa381694d4b OP_CHECKSIGVERIFY 0266a13940d79ce8a272da6094df36875fd9c337c83d4ef491e0fa2a47ab3ffc57 OP_CHECKSIGVERIFY 03747ae0c8012281475a00085795b8bb0d595ebf2322f57ebd7c6b1edbbab56f92 OP_CHECKSIGVERIFY 02e357b1c82274aea4357e36278f912338e3adf1c17d8829edf394a1cc2bedc185 OP_CHECKSIGVERIFY 02dcc75706face7293b47b2e60af164971f9920118986ebf5ea147d077722e316f OP_CHECKSIGVERIFY 0347cdc7f774f1291bc45c7cb1d86eb7ea66a24622e387ccc7ac580b750f1ad9c3 OP_CHECKSIGVERIFY 02e650efb11ecd8ab320b3e5bec0d5852db1cddc1d67ede952f3c042f90dae1e43 OP_CHECKSIGVERIFY 039c24916f37a11398d4186a634414ea371003595e6444c92d01ace02bab5267ea OP_CHECKSIGVERIFY 038a5dbb9595503741fafe92f60187bfb2aad442dda5f9e6c17e5be6ec4b5521aa OP_CHECKSIGVERIFY 0291909a41d7114fc99e81224e37c030efc0c73b33e6b0eedcd8a53bfee276f108 OP_CHECKSIGVERIFY 02da51f2cc61ba9522869d2f9a34a21288cc8d017e4cf0060c85f2fff3ceacaf28 OP_CHECKSIGVERIFY 03237812d3a5ec0c49d8a60b15c2ac676cffc7eabf459dc9ef0ae215a1cbd26bb7 OP_CHECKSIGVERIFY 020e33b6b74b7f7190b0966b4f295199244ed33cea6e324c2f39a227486d87e059 OP_CHECKSIGVERIFY 02d2c96fd98d5da619ef2033892026b7f7595fd03667ab1f0b39a59d2e45a58c98 OP_CHECKSIGVERIFY 03df7ed4e582c8997b3a4c1138fac76144c02a052c7ac2c40e4e34d50e308efb42 OP_CHECKSIGVERIFY 028f343af70f46773a48bd8fcbeeb34a15f3cfee8427b62750006da2ae8a0745fc OP_CHECKSIGVERIFY 027e2f0c4f3d8d90ea0b426c82a6d41226e7b7c579724302034f844fde9a34bf96 OP_CHECKSIGVERIFY 03abdfa8a173a9be3a2669346430dcf5cbf5e2bb2321392bd661b9fa88be82677b OP_CHECKSIG"
280+
}
281+
}
282+
},
267283
{
268284
"exception": "Non push-only scriptSig",
269285
"arguments": {

ts_src/payments/p2sh.ts

+8
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,14 @@ export function p2sh(a: Payment, opts?: PaymentOpts): Payment {
159159
const decompile = bscript.decompile(redeem.output);
160160
if (!decompile || decompile.length < 1)
161161
throw new TypeError('Redeem.output too short');
162+
if (redeem.output.byteLength > 520)
163+
throw new TypeError(
164+
'Redeem.output unspendable if larger than 520 bytes',
165+
);
166+
if (bscript.countNonPushOnlyOPs(decompile) > 201)
167+
throw new TypeError(
168+
'Redeem.output unspendable with more than 201 non-push ops',
169+
);
162170

163171
// match hash against other sources
164172
const hash2 = bcrypto.hash160(redeem.output);

ts_src/payments/p2wsh.ts

+11-2
Original file line numberDiff line numberDiff line change
@@ -180,10 +180,19 @@ export function p2wsh(a: Payment, opts?: PaymentOpts): Payment {
180180
)
181181
throw new TypeError('Ambiguous witness source');
182182

183-
// is the redeem output non-empty?
183+
// is the redeem output non-empty/valid?
184184
if (a.redeem.output) {
185-
if (bscript.decompile(a.redeem.output)!.length === 0)
185+
const decompile = bscript.decompile(a.redeem.output);
186+
if (!decompile || decompile.length < 1)
186187
throw new TypeError('Redeem.output is invalid');
188+
if (a.redeem.output.byteLength > 3600)
189+
throw new TypeError(
190+
'Redeem.output unspendable if larger than 3600 bytes',
191+
);
192+
if (bscript.countNonPushOnlyOPs(decompile) > 201)
193+
throw new TypeError(
194+
'Redeem.output unspendable with more than 201 non-push ops',
195+
);
187196

188197
// match hash against other sources
189198
const hash2 = bcrypto.sha256(a.redeem.output);

ts_src/script.ts

+4
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ export function isPushOnly(value: Stack): boolean {
2727
return types.Array(value) && value.every(isPushOnlyChunk);
2828
}
2929

30+
export function countNonPushOnlyOPs(value: Stack): number {
31+
return value.length - value.filter(isPushOnlyChunk).length;
32+
}
33+
3034
function asMinimalOP(buffer: Buffer): number | void {
3135
if (buffer.length === 0) return OPS.OP_0;
3236
if (buffer.length !== 1) return;

0 commit comments

Comments
 (0)