@smartledger/bsv 9.14.0 → 9.16.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.
- package/CHANGELOG.md +160 -0
- package/README.md +19 -19
- package/bsv-gdaf.min.js +29 -29
- package/bsv-ltp.min.js +22 -22
- package/bsv-smartcontract.min.js +1 -1
- package/bsv.bundle.js +29 -29
- package/bsv.d.ts +7 -0
- package/bsv.min.js +29 -29
- package/docs/AUDIT_SCOPE.md +6 -6
- package/docs/BRC220_BATCH_LEAF_AMENDMENT.md +16 -4
- package/docs/BRC220_CERTIFICATE_FIELDS_AMENDMENT.md +11 -4
- package/docs/BRC220_PLAN.md +5 -2
- package/docs/MODULE_REFERENCE_COMPLETE.md +27 -27
- package/docs/advanced/UTXO_MANAGER_GUIDE.md +1 -1
- package/docs/audit-rfq/cure53.txt +1 -1
- package/docs/audit-rfq/ncc-group.txt +1 -1
- package/docs/audit-rfq/trail-of-bits.txt +1 -1
- package/docs/getting-started/INSTALLATION.md +23 -23
- package/docs/getting-started/QUICK_START.md +7 -7
- package/docs/migration/FROM_BSV_1_5_6.md +5 -5
- package/lib/script/interpreter.js +131 -39
- package/package.json +9 -5
- package/tools/gen-blind-spot-vectors.js +422 -0
- package/tools/minimal_reproduction.js +1 -1
- package/tools/opcode_map.js +11 -4
- package/tools/simple_real_tx.js +1 -1
- package/tools/sv-vector-coverage.js +174 -0
- package/tools/sv-vector-harness.js +19 -4
- package/version.js +1 -1
|
@@ -98,11 +98,34 @@ Interpreter.prototype._verifyCore = function (scriptSig, scriptPubkey, tx, nin,
|
|
|
98
98
|
})
|
|
99
99
|
var stackCopy
|
|
100
100
|
|
|
101
|
-
|
|
102
|
-
|
|
101
|
+
// A UTXO cannot be post-Chronicle without being post-Genesis. The node refuses the
|
|
102
|
+
// combination outright (valid_flags, interpreter.cpp) rather than picking an era.
|
|
103
|
+
if ((flags & Interpreter.SCRIPT_UTXO_AFTER_CHRONICLE) !== 0 &&
|
|
104
|
+
(flags & Interpreter.SCRIPT_UTXO_AFTER_GENESIS) === 0) {
|
|
105
|
+
this.errstr = 'SCRIPT_ERR_INVALID_FLAGS'
|
|
103
106
|
return false
|
|
104
107
|
}
|
|
105
108
|
|
|
109
|
+
// SIGPUSHONLY is a rule of an era, not of the flag alone:
|
|
110
|
+
//
|
|
111
|
+
// if((IsGenesis(flags) && !IsChronicle(flags)) ||
|
|
112
|
+
// (IsChronicle(flags) && !IsMalleableTxnVersion(checker.Version())))
|
|
113
|
+
//
|
|
114
|
+
// Before Genesis this branch refused nothing — a non-push scriptSig was caught only where
|
|
115
|
+
// P2SH demanded it, below — and the node never sets the flag there anyway
|
|
116
|
+
// (InputScriptVerifyFlags adds it only once the block era is post-Genesis). Under
|
|
117
|
+
// Chronicle it survives as a non-malleability rule, so a malleable version is exempt,
|
|
118
|
+
// and that case DOES arise on today's mainnet flags.
|
|
119
|
+
if ((flags & Interpreter.SCRIPT_VERIFY_SIGPUSHONLY) !== 0) {
|
|
120
|
+
var chronicleBlock = (flags & Interpreter.SCRIPT_CHRONICLE) !== 0
|
|
121
|
+
var pushOnlyRequired = (((flags & Interpreter.SCRIPT_GENESIS) !== 0) && !chronicleBlock) ||
|
|
122
|
+
(chronicleBlock && enforcesNonMalleability(flags, tx))
|
|
123
|
+
if (pushOnlyRequired && !scriptSig.isPushOnly()) {
|
|
124
|
+
this.errstr = 'SCRIPT_ERR_SIG_PUSHONLY'
|
|
125
|
+
return false
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
106
129
|
// evaluate scriptSig
|
|
107
130
|
if (!this.evaluate()) {
|
|
108
131
|
return false
|
|
@@ -197,18 +220,25 @@ Interpreter.prototype._verifyCore = function (scriptSig, scriptPubkey, tx, nin,
|
|
|
197
220
|
// Disallow CLEANSTACK without P2SH, as otherwise a switch
|
|
198
221
|
// CLEANSTACK->P2SH+CLEANSTACK would be possible, which is not a
|
|
199
222
|
// softfork (and P2SH should be one).
|
|
200
|
-
//
|
|
201
|
-
//
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
223
|
+
// The flags come from a caller, so this is a bad request rather than a broken
|
|
224
|
+
// invariant. The node names it (SCRIPT_ERR_INVALID_FLAGS); throwing turned a verdict
|
|
225
|
+
// into a crash. It requires the P2SH flag in every era, including after Genesis removed
|
|
226
|
+
// P2SH, and its own corpus never reaches this branch because the harness adds the flag
|
|
227
|
+
// (`if(flags & SCRIPT_VERIFY_CLEANSTACK) flags |= SCRIPT_VERIFY_P2SH;` in DoTest,
|
|
228
|
+
// src/test/script_tests.cpp) — which is why this used to carry a post-Genesis carve-out
|
|
229
|
+
// that let the pair through. That was ours, not the node's.
|
|
230
|
+
if ((flags & Interpreter.SCRIPT_VERIFY_P2SH) === 0) {
|
|
231
|
+
this.errstr = 'SCRIPT_ERR_INVALID_FLAGS'
|
|
232
|
+
return false
|
|
205
233
|
}
|
|
206
234
|
|
|
207
235
|
// The final stack. After a P2SH evaluation that is stackCopy itself, since
|
|
208
236
|
// the redeem script was evaluated over it, but reading stackCopy directly
|
|
209
237
|
// is wrong once P2SH no longer applies: it is then either the stack as it
|
|
210
238
|
// stood after the scriptSig, or never assigned at all.
|
|
211
|
-
|
|
239
|
+
// Clean stack was only ever a policy rule, never consensus, so Chronicle ties it to
|
|
240
|
+
// the transaction version rather than to the age of the output being spent.
|
|
241
|
+
if (this.enforceNonMalleability() && this.stack.length !== 1) {
|
|
212
242
|
this.errstr = 'SCRIPT_ERR_CLEANSTACK'
|
|
213
243
|
return false
|
|
214
244
|
}
|
|
@@ -841,6 +871,37 @@ Interpreter.castToBool = function (buf) {
|
|
|
841
871
|
/**
|
|
842
872
|
* Translated from bitcoind's CheckSignatureEncoding
|
|
843
873
|
*/
|
|
874
|
+
/**
|
|
875
|
+
* Chronicle lets a transaction opt into malleability by using a version above 1, and the
|
|
876
|
+
* rules that exist only to stop a signed transaction being rewritten in flight then stop
|
|
877
|
+
* applying to it. The node's EnforceNonMalleability(flags, checker.Version()):
|
|
878
|
+
*
|
|
879
|
+
* return !(IsChronicle(flags) && IsMalleableTxnVersion(txnVersion)); // version > 1
|
|
880
|
+
*
|
|
881
|
+
* It gates LOW_S, MINIMALDATA, MINIMALIF, NULLFAIL, NULLDUMMY, SIGPUSHONLY and CLEANSTACK.
|
|
882
|
+
* Note which era flag it reads: SCRIPT_CHRONICLE, the era of the block being built, not
|
|
883
|
+
* SCRIPT_UTXO_AFTER_CHRONICLE, the era of the output being spent.
|
|
884
|
+
*
|
|
885
|
+
* Every version at or below 1 is non-malleable, so the rules apply; a missing transaction
|
|
886
|
+
* is treated the same way, which is the enforcing answer.
|
|
887
|
+
*/
|
|
888
|
+
function enforcesNonMalleability (flags, tx) {
|
|
889
|
+
if ((flags & Interpreter.SCRIPT_CHRONICLE) === 0) {
|
|
890
|
+
return true
|
|
891
|
+
}
|
|
892
|
+
// int32, as CTransaction::nVersion is and as checker.Version() returns it. Comparing the
|
|
893
|
+
// JS number would read a version of 0xffffffff as 4294967295 and call the transaction
|
|
894
|
+
// malleable, where the node reads -1 and enforces. Such a version cannot arrive from the
|
|
895
|
+
// network — writeInt32LE refuses it and readInt32LE has already signed anything parsed —
|
|
896
|
+
// but a caller can set it in code, and the fail-open reading is the wrong one to have.
|
|
897
|
+
// With no transaction at all the rules apply: BaseSignatureChecker::Version() returns 0.
|
|
898
|
+
return !(tx && ((tx.version | 0) > 1))
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
Interpreter.prototype.enforceNonMalleability = function () {
|
|
902
|
+
return enforcesNonMalleability(this.flags, this.tx)
|
|
903
|
+
}
|
|
904
|
+
|
|
844
905
|
Interpreter.prototype.checkSignatureEncoding = function (buf) {
|
|
845
906
|
var sig
|
|
846
907
|
|
|
@@ -850,16 +911,26 @@ Interpreter.prototype.checkSignatureEncoding = function (buf) {
|
|
|
850
911
|
return true
|
|
851
912
|
}
|
|
852
913
|
|
|
914
|
+
// Three independent checks, as CheckSignatureEncoding has them. They used to be chained
|
|
915
|
+
// with else-if, so LOW_S — which mainnetFlags() and currentConsensusFlags() both set —
|
|
916
|
+
// returned early and the whole STRICTENC block below never ran. On the library's own
|
|
917
|
+
// default flags that silently accepted a signature with an undefined hash type, one
|
|
918
|
+
// without FORKID where FORKID is required, and one asking for the Chronicle digest
|
|
919
|
+
// outside Chronicle: three things the node refuses by name.
|
|
853
920
|
if ((this.flags & (Interpreter.SCRIPT_VERIFY_DERSIG | Interpreter.SCRIPT_VERIFY_LOW_S | Interpreter.SCRIPT_VERIFY_STRICTENC)) !== 0 && !Signature.isTxDER(buf)) {
|
|
854
921
|
this.errstr = 'SCRIPT_ERR_SIG_DER_INVALID_FORMAT'
|
|
855
922
|
return false
|
|
856
|
-
}
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
if ((this.flags & Interpreter.SCRIPT_VERIFY_LOW_S) !== 0) {
|
|
857
926
|
sig = Signature.fromTxFormat(buf)
|
|
858
|
-
if (!sig.hasLowS()) {
|
|
927
|
+
if (!sig.hasLowS() && this.enforceNonMalleability()) {
|
|
859
928
|
this.errstr = 'SCRIPT_ERR_SIG_DER_HIGH_S'
|
|
860
929
|
return false
|
|
861
930
|
}
|
|
862
|
-
}
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
if ((this.flags & Interpreter.SCRIPT_VERIFY_STRICTENC) !== 0) {
|
|
863
934
|
sig = Signature.fromTxFormat(buf)
|
|
864
935
|
if (!sig.hasDefinedHashtype()) {
|
|
865
936
|
this.errstr = 'SCRIPT_ERR_SIG_HASHTYPE'
|
|
@@ -1344,27 +1415,40 @@ Interpreter.prototype.step = function () {
|
|
|
1344
1415
|
switch (opcode) {
|
|
1345
1416
|
case Opcode.OP_2MUL:
|
|
1346
1417
|
case Opcode.OP_2DIV:
|
|
1347
|
-
// Chronicle restores both
|
|
1348
|
-
//
|
|
1349
|
-
//
|
|
1350
|
-
//
|
|
1418
|
+
// Chronicle restores both; until the UTXO is post-Chronicle they stay disabled.
|
|
1419
|
+
//
|
|
1420
|
+
// "Disabled" is stronger than "unimplemented", but only before Genesis. The node reads
|
|
1421
|
+
//
|
|
1422
|
+
// if(IsOpcodeDisabled(opcode, utxoEra) && (!utxo_after_genesis || fExec))
|
|
1423
|
+
// return SCRIPT_ERR_DISABLED_OPCODE;
|
|
1424
|
+
//
|
|
1425
|
+
// so a disabled opcode in an UNEXECUTED branch fails a pre-Genesis spend and is harmless
|
|
1426
|
+
// in a post-Genesis one. That is why this lives in isOpcodeDisabled, which the caller
|
|
1427
|
+
// consults before testing fExec — the era decides, not the branch alone. An earlier
|
|
1428
|
+
// version of this comment said it fails unexecuted in every era, which is half the rule.
|
|
1351
1429
|
if (!self.isAfterChronicle()) {
|
|
1352
1430
|
return true
|
|
1353
1431
|
}
|
|
1354
1432
|
break
|
|
1355
1433
|
|
|
1434
|
+
// Restored on BSV and never gated by the node. Monolith came back in May 2018 and
|
|
1435
|
+
// Magnetic in November 2018, and IsOpcodeDisabled (src/script/interpreter.cpp) disables
|
|
1436
|
+
// OP_2MUL and OP_2DIV and nothing else — so every opcode below executes in every era the
|
|
1437
|
+
// node can validate, with no flag to enable.
|
|
1438
|
+
//
|
|
1439
|
+
// The four Magnetic ones used to be refused here unless SCRIPT_ENABLE_MAGNETIC_OPCODES
|
|
1440
|
+
// was set, "for backwards compatibility". That refused 77 rows of the node's own corpus
|
|
1441
|
+
// as DISABLED_OPCODE. Fail-closed, so nothing was at risk of being accepted wrongly, but
|
|
1442
|
+
// they were spends the network accepts. The Monolith group beside them had already made
|
|
1443
|
+
// the opposite call on identical reasoning, so the two halves of one 2018 upgrade
|
|
1444
|
+
// disagreed with each other.
|
|
1445
|
+
//
|
|
1446
|
+
// SCRIPT_ENABLE_MAGNETIC_OPCODES and SCRIPT_ENABLE_MONOLITH_OPCODES remain exported and
|
|
1447
|
+
// accepted — they are public API — and setting either is now simply redundant.
|
|
1356
1448
|
case Opcode.OP_INVERT:
|
|
1357
1449
|
case Opcode.OP_MUL:
|
|
1358
1450
|
case Opcode.OP_LSHIFT:
|
|
1359
1451
|
case Opcode.OP_RSHIFT:
|
|
1360
|
-
// Magnetic opcodes - still require flag for backwards compatibility
|
|
1361
|
-
if ((self.flags & Interpreter.SCRIPT_ENABLE_MAGNETIC_OPCODES) === 0) {
|
|
1362
|
-
return true
|
|
1363
|
-
}
|
|
1364
|
-
break
|
|
1365
|
-
|
|
1366
|
-
// Monolith opcodes are now enabled by default in SmartLedger BSV
|
|
1367
|
-
// These were activated in May 2018 and are part of standard BSV consensus
|
|
1368
1452
|
case Opcode.OP_DIV:
|
|
1369
1453
|
case Opcode.OP_MOD:
|
|
1370
1454
|
case Opcode.OP_SPLIT:
|
|
@@ -1374,7 +1458,6 @@ Interpreter.prototype.step = function () {
|
|
|
1374
1458
|
case Opcode.OP_XOR:
|
|
1375
1459
|
case Opcode.OP_BIN2NUM:
|
|
1376
1460
|
case Opcode.OP_NUM2BIN:
|
|
1377
|
-
// These opcodes are now always enabled - no flag required
|
|
1378
1461
|
return false
|
|
1379
1462
|
|
|
1380
1463
|
default:
|
|
@@ -1384,7 +1467,8 @@ Interpreter.prototype.step = function () {
|
|
|
1384
1467
|
return false
|
|
1385
1468
|
}
|
|
1386
1469
|
|
|
1387
|
-
var fRequireMinimal = (this.flags & Interpreter.SCRIPT_VERIFY_MINIMALDATA) !== 0
|
|
1470
|
+
var fRequireMinimal = (this.flags & Interpreter.SCRIPT_VERIFY_MINIMALDATA) !== 0 &&
|
|
1471
|
+
this.enforceNonMalleability()
|
|
1388
1472
|
|
|
1389
1473
|
var buf, buf1, buf2, spliced, n, x1, x2, bn, bn1, bn2, bufSig, bufPubkey, subscript
|
|
1390
1474
|
var sig, pubkey
|
|
@@ -1770,15 +1854,11 @@ Interpreter.prototype.step = function () {
|
|
|
1770
1854
|
}
|
|
1771
1855
|
buf = stacktop(-1)
|
|
1772
1856
|
|
|
1773
|
-
if (this.flags & Interpreter.SCRIPT_VERIFY_MINIMALIF)
|
|
1774
|
-
|
|
1775
|
-
this.
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
if (buf.length === 1 && buf[0] !== 1) {
|
|
1779
|
-
this.errstr = 'SCRIPT_ERR_MINIMALIF'
|
|
1780
|
-
return false
|
|
1781
|
-
}
|
|
1857
|
+
if ((this.flags & Interpreter.SCRIPT_VERIFY_MINIMALIF) &&
|
|
1858
|
+
(buf.length > 1 || (buf.length === 1 && buf[0] !== 1)) &&
|
|
1859
|
+
this.enforceNonMalleability()) {
|
|
1860
|
+
this.errstr = 'SCRIPT_ERR_MINIMALIF'
|
|
1861
|
+
return false
|
|
1782
1862
|
}
|
|
1783
1863
|
fValue = Interpreter.castToBool(buf)
|
|
1784
1864
|
if (opcodenum === Opcode.OP_NOTIF) {
|
|
@@ -2457,7 +2537,7 @@ Interpreter.prototype.step = function () {
|
|
|
2457
2537
|
}
|
|
2458
2538
|
|
|
2459
2539
|
if (!fSuccess && (this.flags & Interpreter.SCRIPT_VERIFY_NULLFAIL) &&
|
|
2460
|
-
bufSig.length) {
|
|
2540
|
+
bufSig.length && this.enforceNonMalleability()) {
|
|
2461
2541
|
this.errstr = 'SCRIPT_ERR_NULLFAIL'
|
|
2462
2542
|
return false
|
|
2463
2543
|
}
|
|
@@ -2487,7 +2567,17 @@ Interpreter.prototype.step = function () {
|
|
|
2487
2567
|
return false
|
|
2488
2568
|
}
|
|
2489
2569
|
|
|
2490
|
-
|
|
2570
|
+
// FOUR bytes, not the era's length. The node hardcodes it and says why:
|
|
2571
|
+
//
|
|
2572
|
+
// // initialize to max size of CScriptNum::MAXIMUM_ELEMENT_SIZE (4 bytes)
|
|
2573
|
+
// // because only 4 byte integers are supported by OP_CHECKMULTISIG / OP_CHECKMULTISIGVERIFY
|
|
2574
|
+
// nKeysCountSigned = CScriptNum(stack.stacktop(-i).GetElement(), requireMinimal,
|
|
2575
|
+
// CScriptNum::MAXIMUM_ELEMENT_SIZE).getint();
|
|
2576
|
+
//
|
|
2577
|
+
// So it is era-independent, unlike every other operand decode in this file. Passing
|
|
2578
|
+
// maxScriptNumLength() here accepted a 5-byte count that the node refuses as
|
|
2579
|
+
// SCRIPTNUM_OVERFLOW in every era — a false accept, the direction that costs money.
|
|
2580
|
+
var nKeysCount = BN.fromScriptNumBuffer(stacktop(-i), fRequireMinimal, 4).toNumber()
|
|
2491
2581
|
// TODO: Keys and opcount are parameterized in client. No magic numbers!
|
|
2492
2582
|
// Genesis raised this to UINT32_MAX rather than removing it.
|
|
2493
2583
|
if (nKeysCount < 0 || nKeysCount > this.maxPubKeysPerMultisig()) {
|
|
@@ -2521,7 +2611,8 @@ Interpreter.prototype.step = function () {
|
|
|
2521
2611
|
return false
|
|
2522
2612
|
}
|
|
2523
2613
|
|
|
2524
|
-
|
|
2614
|
+
// Four bytes, for the same reason as nKeysCount above.
|
|
2615
|
+
var nSigsCount = BN.fromScriptNumBuffer(stacktop(-i), fRequireMinimal, 4).toNumber()
|
|
2525
2616
|
if (nSigsCount < 0 || nSigsCount > nKeysCount) {
|
|
2526
2617
|
this.errstr = 'SCRIPT_ERR_SIG_COUNT'
|
|
2527
2618
|
return false
|
|
@@ -2583,7 +2674,7 @@ Interpreter.prototype.step = function () {
|
|
|
2583
2674
|
// Clean up stack of actual arguments
|
|
2584
2675
|
while (i-- > 1) {
|
|
2585
2676
|
if (!fSuccess && (this.flags & Interpreter.SCRIPT_VERIFY_NULLFAIL) &&
|
|
2586
|
-
!ikey2 && stacktop(-1).length) {
|
|
2677
|
+
!ikey2 && stacktop(-1).length && this.enforceNonMalleability()) {
|
|
2587
2678
|
this.errstr = 'SCRIPT_ERR_NULLFAIL'
|
|
2588
2679
|
return false
|
|
2589
2680
|
}
|
|
@@ -2605,7 +2696,8 @@ Interpreter.prototype.step = function () {
|
|
|
2605
2696
|
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'
|
|
2606
2697
|
return false
|
|
2607
2698
|
}
|
|
2608
|
-
if ((this.flags & Interpreter.SCRIPT_VERIFY_NULLDUMMY) && stacktop(-1).length
|
|
2699
|
+
if ((this.flags & Interpreter.SCRIPT_VERIFY_NULLDUMMY) && stacktop(-1).length &&
|
|
2700
|
+
this.enforceNonMalleability()) {
|
|
2609
2701
|
this.errstr = 'SCRIPT_ERR_SIG_NULLDUMMY'
|
|
2610
2702
|
return false
|
|
2611
2703
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smartledger/bsv",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.16.0",
|
|
4
4
|
"description": "Bitcoin SV library with an interpreter-verified script engine: OP_PUSH_TX covenants, BIP-143 preimage tooling, and consensus flags that match what miners actually enforce. Also ships DID:web / W3C VC-JWT credentials and the Legal Token Protocol.",
|
|
5
5
|
"author": "SmartLedger Technology <hello@smartledger.technology> (https://smartledger.technology)",
|
|
6
6
|
"homepage": "https://github.com/codenlighten/smartledger-bsv#readme",
|
|
@@ -145,7 +145,8 @@
|
|
|
145
145
|
"check:dts": "node scripts/check-dts-coverage.js",
|
|
146
146
|
"check:audit-scope": "node scripts/check-audit-scope.js",
|
|
147
147
|
"check:audit-scope:fix": "node scripts/check-audit-scope.js --fix",
|
|
148
|
-
"check:dts:update": "node scripts/check-dts-coverage.js --update"
|
|
148
|
+
"check:dts:update": "node scripts/check-dts-coverage.js --update",
|
|
149
|
+
"vectors:sv-coverage": "node tools/sv-vector-coverage.js"
|
|
149
150
|
},
|
|
150
151
|
"unpkg": "bsv.min.js",
|
|
151
152
|
"jsdelivr": "bsv.min.js",
|
|
@@ -243,13 +244,16 @@
|
|
|
243
244
|
"vm-browserify": "^1.1.2"
|
|
244
245
|
},
|
|
245
246
|
"overrides": {
|
|
246
|
-
"js-yaml@^3": "^3.15.
|
|
247
|
-
"js-yaml@^4": "^4.3.
|
|
247
|
+
"js-yaml@^3": "^3.15.2",
|
|
248
|
+
"js-yaml@^4": "^4.3.2",
|
|
248
249
|
"serialize-javascript": "^7.0.5",
|
|
249
250
|
"tmp": "^0.2.7",
|
|
250
251
|
"mocha": {
|
|
251
252
|
"diff": "^8.0.3"
|
|
252
|
-
}
|
|
253
|
+
},
|
|
254
|
+
"brace-expansion": "^2.0.2",
|
|
255
|
+
"browserslist": "^4.28.7",
|
|
256
|
+
"baseline-browser-mapping": "^2.11.0"
|
|
253
257
|
},
|
|
254
258
|
"license": "MIT",
|
|
255
259
|
"standard": {
|