@offckb/cli 0.4.9-canary-2b6b3af.0 → 0.4.9
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/README.md +77 -23
- package/build/index.js +2270 -670
- package/package.json +2 -2
package/build/index.js
CHANGED
|
@@ -353,6 +353,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
353
353
|
});
|
|
354
354
|
};
|
|
355
355
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
356
|
+
exports.runCli = runCli;
|
|
356
357
|
const commander_1 = __nccwpck_require__(53497);
|
|
357
358
|
const node_1 = __nccwpck_require__(998);
|
|
358
359
|
const accounts_1 = __nccwpck_require__(87398);
|
|
@@ -366,6 +367,8 @@ const udt_1 = __nccwpck_require__(50703);
|
|
|
366
367
|
const create_1 = __nccwpck_require__(51534);
|
|
367
368
|
const config_1 = __nccwpck_require__(93004);
|
|
368
369
|
const devnet_config_1 = __nccwpck_require__(10015);
|
|
370
|
+
const devnet_fork_1 = __nccwpck_require__(36709);
|
|
371
|
+
const devnet_info_1 = __nccwpck_require__(60905);
|
|
369
372
|
const debug_1 = __nccwpck_require__(39591);
|
|
370
373
|
const system_scripts_1 = __nccwpck_require__(86198);
|
|
371
374
|
const transfer_all_1 = __nccwpck_require__(92039);
|
|
@@ -373,16 +376,26 @@ const gen_1 = __nccwpck_require__(750);
|
|
|
373
376
|
const ckb_debugger_1 = __nccwpck_require__(14815);
|
|
374
377
|
const logger_1 = __nccwpck_require__(65370);
|
|
375
378
|
const status_1 = __nccwpck_require__(71420);
|
|
376
|
-
const validator_1 = __nccwpck_require__(39534);
|
|
377
379
|
const version = (__nccwpck_require__(8330)/* .version */ .rE);
|
|
378
380
|
const description = (__nccwpck_require__(8330)/* .description */ .h_);
|
|
379
381
|
// fix windows terminal encoding of simplified chinese text
|
|
380
382
|
(0, encoding_1.setUTF8EncodingForWindows)();
|
|
381
383
|
const program = new commander_1.Command();
|
|
382
384
|
program.name('offckb').description(description).version(version).enablePositionalOptions();
|
|
385
|
+
let activeCommand = 'offckb';
|
|
386
|
+
function commandPath(command) {
|
|
387
|
+
const names = [];
|
|
388
|
+
let current = command;
|
|
389
|
+
while (current === null || current === void 0 ? void 0 : current.parent) {
|
|
390
|
+
names.unshift(current.name());
|
|
391
|
+
current = current.parent;
|
|
392
|
+
}
|
|
393
|
+
return names.join('.') || 'offckb';
|
|
394
|
+
}
|
|
383
395
|
program.option('--json', 'Output logs in JSON format for agent/programmatic consumption');
|
|
384
|
-
program.hook('preAction', (
|
|
385
|
-
|
|
396
|
+
program.hook('preAction', (_thisCommand, actionCommand) => {
|
|
397
|
+
activeCommand = commandPath(actionCommand);
|
|
398
|
+
const opts = actionCommand.optsWithGlobals();
|
|
386
399
|
if (opts.json) {
|
|
387
400
|
logger_1.logger.setJsonMode(true);
|
|
388
401
|
}
|
|
@@ -419,7 +432,8 @@ program
|
|
|
419
432
|
.option('--target <target>', 'Specify the script binaries file/folder path to deploy', './')
|
|
420
433
|
.option('-o, --output <output>', 'Specify the output folder path for the deployment record files', './deployment')
|
|
421
434
|
.option('-t, --type-id', 'Specify if use upgradable type id to deploy the script')
|
|
422
|
-
.option('--privkey <privkey>', 'Specify the private key to deploy scripts')
|
|
435
|
+
.option('--privkey <privkey>', 'Specify the private key to deploy scripts (visible in shell history)')
|
|
436
|
+
.option('--privkey-file <path>', 'Read the private key from a local file')
|
|
423
437
|
.option('-y, --yes', 'Skip confirmation prompt and deploy immediately')
|
|
424
438
|
.action((options) => (0, deploy_1.deploy)(options));
|
|
425
439
|
program
|
|
@@ -432,8 +446,7 @@ program
|
|
|
432
446
|
.action((option) => __awaiter(void 0, void 0, void 0, function* () {
|
|
433
447
|
// For debugging, tx-hash is required
|
|
434
448
|
if (!option.txHash) {
|
|
435
|
-
|
|
436
|
-
process.exit(1);
|
|
449
|
+
throw new Error('--tx-hash is required for debugging operations');
|
|
437
450
|
}
|
|
438
451
|
const txHash = option.txHash;
|
|
439
452
|
if (option.singleScript) {
|
|
@@ -463,34 +476,43 @@ program
|
|
|
463
476
|
.description('Clean the devnet data, need to stop running the chain first')
|
|
464
477
|
.option('-d, --data', 'Only remove chain data, keep devnet config files')
|
|
465
478
|
.action((options) => (0, clean_1.clean)(options));
|
|
466
|
-
program
|
|
479
|
+
program
|
|
480
|
+
.command('accounts')
|
|
481
|
+
.description('Print account list info')
|
|
482
|
+
.option('--show-private-keys', 'Include built-in dev private keys (hidden by default)')
|
|
483
|
+
.action((options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
484
|
+
yield (0, accounts_1.accounts)(options);
|
|
485
|
+
}));
|
|
467
486
|
program
|
|
468
487
|
.command('deposit [toAddress] [amountInCKB]')
|
|
469
488
|
.description('Deposit CKB tokens to address, only devnet and testnet')
|
|
470
489
|
.option('--network <network>', 'Specify the network to deposit to', 'devnet')
|
|
471
490
|
.option('-r, --proxy-rpc', 'Use Proxy RPC to connect to blockchain')
|
|
472
491
|
.action((toAddress, amountInCKB, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
473
|
-
|
|
492
|
+
yield (0, deposit_1.deposit)(toAddress, amountInCKB, options);
|
|
474
493
|
}));
|
|
475
494
|
program
|
|
476
495
|
.command('transfer [toAddress] [amount]')
|
|
477
496
|
.description('Transfer CKB or UDT tokens to address, only devnet and testnet')
|
|
478
497
|
.option('--network <network>', 'Specify the network to transfer to', 'devnet')
|
|
479
|
-
.option('--privkey <privkey>', 'Specify the private key to transfer')
|
|
480
|
-
.
|
|
498
|
+
.option('--privkey <privkey>', 'Specify the private key to transfer (visible in shell history)')
|
|
499
|
+
.option('--privkey-file <path>', 'Read the private key from a local file')
|
|
500
|
+
.addOption(new commander_1.Option('--udt-kind <kind>', 'Specify the UDT kind').choices(['sudt', 'xudt']))
|
|
481
501
|
.option('--udt-type-args <typeArgs>', 'Specify the UDT type script args to transfer UDT')
|
|
502
|
+
.option('--allow-mainnet-replay-risk', 'Allow a non-built-in key on a Mainnet fork (copied inputs remain blocked)')
|
|
482
503
|
.option('-r, --proxy-rpc', 'Use Proxy RPC to connect to blockchain')
|
|
483
504
|
.action((toAddress, amount, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
484
|
-
|
|
505
|
+
yield (0, transfer_1.transfer)(toAddress, amount, options);
|
|
485
506
|
}));
|
|
486
507
|
program
|
|
487
508
|
.command('transfer-all [toAddress]')
|
|
488
509
|
.description('Transfer All CKB tokens to address, only devnet and testnet')
|
|
489
510
|
.option('--network <network>', 'Specify the network to transfer to', 'devnet')
|
|
490
|
-
.option('--privkey <privkey>', 'Specify the private key
|
|
511
|
+
.option('--privkey <privkey>', 'Specify the private key (visible in shell history)')
|
|
512
|
+
.option('--privkey-file <path>', 'Read the private key from a local file')
|
|
491
513
|
.option('-r, --proxy-rpc', 'Use Proxy RPC to connect to blockchain')
|
|
492
514
|
.action((toAddress, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
493
|
-
|
|
515
|
+
yield (0, transfer_all_1.transferAll)(toAddress, options);
|
|
494
516
|
}));
|
|
495
517
|
program
|
|
496
518
|
.command('balance [toAddress]')
|
|
@@ -500,7 +522,7 @@ program
|
|
|
500
522
|
.option('--udt-type-args <typeArgs>', 'Filter by UDT type script args')
|
|
501
523
|
.option('--no-udt', 'Skip UDT balance scan')
|
|
502
524
|
.action((toAddress, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
503
|
-
|
|
525
|
+
yield (0, balance_1.balanceOf)(toAddress, options);
|
|
504
526
|
}));
|
|
505
527
|
const udtCommand = program.command('udt').description('UDT token commands');
|
|
506
528
|
udtCommand
|
|
@@ -510,9 +532,10 @@ udtCommand
|
|
|
510
532
|
.addOption(new commander_1.Option('--udt-kind <kind>', 'Specify the UDT kind').choices(['sudt', 'xudt']).default('sudt'))
|
|
511
533
|
.option('--type-args <typeArgs>', 'Specify the UDT type script args (xudt only; defaults to signer lock hash)')
|
|
512
534
|
.option('--to <toAddress>', 'Specify the receiver address (defaults to signer)')
|
|
513
|
-
.option('--privkey <privkey>', 'Specify the private key to issue UDT')
|
|
535
|
+
.option('--privkey <privkey>', 'Specify the private key to issue UDT (visible in shell history)')
|
|
536
|
+
.option('--privkey-file <path>', 'Read the private key from a local file')
|
|
514
537
|
.action((amount, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
515
|
-
|
|
538
|
+
yield (0, udt_1.udtIssue)(amount, options);
|
|
516
539
|
}));
|
|
517
540
|
udtCommand
|
|
518
541
|
.command('destroy <amount>')
|
|
@@ -520,9 +543,10 @@ udtCommand
|
|
|
520
543
|
.option('--network <network>', 'Specify the network', 'devnet')
|
|
521
544
|
.addOption(new commander_1.Option('--udt-kind <kind>', 'Specify the UDT kind').choices(['sudt', 'xudt']).default('sudt'))
|
|
522
545
|
.requiredOption('--type-args <typeArgs>', 'Specify the UDT type script args')
|
|
523
|
-
.option('--privkey <privkey>', 'Specify the private key to destroy UDT')
|
|
546
|
+
.option('--privkey <privkey>', 'Specify the private key to destroy UDT (visible in shell history)')
|
|
547
|
+
.option('--privkey-file <path>', 'Read the private key from a local file')
|
|
524
548
|
.action((amount, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
525
|
-
|
|
549
|
+
yield (0, udt_1.udtDestroy)(amount, options);
|
|
526
550
|
}));
|
|
527
551
|
program
|
|
528
552
|
.command('debugger')
|
|
@@ -536,10 +560,11 @@ program
|
|
|
536
560
|
program
|
|
537
561
|
.command('status')
|
|
538
562
|
.description('Show ckb-tui status interface')
|
|
539
|
-
.
|
|
563
|
+
.addOption(new commander_1.Option('--network <network>', 'Specify the network whose node status to monitor')
|
|
564
|
+
.choices(['devnet', 'testnet', 'mainnet'])
|
|
565
|
+
.default('devnet'))
|
|
540
566
|
.action((option) => __awaiter(void 0, void 0, void 0, function* () {
|
|
541
|
-
(0,
|
|
542
|
-
return yield (0, status_1.status)({ network: option.network });
|
|
567
|
+
yield (0, status_1.status)({ network: option.network });
|
|
543
568
|
}));
|
|
544
569
|
program
|
|
545
570
|
.command('config <action> [item] [value]')
|
|
@@ -551,10 +576,77 @@ devnetCommand
|
|
|
551
576
|
.description('Open a full-screen editor to tweak devnet config files')
|
|
552
577
|
.option('-s, --set <key=value>', 'Set a devnet config field non-interactively (repeatable), e.g. --set ckb.logger.filter=info', (value, previous = []) => [...previous, value], [])
|
|
553
578
|
.action(devnet_config_1.devnetConfig);
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
579
|
+
devnetCommand
|
|
580
|
+
.command('info')
|
|
581
|
+
.description('Show fork metadata and node/indexer readiness')
|
|
582
|
+
.action(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
583
|
+
yield (0, devnet_info_1.devnetInfo)();
|
|
584
|
+
}));
|
|
585
|
+
devnetCommand
|
|
586
|
+
.command('fork')
|
|
587
|
+
.description('Fork an existing mainnet/testnet chain data directory into the local devnet')
|
|
588
|
+
.option('--from <dir>', 'Path to the source CKB node directory used with `ckb -C`')
|
|
589
|
+
.option('--source <source>', 'Source chain: mainnet or testnet (auto-detected from the source ckb.toml when omitted)')
|
|
590
|
+
.option('--spec-file <path>', 'Use a local chain spec file instead of downloading it')
|
|
591
|
+
.option('--force', 'Replace the existing devnet (or a previous fork)')
|
|
592
|
+
.option('--migrate', 'Migrate only the copied database when the selected CKB version requires it')
|
|
593
|
+
.option('--dry-run', 'Run source/spec/database preflight without replacing the current devnet')
|
|
594
|
+
.action(devnet_fork_1.devnetFork);
|
|
595
|
+
function normalizeGlobalJsonFlag(argv) {
|
|
596
|
+
const jsonRequested = argv.slice(2).includes('--json');
|
|
597
|
+
if (!jsonRequested)
|
|
598
|
+
return argv;
|
|
599
|
+
return [argv[0], argv[1], '--json', ...argv.slice(2).filter((arg) => arg !== '--json')];
|
|
600
|
+
}
|
|
601
|
+
function installBrokenPipeHandlers() {
|
|
602
|
+
for (const stream of [process.stdout, process.stderr]) {
|
|
603
|
+
stream.on('error', (error) => {
|
|
604
|
+
if (error.code === 'EPIPE') {
|
|
605
|
+
process.exit(0);
|
|
606
|
+
}
|
|
607
|
+
throw error;
|
|
608
|
+
});
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
function configureCommanderErrors(command) {
|
|
612
|
+
command.exitOverride();
|
|
613
|
+
command.configureOutput({
|
|
614
|
+
writeErr: (text) => {
|
|
615
|
+
if (!logger_1.logger.isJsonMode())
|
|
616
|
+
process.stderr.write(text);
|
|
617
|
+
},
|
|
618
|
+
});
|
|
619
|
+
command.commands.forEach(configureCommanderErrors);
|
|
620
|
+
}
|
|
621
|
+
function runCli() {
|
|
622
|
+
return __awaiter(this, arguments, void 0, function* (argv = process.argv) {
|
|
623
|
+
installBrokenPipeHandlers();
|
|
624
|
+
const normalizedArgv = normalizeGlobalJsonFlag(argv);
|
|
625
|
+
if (normalizedArgv.includes('--json'))
|
|
626
|
+
logger_1.logger.setJsonMode(true);
|
|
627
|
+
if (!normalizedArgv.slice(2).length) {
|
|
628
|
+
program.outputHelp();
|
|
629
|
+
return;
|
|
630
|
+
}
|
|
631
|
+
configureCommanderErrors(program);
|
|
632
|
+
try {
|
|
633
|
+
yield program.parseAsync(normalizedArgv);
|
|
634
|
+
if (logger_1.logger.isJsonMode() && !logger_1.logger.hasResult() && (process.exitCode == null || process.exitCode === 0)) {
|
|
635
|
+
logger_1.logger.result({ command: activeCommand, completed: true });
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
catch (error) {
|
|
639
|
+
if (error instanceof commander_1.CommanderError && error.exitCode === 0)
|
|
640
|
+
return;
|
|
641
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
642
|
+
const code = error instanceof commander_1.CommanderError ? error.code : 'COMMAND_FAILED';
|
|
643
|
+
logger_1.logger.failure(code, message);
|
|
644
|
+
process.exitCode = error instanceof commander_1.CommanderError ? error.exitCode : 1;
|
|
645
|
+
}
|
|
646
|
+
});
|
|
647
|
+
}
|
|
648
|
+
if (require.main === require.cache[eval('__filename')]) {
|
|
649
|
+
void runCli();
|
|
558
650
|
}
|
|
559
651
|
|
|
560
652
|
|
|
@@ -565,40 +657,90 @@ if (!process.argv.slice(2).length) {
|
|
|
565
657
|
|
|
566
658
|
"use strict";
|
|
567
659
|
|
|
660
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
661
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
662
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
663
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
664
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
665
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
666
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
667
|
+
});
|
|
668
|
+
};
|
|
568
669
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
569
670
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
570
671
|
};
|
|
571
672
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
572
673
|
exports.accounts = accounts;
|
|
573
674
|
const account_json_1 = __importDefault(__nccwpck_require__(13849));
|
|
675
|
+
const core_1 = __nccwpck_require__(39842);
|
|
676
|
+
const setting_1 = __nccwpck_require__(25546);
|
|
677
|
+
const fork_1 = __nccwpck_require__(77912);
|
|
678
|
+
const readiness_1 = __nccwpck_require__(19326);
|
|
679
|
+
const base_1 = __nccwpck_require__(69951);
|
|
574
680
|
const logger_1 = __nccwpck_require__(65370);
|
|
575
681
|
function accounts() {
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
`privkey: ${account.privkey}`,
|
|
591
|
-
`pubkey: ${account.pubkey}`,
|
|
592
|
-
`lock_arg: ${account.lockScript.args}`,
|
|
593
|
-
'lockScript:',
|
|
594
|
-
` codeHash: ${account.lockScript.codeHash}`,
|
|
595
|
-
` hashType: ${account.lockScript.hashType}`,
|
|
596
|
-
` args: ${account.lockScript.args}`,
|
|
682
|
+
return __awaiter(this, arguments, void 0, function* (options = {}) {
|
|
683
|
+
const settings = (0, setting_1.readSettings)();
|
|
684
|
+
const fork = (0, fork_1.readForkState)(settings.devnet.configPath);
|
|
685
|
+
const isMainnetFork = (fork === null || fork === void 0 ? void 0 : fork.source) === 'mainnet';
|
|
686
|
+
const client = isMainnetFork
|
|
687
|
+
? new core_1.ccc.ClientPublicMainnet({ url: settings.devnet.rpcUrl, fallbacks: [] })
|
|
688
|
+
: new core_1.ccc.ClientPublicTestnet({ url: settings.devnet.rpcUrl, fallbacks: [] });
|
|
689
|
+
const context = fork ? `DEVNET (fork of ${fork.source.toUpperCase()})` : 'DEVNET';
|
|
690
|
+
const readiness = fork ? yield (0, readiness_1.warnIfForkIndexerIsBehind)(base_1.Network.devnet) : undefined;
|
|
691
|
+
const canReadSpendableBalance = (readiness === null || readiness === void 0 ? void 0 : readiness.ready) === true && readiness.indexerTip != null && readiness.indexerLag === BigInt(0);
|
|
692
|
+
logger_1.logger.warn([
|
|
693
|
+
'#### All Accounts are for test and develop only ####'.toUpperCase(),
|
|
694
|
+
"#### DON'T use these accounts on Mainnet ####".toUpperCase(),
|
|
695
|
+
'#### Otherwise You will lose your money ####'.toUpperCase(),
|
|
597
696
|
'',
|
|
598
|
-
];
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
697
|
+
]);
|
|
698
|
+
if (fork) {
|
|
699
|
+
logger_1.logger.info([
|
|
700
|
+
`Print account list for ${context}. Addresses use the source-chain prefix.`,
|
|
701
|
+
'Forked devnets do not include the standard offckb genesis allocation; funds come from fork-mined cellbase cells.',
|
|
702
|
+
'Run `offckb devnet info` before trusting balances while the indexer catches up.',
|
|
703
|
+
'',
|
|
704
|
+
]);
|
|
705
|
+
}
|
|
706
|
+
else {
|
|
707
|
+
logger_1.logger.info([
|
|
708
|
+
'Print account list, each account is funded with 42_000_000_00000000 capacity in the devnet genesis block.',
|
|
709
|
+
'',
|
|
710
|
+
]);
|
|
711
|
+
}
|
|
712
|
+
const resolvedAccounts = yield Promise.all(account_json_1.default.map((account, index) => __awaiter(this, void 0, void 0, function* () {
|
|
713
|
+
const script = core_1.ccc.Script.from(account.lockScript);
|
|
714
|
+
const address = core_1.ccc.Address.fromScript(script, client).toString();
|
|
715
|
+
const spendableCkb = canReadSpendableBalance
|
|
716
|
+
? core_1.ccc.fixedPointToString(yield client.getBalanceSingle(script))
|
|
717
|
+
: undefined;
|
|
718
|
+
return Object.assign(Object.assign(Object.assign({ index,
|
|
719
|
+
address }, (spendableCkb == null ? {} : { spendableCkb })), (options.showPrivateKeys ? { privkey: account.privkey } : {})), { pubkey: account.pubkey, lockArg: account.lockScript.args, lockScript: account.lockScript });
|
|
720
|
+
})));
|
|
721
|
+
const accountDetails = resolvedAccounts.map((account) => {
|
|
722
|
+
return [
|
|
723
|
+
`- "#": ${account.index}`,
|
|
724
|
+
`address: ${account.address}`,
|
|
725
|
+
...('spendableCkb' in account ? [`spendable_ckb: ${account.spendableCkb}`] : []),
|
|
726
|
+
...(options.showPrivateKeys ? [`privkey: ${account.privkey}`] : []),
|
|
727
|
+
`pubkey: ${account.pubkey}`,
|
|
728
|
+
`lock_arg: ${account.lockArg}`,
|
|
729
|
+
'lockScript:',
|
|
730
|
+
` codeHash: ${account.lockScript.codeHash}`,
|
|
731
|
+
` hashType: ${account.lockScript.hashType}`,
|
|
732
|
+
` args: ${account.lockScript.args}`,
|
|
733
|
+
'',
|
|
734
|
+
];
|
|
735
|
+
});
|
|
736
|
+
accountDetails.forEach((details, _index) => {
|
|
737
|
+
logger_1.logger.info(details);
|
|
738
|
+
});
|
|
739
|
+
if (!options.showPrivateKeys) {
|
|
740
|
+
logger_1.logger.info('Private keys are hidden by default. Use --show-private-keys only in a trusted local terminal.');
|
|
741
|
+
}
|
|
742
|
+
logger_1.logger.result({ command: 'accounts', context, forked: Boolean(fork), accounts: resolvedAccounts });
|
|
743
|
+
return resolvedAccounts;
|
|
602
744
|
});
|
|
603
745
|
}
|
|
604
746
|
|
|
@@ -625,10 +767,12 @@ const ckb_1 = __nccwpck_require__(83748);
|
|
|
625
767
|
const validator_1 = __nccwpck_require__(39534);
|
|
626
768
|
const base_1 = __nccwpck_require__(69951);
|
|
627
769
|
const logger_1 = __nccwpck_require__(65370);
|
|
770
|
+
const readiness_1 = __nccwpck_require__(19326);
|
|
628
771
|
function balanceOf(address_1) {
|
|
629
772
|
return __awaiter(this, arguments, void 0, function* (address, opt = { network: base_1.Network.devnet }) {
|
|
630
773
|
const network = opt.network;
|
|
631
774
|
(0, validator_1.validateNetworkOpt)(network);
|
|
775
|
+
yield (0, readiness_1.warnIfForkIndexerIsBehind)(network);
|
|
632
776
|
const ckb = new ckb_1.CKB({ network });
|
|
633
777
|
const [balanceInCKB, udtBalances] = yield Promise.all([
|
|
634
778
|
ckb.balance(address),
|
|
@@ -642,7 +786,9 @@ function balanceOf(address_1) {
|
|
|
642
786
|
logger_1.logger.info(` ${udt.kind} (args=${udt.args}): ${udt.balance}`);
|
|
643
787
|
}
|
|
644
788
|
}
|
|
645
|
-
|
|
789
|
+
const result = { command: 'balance', network, address, ckb: balanceInCKB, udt: filtered };
|
|
790
|
+
logger_1.logger.result(result);
|
|
791
|
+
return result;
|
|
646
792
|
});
|
|
647
793
|
}
|
|
648
794
|
function filterUdtBalances(balances, opt) {
|
|
@@ -686,8 +832,7 @@ function clean(options) {
|
|
|
686
832
|
logger_1.logger.info(`Chain data cleaned. Devnet config files preserved.`);
|
|
687
833
|
}
|
|
688
834
|
catch (error) {
|
|
689
|
-
|
|
690
|
-
logger_1.logger.error(error.message);
|
|
835
|
+
throw new Error(`Failed to clean chain data. Did you stop the chain first? ${error.message}`);
|
|
691
836
|
}
|
|
692
837
|
}
|
|
693
838
|
else {
|
|
@@ -703,8 +848,7 @@ function clean(options) {
|
|
|
703
848
|
logger_1.logger.info(`Chain data cleaned.`);
|
|
704
849
|
}
|
|
705
850
|
catch (error) {
|
|
706
|
-
|
|
707
|
-
logger_1.logger.error(error.message);
|
|
851
|
+
throw new Error(`Failed to clean devnet data. Did you stop the chain first? ${error.message}`);
|
|
708
852
|
}
|
|
709
853
|
}
|
|
710
854
|
else {
|
|
@@ -761,8 +905,7 @@ function Config(action, item, value) {
|
|
|
761
905
|
const settings = (0, setting_1.readSettings)();
|
|
762
906
|
const proxy = settings.proxy;
|
|
763
907
|
if (proxy == null) {
|
|
764
|
-
logger_1.logger.info(`No Proxy.`);
|
|
765
|
-
process.exit(0);
|
|
908
|
+
return logger_1.logger.info(`No Proxy.`);
|
|
766
909
|
}
|
|
767
910
|
return logger_1.logger.info(`${request_1.Request.proxyConfigToUrl(proxy)}`);
|
|
768
911
|
}
|
|
@@ -787,7 +930,7 @@ function Config(action, item, value) {
|
|
|
787
930
|
return (0, setting_1.writeSettings)(settings);
|
|
788
931
|
}
|
|
789
932
|
catch (error) {
|
|
790
|
-
|
|
933
|
+
throw new Error(`invalid proxyURL: ${error.message}`);
|
|
791
934
|
}
|
|
792
935
|
}
|
|
793
936
|
case ConfigItem.ckbVersion: {
|
|
@@ -799,11 +942,11 @@ function Config(action, item, value) {
|
|
|
799
942
|
return (0, setting_1.writeSettings)(settings);
|
|
800
943
|
}
|
|
801
944
|
else {
|
|
802
|
-
|
|
945
|
+
throw new Error(`invalid version value, ${value}. Check available versions on https://github.com/nervosnetwork/ckb/tags`);
|
|
803
946
|
}
|
|
804
947
|
}
|
|
805
948
|
catch (error) {
|
|
806
|
-
|
|
949
|
+
throw new Error(`invalid version value: ${error.message}`);
|
|
807
950
|
}
|
|
808
951
|
}
|
|
809
952
|
default:
|
|
@@ -923,8 +1066,7 @@ function createScriptProject(name_1) {
|
|
|
923
1066
|
const fullProjectPath = path.resolve(projectPath);
|
|
924
1067
|
// Check if directory already exists
|
|
925
1068
|
if (fs.existsSync(fullProjectPath)) {
|
|
926
|
-
|
|
927
|
-
process.exit(1);
|
|
1069
|
+
throw new Error(`Directory '${projectPath}' already exists!`);
|
|
928
1070
|
}
|
|
929
1071
|
logger_1.logger.info([
|
|
930
1072
|
'📝 Project details:',
|
|
@@ -945,8 +1087,7 @@ function createScriptProject(name_1) {
|
|
|
945
1087
|
// Get template directory (adjust path based on whether we're running from source or built)
|
|
946
1088
|
const templateDir = possiblePaths.find((p) => fs.existsSync(p)) || possiblePaths[0];
|
|
947
1089
|
if (!fs.existsSync(templateDir)) {
|
|
948
|
-
|
|
949
|
-
process.exit(1);
|
|
1090
|
+
throw new Error(`Template directory not found: ${templateDir}`);
|
|
950
1091
|
}
|
|
951
1092
|
// Initialize template processor
|
|
952
1093
|
const processor = new processor_1.TemplateProcessor(templateDir);
|
|
@@ -1022,8 +1163,7 @@ function createScriptProject(name_1) {
|
|
|
1022
1163
|
}
|
|
1023
1164
|
}
|
|
1024
1165
|
catch (error) {
|
|
1025
|
-
|
|
1026
|
-
process.exit(1);
|
|
1166
|
+
throw new Error(`Failed to create project: ${error.message}`);
|
|
1027
1167
|
}
|
|
1028
1168
|
});
|
|
1029
1169
|
}
|
|
@@ -1089,6 +1229,7 @@ const path_1 = __importDefault(__nccwpck_require__(16928));
|
|
|
1089
1229
|
const advanced_1 = __nccwpck_require__(98486);
|
|
1090
1230
|
const base_1 = __nccwpck_require__(69951);
|
|
1091
1231
|
const encoding_1 = __nccwpck_require__(6851);
|
|
1232
|
+
const json_rpc_1 = __nccwpck_require__(51726);
|
|
1092
1233
|
const logger_1 = __nccwpck_require__(65370);
|
|
1093
1234
|
function debugTransaction(txHash, network) {
|
|
1094
1235
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -1159,8 +1300,8 @@ function buildTxFileOptionBy(txHash, network) {
|
|
|
1159
1300
|
if (!fs_1.default.existsSync(outputFilePath)) {
|
|
1160
1301
|
const rpc = settings[network].rpcUrl;
|
|
1161
1302
|
const txJsonFilePath = buildTransactionJsonFilePath(network, txHash);
|
|
1162
|
-
if (!fs_1.default.existsSync(
|
|
1163
|
-
|
|
1303
|
+
if (!fs_1.default.existsSync(txJsonFilePath)) {
|
|
1304
|
+
yield fetchTransactionIntoCache(rpc, txHash, txJsonFilePath);
|
|
1164
1305
|
}
|
|
1165
1306
|
yield (0, ckb_tx_dumper_1.dumpTransaction)({ rpc, txJsonFilePath, outputFilePath });
|
|
1166
1307
|
}
|
|
@@ -1168,6 +1309,23 @@ function buildTxFileOptionBy(txHash, network) {
|
|
|
1168
1309
|
return opt;
|
|
1169
1310
|
});
|
|
1170
1311
|
}
|
|
1312
|
+
// Fallback for transactions that never went through the local RPC proxy
|
|
1313
|
+
// (e.g. historical transactions on a forked devnet): pull the transaction
|
|
1314
|
+
// from the node and cache it in the same JSON-RPC format the proxy stores.
|
|
1315
|
+
function fetchTransactionIntoCache(rpc, txHash, txJsonFilePath) {
|
|
1316
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1317
|
+
logger_1.logger.info(`Transaction ${txHash} not found in local cache, fetching from ${rpc} ..`);
|
|
1318
|
+
const result = yield (0, json_rpc_1.callJsonRpc)(rpc, 'get_transaction', [txHash]).catch((error) => {
|
|
1319
|
+
throw new Error(`Failed to fetch transaction ${txHash} from ${rpc}: ${error.message}`);
|
|
1320
|
+
});
|
|
1321
|
+
if (!(result === null || result === void 0 ? void 0 : result.transaction)) {
|
|
1322
|
+
throw new Error(`Transaction ${txHash} not found on ${rpc}. ` +
|
|
1323
|
+
`Check the hash and the --network option, or send the transaction through the offckb RPC proxy first.`);
|
|
1324
|
+
}
|
|
1325
|
+
fs_1.default.mkdirSync(path_1.default.dirname(txJsonFilePath), { recursive: true });
|
|
1326
|
+
fs_1.default.writeFileSync(txJsonFilePath, JSON.stringify(result.transaction, null, 2));
|
|
1327
|
+
});
|
|
1328
|
+
}
|
|
1171
1329
|
function buildTransactionJsonFilePath(network, txHash) {
|
|
1172
1330
|
const settings = (0, setting_1.readSettings)();
|
|
1173
1331
|
if (network === base_1.Network.devnet) {
|
|
@@ -1230,8 +1388,7 @@ function buildContract(jsFile, outputFile, jsVmPath) {
|
|
|
1230
1388
|
logger_1.logger.success(`✅ Contract built successfully: ${outputFile}`);
|
|
1231
1389
|
}
|
|
1232
1390
|
catch (error) {
|
|
1233
|
-
|
|
1234
|
-
process.exit(1);
|
|
1391
|
+
throw new Error(`Build failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
1235
1392
|
}
|
|
1236
1393
|
});
|
|
1237
1394
|
}
|
|
@@ -1267,14 +1424,19 @@ const deploy_1 = __nccwpck_require__(45615);
|
|
|
1267
1424
|
const ckb_1 = __nccwpck_require__(83748);
|
|
1268
1425
|
const prompts_1 = __nccwpck_require__(18167);
|
|
1269
1426
|
const logger_1 = __nccwpck_require__(65370);
|
|
1427
|
+
const private_key_1 = __nccwpck_require__(26241);
|
|
1428
|
+
const readiness_1 = __nccwpck_require__(19326);
|
|
1429
|
+
const fork_safety_1 = __nccwpck_require__(47625);
|
|
1270
1430
|
function deploy() {
|
|
1271
1431
|
return __awaiter(this, arguments, void 0, function* (opt = { network: base_1.Network.devnet, typeId: false, target: './', output: './deployment' }) {
|
|
1272
1432
|
var _a;
|
|
1273
1433
|
const network = opt.network;
|
|
1274
1434
|
(0, validator_1.validateNetworkOpt)(network);
|
|
1275
|
-
const ckb = new ckb_1.CKB({ network });
|
|
1276
1435
|
// we use deployerAccount to deploy contract by default
|
|
1277
|
-
const privateKey = opt
|
|
1436
|
+
const privateKey = (0, private_key_1.resolvePrivateKey)(opt, account_1.deployerAccount.privkey);
|
|
1437
|
+
(0, fork_safety_1.warnIfMainnetForkSigning)(network, privateKey);
|
|
1438
|
+
yield (0, readiness_1.warnIfForkIndexerIsBehind)(network);
|
|
1439
|
+
const ckb = new ckb_1.CKB({ network });
|
|
1278
1440
|
const enableTypeId = (_a = opt.typeId) !== null && _a !== void 0 ? _a : false;
|
|
1279
1441
|
const targetFolder = opt.target;
|
|
1280
1442
|
const output = opt.output;
|
|
@@ -1298,7 +1460,7 @@ function deploy() {
|
|
|
1298
1460
|
'',
|
|
1299
1461
|
` 📁 Deployment artifacts will be saved to: ${outputFolder}`,
|
|
1300
1462
|
` 🌐 Network: ${network}`,
|
|
1301
|
-
` 🔑 Using ${opt.privkey ? 'custom' : 'default'} private key`,
|
|
1463
|
+
` 🔑 Using ${opt.privkey || opt.privkeyFile || process.env.OFFCKB_PRIVATE_KEY ? 'custom' : 'default'} private key`,
|
|
1302
1464
|
` 🔄 Type ID: ${enableTypeId ? 'enabled (upgradable)' : 'disabled (immutable)'}`,
|
|
1303
1465
|
]);
|
|
1304
1466
|
// Skip confirmation if -y flag is provided
|
|
@@ -1344,22 +1506,40 @@ const link_1 = __nccwpck_require__(27814);
|
|
|
1344
1506
|
const validator_1 = __nccwpck_require__(39534);
|
|
1345
1507
|
const request_1 = __nccwpck_require__(65897);
|
|
1346
1508
|
const logger_1 = __nccwpck_require__(65370);
|
|
1509
|
+
const readiness_1 = __nccwpck_require__(19326);
|
|
1510
|
+
const fork_safety_1 = __nccwpck_require__(47625);
|
|
1511
|
+
const TESTNET_FAUCET_CLAIM_AMOUNT = '10000';
|
|
1347
1512
|
function deposit(toAddress_1, amountInCKB_1) {
|
|
1348
1513
|
return __awaiter(this, arguments, void 0, function* (toAddress, amountInCKB, opt = { network: base_1.Network.devnet }) {
|
|
1349
1514
|
const network = opt.network;
|
|
1350
1515
|
(0, validator_1.validateNetworkOpt)(network);
|
|
1351
1516
|
const ckb = new ckb_1.CKB({ network });
|
|
1352
1517
|
if (network === 'testnet') {
|
|
1353
|
-
|
|
1518
|
+
const txHash = yield depositFromTestnetFaucet(toAddress, ckb);
|
|
1519
|
+
logger_1.logger.result({
|
|
1520
|
+
command: 'deposit',
|
|
1521
|
+
network,
|
|
1522
|
+
source: 'fixed-testnet-faucet-claim',
|
|
1523
|
+
requestedAmount: amountInCKB,
|
|
1524
|
+
faucetClaimAmount: TESTNET_FAUCET_CLAIM_AMOUNT,
|
|
1525
|
+
toAddress,
|
|
1526
|
+
txHash,
|
|
1527
|
+
});
|
|
1528
|
+
return txHash;
|
|
1354
1529
|
}
|
|
1355
1530
|
// deposit from devnet miner
|
|
1356
1531
|
const privateKey = account_1.ckbDevnetMinerAccount.privkey;
|
|
1532
|
+
const rejectInputsAtOrBeforeBlock = (0, fork_safety_1.validateMainnetForkSigning)(network, privateKey);
|
|
1533
|
+
yield (0, readiness_1.warnIfForkIndexerIsBehind)(network);
|
|
1357
1534
|
const txHash = yield ckb.transfer({
|
|
1358
1535
|
toAddress,
|
|
1359
1536
|
privateKey,
|
|
1360
1537
|
amountInCKB,
|
|
1538
|
+
rejectInputsAtOrBeforeBlock,
|
|
1361
1539
|
});
|
|
1362
1540
|
logger_1.logger.info('tx hash: ', txHash);
|
|
1541
|
+
logger_1.logger.result({ command: 'deposit', network, amount: amountInCKB, toAddress, txHash });
|
|
1542
|
+
return txHash;
|
|
1363
1543
|
});
|
|
1364
1544
|
}
|
|
1365
1545
|
function depositFromTestnetFaucet(ckbAddress, ckb) {
|
|
@@ -1385,6 +1565,7 @@ function depositFromTestnetFaucet(ckbAddress, ckb) {
|
|
|
1385
1565
|
}
|
|
1386
1566
|
const txHash = yield ckb.transferAll({ privateKey: randomAccountPrivateKey, toAddress: ckbAddress });
|
|
1387
1567
|
logger_1.logger.info(`Done, check ${(0, link_1.buildTestnetTxLink)(txHash)} for details.`);
|
|
1568
|
+
return txHash;
|
|
1388
1569
|
});
|
|
1389
1570
|
}
|
|
1390
1571
|
function sendClaimRequest(toAddress) {
|
|
@@ -1400,7 +1581,7 @@ function sendClaimRequest(toAddress) {
|
|
|
1400
1581
|
const body = JSON.stringify({
|
|
1401
1582
|
claim_event: {
|
|
1402
1583
|
address_hash: toAddress,
|
|
1403
|
-
amount:
|
|
1584
|
+
amount: TESTNET_FAUCET_CLAIM_AMOUNT, // unit: CKB
|
|
1404
1585
|
},
|
|
1405
1586
|
});
|
|
1406
1587
|
const config = {
|
|
@@ -1482,12 +1663,8 @@ function devnetConfig() {
|
|
|
1482
1663
|
return;
|
|
1483
1664
|
}
|
|
1484
1665
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
logger_1.logger.info(' offckb devnet config --set ckb.logger.filter=info');
|
|
1488
|
-
logger_1.logger.info(' offckb devnet config --set miner.client.poll_interval=1500');
|
|
1489
|
-
process.exitCode = 1;
|
|
1490
|
-
return;
|
|
1666
|
+
throw new Error('Interactive devnet config editor requires a TTY terminal. Use non-interactive mode, e.g. ' +
|
|
1667
|
+
'`offckb devnet config --set ckb.logger.filter=info`.');
|
|
1491
1668
|
}
|
|
1492
1669
|
const isSaved = yield (0, devnet_config_tui_1.runDevnetConfigTui)(editor, configPath);
|
|
1493
1670
|
if (isSaved) {
|
|
@@ -1498,13 +1675,121 @@ function devnetConfig() {
|
|
|
1498
1675
|
logger_1.logger.info('No changes saved.');
|
|
1499
1676
|
}
|
|
1500
1677
|
catch (error) {
|
|
1501
|
-
|
|
1502
|
-
logger_1.logger.error(message);
|
|
1678
|
+
let message = error instanceof Error ? error.message : String(error);
|
|
1503
1679
|
if (error instanceof config_editor_1.InitializationError) {
|
|
1504
|
-
|
|
1680
|
+
message += ' Tip: run `offckb node` once to initialize devnet config files first.';
|
|
1505
1681
|
}
|
|
1506
|
-
|
|
1682
|
+
throw new Error(message);
|
|
1683
|
+
}
|
|
1684
|
+
});
|
|
1685
|
+
}
|
|
1686
|
+
|
|
1687
|
+
|
|
1688
|
+
/***/ }),
|
|
1689
|
+
|
|
1690
|
+
/***/ 36709:
|
|
1691
|
+
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
|
1692
|
+
|
|
1693
|
+
"use strict";
|
|
1694
|
+
|
|
1695
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
1696
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
1697
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
1698
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
1699
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
1700
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
1701
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
1702
|
+
});
|
|
1703
|
+
};
|
|
1704
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
1705
|
+
exports.devnetFork = devnetFork;
|
|
1706
|
+
const fork_1 = __nccwpck_require__(77912);
|
|
1707
|
+
function devnetFork(options) {
|
|
1708
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1709
|
+
if (options.source && options.source !== 'mainnet' && options.source !== 'testnet') {
|
|
1710
|
+
throw new Error(`Invalid --source value: ${options.source}. Expected mainnet or testnet.`);
|
|
1507
1711
|
}
|
|
1712
|
+
yield (0, fork_1.forkDevnet)(options);
|
|
1713
|
+
});
|
|
1714
|
+
}
|
|
1715
|
+
|
|
1716
|
+
|
|
1717
|
+
/***/ }),
|
|
1718
|
+
|
|
1719
|
+
/***/ 60905:
|
|
1720
|
+
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
|
1721
|
+
|
|
1722
|
+
"use strict";
|
|
1723
|
+
|
|
1724
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
1725
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
1726
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
1727
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
1728
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
1729
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
1730
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
1731
|
+
});
|
|
1732
|
+
};
|
|
1733
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
1734
|
+
exports.devnetInfo = devnetInfo;
|
|
1735
|
+
const setting_1 = __nccwpck_require__(25546);
|
|
1736
|
+
const fork_1 = __nccwpck_require__(77912);
|
|
1737
|
+
const readiness_1 = __nccwpck_require__(19326);
|
|
1738
|
+
const logger_1 = __nccwpck_require__(65370);
|
|
1739
|
+
function devnetInfo() {
|
|
1740
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1741
|
+
var _a, _b, _c;
|
|
1742
|
+
const settings = (0, setting_1.readSettings)();
|
|
1743
|
+
const fork = (0, fork_1.readForkState)(settings.devnet.configPath);
|
|
1744
|
+
const readiness = yield (0, readiness_1.checkNodeReadiness)(settings.devnet.rpcUrl);
|
|
1745
|
+
const indexerReady = readiness.indexerTip != null && readiness.indexerLag === BigInt(0);
|
|
1746
|
+
const networkIsolated = fork && readiness.peers != null ? readiness.peers === 0 : undefined;
|
|
1747
|
+
const result = {
|
|
1748
|
+
command: 'devnet.info',
|
|
1749
|
+
kind: fork ? `fork-of-${fork.source}` : 'pure-devnet',
|
|
1750
|
+
configPath: settings.devnet.configPath,
|
|
1751
|
+
rpcUrl: settings.devnet.rpcUrl,
|
|
1752
|
+
proxyUrl: `http://127.0.0.1:${settings.devnet.rpcProxyPort}`,
|
|
1753
|
+
ready: readiness.ready,
|
|
1754
|
+
nodeTip: (_a = readiness.nodeTip) === null || _a === void 0 ? void 0 : _a.toString(),
|
|
1755
|
+
indexerTip: (_b = readiness.indexerTip) === null || _b === void 0 ? void 0 : _b.toString(),
|
|
1756
|
+
indexerLag: (_c = readiness.indexerLag) === null || _c === void 0 ? void 0 : _c.toString(),
|
|
1757
|
+
indexerReady,
|
|
1758
|
+
peers: readiness.peers,
|
|
1759
|
+
networkIsolated,
|
|
1760
|
+
error: readiness.error,
|
|
1761
|
+
fork,
|
|
1762
|
+
};
|
|
1763
|
+
logger_1.logger.info(`Devnet: ${result.kind}`);
|
|
1764
|
+
logger_1.logger.info(`RPC: ${result.rpcUrl}`);
|
|
1765
|
+
logger_1.logger.info(`Proxy RPC: ${result.proxyUrl}`);
|
|
1766
|
+
logger_1.logger.info(`Node ready: ${result.ready ? 'yes' : 'no'}`);
|
|
1767
|
+
if (readiness.nodeTip != null)
|
|
1768
|
+
logger_1.logger.info(`Node tip: ${readiness.nodeTip}`);
|
|
1769
|
+
if (readiness.indexerTip != null)
|
|
1770
|
+
logger_1.logger.info(`Indexer tip: ${readiness.indexerTip}`);
|
|
1771
|
+
if (readiness.indexerLag != null) {
|
|
1772
|
+
const message = `Indexer lag: ${readiness.indexerLag}`;
|
|
1773
|
+
if (readiness.indexerLag > BigInt(0))
|
|
1774
|
+
logger_1.logger.warn(`${message}; indexed queries may be stale.`);
|
|
1775
|
+
else
|
|
1776
|
+
logger_1.logger.info(message);
|
|
1777
|
+
}
|
|
1778
|
+
logger_1.logger.info(`Indexer ready: ${indexerReady ? 'yes' : 'no'}`);
|
|
1779
|
+
if (readiness.peers != null)
|
|
1780
|
+
logger_1.logger.info(`Peers: ${readiness.peers}`);
|
|
1781
|
+
if (fork)
|
|
1782
|
+
logger_1.logger.info(`Public network isolated: ${networkIsolated == null ? 'unknown' : networkIsolated ? 'yes' : 'NO'}`);
|
|
1783
|
+
if (fork && readiness.peers != null && readiness.peers > 0) {
|
|
1784
|
+
logger_1.logger.warn('A forked devnet has connected peers. Stop it and inspect ckb.toml before signing or mining.');
|
|
1785
|
+
}
|
|
1786
|
+
if ((fork === null || fork === void 0 ? void 0 : fork.source) === 'mainnet') {
|
|
1787
|
+
logger_1.logger.warn('MAINNET FORK REPLAY RISK: only sign with built-in dev keys and fork-mined cells.');
|
|
1788
|
+
}
|
|
1789
|
+
if (readiness.error)
|
|
1790
|
+
logger_1.logger.warn(readiness.error);
|
|
1791
|
+
logger_1.logger.result(result);
|
|
1792
|
+
return result;
|
|
1508
1793
|
});
|
|
1509
1794
|
}
|
|
1510
1795
|
|
|
@@ -1570,14 +1855,23 @@ const path = __importStar(__nccwpck_require__(16928));
|
|
|
1570
1855
|
const init_chain_1 = __nccwpck_require__(1360);
|
|
1571
1856
|
const install_1 = __nccwpck_require__(65611);
|
|
1572
1857
|
const setting_1 = __nccwpck_require__(25546);
|
|
1573
|
-
const encoding_1 = __nccwpck_require__(6851);
|
|
1574
1858
|
const rpc_proxy_1 = __nccwpck_require__(46589);
|
|
1859
|
+
const fork_1 = __nccwpck_require__(77912);
|
|
1860
|
+
const json_rpc_1 = __nccwpck_require__(51726);
|
|
1575
1861
|
const base_1 = __nccwpck_require__(69951);
|
|
1576
1862
|
const logger_1 = __nccwpck_require__(65370);
|
|
1863
|
+
const readiness_1 = __nccwpck_require__(19326);
|
|
1577
1864
|
const DAEMON_LOG_DIR = 'logs';
|
|
1578
1865
|
const DAEMON_LOG_FILE = 'daemon.log';
|
|
1579
1866
|
const DAEMON_PID_FILE = 'daemon.pid';
|
|
1580
1867
|
const DAEMON_CHILD_ENV = 'OFFCKB_DAEMON_CHILD';
|
|
1868
|
+
const NODE_READY_TIMEOUT_MS = 90000;
|
|
1869
|
+
const FORK_NODE_READY_TIMEOUT_MS = 10 * 60000;
|
|
1870
|
+
function cleanChildOutput(data) {
|
|
1871
|
+
// CKB colors its output even when it is redirected. Strip ANSI control
|
|
1872
|
+
// sequences so JSON logs stay machine-readable.
|
|
1873
|
+
return String(data).replace(/\u001b\[[0-?]*[ -/]*[@-~]/g, '');
|
|
1874
|
+
}
|
|
1581
1875
|
function startNode({ version, network = base_1.Network.devnet, binaryPath, daemon }) {
|
|
1582
1876
|
if (binaryPath && network !== base_1.Network.devnet) {
|
|
1583
1877
|
logger_1.logger.warn('Custom binaryPath is only supported for devnet. The provided binaryPath will be ignored.');
|
|
@@ -1598,7 +1892,7 @@ function startNode({ version, network = base_1.Network.devnet, binaryPath, daemo
|
|
|
1598
1892
|
}
|
|
1599
1893
|
function nodeDevnet(_a) {
|
|
1600
1894
|
return __awaiter(this, arguments, void 0, function* ({ version, binaryPath, daemon }) {
|
|
1601
|
-
var _b, _c;
|
|
1895
|
+
var _b, _c, _d, _e, _f;
|
|
1602
1896
|
if (daemon) {
|
|
1603
1897
|
return startDaemon();
|
|
1604
1898
|
}
|
|
@@ -1606,54 +1900,114 @@ function nodeDevnet(_a) {
|
|
|
1606
1900
|
const ckbVersion = version || settings.bins.defaultCKBVersion;
|
|
1607
1901
|
let ckbBinPath = '';
|
|
1608
1902
|
if (binaryPath) {
|
|
1609
|
-
ckbBinPath =
|
|
1903
|
+
ckbBinPath = binaryPath;
|
|
1610
1904
|
logger_1.logger.info(`Using custom CKB binary path: ${ckbBinPath}`);
|
|
1611
1905
|
}
|
|
1612
1906
|
else {
|
|
1613
1907
|
yield (0, install_1.installCKBBinary)(ckbVersion);
|
|
1614
|
-
ckbBinPath = (0,
|
|
1908
|
+
ckbBinPath = (0, setting_1.getCKBBinaryPath)(ckbVersion);
|
|
1615
1909
|
}
|
|
1616
1910
|
yield (0, init_chain_1.initChainIfNeeded)();
|
|
1617
|
-
const devnetConfigPath =
|
|
1618
|
-
|
|
1619
|
-
|
|
1911
|
+
const devnetConfigPath = settings.devnet.configPath;
|
|
1912
|
+
// A forked devnet must boot once with --skip-spec-check --overwrite-spec so
|
|
1913
|
+
// the imported (and patched) spec replaces the source chain's stored spec.
|
|
1914
|
+
const forkState = (0, fork_1.readForkState)(settings.devnet.configPath);
|
|
1915
|
+
const firstRunFlags = (forkState === null || forkState === void 0 ? void 0 : forkState.firstRunPending) ? ' --skip-spec-check --overwrite-spec' : '';
|
|
1916
|
+
if (forkState === null || forkState === void 0 ? void 0 : forkState.firstRunPending) {
|
|
1917
|
+
logger_1.logger.info(`Forked devnet (${forkState.source}) detected, first run uses --skip-spec-check --overwrite-spec.`);
|
|
1918
|
+
}
|
|
1620
1919
|
logger_1.logger.info(`Launching CKB devnet Node...`);
|
|
1920
|
+
const runArgs = ['run', '-C', devnetConfigPath];
|
|
1921
|
+
if (firstRunFlags)
|
|
1922
|
+
runArgs.push('--skip-spec-check', '--overwrite-spec');
|
|
1923
|
+
const ckbProcess = (0, child_process_1.spawn)(ckbBinPath, runArgs, { stdio: ['ignore', 'pipe', 'pipe'] });
|
|
1924
|
+
(_b = ckbProcess.stdout) === null || _b === void 0 ? void 0 : _b.on('data', (data) => logger_1.logger.info(['CKB:', cleanChildOutput(data)]));
|
|
1925
|
+
(_c = ckbProcess.stderr) === null || _c === void 0 ? void 0 : _c.on('data', (data) => logger_1.logger.error(['CKB error:', cleanChildOutput(data)]));
|
|
1926
|
+
let ckbExited = false;
|
|
1927
|
+
ckbProcess.once('exit', () => {
|
|
1928
|
+
ckbExited = true;
|
|
1929
|
+
});
|
|
1930
|
+
ckbProcess.once('error', () => {
|
|
1931
|
+
ckbExited = true;
|
|
1932
|
+
});
|
|
1933
|
+
const timeoutMs = forkState ? FORK_NODE_READY_TIMEOUT_MS : NODE_READY_TIMEOUT_MS;
|
|
1934
|
+
const readiness = yield (0, readiness_1.waitForNodeReady)(settings.devnet.rpcUrl, timeoutMs, () => !ckbExited);
|
|
1935
|
+
if (!readiness.ready) {
|
|
1936
|
+
if (!ckbExited)
|
|
1937
|
+
ckbProcess.kill('SIGTERM');
|
|
1938
|
+
throw new Error(`CKB devnet failed to become ready: ${(_d = readiness.error) !== null && _d !== void 0 ? _d : 'CKB process exited'}`);
|
|
1939
|
+
}
|
|
1940
|
+
if (ckbExited) {
|
|
1941
|
+
throw new Error('CKB devnet exited immediately after its readiness check.');
|
|
1942
|
+
}
|
|
1943
|
+
if (forkState === null || forkState === void 0 ? void 0 : forkState.firstRunPending) {
|
|
1944
|
+
yield clearForkFirstRunWhenNodeUp(ckbProcess, settings.devnet.rpcUrl, settings.devnet.configPath, forkState.genesisHash);
|
|
1945
|
+
}
|
|
1946
|
+
let minerProcess;
|
|
1621
1947
|
try {
|
|
1622
|
-
|
|
1623
|
-
const ckbProcess = (0, child_process_1.exec)(ckbCmd);
|
|
1624
|
-
// Log first command's output
|
|
1625
|
-
(_b = ckbProcess.stdout) === null || _b === void 0 ? void 0 : _b.on('data', (data) => {
|
|
1626
|
-
logger_1.logger.info(['CKB:', data.toString()]);
|
|
1627
|
-
});
|
|
1628
|
-
(_c = ckbProcess.stderr) === null || _c === void 0 ? void 0 : _c.on('data', (data) => {
|
|
1629
|
-
logger_1.logger.error(['CKB error:', data.toString()]);
|
|
1630
|
-
});
|
|
1631
|
-
// Start the second command after 3 seconds
|
|
1632
|
-
setTimeout(() => __awaiter(this, void 0, void 0, function* () {
|
|
1633
|
-
var _a, _b;
|
|
1634
|
-
try {
|
|
1635
|
-
// Run second command
|
|
1636
|
-
const minerProcess = (0, child_process_1.exec)(minerCmd);
|
|
1637
|
-
(_a = minerProcess.stdout) === null || _a === void 0 ? void 0 : _a.on('data', (data) => {
|
|
1638
|
-
logger_1.logger.info(['CKB-Miner:', data.toString()]);
|
|
1639
|
-
});
|
|
1640
|
-
(_b = minerProcess.stderr) === null || _b === void 0 ? void 0 : _b.on('data', (data) => {
|
|
1641
|
-
logger_1.logger.error(['CKB-Miner error:', data.toString()]);
|
|
1642
|
-
});
|
|
1643
|
-
// by default we start the proxy server
|
|
1644
|
-
const ckbRpc = settings.devnet.rpcUrl;
|
|
1645
|
-
const port = settings.devnet.rpcProxyPort;
|
|
1646
|
-
const proxy = (0, rpc_proxy_1.createRPCProxy)(base_1.Network.devnet, ckbRpc, port);
|
|
1647
|
-
proxy.start();
|
|
1648
|
-
}
|
|
1649
|
-
catch (error) {
|
|
1650
|
-
logger_1.logger.error('Error running CKB-Miner:', error);
|
|
1651
|
-
}
|
|
1652
|
-
}), 3000);
|
|
1948
|
+
minerProcess = (0, child_process_1.spawn)(ckbBinPath, ['miner', '-C', devnetConfigPath], { stdio: ['ignore', 'pipe', 'pipe'] });
|
|
1653
1949
|
}
|
|
1654
1950
|
catch (error) {
|
|
1655
|
-
|
|
1951
|
+
ckbProcess.kill('SIGTERM');
|
|
1952
|
+
throw new Error(`CKB miner failed to start: ${error.message}`);
|
|
1656
1953
|
}
|
|
1954
|
+
(_e = minerProcess.stdout) === null || _e === void 0 ? void 0 : _e.on('data', (data) => logger_1.logger.info(['CKB-Miner:', cleanChildOutput(data)]));
|
|
1955
|
+
(_f = minerProcess.stderr) === null || _f === void 0 ? void 0 : _f.on('data', (data) => logger_1.logger.error(['CKB-Miner error:', cleanChildOutput(data)]));
|
|
1956
|
+
try {
|
|
1957
|
+
yield waitForChildSpawn(minerProcess, 'CKB miner');
|
|
1958
|
+
}
|
|
1959
|
+
catch (error) {
|
|
1960
|
+
ckbProcess.kill('SIGTERM');
|
|
1961
|
+
throw error;
|
|
1962
|
+
}
|
|
1963
|
+
if (ckbExited) {
|
|
1964
|
+
if (!minerProcess.killed)
|
|
1965
|
+
minerProcess.kill('SIGTERM');
|
|
1966
|
+
throw new Error('CKB devnet exited while the miner was starting.');
|
|
1967
|
+
}
|
|
1968
|
+
const proxy = (0, rpc_proxy_1.createRPCProxy)(base_1.Network.devnet, settings.devnet.rpcUrl, settings.devnet.rpcProxyPort);
|
|
1969
|
+
proxy.start();
|
|
1970
|
+
logger_1.logger.success(`CKB devnet is ready at ${settings.devnet.rpcUrl}.`);
|
|
1971
|
+
logger_1.logger.result({
|
|
1972
|
+
command: 'node',
|
|
1973
|
+
network: base_1.Network.devnet,
|
|
1974
|
+
daemon: false,
|
|
1975
|
+
rpcUrl: settings.devnet.rpcUrl,
|
|
1976
|
+
proxyUrl: `http://127.0.0.1:${settings.devnet.rpcProxyPort}`,
|
|
1977
|
+
});
|
|
1978
|
+
// Treat CKB, miner and proxy as one service. A dead CKB must not leave a
|
|
1979
|
+
// healthy-looking proxy and a miner that retries forever.
|
|
1980
|
+
let serviceStopping = false;
|
|
1981
|
+
const stopService = (component, code, signal) => {
|
|
1982
|
+
if (serviceStopping)
|
|
1983
|
+
return;
|
|
1984
|
+
serviceStopping = true;
|
|
1985
|
+
if (component !== 'CKB node' && !ckbProcess.killed)
|
|
1986
|
+
ckbProcess.kill('SIGTERM');
|
|
1987
|
+
if (component !== 'CKB miner' && !minerProcess.killed)
|
|
1988
|
+
minerProcess.kill('SIGTERM');
|
|
1989
|
+
proxy.stop();
|
|
1990
|
+
if (process.env[DAEMON_CHILD_ENV] === '1')
|
|
1991
|
+
cleanupPidFile(resolveDaemonPaths().pidFile);
|
|
1992
|
+
logger_1.logger.error(`${component} exited unexpectedly (code=${code !== null && code !== void 0 ? code : 'null'}, signal=${signal !== null && signal !== void 0 ? signal : 'none'}).`);
|
|
1993
|
+
process.exitCode = typeof code === 'number' && code > 0 ? code : 1;
|
|
1994
|
+
};
|
|
1995
|
+
ckbProcess.once('exit', (code, signal) => stopService('CKB node', code, signal));
|
|
1996
|
+
minerProcess.once('exit', (code, signal) => stopService('CKB miner', code, signal));
|
|
1997
|
+
});
|
|
1998
|
+
}
|
|
1999
|
+
function waitForChildSpawn(child, label) {
|
|
2000
|
+
return new Promise((resolve, reject) => {
|
|
2001
|
+
const onSpawn = () => {
|
|
2002
|
+
child.removeListener('error', onError);
|
|
2003
|
+
resolve();
|
|
2004
|
+
};
|
|
2005
|
+
const onError = (error) => {
|
|
2006
|
+
child.removeListener('spawn', onSpawn);
|
|
2007
|
+
reject(new Error(`${label} failed to start: ${error.message}`));
|
|
2008
|
+
};
|
|
2009
|
+
child.once('spawn', onSpawn);
|
|
2010
|
+
child.once('error', onError);
|
|
1657
2011
|
});
|
|
1658
2012
|
}
|
|
1659
2013
|
function resolveDaemonPaths() {
|
|
@@ -1663,6 +2017,49 @@ function resolveDaemonPaths() {
|
|
|
1663
2017
|
const pidFile = path.join(logDir, DAEMON_PID_FILE);
|
|
1664
2018
|
return { logDir, logFile, pidFile };
|
|
1665
2019
|
}
|
|
2020
|
+
// Poll the devnet RPC until the spawned node answers with the fork's genesis
|
|
2021
|
+
// hash, then mark the first run as done so subsequent `offckb node` runs boot
|
|
2022
|
+
// normally. Two guards against clearing the flag on the wrong signal:
|
|
2023
|
+
// - the poll aborts when the spawned ckb process exits (e.g. failed boot),
|
|
2024
|
+
// - an answering node is only trusted when its genesis matches the fork
|
|
2025
|
+
// state — an unrelated node occupying the port must not clear the flag.
|
|
2026
|
+
function clearForkFirstRunWhenNodeUp(ckbProcess, rpcUrl, configPath, expectedGenesisHash) {
|
|
2027
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2028
|
+
let processExited = false;
|
|
2029
|
+
const markExited = () => {
|
|
2030
|
+
processExited = true;
|
|
2031
|
+
};
|
|
2032
|
+
ckbProcess.once('exit', markExited);
|
|
2033
|
+
ckbProcess.once('error', markExited);
|
|
2034
|
+
const timeoutMs = 10 * 60 * 1000; // large forks take a while to boot
|
|
2035
|
+
const start = Date.now();
|
|
2036
|
+
while (!processExited && Date.now() - start < timeoutMs) {
|
|
2037
|
+
try {
|
|
2038
|
+
const genesisHash = String(yield (0, json_rpc_1.callJsonRpc)(rpcUrl, 'get_block_hash', ['0x0'], 5000)).toLowerCase();
|
|
2039
|
+
if (genesisHash !== expectedGenesisHash.toLowerCase()) {
|
|
2040
|
+
logger_1.logger.warn(`A node is answering at ${rpcUrl} but reports a different genesis (${genesisHash}); ` +
|
|
2041
|
+
'leaving the first-run flags in place.');
|
|
2042
|
+
return;
|
|
2043
|
+
}
|
|
2044
|
+
// The miner has not started yet, so this tip is the exact boundary
|
|
2045
|
+
// between copied public-chain state and cells mined on the local fork.
|
|
2046
|
+
const forkBlockNumber = BigInt(String(yield (0, json_rpc_1.callJsonRpc)(rpcUrl, 'get_tip_block_number', [], 5000))).toString();
|
|
2047
|
+
(0, fork_1.markForkFirstRunComplete)(configPath, forkBlockNumber);
|
|
2048
|
+
logger_1.logger.success('Forked devnet is up; first-run spec flags cleared.');
|
|
2049
|
+
return;
|
|
2050
|
+
}
|
|
2051
|
+
catch (_a) {
|
|
2052
|
+
yield new Promise((resolve) => setTimeout(resolve, 1000));
|
|
2053
|
+
}
|
|
2054
|
+
}
|
|
2055
|
+
if (processExited) {
|
|
2056
|
+
logger_1.logger.warn('The CKB process exited before the forked devnet came up; first-run flags will be retried next time.');
|
|
2057
|
+
}
|
|
2058
|
+
else {
|
|
2059
|
+
logger_1.logger.warn('Timed out waiting for the forked devnet to start; first-run flags will be retried next time.');
|
|
2060
|
+
}
|
|
2061
|
+
});
|
|
2062
|
+
}
|
|
1666
2063
|
function readPidFile(pidFile) {
|
|
1667
2064
|
var _a, _b;
|
|
1668
2065
|
let raw;
|
|
@@ -1689,6 +2086,7 @@ function readPidFile(pidFile) {
|
|
|
1689
2086
|
pid,
|
|
1690
2087
|
scriptPath: parsed.scriptPath,
|
|
1691
2088
|
startedAt: (_b = parsed.startedAt) !== null && _b !== void 0 ? _b : new Date(0).toISOString(),
|
|
2089
|
+
status: parsed.status,
|
|
1692
2090
|
};
|
|
1693
2091
|
}
|
|
1694
2092
|
}
|
|
@@ -1702,6 +2100,39 @@ function readPidFile(pidFile) {
|
|
|
1702
2100
|
function writePidFile(pidFile, metadata) {
|
|
1703
2101
|
fs.writeFileSync(pidFile, JSON.stringify(metadata, null, 2));
|
|
1704
2102
|
}
|
|
2103
|
+
function reservePidFile(pidFile, scriptPath) {
|
|
2104
|
+
let fd;
|
|
2105
|
+
try {
|
|
2106
|
+
fd = fs.openSync(pidFile, 'wx');
|
|
2107
|
+
}
|
|
2108
|
+
catch (error) {
|
|
2109
|
+
const err = error;
|
|
2110
|
+
if (err.code === 'EEXIST') {
|
|
2111
|
+
throw new Error('A CKB devnet daemon startup is already in progress. Try again after it completes.');
|
|
2112
|
+
}
|
|
2113
|
+
throw new Error(`Failed to reserve daemon PID file ${pidFile}: ${err.message}`);
|
|
2114
|
+
}
|
|
2115
|
+
let writeError;
|
|
2116
|
+
try {
|
|
2117
|
+
const reservation = {
|
|
2118
|
+
pid: process.pid,
|
|
2119
|
+
scriptPath,
|
|
2120
|
+
startedAt: new Date().toISOString(),
|
|
2121
|
+
status: 'starting',
|
|
2122
|
+
};
|
|
2123
|
+
fs.writeFileSync(fd, JSON.stringify(reservation, null, 2));
|
|
2124
|
+
}
|
|
2125
|
+
catch (error) {
|
|
2126
|
+
writeError = error;
|
|
2127
|
+
}
|
|
2128
|
+
finally {
|
|
2129
|
+
fs.closeSync(fd);
|
|
2130
|
+
}
|
|
2131
|
+
if (writeError) {
|
|
2132
|
+
cleanupPidFile(pidFile);
|
|
2133
|
+
throw new Error(`Failed to initialize daemon PID reservation ${pidFile}: ${writeError.message}`);
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
1705
2136
|
function resolveCliEntry() {
|
|
1706
2137
|
var _a;
|
|
1707
2138
|
// In priority order. process.argv[1] is the most reliable for a Node CLI.
|
|
@@ -1723,12 +2154,19 @@ function resolveCliEntry() {
|
|
|
1723
2154
|
return null;
|
|
1724
2155
|
}
|
|
1725
2156
|
function isProcessAlive(pid) {
|
|
2157
|
+
if (!Number.isInteger(pid) || pid <= 0)
|
|
2158
|
+
return false;
|
|
1726
2159
|
try {
|
|
1727
2160
|
process.kill(pid, 0);
|
|
1728
2161
|
return true;
|
|
1729
2162
|
}
|
|
1730
|
-
catch (
|
|
1731
|
-
|
|
2163
|
+
catch (error) {
|
|
2164
|
+
const err = error;
|
|
2165
|
+
if (err.code === 'ESRCH')
|
|
2166
|
+
return false;
|
|
2167
|
+
if (err.code === 'EPERM')
|
|
2168
|
+
throw new Error(`Permission denied when checking daemon process ${pid}.`);
|
|
2169
|
+
throw error;
|
|
1732
2170
|
}
|
|
1733
2171
|
}
|
|
1734
2172
|
function cleanupPidFile(pidFile) {
|
|
@@ -1741,10 +2179,16 @@ function cleanupPidFile(pidFile) {
|
|
|
1741
2179
|
}
|
|
1742
2180
|
function waitForProcessExit(pid, timeoutMs) {
|
|
1743
2181
|
const start = Date.now();
|
|
1744
|
-
return new Promise((resolve) => {
|
|
2182
|
+
return new Promise((resolve, reject) => {
|
|
1745
2183
|
const check = () => {
|
|
1746
|
-
|
|
1747
|
-
|
|
2184
|
+
try {
|
|
2185
|
+
if (!isProcessAlive(pid)) {
|
|
2186
|
+
resolve(true);
|
|
2187
|
+
return;
|
|
2188
|
+
}
|
|
2189
|
+
}
|
|
2190
|
+
catch (error) {
|
|
2191
|
+
reject(error);
|
|
1748
2192
|
return;
|
|
1749
2193
|
}
|
|
1750
2194
|
if (Date.now() - start >= timeoutMs) {
|
|
@@ -1824,73 +2268,159 @@ function terminateProcess(pid, signal) {
|
|
|
1824
2268
|
}
|
|
1825
2269
|
});
|
|
1826
2270
|
}
|
|
2271
|
+
function failDaemonStartup(error, pid, pidFile) {
|
|
2272
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2273
|
+
let exited = false;
|
|
2274
|
+
try {
|
|
2275
|
+
exited = !isProcessAlive(pid);
|
|
2276
|
+
if (!exited) {
|
|
2277
|
+
yield terminateProcess(pid, 'SIGTERM');
|
|
2278
|
+
exited = yield waitForProcessExit(pid, 5000);
|
|
2279
|
+
if (!exited) {
|
|
2280
|
+
yield terminateProcess(pid, 'SIGKILL');
|
|
2281
|
+
exited = yield waitForProcessExit(pid, 5000);
|
|
2282
|
+
}
|
|
2283
|
+
}
|
|
2284
|
+
}
|
|
2285
|
+
catch (_a) {
|
|
2286
|
+
// The child may have exited while cleanup signals were sent. If liveness
|
|
2287
|
+
// cannot be checked, preserve the PID file for a later explicit stop.
|
|
2288
|
+
try {
|
|
2289
|
+
exited = !isProcessAlive(pid);
|
|
2290
|
+
}
|
|
2291
|
+
catch (_b) {
|
|
2292
|
+
exited = false;
|
|
2293
|
+
}
|
|
2294
|
+
}
|
|
2295
|
+
if (exited) {
|
|
2296
|
+
cleanupPidFile(pidFile);
|
|
2297
|
+
}
|
|
2298
|
+
else {
|
|
2299
|
+
error.message += ` Process ${pid} is still running; PID file was preserved.`;
|
|
2300
|
+
}
|
|
2301
|
+
throw error;
|
|
2302
|
+
});
|
|
2303
|
+
}
|
|
1827
2304
|
function startDaemon() {
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
2305
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2306
|
+
var _a;
|
|
2307
|
+
const { logDir, logFile, pidFile } = resolveDaemonPaths();
|
|
2308
|
+
try {
|
|
2309
|
+
fs.mkdirSync(logDir, { recursive: true });
|
|
2310
|
+
}
|
|
2311
|
+
catch (error) {
|
|
2312
|
+
throw new Error(`Failed to prepare daemon log directory at ${logDir}: ${error.message}`);
|
|
2313
|
+
}
|
|
2314
|
+
const settings = (0, setting_1.readSettings)();
|
|
2315
|
+
const activeNode = yield (0, readiness_1.checkNodeReadiness)(settings.devnet.rpcUrl, 1000);
|
|
2316
|
+
if (activeNode.ready) {
|
|
2317
|
+
throw new Error(`A CKB node is already answering at ${settings.devnet.rpcUrl}. Stop it before starting daemon mode.`);
|
|
2318
|
+
}
|
|
2319
|
+
// Prevent duplicate daemon starts. If a daemon is already running, refuse
|
|
2320
|
+
// to overwrite its PID file.
|
|
2321
|
+
const existing = readPidFile(pidFile);
|
|
2322
|
+
if (existing) {
|
|
2323
|
+
if (isProcessAlive(existing.pid)) {
|
|
2324
|
+
const identityOk = yield verifyDaemonIdentity(existing.pid, existing);
|
|
2325
|
+
if (identityOk) {
|
|
2326
|
+
if (existing.status === 'starting') {
|
|
2327
|
+
throw new Error(`Another CKB devnet daemon startup is already in progress (PID ${existing.pid}).`);
|
|
2328
|
+
}
|
|
2329
|
+
throw new Error(`A CKB devnet daemon is already running (PID ${existing.pid}). Stop it first with: offckb node stop`);
|
|
2330
|
+
}
|
|
2331
|
+
logger_1.logger.warn(`PID ${existing.pid} from ${pidFile} belongs to another process; removing stale daemon metadata without signaling it.`);
|
|
2332
|
+
}
|
|
2333
|
+
// Stale PID file from a crashed daemon; clean it up before atomically
|
|
2334
|
+
// reserving the same control file for this startup attempt.
|
|
2335
|
+
cleanupPidFile(pidFile);
|
|
2336
|
+
}
|
|
2337
|
+
const scriptPath = resolveCliEntry();
|
|
2338
|
+
if (!scriptPath) {
|
|
2339
|
+
throw new Error('Unable to determine the CLI entry point for daemon mode. Set OFFCKB_CLI_PATH to the offckb script.');
|
|
2340
|
+
}
|
|
2341
|
+
reservePidFile(pidFile, scriptPath);
|
|
2342
|
+
let out;
|
|
2343
|
+
let err;
|
|
2344
|
+
try {
|
|
2345
|
+
out = fs.openSync(logFile, 'a');
|
|
2346
|
+
err = fs.openSync(logFile, 'a');
|
|
2347
|
+
}
|
|
2348
|
+
catch (error) {
|
|
2349
|
+
closeFileDescriptors(out, err);
|
|
2350
|
+
cleanupPidFile(pidFile);
|
|
2351
|
+
throw new Error(`Failed to prepare daemon log directory or log file at ${logFile}: ${error.message}`);
|
|
2352
|
+
}
|
|
2353
|
+
const childArgs = process.argv.slice(2).filter((arg) => arg !== '--daemon');
|
|
2354
|
+
const childEnv = Object.assign(Object.assign({}, process.env), { [DAEMON_CHILD_ENV]: '1' });
|
|
2355
|
+
let child;
|
|
2356
|
+
try {
|
|
2357
|
+
child = (0, child_process_1.spawn)(process.execPath, [scriptPath, ...childArgs], {
|
|
2358
|
+
detached: true,
|
|
2359
|
+
stdio: ['ignore', out, err],
|
|
2360
|
+
env: childEnv,
|
|
2361
|
+
});
|
|
2362
|
+
}
|
|
2363
|
+
catch (error) {
|
|
2364
|
+
closeFileDescriptors(out, err);
|
|
2365
|
+
cleanupPidFile(pidFile);
|
|
2366
|
+
throw new Error(`Failed to spawn daemon process: ${error.message}`);
|
|
2367
|
+
}
|
|
2368
|
+
if (!child.pid) {
|
|
2369
|
+
closeFileDescriptors(out, err);
|
|
2370
|
+
cleanupPidFile(pidFile);
|
|
2371
|
+
throw new Error('Failed to spawn daemon process: no PID returned.');
|
|
2372
|
+
}
|
|
2373
|
+
child.unref();
|
|
2374
|
+
child.on('error', (error) => {
|
|
2375
|
+
logger_1.logger.error('Daemon child process failed to start:', error);
|
|
2376
|
+
cleanupPidFile(pidFile);
|
|
1865
2377
|
});
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
2378
|
+
const metadata = {
|
|
2379
|
+
pid: child.pid,
|
|
2380
|
+
scriptPath,
|
|
2381
|
+
startedAt: new Date().toISOString(),
|
|
2382
|
+
status: 'starting',
|
|
2383
|
+
};
|
|
2384
|
+
try {
|
|
2385
|
+
writePidFile(pidFile, metadata);
|
|
2386
|
+
}
|
|
2387
|
+
catch (error) {
|
|
2388
|
+
closeFileDescriptors(out, err);
|
|
2389
|
+
return failDaemonStartup(error, child.pid, pidFile);
|
|
2390
|
+
}
|
|
2391
|
+
// File descriptors are now owned by the spawned child; close our copies.
|
|
1874
2392
|
closeFileDescriptors(out, err);
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
2393
|
+
const proxyUrl = `http://127.0.0.1:${settings.devnet.rpcProxyPort}`;
|
|
2394
|
+
try {
|
|
2395
|
+
const forkState = (0, fork_1.readForkState)(settings.devnet.configPath);
|
|
2396
|
+
const timeoutMs = forkState ? FORK_NODE_READY_TIMEOUT_MS : NODE_READY_TIMEOUT_MS;
|
|
2397
|
+
// The proxy only starts after the child has a healthy CKB RPC and has
|
|
2398
|
+
// successfully spawned the miner, so this is the daemon's service-level
|
|
2399
|
+
// readiness check rather than a port/process check.
|
|
2400
|
+
const readiness = yield (0, readiness_1.waitForNodeReady)(proxyUrl, timeoutMs, () => isProcessAlive(child.pid));
|
|
2401
|
+
if (!readiness.ready) {
|
|
2402
|
+
throw new Error(`CKB devnet daemon failed to become ready. See ${logFile}. ${(_a = readiness.error) !== null && _a !== void 0 ? _a : 'Daemon process exited.'}`);
|
|
2403
|
+
}
|
|
2404
|
+
writePidFile(pidFile, Object.assign(Object.assign({}, metadata), { status: 'running' }));
|
|
2405
|
+
}
|
|
2406
|
+
catch (error) {
|
|
2407
|
+
return failDaemonStartup(error, child.pid, pidFile);
|
|
2408
|
+
}
|
|
2409
|
+
logger_1.logger.success(`CKB devnet daemon started with PID ${child.pid} and passed its RPC/proxy health check.`);
|
|
2410
|
+
logger_1.logger.info(`Logs: ${logFile}`);
|
|
2411
|
+
logger_1.logger.info(`PID file: ${pidFile}`);
|
|
2412
|
+
logger_1.logger.info('Stop the daemon with: offckb node stop');
|
|
2413
|
+
logger_1.logger.result({
|
|
2414
|
+
command: 'node',
|
|
2415
|
+
network: base_1.Network.devnet,
|
|
2416
|
+
daemon: true,
|
|
2417
|
+
pid: child.pid,
|
|
2418
|
+
rpcUrl: settings.devnet.rpcUrl,
|
|
2419
|
+
proxyUrl,
|
|
2420
|
+
logFile,
|
|
2421
|
+
pidFile,
|
|
2422
|
+
});
|
|
1881
2423
|
});
|
|
1882
|
-
const metadata = {
|
|
1883
|
-
pid: child.pid,
|
|
1884
|
-
scriptPath,
|
|
1885
|
-
startedAt: new Date().toISOString(),
|
|
1886
|
-
};
|
|
1887
|
-
writePidFile(pidFile, metadata);
|
|
1888
|
-
// File descriptors are now owned by the spawned child; close our copies.
|
|
1889
|
-
closeFileDescriptors(out, err);
|
|
1890
|
-
logger_1.logger.success(`CKB devnet daemon started with PID ${child.pid}.`);
|
|
1891
|
-
logger_1.logger.info(`Logs: ${logFile}`);
|
|
1892
|
-
logger_1.logger.info(`PID file: ${pidFile}`);
|
|
1893
|
-
logger_1.logger.info('Stop the daemon with: offckb node stop');
|
|
1894
2424
|
}
|
|
1895
2425
|
function closeFileDescriptors(...fds) {
|
|
1896
2426
|
for (const fd of fds) {
|
|
@@ -1910,24 +2440,28 @@ function stopNode() {
|
|
|
1910
2440
|
const metadata = readPidFile(pidFile);
|
|
1911
2441
|
if (!metadata) {
|
|
1912
2442
|
logger_1.logger.warn(`No daemon PID file found at ${pidFile}. Is the devnet daemon running?`);
|
|
2443
|
+
logger_1.logger.result({ command: 'node.stop', stopped: false, reason: 'not-running' });
|
|
1913
2444
|
return;
|
|
1914
2445
|
}
|
|
1915
2446
|
const pid = metadata.pid;
|
|
1916
2447
|
if (!Number.isInteger(pid) || pid <= 0) {
|
|
1917
|
-
logger_1.logger.error(`Invalid PID in ${pidFile}: ${pid}`);
|
|
1918
2448
|
cleanupPidFile(pidFile);
|
|
1919
|
-
|
|
2449
|
+
throw new Error(`Invalid PID in ${pidFile}: ${pid}`);
|
|
1920
2450
|
}
|
|
1921
|
-
|
|
2451
|
+
const processAlive = isProcessAlive(pid);
|
|
2452
|
+
if (!processAlive) {
|
|
1922
2453
|
logger_1.logger.warn(`Daemon process ${pid} is not running.`);
|
|
1923
2454
|
cleanupPidFile(pidFile);
|
|
2455
|
+
logger_1.logger.result({ command: 'node.stop', stopped: false, reason: 'stale-pid', pid });
|
|
1924
2456
|
return;
|
|
1925
2457
|
}
|
|
2458
|
+
if (metadata.status === 'starting') {
|
|
2459
|
+
throw new Error(`CKB devnet daemon startup is still in progress (PID ${pid}). Try stopping it again shortly.`);
|
|
2460
|
+
}
|
|
1926
2461
|
const identityOk = yield verifyDaemonIdentity(pid, metadata);
|
|
1927
2462
|
if (!identityOk) {
|
|
1928
|
-
|
|
2463
|
+
throw new Error(`Process ${pid} does not appear to be the offckb daemon. Refusing to send signals to avoid killing an unrelated process. ` +
|
|
1929
2464
|
`If you are sure this is the daemon, stop it manually and remove ${pidFile}.`);
|
|
1930
|
-
return;
|
|
1931
2465
|
}
|
|
1932
2466
|
logger_1.logger.info(`Stopping CKB devnet daemon (PID ${pid})...`);
|
|
1933
2467
|
try {
|
|
@@ -1938,17 +2472,13 @@ function stopNode() {
|
|
|
1938
2472
|
if (err.code === 'ESRCH') {
|
|
1939
2473
|
logger_1.logger.warn(`Daemon process ${pid} is not running.`);
|
|
1940
2474
|
cleanupPidFile(pidFile);
|
|
2475
|
+
logger_1.logger.result({ command: 'node.stop', stopped: false, reason: 'already-exited', pid });
|
|
1941
2476
|
return;
|
|
1942
2477
|
}
|
|
1943
2478
|
if (err.code === 'EPERM') {
|
|
1944
|
-
|
|
2479
|
+
throw new Error(`Permission denied when sending SIGTERM to daemon process ${pid}.`);
|
|
1945
2480
|
}
|
|
1946
|
-
|
|
1947
|
-
logger_1.logger.error(`Failed to send SIGTERM to daemon process ${pid}:`, error);
|
|
1948
|
-
}
|
|
1949
|
-
// Still try to clean up the PID file so the user can recover.
|
|
1950
|
-
cleanupPidFile(pidFile);
|
|
1951
|
-
return;
|
|
2481
|
+
throw new Error(`Failed to send SIGTERM to daemon process ${pid}: ${err.message}`);
|
|
1952
2482
|
}
|
|
1953
2483
|
const exited = yield waitForProcessExit(pid, 5000);
|
|
1954
2484
|
if (!exited) {
|
|
@@ -1957,11 +2487,12 @@ function stopNode() {
|
|
|
1957
2487
|
yield terminateProcess(pid, 'SIGKILL');
|
|
1958
2488
|
}
|
|
1959
2489
|
catch (error) {
|
|
1960
|
-
|
|
2490
|
+
throw new Error(`Failed to send SIGKILL to daemon process ${pid}: ${error.message}`);
|
|
1961
2491
|
}
|
|
1962
2492
|
}
|
|
1963
2493
|
cleanupPidFile(pidFile);
|
|
1964
2494
|
logger_1.logger.success('CKB devnet daemon stopped.');
|
|
2495
|
+
logger_1.logger.result({ command: 'node.stop', stopped: true, pid });
|
|
1965
2496
|
});
|
|
1966
2497
|
}
|
|
1967
2498
|
function nodeTestnet() {
|
|
@@ -1995,39 +2526,6 @@ function nodeMainnet() {
|
|
|
1995
2526
|
|
|
1996
2527
|
"use strict";
|
|
1997
2528
|
|
|
1998
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
1999
|
-
if (k2 === undefined) k2 = k;
|
|
2000
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
2001
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
2002
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
2003
|
-
}
|
|
2004
|
-
Object.defineProperty(o, k2, desc);
|
|
2005
|
-
}) : (function(o, m, k, k2) {
|
|
2006
|
-
if (k2 === undefined) k2 = k;
|
|
2007
|
-
o[k2] = m[k];
|
|
2008
|
-
}));
|
|
2009
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
2010
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
2011
|
-
}) : function(o, v) {
|
|
2012
|
-
o["default"] = v;
|
|
2013
|
-
});
|
|
2014
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
2015
|
-
var ownKeys = function(o) {
|
|
2016
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
2017
|
-
var ar = [];
|
|
2018
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
2019
|
-
return ar;
|
|
2020
|
-
};
|
|
2021
|
-
return ownKeys(o);
|
|
2022
|
-
};
|
|
2023
|
-
return function (mod) {
|
|
2024
|
-
if (mod && mod.__esModule) return mod;
|
|
2025
|
-
var result = {};
|
|
2026
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
2027
|
-
__setModuleDefault(result, mod);
|
|
2028
|
-
return result;
|
|
2029
|
-
};
|
|
2030
|
-
})();
|
|
2031
2529
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2032
2530
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
2033
2531
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -2042,8 +2540,7 @@ exports.status = status;
|
|
|
2042
2540
|
const setting_1 = __nccwpck_require__(25546);
|
|
2043
2541
|
const ckb_tui_1 = __nccwpck_require__(7020);
|
|
2044
2542
|
const base_1 = __nccwpck_require__(69951);
|
|
2045
|
-
const
|
|
2046
|
-
const net = __importStar(__nccwpck_require__(69278));
|
|
2543
|
+
const readiness_1 = __nccwpck_require__(19326);
|
|
2047
2544
|
const NETWORK_SETTINGS_KEY = {
|
|
2048
2545
|
[base_1.Network.devnet]: 'devnet',
|
|
2049
2546
|
[base_1.Network.testnet]: 'testnet',
|
|
@@ -2051,65 +2548,27 @@ const NETWORK_SETTINGS_KEY = {
|
|
|
2051
2548
|
};
|
|
2052
2549
|
function status(_a) {
|
|
2053
2550
|
return __awaiter(this, arguments, void 0, function* ({ network }) {
|
|
2054
|
-
var _b;
|
|
2551
|
+
var _b, _c;
|
|
2055
2552
|
// ckb-tui is an interactive terminal UI. Running it without a TTY
|
|
2056
2553
|
// (pipe, redirect, CI) would hang or produce garbage output.
|
|
2057
2554
|
if (!process.stdout.isTTY || !process.stdin.isTTY) {
|
|
2058
|
-
|
|
2059
|
-
'It cannot be used in pipes, redirects, or non-interactive environments like CI.');
|
|
2060
|
-
process.exit(1);
|
|
2555
|
+
throw new Error('The status command requires an interactive terminal (TTY). It cannot be used in pipes, redirects, or CI.');
|
|
2061
2556
|
}
|
|
2062
2557
|
const settings = (0, setting_1.readSettings)();
|
|
2063
2558
|
const networkKey = NETWORK_SETTINGS_KEY[network];
|
|
2064
2559
|
const port = settings[networkKey].rpcProxyPort;
|
|
2065
2560
|
const url = `http://127.0.0.1:${port}`;
|
|
2066
|
-
const
|
|
2067
|
-
if (!
|
|
2068
|
-
|
|
2069
|
-
return;
|
|
2561
|
+
const readiness = yield (0, readiness_1.checkNodeReadiness)(url);
|
|
2562
|
+
if (!readiness.ready) {
|
|
2563
|
+
throw new Error(`RPC proxy ${url} is not connected to a healthy ${network} node: ${(_b = readiness.error) !== null && _b !== void 0 ? _b : 'health check failed'}`);
|
|
2070
2564
|
}
|
|
2071
2565
|
const result = ckb_tui_1.CKBTui.run(['-r', url]);
|
|
2072
2566
|
// Propagate ckb-tui exit code so scripts can detect TUI failure
|
|
2073
2567
|
if (result.status !== 0) {
|
|
2074
|
-
|
|
2568
|
+
throw new Error(`ckb-tui exited with code ${(_c = result.status) !== null && _c !== void 0 ? _c : 'unknown'}`);
|
|
2075
2569
|
}
|
|
2076
2570
|
});
|
|
2077
2571
|
}
|
|
2078
|
-
function isRPCPortListening(port) {
|
|
2079
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
2080
|
-
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
|
2081
|
-
return false;
|
|
2082
|
-
}
|
|
2083
|
-
const client = new net.Socket();
|
|
2084
|
-
return new Promise((resolve) => {
|
|
2085
|
-
let settled = false;
|
|
2086
|
-
const TIMEOUT_MS = 2000;
|
|
2087
|
-
const timeout = setTimeout(() => {
|
|
2088
|
-
if (!settled) {
|
|
2089
|
-
settled = true;
|
|
2090
|
-
client.destroy();
|
|
2091
|
-
resolve(false);
|
|
2092
|
-
}
|
|
2093
|
-
}, TIMEOUT_MS);
|
|
2094
|
-
client.once('error', () => {
|
|
2095
|
-
if (!settled) {
|
|
2096
|
-
settled = true;
|
|
2097
|
-
clearTimeout(timeout);
|
|
2098
|
-
resolve(false);
|
|
2099
|
-
}
|
|
2100
|
-
});
|
|
2101
|
-
client.once('connect', () => {
|
|
2102
|
-
if (!settled) {
|
|
2103
|
-
settled = true;
|
|
2104
|
-
clearTimeout(timeout);
|
|
2105
|
-
client.end();
|
|
2106
|
-
resolve(true);
|
|
2107
|
-
}
|
|
2108
|
-
});
|
|
2109
|
-
client.connect(port, '127.0.0.1');
|
|
2110
|
-
});
|
|
2111
|
-
});
|
|
2112
|
-
}
|
|
2113
2572
|
|
|
2114
2573
|
|
|
2115
2574
|
/***/ }),
|
|
@@ -2134,7 +2593,6 @@ exports.printSystemScripts = printSystemScripts;
|
|
|
2134
2593
|
exports.printInSystemStyle = printInSystemStyle;
|
|
2135
2594
|
exports.printInLumosConfigStyle = printInLumosConfigStyle;
|
|
2136
2595
|
exports.printInCCCStyle = printInCCCStyle;
|
|
2137
|
-
exports.systemCellToScriptInfo = systemCellToScriptInfo;
|
|
2138
2596
|
exports.toLumosConfig = toLumosConfig;
|
|
2139
2597
|
const base_1 = __nccwpck_require__(69951);
|
|
2140
2598
|
const public_1 = __nccwpck_require__(84535);
|
|
@@ -2148,26 +2606,41 @@ var PrintStyle;
|
|
|
2148
2606
|
})(PrintStyle || (exports.PrintStyle = PrintStyle = {}));
|
|
2149
2607
|
function printSystemScripts(_a) {
|
|
2150
2608
|
return __awaiter(this, arguments, void 0, function* ({ style = PrintStyle.system, network = base_1.Network.devnet }) {
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2609
|
+
var _b;
|
|
2610
|
+
let systemScripts;
|
|
2611
|
+
// Display label and address prefix follow the chain the devnet actually
|
|
2612
|
+
// runs: a fork carries the source chain's genesis, scripts and prefix.
|
|
2613
|
+
let label = network.toUpperCase();
|
|
2614
|
+
let addressPrefix = network === base_1.Network.mainnet ? 'ckb' : 'ckt';
|
|
2615
|
+
if (network === base_1.Network.mainnet) {
|
|
2616
|
+
systemScripts = public_1.MAINNET_SYSTEM_SCRIPTS;
|
|
2617
|
+
}
|
|
2618
|
+
else if (network === base_1.Network.testnet) {
|
|
2619
|
+
systemScripts = public_1.TESTNET_SYSTEM_SCRIPTS;
|
|
2620
|
+
}
|
|
2621
|
+
else {
|
|
2622
|
+
const resolved = (0, private_1.resolveDevnetSystemScripts)();
|
|
2623
|
+
systemScripts = (_b = resolved === null || resolved === void 0 ? void 0 : resolved.scripts) !== null && _b !== void 0 ? _b : null;
|
|
2624
|
+
if (resolved === null || resolved === void 0 ? void 0 : resolved.forkedFrom) {
|
|
2625
|
+
label = `DEVNET (fork of ${resolved.forkedFrom.toUpperCase()})`;
|
|
2626
|
+
addressPrefix = resolved.forkedFrom === 'mainnet' ? 'ckb' : 'ckt';
|
|
2627
|
+
}
|
|
2628
|
+
}
|
|
2156
2629
|
if (!systemScripts)
|
|
2157
2630
|
return logger_1.logger.info(`SystemScripts is null, ${network}`);
|
|
2158
2631
|
if (style === PrintStyle.system) {
|
|
2159
|
-
return printInSystemStyle(systemScripts,
|
|
2632
|
+
return printInSystemStyle(systemScripts, label);
|
|
2160
2633
|
}
|
|
2161
2634
|
if (style === PrintStyle.lumos) {
|
|
2162
|
-
return printInLumosConfigStyle(systemScripts,
|
|
2635
|
+
return printInLumosConfigStyle(systemScripts, label, addressPrefix);
|
|
2163
2636
|
}
|
|
2164
2637
|
if (style === PrintStyle.ccc) {
|
|
2165
|
-
return printInCCCStyle(systemScripts,
|
|
2638
|
+
return printInCCCStyle(systemScripts, label);
|
|
2166
2639
|
}
|
|
2167
2640
|
});
|
|
2168
2641
|
}
|
|
2169
|
-
function printInSystemStyle(systemScripts,
|
|
2170
|
-
logger_1.logger.info(`*** CKB ${
|
|
2642
|
+
function printInSystemStyle(systemScripts, label) {
|
|
2643
|
+
logger_1.logger.info(`*** CKB ${label} System Scripts ***\n`);
|
|
2171
2644
|
for (const [name, script] of Object.entries(systemScripts)) {
|
|
2172
2645
|
logger_1.logger.info(`- name: ${name}`);
|
|
2173
2646
|
if (script == null) {
|
|
@@ -2180,67 +2653,16 @@ function printInSystemStyle(systemScripts, network) {
|
|
|
2180
2653
|
logger_1.logger.info(` cellDeps: ${JSON.stringify(script.script.cellDeps, null, 2)}\n`);
|
|
2181
2654
|
}
|
|
2182
2655
|
}
|
|
2183
|
-
function printInLumosConfigStyle(scripts,
|
|
2184
|
-
const config = toLumosConfig(scripts,
|
|
2185
|
-
logger_1.logger.info(`*** CKB ${
|
|
2656
|
+
function printInLumosConfigStyle(scripts, label, addressPrefix) {
|
|
2657
|
+
const config = toLumosConfig(scripts, addressPrefix);
|
|
2658
|
+
logger_1.logger.info(`*** CKB ${label} System Scripts As LumosConfig ***\n`);
|
|
2186
2659
|
logger_1.logger.info(JSON.stringify(config, null, 2));
|
|
2187
2660
|
}
|
|
2188
|
-
function printInCCCStyle(scripts,
|
|
2661
|
+
function printInCCCStyle(scripts, label) {
|
|
2189
2662
|
const knownsScripts = (0, private_1.toCCCKnownScripts)(scripts);
|
|
2190
|
-
logger_1.logger.info(`*** CKB ${
|
|
2663
|
+
logger_1.logger.info(`*** CKB ${label} System Scripts As CCC KnownScripts ***\n`);
|
|
2191
2664
|
logger_1.logger.info(JSON.stringify(knownsScripts, null, 2));
|
|
2192
2665
|
}
|
|
2193
|
-
function systemCellToScriptInfo({ cell, depType, depGroup, extraCellDeps, }) {
|
|
2194
|
-
// todo: we left the type in cellDepsInfo since it requires async fetching and
|
|
2195
|
-
// chain running to get the full type script of the type-id deps.
|
|
2196
|
-
// Also, in devnet there is no real need to auto upgrade the system scripts with type-id
|
|
2197
|
-
if (depType === 'code') {
|
|
2198
|
-
let cellDeps = [
|
|
2199
|
-
{
|
|
2200
|
-
cellDep: {
|
|
2201
|
-
outPoint: {
|
|
2202
|
-
txHash: cell.tx_hash,
|
|
2203
|
-
index: cell.index,
|
|
2204
|
-
},
|
|
2205
|
-
depType,
|
|
2206
|
-
},
|
|
2207
|
-
},
|
|
2208
|
-
];
|
|
2209
|
-
if (extraCellDeps && extraCellDeps.length > 0) {
|
|
2210
|
-
cellDeps = [...extraCellDeps, ...cellDeps];
|
|
2211
|
-
}
|
|
2212
|
-
return {
|
|
2213
|
-
codeHash: (cell.type_hash || cell.data_hash),
|
|
2214
|
-
hashType: cell.type_hash ? 'type' : 'data2',
|
|
2215
|
-
cellDeps,
|
|
2216
|
-
};
|
|
2217
|
-
}
|
|
2218
|
-
if (depType === 'depGroup') {
|
|
2219
|
-
if (!depGroup) {
|
|
2220
|
-
throw new Error('require depGroup info since the dep type is depGroup');
|
|
2221
|
-
}
|
|
2222
|
-
let cellDeps = [
|
|
2223
|
-
{
|
|
2224
|
-
cellDep: {
|
|
2225
|
-
outPoint: {
|
|
2226
|
-
txHash: depGroup.txHash,
|
|
2227
|
-
index: depGroup.index,
|
|
2228
|
-
},
|
|
2229
|
-
depType,
|
|
2230
|
-
},
|
|
2231
|
-
},
|
|
2232
|
-
];
|
|
2233
|
-
if (extraCellDeps && extraCellDeps.length > 0) {
|
|
2234
|
-
cellDeps = [...extraCellDeps, ...cellDeps];
|
|
2235
|
-
}
|
|
2236
|
-
return {
|
|
2237
|
-
codeHash: (cell.type_hash || cell.data_hash),
|
|
2238
|
-
hashType: cell.type_hash ? 'type' : 'data2',
|
|
2239
|
-
cellDeps,
|
|
2240
|
-
};
|
|
2241
|
-
}
|
|
2242
|
-
throw new Error(`unknown DepType ${depType}`);
|
|
2243
|
-
}
|
|
2244
2666
|
function toLumosConfig(scripts, addressPrefix = 'ckt') {
|
|
2245
2667
|
const config = {
|
|
2246
2668
|
PREFIX: addressPrefix,
|
|
@@ -2379,14 +2801,16 @@ const base_1 = __nccwpck_require__(69951);
|
|
|
2379
2801
|
const link_1 = __nccwpck_require__(27814);
|
|
2380
2802
|
const validator_1 = __nccwpck_require__(39534);
|
|
2381
2803
|
const logger_1 = __nccwpck_require__(65370);
|
|
2804
|
+
const private_key_1 = __nccwpck_require__(26241);
|
|
2805
|
+
const readiness_1 = __nccwpck_require__(19326);
|
|
2806
|
+
const fork_safety_1 = __nccwpck_require__(47625);
|
|
2382
2807
|
function transferAll(toAddress_1) {
|
|
2383
2808
|
return __awaiter(this, arguments, void 0, function* (toAddress, opt = { network: base_1.Network.devnet }) {
|
|
2384
2809
|
const network = opt.network;
|
|
2385
2810
|
(0, validator_1.validateNetworkOpt)(network);
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
const privateKey = opt.privkey;
|
|
2811
|
+
const privateKey = (0, private_key_1.resolvePrivateKey)(opt);
|
|
2812
|
+
(0, fork_safety_1.warnIfMainnetForkSigning)(network, privateKey);
|
|
2813
|
+
yield (0, readiness_1.warnIfForkIndexerIsBehind)(network);
|
|
2390
2814
|
const ckb = new ckb_1.CKB({ network });
|
|
2391
2815
|
const txHash = yield ckb.transferAll({
|
|
2392
2816
|
toAddress,
|
|
@@ -2394,9 +2818,12 @@ function transferAll(toAddress_1) {
|
|
|
2394
2818
|
});
|
|
2395
2819
|
if (network === 'testnet') {
|
|
2396
2820
|
logger_1.logger.info(`Successfully transfer, check ${(0, link_1.buildTestnetTxLink)(txHash)} for details.`);
|
|
2397
|
-
|
|
2821
|
+
logger_1.logger.result({ command: 'transfer-all', network, toAddress, txHash });
|
|
2822
|
+
return txHash;
|
|
2398
2823
|
}
|
|
2399
2824
|
logger_1.logger.info('Successfully transfer, txHash:', txHash);
|
|
2825
|
+
logger_1.logger.result({ command: 'transfer-all', network, toAddress, txHash });
|
|
2826
|
+
return txHash;
|
|
2400
2827
|
});
|
|
2401
2828
|
}
|
|
2402
2829
|
|
|
@@ -2423,37 +2850,61 @@ const ckb_1 = __nccwpck_require__(83748);
|
|
|
2423
2850
|
const base_1 = __nccwpck_require__(69951);
|
|
2424
2851
|
const link_1 = __nccwpck_require__(27814);
|
|
2425
2852
|
const validator_1 = __nccwpck_require__(39534);
|
|
2853
|
+
const private_key_1 = __nccwpck_require__(26241);
|
|
2854
|
+
const logger_1 = __nccwpck_require__(65370);
|
|
2855
|
+
const readiness_1 = __nccwpck_require__(19326);
|
|
2856
|
+
const fork_safety_1 = __nccwpck_require__(47625);
|
|
2426
2857
|
function transfer(toAddress_1, amount_1) {
|
|
2427
2858
|
return __awaiter(this, arguments, void 0, function* (toAddress, amount, opt = { network: base_1.Network.devnet }) {
|
|
2428
2859
|
var _a;
|
|
2429
2860
|
const network = opt.network;
|
|
2430
2861
|
(0, validator_1.validateNetworkOpt)(network);
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2862
|
+
let udtKind;
|
|
2863
|
+
let udtTypeArgs;
|
|
2864
|
+
if (opt.udtKind != null || opt.udtTypeArgs != null) {
|
|
2865
|
+
if (!opt.udtTypeArgs) {
|
|
2866
|
+
throw new Error('UDT type args are required for a UDT transfer');
|
|
2867
|
+
}
|
|
2868
|
+
(0, validator_1.validateUdtAmount)(amount);
|
|
2869
|
+
udtKind = (_a = opt.udtKind) !== null && _a !== void 0 ? _a : 'sudt';
|
|
2870
|
+
(0, validator_1.validateUdtKind)(udtKind);
|
|
2871
|
+
udtTypeArgs = (0, validator_1.validateUdtTypeArgs)(udtKind, opt.udtTypeArgs);
|
|
2872
|
+
}
|
|
2873
|
+
const privateKey = (0, private_key_1.resolvePrivateKey)(opt);
|
|
2874
|
+
const rejectInputsAtOrBeforeBlock = (0, fork_safety_1.validateMainnetForkSigning)(network, privateKey, opt.allowMainnetReplayRisk);
|
|
2875
|
+
yield (0, readiness_1.warnIfForkIndexerIsBehind)(network);
|
|
2435
2876
|
const ckb = new ckb_1.CKB({ network });
|
|
2436
|
-
if (
|
|
2437
|
-
const
|
|
2438
|
-
(0, validator_1.validateUdtKind)(kind);
|
|
2439
|
-
const udtTypeArgs = (0, validator_1.validateUdtTypeArgs)(kind, opt.udtTypeArgs);
|
|
2440
|
-
const udtType = yield ckb.buildUdtTypeScript(kind, udtTypeArgs);
|
|
2877
|
+
if (udtKind && udtTypeArgs) {
|
|
2878
|
+
const udtType = yield ckb.buildUdtTypeScript(udtKind, udtTypeArgs);
|
|
2441
2879
|
const txHash = yield ckb.udtTransfer({
|
|
2442
2880
|
toAddress,
|
|
2443
2881
|
amount,
|
|
2444
2882
|
privateKey,
|
|
2445
2883
|
udtType,
|
|
2446
|
-
kind,
|
|
2884
|
+
kind: udtKind,
|
|
2885
|
+
rejectInputsAtOrBeforeBlock,
|
|
2447
2886
|
});
|
|
2448
2887
|
(0, link_1.logTxSuccess)(network, txHash, 'transfer UDT');
|
|
2449
|
-
|
|
2888
|
+
logger_1.logger.result({
|
|
2889
|
+
command: 'udt.transfer',
|
|
2890
|
+
network,
|
|
2891
|
+
kind: udtKind,
|
|
2892
|
+
amount,
|
|
2893
|
+
typeArgs: udtTypeArgs,
|
|
2894
|
+
toAddress,
|
|
2895
|
+
txHash,
|
|
2896
|
+
});
|
|
2897
|
+
return txHash;
|
|
2450
2898
|
}
|
|
2451
2899
|
const txHash = yield ckb.transfer({
|
|
2452
2900
|
toAddress,
|
|
2453
2901
|
amountInCKB: amount,
|
|
2454
2902
|
privateKey,
|
|
2903
|
+
rejectInputsAtOrBeforeBlock,
|
|
2455
2904
|
});
|
|
2456
2905
|
(0, link_1.logTxSuccess)(network, txHash, 'transfer');
|
|
2906
|
+
logger_1.logger.result({ command: 'transfer', network, amount, toAddress, txHash });
|
|
2907
|
+
return txHash;
|
|
2457
2908
|
});
|
|
2458
2909
|
}
|
|
2459
2910
|
|
|
@@ -2481,41 +2932,65 @@ const ckb_1 = __nccwpck_require__(83748);
|
|
|
2481
2932
|
const base_1 = __nccwpck_require__(69951);
|
|
2482
2933
|
const link_1 = __nccwpck_require__(27814);
|
|
2483
2934
|
const validator_1 = __nccwpck_require__(39534);
|
|
2935
|
+
const private_key_1 = __nccwpck_require__(26241);
|
|
2936
|
+
const logger_1 = __nccwpck_require__(65370);
|
|
2937
|
+
const readiness_1 = __nccwpck_require__(19326);
|
|
2938
|
+
const fork_safety_1 = __nccwpck_require__(47625);
|
|
2484
2939
|
function udtIssue(amount_1) {
|
|
2485
|
-
return __awaiter(this, arguments, void 0, function* (amount, opt = { network: base_1.Network.devnet, udtKind: 'sudt'
|
|
2940
|
+
return __awaiter(this, arguments, void 0, function* (amount, opt = { network: base_1.Network.devnet, udtKind: 'sudt' }) {
|
|
2486
2941
|
const network = opt.network;
|
|
2487
2942
|
(0, validator_1.validateNetworkOpt)(network);
|
|
2488
2943
|
(0, validator_1.validateUdtKind)(opt.udtKind);
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2944
|
+
(0, validator_1.validateUdtAmount)(amount);
|
|
2945
|
+
const typeArgs = opt.typeArgs ? (0, validator_1.validateUdtTypeArgs)(opt.udtKind, opt.typeArgs) : undefined;
|
|
2946
|
+
const privateKey = (0, private_key_1.resolvePrivateKey)(opt);
|
|
2947
|
+
(0, fork_safety_1.warnIfMainnetForkSigning)(network, privateKey);
|
|
2948
|
+
yield (0, readiness_1.warnIfForkIndexerIsBehind)(network);
|
|
2492
2949
|
const ckb = new ckb_1.CKB({ network });
|
|
2493
|
-
const
|
|
2494
|
-
privateKey
|
|
2950
|
+
const result = yield ckb.udtIssue({
|
|
2951
|
+
privateKey,
|
|
2495
2952
|
kind: opt.udtKind,
|
|
2496
2953
|
amount,
|
|
2497
|
-
typeArgs
|
|
2954
|
+
typeArgs,
|
|
2498
2955
|
toAddress: opt.to,
|
|
2499
2956
|
});
|
|
2500
|
-
(0, link_1.logTxSuccess)(network, txHash, 'issued UDT');
|
|
2957
|
+
(0, link_1.logTxSuccess)(network, result.txHash, 'issued UDT');
|
|
2958
|
+
logger_1.logger.info(`UDT kind: ${opt.udtKind}`);
|
|
2959
|
+
logger_1.logger.info(`UDT type args: ${result.typeArgs}`);
|
|
2960
|
+
logger_1.logger.info(`Receiver: ${result.receiver}`);
|
|
2961
|
+
logger_1.logger.info(`Next: offckb balance ${result.receiver} --udt-kind ${opt.udtKind} --udt-type-args ${result.typeArgs}`);
|
|
2962
|
+
logger_1.logger.result({
|
|
2963
|
+
command: 'udt.issue',
|
|
2964
|
+
network,
|
|
2965
|
+
kind: opt.udtKind,
|
|
2966
|
+
amount,
|
|
2967
|
+
receiver: result.receiver,
|
|
2968
|
+
typeArgs: result.typeArgs,
|
|
2969
|
+
txHash: result.txHash,
|
|
2970
|
+
});
|
|
2971
|
+
return result;
|
|
2501
2972
|
});
|
|
2502
2973
|
}
|
|
2503
2974
|
function udtDestroy(amount_1) {
|
|
2504
|
-
return __awaiter(this, arguments, void 0, function* (amount, opt = { network: base_1.Network.devnet, udtKind: 'sudt', typeArgs: ''
|
|
2975
|
+
return __awaiter(this, arguments, void 0, function* (amount, opt = { network: base_1.Network.devnet, udtKind: 'sudt', typeArgs: '' }) {
|
|
2505
2976
|
const network = opt.network;
|
|
2506
2977
|
(0, validator_1.validateNetworkOpt)(network);
|
|
2507
2978
|
(0, validator_1.validateUdtKind)(opt.udtKind);
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2979
|
+
(0, validator_1.validateUdtAmount)(amount);
|
|
2980
|
+
const typeArgs = (0, validator_1.validateUdtTypeArgs)(opt.udtKind, opt.typeArgs);
|
|
2981
|
+
const privateKey = (0, private_key_1.resolvePrivateKey)(opt);
|
|
2982
|
+
(0, fork_safety_1.warnIfMainnetForkSigning)(network, privateKey);
|
|
2983
|
+
yield (0, readiness_1.warnIfForkIndexerIsBehind)(network);
|
|
2511
2984
|
const ckb = new ckb_1.CKB({ network });
|
|
2512
2985
|
const txHash = yield ckb.udtDestroy({
|
|
2513
|
-
privateKey
|
|
2986
|
+
privateKey,
|
|
2514
2987
|
kind: opt.udtKind,
|
|
2515
2988
|
amount,
|
|
2516
|
-
typeArgs
|
|
2989
|
+
typeArgs,
|
|
2517
2990
|
});
|
|
2518
2991
|
(0, link_1.logTxSuccess)(network, txHash, 'destroyed UDT');
|
|
2992
|
+
logger_1.logger.result({ command: 'udt.destroy', network, kind: opt.udtKind, amount, typeArgs, txHash });
|
|
2993
|
+
return txHash;
|
|
2519
2994
|
});
|
|
2520
2995
|
}
|
|
2521
2996
|
|
|
@@ -3487,6 +3962,640 @@ class InitializationError extends Error {
|
|
|
3487
3962
|
exports.InitializationError = InitializationError;
|
|
3488
3963
|
|
|
3489
3964
|
|
|
3965
|
+
/***/ }),
|
|
3966
|
+
|
|
3967
|
+
/***/ 77912:
|
|
3968
|
+
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
|
3969
|
+
|
|
3970
|
+
"use strict";
|
|
3971
|
+
|
|
3972
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3973
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3974
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
3975
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
3976
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
3977
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
3978
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
3979
|
+
});
|
|
3980
|
+
};
|
|
3981
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3982
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
3983
|
+
};
|
|
3984
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
3985
|
+
exports.FORK_STATE_FILE = void 0;
|
|
3986
|
+
exports.getForkStatePath = getForkStatePath;
|
|
3987
|
+
exports.readForkState = readForkState;
|
|
3988
|
+
exports.writeForkState = writeForkState;
|
|
3989
|
+
exports.markForkFirstRunComplete = markForkFirstRunComplete;
|
|
3990
|
+
exports.detectSourceFromCkbToml = detectSourceFromCkbToml;
|
|
3991
|
+
exports.parseGenesisHashFromInitOutput = parseGenesisHashFromInitOutput;
|
|
3992
|
+
exports.parseGenesisHashFromListHashes = parseGenesisHashFromListHashes;
|
|
3993
|
+
exports.expectedGenesisHash = expectedGenesisHash;
|
|
3994
|
+
exports.patchDevSpecForFork = patchDevSpecForFork;
|
|
3995
|
+
exports.copySourceData = copySourceData;
|
|
3996
|
+
exports.isolateForkCkbConfig = isolateForkCkbConfig;
|
|
3997
|
+
exports.migrationNeededFromExitCode = migrationNeededFromExitCode;
|
|
3998
|
+
exports.forkDevnet = forkDevnet;
|
|
3999
|
+
const child_process_1 = __nccwpck_require__(35317);
|
|
4000
|
+
const fs_1 = __importDefault(__nccwpck_require__(79896));
|
|
4001
|
+
const os_1 = __importDefault(__nccwpck_require__(70857));
|
|
4002
|
+
const path_1 = __importDefault(__nccwpck_require__(16928));
|
|
4003
|
+
const toml_1 = __importDefault(__nccwpck_require__(2811));
|
|
4004
|
+
const setting_1 = __nccwpck_require__(25546);
|
|
4005
|
+
const install_1 = __nccwpck_require__(65611);
|
|
4006
|
+
const fs_2 = __nccwpck_require__(37293);
|
|
4007
|
+
const request_1 = __nccwpck_require__(65897);
|
|
4008
|
+
const logger_1 = __nccwpck_require__(65370);
|
|
4009
|
+
const const_1 = __nccwpck_require__(75587);
|
|
4010
|
+
exports.FORK_STATE_FILE = 'fork.json';
|
|
4011
|
+
// The official guide requires genesis_epoch_length to stay at 1743 for a
|
|
4012
|
+
// mainnet fork, and to fall back to the default 1000 for a testnet fork
|
|
4013
|
+
// (i.e. the key must be absent). Getting this wrong produces a different
|
|
4014
|
+
// genesis hash and the node refuses to start. See nervosnetwork/ckb#5205.
|
|
4015
|
+
const MAINNET_GENESIS_EPOCH_LENGTH = 1743;
|
|
4016
|
+
function getForkStatePath(configPath) {
|
|
4017
|
+
return path_1.default.join(configPath, exports.FORK_STATE_FILE);
|
|
4018
|
+
}
|
|
4019
|
+
function readForkState(configPath) {
|
|
4020
|
+
const statePath = getForkStatePath(configPath);
|
|
4021
|
+
let raw;
|
|
4022
|
+
try {
|
|
4023
|
+
raw = fs_1.default.readFileSync(statePath, 'utf8');
|
|
4024
|
+
}
|
|
4025
|
+
catch (_a) {
|
|
4026
|
+
return null;
|
|
4027
|
+
}
|
|
4028
|
+
try {
|
|
4029
|
+
const parsed = JSON.parse(raw);
|
|
4030
|
+
if (typeof parsed.source !== 'string' || typeof parsed.firstRunPending !== 'boolean') {
|
|
4031
|
+
return null;
|
|
4032
|
+
}
|
|
4033
|
+
return parsed;
|
|
4034
|
+
}
|
|
4035
|
+
catch (_b) {
|
|
4036
|
+
return null;
|
|
4037
|
+
}
|
|
4038
|
+
}
|
|
4039
|
+
function writeForkState(configPath, state) {
|
|
4040
|
+
const statePath = getForkStatePath(configPath);
|
|
4041
|
+
const tempPath = `${statePath}.tmp`;
|
|
4042
|
+
fs_1.default.writeFileSync(tempPath, JSON.stringify(state, null, 2));
|
|
4043
|
+
fs_1.default.renameSync(tempPath, statePath);
|
|
4044
|
+
}
|
|
4045
|
+
function markForkFirstRunComplete(configPath, forkBlockNumber) {
|
|
4046
|
+
const state = readForkState(configPath);
|
|
4047
|
+
if (!state || !state.firstRunPending)
|
|
4048
|
+
return;
|
|
4049
|
+
writeForkState(configPath, Object.assign(Object.assign(Object.assign({}, state), { firstRunPending: false }), (forkBlockNumber == null ? {} : { forkBlockNumber })));
|
|
4050
|
+
}
|
|
4051
|
+
function detectSourceFromCkbToml(ckbTomlContent) {
|
|
4052
|
+
let parsed;
|
|
4053
|
+
try {
|
|
4054
|
+
parsed = toml_1.default.parse(ckbTomlContent);
|
|
4055
|
+
}
|
|
4056
|
+
catch (_a) {
|
|
4057
|
+
return null;
|
|
4058
|
+
}
|
|
4059
|
+
const chain = parsed.chain;
|
|
4060
|
+
if (chain == null || typeof chain !== 'object')
|
|
4061
|
+
return null;
|
|
4062
|
+
const spec = chain.spec;
|
|
4063
|
+
if (spec == null || typeof spec !== 'object')
|
|
4064
|
+
return null;
|
|
4065
|
+
const bundled = spec.bundled;
|
|
4066
|
+
if (typeof bundled !== 'string')
|
|
4067
|
+
return null;
|
|
4068
|
+
if (bundled.includes('mainnet'))
|
|
4069
|
+
return 'mainnet';
|
|
4070
|
+
if (bundled.includes('testnet'))
|
|
4071
|
+
return 'testnet';
|
|
4072
|
+
return null;
|
|
4073
|
+
}
|
|
4074
|
+
function parseGenesisHashFromInitOutput(output) {
|
|
4075
|
+
const match = output.match(/Genesis Hash:\s*(0x[0-9a-fA-F]{64})/);
|
|
4076
|
+
return match ? match[1].toLowerCase() : null;
|
|
4077
|
+
}
|
|
4078
|
+
// `ckb list-hashes` prints TOML with a single table whose `genesis` field is
|
|
4079
|
+
// the chain's genesis hash.
|
|
4080
|
+
function parseGenesisHashFromListHashes(output) {
|
|
4081
|
+
const match = output.match(/^\s*genesis\s*=\s*"(0x[0-9a-fA-F]{64})"\s*$/m);
|
|
4082
|
+
return match ? match[1].toLowerCase() : null;
|
|
4083
|
+
}
|
|
4084
|
+
function expectedGenesisHash(source) {
|
|
4085
|
+
return source === 'mainnet' ? const_1.MAINNET_GENESIS_HASH : const_1.TESTNET_GENESIS_HASH;
|
|
4086
|
+
}
|
|
4087
|
+
// Patch the imported chain spec into a minable dev chain, following
|
|
4088
|
+
// https://docs.nervos.org/docs/node/devnet-from-existing-data
|
|
4089
|
+
function patchDevSpecForFork(spec, source) {
|
|
4090
|
+
var _a, _b;
|
|
4091
|
+
const pow = Object.assign(Object.assign({}, ((_a = spec.pow) !== null && _a !== void 0 ? _a : {})), { func: 'Dummy' });
|
|
4092
|
+
const params = Object.assign({}, ((_b = spec.params) !== null && _b !== void 0 ? _b : {}));
|
|
4093
|
+
params.cellbase_maturity = 0;
|
|
4094
|
+
params.permanent_difficulty_in_dummy = true;
|
|
4095
|
+
if (source === 'mainnet') {
|
|
4096
|
+
params.genesis_epoch_length = MAINNET_GENESIS_EPOCH_LENGTH;
|
|
4097
|
+
}
|
|
4098
|
+
else if (source === 'testnet') {
|
|
4099
|
+
// testnet derives genesis_epoch_length from the default (1000); a leftover
|
|
4100
|
+
// mainnet value here is exactly the nervosnetwork/ckb#5205 trap.
|
|
4101
|
+
delete params.genesis_epoch_length;
|
|
4102
|
+
}
|
|
4103
|
+
// custom specs keep whatever genesis_epoch_length they declared
|
|
4104
|
+
return Object.assign(Object.assign({}, spec), { pow, params });
|
|
4105
|
+
}
|
|
4106
|
+
function validateSourceDir(sourceDir) {
|
|
4107
|
+
if (!(0, fs_2.isFolderExists)(sourceDir)) {
|
|
4108
|
+
throw new Error(`Source directory does not exist: ${sourceDir}`);
|
|
4109
|
+
}
|
|
4110
|
+
if (!(0, fs_2.isFolderExists)(path_1.default.join(sourceDir, 'data', 'db'))) {
|
|
4111
|
+
throw new Error(`${sourceDir} does not look like a CKB node directory (missing data/db). ` +
|
|
4112
|
+
`Point --from at the directory the source node runs with (-C).`);
|
|
4113
|
+
}
|
|
4114
|
+
}
|
|
4115
|
+
// Best-effort detection of a running ckb process using the given directory.
|
|
4116
|
+
// Returns null when the check cannot be performed (Windows, no ps).
|
|
4117
|
+
function isCkbNodeRunningOn(dir) {
|
|
4118
|
+
if (process.platform === 'win32')
|
|
4119
|
+
return null;
|
|
4120
|
+
let processes = '';
|
|
4121
|
+
try {
|
|
4122
|
+
processes = (0, child_process_1.execSync)('ps -eo args', { encoding: 'utf8', maxBuffer: 16 * 1024 * 1024 });
|
|
4123
|
+
}
|
|
4124
|
+
catch (_a) {
|
|
4125
|
+
return null;
|
|
4126
|
+
}
|
|
4127
|
+
return processes.split('\n').some((line) => {
|
|
4128
|
+
var _a;
|
|
4129
|
+
const tokens = line.trim().split(/\s+/);
|
|
4130
|
+
// The program itself must be a ckb binary — a looser match would flag
|
|
4131
|
+
// unrelated processes that merely mention the directory.
|
|
4132
|
+
const program = path_1.default.basename((_a = tokens[0]) !== null && _a !== void 0 ? _a : '');
|
|
4133
|
+
if (program !== 'ckb' && program !== 'ckb.exe')
|
|
4134
|
+
return false;
|
|
4135
|
+
return tokens.includes('run') && line.includes(dir);
|
|
4136
|
+
});
|
|
4137
|
+
}
|
|
4138
|
+
function assertSourceNodeStopped(sourceDir) {
|
|
4139
|
+
const running = isCkbNodeRunningOn(sourceDir);
|
|
4140
|
+
if (running === null) {
|
|
4141
|
+
logger_1.logger.warn('Make sure the source CKB node is stopped; copying a live database produces corrupted data.');
|
|
4142
|
+
return;
|
|
4143
|
+
}
|
|
4144
|
+
if (running) {
|
|
4145
|
+
throw new Error(`A CKB node appears to be running on ${sourceDir}. Stop it first; ` +
|
|
4146
|
+
`copying a live database produces corrupted data.`);
|
|
4147
|
+
}
|
|
4148
|
+
}
|
|
4149
|
+
function assertOffckbDevnetStopped() {
|
|
4150
|
+
const settings = (0, setting_1.readSettings)();
|
|
4151
|
+
// Foreground `offckb node` (no daemon pid file): look for the ckb process.
|
|
4152
|
+
if (isCkbNodeRunningOn(settings.devnet.configPath) === true) {
|
|
4153
|
+
throw new Error('An offckb devnet node appears to be running. Stop it before forking.');
|
|
4154
|
+
}
|
|
4155
|
+
// Daemon mode: check the pid file.
|
|
4156
|
+
const pidFile = path_1.default.join(settings.devnet.dataPath, 'logs', 'daemon.pid');
|
|
4157
|
+
let raw;
|
|
4158
|
+
try {
|
|
4159
|
+
raw = fs_1.default.readFileSync(pidFile, 'utf8').trim();
|
|
4160
|
+
}
|
|
4161
|
+
catch (_a) {
|
|
4162
|
+
return;
|
|
4163
|
+
}
|
|
4164
|
+
let pid = Number(raw);
|
|
4165
|
+
if (!Number.isInteger(pid) || pid <= 0) {
|
|
4166
|
+
try {
|
|
4167
|
+
pid = Number(JSON.parse(raw).pid);
|
|
4168
|
+
}
|
|
4169
|
+
catch (_b) {
|
|
4170
|
+
return;
|
|
4171
|
+
}
|
|
4172
|
+
}
|
|
4173
|
+
if (!Number.isInteger(pid) || pid <= 0)
|
|
4174
|
+
return;
|
|
4175
|
+
let alive = true;
|
|
4176
|
+
try {
|
|
4177
|
+
process.kill(pid, 0);
|
|
4178
|
+
}
|
|
4179
|
+
catch (_c) {
|
|
4180
|
+
alive = false; // ESRCH: stale pid file, no daemon running
|
|
4181
|
+
}
|
|
4182
|
+
if (alive) {
|
|
4183
|
+
throw new Error(`The offckb devnet daemon is running (PID ${pid}). Stop it first with: offckb node stop`);
|
|
4184
|
+
}
|
|
4185
|
+
}
|
|
4186
|
+
function resolveSpecFile(options, source, ckbVersion) {
|
|
4187
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
4188
|
+
if (options.specFile) {
|
|
4189
|
+
const specFile = path_1.default.resolve(options.specFile);
|
|
4190
|
+
if (!fs_1.default.existsSync(specFile)) {
|
|
4191
|
+
throw new Error(`Spec file not found: ${specFile}`);
|
|
4192
|
+
}
|
|
4193
|
+
return specFile;
|
|
4194
|
+
}
|
|
4195
|
+
const cacheDir = path_1.default.join(setting_1.cachePath, 'specs', ckbVersion);
|
|
4196
|
+
const cachedSpec = path_1.default.join(cacheDir, `${source}.toml`);
|
|
4197
|
+
if (fs_1.default.existsSync(cachedSpec)) {
|
|
4198
|
+
logger_1.logger.debug(`Using cached ${source} spec: ${cachedSpec}`);
|
|
4199
|
+
return cachedSpec;
|
|
4200
|
+
}
|
|
4201
|
+
const url = `https://raw.githubusercontent.com/nervosnetwork/ckb/v${ckbVersion}/resource/specs/${source}.toml`;
|
|
4202
|
+
logger_1.logger.info(`Downloading ${source} chain spec from ${url} ..`);
|
|
4203
|
+
try {
|
|
4204
|
+
const response = yield request_1.Request.send(url);
|
|
4205
|
+
const content = yield response.text();
|
|
4206
|
+
fs_1.default.mkdirSync(cacheDir, { recursive: true });
|
|
4207
|
+
fs_1.default.writeFileSync(cachedSpec, content);
|
|
4208
|
+
return cachedSpec;
|
|
4209
|
+
}
|
|
4210
|
+
catch (error) {
|
|
4211
|
+
throw new Error(`Failed to download the ${source} chain spec for CKB v${ckbVersion}: ${error.message}. ` +
|
|
4212
|
+
`Pass a local copy with --spec-file.`);
|
|
4213
|
+
}
|
|
4214
|
+
});
|
|
4215
|
+
}
|
|
4216
|
+
function copySourceData(sourceDir, configPath) {
|
|
4217
|
+
const sourceData = path_1.default.join(sourceDir, 'data');
|
|
4218
|
+
const targetData = path_1.default.join(configPath, 'data');
|
|
4219
|
+
logger_1.logger.info(`Copying chain data from ${sourceData} to ${targetData} ..`);
|
|
4220
|
+
logger_1.logger.info('This can take a while for large chains.');
|
|
4221
|
+
fs_1.default.mkdirSync(configPath, { recursive: true });
|
|
4222
|
+
// Full copy on purpose: never hardlink — RocksDB appends to WAL/MANIFEST in
|
|
4223
|
+
// place, and linked files would corrupt the source chain.
|
|
4224
|
+
const excludedTopLevelEntries = new Set(['network', 'logs', 'tmp']);
|
|
4225
|
+
fs_1.default.mkdirSync(targetData, { recursive: true });
|
|
4226
|
+
// Enumerate top-level entries instead of relying on fs.cp's filter paths,
|
|
4227
|
+
// which may use Windows extended-length prefixes and bypass relative-path
|
|
4228
|
+
// comparisons.
|
|
4229
|
+
for (const entry of fs_1.default.readdirSync(sourceData)) {
|
|
4230
|
+
if (excludedTopLevelEntries.has(entry))
|
|
4231
|
+
continue;
|
|
4232
|
+
fs_1.default.cpSync(path_1.default.join(sourceData, entry), path_1.default.join(targetData, entry), { recursive: true });
|
|
4233
|
+
}
|
|
4234
|
+
logger_1.logger.info('Excluded source network peers and transient logs/tmp data from the fork.');
|
|
4235
|
+
}
|
|
4236
|
+
function isolateForkCkbConfig(config) {
|
|
4237
|
+
var _a, _b;
|
|
4238
|
+
const network = Object.assign({}, ((_a = config.network) !== null && _a !== void 0 ? _a : {}));
|
|
4239
|
+
network.bootnodes = [];
|
|
4240
|
+
network.max_outbound_peers = 0;
|
|
4241
|
+
network.whitelist_only = true;
|
|
4242
|
+
network.discovery_local_address = false;
|
|
4243
|
+
const loggerConfig = Object.assign({}, ((_b = config.logger) !== null && _b !== void 0 ? _b : {}));
|
|
4244
|
+
loggerConfig.filter = 'warn';
|
|
4245
|
+
return Object.assign(Object.assign({}, config), { network, logger: loggerConfig });
|
|
4246
|
+
}
|
|
4247
|
+
function runCkbInit(ckbBinPath, configPath, specFile) {
|
|
4248
|
+
// argv form, never a shell: --spec-file is user input and quote-wrapping
|
|
4249
|
+
// alone does not stop shell expansion (command substitution still runs
|
|
4250
|
+
// inside double quotes).
|
|
4251
|
+
const args = ['init', '-C', configPath, '--chain', 'dev', '--import-spec', specFile, '--force'];
|
|
4252
|
+
logger_1.logger.debug(`Running: ${ckbBinPath} ${args.join(' ')}`);
|
|
4253
|
+
return (0, child_process_1.execFileSync)(ckbBinPath, args, {
|
|
4254
|
+
encoding: 'utf8',
|
|
4255
|
+
maxBuffer: 16 * 1024 * 1024,
|
|
4256
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
4257
|
+
});
|
|
4258
|
+
}
|
|
4259
|
+
function migrationNeededFromExitCode(status) {
|
|
4260
|
+
if (status === 0)
|
|
4261
|
+
return true;
|
|
4262
|
+
if (status === 64)
|
|
4263
|
+
return false;
|
|
4264
|
+
throw new Error(`ckb migrate --check failed with exit code ${status !== null && status !== void 0 ? status : 'unknown'}`);
|
|
4265
|
+
}
|
|
4266
|
+
function isDatabaseMigrationNeeded(ckbBinPath, configPath) {
|
|
4267
|
+
const result = (0, child_process_1.spawnSync)(ckbBinPath, ['migrate', '--check', '-C', configPath], {
|
|
4268
|
+
encoding: 'utf8',
|
|
4269
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
4270
|
+
});
|
|
4271
|
+
if (result.error) {
|
|
4272
|
+
throw new Error(`Could not check the CKB database version: ${result.error.message}`);
|
|
4273
|
+
}
|
|
4274
|
+
try {
|
|
4275
|
+
return migrationNeededFromExitCode(result.status);
|
|
4276
|
+
}
|
|
4277
|
+
catch (error) {
|
|
4278
|
+
const details = [result.stdout, result.stderr].filter(Boolean).join('\n').trim();
|
|
4279
|
+
throw new Error(`${error.message}${details ? `: ${details}` : ''}`);
|
|
4280
|
+
}
|
|
4281
|
+
}
|
|
4282
|
+
function migrateDatabaseCopy(ckbBinPath, configPath) {
|
|
4283
|
+
var _a, _b;
|
|
4284
|
+
logger_1.logger.info('Migrating the copied database (the source directory remains untouched) ..');
|
|
4285
|
+
const result = (0, child_process_1.spawnSync)(ckbBinPath, ['migrate', '--force', '-C', configPath], {
|
|
4286
|
+
encoding: 'utf8',
|
|
4287
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
4288
|
+
});
|
|
4289
|
+
if (result.error || result.status !== 0) {
|
|
4290
|
+
const details = [result.stdout, result.stderr].filter(Boolean).join('\n').trim();
|
|
4291
|
+
throw new Error(`Failed to migrate the copied database: ${(_b = (_a = result.error) === null || _a === void 0 ? void 0 : _a.message) !== null && _b !== void 0 ? _b : `exit code ${result.status}`}` +
|
|
4292
|
+
`${details ? `\n${details}` : ''}`);
|
|
4293
|
+
}
|
|
4294
|
+
logger_1.logger.success('Copied database migration completed.');
|
|
4295
|
+
}
|
|
4296
|
+
// Best-effort read of the source directory's own chain identity. `ckb
|
|
4297
|
+
// list-hashes` resolves the chain spec of the given config dir (no database
|
|
4298
|
+
// access needed), which tells us which chain the source node was configured
|
|
4299
|
+
// for. Returns null when the source is not a standard config dir.
|
|
4300
|
+
function readSourceGenesisHash(ckbBinPath, sourceDir) {
|
|
4301
|
+
try {
|
|
4302
|
+
const output = (0, child_process_1.execFileSync)(ckbBinPath, ['list-hashes', '-C', sourceDir], {
|
|
4303
|
+
encoding: 'utf8',
|
|
4304
|
+
maxBuffer: 16 * 1024 * 1024,
|
|
4305
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
4306
|
+
});
|
|
4307
|
+
return parseGenesisHashFromListHashes(output);
|
|
4308
|
+
}
|
|
4309
|
+
catch (_a) {
|
|
4310
|
+
return null;
|
|
4311
|
+
}
|
|
4312
|
+
}
|
|
4313
|
+
function validateForkSpec(ckbBinPath, sourceDir, specFile, declaredSource) {
|
|
4314
|
+
var _a;
|
|
4315
|
+
const tempConfigPath = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'offckb-fork-preflight-'));
|
|
4316
|
+
try {
|
|
4317
|
+
const initOutput = runCkbInit(ckbBinPath, tempConfigPath, specFile);
|
|
4318
|
+
const genesisHash = parseGenesisHashFromInitOutput(initOutput);
|
|
4319
|
+
if (!genesisHash) {
|
|
4320
|
+
throw new Error(`Could not parse the genesis hash from ckb init output:\n${initOutput}`);
|
|
4321
|
+
}
|
|
4322
|
+
const source = (_a = declaredSource !== null && declaredSource !== void 0 ? declaredSource : (0, const_1.identifyPublicChainByGenesisHash)(genesisHash)) !== null && _a !== void 0 ? _a : 'custom';
|
|
4323
|
+
if (source !== 'custom') {
|
|
4324
|
+
const expected = expectedGenesisHash(source);
|
|
4325
|
+
if (genesisHash !== expected) {
|
|
4326
|
+
throw new Error(`Genesis hash mismatch: expected ${expected} for ${source}, got ${genesisHash}. ` +
|
|
4327
|
+
'This usually means the chain spec does not match the source data.');
|
|
4328
|
+
}
|
|
4329
|
+
}
|
|
4330
|
+
const sourceGenesisHash = readSourceGenesisHash(ckbBinPath, sourceDir);
|
|
4331
|
+
if (sourceGenesisHash && sourceGenesisHash !== genesisHash) {
|
|
4332
|
+
throw new Error(`The source directory is configured for a different chain (genesis ${sourceGenesisHash}) ` +
|
|
4333
|
+
`than the imported spec (genesis ${genesisHash}). Pass a matching --source or --spec-file.`);
|
|
4334
|
+
}
|
|
4335
|
+
return { source, genesisHash };
|
|
4336
|
+
}
|
|
4337
|
+
finally {
|
|
4338
|
+
fs_1.default.rmSync(tempConfigPath, { recursive: true, force: true });
|
|
4339
|
+
}
|
|
4340
|
+
}
|
|
4341
|
+
// Overwrite the ckb-init-generated configs with offckb's own devnet configs so
|
|
4342
|
+
// the fork behaves like a normal offckb devnet (miner account as block
|
|
4343
|
+
// assembler, RPC on 8114 with the Indexer module, proxy on 28114). The
|
|
4344
|
+
// imported specs/dev.toml is kept.
|
|
4345
|
+
function alignConfigsWithOffckb(configPath) {
|
|
4346
|
+
const settings = (0, setting_1.readSettings)();
|
|
4347
|
+
const devnetSourcePath = path_1.default.resolve(setting_1.packageRootPath, './ckb/devnet');
|
|
4348
|
+
const ckbConfigPath = path_1.default.join(configPath, 'ckb.toml');
|
|
4349
|
+
const parsedCkbConfig = toml_1.default.parse(fs_1.default.readFileSync(path_1.default.join(devnetSourcePath, 'ckb.toml'), 'utf8'));
|
|
4350
|
+
const ckbConfig = isolateForkCkbConfig(parsedCkbConfig);
|
|
4351
|
+
fs_1.default.writeFileSync(ckbConfigPath, toml_1.default.stringify(ckbConfig));
|
|
4352
|
+
fs_1.default.copyFileSync(path_1.default.join(devnetSourcePath, 'default.db-options'), path_1.default.join(configPath, 'default.db-options'));
|
|
4353
|
+
const minerToml = fs_1.default.readFileSync(path_1.default.join(devnetSourcePath, 'ckb-miner.toml'), 'utf8');
|
|
4354
|
+
fs_1.default.writeFileSync(path_1.default.join(configPath, 'ckb-miner.toml'), minerToml.replace('http://ckb:8114/', settings.devnet.rpcUrl));
|
|
4355
|
+
}
|
|
4356
|
+
function forkDevnet(options) {
|
|
4357
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
4358
|
+
var _a;
|
|
4359
|
+
if (!options.from) {
|
|
4360
|
+
throw new Error('Database fork requires a source CKB directory: --from <dir>.');
|
|
4361
|
+
}
|
|
4362
|
+
const settings = (0, setting_1.readSettings)();
|
|
4363
|
+
const configPath = settings.devnet.configPath;
|
|
4364
|
+
const ckbVersion = settings.bins.defaultCKBVersion;
|
|
4365
|
+
const sourceDir = path_1.default.resolve(options.from);
|
|
4366
|
+
validateSourceDir(sourceDir);
|
|
4367
|
+
assertSourceNodeStopped(sourceDir);
|
|
4368
|
+
// Identify the source chain: explicit flag > ckb.toml bundled spec.
|
|
4369
|
+
let source = (_a = options.source) !== null && _a !== void 0 ? _a : null;
|
|
4370
|
+
if (source == null) {
|
|
4371
|
+
const sourceCkbToml = path_1.default.join(sourceDir, 'ckb.toml');
|
|
4372
|
+
if (fs_1.default.existsSync(sourceCkbToml)) {
|
|
4373
|
+
source = detectSourceFromCkbToml(fs_1.default.readFileSync(sourceCkbToml, 'utf8'));
|
|
4374
|
+
}
|
|
4375
|
+
}
|
|
4376
|
+
if (source == null && !options.specFile) {
|
|
4377
|
+
throw new Error('Could not identify the source chain from the source directory. ' +
|
|
4378
|
+
'Pass --source mainnet|testnet, or provide the chain spec with --spec-file.');
|
|
4379
|
+
}
|
|
4380
|
+
yield (0, install_1.installCKBBinary)(ckbVersion);
|
|
4381
|
+
const ckbBinPath = (0, setting_1.getCKBBinaryPath)(ckbVersion);
|
|
4382
|
+
const databaseMigrationNeeded = isDatabaseMigrationNeeded(ckbBinPath, sourceDir);
|
|
4383
|
+
const sourcePeerStoreDetected = fs_1.default.existsSync(path_1.default.join(sourceDir, 'data', 'network', 'peer_store'));
|
|
4384
|
+
const specFile = yield resolveSpecFile(options, source !== null && source !== void 0 ? source : 'mainnet', ckbVersion);
|
|
4385
|
+
const specPreflight = validateForkSpec(ckbBinPath, sourceDir, specFile, source);
|
|
4386
|
+
source = specPreflight.source;
|
|
4387
|
+
logger_1.logger.info(`Fork preflight: source=${source}, genesis=${specPreflight.genesisHash}, CKB=${ckbVersion}, migration=${databaseMigrationNeeded ? 'required' : 'not required'}.`);
|
|
4388
|
+
if (sourcePeerStoreDetected) {
|
|
4389
|
+
logger_1.logger.info('A persisted source peer store was detected and will be excluded from the fork.');
|
|
4390
|
+
}
|
|
4391
|
+
if (options.dryRun) {
|
|
4392
|
+
logger_1.logger.success('Fork preflight passed. No devnet files were changed.');
|
|
4393
|
+
logger_1.logger.result({
|
|
4394
|
+
command: 'devnet.fork.preflight',
|
|
4395
|
+
sourceDir,
|
|
4396
|
+
source,
|
|
4397
|
+
genesisHash: specPreflight.genesisHash,
|
|
4398
|
+
ckbVersion,
|
|
4399
|
+
databaseMigrationNeeded,
|
|
4400
|
+
sourcePeerStoreDetected,
|
|
4401
|
+
sourcePeerStoreWillBeExcluded: true,
|
|
4402
|
+
targetDir: configPath,
|
|
4403
|
+
});
|
|
4404
|
+
return;
|
|
4405
|
+
}
|
|
4406
|
+
assertOffckbDevnetStopped();
|
|
4407
|
+
if (databaseMigrationNeeded && !options.migrate) {
|
|
4408
|
+
throw new Error(`The source database requires migration for CKB v${ckbVersion}. ` +
|
|
4409
|
+
'Re-run with --migrate to migrate only the copied devnet, leaving the source untouched.');
|
|
4410
|
+
}
|
|
4411
|
+
if ((0, fs_2.isFolderExists)(configPath)) {
|
|
4412
|
+
if (!options.force) {
|
|
4413
|
+
throw new Error(`A devnet already exists at ${configPath}. Re-run with --force to replace it, ` +
|
|
4414
|
+
`or reset it first with: offckb clean`);
|
|
4415
|
+
}
|
|
4416
|
+
logger_1.logger.info(`Removing existing devnet at ${configPath} ..`);
|
|
4417
|
+
fs_1.default.rmSync(configPath, { recursive: true, force: true });
|
|
4418
|
+
}
|
|
4419
|
+
try {
|
|
4420
|
+
// Inside the try so a failed copy (disk full, permissions, I/O) gets the
|
|
4421
|
+
// same rollback: a partial configPath would otherwise block the next
|
|
4422
|
+
// attempt as an "existing devnet".
|
|
4423
|
+
copySourceData(sourceDir, configPath);
|
|
4424
|
+
const initOutput = runCkbInit(ckbBinPath, configPath, specFile);
|
|
4425
|
+
const genesisHash = parseGenesisHashFromInitOutput(initOutput);
|
|
4426
|
+
if (!genesisHash) {
|
|
4427
|
+
throw new Error(`Could not parse the genesis hash from ckb init output:\n${initOutput}`);
|
|
4428
|
+
}
|
|
4429
|
+
if (genesisHash !== specPreflight.genesisHash) {
|
|
4430
|
+
throw new Error(`Chain spec changed after preflight: expected genesis ${specPreflight.genesisHash}, got ${genesisHash}.`);
|
|
4431
|
+
}
|
|
4432
|
+
const devSpecPath = path_1.default.join(configPath, 'specs', 'dev.toml');
|
|
4433
|
+
const spec = toml_1.default.parse(fs_1.default.readFileSync(devSpecPath, 'utf8'));
|
|
4434
|
+
const patched = patchDevSpecForFork(spec, source);
|
|
4435
|
+
const tempSpecPath = `${devSpecPath}.tmp`;
|
|
4436
|
+
fs_1.default.writeFileSync(tempSpecPath, toml_1.default.stringify(patched));
|
|
4437
|
+
fs_1.default.renameSync(tempSpecPath, devSpecPath);
|
|
4438
|
+
alignConfigsWithOffckb(configPath);
|
|
4439
|
+
if (databaseMigrationNeeded) {
|
|
4440
|
+
migrateDatabaseCopy(ckbBinPath, configPath);
|
|
4441
|
+
}
|
|
4442
|
+
const state = {
|
|
4443
|
+
source,
|
|
4444
|
+
sourceDir,
|
|
4445
|
+
ckbVersion,
|
|
4446
|
+
genesisHash,
|
|
4447
|
+
forkedAt: new Date().toISOString(),
|
|
4448
|
+
firstRunPending: true,
|
|
4449
|
+
databaseMigrated: databaseMigrationNeeded,
|
|
4450
|
+
networkIsolated: true,
|
|
4451
|
+
};
|
|
4452
|
+
writeForkState(configPath, state);
|
|
4453
|
+
logger_1.logger.success(`Devnet forked from ${sourceDir} (${source}, genesis ${genesisHash}).`);
|
|
4454
|
+
logger_1.logger.info('Start it with: offckb node --daemon');
|
|
4455
|
+
logger_1.logger.info('The first run applies --skip-spec-check --overwrite-spec automatically.');
|
|
4456
|
+
logger_1.logger.info('Then inspect node, Indexer, and network isolation with: offckb devnet info');
|
|
4457
|
+
logger_1.logger.info('List source-prefix dev addresses with: offckb accounts');
|
|
4458
|
+
if (source === 'mainnet') {
|
|
4459
|
+
logger_1.logger.warn('MAINNET FORK REPLAY RISK: only sign with built-in dev keys and fork-mined cells.');
|
|
4460
|
+
}
|
|
4461
|
+
logger_1.logger.result({
|
|
4462
|
+
command: 'devnet.fork',
|
|
4463
|
+
sourceDir,
|
|
4464
|
+
source,
|
|
4465
|
+
genesisHash,
|
|
4466
|
+
ckbVersion,
|
|
4467
|
+
databaseMigrated: databaseMigrationNeeded,
|
|
4468
|
+
networkIsolated: true,
|
|
4469
|
+
next: ['offckb node --daemon', 'offckb devnet info', 'offckb accounts'],
|
|
4470
|
+
});
|
|
4471
|
+
}
|
|
4472
|
+
catch (error) {
|
|
4473
|
+
// Leave no half-forked devnet behind.
|
|
4474
|
+
fs_1.default.rmSync(configPath, { recursive: true, force: true });
|
|
4475
|
+
throw error;
|
|
4476
|
+
}
|
|
4477
|
+
});
|
|
4478
|
+
}
|
|
4479
|
+
|
|
4480
|
+
|
|
4481
|
+
/***/ }),
|
|
4482
|
+
|
|
4483
|
+
/***/ 19326:
|
|
4484
|
+
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
|
4485
|
+
|
|
4486
|
+
"use strict";
|
|
4487
|
+
|
|
4488
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
4489
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4490
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4491
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
4492
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
4493
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
4494
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
4495
|
+
});
|
|
4496
|
+
};
|
|
4497
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
4498
|
+
exports.checkNodeReadiness = checkNodeReadiness;
|
|
4499
|
+
exports.waitForNodeReady = waitForNodeReady;
|
|
4500
|
+
exports.checkConfiguredDevnetReadiness = checkConfiguredDevnetReadiness;
|
|
4501
|
+
exports.warnIfForkIndexerIsBehind = warnIfForkIndexerIsBehind;
|
|
4502
|
+
const setting_1 = __nccwpck_require__(25546);
|
|
4503
|
+
const base_1 = __nccwpck_require__(69951);
|
|
4504
|
+
const logger_1 = __nccwpck_require__(65370);
|
|
4505
|
+
const json_rpc_1 = __nccwpck_require__(51726);
|
|
4506
|
+
const fork_1 = __nccwpck_require__(77912);
|
|
4507
|
+
function parseHexNumber(value) {
|
|
4508
|
+
if (typeof value !== 'string' || !/^0x[0-9a-f]+$/i.test(value))
|
|
4509
|
+
return undefined;
|
|
4510
|
+
return BigInt(value);
|
|
4511
|
+
}
|
|
4512
|
+
function checkNodeReadiness(rpcUrl_1) {
|
|
4513
|
+
return __awaiter(this, arguments, void 0, function* (rpcUrl, timeoutMs = 3000) {
|
|
4514
|
+
try {
|
|
4515
|
+
const [nodeInfo, tipValue] = yield Promise.all([
|
|
4516
|
+
(0, json_rpc_1.callJsonRpc)(rpcUrl, 'local_node_info', [], timeoutMs),
|
|
4517
|
+
(0, json_rpc_1.callJsonRpc)(rpcUrl, 'get_tip_block_number', [], timeoutMs),
|
|
4518
|
+
]);
|
|
4519
|
+
const nodeTip = parseHexNumber(tipValue);
|
|
4520
|
+
if (nodeTip == null) {
|
|
4521
|
+
throw new Error(`Invalid node tip returned by ${rpcUrl}`);
|
|
4522
|
+
}
|
|
4523
|
+
let indexerTip;
|
|
4524
|
+
try {
|
|
4525
|
+
const value = yield (0, json_rpc_1.callJsonRpc)(rpcUrl, 'get_indexer_tip', [], timeoutMs);
|
|
4526
|
+
indexerTip = parseHexNumber(value === null || value === void 0 ? void 0 : value.block_number);
|
|
4527
|
+
}
|
|
4528
|
+
catch (_a) {
|
|
4529
|
+
// Indexer readiness is reported separately and does not make the node RPC unhealthy.
|
|
4530
|
+
}
|
|
4531
|
+
let peers;
|
|
4532
|
+
try {
|
|
4533
|
+
const value = yield (0, json_rpc_1.callJsonRpc)(rpcUrl, 'get_peers', [], timeoutMs);
|
|
4534
|
+
peers = Array.isArray(value) ? value.length : undefined;
|
|
4535
|
+
}
|
|
4536
|
+
catch (_b) {
|
|
4537
|
+
// The Net RPC module can be disabled on custom nodes.
|
|
4538
|
+
}
|
|
4539
|
+
const indexerLag = indexerTip == null ? undefined : indexerTip >= nodeTip ? BigInt(0) : nodeTip - indexerTip;
|
|
4540
|
+
return {
|
|
4541
|
+
ready: true,
|
|
4542
|
+
rpcUrl,
|
|
4543
|
+
version: typeof (nodeInfo === null || nodeInfo === void 0 ? void 0 : nodeInfo.version) === 'string' ? nodeInfo.version : undefined,
|
|
4544
|
+
nodeTip,
|
|
4545
|
+
indexerTip,
|
|
4546
|
+
indexerLag,
|
|
4547
|
+
peers,
|
|
4548
|
+
};
|
|
4549
|
+
}
|
|
4550
|
+
catch (error) {
|
|
4551
|
+
return {
|
|
4552
|
+
ready: false,
|
|
4553
|
+
rpcUrl,
|
|
4554
|
+
error: error instanceof Error ? error.message : String(error),
|
|
4555
|
+
};
|
|
4556
|
+
}
|
|
4557
|
+
});
|
|
4558
|
+
}
|
|
4559
|
+
function waitForNodeReady(rpcUrl_1, timeoutMs_1) {
|
|
4560
|
+
return __awaiter(this, arguments, void 0, function* (rpcUrl, timeoutMs, isProcessAlive = () => true) {
|
|
4561
|
+
const start = Date.now();
|
|
4562
|
+
let last = yield checkNodeReadiness(rpcUrl);
|
|
4563
|
+
while (!last.ready && isProcessAlive() && Date.now() - start < timeoutMs) {
|
|
4564
|
+
yield new Promise((resolve) => setTimeout(resolve, 500));
|
|
4565
|
+
last = yield checkNodeReadiness(rpcUrl);
|
|
4566
|
+
}
|
|
4567
|
+
return last;
|
|
4568
|
+
});
|
|
4569
|
+
}
|
|
4570
|
+
function checkConfiguredDevnetReadiness() {
|
|
4571
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
4572
|
+
return checkNodeReadiness((0, setting_1.readSettings)().devnet.rpcUrl);
|
|
4573
|
+
});
|
|
4574
|
+
}
|
|
4575
|
+
function warnIfForkIndexerIsBehind(network) {
|
|
4576
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
4577
|
+
var _a;
|
|
4578
|
+
if (network !== base_1.Network.devnet)
|
|
4579
|
+
return undefined;
|
|
4580
|
+
const settings = (0, setting_1.readSettings)();
|
|
4581
|
+
if (!(0, fork_1.readForkState)(settings.devnet.configPath))
|
|
4582
|
+
return undefined;
|
|
4583
|
+
const readiness = yield checkNodeReadiness(settings.devnet.rpcUrl);
|
|
4584
|
+
if (!readiness.ready) {
|
|
4585
|
+
logger_1.logger.warn(`The forked devnet is not RPC-ready: ${(_a = readiness.error) !== null && _a !== void 0 ? _a : 'health check failed'}`);
|
|
4586
|
+
}
|
|
4587
|
+
else if (readiness.indexerTip == null) {
|
|
4588
|
+
logger_1.logger.warn('The CKB indexer is not ready yet; cell and balance lookups may be incomplete. Check `offckb devnet info`.');
|
|
4589
|
+
}
|
|
4590
|
+
else if (readiness.indexerLag && readiness.indexerLag > BigInt(0)) {
|
|
4591
|
+
logger_1.logger.warn(`The CKB indexer is ${readiness.indexerLag} blocks behind the node; cell and balance lookups may be incomplete. ` +
|
|
4592
|
+
'Check `offckb devnet info`.');
|
|
4593
|
+
}
|
|
4594
|
+
return readiness;
|
|
4595
|
+
});
|
|
4596
|
+
}
|
|
4597
|
+
|
|
4598
|
+
|
|
3490
4599
|
/***/ }),
|
|
3491
4600
|
|
|
3492
4601
|
/***/ 1360:
|
|
@@ -3518,19 +4627,27 @@ function initChainIfNeeded() {
|
|
|
3518
4627
|
const settings = (0, setting_1.readSettings)();
|
|
3519
4628
|
const devnetSourcePath = path_1.default.resolve(setting_1.packageRootPath, './ckb/devnet');
|
|
3520
4629
|
const devnetConfigPath = settings.devnet.configPath;
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
4630
|
+
const requiredConfigFiles = ['ckb.toml', 'ckb-miner.toml', path_1.default.join('specs', 'dev.toml')];
|
|
4631
|
+
const isInitialized = (0, fs_2.isFolderExists)(devnetConfigPath) &&
|
|
4632
|
+
requiredConfigFiles.every((relativePath) => fs_1.default.existsSync(path_1.default.join(devnetConfigPath, relativePath)));
|
|
4633
|
+
const minerConfigPath = path_1.default.join(devnetConfigPath, 'ckb-miner.toml');
|
|
4634
|
+
const minerConfigWasMissing = !fs_1.default.existsSync(minerConfigPath);
|
|
4635
|
+
// Daemon mode creates data/logs before the child starts. A directory-only
|
|
4636
|
+
// check therefore mistakes a fresh install for an initialized chain. Check
|
|
4637
|
+
// the files CKB actually needs instead, and repair an incomplete directory.
|
|
4638
|
+
if (!isInitialized) {
|
|
4639
|
+
yield (0, fs_2.copyFilesWithExclusion)(devnetSourcePath, devnetConfigPath, ['data'], false);
|
|
3524
4640
|
logger_1.logger.debug(`init devnet config folder: ${devnetConfigPath}`);
|
|
3525
4641
|
// copy and edit ckb-miner.toml
|
|
3526
4642
|
const minerToml = path_1.default.join(devnetSourcePath, 'ckb-miner.toml');
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
4643
|
+
if (minerConfigWasMissing) {
|
|
4644
|
+
// Read the content of the ckb-miner.toml file
|
|
4645
|
+
const data = fs_1.default.readFileSync(minerToml, 'utf8');
|
|
4646
|
+
// Replace the URL
|
|
4647
|
+
const modifiedData = data.replace('http://ckb:8114/', settings.devnet.rpcUrl);
|
|
4648
|
+
// Write the modified content back to the file
|
|
4649
|
+
fs_1.default.writeFileSync(minerConfigPath, modifiedData, 'utf8');
|
|
4650
|
+
}
|
|
3534
4651
|
}
|
|
3535
4652
|
});
|
|
3536
4653
|
}
|
|
@@ -3601,7 +4718,7 @@ const fs = __importStar(__nccwpck_require__(79896));
|
|
|
3601
4718
|
const path = __importStar(__nccwpck_require__(16928));
|
|
3602
4719
|
const semver_1 = __importDefault(__nccwpck_require__(89939));
|
|
3603
4720
|
const os_1 = __importDefault(__nccwpck_require__(70857));
|
|
3604
|
-
const adm_zip_1 = __importDefault(__nccwpck_require__(
|
|
4721
|
+
const adm_zip_1 = __importDefault(__nccwpck_require__(3858));
|
|
3605
4722
|
const tar = __importStar(__nccwpck_require__(80228));
|
|
3606
4723
|
const request_1 = __nccwpck_require__(65897);
|
|
3607
4724
|
const setting_1 = __nccwpck_require__(25546);
|
|
@@ -3660,6 +4777,7 @@ function downloadCKBBinaryAndUnzip(version) {
|
|
|
3660
4777
|
}
|
|
3661
4778
|
catch (error) {
|
|
3662
4779
|
logger_1.logger.error('Error installing dependency binary:', error.message);
|
|
4780
|
+
throw error;
|
|
3663
4781
|
}
|
|
3664
4782
|
});
|
|
3665
4783
|
}
|
|
@@ -3821,7 +4939,8 @@ function buildDownloadUrl(version, opt = {}) {
|
|
|
3821
4939
|
"use strict";
|
|
3822
4940
|
|
|
3823
4941
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
3824
|
-
exports.TYPE_ID_SCRIPT = void 0;
|
|
4942
|
+
exports.TESTNET_GENESIS_HASH = exports.MAINNET_GENESIS_HASH = exports.TYPE_ID_SCRIPT = void 0;
|
|
4943
|
+
exports.identifyPublicChainByGenesisHash = identifyPublicChainByGenesisHash;
|
|
3825
4944
|
exports.TYPE_ID_SCRIPT = {
|
|
3826
4945
|
name: 'type_id',
|
|
3827
4946
|
script: {
|
|
@@ -3830,6 +4949,18 @@ exports.TYPE_ID_SCRIPT = {
|
|
|
3830
4949
|
cellDeps: [],
|
|
3831
4950
|
},
|
|
3832
4951
|
};
|
|
4952
|
+
// Well-known genesis block hashes, used to identify which chain a devnet
|
|
4953
|
+
// actually runs (a forked devnet carries the source chain's genesis).
|
|
4954
|
+
// https://github.com/nervosnetwork/ckb/tree/master/resource/specs
|
|
4955
|
+
exports.MAINNET_GENESIS_HASH = '0x92b197aa1fba0f63633922c61c92375c9c074a93e85963554f5499fe1450d0e5';
|
|
4956
|
+
exports.TESTNET_GENESIS_HASH = '0x10639e0895502b5688a6be8cf69460d76541bfa4821629d86d62ba0aae3f9606';
|
|
4957
|
+
function identifyPublicChainByGenesisHash(genesisHash) {
|
|
4958
|
+
if (genesisHash === exports.MAINNET_GENESIS_HASH)
|
|
4959
|
+
return 'mainnet';
|
|
4960
|
+
if (genesisHash === exports.TESTNET_GENESIS_HASH)
|
|
4961
|
+
return 'testnet';
|
|
4962
|
+
return null;
|
|
4963
|
+
}
|
|
3833
4964
|
|
|
3834
4965
|
|
|
3835
4966
|
/***/ }),
|
|
@@ -3917,30 +5048,21 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3917
5048
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
3918
5049
|
};
|
|
3919
5050
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
5051
|
+
exports.resolveDevnetSystemScripts = resolveDevnetSystemScripts;
|
|
3920
5052
|
exports.getDevnetSystemScriptsFromListHashes = getDevnetSystemScriptsFromListHashes;
|
|
3921
5053
|
exports.toCCCKnownScripts = toCCCKnownScripts;
|
|
3922
5054
|
exports.buildCCCDevnetKnownScripts = buildCCCDevnetKnownScripts;
|
|
5055
|
+
exports.buildDevnetCCCClient = buildDevnetCCCClient;
|
|
3923
5056
|
const core_1 = __nccwpck_require__(39842);
|
|
3924
5057
|
const setting_1 = __nccwpck_require__(25546);
|
|
3925
|
-
const system_scripts_1 = __nccwpck_require__(86198);
|
|
3926
5058
|
const list_hashes_1 = __nccwpck_require__(31603);
|
|
3927
5059
|
const logger_1 = __nccwpck_require__(65370);
|
|
3928
5060
|
const const_1 = __nccwpck_require__(75587);
|
|
5061
|
+
const public_1 = __nccwpck_require__(84535);
|
|
3929
5062
|
const toml_1 = __importDefault(__nccwpck_require__(2811));
|
|
3930
5063
|
const util_1 = __nccwpck_require__(58642);
|
|
3931
|
-
function
|
|
5064
|
+
function buildSystemScriptsFromSpecHashes(chainSpecHashes) {
|
|
3932
5065
|
var _a;
|
|
3933
|
-
const settings = (0, setting_1.readSettings)();
|
|
3934
|
-
const listHashesString = (0, list_hashes_1.getDevnetListHashes)(settings.bins.defaultCKBVersion);
|
|
3935
|
-
if (!listHashesString) {
|
|
3936
|
-
logger_1.logger.info(`list-hashes not found!`);
|
|
3937
|
-
return null;
|
|
3938
|
-
}
|
|
3939
|
-
const listHashes = toml_1.default.parse(listHashesString);
|
|
3940
|
-
const chainSpecHashes = Object.values(listHashes)[0];
|
|
3941
|
-
if (chainSpecHashes == null) {
|
|
3942
|
-
throw new Error(`invalid chain spec hashes file ${listHashesString}`);
|
|
3943
|
-
}
|
|
3944
5066
|
const systemScriptArray = chainSpecHashes.system_cells
|
|
3945
5067
|
.map((cell) => {
|
|
3946
5068
|
// Extract the file name from the path using the helper function
|
|
@@ -3953,7 +5075,7 @@ function getDevnetSystemScriptsFromListHashes() {
|
|
|
3953
5075
|
txHash: chainSpecHashes.dep_groups[depGroupIndex].tx_hash,
|
|
3954
5076
|
index: chainSpecHashes.dep_groups[depGroupIndex].index,
|
|
3955
5077
|
};
|
|
3956
|
-
const scriptInfo = (0,
|
|
5078
|
+
const scriptInfo = (0, util_1.systemCellToScriptInfo)({ cell, depType, depGroup });
|
|
3957
5079
|
return {
|
|
3958
5080
|
name,
|
|
3959
5081
|
file: cell.path,
|
|
@@ -3973,6 +5095,46 @@ function getDevnetSystemScriptsFromListHashes() {
|
|
|
3973
5095
|
systemScripts.type_id = const_1.TYPE_ID_SCRIPT;
|
|
3974
5096
|
return systemScripts;
|
|
3975
5097
|
}
|
|
5098
|
+
// `ckb list-hashes` only reports what the chain spec declares in genesis.
|
|
5099
|
+
// Post-genesis deployments (sudt/xudt/omnilock/spore on mainnet and testnet)
|
|
5100
|
+
// can never appear there, so for a forked devnet we fill the gaps from the
|
|
5101
|
+
// well-known static records of the chain the genesis belongs to. Genesis
|
|
5102
|
+
// scripts always come from list-hashes — the chain's own spec wins.
|
|
5103
|
+
function supplementFromStaticRecord(scripts, staticRecord) {
|
|
5104
|
+
for (const [name, script] of Object.entries(staticRecord)) {
|
|
5105
|
+
const key = name;
|
|
5106
|
+
if (scripts[key] == null && script != null) {
|
|
5107
|
+
// deep clone so callers can never mutate the shared static record
|
|
5108
|
+
scripts[key] = JSON.parse(JSON.stringify(script));
|
|
5109
|
+
}
|
|
5110
|
+
}
|
|
5111
|
+
}
|
|
5112
|
+
function resolveDevnetSystemScripts() {
|
|
5113
|
+
const settings = (0, setting_1.readSettings)();
|
|
5114
|
+
const listHashesString = (0, list_hashes_1.getDevnetListHashes)(settings.bins.defaultCKBVersion);
|
|
5115
|
+
if (!listHashesString) {
|
|
5116
|
+
logger_1.logger.info(`list-hashes not found!`);
|
|
5117
|
+
return null;
|
|
5118
|
+
}
|
|
5119
|
+
const listHashes = toml_1.default.parse(listHashesString);
|
|
5120
|
+
const chainSpecHashes = Object.values(listHashes)[0];
|
|
5121
|
+
if (chainSpecHashes == null) {
|
|
5122
|
+
throw new Error(`invalid chain spec hashes file ${listHashesString}`);
|
|
5123
|
+
}
|
|
5124
|
+
const scripts = buildSystemScriptsFromSpecHashes(chainSpecHashes);
|
|
5125
|
+
const forkedFrom = (0, const_1.identifyPublicChainByGenesisHash)(chainSpecHashes.genesis);
|
|
5126
|
+
if (forkedFrom === 'mainnet') {
|
|
5127
|
+
supplementFromStaticRecord(scripts, public_1.MAINNET_SYSTEM_SCRIPTS);
|
|
5128
|
+
}
|
|
5129
|
+
else if (forkedFrom === 'testnet') {
|
|
5130
|
+
supplementFromStaticRecord(scripts, public_1.TESTNET_SYSTEM_SCRIPTS);
|
|
5131
|
+
}
|
|
5132
|
+
return { scripts, forkedFrom, genesisHash: chainSpecHashes.genesis };
|
|
5133
|
+
}
|
|
5134
|
+
function getDevnetSystemScriptsFromListHashes() {
|
|
5135
|
+
var _a, _b;
|
|
5136
|
+
return (_b = (_a = resolveDevnetSystemScripts()) === null || _a === void 0 ? void 0 : _a.scripts) !== null && _b !== void 0 ? _b : null;
|
|
5137
|
+
}
|
|
3976
5138
|
function toCCCKnownScripts(scripts) {
|
|
3977
5139
|
const DEVNET_SCRIPTS = {
|
|
3978
5140
|
[core_1.KnownScript.Secp256k1Blake160]: scripts.secp256k1_blake160_sighash_all.script,
|
|
@@ -4000,6 +5162,19 @@ function buildCCCDevnetKnownScripts() {
|
|
|
4000
5162
|
const devnetKnownScripts = toCCCKnownScripts(devnetSystemScripts);
|
|
4001
5163
|
return devnetKnownScripts;
|
|
4002
5164
|
}
|
|
5165
|
+
// Build the ccc client for the devnet. A forked devnet carries the source
|
|
5166
|
+
// chain's genesis, so a mainnet fork must use the `ckb` address prefix
|
|
5167
|
+
// (ClientPublicMainnet); everything else uses the `ckt` prefix. Known scripts
|
|
5168
|
+
// always come from the fork-aware resolver above.
|
|
5169
|
+
function buildDevnetCCCClient(url, fallbacks = []) {
|
|
5170
|
+
const resolved = resolveDevnetSystemScripts();
|
|
5171
|
+
if (resolved == null) {
|
|
5172
|
+
throw new Error('can not getSystemScriptsFromListHashes in devnet');
|
|
5173
|
+
}
|
|
5174
|
+
const scripts = toCCCKnownScripts(resolved.scripts);
|
|
5175
|
+
const ClientCtor = resolved.forkedFrom === 'mainnet' ? core_1.ccc.ClientPublicMainnet : core_1.ccc.ClientPublicTestnet;
|
|
5176
|
+
return new ClientCtor({ url, scripts, fallbacks });
|
|
5177
|
+
}
|
|
4003
5178
|
|
|
4004
5179
|
|
|
4005
5180
|
/***/ }),
|
|
@@ -4384,6 +5559,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
|
4384
5559
|
exports.readDeployedScriptInfoFrom = readDeployedScriptInfoFrom;
|
|
4385
5560
|
exports.getScriptInfoFrom = getScriptInfoFrom;
|
|
4386
5561
|
exports.extractScriptNameFromPath = extractScriptNameFromPath;
|
|
5562
|
+
exports.systemCellToScriptInfo = systemCellToScriptInfo;
|
|
4387
5563
|
const fs = __importStar(__nccwpck_require__(79896));
|
|
4388
5564
|
const migration_1 = __nccwpck_require__(76679);
|
|
4389
5565
|
const path_1 = __importDefault(__nccwpck_require__(16928));
|
|
@@ -4474,6 +5650,57 @@ function extractScriptNameFromPath(pathString) {
|
|
|
4474
5650
|
// On Windows, it handles backslashes; on Unix, it handles forward slashes
|
|
4475
5651
|
return path_1.default.basename(pathString);
|
|
4476
5652
|
}
|
|
5653
|
+
function systemCellToScriptInfo({ cell, depType, depGroup, extraCellDeps, }) {
|
|
5654
|
+
// todo: we left the type in cellDepsInfo since it requires async fetching and
|
|
5655
|
+
// chain running to get the full type script of the type-id deps.
|
|
5656
|
+
// Also, in devnet there is no real need to auto upgrade the system scripts with type-id
|
|
5657
|
+
if (depType === 'code') {
|
|
5658
|
+
let cellDeps = [
|
|
5659
|
+
{
|
|
5660
|
+
cellDep: {
|
|
5661
|
+
outPoint: {
|
|
5662
|
+
txHash: cell.tx_hash,
|
|
5663
|
+
index: cell.index,
|
|
5664
|
+
},
|
|
5665
|
+
depType,
|
|
5666
|
+
},
|
|
5667
|
+
},
|
|
5668
|
+
];
|
|
5669
|
+
if (extraCellDeps && extraCellDeps.length > 0) {
|
|
5670
|
+
cellDeps = [...extraCellDeps, ...cellDeps];
|
|
5671
|
+
}
|
|
5672
|
+
return {
|
|
5673
|
+
codeHash: (cell.type_hash || cell.data_hash),
|
|
5674
|
+
hashType: cell.type_hash ? 'type' : 'data2',
|
|
5675
|
+
cellDeps,
|
|
5676
|
+
};
|
|
5677
|
+
}
|
|
5678
|
+
if (depType === 'depGroup') {
|
|
5679
|
+
if (!depGroup) {
|
|
5680
|
+
throw new Error('require depGroup info since the dep type is depGroup');
|
|
5681
|
+
}
|
|
5682
|
+
let cellDeps = [
|
|
5683
|
+
{
|
|
5684
|
+
cellDep: {
|
|
5685
|
+
outPoint: {
|
|
5686
|
+
txHash: depGroup.txHash,
|
|
5687
|
+
index: depGroup.index,
|
|
5688
|
+
},
|
|
5689
|
+
depType,
|
|
5690
|
+
},
|
|
5691
|
+
},
|
|
5692
|
+
];
|
|
5693
|
+
if (extraCellDeps && extraCellDeps.length > 0) {
|
|
5694
|
+
cellDeps = [...extraCellDeps, ...cellDeps];
|
|
5695
|
+
}
|
|
5696
|
+
return {
|
|
5697
|
+
codeHash: (cell.type_hash || cell.data_hash),
|
|
5698
|
+
hashType: cell.type_hash ? 'type' : 'data2',
|
|
5699
|
+
cellDeps,
|
|
5700
|
+
};
|
|
5701
|
+
}
|
|
5702
|
+
throw new Error(`unknown DepType ${depType}`);
|
|
5703
|
+
}
|
|
4477
5704
|
|
|
4478
5705
|
|
|
4479
5706
|
/***/ }),
|
|
@@ -4541,11 +5768,7 @@ class CKB {
|
|
|
4541
5768
|
url: network_1.networks.testnet.proxy_rpc_url,
|
|
4542
5769
|
fallbacks: [network_1.networks.testnet.rpc_url],
|
|
4543
5770
|
}) // we keep the fallbacks in case the proxy rpc is not started
|
|
4544
|
-
:
|
|
4545
|
-
url: network_1.networks.devnet.proxy_rpc_url,
|
|
4546
|
-
scripts: (0, private_1.buildCCCDevnetKnownScripts)(),
|
|
4547
|
-
fallbacks: [network_1.networks.devnet.rpc_url],
|
|
4548
|
-
});
|
|
5771
|
+
: (0, private_1.buildDevnetCCCClient)(network_1.networks.devnet.proxy_rpc_url, [network_1.networks.devnet.rpc_url]);
|
|
4549
5772
|
}
|
|
4550
5773
|
else {
|
|
4551
5774
|
this.client =
|
|
@@ -4559,11 +5782,7 @@ class CKB {
|
|
|
4559
5782
|
url: network_1.networks.testnet.rpc_url,
|
|
4560
5783
|
fallbacks: [],
|
|
4561
5784
|
}) // pass it to avoid using websocket and fallback RPCs
|
|
4562
|
-
:
|
|
4563
|
-
url: network_1.networks.devnet.rpc_url,
|
|
4564
|
-
scripts: (0, private_1.buildCCCDevnetKnownScripts)(),
|
|
4565
|
-
fallbacks: [], // pass it to avoid using websocket and fallback RPCs
|
|
4566
|
-
});
|
|
5785
|
+
: (0, private_1.buildDevnetCCCClient)(network_1.networks.devnet.rpc_url);
|
|
4567
5786
|
}
|
|
4568
5787
|
}
|
|
4569
5788
|
buildSigner(privateKey) {
|
|
@@ -4620,7 +5839,7 @@ class CKB {
|
|
|
4620
5839
|
});
|
|
4621
5840
|
}
|
|
4622
5841
|
transfer(_a) {
|
|
4623
|
-
return __awaiter(this, arguments, void 0, function* ({ privateKey, toAddress, amountInCKB }) {
|
|
5842
|
+
return __awaiter(this, arguments, void 0, function* ({ privateKey, toAddress, amountInCKB, rejectInputsAtOrBeforeBlock, }) {
|
|
4624
5843
|
const signer = this.buildSigner(privateKey);
|
|
4625
5844
|
const to = yield core_1.ccc.Address.fromString(toAddress, this.client);
|
|
4626
5845
|
const tx = core_1.ccc.Transaction.from({
|
|
@@ -4633,6 +5852,7 @@ class CKB {
|
|
|
4633
5852
|
});
|
|
4634
5853
|
yield tx.completeInputsByCapacity(signer);
|
|
4635
5854
|
yield tx.completeFeeBy(signer, this.feeRate);
|
|
5855
|
+
yield this.assertInputsCreatedAfter(tx, rejectInputsAtOrBeforeBlock);
|
|
4636
5856
|
const txHash = yield signer.sendTransaction(tx);
|
|
4637
5857
|
return txHash;
|
|
4638
5858
|
});
|
|
@@ -4802,7 +6022,7 @@ class CKB {
|
|
|
4802
6022
|
});
|
|
4803
6023
|
}
|
|
4804
6024
|
udtTransfer(_a) {
|
|
4805
|
-
return __awaiter(this, arguments, void 0, function* ({ privateKey, toAddress, amount, udtType, kind }) {
|
|
6025
|
+
return __awaiter(this, arguments, void 0, function* ({ privateKey, toAddress, amount, udtType, kind, rejectInputsAtOrBeforeBlock, }) {
|
|
4806
6026
|
const signer = this.buildSigner(privateKey);
|
|
4807
6027
|
const to = yield core_1.ccc.Address.fromString(toAddress, this.client);
|
|
4808
6028
|
const amountBigInt = (0, validator_1.validateUdtAmount)(amount);
|
|
@@ -4833,10 +6053,28 @@ class CKB {
|
|
|
4833
6053
|
tx.outputsData.push(core_1.ccc.hexFrom(core_1.ccc.numToBytes(changeAmount, 16)));
|
|
4834
6054
|
}
|
|
4835
6055
|
yield tx.completeFeeBy(signer, this.feeRate);
|
|
6056
|
+
yield this.assertInputsCreatedAfter(tx, rejectInputsAtOrBeforeBlock);
|
|
4836
6057
|
const txHash = yield signer.sendTransaction(tx);
|
|
4837
6058
|
return txHash;
|
|
4838
6059
|
});
|
|
4839
6060
|
}
|
|
6061
|
+
assertInputsCreatedAfter(tx, blockNumber) {
|
|
6062
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
6063
|
+
if (blockNumber == null)
|
|
6064
|
+
return;
|
|
6065
|
+
for (const input of tx.inputs) {
|
|
6066
|
+
const outPoint = input.previousOutput;
|
|
6067
|
+
const origin = yield this.client.getTransactionNoCache(outPoint.txHash);
|
|
6068
|
+
if ((origin === null || origin === void 0 ? void 0 : origin.blockNumber) == null) {
|
|
6069
|
+
throw new Error(`Refusing to sign: could not verify the origin block of input ${outPoint.txHash}:${outPoint.index}.`);
|
|
6070
|
+
}
|
|
6071
|
+
if (origin.blockNumber <= blockNumber) {
|
|
6072
|
+
throw new Error(`Refusing to sign: input ${outPoint.txHash}:${outPoint.index} was created at block ${origin.blockNumber}, ` +
|
|
6073
|
+
`at or before the Mainnet fork boundary ${blockNumber}.`);
|
|
6074
|
+
}
|
|
6075
|
+
}
|
|
6076
|
+
});
|
|
6077
|
+
}
|
|
4840
6078
|
udtIssue(_a) {
|
|
4841
6079
|
return __awaiter(this, arguments, void 0, function* ({ privateKey, kind, amount, typeArgs, toAddress }) {
|
|
4842
6080
|
const signer = this.buildSigner(privateKey);
|
|
@@ -4849,7 +6087,7 @@ class CKB {
|
|
|
4849
6087
|
logger_1.logger.warn('SUDT type args are derived from the issuer lock hash; --type-args is ignored');
|
|
4850
6088
|
}
|
|
4851
6089
|
const issuerLockHash = signerAddress.script.hash();
|
|
4852
|
-
resolvedTypeArgs =
|
|
6090
|
+
resolvedTypeArgs = issuerLockHash;
|
|
4853
6091
|
}
|
|
4854
6092
|
else {
|
|
4855
6093
|
if (typeArgs) {
|
|
@@ -4877,7 +6115,7 @@ class CKB {
|
|
|
4877
6115
|
yield tx.completeInputsByCapacity(signer);
|
|
4878
6116
|
yield tx.completeFeeBy(signer, this.feeRate);
|
|
4879
6117
|
const txHash = yield signer.sendTransaction(tx);
|
|
4880
|
-
return txHash;
|
|
6118
|
+
return { txHash, typeArgs: resolvedTypeArgs, receiver: to.toString() };
|
|
4881
6119
|
});
|
|
4882
6120
|
}
|
|
4883
6121
|
udtDestroy(_a) {
|
|
@@ -6336,7 +7574,7 @@ const path = __importStar(__nccwpck_require__(16928));
|
|
|
6336
7574
|
const fs = __importStar(__nccwpck_require__(79896));
|
|
6337
7575
|
const os = __importStar(__nccwpck_require__(70857));
|
|
6338
7576
|
const crypto = __importStar(__nccwpck_require__(76982));
|
|
6339
|
-
const adm_zip_1 = __importDefault(__nccwpck_require__(
|
|
7577
|
+
const adm_zip_1 = __importDefault(__nccwpck_require__(3858));
|
|
6340
7578
|
const setting_1 = __nccwpck_require__(25546);
|
|
6341
7579
|
const logger_1 = __nccwpck_require__(65370);
|
|
6342
7580
|
const fs_1 = __nccwpck_require__(37293);
|
|
@@ -6344,6 +7582,16 @@ const DOWNLOAD_TIMEOUT_MS = 120000;
|
|
|
6344
7582
|
const EXTRACT_TIMEOUT_MS = 60000;
|
|
6345
7583
|
// Strict semver regex: v<major>.<minor>.<patch> (no leading zeros on digits)
|
|
6346
7584
|
const STRICT_VERSION_REGEX = /^v(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/;
|
|
7585
|
+
// Independently pinned digests for the default release. Keeping these in
|
|
7586
|
+
// offckb makes the default installation verifiable even though ckb-tui v0.1.3
|
|
7587
|
+
// did not upload a checksums-sha256.txt asset.
|
|
7588
|
+
const KNOWN_SHA256 = {
|
|
7589
|
+
'v0.1.3': {
|
|
7590
|
+
'ckb-tui-with-node-linux-amd64.tar.gz': '33455cefe2c016149fa8fa3abde7960b348d4606afef9279d787ac8a8b59956f',
|
|
7591
|
+
'ckb-tui-with-node-macos-aarch64.tar.gz': 'de18107ec179ced03608da956013e38ae82e6c1fae588f12c17d138ee6ee072c',
|
|
7592
|
+
'ckb-tui-with-node-windows-amd64.zip': '749d8e09fd5d23fc8af12892b7d197add5aae004f7438678023e4a973f3fd58b',
|
|
7593
|
+
},
|
|
7594
|
+
};
|
|
6347
7595
|
class CKBTui {
|
|
6348
7596
|
/**
|
|
6349
7597
|
* Pure lookup — returns the expected binary path without triggering any
|
|
@@ -6460,7 +7708,7 @@ class CKBTui {
|
|
|
6460
7708
|
if (curlResult.status !== 0) {
|
|
6461
7709
|
throw new Error(`curl exited with code ${curlResult.status}`);
|
|
6462
7710
|
}
|
|
6463
|
-
// 2. Verify checksum
|
|
7711
|
+
// 2. Verify checksum. Installation fails closed if no trusted digest exists.
|
|
6464
7712
|
this.verifyChecksum(version, assetName, archivePath);
|
|
6465
7713
|
// 3. Extract to temp directory
|
|
6466
7714
|
logger_1.logger.info('Extracting...');
|
|
@@ -6498,64 +7746,24 @@ class CKBTui {
|
|
|
6498
7746
|
}
|
|
6499
7747
|
}
|
|
6500
7748
|
}
|
|
6501
|
-
/**
|
|
6502
|
-
* Best-effort SHA-256 checksum verification.
|
|
6503
|
-
* Downloads the checksum file published alongside the release asset and
|
|
6504
|
-
* verifies the downloaded archive. Logs a warning (but does not fail) if
|
|
6505
|
-
* the checksum file is unavailable — this maintains compatibility while
|
|
6506
|
-
* the upstream project adopts checksum publishing.
|
|
6507
|
-
*/
|
|
7749
|
+
/** Verify against an independently pinned digest. */
|
|
6508
7750
|
static verifyChecksum(version, assetName, archivePath) {
|
|
6509
|
-
|
|
6510
|
-
const
|
|
6511
|
-
|
|
6512
|
-
|
|
6513
|
-
|
|
6514
|
-
});
|
|
6515
|
-
if (fetchResult.status !== 0) {
|
|
6516
|
-
logger_1.logger.warn(`SHA-256 checksum file not available for version ${version}. ` +
|
|
6517
|
-
'Skipping integrity verification. Consider asking the upstream maintainer to publish checksum files.');
|
|
6518
|
-
return;
|
|
6519
|
-
}
|
|
6520
|
-
try {
|
|
6521
|
-
const checksumContent = fs.readFileSync(checksumPath, 'utf8');
|
|
6522
|
-
const expectedHash = this.parseChecksumFile(checksumContent, assetName);
|
|
6523
|
-
if (!expectedHash) {
|
|
6524
|
-
logger_1.logger.warn(`Checksum entry for "${assetName}" not found in checksums file. Skipping verification.`);
|
|
6525
|
-
return;
|
|
6526
|
-
}
|
|
6527
|
-
const actualHash = crypto.createHash('sha256').update(fs.readFileSync(archivePath)).digest('hex');
|
|
6528
|
-
if (actualHash !== expectedHash) {
|
|
6529
|
-
throw new Error(`SHA-256 checksum mismatch for ${assetName}.\n` +
|
|
6530
|
-
`Expected: ${expectedHash}\nActual: ${actualHash}\n` +
|
|
6531
|
-
'The downloaded file may be corrupted or tampered with.');
|
|
6532
|
-
}
|
|
6533
|
-
logger_1.logger.info('SHA-256 checksum verified successfully.');
|
|
6534
|
-
}
|
|
6535
|
-
finally {
|
|
6536
|
-
try {
|
|
6537
|
-
fs.unlinkSync(checksumPath);
|
|
6538
|
-
}
|
|
6539
|
-
catch (_a) {
|
|
6540
|
-
// Best effort
|
|
6541
|
-
}
|
|
7751
|
+
var _a;
|
|
7752
|
+
const pinnedHash = (_a = KNOWN_SHA256[version]) === null || _a === void 0 ? void 0 : _a[assetName];
|
|
7753
|
+
if (!pinnedHash) {
|
|
7754
|
+
throw new Error(`No trusted SHA-256 checksum is pinned for ckb-tui ${version} (${assetName}). ` +
|
|
7755
|
+
'Refusing to install an unverified binary.');
|
|
6542
7756
|
}
|
|
7757
|
+
this.assertChecksum(archivePath, assetName, pinnedHash);
|
|
6543
7758
|
}
|
|
6544
|
-
|
|
6545
|
-
|
|
6546
|
-
|
|
6547
|
-
|
|
6548
|
-
|
|
6549
|
-
|
|
6550
|
-
const trimmed = line.trim();
|
|
6551
|
-
if (!trimmed || trimmed.startsWith('#'))
|
|
6552
|
-
continue;
|
|
6553
|
-
const match = trimmed.match(/^([0-9a-fA-F]{64})\s+[*]?(.+)$/);
|
|
6554
|
-
if (match && match[2] === assetName) {
|
|
6555
|
-
return match[1].toLowerCase();
|
|
6556
|
-
}
|
|
7759
|
+
static assertChecksum(archivePath, assetName, expectedHash) {
|
|
7760
|
+
const actualHash = crypto.createHash('sha256').update(fs.readFileSync(archivePath)).digest('hex');
|
|
7761
|
+
if (actualHash !== expectedHash) {
|
|
7762
|
+
throw new Error(`SHA-256 checksum mismatch for ${assetName}.\n` +
|
|
7763
|
+
`Expected: ${expectedHash}\nActual: ${actualHash}\n` +
|
|
7764
|
+
'The downloaded file may be corrupted or tampered with.');
|
|
6557
7765
|
}
|
|
6558
|
-
|
|
7766
|
+
logger_1.logger.info('SHA-256 checksum verified successfully.');
|
|
6559
7767
|
}
|
|
6560
7768
|
/**
|
|
6561
7769
|
* Extract a downloaded archive to the given directory.
|
|
@@ -6619,6 +7827,7 @@ const fs_1 = __importDefault(__nccwpck_require__(79896));
|
|
|
6619
7827
|
const path_1 = __importDefault(__nccwpck_require__(16928));
|
|
6620
7828
|
const core_1 = __nccwpck_require__(39842);
|
|
6621
7829
|
const advanced_1 = __nccwpck_require__(98486);
|
|
7830
|
+
const json_rpc_1 = __nccwpck_require__(51726);
|
|
6622
7831
|
const logger_1 = __nccwpck_require__(65370);
|
|
6623
7832
|
const OutPointCodec = core_1.ccc.mol.struct({
|
|
6624
7833
|
txHash: core_1.ccc.mol.Byte32,
|
|
@@ -6743,6 +7952,19 @@ function resolveInputs(client, inputs) {
|
|
|
6743
7952
|
return resolved;
|
|
6744
7953
|
});
|
|
6745
7954
|
}
|
|
7955
|
+
function resolveHeaderDeps(rpc, headerDeps) {
|
|
7956
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
7957
|
+
const headers = [];
|
|
7958
|
+
for (const hash of headerDeps) {
|
|
7959
|
+
const header = yield (0, json_rpc_1.callJsonRpc)(rpc, 'get_header', [hash]);
|
|
7960
|
+
if (!header) {
|
|
7961
|
+
throw new Error(`Header not found: ${hash}`);
|
|
7962
|
+
}
|
|
7963
|
+
headers.push(header);
|
|
7964
|
+
}
|
|
7965
|
+
return headers;
|
|
7966
|
+
});
|
|
7967
|
+
}
|
|
6746
7968
|
function dumpTransaction(_a) {
|
|
6747
7969
|
return __awaiter(this, arguments, void 0, function* ({ rpc, txJsonFilePath, outputFilePath }) {
|
|
6748
7970
|
try {
|
|
@@ -6758,15 +7980,16 @@ function dumpTransaction(_a) {
|
|
|
6758
7980
|
});
|
|
6759
7981
|
const txJson = JSON.parse(fs_1.default.readFileSync(txJsonFilePath, 'utf-8'));
|
|
6760
7982
|
const tx = advanced_1.cccA.JsonRpcTransformers.transactionTo(txJson);
|
|
6761
|
-
const [cell_deps, inputs] = yield Promise.all([
|
|
7983
|
+
const [cell_deps, inputs, header_deps] = yield Promise.all([
|
|
6762
7984
|
resolveCellDeps(client, tx.cellDeps),
|
|
6763
7985
|
resolveInputs(client, tx.inputs),
|
|
7986
|
+
resolveHeaderDeps(rpc, tx.headerDeps),
|
|
6764
7987
|
]);
|
|
6765
7988
|
const mockTx = {
|
|
6766
7989
|
mock_info: {
|
|
6767
7990
|
inputs,
|
|
6768
7991
|
cell_deps,
|
|
6769
|
-
header_deps
|
|
7992
|
+
header_deps,
|
|
6770
7993
|
},
|
|
6771
7994
|
tx: {
|
|
6772
7995
|
version: '0x' + tx.version.toString(16),
|
|
@@ -8792,6 +10015,77 @@ function encodeBinPathForTerminal(path) {
|
|
|
8792
10015
|
}
|
|
8793
10016
|
|
|
8794
10017
|
|
|
10018
|
+
/***/ }),
|
|
10019
|
+
|
|
10020
|
+
/***/ 47625:
|
|
10021
|
+
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
|
10022
|
+
|
|
10023
|
+
"use strict";
|
|
10024
|
+
|
|
10025
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
10026
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10027
|
+
};
|
|
10028
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
10029
|
+
exports.warnIfMainnetForkSigning = warnIfMainnetForkSigning;
|
|
10030
|
+
exports.validateMainnetForkSigning = validateMainnetForkSigning;
|
|
10031
|
+
const account_json_1 = __importDefault(__nccwpck_require__(13849));
|
|
10032
|
+
const account_1 = __nccwpck_require__(59489);
|
|
10033
|
+
const setting_1 = __nccwpck_require__(25546);
|
|
10034
|
+
const fork_1 = __nccwpck_require__(77912);
|
|
10035
|
+
const base_1 = __nccwpck_require__(69951);
|
|
10036
|
+
const logger_1 = __nccwpck_require__(65370);
|
|
10037
|
+
const BUILT_IN_DEV_KEYS = new Set([...account_json_1.default.map((account) => account.privkey), account_1.ckbDevnetMinerAccount.privkey].map((key) => key.toLowerCase()));
|
|
10038
|
+
function warnIfMainnetForkSigning(network, privateKey) {
|
|
10039
|
+
if (!readMainnetForkState(network))
|
|
10040
|
+
return;
|
|
10041
|
+
logMainnetForkSigningWarning(privateKey);
|
|
10042
|
+
}
|
|
10043
|
+
/**
|
|
10044
|
+
* Fail closed before a Mainnet-fork transfer is constructed or signed.
|
|
10045
|
+
* Returns the copied-chain tip so the transaction layer can reject inputs
|
|
10046
|
+
* created at or before the fork boundary after input selection.
|
|
10047
|
+
*/
|
|
10048
|
+
function validateMainnetForkSigning(network, privateKey, allowMainnetReplayRisk = false) {
|
|
10049
|
+
const fork = readMainnetForkState(network);
|
|
10050
|
+
if (!fork)
|
|
10051
|
+
return undefined;
|
|
10052
|
+
logMainnetForkSigningWarning(privateKey);
|
|
10053
|
+
if (!BUILT_IN_DEV_KEYS.has(privateKey.trim().toLowerCase()) && !allowMainnetReplayRisk) {
|
|
10054
|
+
throw new Error('Refusing to sign with a non-built-in private key on a Mainnet fork. ' +
|
|
10055
|
+
'Use --allow-mainnet-replay-risk only after verifying that no copied Mainnet input will be selected.');
|
|
10056
|
+
}
|
|
10057
|
+
if (fork.forkBlockNumber == null) {
|
|
10058
|
+
throw new Error('Mainnet fork boundary metadata is missing. Restart or recreate the fork before signing so input origins can be verified.');
|
|
10059
|
+
}
|
|
10060
|
+
try {
|
|
10061
|
+
const blockNumber = BigInt(fork.forkBlockNumber);
|
|
10062
|
+
if (blockNumber < BigInt(0))
|
|
10063
|
+
throw new Error('negative block number');
|
|
10064
|
+
return blockNumber;
|
|
10065
|
+
}
|
|
10066
|
+
catch (_a) {
|
|
10067
|
+
throw new Error(`Invalid Mainnet fork boundary metadata: ${fork.forkBlockNumber}`);
|
|
10068
|
+
}
|
|
10069
|
+
}
|
|
10070
|
+
function readMainnetForkState(network) {
|
|
10071
|
+
if (network !== base_1.Network.devnet)
|
|
10072
|
+
return null;
|
|
10073
|
+
const settings = (0, setting_1.readSettings)();
|
|
10074
|
+
const fork = (0, fork_1.readForkState)(settings.devnet.configPath);
|
|
10075
|
+
return (fork === null || fork === void 0 ? void 0 : fork.source) === 'mainnet' ? fork : null;
|
|
10076
|
+
}
|
|
10077
|
+
function logMainnetForkSigningWarning(privateKey) {
|
|
10078
|
+
logger_1.logger.warn([
|
|
10079
|
+
'MAINNET FORK REPLAY RISK: CKB transactions have no chain id.',
|
|
10080
|
+
'A transaction spending cells copied from Mainnet can also be valid on Mainnet.',
|
|
10081
|
+
'Use only built-in dev keys and fork-mined cells unless you explicitly accept that risk.',
|
|
10082
|
+
]);
|
|
10083
|
+
if (!BUILT_IN_DEV_KEYS.has(privateKey.trim().toLowerCase())) {
|
|
10084
|
+
logger_1.logger.warn('A non-built-in private key is being used on a Mainnet fork. Verify every input before signing.');
|
|
10085
|
+
}
|
|
10086
|
+
}
|
|
10087
|
+
|
|
10088
|
+
|
|
8795
10089
|
/***/ }),
|
|
8796
10090
|
|
|
8797
10091
|
/***/ 37293:
|
|
@@ -8897,22 +10191,23 @@ function copyFileSync(source, target) {
|
|
|
8897
10191
|
}
|
|
8898
10192
|
fs.writeFileSync(targetFile, fs.readFileSync(source));
|
|
8899
10193
|
}
|
|
8900
|
-
function copyFilesWithExclusion(
|
|
8901
|
-
return __awaiter(this,
|
|
10194
|
+
function copyFilesWithExclusion(sourceDir_1, destinationDir_1, excludedFolders_1) {
|
|
10195
|
+
return __awaiter(this, arguments, void 0, function* (sourceDir, destinationDir, excludedFolders, overwrite = true) {
|
|
8902
10196
|
try {
|
|
8903
10197
|
// Ensure the destination directory exists
|
|
8904
10198
|
yield fs.promises.mkdir(destinationDir, { recursive: true });
|
|
8905
10199
|
// Start copying recursively from the source directory
|
|
8906
|
-
yield copyRecursive(sourceDir, destinationDir, excludedFolders);
|
|
10200
|
+
yield copyRecursive(sourceDir, destinationDir, excludedFolders, overwrite);
|
|
8907
10201
|
}
|
|
8908
10202
|
catch (error) {
|
|
8909
10203
|
logger_1.logger.error('An error occurred during copying files:', error);
|
|
10204
|
+
throw error;
|
|
8910
10205
|
}
|
|
8911
10206
|
});
|
|
8912
10207
|
}
|
|
8913
10208
|
// Function to recursively copy files and directories
|
|
8914
|
-
function copyRecursive(
|
|
8915
|
-
return __awaiter(this,
|
|
10209
|
+
function copyRecursive(source_1, destination_1, excludedFolders_1) {
|
|
10210
|
+
return __awaiter(this, arguments, void 0, function* (source, destination, excludedFolders, overwrite = true) {
|
|
8916
10211
|
// Get a list of all files and directories in the source directory
|
|
8917
10212
|
const files = yield fs.promises.readdir(source);
|
|
8918
10213
|
// Iterate through each file or directory
|
|
@@ -8929,12 +10224,14 @@ function copyRecursive(source, destination, excludedFolders) {
|
|
|
8929
10224
|
else {
|
|
8930
10225
|
// Ensure destination directory exists before copying
|
|
8931
10226
|
yield fs.promises.mkdir(destPath, { recursive: true });
|
|
8932
|
-
yield copyRecursive(sourcePath, destPath, excludedFolders);
|
|
10227
|
+
yield copyRecursive(sourcePath, destPath, excludedFolders, overwrite);
|
|
8933
10228
|
}
|
|
8934
10229
|
}
|
|
8935
10230
|
else {
|
|
8936
10231
|
// Otherwise, copy the file
|
|
8937
|
-
|
|
10232
|
+
if (overwrite || !fs.existsSync(destPath)) {
|
|
10233
|
+
yield fs.promises.copyFile(sourcePath, destPath);
|
|
10234
|
+
}
|
|
8938
10235
|
}
|
|
8939
10236
|
}
|
|
8940
10237
|
});
|
|
@@ -9019,6 +10316,85 @@ function getSubfolders(folderPath) {
|
|
|
9019
10316
|
}
|
|
9020
10317
|
|
|
9021
10318
|
|
|
10319
|
+
/***/ }),
|
|
10320
|
+
|
|
10321
|
+
/***/ 51726:
|
|
10322
|
+
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
|
10323
|
+
|
|
10324
|
+
"use strict";
|
|
10325
|
+
|
|
10326
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
10327
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
10328
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
10329
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
10330
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
10331
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
10332
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
10333
|
+
});
|
|
10334
|
+
};
|
|
10335
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
10336
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10337
|
+
};
|
|
10338
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
10339
|
+
exports.callJsonRpc = callJsonRpc;
|
|
10340
|
+
const http_1 = __importDefault(__nccwpck_require__(58611));
|
|
10341
|
+
const https_1 = __importDefault(__nccwpck_require__(65692));
|
|
10342
|
+
// Minimal raw JSON-RPC caller. Unlike Request.send it never goes through the
|
|
10343
|
+
// configured proxy, which makes it safe for talking to the local devnet node.
|
|
10344
|
+
function callJsonRpc(rpcUrl_1, method_1, params_1) {
|
|
10345
|
+
return __awaiter(this, arguments, void 0, function* (rpcUrl, method, params, timeoutMs = 30000) {
|
|
10346
|
+
const body = JSON.stringify({ id: 1, jsonrpc: '2.0', method, params });
|
|
10347
|
+
const url = new URL(rpcUrl);
|
|
10348
|
+
const transport = url.protocol === 'https:' ? https_1.default : http_1.default;
|
|
10349
|
+
return new Promise((resolve, reject) => {
|
|
10350
|
+
const req = transport.request({
|
|
10351
|
+
hostname: url.hostname,
|
|
10352
|
+
port: url.port || (url.protocol === 'https:' ? 443 : 80),
|
|
10353
|
+
path: url.pathname + url.search,
|
|
10354
|
+
method: 'POST',
|
|
10355
|
+
headers: {
|
|
10356
|
+
'content-type': 'application/json',
|
|
10357
|
+
'content-length': Buffer.byteLength(body),
|
|
10358
|
+
},
|
|
10359
|
+
timeout: timeoutMs,
|
|
10360
|
+
}, (res) => {
|
|
10361
|
+
const chunks = [];
|
|
10362
|
+
res.on('data', (chunk) => chunks.push(chunk));
|
|
10363
|
+
// The response stream can error or close before `end` (connection
|
|
10364
|
+
// reset, truncated body). Without these listeners the promise would
|
|
10365
|
+
// hang until the request timeout — or the process would crash on an
|
|
10366
|
+
// unhandled stream error.
|
|
10367
|
+
res.once('error', reject);
|
|
10368
|
+
res.on('close', () => {
|
|
10369
|
+
if (!res.complete) {
|
|
10370
|
+
reject(new Error(`JSON-RPC ${method} to ${rpcUrl} returned a truncated response`));
|
|
10371
|
+
}
|
|
10372
|
+
});
|
|
10373
|
+
res.on('end', () => {
|
|
10374
|
+
try {
|
|
10375
|
+
const parsed = JSON.parse(Buffer.concat(chunks).toString('utf8'));
|
|
10376
|
+
if (parsed.error) {
|
|
10377
|
+
reject(new Error(`JSON-RPC ${method} failed: ${JSON.stringify(parsed.error)}`));
|
|
10378
|
+
return;
|
|
10379
|
+
}
|
|
10380
|
+
resolve(parsed.result);
|
|
10381
|
+
}
|
|
10382
|
+
catch (error) {
|
|
10383
|
+
reject(new Error(`Invalid JSON-RPC response from ${rpcUrl}: ${error.message}`));
|
|
10384
|
+
}
|
|
10385
|
+
});
|
|
10386
|
+
});
|
|
10387
|
+
req.on('timeout', () => {
|
|
10388
|
+
req.destroy(new Error(`JSON-RPC ${method} to ${rpcUrl} timed out`));
|
|
10389
|
+
});
|
|
10390
|
+
req.on('error', reject);
|
|
10391
|
+
req.write(body);
|
|
10392
|
+
req.end();
|
|
10393
|
+
});
|
|
10394
|
+
});
|
|
10395
|
+
}
|
|
10396
|
+
|
|
10397
|
+
|
|
9022
10398
|
/***/ }),
|
|
9023
10399
|
|
|
9024
10400
|
/***/ 27814:
|
|
@@ -9100,6 +10476,7 @@ const levelColors = {
|
|
|
9100
10476
|
};
|
|
9101
10477
|
class UnifiedLogger {
|
|
9102
10478
|
constructor(options = {}) {
|
|
10479
|
+
this.resultEmitted = false;
|
|
9103
10480
|
this.enableColors = options.enableColors !== false;
|
|
9104
10481
|
this.showLevel = options.showLevel !== false;
|
|
9105
10482
|
this.jsonMode = options.jsonMode === true;
|
|
@@ -9109,8 +10486,8 @@ class UnifiedLogger {
|
|
|
9109
10486
|
levels: {
|
|
9110
10487
|
error: 0,
|
|
9111
10488
|
warn: 1,
|
|
9112
|
-
|
|
9113
|
-
|
|
10489
|
+
success: 2,
|
|
10490
|
+
info: 3,
|
|
9114
10491
|
debug: 4,
|
|
9115
10492
|
},
|
|
9116
10493
|
format: winston_1.default.format.combine(winston_1.default.format.timestamp(), winston_1.default.format.errors({ stack: true }), winston_1.default.format.printf(({ level, message, timestamp }) => {
|
|
@@ -9122,6 +10499,7 @@ class UnifiedLogger {
|
|
|
9122
10499
|
}),
|
|
9123
10500
|
],
|
|
9124
10501
|
});
|
|
10502
|
+
this.setJsonMode(this.jsonMode);
|
|
9125
10503
|
}
|
|
9126
10504
|
/**
|
|
9127
10505
|
* Toggle JSON output mode. When enabled, every log line is emitted as a
|
|
@@ -9129,6 +10507,36 @@ class UnifiedLogger {
|
|
|
9129
10507
|
*/
|
|
9130
10508
|
setJsonMode(enabled) {
|
|
9131
10509
|
this.jsonMode = enabled;
|
|
10510
|
+
// In machine mode stdout is reserved for command result records. Progress
|
|
10511
|
+
// and diagnostics remain NDJSON, but go to stderr so callers can parse one
|
|
10512
|
+
// stable stdout object without filtering human-oriented logs.
|
|
10513
|
+
for (const transport of this.logger.transports) {
|
|
10514
|
+
if (transport instanceof winston_1.default.transports.Console) {
|
|
10515
|
+
const consoleTransport = transport;
|
|
10516
|
+
consoleTransport.stderrLevels = Object.fromEntries((enabled ? Object.keys(levelColors) : ['error', 'warn']).map((level) => [level, true]));
|
|
10517
|
+
}
|
|
10518
|
+
}
|
|
10519
|
+
}
|
|
10520
|
+
isJsonMode() {
|
|
10521
|
+
return this.jsonMode;
|
|
10522
|
+
}
|
|
10523
|
+
/** Emit one stable, command-level result record for programmatic callers. */
|
|
10524
|
+
result(result) {
|
|
10525
|
+
if (this.jsonMode && !this.resultEmitted) {
|
|
10526
|
+
this.resultEmitted = true;
|
|
10527
|
+
node_process_1.default.stdout.write(`${JSON.stringify(Object.assign({ ok: true }, result))}\n`);
|
|
10528
|
+
}
|
|
10529
|
+
}
|
|
10530
|
+
hasResult() {
|
|
10531
|
+
return this.resultEmitted;
|
|
10532
|
+
}
|
|
10533
|
+
/** Emit a stable error record without exposing internal stack traces. */
|
|
10534
|
+
failure(code, message, details) {
|
|
10535
|
+
if (this.jsonMode) {
|
|
10536
|
+
node_process_1.default.stderr.write(`${JSON.stringify(Object.assign({ ok: false, code, message }, (details == null ? {} : { details })))}\n`);
|
|
10537
|
+
return;
|
|
10538
|
+
}
|
|
10539
|
+
this.error(message);
|
|
9132
10540
|
}
|
|
9133
10541
|
/**
|
|
9134
10542
|
* Format the message with appropriate colors and structure
|
|
@@ -9311,6 +10719,43 @@ const logger = UnifiedLogger.create({ showLevel: false });
|
|
|
9311
10719
|
exports.logger = logger;
|
|
9312
10720
|
|
|
9313
10721
|
|
|
10722
|
+
/***/ }),
|
|
10723
|
+
|
|
10724
|
+
/***/ 26241:
|
|
10725
|
+
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
|
10726
|
+
|
|
10727
|
+
"use strict";
|
|
10728
|
+
|
|
10729
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
10730
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10731
|
+
};
|
|
10732
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
10733
|
+
exports.resolvePrivateKey = resolvePrivateKey;
|
|
10734
|
+
const fs_1 = __importDefault(__nccwpck_require__(79896));
|
|
10735
|
+
const path_1 = __importDefault(__nccwpck_require__(16928));
|
|
10736
|
+
function resolvePrivateKey(input, defaultKey) {
|
|
10737
|
+
if (input.privkey && input.privkeyFile) {
|
|
10738
|
+
throw new Error('Use only one of --privkey or --privkey-file.');
|
|
10739
|
+
}
|
|
10740
|
+
if (input.privkey)
|
|
10741
|
+
return input.privkey;
|
|
10742
|
+
if (input.privkeyFile) {
|
|
10743
|
+
const filePath = path_1.default.resolve(input.privkeyFile);
|
|
10744
|
+
try {
|
|
10745
|
+
return fs_1.default.readFileSync(filePath, 'utf8').trim();
|
|
10746
|
+
}
|
|
10747
|
+
catch (error) {
|
|
10748
|
+
throw new Error(`Could not read private key file ${filePath}: ${error.message}`);
|
|
10749
|
+
}
|
|
10750
|
+
}
|
|
10751
|
+
if (process.env.OFFCKB_PRIVATE_KEY)
|
|
10752
|
+
return process.env.OFFCKB_PRIVATE_KEY;
|
|
10753
|
+
if (defaultKey)
|
|
10754
|
+
return defaultKey;
|
|
10755
|
+
throw new Error('--privkey, --privkey-file, or OFFCKB_PRIVATE_KEY is required!');
|
|
10756
|
+
}
|
|
10757
|
+
|
|
10758
|
+
|
|
9314
10759
|
/***/ }),
|
|
9315
10760
|
|
|
9316
10761
|
/***/ 65897:
|
|
@@ -9405,7 +10850,6 @@ exports.validateUdtTypeArgs = validateUdtTypeArgs;
|
|
|
9405
10850
|
const path_1 = __importDefault(__nccwpck_require__(16928));
|
|
9406
10851
|
const fs_1 = __importDefault(__nccwpck_require__(79896));
|
|
9407
10852
|
const base_1 = __nccwpck_require__(69951);
|
|
9408
|
-
const logger_1 = __nccwpck_require__(65370);
|
|
9409
10853
|
function validateTypescriptWorkspace() {
|
|
9410
10854
|
const cwd = process.cwd();
|
|
9411
10855
|
// Check if package.json exists
|
|
@@ -9447,8 +10891,7 @@ function validateNetworkOpt(network) {
|
|
|
9447
10891
|
throw new Error('invalid network option, ' + network);
|
|
9448
10892
|
}
|
|
9449
10893
|
if (network === base_1.Network.mainnet) {
|
|
9450
|
-
|
|
9451
|
-
process.exit(1);
|
|
10894
|
+
throw new Error('Mainnet not support yet. Please use CKB-CLI to operate on mainnet for better security. Check https://github.com/nervosnetwork/ckb-cli');
|
|
9452
10895
|
}
|
|
9453
10896
|
}
|
|
9454
10897
|
function isValidVersion(version) {
|
|
@@ -9504,9 +10947,12 @@ function validateUdtKind(kind) {
|
|
|
9504
10947
|
const U128_MAX = (BigInt(1) << BigInt(128)) - BigInt(1);
|
|
9505
10948
|
function validateUdtAmount(amount) {
|
|
9506
10949
|
if (!/^\d+$/.test(amount)) {
|
|
9507
|
-
throw new Error(`invalid UDT amount "${amount}", must be a
|
|
10950
|
+
throw new Error(`invalid UDT amount "${amount}", must be a positive decimal integer`);
|
|
9508
10951
|
}
|
|
9509
10952
|
const value = BigInt(amount);
|
|
10953
|
+
if (value === BigInt(0)) {
|
|
10954
|
+
throw new Error('invalid UDT amount "0", must be greater than zero');
|
|
10955
|
+
}
|
|
9510
10956
|
if (value > U128_MAX) {
|
|
9511
10957
|
throw new Error(`UDT amount exceeds 128-bit max: ${amount}`);
|
|
9512
10958
|
}
|
|
@@ -9522,8 +10968,8 @@ function validateHexString(value, name) {
|
|
|
9522
10968
|
function validateUdtTypeArgs(kind, typeArgs) {
|
|
9523
10969
|
const hex = validateHexString(typeArgs, 'type args');
|
|
9524
10970
|
const byteLength = (hex.length - 2) / 2;
|
|
9525
|
-
if (kind === 'sudt' && byteLength !==
|
|
9526
|
-
throw new Error(`invalid SUDT type args length: expected
|
|
10971
|
+
if (kind === 'sudt' && byteLength !== 32) {
|
|
10972
|
+
throw new Error(`invalid SUDT type args length: expected 32 bytes, got ${byteLength}`);
|
|
9527
10973
|
}
|
|
9528
10974
|
if (kind === 'xudt' && byteLength !== 32) {
|
|
9529
10975
|
throw new Error(`invalid xUDT type args length: expected 32 bytes, got ${byteLength}`);
|
|
@@ -17273,13 +18719,13 @@ exports.randomBytes = randomBytes;
|
|
|
17273
18719
|
|
|
17274
18720
|
/***/ }),
|
|
17275
18721
|
|
|
17276
|
-
/***/
|
|
18722
|
+
/***/ 3858:
|
|
17277
18723
|
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
17278
18724
|
|
|
17279
|
-
const Utils = __nccwpck_require__(
|
|
18725
|
+
const Utils = __nccwpck_require__(91373);
|
|
17280
18726
|
const pth = __nccwpck_require__(16928);
|
|
17281
|
-
const ZipEntry = __nccwpck_require__(
|
|
17282
|
-
const ZipFile = __nccwpck_require__(
|
|
18727
|
+
const ZipEntry = __nccwpck_require__(58851);
|
|
18728
|
+
const ZipFile = __nccwpck_require__(46593);
|
|
17283
18729
|
|
|
17284
18730
|
const get_Bool = (...val) => Utils.findLast(val, (c) => typeof c === "boolean");
|
|
17285
18731
|
const get_Str = (...val) => Utils.findLast(val, (c) => typeof c === "string");
|
|
@@ -17325,6 +18771,18 @@ module.exports = function (/**String*/ input, /** object */ options) {
|
|
|
17325
18771
|
// instanciate utils filesystem
|
|
17326
18772
|
const filetools = new Utils(opts);
|
|
17327
18773
|
|
|
18774
|
+
// Restore the archived permissions on extracted directories. This has to run
|
|
18775
|
+
// after a directory's contents are written: applying a restrictive mode
|
|
18776
|
+
// (e.g. 0o500) up front would stop us writing the files it contains. Applying
|
|
18777
|
+
// the deepest paths first keeps parent directories traversable while their
|
|
18778
|
+
// children are updated (issue #530).
|
|
18779
|
+
const applyDirAttributes = (dirEntries) => {
|
|
18780
|
+
dirEntries
|
|
18781
|
+
.filter((d) => d.attr)
|
|
18782
|
+
.sort((a, b) => b.path.length - a.path.length)
|
|
18783
|
+
.forEach((d) => filetools.fs.chmodSync(d.path, d.attr));
|
|
18784
|
+
};
|
|
18785
|
+
|
|
17328
18786
|
if (typeof opts.decoder !== "object" || typeof opts.decoder.encode !== "function" || typeof opts.decoder.decode !== "function") {
|
|
17329
18787
|
opts.decoder = Utils.decoder;
|
|
17330
18788
|
}
|
|
@@ -17364,7 +18822,7 @@ module.exports = function (/**String*/ input, /** object */ options) {
|
|
|
17364
18822
|
function fixPath(zipPath) {
|
|
17365
18823
|
const { join, normalize, sep } = pth.posix;
|
|
17366
18824
|
// convert windows file separators and normalize
|
|
17367
|
-
return join(".
|
|
18825
|
+
return join(pth.isAbsolute(zipPath) ? "/": '.', normalize(sep + zipPath.split("\\").join(sep) + sep));
|
|
17368
18826
|
}
|
|
17369
18827
|
|
|
17370
18828
|
function filenameFilter(filterfn) {
|
|
@@ -17479,6 +18937,7 @@ module.exports = function (/**String*/ input, /** object */ options) {
|
|
|
17479
18937
|
* Remove the entry from the file or the entry and all it's nested directories and files if the given entry is a directory
|
|
17480
18938
|
*
|
|
17481
18939
|
* @param {ZipEntry|string} entry
|
|
18940
|
+
* @param {boolean} withsubfolders
|
|
17482
18941
|
* @returns {void}
|
|
17483
18942
|
*/
|
|
17484
18943
|
deleteFile: function (entry, withsubfolders = true) {
|
|
@@ -17763,7 +19222,7 @@ module.exports = function (/**String*/ input, /** object */ options) {
|
|
|
17763
19222
|
addLocalFolderAsync2: function (options, callback) {
|
|
17764
19223
|
const self = this;
|
|
17765
19224
|
options = typeof options === "object" ? options : { localPath: options };
|
|
17766
|
-
localPath = pth.resolve(fixPath(options.localPath));
|
|
19225
|
+
const localPath = pth.resolve(fixPath(options.localPath));
|
|
17767
19226
|
let { zipPath, filter, namefix } = options;
|
|
17768
19227
|
|
|
17769
19228
|
if (filter instanceof RegExp) {
|
|
@@ -17782,7 +19241,7 @@ module.exports = function (/**String*/ input, /** object */ options) {
|
|
|
17782
19241
|
zipPath = zipPath ? fixPath(zipPath) : "";
|
|
17783
19242
|
|
|
17784
19243
|
// Check Namefix function
|
|
17785
|
-
if (namefix
|
|
19244
|
+
if (namefix === "latin1") {
|
|
17786
19245
|
namefix = (str) =>
|
|
17787
19246
|
str
|
|
17788
19247
|
.normalize("NFD")
|
|
@@ -17958,7 +19417,7 @@ module.exports = function (/**String*/ input, /** object */ options) {
|
|
|
17958
19417
|
|
|
17959
19418
|
var entryName = canonical(item.entryName);
|
|
17960
19419
|
|
|
17961
|
-
var target = sanitize(targetPath, outFileName && !item.isDirectory ? outFileName : maintainEntryPath ? entryName : pth.basename(entryName));
|
|
19420
|
+
var target = sanitize(targetPath, outFileName && !item.isDirectory ? canonical(outFileName) : maintainEntryPath ? entryName : pth.basename(entryName));
|
|
17962
19421
|
|
|
17963
19422
|
if (item.isDirectory) {
|
|
17964
19423
|
var children = _zip.getEntryChildren(item);
|
|
@@ -17968,8 +19427,12 @@ module.exports = function (/**String*/ input, /** object */ options) {
|
|
|
17968
19427
|
if (!content) {
|
|
17969
19428
|
throw Utils.Errors.CANT_EXTRACT_FILE();
|
|
17970
19429
|
}
|
|
17971
|
-
|
|
17972
|
-
|
|
19430
|
+
// When not maintaining the full entry path, keep each child's path
|
|
19431
|
+
// relative to the extracted directory (drop the directory's own
|
|
19432
|
+
// prefix) instead of flattening every file to its basename, which
|
|
19433
|
+
// collapsed subdirectories together (issue #306).
|
|
19434
|
+
var name = canonical(maintainEntryPath ? child.entryName : child.entryName.substring(item.entryName.length));
|
|
19435
|
+
var childName = sanitize(targetPath, name);
|
|
17973
19436
|
// The reverse operation for attr depend on method addFile()
|
|
17974
19437
|
const fileAttr = keepOriginalPermission ? child.header.fileAttr : undefined;
|
|
17975
19438
|
filetools.writeFileTo(childName, content, overwrite, fileAttr);
|
|
@@ -17999,12 +19462,14 @@ module.exports = function (/**String*/ input, /** object */ options) {
|
|
|
17999
19462
|
return false;
|
|
18000
19463
|
}
|
|
18001
19464
|
|
|
18002
|
-
for (var entry
|
|
19465
|
+
for (var entry of _zip.entries) {
|
|
18003
19466
|
try {
|
|
18004
19467
|
if (entry.isDirectory) {
|
|
18005
19468
|
continue;
|
|
18006
19469
|
}
|
|
18007
|
-
|
|
19470
|
+
// was `_zip.entries[entry]` (indexing the array with an entry
|
|
19471
|
+
// object -> undefined -> threw -> test() always returned false)
|
|
19472
|
+
var content = entry.getData(pass);
|
|
18008
19473
|
if (!content) {
|
|
18009
19474
|
return false;
|
|
18010
19475
|
}
|
|
@@ -18031,10 +19496,13 @@ module.exports = function (/**String*/ input, /** object */ options) {
|
|
|
18031
19496
|
overwrite = get_Bool(false, overwrite);
|
|
18032
19497
|
if (!_zip) throw Utils.Errors.NO_ZIP();
|
|
18033
19498
|
|
|
19499
|
+
const dirEntries = [];
|
|
18034
19500
|
_zip.entries.forEach(function (entry) {
|
|
18035
19501
|
var entryName = sanitize(targetPath, canonical(entry.entryName));
|
|
18036
19502
|
if (entry.isDirectory) {
|
|
18037
19503
|
filetools.makeDir(entryName);
|
|
19504
|
+
// defer restoring the directory permission until its files are written
|
|
19505
|
+
if (keepOriginalPermission) dirEntries.push({ path: entryName, attr: entry.header.fileAttr });
|
|
18038
19506
|
return;
|
|
18039
19507
|
}
|
|
18040
19508
|
var content = entry.getData(pass);
|
|
@@ -18045,11 +19513,15 @@ module.exports = function (/**String*/ input, /** object */ options) {
|
|
|
18045
19513
|
const fileAttr = keepOriginalPermission ? entry.header.fileAttr : undefined;
|
|
18046
19514
|
filetools.writeFileTo(entryName, content, overwrite, fileAttr);
|
|
18047
19515
|
try {
|
|
19516
|
+
// best-effort: an invalid date in the archive or a filesystem that
|
|
19517
|
+
// rejects utimes must not fail extraction of already-written content (issue #379)
|
|
18048
19518
|
filetools.fs.utimesSync(entryName, entry.header.time, entry.header.time);
|
|
18049
19519
|
} catch (err) {
|
|
18050
|
-
|
|
19520
|
+
/* ignore timestamp failures */
|
|
18051
19521
|
}
|
|
18052
19522
|
});
|
|
19523
|
+
|
|
19524
|
+
applyDirAttributes(dirEntries);
|
|
18053
19525
|
},
|
|
18054
19526
|
|
|
18055
19527
|
/**
|
|
@@ -18100,20 +19572,41 @@ module.exports = function (/**String*/ input, /** object */ options) {
|
|
|
18100
19572
|
|
|
18101
19573
|
// Create directory entries first synchronously
|
|
18102
19574
|
// this prevents race condition and assures folders are there before writing files
|
|
19575
|
+
const deferredDirAttr = [];
|
|
18103
19576
|
for (const entry of dirEntries) {
|
|
18104
19577
|
const dirPath = getPath(entry);
|
|
18105
19578
|
// The reverse operation for attr depend on method addFile()
|
|
18106
19579
|
const dirAttr = keepOriginalPermission ? entry.header.fileAttr : undefined;
|
|
18107
19580
|
try {
|
|
18108
19581
|
filetools.makeDir(dirPath);
|
|
18109
|
-
if (dirAttr) filetools.fs.chmodSync(dirPath, dirAttr);
|
|
18110
|
-
// in unix timestamp will change if files are later added to folder, but still
|
|
18111
|
-
filetools.fs.utimesSync(dirPath, entry.header.time, entry.header.time);
|
|
18112
19582
|
} catch (er) {
|
|
18113
19583
|
callback(getError("Unable to create folder", dirPath));
|
|
19584
|
+
continue;
|
|
19585
|
+
}
|
|
19586
|
+
// defer restoring the directory permission until its files are written:
|
|
19587
|
+
// a restrictive mode applied now would block writing them
|
|
19588
|
+
if (dirAttr) deferredDirAttr.push({ path: dirPath, attr: dirAttr });
|
|
19589
|
+
try {
|
|
19590
|
+
// in unix timestamp will change if files are later added to folder, but still.
|
|
19591
|
+
// best-effort: a utimes failure must not abort extraction (issue #379)
|
|
19592
|
+
filetools.fs.utimesSync(dirPath, entry.header.time, entry.header.time);
|
|
19593
|
+
} catch (er) {
|
|
19594
|
+
/* ignore timestamp failures */
|
|
18114
19595
|
}
|
|
18115
19596
|
}
|
|
18116
19597
|
|
|
19598
|
+
// restore directory permissions once every file has been extracted
|
|
19599
|
+
const done = (err) => {
|
|
19600
|
+
if (!err) {
|
|
19601
|
+
try {
|
|
19602
|
+
applyDirAttributes(deferredDirAttr);
|
|
19603
|
+
} catch (er) {
|
|
19604
|
+
return callback(getError("Unable to set folder permissions", er.path || ""));
|
|
19605
|
+
}
|
|
19606
|
+
}
|
|
19607
|
+
callback(err);
|
|
19608
|
+
};
|
|
19609
|
+
|
|
18117
19610
|
fileEntries.reverse().reduce(function (next, entry) {
|
|
18118
19611
|
return function (err) {
|
|
18119
19612
|
if (err) {
|
|
@@ -18131,21 +19624,19 @@ module.exports = function (/**String*/ input, /** object */ options) {
|
|
|
18131
19624
|
const fileAttr = keepOriginalPermission ? entry.header.fileAttr : undefined;
|
|
18132
19625
|
filetools.writeFileToAsync(filePath, content, overwrite, fileAttr, function (succ) {
|
|
18133
19626
|
if (!succ) {
|
|
18134
|
-
next(getError("Unable to write file", filePath));
|
|
19627
|
+
return next(getError("Unable to write file", filePath));
|
|
18135
19628
|
}
|
|
18136
|
-
filetools.fs.utimes(filePath, entry.header.time, entry.header.time, function (
|
|
18137
|
-
|
|
18138
|
-
|
|
18139
|
-
|
|
18140
|
-
next();
|
|
18141
|
-
}
|
|
19629
|
+
filetools.fs.utimes(filePath, entry.header.time, entry.header.time, function () {
|
|
19630
|
+
// best-effort: a utimes failure must not abort extraction
|
|
19631
|
+
// of already-written content (issue #379)
|
|
19632
|
+
next();
|
|
18142
19633
|
});
|
|
18143
19634
|
});
|
|
18144
19635
|
}
|
|
18145
19636
|
});
|
|
18146
19637
|
}
|
|
18147
19638
|
};
|
|
18148
|
-
},
|
|
19639
|
+
}, done)();
|
|
18149
19640
|
},
|
|
18150
19641
|
|
|
18151
19642
|
/**
|
|
@@ -18229,10 +19720,10 @@ module.exports = function (/**String*/ input, /** object */ options) {
|
|
|
18229
19720
|
|
|
18230
19721
|
/***/ }),
|
|
18231
19722
|
|
|
18232
|
-
/***/
|
|
19723
|
+
/***/ 88436:
|
|
18233
19724
|
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
18234
19725
|
|
|
18235
|
-
var Utils = __nccwpck_require__(
|
|
19726
|
+
var Utils = __nccwpck_require__(91373),
|
|
18236
19727
|
Constants = Utils.Constants;
|
|
18237
19728
|
|
|
18238
19729
|
/* The central directory file header */
|
|
@@ -18321,6 +19812,7 @@ module.exports = function () {
|
|
|
18321
19812
|
switch (val) {
|
|
18322
19813
|
case Constants.STORED:
|
|
18323
19814
|
this.version = 10;
|
|
19815
|
+
break;
|
|
18324
19816
|
case Constants.DEFLATED:
|
|
18325
19817
|
default:
|
|
18326
19818
|
this.version = 20;
|
|
@@ -18332,6 +19824,7 @@ module.exports = function () {
|
|
|
18332
19824
|
return Utils.fromDOS2Date(this.timeval);
|
|
18333
19825
|
},
|
|
18334
19826
|
set time(val) {
|
|
19827
|
+
val = new Date(val);
|
|
18335
19828
|
this.timeval = Utils.fromDate2DOS(val);
|
|
18336
19829
|
},
|
|
18337
19830
|
|
|
@@ -18454,6 +19947,8 @@ module.exports = function () {
|
|
|
18454
19947
|
_localHeader.version = data.readUInt16LE(Constants.LOCVER);
|
|
18455
19948
|
// general purpose bit flag
|
|
18456
19949
|
_localHeader.flags = data.readUInt16LE(Constants.LOCFLG);
|
|
19950
|
+
// desc flag
|
|
19951
|
+
_localHeader.flags_desc = (_localHeader.flags & Constants.FLG_DESC) > 0;
|
|
18457
19952
|
// compression method
|
|
18458
19953
|
_localHeader.method = data.readUInt16LE(Constants.LOCHOW);
|
|
18459
19954
|
// modification time (2 bytes time, 2 bytes date)
|
|
@@ -18520,7 +20015,11 @@ module.exports = function () {
|
|
|
18520
20015
|
// version needed to extract
|
|
18521
20016
|
data.writeUInt16LE(_version, Constants.LOCVER);
|
|
18522
20017
|
// general purpose bit flag
|
|
18523
|
-
data
|
|
20018
|
+
// clear bit 3 (data descriptor): we always write the real crc-32
|
|
20019
|
+
// and sizes into this local header, so no trailing descriptor is
|
|
20020
|
+
// emitted. Leaving the flag set would make the output unreadable
|
|
20021
|
+
// (see issue #555).
|
|
20022
|
+
data.writeUInt16LE(_flags & ~Constants.FLG_DESC, Constants.LOCFLG);
|
|
18524
20023
|
// compression method
|
|
18525
20024
|
data.writeUInt16LE(_method, Constants.LOCHOW);
|
|
18526
20025
|
// modification time (2 bytes time, 2 bytes date)
|
|
@@ -18548,7 +20047,9 @@ module.exports = function () {
|
|
|
18548
20047
|
// version needed to extract
|
|
18549
20048
|
data.writeUInt16LE(_version, Constants.CENVER);
|
|
18550
20049
|
// encrypt, decrypt flags
|
|
18551
|
-
data
|
|
20050
|
+
// clear bit 3 (data descriptor) to match the local header we emit
|
|
20051
|
+
// (real crc/sizes are written, no descriptor follows the data) — issue #555
|
|
20052
|
+
data.writeUInt16LE(_flags & ~Constants.FLG_DESC, Constants.CENFLG);
|
|
18552
20053
|
// compression method
|
|
18553
20054
|
data.writeUInt16LE(_method, Constants.CENHOW);
|
|
18554
20055
|
// modification time (2 bytes time, 2 bytes date)
|
|
@@ -18610,19 +20111,19 @@ module.exports = function () {
|
|
|
18610
20111
|
|
|
18611
20112
|
/***/ }),
|
|
18612
20113
|
|
|
18613
|
-
/***/
|
|
20114
|
+
/***/ 77837:
|
|
18614
20115
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
18615
20116
|
|
|
18616
|
-
exports.EntryHeader = __nccwpck_require__(
|
|
18617
|
-
exports.MainHeader = __nccwpck_require__(
|
|
20117
|
+
exports.EntryHeader = __nccwpck_require__(88436);
|
|
20118
|
+
exports.MainHeader = __nccwpck_require__(88889);
|
|
18618
20119
|
|
|
18619
20120
|
|
|
18620
20121
|
/***/ }),
|
|
18621
20122
|
|
|
18622
|
-
/***/
|
|
20123
|
+
/***/ 88889:
|
|
18623
20124
|
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
18624
20125
|
|
|
18625
|
-
var Utils = __nccwpck_require__(
|
|
20126
|
+
var Utils = __nccwpck_require__(91373),
|
|
18626
20127
|
Constants = Utils.Constants;
|
|
18627
20128
|
|
|
18628
20129
|
/* The entries in the end of central directory */
|
|
@@ -18633,6 +20134,8 @@ module.exports = function () {
|
|
|
18633
20134
|
_offset = 0,
|
|
18634
20135
|
_commentLength = 0;
|
|
18635
20136
|
|
|
20137
|
+
const needsZip64 = () => _volumeEntries > Constants.EF_ZIP64_OR_16 || _totalEntries > Constants.EF_ZIP64_OR_16 || _size > Constants.EF_ZIP64_OR_32 || _offset > Constants.EF_ZIP64_OR_32;
|
|
20138
|
+
|
|
18636
20139
|
return {
|
|
18637
20140
|
get diskEntries() {
|
|
18638
20141
|
return _volumeEntries;
|
|
@@ -18670,7 +20173,7 @@ module.exports = function () {
|
|
|
18670
20173
|
},
|
|
18671
20174
|
|
|
18672
20175
|
get mainHeaderSize() {
|
|
18673
|
-
return Constants.ENDHDR + _commentLength;
|
|
20176
|
+
return (needsZip64() ? Constants.ZIP64HDR + Constants.END64HDR : 0) + Constants.ENDHDR + _commentLength;
|
|
18674
20177
|
},
|
|
18675
20178
|
|
|
18676
20179
|
loadFromBinary: function (/*Buffer*/ data) {
|
|
@@ -18700,7 +20203,7 @@ module.exports = function () {
|
|
|
18700
20203
|
// total number of entries
|
|
18701
20204
|
_totalEntries = Utils.readBigUInt64LE(data, Constants.ZIP64TOT);
|
|
18702
20205
|
// central directory size in bytes
|
|
18703
|
-
_size = Utils.readBigUInt64LE(data, Constants.
|
|
20206
|
+
_size = Utils.readBigUInt64LE(data, Constants.ZIP64SIZB);
|
|
18704
20207
|
// offset of first CEN header
|
|
18705
20208
|
_offset = Utils.readBigUInt64LE(data, Constants.ZIP64OFF);
|
|
18706
20209
|
|
|
@@ -18709,22 +20212,67 @@ module.exports = function () {
|
|
|
18709
20212
|
},
|
|
18710
20213
|
|
|
18711
20214
|
toBinary: function () {
|
|
18712
|
-
|
|
20215
|
+
if (!needsZip64()) {
|
|
20216
|
+
var b = Buffer.alloc(Constants.ENDHDR + _commentLength);
|
|
20217
|
+
// "PK 05 06" signature
|
|
20218
|
+
b.writeUInt32LE(Constants.ENDSIG, 0);
|
|
20219
|
+
b.writeUInt32LE(0, 4);
|
|
20220
|
+
// number of entries on this volume
|
|
20221
|
+
b.writeUInt16LE(_volumeEntries, Constants.ENDSUB);
|
|
20222
|
+
// total number of entries
|
|
20223
|
+
b.writeUInt16LE(_totalEntries, Constants.ENDTOT);
|
|
20224
|
+
// central directory size in bytes
|
|
20225
|
+
b.writeUInt32LE(_size, Constants.ENDSIZ);
|
|
20226
|
+
// offset of first CEN header
|
|
20227
|
+
b.writeUInt32LE(_offset, Constants.ENDOFF);
|
|
20228
|
+
// zip file comment length
|
|
20229
|
+
b.writeUInt16LE(_commentLength, Constants.ENDCOM);
|
|
20230
|
+
// fill comment memory with spaces so no garbage is left there
|
|
20231
|
+
b.fill(" ", Constants.ENDHDR);
|
|
20232
|
+
|
|
20233
|
+
return b;
|
|
20234
|
+
}
|
|
20235
|
+
|
|
20236
|
+
var b = Buffer.alloc(this.mainHeaderSize);
|
|
20237
|
+
let offset = 0;
|
|
20238
|
+
|
|
20239
|
+
// Zip64 end of central directory record.
|
|
20240
|
+
b.writeUInt32LE(Constants.ZIP64SIG, offset);
|
|
20241
|
+
Utils.writeBigUInt64LE(b, Constants.ZIP64HDR - Constants.ZIP64LEAD, offset + Constants.ZIP64SIZE);
|
|
20242
|
+
b.writeUInt16LE(45, offset + Constants.ZIP64VEM);
|
|
20243
|
+
b.writeUInt16LE(45, offset + Constants.ZIP64VER);
|
|
20244
|
+
b.writeUInt32LE(0, offset + Constants.ZIP64DSK);
|
|
20245
|
+
b.writeUInt32LE(0, offset + Constants.ZIP64DSKDIR);
|
|
20246
|
+
Utils.writeBigUInt64LE(b, _volumeEntries, offset + Constants.ZIP64SUB);
|
|
20247
|
+
Utils.writeBigUInt64LE(b, _totalEntries, offset + Constants.ZIP64TOT);
|
|
20248
|
+
Utils.writeBigUInt64LE(b, _size, offset + Constants.ZIP64SIZB);
|
|
20249
|
+
Utils.writeBigUInt64LE(b, _offset, offset + Constants.ZIP64OFF);
|
|
20250
|
+
|
|
20251
|
+
const zip64EndOffset = _offset + _size;
|
|
20252
|
+
offset += Constants.ZIP64HDR;
|
|
20253
|
+
|
|
20254
|
+
// Zip64 end of central directory locator.
|
|
20255
|
+
b.writeUInt32LE(Constants.END64SIG, offset);
|
|
20256
|
+
b.writeUInt32LE(0, offset + Constants.END64START);
|
|
20257
|
+
Utils.writeBigUInt64LE(b, zip64EndOffset, offset + Constants.END64OFF);
|
|
20258
|
+
b.writeUInt32LE(1, offset + Constants.END64NUMDISKS);
|
|
20259
|
+
offset += Constants.END64HDR;
|
|
20260
|
+
|
|
18713
20261
|
// "PK 05 06" signature
|
|
18714
|
-
b.writeUInt32LE(Constants.ENDSIG,
|
|
18715
|
-
b.writeUInt32LE(0, 4);
|
|
20262
|
+
b.writeUInt32LE(Constants.ENDSIG, offset);
|
|
20263
|
+
b.writeUInt32LE(0, offset + 4);
|
|
18716
20264
|
// number of entries on this volume
|
|
18717
|
-
b.writeUInt16LE(_volumeEntries, Constants.ENDSUB);
|
|
20265
|
+
b.writeUInt16LE(Math.min(_volumeEntries, Constants.EF_ZIP64_OR_16), offset + Constants.ENDSUB);
|
|
18718
20266
|
// total number of entries
|
|
18719
|
-
b.writeUInt16LE(_totalEntries, Constants.ENDTOT);
|
|
20267
|
+
b.writeUInt16LE(Math.min(_totalEntries, Constants.EF_ZIP64_OR_16), offset + Constants.ENDTOT);
|
|
18720
20268
|
// central directory size in bytes
|
|
18721
|
-
b.writeUInt32LE(_size, Constants.ENDSIZ);
|
|
20269
|
+
b.writeUInt32LE(Math.min(_size, Constants.EF_ZIP64_OR_32), offset + Constants.ENDSIZ);
|
|
18722
20270
|
// offset of first CEN header
|
|
18723
|
-
b.writeUInt32LE(_offset, Constants.ENDOFF);
|
|
20271
|
+
b.writeUInt32LE(Math.min(_offset, Constants.EF_ZIP64_OR_32), offset + Constants.ENDOFF);
|
|
18724
20272
|
// zip file comment length
|
|
18725
|
-
b.writeUInt16LE(_commentLength, Constants.ENDCOM);
|
|
20273
|
+
b.writeUInt16LE(_commentLength, offset + Constants.ENDCOM);
|
|
18726
20274
|
// fill comment memory with spaces so no garbage is left there
|
|
18727
|
-
b.fill(" ", Constants.ENDHDR);
|
|
20275
|
+
b.fill(" ", offset + Constants.ENDHDR);
|
|
18728
20276
|
|
|
18729
20277
|
return b;
|
|
18730
20278
|
},
|
|
@@ -18756,7 +20304,7 @@ module.exports = function () {
|
|
|
18756
20304
|
|
|
18757
20305
|
/***/ }),
|
|
18758
20306
|
|
|
18759
|
-
/***/
|
|
20307
|
+
/***/ 49466:
|
|
18760
20308
|
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
18761
20309
|
|
|
18762
20310
|
module.exports = function (/*Buffer*/ inbuf) {
|
|
@@ -18796,20 +20344,20 @@ module.exports = function (/*Buffer*/ inbuf) {
|
|
|
18796
20344
|
|
|
18797
20345
|
/***/ }),
|
|
18798
20346
|
|
|
18799
|
-
/***/
|
|
20347
|
+
/***/ 70493:
|
|
18800
20348
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
18801
20349
|
|
|
18802
|
-
exports.Deflater = __nccwpck_require__(
|
|
18803
|
-
exports.Inflater = __nccwpck_require__(
|
|
18804
|
-
exports.ZipCrypto = __nccwpck_require__(
|
|
20350
|
+
exports.Deflater = __nccwpck_require__(49466);
|
|
20351
|
+
exports.Inflater = __nccwpck_require__(27298);
|
|
20352
|
+
exports.ZipCrypto = __nccwpck_require__(19687);
|
|
18805
20353
|
|
|
18806
20354
|
|
|
18807
20355
|
/***/ }),
|
|
18808
20356
|
|
|
18809
|
-
/***/
|
|
20357
|
+
/***/ 27298:
|
|
18810
20358
|
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
18811
20359
|
|
|
18812
|
-
const version = +(process
|
|
20360
|
+
const version = +(process?.versions?.node ?? "").split(".")[0] || 0;
|
|
18813
20361
|
|
|
18814
20362
|
module.exports = function (/*Buffer*/ inbuf, /*number*/ expectedLength) {
|
|
18815
20363
|
var zlib = __nccwpck_require__(43106);
|
|
@@ -18847,7 +20395,7 @@ module.exports = function (/*Buffer*/ inbuf, /*number*/ expectedLength) {
|
|
|
18847
20395
|
|
|
18848
20396
|
/***/ }),
|
|
18849
20397
|
|
|
18850
|
-
/***/
|
|
20398
|
+
/***/ 19687:
|
|
18851
20399
|
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
18852
20400
|
|
|
18853
20401
|
"use strict";
|
|
@@ -18856,7 +20404,7 @@ module.exports = function (/*Buffer*/ inbuf, /*number*/ expectedLength) {
|
|
|
18856
20404
|
// node crypt, we use it for generate salt
|
|
18857
20405
|
// eslint-disable-next-line node/no-unsupported-features/node-builtins
|
|
18858
20406
|
const { randomFillSync } = __nccwpck_require__(76982);
|
|
18859
|
-
const Errors = __nccwpck_require__(
|
|
20407
|
+
const Errors = __nccwpck_require__(9314);
|
|
18860
20408
|
|
|
18861
20409
|
// generate CRC32 lookup table
|
|
18862
20410
|
const crctable = new Uint32Array(256).map((t, crc) => {
|
|
@@ -19030,7 +20578,7 @@ module.exports = { decrypt, encrypt, _salter };
|
|
|
19030
20578
|
|
|
19031
20579
|
/***/ }),
|
|
19032
20580
|
|
|
19033
|
-
/***/
|
|
20581
|
+
/***/ 85604:
|
|
19034
20582
|
/***/ ((module) => {
|
|
19035
20583
|
|
|
19036
20584
|
module.exports = {
|
|
@@ -19179,7 +20727,7 @@ module.exports = {
|
|
|
19179
20727
|
|
|
19180
20728
|
/***/ }),
|
|
19181
20729
|
|
|
19182
|
-
/***/
|
|
20730
|
+
/***/ 95825:
|
|
19183
20731
|
/***/ ((module) => {
|
|
19184
20732
|
|
|
19185
20733
|
module.exports = {
|
|
@@ -19191,7 +20739,7 @@ module.exports = {
|
|
|
19191
20739
|
|
|
19192
20740
|
/***/ }),
|
|
19193
20741
|
|
|
19194
|
-
/***/
|
|
20742
|
+
/***/ 9314:
|
|
19195
20743
|
/***/ ((__unused_webpack_module, exports) => {
|
|
19196
20744
|
|
|
19197
20745
|
const errors = {
|
|
@@ -19261,7 +20809,7 @@ for (const msg of Object.keys(errors)) {
|
|
|
19261
20809
|
|
|
19262
20810
|
/***/ }),
|
|
19263
20811
|
|
|
19264
|
-
/***/
|
|
20812
|
+
/***/ 71560:
|
|
19265
20813
|
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
19266
20814
|
|
|
19267
20815
|
const pth = __nccwpck_require__(16928);
|
|
@@ -19344,25 +20892,25 @@ module.exports = function (/*String*/ path, /*Utils object*/ { fs }) {
|
|
|
19344
20892
|
|
|
19345
20893
|
/***/ }),
|
|
19346
20894
|
|
|
19347
|
-
/***/
|
|
20895
|
+
/***/ 91373:
|
|
19348
20896
|
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
19349
20897
|
|
|
19350
|
-
module.exports = __nccwpck_require__(
|
|
19351
|
-
module.exports.Constants = __nccwpck_require__(
|
|
19352
|
-
module.exports.Errors = __nccwpck_require__(
|
|
19353
|
-
module.exports.FileAttr = __nccwpck_require__(
|
|
19354
|
-
module.exports.decoder = __nccwpck_require__(
|
|
20898
|
+
module.exports = __nccwpck_require__(12056);
|
|
20899
|
+
module.exports.Constants = __nccwpck_require__(85604);
|
|
20900
|
+
module.exports.Errors = __nccwpck_require__(9314);
|
|
20901
|
+
module.exports.FileAttr = __nccwpck_require__(71560);
|
|
20902
|
+
module.exports.decoder = __nccwpck_require__(95825);
|
|
19355
20903
|
|
|
19356
20904
|
|
|
19357
20905
|
/***/ }),
|
|
19358
20906
|
|
|
19359
|
-
/***/
|
|
20907
|
+
/***/ 12056:
|
|
19360
20908
|
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
19361
20909
|
|
|
19362
20910
|
const fsystem = __nccwpck_require__(79896);
|
|
19363
20911
|
const pth = __nccwpck_require__(16928);
|
|
19364
|
-
const Constants = __nccwpck_require__(
|
|
19365
|
-
const Errors = __nccwpck_require__(
|
|
20912
|
+
const Constants = __nccwpck_require__(85604);
|
|
20913
|
+
const Errors = __nccwpck_require__(9314);
|
|
19366
20914
|
const isWin = typeof process === "object" && "win32" === process.platform;
|
|
19367
20915
|
|
|
19368
20916
|
const is_Obj = (obj) => typeof obj === "object" && obj !== null;
|
|
@@ -19410,7 +20958,11 @@ Utils.prototype.makeDir = function (/*String*/ folder) {
|
|
|
19410
20958
|
try {
|
|
19411
20959
|
stat = self.fs.statSync(resolvedPath);
|
|
19412
20960
|
} catch (e) {
|
|
19413
|
-
|
|
20961
|
+
if (e.message && e.message.startsWith('ENOENT')) {
|
|
20962
|
+
self.fs.mkdirSync(resolvedPath);
|
|
20963
|
+
} else {
|
|
20964
|
+
throw e;
|
|
20965
|
+
}
|
|
19414
20966
|
}
|
|
19415
20967
|
if (stat && stat.isFile()) throw Errors.FILE_IN_THE_WAY(`"${resolvedPath}"`);
|
|
19416
20968
|
});
|
|
@@ -19464,39 +21016,51 @@ Utils.prototype.writeFileToAsync = function (/*String*/ path, /*Buffer*/ content
|
|
|
19464
21016
|
if (exist && !overwrite) return callback(false);
|
|
19465
21017
|
|
|
19466
21018
|
self.fs.stat(path, function (err, stat) {
|
|
19467
|
-
if (exist && stat.isDirectory()) {
|
|
21019
|
+
if (exist && stat && stat.isDirectory()) {
|
|
19468
21020
|
return callback(false);
|
|
19469
21021
|
}
|
|
19470
21022
|
|
|
19471
21023
|
var folder = pth.dirname(path);
|
|
19472
21024
|
self.fs.exists(folder, function (exists) {
|
|
19473
|
-
if (!exists)
|
|
21025
|
+
if (!exists) {
|
|
21026
|
+
// makeDir is synchronous and can throw (e.g. EACCES); report failure
|
|
21027
|
+
// rather than letting it escape this callback as an uncaught exception
|
|
21028
|
+
try {
|
|
21029
|
+
self.makeDir(folder);
|
|
21030
|
+
} catch (e) {
|
|
21031
|
+
return callback(false);
|
|
21032
|
+
}
|
|
21033
|
+
}
|
|
21034
|
+
|
|
21035
|
+
// write the content to an open descriptor, then apply the attributes
|
|
21036
|
+
const writeToFd = function (fd) {
|
|
21037
|
+
self.fs.write(fd, content, 0, content.length, 0, function (writeErr) {
|
|
21038
|
+
self.fs.close(fd, function () {
|
|
21039
|
+
// surface write failures instead of silently reporting success (issue #402)
|
|
21040
|
+
if (writeErr) return callback(false);
|
|
21041
|
+
self.fs.chmod(path, attr || 0o666, function () {
|
|
21042
|
+
callback(true);
|
|
21043
|
+
});
|
|
21044
|
+
});
|
|
21045
|
+
});
|
|
21046
|
+
};
|
|
19474
21047
|
|
|
19475
21048
|
self.fs.open(path, "w", 0o666, function (err, fd) {
|
|
19476
21049
|
if (err) {
|
|
21050
|
+
// the target may exist but be read-only: make it writable and retry once
|
|
19477
21051
|
self.fs.chmod(path, 0o666, function () {
|
|
19478
|
-
self.fs.open(path, "w", 0o666, function (
|
|
19479
|
-
|
|
19480
|
-
|
|
19481
|
-
|
|
19482
|
-
|
|
19483
|
-
|
|
19484
|
-
});
|
|
19485
|
-
});
|
|
21052
|
+
self.fs.open(path, "w", 0o666, function (retryErr, fd) {
|
|
21053
|
+
// Previously the retry error was ignored and an undefined fd was
|
|
21054
|
+
// passed to fs.write, throwing an uncaught ERR_INVALID_ARG_TYPE that
|
|
21055
|
+
// crashed the process (issues #470, #459, #402). Report failure instead.
|
|
21056
|
+
if (retryErr || !fd) return callback(false);
|
|
21057
|
+
writeToFd(fd);
|
|
19486
21058
|
});
|
|
19487
21059
|
});
|
|
19488
21060
|
} else if (fd) {
|
|
19489
|
-
|
|
19490
|
-
self.fs.close(fd, function () {
|
|
19491
|
-
self.fs.chmod(path, attr || 0o666, function () {
|
|
19492
|
-
callback(true);
|
|
19493
|
-
});
|
|
19494
|
-
});
|
|
19495
|
-
});
|
|
21061
|
+
writeToFd(fd);
|
|
19496
21062
|
} else {
|
|
19497
|
-
|
|
19498
|
-
callback(true);
|
|
19499
|
-
});
|
|
21063
|
+
callback(false);
|
|
19500
21064
|
}
|
|
19501
21065
|
});
|
|
19502
21066
|
});
|
|
@@ -19507,7 +21071,7 @@ Utils.prototype.writeFileToAsync = function (/*String*/ path, /*Buffer*/ content
|
|
|
19507
21071
|
Utils.prototype.findFiles = function (/*String*/ path) {
|
|
19508
21072
|
const self = this;
|
|
19509
21073
|
|
|
19510
|
-
function findSync(/*String*/ dir, /*RegExp*/ pattern, /*Boolean*/ recursive) {
|
|
21074
|
+
function findSync(/*String*/ dir, /*RegExp*/ pattern, /*Boolean*/ recursive, /*Set*/ visited) {
|
|
19511
21075
|
if (typeof pattern === "boolean") {
|
|
19512
21076
|
recursive = pattern;
|
|
19513
21077
|
pattern = undefined;
|
|
@@ -19521,12 +21085,22 @@ Utils.prototype.findFiles = function (/*String*/ path) {
|
|
|
19521
21085
|
files.push(pth.normalize(path) + (stat.isDirectory() ? self.sep : ""));
|
|
19522
21086
|
}
|
|
19523
21087
|
|
|
19524
|
-
if (stat.isDirectory() && recursive)
|
|
21088
|
+
if (stat.isDirectory() && recursive) {
|
|
21089
|
+
// Descend by resolved real path and skip directories we have already
|
|
21090
|
+
// visited. This stops a symlink that points back to an ancestor from
|
|
21091
|
+
// recursing forever until the path fails with ELOOP / ENAMETOOLONG
|
|
21092
|
+
// (issue #541).
|
|
21093
|
+
const realDir = self.fs.realpathSync(path);
|
|
21094
|
+
if (!visited.has(realDir)) {
|
|
21095
|
+
visited.add(realDir);
|
|
21096
|
+
files = files.concat(findSync(path, pattern, recursive, visited));
|
|
21097
|
+
}
|
|
21098
|
+
}
|
|
19525
21099
|
});
|
|
19526
21100
|
return files;
|
|
19527
21101
|
}
|
|
19528
21102
|
|
|
19529
|
-
return findSync(path, undefined, true);
|
|
21103
|
+
return findSync(path, undefined, true, new Set([self.fs.realpathSync(path)]));
|
|
19530
21104
|
};
|
|
19531
21105
|
|
|
19532
21106
|
/**
|
|
@@ -19544,29 +21118,54 @@ Utils.prototype.findFiles = function (/*String*/ path) {
|
|
|
19544
21118
|
*/
|
|
19545
21119
|
Utils.prototype.findFilesAsync = function (dir, cb) {
|
|
19546
21120
|
const self = this;
|
|
19547
|
-
|
|
19548
|
-
|
|
19549
|
-
|
|
19550
|
-
|
|
19551
|
-
|
|
19552
|
-
|
|
19553
|
-
|
|
19554
|
-
|
|
19555
|
-
|
|
19556
|
-
|
|
21121
|
+
const results = [];
|
|
21122
|
+
let finished = false;
|
|
21123
|
+
const finish = function (err) {
|
|
21124
|
+
if (finished) return;
|
|
21125
|
+
finished = true;
|
|
21126
|
+
cb(err, err ? undefined : results);
|
|
21127
|
+
};
|
|
21128
|
+
|
|
21129
|
+
// Descend by resolved real path and skip directories already visited, so a
|
|
21130
|
+
// symlink pointing back to an ancestor cannot recurse forever (issue #541).
|
|
21131
|
+
const walk = function (dir, visited, done) {
|
|
21132
|
+
self.fs.readdir(dir, function (err, list) {
|
|
21133
|
+
if (err) return done(err);
|
|
21134
|
+
let pending = list.length;
|
|
21135
|
+
if (!pending) return done();
|
|
21136
|
+
list.forEach(function (name) {
|
|
21137
|
+
const file = pth.join(dir, name);
|
|
21138
|
+
self.fs.stat(file, function (err, stat) {
|
|
21139
|
+
if (err) return done(err);
|
|
21140
|
+
if (!stat) {
|
|
21141
|
+
if (!--pending) done();
|
|
21142
|
+
return;
|
|
21143
|
+
}
|
|
19557
21144
|
results.push(pth.normalize(file) + (stat.isDirectory() ? self.sep : ""));
|
|
19558
|
-
if (stat.isDirectory()) {
|
|
19559
|
-
|
|
19560
|
-
|
|
19561
|
-
results = results.concat(res);
|
|
19562
|
-
if (!--list_length) cb(null, results);
|
|
19563
|
-
});
|
|
19564
|
-
} else {
|
|
19565
|
-
if (!--list_length) cb(null, results);
|
|
21145
|
+
if (!stat.isDirectory()) {
|
|
21146
|
+
if (!--pending) done();
|
|
21147
|
+
return;
|
|
19566
21148
|
}
|
|
19567
|
-
|
|
21149
|
+
self.fs.realpath(file, function (err, realDir) {
|
|
21150
|
+
if (err) return done(err);
|
|
21151
|
+
if (visited.has(realDir)) {
|
|
21152
|
+
if (!--pending) done();
|
|
21153
|
+
return;
|
|
21154
|
+
}
|
|
21155
|
+
visited.add(realDir);
|
|
21156
|
+
walk(file, visited, function (err) {
|
|
21157
|
+
if (err) return done(err);
|
|
21158
|
+
if (!--pending) done();
|
|
21159
|
+
});
|
|
21160
|
+
});
|
|
21161
|
+
});
|
|
19568
21162
|
});
|
|
19569
21163
|
});
|
|
21164
|
+
};
|
|
21165
|
+
|
|
21166
|
+
self.fs.realpath(dir, function (err, realDir) {
|
|
21167
|
+
if (err) return finish(err);
|
|
21168
|
+
walk(dir, new Set([realDir]), finish);
|
|
19570
21169
|
});
|
|
19571
21170
|
};
|
|
19572
21171
|
|
|
@@ -19647,13 +21246,13 @@ Utils.findLast = function (arr, callback) {
|
|
|
19647
21246
|
return void 0;
|
|
19648
21247
|
};
|
|
19649
21248
|
|
|
19650
|
-
// make
|
|
21249
|
+
// make absolute paths taking prefix as root folder
|
|
19651
21250
|
Utils.sanitize = function (/*string*/ prefix, /*string*/ name) {
|
|
19652
21251
|
prefix = pth.resolve(pth.normalize(prefix));
|
|
19653
21252
|
var parts = name.split("/");
|
|
19654
21253
|
for (var i = 0, l = parts.length; i < l; i++) {
|
|
19655
21254
|
var path = pth.normalize(pth.join(prefix, parts.slice(i, l).join(pth.sep)));
|
|
19656
|
-
if (path.
|
|
21255
|
+
if (path === prefix || path.startsWith(prefix + pth.sep)) {
|
|
19657
21256
|
return path;
|
|
19658
21257
|
}
|
|
19659
21258
|
}
|
|
@@ -19673,10 +21272,16 @@ Utils.toBuffer = function toBuffer(/*buffer, Uint8Array, string*/ input, /* func
|
|
|
19673
21272
|
};
|
|
19674
21273
|
|
|
19675
21274
|
Utils.readBigUInt64LE = function (/*Buffer*/ buffer, /*int*/ index) {
|
|
19676
|
-
|
|
19677
|
-
|
|
21275
|
+
const lo = buffer.readUInt32LE(index);
|
|
21276
|
+
const hi = buffer.readUInt32LE(index + 4);
|
|
21277
|
+
return hi * 0x100000000 + lo;
|
|
21278
|
+
};
|
|
19678
21279
|
|
|
19679
|
-
|
|
21280
|
+
Utils.writeBigUInt64LE = function (/*Buffer*/ buffer, /*Number*/ value, /*int*/ index) {
|
|
21281
|
+
const lo = value >>> 0;
|
|
21282
|
+
const hi = Math.floor(value / 0x100000000) >>> 0;
|
|
21283
|
+
buffer.writeUInt32LE(lo, index);
|
|
21284
|
+
buffer.writeUInt32LE(hi, index + 4);
|
|
19680
21285
|
};
|
|
19681
21286
|
|
|
19682
21287
|
Utils.fromDOS2Date = function (val) {
|
|
@@ -19699,13 +21304,13 @@ Utils.crcTable = crcTable;
|
|
|
19699
21304
|
|
|
19700
21305
|
/***/ }),
|
|
19701
21306
|
|
|
19702
|
-
/***/
|
|
21307
|
+
/***/ 58851:
|
|
19703
21308
|
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
19704
21309
|
|
|
19705
|
-
var Utils = __nccwpck_require__(
|
|
19706
|
-
Headers = __nccwpck_require__(
|
|
21310
|
+
var Utils = __nccwpck_require__(91373),
|
|
21311
|
+
Headers = __nccwpck_require__(77837),
|
|
19707
21312
|
Constants = Utils.Constants,
|
|
19708
|
-
Methods = __nccwpck_require__(
|
|
21313
|
+
Methods = __nccwpck_require__(70493);
|
|
19709
21314
|
|
|
19710
21315
|
module.exports = function (/** object */ options, /*Buffer*/ input) {
|
|
19711
21316
|
var _centralHeader = new Headers.EntryHeader(),
|
|
@@ -19733,48 +21338,23 @@ module.exports = function (/** object */ options, /*Buffer*/ input) {
|
|
|
19733
21338
|
}
|
|
19734
21339
|
|
|
19735
21340
|
function crc32OK(data) {
|
|
19736
|
-
//
|
|
19737
|
-
|
|
19738
|
-
|
|
19739
|
-
|
|
19740
|
-
|
|
19741
|
-
|
|
19742
|
-
|
|
19743
|
-
|
|
19744
|
-
|
|
19745
|
-
|
|
19746
|
-
|
|
19747
|
-
|
|
19748
|
-
|
|
19749
|
-
|
|
19750
|
-
|
|
19751
|
-
// descriptor with signature
|
|
19752
|
-
descriptor.crc = input.readUInt32LE(dataEndOffset + Constants.EXTCRC);
|
|
19753
|
-
descriptor.compressedSize = input.readUInt32LE(dataEndOffset + Constants.EXTSIZ);
|
|
19754
|
-
descriptor.size = input.readUInt32LE(dataEndOffset + Constants.EXTLEN);
|
|
19755
|
-
} else if (input.readUInt16LE(dataEndOffset + 12) === 0x4b50) {
|
|
19756
|
-
// descriptor without signature (we check is new header starting where we expect)
|
|
19757
|
-
descriptor.crc = input.readUInt32LE(dataEndOffset + Constants.EXTCRC - 4);
|
|
19758
|
-
descriptor.compressedSize = input.readUInt32LE(dataEndOffset + Constants.EXTSIZ - 4);
|
|
19759
|
-
descriptor.size = input.readUInt32LE(dataEndOffset + Constants.EXTLEN - 4);
|
|
19760
|
-
} else {
|
|
19761
|
-
throw Utils.Errors.DESCRIPTOR_UNKNOWN();
|
|
19762
|
-
}
|
|
19763
|
-
|
|
19764
|
-
// check data integrity
|
|
19765
|
-
if (descriptor.compressedSize !== _centralHeader.compressedSize || descriptor.size !== _centralHeader.size || descriptor.crc !== _centralHeader.crc) {
|
|
19766
|
-
throw Utils.Errors.DESCRIPTOR_FAULTY();
|
|
19767
|
-
}
|
|
19768
|
-
if (Utils.crc32(data) !== descriptor.crc) {
|
|
19769
|
-
return false;
|
|
19770
|
-
}
|
|
21341
|
+
// When bit 3 (0x08) of the general-purpose flags is set, the crc-32 and
|
|
21342
|
+
// sizes were unknown when the local file header was written, so that
|
|
21343
|
+
// header carries placeholder zeros and the real values are repeated in a
|
|
21344
|
+
// data descriptor after the compressed data. adm-zip always parses the
|
|
21345
|
+
// central directory, whose header holds the authoritative crc-32 and
|
|
21346
|
+
// sizes, so we validate the payload against that value.
|
|
21347
|
+
//
|
|
21348
|
+
// Earlier versions instead located and parsed the trailing descriptor and
|
|
21349
|
+
// threw when it was absent or in an unexpected shape. Many valid archives
|
|
21350
|
+
// set the descriptor flag but write the real crc/sizes into the local and
|
|
21351
|
+
// central headers without emitting a descriptor (or write one we did not
|
|
21352
|
+
// recognise), so that strict handling rejected readable zips
|
|
21353
|
+
// (issues #533, #548, #554). Trusting the central-directory crc keeps the
|
|
21354
|
+
// integrity check while accepting those archives.
|
|
21355
|
+
const expectedCrc = _centralHeader.flags_desc || _centralHeader.localHeader.flags_desc ? _centralHeader.crc : _centralHeader.localHeader.crc;
|
|
19771
21356
|
|
|
19772
|
-
|
|
19773
|
-
// if bit 3 is set and any value in local header "zip64 Extended information" extra field are set 0 (place holder)
|
|
19774
|
-
// then 64-bit descriptor format is used instead of 32-bit
|
|
19775
|
-
// central header - "zip64 Extended information" extra field should store real values and not place holders
|
|
19776
|
-
}
|
|
19777
|
-
return true;
|
|
21357
|
+
return Utils.crc32(data) === expectedCrc;
|
|
19778
21358
|
}
|
|
19779
21359
|
|
|
19780
21360
|
function decompress(/*Boolean*/ async, /*Function*/ callback, /*String, Buffer*/ pass) {
|
|
@@ -19804,10 +21384,16 @@ module.exports = function (/** object */ options, /*Buffer*/ input) {
|
|
|
19804
21384
|
compressedData = Methods.ZipCrypto.decrypt(compressedData, _centralHeader, pass);
|
|
19805
21385
|
}
|
|
19806
21386
|
|
|
19807
|
-
var data
|
|
21387
|
+
var data;
|
|
19808
21388
|
|
|
19809
21389
|
switch (_centralHeader.method) {
|
|
19810
21390
|
case Utils.Constants.STORED:
|
|
21391
|
+
// STORED entries are not compressed, so the uncompressed output is
|
|
21392
|
+
// exactly the bytes present in the archive. Allocate from the real
|
|
21393
|
+
// data length rather than the attacker-declared central-directory
|
|
21394
|
+
// size, otherwise a tiny archive can declare a huge size and force a
|
|
21395
|
+
// multi-gigabyte allocation before any validation (CVE-2026-39244).
|
|
21396
|
+
data = Buffer.alloc(compressedData.length);
|
|
19811
21397
|
compressedData.copy(data);
|
|
19812
21398
|
if (!crc32OK(data)) {
|
|
19813
21399
|
if (async && callback) callback(data, Utils.Errors.BAD_CRC()); //si added error
|
|
@@ -19818,17 +21404,19 @@ module.exports = function (/** object */ options, /*Buffer*/ input) {
|
|
|
19818
21404
|
return data;
|
|
19819
21405
|
}
|
|
19820
21406
|
case Utils.Constants.DEFLATED:
|
|
21407
|
+
// Do not pre-allocate the declared uncompressed size. The inflater
|
|
21408
|
+
// grows its output buffer as zlib emits data and caps the total at
|
|
21409
|
+
// the declared size (maxOutputLength), so a bogus size can no longer
|
|
21410
|
+
// trigger an eager allocation before the data is read (CVE-2026-39244).
|
|
19821
21411
|
var inflater = new Methods.Inflater(compressedData, _centralHeader.size);
|
|
19822
21412
|
if (!async) {
|
|
19823
|
-
|
|
19824
|
-
result.copy(data, 0);
|
|
21413
|
+
data = inflater.inflate();
|
|
19825
21414
|
if (!crc32OK(data)) {
|
|
19826
21415
|
throw Utils.Errors.BAD_CRC(`"${decoder.decode(_entryName)}"`);
|
|
19827
21416
|
}
|
|
19828
21417
|
return data;
|
|
19829
21418
|
} else {
|
|
19830
21419
|
inflater.inflateAsync(function (result) {
|
|
19831
|
-
result.copy(result, 0);
|
|
19832
21420
|
if (callback) {
|
|
19833
21421
|
if (!crc32OK(result)) {
|
|
19834
21422
|
callback(result, Utils.Errors.BAD_CRC()); //si added error
|
|
@@ -19890,7 +21478,7 @@ module.exports = function (/** object */ options, /*Buffer*/ input) {
|
|
|
19890
21478
|
}
|
|
19891
21479
|
|
|
19892
21480
|
function readUInt64LE(buffer, offset) {
|
|
19893
|
-
return (buffer
|
|
21481
|
+
return Utils.readBigUInt64LE(buffer, offset);
|
|
19894
21482
|
}
|
|
19895
21483
|
|
|
19896
21484
|
function parseExtra(data) {
|
|
@@ -19984,10 +21572,12 @@ module.exports = function (/** object */ options, /*Buffer*/ input) {
|
|
|
19984
21572
|
},
|
|
19985
21573
|
|
|
19986
21574
|
get name() {
|
|
19987
|
-
|
|
21575
|
+
const n = decoder.decode(_entryName);
|
|
21576
|
+
// For directories the name is the last path segment; drop the trailing
|
|
21577
|
+
// separator first so "a/b/c/" yields "c" and not "" (issue #466).
|
|
19988
21578
|
return _isDirectory
|
|
19989
21579
|
? n
|
|
19990
|
-
.
|
|
21580
|
+
.replace(/[/\\]$/, "")
|
|
19991
21581
|
.split("/")
|
|
19992
21582
|
.pop()
|
|
19993
21583
|
: n.split("/").pop();
|
|
@@ -20111,16 +21701,19 @@ module.exports = function (/** object */ options, /*Buffer*/ input) {
|
|
|
20111
21701
|
|
|
20112
21702
|
/***/ }),
|
|
20113
21703
|
|
|
20114
|
-
/***/
|
|
21704
|
+
/***/ 46593:
|
|
20115
21705
|
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
20116
21706
|
|
|
20117
|
-
const ZipEntry = __nccwpck_require__(
|
|
20118
|
-
const Headers = __nccwpck_require__(
|
|
20119
|
-
const Utils = __nccwpck_require__(
|
|
21707
|
+
const ZipEntry = __nccwpck_require__(58851);
|
|
21708
|
+
const Headers = __nccwpck_require__(77837);
|
|
21709
|
+
const Utils = __nccwpck_require__(91373);
|
|
20120
21710
|
|
|
20121
21711
|
module.exports = function (/*Buffer|null*/ inBuffer, /** object */ options) {
|
|
20122
21712
|
var entryList = [],
|
|
20123
|
-
|
|
21713
|
+
// prototype-less: entry names come from untrusted input, so keys like
|
|
21714
|
+
// "__proto__" or "constructor" must be plain data, not touch the prototype
|
|
21715
|
+
// chain (which otherwise crashes addFile and hides such entries)
|
|
21716
|
+
entryTable = Object.create(null),
|
|
20124
21717
|
_comment = Buffer.alloc(0),
|
|
20125
21718
|
mainHeader = new Headers.MainHeader(),
|
|
20126
21719
|
loadedEntries = false;
|
|
@@ -20170,7 +21763,7 @@ module.exports = function (/*Buffer|null*/ inBuffer, /** object */ options) {
|
|
|
20170
21763
|
|
|
20171
21764
|
function readEntries() {
|
|
20172
21765
|
loadedEntries = true;
|
|
20173
|
-
entryTable =
|
|
21766
|
+
entryTable = Object.create(null);
|
|
20174
21767
|
if (mainHeader.diskEntries > (inBuffer.length - mainHeader.offset) / Utils.Constants.CENHDR) {
|
|
20175
21768
|
throw Utils.Errors.DISK_ENTRY_TOO_LARGE();
|
|
20176
21769
|
}
|
|
@@ -20247,7 +21840,14 @@ module.exports = function (/*Buffer|null*/ inBuffer, /** object */ options) {
|
|
|
20247
21840
|
|
|
20248
21841
|
function sortEntries() {
|
|
20249
21842
|
if (entryList.length > 1 && !noSort) {
|
|
20250
|
-
|
|
21843
|
+
// Decode + lowercase each name once rather than on every comparison:
|
|
21844
|
+
// the entryName getter re-decodes the underlying buffer on each access,
|
|
21845
|
+
// so the previous inline comparator did O(n log n) redundant decoding.
|
|
21846
|
+
// Ordering is unchanged (same localeCompare on the same keys).
|
|
21847
|
+
entryList = entryList
|
|
21848
|
+
.map((entry) => ({ entry, key: entry.entryName.toLowerCase() }))
|
|
21849
|
+
.sort((a, b) => a.key.localeCompare(b.key))
|
|
21850
|
+
.map((pair) => pair.entry);
|
|
20251
21851
|
}
|
|
20252
21852
|
}
|
|
20253
21853
|
|
|
@@ -20459,7 +22059,7 @@ module.exports = function (/*Buffer|null*/ inBuffer, /** object */ options) {
|
|
|
20459
22059
|
// write main header
|
|
20460
22060
|
const mh = mainHeader.toBinary();
|
|
20461
22061
|
if (_comment) {
|
|
20462
|
-
_comment.copy(mh,
|
|
22062
|
+
_comment.copy(mh, mh.length - _comment.length); // add zip file comment
|
|
20463
22063
|
}
|
|
20464
22064
|
mh.copy(outBuffer, dindex);
|
|
20465
22065
|
|
|
@@ -20537,7 +22137,7 @@ module.exports = function (/*Buffer|null*/ inBuffer, /** object */ options) {
|
|
|
20537
22137
|
|
|
20538
22138
|
const mh = mainHeader.toBinary();
|
|
20539
22139
|
if (_comment) {
|
|
20540
|
-
_comment.copy(mh,
|
|
22140
|
+
_comment.copy(mh, mh.length - _comment.length); // add zip file comment
|
|
20541
22141
|
}
|
|
20542
22142
|
|
|
20543
22143
|
mh.copy(outBuffer, dindex); // write main header
|
|
@@ -129501,7 +131101,7 @@ module.exports = {"version":"3.17.0"};
|
|
|
129501
131101
|
/***/ ((module) => {
|
|
129502
131102
|
|
|
129503
131103
|
"use strict";
|
|
129504
|
-
module.exports = /*#__PURE__*/JSON.parse('{"rE":"0.4.9
|
|
131104
|
+
module.exports = /*#__PURE__*/JSON.parse('{"rE":"0.4.9","h_":"ckb development network for your first try"}');
|
|
129505
131105
|
|
|
129506
131106
|
/***/ })
|
|
129507
131107
|
|