beignet 0.7.2 → 0.7.4

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.
Files changed (38) hide show
  1. package/dist/cli/auth.js +1 -0
  2. package/dist/cli/auth.js.map +1 -1
  3. package/dist/cli/beignet-node.js +50 -3
  4. package/dist/cli/beignet-node.js.map +1 -1
  5. package/dist/cli/cli.js +16 -3
  6. package/dist/cli/cli.js.map +1 -1
  7. package/dist/cli/daemon.js +8 -2
  8. package/dist/cli/daemon.js.map +1 -1
  9. package/dist/cli/openapi.js +44 -1
  10. package/dist/cli/openapi.js.map +1 -1
  11. package/dist/lightning/chain/chain-watcher.js +11 -1
  12. package/dist/lightning/chain/chain-watcher.js.map +1 -1
  13. package/dist/lightning/channel/channel-manager.js +50 -8
  14. package/dist/lightning/channel/channel-manager.js.map +1 -1
  15. package/dist/lightning/channel/channel.js +147 -25
  16. package/dist/lightning/channel/channel.js.map +1 -1
  17. package/dist/lightning/channel/dual-funding.js +1 -1
  18. package/dist/lightning/channel/dual-funding.js.map +1 -1
  19. package/dist/lightning/gossip/pathfinding.js +4 -2
  20. package/dist/lightning/gossip/pathfinding.js.map +1 -1
  21. package/dist/lightning/node/lightning-node.js +227 -23
  22. package/dist/lightning/node/lightning-node.js.map +1 -1
  23. package/dist/lightning/wallet/wallet-funding-provider.js +125 -9
  24. package/dist/lightning/wallet/wallet-funding-provider.js.map +1 -1
  25. package/dist/types/cli/beignet-node.d.ts +7 -2
  26. package/dist/types/cli/types.d.ts +15 -0
  27. package/dist/types/lightning/channel/channel-manager.d.ts +7 -2
  28. package/dist/types/lightning/channel/channel.d.ts +6 -1
  29. package/dist/types/lightning/channel/dual-funding.d.ts +1 -0
  30. package/dist/types/lightning/node/lightning-node.d.ts +24 -2
  31. package/dist/types/lightning/wallet/wallet-funding-provider.d.ts +29 -0
  32. package/dist/types/types/wallet.d.ts +2 -0
  33. package/dist/types/wallet/index.d.ts +2 -1
  34. package/dist/types/wallet.js.map +1 -1
  35. package/dist/wallet/index.js +5 -2
  36. package/dist/wallet/index.js.map +1 -1
  37. package/docs/ROADMAP.md +12 -0
  38. package/package.json +1 -1
@@ -226,6 +226,11 @@ class Channel {
226
226
  channelTypeFlags.setCompulsory(flags_1.Feature.ANCHOR_ZERO_FEE_HTLC);
227
227
  }
228
228
  }
229
+ const zeroConf = this._state.zeroConfEnabled && this._state.trustedPeer;
230
+ if (zeroConf) {
231
+ channelTypeFlags.setCompulsory(flags_1.Feature.SCID_ALIAS);
232
+ channelTypeFlags.setCompulsory(flags_1.Feature.ZERO_CONF);
233
+ }
229
234
  const channelType = channelTypeFlags.toBuffer();
230
235
  this._state.channelType = channelType;
231
236
  const channelReserve = computeChannelReserve(this._state.fundingSatoshis, this._state.localConfig.dustLimitSatoshis);
@@ -247,9 +252,12 @@ class Channel {
247
252
  delayedPaymentBasepoint: this._state.localBasepoints.delayedPaymentBasepoint,
248
253
  htlcBasepoint: this._state.localBasepoints.htlcBasepoint,
249
254
  firstPerCommitmentPoint: firstPoint,
250
- channelFlags: preferTaproot ? 0x00 : 0x01,
255
+ channelFlags: preferTaproot || zeroConf ? 0x00 : 0x01,
251
256
  channelType
252
257
  };
258
+ if (zeroConf) {
259
+ this._state.announceChannel = false;
260
+ }
253
261
  if (preferTaproot) {
254
262
  msg.nextLocalNonce = this._ensureLocalFundingNonce();
255
263
  }
@@ -378,7 +386,20 @@ class Channel {
378
386
  htlcBasepoint: msg.htlcBasepoint,
379
387
  firstPerCommitmentPoint: msg.firstPerCommitmentPoint
380
388
  };
381
- this._state.minimumDepth = msg.minimumDepth;
389
+ if (this._state.channelType &&
390
+ flags_1.FeatureFlags.fromBuffer(this._state.channelType).hasFeature(flags_1.Feature.ZERO_CONF)) {
391
+ if (msg.minimumDepth !== 0) {
392
+ return [
393
+ {
394
+ type: channel_actions_1.ChannelActionType.ERROR,
395
+ message: `zero_conf accept_channel must use minimum_depth 0, got ${msg.minimumDepth}`
396
+ }
397
+ ];
398
+ }
399
+ }
400
+ else {
401
+ this._state.minimumDepth = msg.minimumDepth;
402
+ }
382
403
  this._state.remoteCurrentPerCommitmentPoint = msg.firstPerCommitmentPoint;
383
404
  if (msg.channelType && this._state.channelType) {
384
405
  const localBits = flags_1.FeatureFlags.fromBuffer(this._state.channelType).listSetBits();
@@ -557,14 +578,17 @@ class Channel {
557
578
  }
558
579
  ];
559
580
  }
560
- if (proposedFlags.hasFeature(flags_1.Feature.ZERO_CONF) &&
561
- !(this._state.zeroConfEnabled && this._state.trustedPeer)) {
562
- return [
563
- {
564
- type: channel_actions_1.ChannelActionType.ERROR,
565
- message: 'Proposed zero_conf channel type requires a trusted peer'
566
- }
567
- ];
581
+ if (proposedFlags.hasFeature(flags_1.Feature.ZERO_CONF)) {
582
+ if (!this._state.trustedPeer) {
583
+ return [
584
+ {
585
+ type: channel_actions_1.ChannelActionType.ERROR,
586
+ message: 'Proposed zero_conf channel type requires a trusted peer'
587
+ }
588
+ ];
589
+ }
590
+ this._state.zeroConfEnabled = true;
591
+ this._state.minimumDepth = 0;
568
592
  }
569
593
  this._state.channelType = msg.channelType;
570
594
  }
@@ -677,7 +701,7 @@ class Channel {
677
701
  partialSignatureWithNonce: taproot ? partialSignatureWithNonce : undefined
678
702
  };
679
703
  this._state.state = types_2.ChannelState.AWAITING_FUNDING_CONFIRMED;
680
- return [
704
+ const actions = [
681
705
  { type: channel_actions_1.ChannelActionType.PERSIST_STATE },
682
706
  sendMsg(types_1.MessageType.FUNDING_SIGNED, (0, channel_funding_1.encodeFundingSignedMessage)(signedMsg)),
683
707
  {
@@ -687,6 +711,10 @@ class Channel {
687
711
  minimumDepth: this._state.minimumDepth
688
712
  }
689
713
  ];
714
+ if (this._state.zeroConfEnabled && this._state.trustedPeer) {
715
+ actions.push(...this.fundingConfirmed());
716
+ }
717
+ return actions;
690
718
  }
691
719
  fundingConfirmed() {
692
720
  if (this._state.state !== types_2.ChannelState.AWAITING_FUNDING_CONFIRMED &&
@@ -3642,6 +3670,16 @@ class Channel {
3642
3670
  const ourWalletWitnesses = [];
3643
3671
  const ourWalletInputIndices = [];
3644
3672
  if (this._spliceInInputs) {
3673
+ const p2wshScript = require('bitcoinjs-lib').payments.p2wsh({
3674
+ redeem: { output: oldFunding.witnessScript }
3675
+ }).output;
3676
+ const prevouts = this._collectPrevouts(tx, [...this._spliceInInputs.inputs, ...built.inputs], {
3677
+ index: sharedInputIndex,
3678
+ script: p2wshScript,
3679
+ value: this._state.fundingSatoshis
3680
+ });
3681
+ if (!prevouts)
3682
+ return null;
3645
3683
  for (let i = 0; i < tx.ins.length; i++) {
3646
3684
  if (i === sharedInputIndex)
3647
3685
  continue;
@@ -3651,7 +3689,7 @@ class Channel {
3651
3689
  wi.prevOutputIndex === vout);
3652
3690
  if (!w)
3653
3691
  continue;
3654
- const witness = w.signWitness(tx, i, w.value);
3692
+ const witness = w.signWitness(tx, i, w.value, prevouts);
3655
3693
  tx.setWitness(i, witness);
3656
3694
  ourWalletWitnesses.push(witness);
3657
3695
  ourWalletInputIndices.push(i);
@@ -4341,10 +4379,15 @@ class Channel {
4341
4379
  witnesses: this._spliceTx.ourWalletWitnesses,
4342
4380
  sharedInputSignature: signed.signature
4343
4381
  };
4344
- return [
4382
+ const actions = [
4345
4383
  { type: channel_actions_1.ChannelActionType.PERSIST_STATE },
4346
4384
  sendMsg(types_1.MessageType.TX_SIGNATURES, (0, interactive_tx_1.encodeTxSignaturesMessage)(msg))
4347
4385
  ];
4386
+ if (this._isZeroConfChannelType() &&
4387
+ this._state.spliceInFlight?.receivedTxSignatures) {
4388
+ actions.push(...this.sendSpliceLocked());
4389
+ }
4390
+ return actions;
4348
4391
  }
4349
4392
  completeSplice() {
4350
4393
  const inflight = this._state.spliceInFlight;
@@ -4792,14 +4835,18 @@ class Channel {
4792
4835
  this._state.fundingLocktime = msg.locktime;
4793
4836
  if (msg.channelType) {
4794
4837
  const proposedFlags = flags_1.FeatureFlags.fromBuffer(msg.channelType);
4795
- if (proposedFlags.hasFeature(flags_1.Feature.ZERO_CONF) &&
4796
- !(this._state.zeroConfEnabled && this._state.trustedPeer)) {
4797
- return [
4798
- {
4799
- type: channel_actions_1.ChannelActionType.ERROR,
4800
- message: 'Proposed zero_conf channel type requires a trusted peer'
4801
- }
4802
- ];
4838
+ if (proposedFlags.hasFeature(flags_1.Feature.ZERO_CONF)) {
4839
+ if (!this._state.trustedPeer) {
4840
+ return [
4841
+ {
4842
+ type: channel_actions_1.ChannelActionType.ERROR,
4843
+ message: 'Proposed zero_conf channel type requires a trusted peer'
4844
+ }
4845
+ ];
4846
+ }
4847
+ this._state.zeroConfEnabled = true;
4848
+ this._state.minimumDepth = 0;
4849
+ localParams = { ...localParams, minimumDepth: 0 };
4803
4850
  }
4804
4851
  }
4805
4852
  localParams = {
@@ -4923,6 +4970,16 @@ class Channel {
4923
4970
  }
4924
4971
  ];
4925
4972
  }
4973
+ if (this._state.channelType &&
4974
+ flags_1.FeatureFlags.fromBuffer(this._state.channelType).hasFeature(flags_1.Feature.ZERO_CONF) &&
4975
+ msg.minimumDepth !== 0) {
4976
+ return [
4977
+ {
4978
+ type: channel_actions_1.ChannelActionType.ERROR,
4979
+ message: `zero_conf accept_channel2 must use minimum_depth 0, got ${msg.minimumDepth}`
4980
+ }
4981
+ ];
4982
+ }
4926
4983
  this._state.remoteBasepoints = session.getRemoteBasepoints();
4927
4984
  this._state.remoteCurrentPerCommitmentPoint = msg.firstPerCommitmentPoint;
4928
4985
  this._state.channelId = (0, validation_1.deriveV2ChannelId)(this._state.localBasepoints.revocationBasepoint, this._state.remoteBasepoints.revocationBasepoint);
@@ -5763,6 +5820,9 @@ class Channel {
5763
5820
  const built = this._v2NegotiatedTx();
5764
5821
  if (!built)
5765
5822
  return [];
5823
+ const prevouts = this._collectPrevouts(built.tx, session.getTxBuilder()?.getInputs() ?? []);
5824
+ if (!prevouts)
5825
+ return [];
5766
5826
  const witnesses = [];
5767
5827
  for (let i = 0; i < built.tx.ins.length; i++) {
5768
5828
  const prevTxid = Buffer.from(built.tx.ins[i].hash);
@@ -5771,7 +5831,7 @@ class Channel {
5771
5831
  wi.prevOutputIndex === vout);
5772
5832
  if (!w)
5773
5833
  continue;
5774
- const witness = w.signWitness(built.tx, i, w.value);
5834
+ const witness = w.signWitness(built.tx, i, w.value, prevouts);
5775
5835
  built.tx.setWitness(i, witness);
5776
5836
  witnesses.push(witness);
5777
5837
  }
@@ -5819,7 +5879,7 @@ class Channel {
5819
5879
  txid,
5820
5880
  witnesses
5821
5881
  };
5822
- return [
5882
+ const actions = [
5823
5883
  { type: channel_actions_1.ChannelActionType.PERSIST_STATE },
5824
5884
  sendMsg(types_1.MessageType.TX_SIGNATURES, (0, interactive_tx_1.encodeTxSignaturesMessage)(msg)),
5825
5885
  {
@@ -5829,6 +5889,12 @@ class Channel {
5829
5889
  minimumDepth: this._state.minimumDepth
5830
5890
  }
5831
5891
  ];
5892
+ if (this._state.state === types_2.ChannelState.AWAITING_FUNDING_CONFIRMED &&
5893
+ this._state.zeroConfEnabled &&
5894
+ this._state.trustedPeer) {
5895
+ actions.push(...this.fundingConfirmed());
5896
+ }
5897
+ return actions;
5832
5898
  }
5833
5899
  sendTxSignatures(txid, outputIndex, witnesses) {
5834
5900
  const session = this._state.dualFundingSession;
@@ -5911,7 +5977,8 @@ class Channel {
5911
5977
  fundingOutputIndex: this._spliceTx.newFundingOutputIndex,
5912
5978
  minimumDepth: this._state.minimumDepth
5913
5979
  });
5914
- if (this._state.spliceInFlight?.confirmed) {
5980
+ if (this._isZeroConfChannelType() ||
5981
+ this._state.spliceInFlight?.confirmed) {
5915
5982
  actions.push(...this.sendSpliceLocked());
5916
5983
  }
5917
5984
  return actions;
@@ -5957,9 +6024,46 @@ class Channel {
5957
6024
  });
5958
6025
  }
5959
6026
  }
6027
+ if (this._state.zeroConfEnabled && this._state.trustedPeer) {
6028
+ actions.push(...this.fundingConfirmed());
6029
+ }
5960
6030
  }
5961
6031
  return actions;
5962
6032
  }
6033
+ _collectPrevouts(tx, inputs, sharedOverride) {
6034
+ const bitcoin = require('bitcoinjs-lib');
6035
+ const scripts = [];
6036
+ const values = [];
6037
+ for (let i = 0; i < tx.ins.length; i++) {
6038
+ if (sharedOverride && sharedOverride.index === i) {
6039
+ scripts.push(sharedOverride.script);
6040
+ values.push(sharedOverride.value);
6041
+ continue;
6042
+ }
6043
+ const txid = Buffer.from(tx.ins[i].hash);
6044
+ const vout = tx.ins[i].index;
6045
+ const source = inputs.find((inp) => {
6046
+ if (!inp.prevTx || inp.prevTx.length < 32)
6047
+ return false;
6048
+ return (extractTxidFromPrevTx(inp.prevTx).equals(txid) &&
6049
+ (inp.prevTxVout ?? inp.prevOutputIndex) === vout);
6050
+ });
6051
+ if (!source)
6052
+ return null;
6053
+ try {
6054
+ const prev = bitcoin.Transaction.fromBuffer(source.prevTx);
6055
+ const out = prev.outs[vout];
6056
+ if (!out)
6057
+ return null;
6058
+ scripts.push(Buffer.from(out.script));
6059
+ values.push(BigInt(out.value));
6060
+ }
6061
+ catch {
6062
+ return null;
6063
+ }
6064
+ }
6065
+ return { scripts, values };
6066
+ }
5963
6067
  _assembleV2FundingTx() {
5964
6068
  const session = this._state.dualFundingSession;
5965
6069
  const c = this._dualFundingContribution;
@@ -5974,6 +6078,9 @@ class Channel {
5974
6078
  const sorted = [...builder.getInputs()].sort((a, b) => a.serialId < b.serialId ? -1 : 1);
5975
6079
  if (sorted.length !== built.tx.ins.length)
5976
6080
  return null;
6081
+ const prevouts = this._collectPrevouts(built.tx, sorted);
6082
+ if (!prevouts)
6083
+ return null;
5977
6084
  const remote = session.getRemoteWitnesses() ?? [];
5978
6085
  let r = 0;
5979
6086
  for (let i = 0; i < built.tx.ins.length; i++) {
@@ -5985,7 +6092,7 @@ class Channel {
5985
6092
  wi.prevOutputIndex === vout);
5986
6093
  if (!w)
5987
6094
  return null;
5988
- built.tx.setWitness(i, w.signWitness(built.tx, i, w.value));
6095
+ built.tx.setWitness(i, w.signWitness(built.tx, i, w.value, prevouts));
5989
6096
  }
5990
6097
  else {
5991
6098
  if (r >= remote.length)
@@ -5995,7 +6102,19 @@ class Channel {
5995
6102
  }
5996
6103
  return built.tx.toBuffer();
5997
6104
  }
6105
+ _isZeroConfChannelType() {
6106
+ return (this._state.channelType !== null &&
6107
+ flags_1.FeatureFlags.fromBuffer(this._state.channelType).hasFeature(flags_1.Feature.ZERO_CONF));
6108
+ }
5998
6109
  initiateTxRbf(newFeeratePerkw, newLocktime) {
6110
+ if (this._isZeroConfChannelType()) {
6111
+ return [
6112
+ {
6113
+ type: channel_actions_1.ChannelActionType.ERROR,
6114
+ message: 'tx_init_rbf is forbidden on an option_zeroconf channel'
6115
+ }
6116
+ ];
6117
+ }
5999
6118
  const session = this._state.dualFundingSession;
6000
6119
  if (!session) {
6001
6120
  return [
@@ -6020,6 +6139,9 @@ class Channel {
6020
6139
  return [sendMsg(types_1.MessageType.TX_INIT_RBF, (0, interactive_tx_1.encodeTxInitRbfMessage)(msg))];
6021
6140
  }
6022
6141
  handleTxInitRbf(msg) {
6142
+ if (this._isZeroConfChannelType()) {
6143
+ return this._failChannelWithWireError('tx_init_rbf is forbidden on an option_zeroconf channel');
6144
+ }
6023
6145
  if (this._spliceSession && !this._spliceSession.isComplete()) {
6024
6146
  return [
6025
6147
  sendMsg(types_1.MessageType.TX_ABORT, (0, interactive_tx_1.encodeTxAbortMessage)({