@smartledger/bsv 6.2.1 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -40,6 +40,15 @@ function Preimage(preimage, options) {
40
40
  }
41
41
  }
42
42
 
43
+ // Structural minimum of a BIP-143 preimage, so a too-short buffer fails with an
44
+ // HONEST error instead of tripping decodeCompactSize into a misleading
45
+ // "8-byte CompactSize" throw. LEFT fixed (nVersion 4 + hashPrevouts 32 +
46
+ // hashSequence 32 + outpoint 36 = 104) + smallest scriptLen varint (1) + RIGHT
47
+ // fixed (amount 8 + nSequence 4 + hashOutputs 32 + nLocktime 4 + sighash 4 = 52).
48
+ Preimage.LEFT_FIXED_LENGTH = 4 + 32 + 32 + 36 // 104
49
+ Preimage.RIGHT_FIXED_LENGTH = 8 + 4 + 32 + 4 + 4 // 52
50
+ Preimage.MIN_PREIMAGE_LENGTH = Preimage.LEFT_FIXED_LENGTH + 1 + Preimage.RIGHT_FIXED_LENGTH // 157
51
+
43
52
  /**
44
53
  * Extract all preimage fields using bidirectional strategy
45
54
  * @param {string} extractionStrategy - 'LEFT', 'RIGHT', or 'DYNAMIC'
@@ -141,13 +150,27 @@ Preimage.prototype.extractFields = function(fieldNames) {
141
150
  * @returns {Object} Validation result
142
151
  */
143
152
  Preimage.prototype.validate = function() {
153
+ var errors = []
154
+ var warnings = []
155
+
156
+ // Length first: a buffer too short to hold the fixed fields can't be
157
+ // field-extracted, so report it without tripping extraction. (For a
158
+ // non-deferred Preimage construction already threw the same error.)
159
+ if (this.preimage.length < Preimage.MIN_PREIMAGE_LENGTH) {
160
+ errors.push('Preimage too short: ' + this.preimage.length +
161
+ ' bytes (BIP-143 preimage requires at least ' + Preimage.MIN_PREIMAGE_LENGTH + ')')
162
+ return {
163
+ valid: false,
164
+ errors: errors,
165
+ warnings: warnings,
166
+ sighashInfo: this.sighashInfo
167
+ }
168
+ }
169
+
144
170
  if (!this.fields) {
145
171
  this._extractFields()
146
172
  }
147
173
 
148
- var errors = []
149
- var warnings = []
150
-
151
174
  // Check required fields
152
175
  var requiredFields = [
153
176
  'version', 'hashPrevouts', 'hashSequence', 'outpoint',
@@ -165,11 +188,6 @@ Preimage.prototype.validate = function() {
165
188
  warnings.push('Zero hashes detected - check SIGHASH flags: ' + this.sighashInfo.zeroFields.join(', '))
166
189
  }
167
190
 
168
- // Validate preimage length
169
- if (this.preimage.length < 104) { // Minimum BIP-143 preimage size
170
- errors.push('Preimage too short: ' + this.preimage.length + ' bytes (minimum 104)')
171
- }
172
-
173
191
  return {
174
192
  valid: errors.length === 0,
175
193
  errors: errors,
@@ -222,6 +240,13 @@ Preimage.prototype._extractFields = function() {
222
240
  warnings: []
223
241
  }
224
242
 
243
+ // Fail closed with an honest error before any slice/varint work runs on a
244
+ // buffer too small to hold the fixed BIP-143 fields.
245
+ if (this.preimage.length < Preimage.MIN_PREIMAGE_LENGTH) {
246
+ throw new Error('Preimage too short: ' + this.preimage.length +
247
+ ' bytes (BIP-143 preimage requires at least ' + Preimage.MIN_PREIMAGE_LENGTH + ')')
248
+ }
249
+
225
250
  try {
226
251
  if (this.strategy === 'LEFT' || this.strategy === 'DYNAMIC') {
227
252
  this._extractFromLeft()
@@ -735,6 +760,10 @@ Preimage.prototype._getExtractionStrategy = function(fieldName) {
735
760
  * @returns {Object} Decoded value and next offset
736
761
  */
737
762
  Preimage.decodeCompactSize = function(buffer, offset) {
763
+ if (offset >= buffer.length) {
764
+ throw new Error('CompactSize read past end of preimage buffer (offset ' +
765
+ offset + ', length ' + buffer.length + ')')
766
+ }
738
767
  var firstByte = buffer[offset]
739
768
 
740
769
  if (firstByte < 0xfd) {
@@ -742,24 +771,22 @@ Preimage.decodeCompactSize = function(buffer, offset) {
742
771
  return { value: firstByte, nextOffset: offset + 1, bytes: 1 }
743
772
  } else if (firstByte === 0xfd) {
744
773
  // 2 byte encoding (253-65535)
774
+ if (offset + 3 > buffer.length) {
775
+ throw new Error('Truncated 2-byte CompactSize in preimage at offset ' + offset)
776
+ }
745
777
  var value = buffer.readUInt16LE(offset + 1)
746
778
  return { value: value, nextOffset: offset + 3, bytes: 3 }
747
779
  } else if (firstByte === 0xfe) {
748
780
  // 4 byte encoding (65536-4294967295) - rare for script lengths
749
- var value = buffer.readUInt32LE(offset + 1)
750
- return { value: value, nextOffset: offset + 5, bytes: 5 }
751
- } else {
752
- // 8 byte encoding - extremely rare, try to handle gracefully
753
- console.warn('Encountered 8-byte CompactSize - this is very unusual for script lengths')
754
- // For our purposes, assume it's a reasonable script length and try to parse it
755
- // This is a fallback for malformed or test data
756
- try {
757
- // Read as 4-byte for now since 8-byte values would be enormous for scripts
758
- var value = buffer.readUInt32LE(offset + 1)
759
- return { value: value, nextOffset: offset + 9, bytes: 9 } // Skip full 8 bytes + marker
760
- } catch (e) {
761
- throw new Error('Invalid 8-byte CompactSize encoding in preimage')
781
+ if (offset + 5 > buffer.length) {
782
+ throw new Error('Truncated 4-byte CompactSize in preimage at offset ' + offset)
762
783
  }
784
+ var value4 = buffer.readUInt32LE(offset + 1)
785
+ return { value: value4, nextOffset: offset + 5, bytes: 5 }
786
+ } else {
787
+ // 0xff marks an 8-byte length (>4 GB) - impossible for a real script length,
788
+ // so this is malformed/misaligned data rather than a value to salvage.
789
+ throw new Error('Invalid CompactSize: 8-byte length prefix (0xff) is not a valid script length')
763
790
  }
764
791
  }
765
792
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smartledger/bsv",
3
- "version": "6.2.1",
3
+ "version": "7.0.0",
4
4
  "description": "🚀 Complete Bitcoin SV development framework with legally-recognizable DID:web + W3C VC-JWT toolkit, Legal Token Protocol (LTP), Global Digital Attestation Framework (GDAF), StatusList2021 revocation, and 16 flexible loading options. Standards-based credentials with ES256/ES256K support, on-chain BSV anchoring, and comprehensive Bitcoin SV API. Perfect for legal tokens, verifiable credentials, DeFi, smart contracts, and secure Bitcoin applications.",
5
5
  "author": "SmartLedger Technology <hello@smartledger.technology> (https://smartledger.technology)",
6
6
  "homepage": "https://github.com/codenlighten/smartledger-bsv#readme",
@@ -9,6 +9,19 @@
9
9
  },
10
10
  "main": "index.js",
11
11
  "types": "bsv.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./bsv.d.ts",
15
+ "import": "./index.mjs",
16
+ "require": "./index.js",
17
+ "default": "./index.js"
18
+ },
19
+ "./package.json": "./package.json",
20
+ "./version": "./version.js",
21
+ "./lib/*.js": "./lib/*.js",
22
+ "./lib/*": "./lib/*.js",
23
+ "./*": "./*"
24
+ },
12
25
  "engines": {
13
26
  "node": ">=20.19.0"
14
27
  },
@@ -51,7 +64,7 @@
51
64
  "preimage:extract": "node examples/preimage/extract_preimage_bidirectional.js",
52
65
  "prepublishOnly": "npm run build-all",
53
66
  "sync-cdn": "node scripts/sync-cdn-urls.js",
54
- "version": "node scripts/sync-cdn-urls.js && node scripts/sync-version.js && git add README.md docs version.js",
67
+ "version": "node scripts/sync-cdn-urls.js && node scripts/sync-version.js && node scripts/gen-esm-wrapper.js && git add README.md docs version.js index.mjs",
55
68
  "test:browser:ci": "node tests/browser-smoke-runner.js"
56
69
  },
57
70
  "unpkg": "bsv.min.js",
@@ -59,6 +72,7 @@
59
72
  "cdn": "bsv.min.js",
60
73
  "files": [
61
74
  "index.js",
75
+ "index.mjs",
62
76
  "version.js",
63
77
  "test/",
64
78
  ".mocharc.json",
@@ -196,12 +210,12 @@
196
210
  },
197
211
  "devDependencies": {
198
212
  "assert": "^2.1.0",
199
- "brfs": "2.0.1",
200
213
  "browserify-zlib": "^0.2.0",
201
214
  "buffer": "^6.0.3",
202
215
  "chai": "4.2.0",
203
216
  "crypto-browserify": "^3.12.1",
204
217
  "esbuild": "^0.28.1",
218
+ "events": "^3.3.0",
205
219
  "jose": "^5.10.0",
206
220
  "mocha": "^11.7.6",
207
221
  "nyc": "^18.0.0",
@@ -210,12 +224,9 @@
210
224
  "sinon": "7.2.3",
211
225
  "standard": "12.0.1",
212
226
  "stream-browserify": "^3.0.0",
213
- "terser-webpack-plugin": "^5.6.1",
214
227
  "typescript": "^5.9.3",
215
228
  "util": "^0.12.5",
216
- "vm-browserify": "^1.1.2",
217
- "webpack": "^5.107.2",
218
- "webpack-cli": "^5.1.4"
229
+ "vm-browserify": "^1.1.2"
219
230
  },
220
231
  "license": "MIT",
221
232
  "standard": {
@@ -0,0 +1,66 @@
1
+ 'use strict'
2
+
3
+ /* global describe, it */
4
+
5
+ // Guards index.mjs — the real ESM entry behind the package's `import` condition.
6
+ // Asserts (a) it hasn't drifted from the CJS surface, (b) native ESM default AND
7
+ // named imports actually work, and (c) deprecated getters (SmartUTXO) are NOT
8
+ // forced as named exports (they'd fire their warning on every import).
9
+ //
10
+ // ESM behaviour is exercised in a child process (via an --input-type=module
11
+ // script string) rather than a dynamic import() in this file, so the source
12
+ // stays parseable by the pinned standard@12 linter.
13
+
14
+ require('chai').should()
15
+ var fs = require('fs')
16
+ var path = require('path')
17
+ var execFileSync = require('child_process').execFileSync
18
+ var spawnSync = require('child_process').spawnSync
19
+ var gen = require('../../scripts/gen-esm-wrapper')
20
+
21
+ var ROOT = path.resolve(__dirname, '../..')
22
+ var MJS = path.join(ROOT, 'index.mjs')
23
+
24
+ function runEsm (body) {
25
+ return execFileSync(process.execPath, ['--input-type=module', '-e', body],
26
+ { cwd: ROOT, stdio: 'pipe' })
27
+ }
28
+
29
+ describe('ESM wrapper (index.mjs)', function () {
30
+ it('is in sync with the CJS surface (no drift)', function () {
31
+ var onDisk = fs.readFileSync(MJS, 'utf8')
32
+ onDisk.should.equal(gen.generate())
33
+ })
34
+
35
+ it('exports every non-accessor top-level member as a named binding', function () {
36
+ var bsv = require('../..')
37
+ var names = gen.exportableNames(bsv)
38
+ names.length.should.be.above(100)
39
+ // SmartUTXO is an accessor (deprecated getter) and must be excluded.
40
+ names.should.not.include('SmartUTXO')
41
+ Object.getOwnPropertyDescriptor(bsv, 'SmartUTXO').get.should.be.a('function')
42
+ })
43
+
44
+ it('resolves real ESM default + named imports natively', function () {
45
+ runEsm(
46
+ 'import bsv, { PrivateKey, crypto } from ' + JSON.stringify('./index.mjs') + ';' +
47
+ 'process.exit((bsv && typeof PrivateKey === "function" && ' +
48
+ 'PrivateKey === bsv.PrivateKey && typeof crypto.ECDSA === "function") ? 0 : 3)')
49
+ })
50
+
51
+ it('does not emit the SmartUTXO deprecation warning at import (getter excluded)', function () {
52
+ // Re-exporting the getter would trip its console.warn at import time; stderr
53
+ // must be empty for a bare `import './index.mjs'`.
54
+ var res = spawnSync(process.execPath,
55
+ ['--input-type=module', '-e', 'import ' + JSON.stringify('./index.mjs') + ';'],
56
+ { cwd: ROOT, encoding: 'utf8' })
57
+ res.status.should.equal(0)
58
+ res.stderr.should.equal('')
59
+ })
60
+
61
+ it('keeps deprecated getters reachable via the default export only', function () {
62
+ runEsm(
63
+ 'import bsv from ' + JSON.stringify('./index.mjs') + ';' +
64
+ 'process.exit(("SmartUTXO" in bsv) ? 0 : 3)')
65
+ })
66
+ })
@@ -0,0 +1,58 @@
1
+ 'use strict'
2
+
3
+ /* global describe, it */
4
+
5
+ // Guards the 7.0 package.json `exports` map. Adding `exports` switches Node to
6
+ // strict subpath resolution, so this asserts the surface consumers actually use
7
+ // still resolves (via package self-reference, which Node enables once `exports`
8
+ // exists): the main entry, package.json, ./version, the shipped bundles, and
9
+ // lib/* deep imports in BOTH extension styles. Also smoke-tests the ESM `import`
10
+ // condition in a child process so the dual-ready "." entry can't silently rot.
11
+
12
+ require('chai').should()
13
+ var path = require('path')
14
+ var execFileSync = require('child_process').execFileSync
15
+
16
+ var N = '@smartledger/bsv'
17
+ var ROOT = path.resolve(__dirname, '../..')
18
+
19
+ describe('7.0 exports map resolution', function () {
20
+ it('resolves the main entry via self-reference', function () {
21
+ var bsv = require(N)
22
+ bsv.should.be.an('object')
23
+ bsv.PrivateKey.should.be.a('function')
24
+ bsv.crypto.ECDSA.should.be.a('function')
25
+ })
26
+
27
+ it('exposes package.json and ./version, and they agree', function () {
28
+ var pkg = require(N + '/package.json')
29
+ var version = require(N + '/version')
30
+ pkg.name.should.equal(N)
31
+ version.should.equal(pkg.version)
32
+ })
33
+
34
+ it('resolves lib/* deep imports with and without the .js extension', function () {
35
+ var withExt = require(N + '/lib/crypto/ecdsa.js')
36
+ var noExt = require(N + '/lib/crypto/ecdsa')
37
+ withExt.should.be.a('function')
38
+ noExt.should.equal(withExt) // same module, one cache entry
39
+ })
40
+
41
+ it('serves the full browser bundle over a subpath (loaded in isolation)', function () {
42
+ // The bundle is a self-contained bsv; loading it in-process collides with the
43
+ // main require above ("multiple bsv instances"), so resolve+load it in a child.
44
+ var script = 'var m=require(' + JSON.stringify(N + '/bsv.min.js') + ');' +
45
+ 'process.exit(m && m.PrivateKey ? 0 : 3)'
46
+ execFileSync(process.execPath, ['-e', script], { cwd: ROOT, stdio: 'pipe' })
47
+ })
48
+
49
+ it('routes the ESM `import` condition to index.mjs with default AND named exports', function () {
50
+ // Proves the dual-ESM entry end-to-end through the package specifier: the
51
+ // `import` condition resolves to index.mjs, which exposes real named bindings.
52
+ var script =
53
+ 'import bsv, { PrivateKey, Transaction, crypto } from ' + JSON.stringify(N) + ';' +
54
+ 'process.exit((bsv && bsv.PrivateKey && PrivateKey === bsv.PrivateKey && ' +
55
+ 'typeof Transaction === "function" && typeof crypto.ECDSA === "function") ? 0 : 3)'
56
+ execFileSync(process.execPath, ['--input-type=module', '-e', script], { cwd: ROOT, stdio: 'pipe' })
57
+ })
58
+ })
@@ -176,7 +176,7 @@ describe('ECDSA', function () {
176
176
  it('should create a valid signature', function () {
177
177
  ecdsa.randomK()
178
178
  ecdsa.sign()
179
- ecdsa.verify().verified.should.equal(true)
179
+ ecdsa.verify().should.equal(true)
180
180
  })
181
181
 
182
182
  it('should should throw an error if hashbuf is not 32 bytes', function () {
@@ -253,11 +253,36 @@ describe('ECDSA', function () {
253
253
  it('should verify a signature that was just signed', function () {
254
254
  ecdsa.sig = Signature.fromString('3046022100e9915e6236695f093a4128ac2a956c' +
255
255
  '40ed971531de2f4f41ba05fac7e2bd019c02210094e6a4a769cc7f2a8ab3db696c7cd8d56bcdbfff860a8c81de4bc6a798b90827')
256
- ecdsa.verify().verified.should.equal(true)
256
+ ecdsa.verify().should.equal(true)
257
+ })
258
+ // 7.0: verify() returns a strict boolean, not the (always-truthy) instance.
259
+ // A forged signature must be REJECTED by `if (ecdsa.verify())`, which was the
260
+ // whole point of removing the trap.
261
+ it('returns a strict boolean, not the instance (7.0 trap closed)', function () {
262
+ ecdsa.signRandomK()
263
+ var result = ecdsa.verify()
264
+ result.should.be.a('boolean')
265
+ result.should.equal(true)
266
+ // Forge the signature: the return value itself must be falsy.
267
+ var forged = new ECDSA()
268
+ forged.hashbuf = ecdsa.hashbuf
269
+ forged.pubkey = ecdsa.pubkey
270
+ forged.sig = new Signature(ecdsa.sig.r.add(new BN(1)), ecdsa.sig.s)
271
+ forged.verify().should.equal(false)
272
+ ;(!!forged.verify()).should.equal(false) // `if (forged.verify())` does NOT enter
273
+ })
274
+ it('verifyBool() remains a strict-boolean alias', function () {
275
+ ecdsa.signRandomK()
276
+ ecdsa.verifyBool().should.equal(true)
277
+ var forged = new ECDSA()
278
+ forged.hashbuf = ecdsa.hashbuf
279
+ forged.pubkey = ecdsa.pubkey
280
+ forged.sig = new Signature(ecdsa.sig.r.add(new BN(1)), ecdsa.sig.s)
281
+ forged.verifyBool().should.equal(false)
257
282
  })
258
283
  it('should verify this known good signature', function () {
259
284
  ecdsa.signRandomK()
260
- ecdsa.verify().verified.should.equal(true)
285
+ ecdsa.verify().should.equal(true)
261
286
  })
262
287
  it('should verify a valid signature, and unverify an invalid signature', function () {
263
288
  var sig = ECDSA.sign(ecdsa.hashbuf, ecdsa.privkey)
@@ -295,7 +320,7 @@ describe('ECDSA', function () {
295
320
  ecdsa2.k.toString().should.equal(ecdsa.k.toString())
296
321
  ecdsa2.sig.toString().should.equal(ecdsa.sig.toString())
297
322
  ecdsa2.sig.i.should.equal(ecdsa.sig.i)
298
- ecdsa.verify().verified.should.equal(true)
323
+ ecdsa.verify().should.equal(true)
299
324
  })
300
325
  })
301
326
 
@@ -49,15 +49,19 @@ describe('security: fail-closed verification contracts', function () {
49
49
  inst(wrongPub).verifyBool().should.equal(false)
50
50
  })
51
51
 
52
- // Locks the documented trap: instance .verify() returns the INSTANCE (truthy), so it
53
- // must never be read as a boolean. If this ever changes (e.g. a deliberate 7.0 that
54
- // makes verify() return a bool), this test forces the change to be intentional.
55
- it('instance .verify() returns the instance with the result on .verified (documented trap)', function () {
56
- var e = new ECDSA(); e.hashbuf = hash; e.sig = goodSig; e.pubkey = wrongPub
57
- var r = e.verify()
58
- ;(typeof r).should.equal('object') // NOT a boolean — the trap
59
- isStrictBool(r.verified).should.equal(true)
60
- r.verified.should.equal(false) // forged → verified is false, even though `r` is truthy
52
+ // 7.0: the trap is CLOSED. Instance .verify() now returns a STRICT boolean, so
53
+ // `if (ecdsa.verify())` correctly rejects a forgery. (Pre-7.0 it returned the
54
+ // truthy instance with the real result on .verified; that idiom is gone.)
55
+ it('instance .verify() returns a strict boolean and fails closed on a forgery', function () {
56
+ var good = new ECDSA(); good.hashbuf = hash; good.sig = goodSig; good.pubkey = rightPub
57
+ isStrictBool(good.verify()).should.equal(true)
58
+ good.verify().should.equal(true)
59
+
60
+ var forged = new ECDSA(); forged.hashbuf = hash; forged.sig = goodSig; forged.pubkey = wrongPub
61
+ isStrictBool(forged.verify()).should.equal(true)
62
+ forged.verify().should.equal(false) // forged → false, and `if (forged.verify())` does NOT enter
63
+ // The result is still mirrored on .verified as a side effect.
64
+ forged.verified.should.equal(false)
61
65
  })
62
66
  })
63
67
 
@@ -0,0 +1,98 @@
1
+ 'use strict'
2
+
3
+ /* global describe, it */
4
+
5
+ // Coverage for SmartContract.Preimage (previously untested public class).
6
+ // Focus: a too-short buffer must fail with an HONEST error (it used to trip
7
+ // decodeCompactSize into a misleading "8-byte CompactSize" throw plus console
8
+ // spam), while real BIP-143 preimages round-trip their fields.
9
+
10
+ require('chai').should()
11
+ var bsv = require('../..')
12
+ var Preimage = bsv.SmartContract.Preimage
13
+
14
+ describe('SmartContract.Preimage', function () {
15
+ describe('length guard (honest failure)', function () {
16
+ it('exposes the derived BIP-143 structural minimum (157)', function () {
17
+ Preimage.LEFT_FIXED_LENGTH.should.equal(104)
18
+ Preimage.RIGHT_FIXED_LENGTH.should.equal(52)
19
+ Preimage.MIN_PREIMAGE_LENGTH.should.equal(157)
20
+ })
21
+
22
+ it('throws a clear "too short" error at construction, not a CompactSize error', function () {
23
+ ;[0, 50, 103, 156].forEach(function (n) {
24
+ (function () { return new Preimage(Buffer.alloc(n)) })
25
+ .should.throw(/Preimage too short/)
26
+ })
27
+ })
28
+
29
+ it('does NOT mention CompactSize when the real problem is length', function () {
30
+ var threw
31
+ try { threw = new Preimage(Buffer.alloc(50)) } catch (e) { threw = e.message }
32
+ threw.should.match(/Preimage too short/)
33
+ threw.should.not.match(/CompactSize/)
34
+ })
35
+
36
+ it('validate() reports the length gracefully for a deferred preimage (no throw)', function () {
37
+ var p = new Preimage(Buffer.alloc(50), { deferExtraction: true })
38
+ var res = p.validate()
39
+ res.valid.should.equal(false)
40
+ res.errors.join(' ').should.match(/Preimage too short: 50 bytes/)
41
+ })
42
+
43
+ it('accepts a buffer exactly at the minimum length', function () {
44
+ // 157 bytes: 104 left + 1-byte scriptLen varint (0x00 => empty script) + 52 right.
45
+ var buf = Buffer.alloc(Preimage.MIN_PREIMAGE_LENGTH)
46
+ ;(function () { return new Preimage(buf) }).should.not.throw()
47
+ })
48
+ })
49
+
50
+ describe('decodeCompactSize (honest failure)', function () {
51
+ it('throws when reading past the end of the buffer', function () {
52
+ (function () { Preimage.decodeCompactSize(Buffer.alloc(4), 4) })
53
+ .should.throw(/past end of preimage buffer/)
54
+ })
55
+
56
+ it('rejects the 8-byte (0xff) length prefix as invalid for a script length', function () {
57
+ var buf = Buffer.concat([Buffer.from([0xff]), Buffer.alloc(8)])
58
+ ;(function () { Preimage.decodeCompactSize(buf, 0) })
59
+ .should.throw(/8-byte length prefix/)
60
+ })
61
+
62
+ it('rejects a truncated 2-byte CompactSize', function () {
63
+ (function () { Preimage.decodeCompactSize(Buffer.from([0xfd, 0x01]), 0) })
64
+ .should.throw(/Truncated 2-byte CompactSize/)
65
+ })
66
+
67
+ it('decodes a plain 1-byte length', function () {
68
+ var r = Preimage.decodeCompactSize(Buffer.from([0x19]), 0)
69
+ r.value.should.equal(0x19)
70
+ r.bytes.should.equal(1)
71
+ r.nextOffset.should.equal(1)
72
+ })
73
+ })
74
+
75
+ describe('real preimage round-trip', function () {
76
+ it('constructs, extracts fields, and validates a genuine preimage', function () {
77
+ var ex = Preimage.createExample(0x41) // SIGHASH_ALL | FORKID
78
+ ex.preimage.length.should.be.above(Preimage.MIN_PREIMAGE_LENGTH)
79
+
80
+ // Fixed-width fields come back at their BIP-143 sizes.
81
+ ex.getField('version').length.should.equal(4)
82
+ ex.getField('hashPrevouts').length.should.equal(32)
83
+ ex.getField('hashOutputs').length.should.equal(32)
84
+ ex.getField('sighash').length.should.equal(4)
85
+
86
+ var v = ex.validate()
87
+ v.valid.should.equal(true)
88
+ v.errors.length.should.equal(0)
89
+ })
90
+
91
+ it('reports SIGHASH flag info for the extracted sighash', function () {
92
+ var ex = Preimage.createExample(0x41)
93
+ var info = ex.getSighashInfo()
94
+ info.flagName.should.match(/ALL/)
95
+ info.flagName.should.match(/FORKID/)
96
+ })
97
+ })
98
+ })
package/version.js CHANGED
@@ -1,3 +1,3 @@
1
1
  'use strict'
2
2
  // GENERATED by scripts/sync-version.js on `npm version` — do not edit.
3
- module.exports = '6.2.1'
3
+ module.exports = '7.0.0'