beignet 0.27.0 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -722,6 +722,7 @@ class BeignetNode extends events_1.EventEmitter {
722
722
  this.rapidGossipSync = true;
723
723
  this._initialGossipPrime = null;
724
724
  this._releaseBootRgs = null;
725
+ this._rapidGossipSync = null;
725
726
  this._deferredGossipSyncs = new Set();
726
727
  this.electrumServerCount = 1;
727
728
  this._failoverInProgress = false;
@@ -916,7 +917,7 @@ class BeignetNode extends events_1.EventEmitter {
916
917
  }
917
918
  let encryptionKey;
918
919
  if (opts.storageEncryption ?? true) {
919
- encryptionKey = (0, encryption_1.deriveStorageKey)(bip39.mnemonicToSeedSync(this.mnemonic));
920
+ encryptionKey = (0, encryption_1.deriveStorageKey)(this.walletSeed());
920
921
  }
921
922
  this._storageEncryptionKey = encryptionKey;
922
923
  this.finishStagedCapsuleRestore(dbPath);
@@ -977,6 +978,7 @@ class BeignetNode extends events_1.EventEmitter {
977
978
  };
978
979
  const walletResult = await wallet_1.Wallet.create({
979
980
  mnemonic: this.mnemonic,
981
+ seed: this.walletSeed(),
980
982
  network: beignetNetwork,
981
983
  disableRefreshOnCreate: true,
982
984
  ...(opts.addressType
@@ -1094,6 +1096,7 @@ class BeignetNode extends events_1.EventEmitter {
1094
1096
  this._nodeStorageView = (0, node_storage_view_1.nodeStorageView)(this.storage);
1095
1097
  this.node = lightning_node_1.LightningNode.fromMnemonic(this.mnemonic, {
1096
1098
  coinType,
1099
+ seed: this.walletSeed(),
1097
1100
  network: lnNetwork,
1098
1101
  storage: this._nodeStorageView,
1099
1102
  newChannelsRefused: () => this.newChannelRefusal(),
@@ -1783,6 +1786,10 @@ class BeignetNode extends events_1.EventEmitter {
1783
1786
  }
1784
1787
  if (this.rapidGossipSync && this.networkName === 'mainnet') {
1785
1788
  const rgs = this.syncRapidGossip().catch((err) => {
1789
+ if (err instanceof rapid_sync_1.RapidGossipCancelledError && this.destroyed) {
1790
+ this.log('debug', 'Rapid gossip sync cancelled by shutdown', {});
1791
+ return;
1792
+ }
1786
1793
  this.log('warn', 'Rapid gossip sync failed', {
1787
1794
  error: err instanceof Error ? err.message : String(err)
1788
1795
  });
@@ -3092,10 +3099,19 @@ class BeignetNode extends events_1.EventEmitter {
3092
3099
  }
3093
3100
  nodeSecret() {
3094
3101
  if (!this._nodeSecret) {
3095
- this._nodeSecret = (0, wallet_keys_1.deriveLightningKeysFromMnemonic)(this.mnemonic, undefined, this.toCoinType(this.networkName)).nodePrivateKey;
3102
+ if (!bip39.validateMnemonic(this.mnemonic)) {
3103
+ throw new Error('Invalid BIP39 mnemonic');
3104
+ }
3105
+ this._nodeSecret = (0, wallet_keys_1.deriveLightningKeysFromSeed)(this.walletSeed(), this.toCoinType(this.networkName)).nodePrivateKey;
3096
3106
  }
3097
3107
  return this._nodeSecret;
3098
3108
  }
3109
+ walletSeed() {
3110
+ if (!this._walletSeed) {
3111
+ this._walletSeed = bip39.mnemonicToSeedSync(this.mnemonic);
3112
+ }
3113
+ return Buffer.from(this._walletSeed);
3114
+ }
3099
3115
  async restoreFromGuardians() {
3100
3116
  if (this._restoreInFlight) {
3101
3117
  throw new errors_1.BeignetError('RESTORE_IN_PROGRESS', 'A guardian restore is already running; watch ' +
@@ -4192,24 +4208,58 @@ class BeignetNode extends events_1.EventEmitter {
4192
4208
  this._lastGraphSyncAt = Date.now();
4193
4209
  return synced;
4194
4210
  }
4195
- async syncRapidGossip() {
4211
+ syncRapidGossip() {
4212
+ if (this._rapidGossipSync)
4213
+ return this._rapidGossipSync;
4214
+ const run = this.runRapidGossipSync();
4215
+ this._rapidGossipSync = run;
4216
+ const clear = () => {
4217
+ if (this._rapidGossipSync === run)
4218
+ this._rapidGossipSync = null;
4219
+ };
4220
+ void run.then(clear, clear);
4221
+ return run;
4222
+ }
4223
+ async runRapidGossipSync() {
4196
4224
  if (this.networkName !== 'mainnet') {
4197
4225
  this.log('warn', 'Rapid gossip sync is only available on mainnet', {});
4198
4226
  return null;
4199
4227
  }
4200
4228
  const url = this.rapidGossipSyncUrl ?? rapid_sync_1.DEFAULT_RGS_URL;
4201
4229
  this.log('info', 'Rapid gossip sync: downloading snapshot', { url });
4230
+ const downloadStart = Date.now();
4202
4231
  const data = await (0, rapid_sync_1.fetchRapidGossipSnapshot)(url);
4203
- const result = this.node.loadRapidGossipSnapshot(data);
4232
+ const downloadMs = Date.now() - downloadStart;
4233
+ if (this.destroyed)
4234
+ throw new rapid_sync_1.RapidGossipCancelledError();
4235
+ let slices = 0;
4236
+ let busyMs = 0;
4237
+ const applyStart = Date.now();
4238
+ const result = await this.node.loadRapidGossipSnapshotAsync(data, {
4239
+ cancelled: () => this.destroyed,
4240
+ onSlice: (ms) => {
4241
+ slices++;
4242
+ busyMs += ms;
4243
+ }
4244
+ });
4245
+ const applyMs = Date.now() - applyStart;
4204
4246
  this._lastGraphSyncAt = Date.now();
4205
4247
  this.log('info', 'Rapid gossip sync complete', {
4206
4248
  channelsAdded: result.channelsAdded,
4207
4249
  updatesApplied: result.updatesApplied,
4208
- nodes: result.nodeCount
4250
+ nodes: result.nodeCount,
4251
+ downloadMs,
4252
+ applyMs,
4253
+ busyMs,
4254
+ slices
4209
4255
  });
4210
4256
  this.emit('gossip:synced', {
4211
4257
  channelsAdded: result.channelsAdded,
4212
- updatesApplied: result.updatesApplied
4258
+ updatesApplied: result.updatesApplied,
4259
+ downloadMs,
4260
+ applyMs,
4261
+ busyMs,
4262
+ slices
4213
4263
  });
4214
4264
  return {
4215
4265
  channelsAdded: result.channelsAdded,
@@ -8199,7 +8249,7 @@ class BeignetNode extends events_1.EventEmitter {
8199
8249
  }
8200
8250
  async backup(destPath) {
8201
8251
  await this.storage.backup(destPath);
8202
- await (0, backup_mac_1.writeBackupMac)((0, backup_mac_1.deriveBackupMacKey)(bip39.mnemonicToSeedSync(this.mnemonic)), destPath);
8252
+ await (0, backup_mac_1.writeBackupMac)((0, backup_mac_1.deriveBackupMacKey)(this.walletSeed()), destPath);
8203
8253
  }
8204
8254
  storageFiles() {
8205
8255
  const dbPath = fs.realpathSync.native(path.join(this.dataDir, `${this.networkName}.db`));
@@ -8250,14 +8300,14 @@ class BeignetNode extends events_1.EventEmitter {
8250
8300
  createdAt: Date.now(),
8251
8301
  channels: data.channels
8252
8302
  };
8253
- const seed = bip39.mnemonicToSeedSync(this.mnemonic);
8303
+ const seed = this.walletSeed();
8254
8304
  const encoded = (0, scb_1.encodeScb)(backup, seed);
8255
8305
  const scbPath = path.join(this.dataDir, 'channels.scb');
8256
8306
  (0, fs_utils_1.writeFileAtomic)(scbPath, encoded);
8257
8307
  return { encoded, channelCount: data.channels.length, path: scbPath };
8258
8308
  }
8259
8309
  async restoreFromScb(encoded) {
8260
- const seed = bip39.mnemonicToSeedSync(this.mnemonic);
8310
+ const seed = this.walletSeed();
8261
8311
  const backup = (0, scb_1.decodeScb)(encoded.trim(), seed);
8262
8312
  const expectedNetwork = this.toLnNetwork(this.networkName);
8263
8313
  if (backup.network !== expectedNetwork) {
@@ -8378,14 +8428,14 @@ class BeignetNode extends events_1.EventEmitter {
8378
8428
  });
8379
8429
  }
8380
8430
  }
8381
- const seed = bip39.mnemonicToSeedSync(this.mnemonic);
8431
+ const seed = this.walletSeed();
8382
8432
  this.offerRetrievedScb((0, scb_1.encodeScb)(embedded, seed), embedded, peerPubkey, 'capsule');
8383
8433
  return;
8384
8434
  }
8385
8435
  let backup;
8386
8436
  const encoded = blob.toString('utf8');
8387
8437
  try {
8388
- const seed = bip39.mnemonicToSeedSync(this.mnemonic);
8438
+ const seed = this.walletSeed();
8389
8439
  backup = (0, scb_1.decodeScb)(encoded, seed);
8390
8440
  }
8391
8441
  catch {