@btc-vision/transaction 1.7.6 → 1.7.10

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 (183) hide show
  1. package/browser/_version.d.ts +1 -0
  2. package/browser/chain/ChainData.d.ts +4 -0
  3. package/browser/{src/deterministic → deterministic}/DeterministicMap.d.ts +3 -3
  4. package/browser/deterministic/FastMap.d.ts +24 -0
  5. package/browser/{src/epoch → epoch}/interfaces/IChallengeSolution.d.ts +4 -4
  6. package/browser/{src/generators → generators}/Features.d.ts +6 -1
  7. package/browser/{src/generators → generators}/Generator.d.ts +1 -0
  8. package/browser/generators/MLDSAData.d.ts +15 -0
  9. package/browser/index.js +1 -1
  10. package/browser/{src/keypair → keypair}/Address.d.ts +9 -3
  11. package/browser/{src/keypair → keypair}/MessageSigner.d.ts +9 -0
  12. package/browser/{src/opnet.d.ts → opnet.d.ts} +2 -1
  13. package/browser/{src/transaction → transaction}/browser/Web3Provider.d.ts +15 -4
  14. package/browser/transaction/browser/types/OPWallet.d.ts +6 -0
  15. package/browser/{src/transaction → transaction}/builders/CustomScriptTransaction.d.ts +1 -0
  16. package/browser/{src/transaction → transaction}/builders/DeploymentTransaction.d.ts +1 -0
  17. package/browser/{src/transaction → transaction}/builders/TransactionBuilder.d.ts +4 -0
  18. package/browser/{src/transaction → transaction}/interfaces/ITransactionParameters.d.ts +3 -0
  19. package/browser/{src/transaction → transaction}/shared/TweakedTransaction.d.ts +6 -0
  20. package/browser/{src/utxo → utxo}/OPNetLimitedProvider.d.ts +1 -0
  21. package/build/_version.d.ts +1 -1
  22. package/build/_version.js +1 -1
  23. package/build/chain/ChainData.d.ts +4 -0
  24. package/build/chain/ChainData.js +20 -0
  25. package/build/deterministic/AddressMap.js +2 -2
  26. package/build/deterministic/DeterministicMap.d.ts +3 -3
  27. package/build/deterministic/DeterministicMap.js +2 -2
  28. package/build/deterministic/FastMap.d.ts +24 -0
  29. package/build/deterministic/{Map.js → FastMap.js} +22 -28
  30. package/build/epoch/ChallengeSolution.js +4 -4
  31. package/build/epoch/interfaces/IChallengeSolution.d.ts +4 -4
  32. package/build/generators/Features.d.ts +6 -1
  33. package/build/generators/Features.js +1 -0
  34. package/build/generators/Generator.d.ts +1 -0
  35. package/build/generators/Generator.js +24 -2
  36. package/build/generators/MLDSAData.d.ts +15 -0
  37. package/build/generators/MLDSAData.js +19 -0
  38. package/build/generators/builders/CalldataGenerator.js +1 -1
  39. package/build/generators/builders/DeploymentGenerator.js +1 -1
  40. package/build/generators/builders/P2WDAGenerator.js +1 -1
  41. package/build/keypair/Address.d.ts +9 -3
  42. package/build/keypair/Address.js +63 -38
  43. package/build/keypair/MessageSigner.d.ts +9 -0
  44. package/build/keypair/MessageSigner.js +101 -3
  45. package/build/opnet.d.ts +2 -1
  46. package/build/opnet.js +2 -1
  47. package/build/transaction/TransactionFactory.js +3 -0
  48. package/build/transaction/browser/Web3Provider.d.ts +15 -4
  49. package/build/transaction/browser/types/OPWallet.d.ts +2 -10
  50. package/build/transaction/browser/types/OPWallet.js +4 -2
  51. package/build/transaction/builders/CustomScriptTransaction.d.ts +1 -0
  52. package/build/transaction/builders/CustomScriptTransaction.js +3 -0
  53. package/build/transaction/builders/DeploymentTransaction.d.ts +1 -0
  54. package/build/transaction/builders/DeploymentTransaction.js +26 -1
  55. package/build/transaction/builders/InteractionTransaction.js +14 -1
  56. package/build/transaction/builders/InteractionTransactionP2WDA.js +14 -1
  57. package/build/transaction/builders/TransactionBuilder.d.ts +4 -0
  58. package/build/transaction/builders/TransactionBuilder.js +77 -0
  59. package/build/transaction/interfaces/ITransactionParameters.d.ts +3 -0
  60. package/build/transaction/shared/P2TR_MS.js +1 -0
  61. package/build/transaction/shared/TweakedTransaction.d.ts +6 -0
  62. package/build/transaction/shared/TweakedTransaction.js +19 -0
  63. package/build/utxo/OPNetLimitedProvider.d.ts +1 -0
  64. package/build/utxo/OPNetLimitedProvider.js +11 -1
  65. package/eslint.config.js +2 -1
  66. package/package.json +1 -1
  67. package/src/_version.ts +1 -1
  68. package/src/chain/ChainData.ts +32 -0
  69. package/src/deterministic/AddressMap.ts +3 -3
  70. package/src/deterministic/DeterministicMap.ts +9 -6
  71. package/src/deterministic/{Map.ts → FastMap.ts} +46 -33
  72. package/src/epoch/ChallengeSolution.ts +4 -4
  73. package/src/epoch/interfaces/IChallengeSolution.ts +4 -4
  74. package/src/generators/Features.ts +8 -2
  75. package/src/generators/Generator.ts +35 -2
  76. package/src/generators/MLDSAData.ts +30 -0
  77. package/src/generators/builders/CalldataGenerator.ts +1 -1
  78. package/src/generators/builders/DeploymentGenerator.ts +2 -1
  79. package/src/generators/builders/LegacyCalldataGenerator.ts +1 -0
  80. package/src/generators/builders/P2WDAGenerator.ts +5 -1
  81. package/src/keypair/Address.ts +78 -38
  82. package/src/keypair/MessageSigner.ts +214 -15
  83. package/src/opnet.ts +3 -1
  84. package/src/transaction/TransactionFactory.ts +3 -0
  85. package/src/transaction/browser/Web3Provider.ts +64 -4
  86. package/src/transaction/browser/types/OPWallet.ts +6 -53
  87. package/src/transaction/builders/CustomScriptTransaction.ts +4 -0
  88. package/src/transaction/builders/DeploymentTransaction.ts +36 -8
  89. package/src/transaction/builders/InteractionTransaction.ts +17 -7
  90. package/src/transaction/builders/InteractionTransactionP2WDA.ts +17 -7
  91. package/src/transaction/builders/TransactionBuilder.ts +107 -0
  92. package/src/transaction/interfaces/ITransactionParameters.ts +12 -0
  93. package/src/transaction/shared/P2TR_MS.ts +1 -0
  94. package/src/transaction/shared/TweakedTransaction.ts +35 -0
  95. package/src/utxo/OPNetLimitedProvider.ts +19 -2
  96. package/test/address.test.ts +18 -20
  97. package/test/addressmap.test.ts +783 -0
  98. package/test/addressverificator-mldsa.test.ts +40 -16
  99. package/test/fastmap-setall.test.ts +143 -0
  100. package/test/fastmap.test.ts +917 -0
  101. package/test/messagesigner-mldsa.test.ts +50 -50
  102. package/test/messagesigner-schnorr.test.ts +40 -40
  103. package/test/old/FastBigIntMap.ts +132 -0
  104. package/test/oldfastmap.test.ts +917 -0
  105. package/tsconfig.webpack.json +2 -6
  106. package/webpack.config.js +1 -1
  107. package/browser/src/_version.d.ts +0 -1
  108. package/browser/src/deterministic/Map.d.ts +0 -19
  109. package/browser/src/transaction/browser/types/OPWallet.d.ts +0 -14
  110. package/browser/test/address.test.d.ts +0 -1
  111. package/browser/test/addressverificator-mldsa.test.d.ts +0 -1
  112. package/browser/test/derivePath.test.d.ts +0 -1
  113. package/browser/test/messagesigner-mldsa.test.d.ts +0 -1
  114. package/browser/test/messagesigner-schnorr.test.d.ts +0 -1
  115. package/browser/test/network-awareness.test.d.ts +0 -1
  116. package/build/deterministic/Map.d.ts +0 -19
  117. /package/browser/{src/abi → abi}/ABICoder.d.ts +0 -0
  118. /package/browser/{src/buffer → buffer}/BinaryReader.d.ts +0 -0
  119. /package/browser/{src/buffer → buffer}/BinaryWriter.d.ts +0 -0
  120. /package/browser/{src/bytecode → bytecode}/Compressor.d.ts +0 -0
  121. /package/browser/{src/consensus → consensus}/Consensus.d.ts +0 -0
  122. /package/browser/{src/consensus → consensus}/ConsensusConfig.d.ts +0 -0
  123. /package/browser/{src/consensus → consensus}/metadata/RoswellConsensus.d.ts +0 -0
  124. /package/browser/{src/crypto → crypto}/crypto-browser.d.ts +0 -0
  125. /package/browser/{src/crypto → crypto}/crypto.d.ts +0 -0
  126. /package/browser/{src/deterministic → deterministic}/AddressMap.d.ts +0 -0
  127. /package/browser/{src/deterministic → deterministic}/AddressSet.d.ts +0 -0
  128. /package/browser/{src/deterministic → deterministic}/CustomMap.d.ts +0 -0
  129. /package/browser/{src/deterministic → deterministic}/DeterministicSet.d.ts +0 -0
  130. /package/browser/{src/epoch → epoch}/ChallengeSolution.d.ts +0 -0
  131. /package/browser/{src/epoch → epoch}/validator/EpochValidator.d.ts +0 -0
  132. /package/browser/{src/event → event}/NetEvent.d.ts +0 -0
  133. /package/browser/{src/generators → generators}/AddressGenerator.d.ts +0 -0
  134. /package/browser/{src/generators → generators}/builders/CalldataGenerator.d.ts +0 -0
  135. /package/browser/{src/generators → generators}/builders/CustomGenerator.d.ts +0 -0
  136. /package/browser/{src/generators → generators}/builders/DeploymentGenerator.d.ts +0 -0
  137. /package/browser/{src/generators → generators}/builders/LegacyCalldataGenerator.d.ts +0 -0
  138. /package/browser/{src/generators → generators}/builders/MultiSignGenerator.d.ts +0 -0
  139. /package/browser/{src/generators → generators}/builders/P2WDAGenerator.d.ts +0 -0
  140. /package/browser/{src/index.d.ts → index.d.ts} +0 -0
  141. /package/browser/{src/keypair → keypair}/AddressVerificator.d.ts +0 -0
  142. /package/browser/{src/keypair → keypair}/EcKeyPair.d.ts +0 -0
  143. /package/browser/{src/keypair → keypair}/Secp256k1PointDeriver.d.ts +0 -0
  144. /package/browser/{src/keypair → keypair}/Wallet.d.ts +0 -0
  145. /package/browser/{src/keypair → keypair}/interfaces/IWallet.d.ts +0 -0
  146. /package/browser/{src/metadata → metadata}/ContractBaseMetadata.d.ts +0 -0
  147. /package/browser/{src/metadata → metadata}/tokens.d.ts +0 -0
  148. /package/browser/{src/mnemonic → mnemonic}/BIPStandard.d.ts +0 -0
  149. /package/browser/{src/mnemonic → mnemonic}/Mnemonic.d.ts +0 -0
  150. /package/browser/{src/mnemonic → mnemonic}/MnemonicStrength.d.ts +0 -0
  151. /package/browser/{src/network → network}/ChainId.d.ts +0 -0
  152. /package/browser/{src/p2wda → p2wda}/P2WDADetector.d.ts +0 -0
  153. /package/browser/{src/signer → signer}/SignerUtils.d.ts +0 -0
  154. /package/browser/{src/signer → signer}/TweakedSigner.d.ts +0 -0
  155. /package/browser/{src/transaction → transaction}/ContractAddress.d.ts +0 -0
  156. /package/browser/{src/transaction → transaction}/TransactionFactory.d.ts +0 -0
  157. /package/browser/{src/transaction → transaction}/browser/BrowserSignerBase.d.ts +0 -0
  158. /package/browser/{src/transaction → transaction}/browser/extensions/UnisatSigner.d.ts +0 -0
  159. /package/browser/{src/transaction → transaction}/browser/extensions/XverseSigner.d.ts +0 -0
  160. /package/browser/{src/transaction → transaction}/browser/types/Unisat.d.ts +0 -0
  161. /package/browser/{src/transaction → transaction}/browser/types/Xverse.d.ts +0 -0
  162. /package/browser/{src/transaction → transaction}/builders/CancelTransaction.d.ts +0 -0
  163. /package/browser/{src/transaction → transaction}/builders/ChallengeSolutionTransaction.d.ts +0 -0
  164. /package/browser/{src/transaction → transaction}/builders/FundingTransaction.d.ts +0 -0
  165. /package/browser/{src/transaction → transaction}/builders/InteractionTransaction.d.ts +0 -0
  166. /package/browser/{src/transaction → transaction}/builders/InteractionTransactionP2WDA.d.ts +0 -0
  167. /package/browser/{src/transaction → transaction}/builders/MultiSignTransaction.d.ts +0 -0
  168. /package/browser/{src/transaction → transaction}/builders/SharedInteractionTransaction.d.ts +0 -0
  169. /package/browser/{src/transaction → transaction}/enums/TransactionType.d.ts +0 -0
  170. /package/browser/{src/transaction → transaction}/interfaces/Tap.d.ts +0 -0
  171. /package/browser/{src/transaction → transaction}/mineable/IP2WSHAddress.d.ts +0 -0
  172. /package/browser/{src/transaction → transaction}/mineable/TimelockGenerator.d.ts +0 -0
  173. /package/browser/{src/transaction → transaction}/processor/PsbtTransaction.d.ts +0 -0
  174. /package/browser/{src/transaction → transaction}/psbt/PSBTTypes.d.ts +0 -0
  175. /package/browser/{src/transaction → transaction}/shared/P2TR_MS.d.ts +0 -0
  176. /package/browser/{src/utils → utils}/BitcoinUtils.d.ts +0 -0
  177. /package/browser/{src/utils → utils}/BufferHelper.d.ts +0 -0
  178. /package/browser/{src/utils → utils}/StringToBuffer.d.ts +0 -0
  179. /package/browser/{src/utils → utils}/lengths.d.ts +0 -0
  180. /package/browser/{src/utils → utils}/types.d.ts +0 -0
  181. /package/browser/{src/utxo → utxo}/interfaces/BroadcastResponse.d.ts +0 -0
  182. /package/browser/{src/utxo → utxo}/interfaces/IUTXO.d.ts +0 -0
  183. /package/browser/{src/verification → verification}/TapscriptVerificator.d.ts +0 -0
@@ -13,7 +13,20 @@ export class InteractionTransaction extends SharedInteractionTransaction {
13
13
  if (this.contractSecret.length !== 32) {
14
14
  throw new Error('Invalid contract secret length. Expected 32 bytes.');
15
15
  }
16
- this.compiledTargetScript = this.calldataGenerator.compile(this.calldata, this.contractSecret, this.challenge, this.priorityFee, this.generateFeatures(parameters));
16
+ if (parameters.compiledTargetScript) {
17
+ if (Buffer.isBuffer(parameters.compiledTargetScript)) {
18
+ this.compiledTargetScript = parameters.compiledTargetScript;
19
+ }
20
+ else if (typeof parameters.compiledTargetScript === 'string') {
21
+ this.compiledTargetScript = Buffer.from(parameters.compiledTargetScript, 'hex');
22
+ }
23
+ else {
24
+ throw new Error('Invalid compiled target script format.');
25
+ }
26
+ }
27
+ else {
28
+ this.compiledTargetScript = this.calldataGenerator.compile(this.calldata, this.contractSecret, this.challenge, this.priorityFee, this.generateFeatures(parameters));
29
+ }
17
30
  this.scriptTree = this.getScriptTree();
18
31
  this.internalInit();
19
32
  }
@@ -41,7 +41,20 @@ export class InteractionTransactionP2WDA extends TransactionBuilder {
41
41
  }
42
42
  this.epochChallenge = TimeLockGenerator.generateTimeLockAddress(this.challenge.publicKey.originalPublicKeyBuffer(), this.network);
43
43
  this.validateP2WDAInputs();
44
- this.compiledOperationData = this.p2wdaGenerator.compile(this.calldata, this.contractSecret, this.challenge, this.priorityFee, this.generateFeatures(parameters));
44
+ if (parameters.compiledTargetScript) {
45
+ if (Buffer.isBuffer(parameters.compiledTargetScript)) {
46
+ this.compiledOperationData = parameters.compiledTargetScript;
47
+ }
48
+ else if (typeof parameters.compiledTargetScript === 'string') {
49
+ this.compiledOperationData = Buffer.from(parameters.compiledTargetScript, 'hex');
50
+ }
51
+ else {
52
+ throw new Error('Invalid compiled target script format.');
53
+ }
54
+ }
55
+ else {
56
+ this.compiledOperationData = this.p2wdaGenerator.compile(this.calldata, this.contractSecret, this.challenge, this.priorityFee, this.generateFeatures(parameters));
57
+ }
45
58
  this.validateOperationDataSize();
46
59
  this.internalInit();
47
60
  }
@@ -7,6 +7,7 @@ import { ECPairInterface } from 'ecpair';
7
7
  import { TweakedTransaction } from '../shared/TweakedTransaction.js';
8
8
  import { UnisatSigner } from '../browser/extensions/UnisatSigner.js';
9
9
  import { IP2WSHAddress } from '../mineable/IP2WSHAddress.js';
10
+ import { Feature, Features } from '../../generators/Features.js';
10
11
  export declare const MINIMUM_AMOUNT_REWARD: bigint;
11
12
  export declare const MINIMUM_AMOUNT_CA: bigint;
12
13
  export declare const ANCHOR_SCRIPT: Buffer<ArrayBuffer>;
@@ -64,6 +65,9 @@ export declare abstract class TransactionBuilder<T extends TransactionType> exte
64
65
  protected addRefundOutput(amountSpent: bigint, expectRefund?: boolean): Promise<void>;
65
66
  protected defineLockScript(): Buffer;
66
67
  protected addValueToToOutput(value: number | bigint): void;
68
+ protected generateLegacySignature(): Buffer;
69
+ protected generateMLDSASignature(): Buffer;
70
+ protected generateMLDSALinkRequest(parameters: ITransactionParameters, features: Feature<Features>[]): void;
67
71
  protected getTransactionOPNetFee(): bigint;
68
72
  protected calculateTotalUTXOAmount(): bigint;
69
73
  protected calculateTotalVOutAmount(): bigint;
@@ -4,6 +4,12 @@ import { EcKeyPair } from '../../keypair/EcKeyPair.js';
4
4
  import { AddressVerificator } from '../../keypair/AddressVerificator.js';
5
5
  import { TweakedTransaction } from '../shared/TweakedTransaction.js';
6
6
  import { P2WDADetector } from '../../p2wda/P2WDADetector.js';
7
+ import { Features } from '../../generators/Features.js';
8
+ import { BITCOIN_PROTOCOL_ID, getChainId } from '../../chain/ChainData.js';
9
+ import { BinaryWriter } from '../../buffer/BinaryWriter.js';
10
+ import { MLDSASecurityLevel } from '@btc-vision/bip32';
11
+ import { MessageSigner } from '../../keypair/MessageSigner.js';
12
+ import { getLevelFromPublicKeyLength } from '../../generators/MLDSAData.js';
7
13
  initEccLib(ecc);
8
14
  export const MINIMUM_AMOUNT_REWARD = 330n;
9
15
  export const MINIMUM_AMOUNT_CA = 297n;
@@ -112,6 +118,7 @@ export class TransactionBuilder extends TweakedTransaction {
112
118
  amount: this.estimatedFees,
113
119
  optionalOutputs: this.optionalOutputs,
114
120
  optionalInputs: this.optionalInputs,
121
+ mldsaSigner: null,
115
122
  };
116
123
  }
117
124
  setDestinationAddress(address) {
@@ -487,6 +494,76 @@ export class TransactionBuilder extends TweakedTransaction {
487
494
  }
488
495
  throw new Error('Output not found');
489
496
  }
497
+ generateLegacySignature() {
498
+ this.tweakSigner();
499
+ if (!this.tweakedSigner) {
500
+ throw new Error('Tweaked signer is not defined');
501
+ }
502
+ const tweakedKey = toXOnly(this.tweakedSigner.publicKey);
503
+ const chainId = getChainId(this.network);
504
+ const writer = new BinaryWriter();
505
+ writer.writeU8(MLDSASecurityLevel.LEVEL2);
506
+ writer.writeBytes(this.hashedPublicKey);
507
+ writer.writeBytes(tweakedKey);
508
+ writer.writeBytes(BITCOIN_PROTOCOL_ID);
509
+ writer.writeBytes(chainId);
510
+ const message = writer.getBuffer();
511
+ const signature = MessageSigner.signMessage(this.tweakedSigner, message);
512
+ const isValid = MessageSigner.verifySignature(tweakedKey, message, signature.signature);
513
+ if (!isValid) {
514
+ throw new Error('Could not verify generated legacy signature for MLDSA link request');
515
+ }
516
+ return Buffer.from(signature.signature);
517
+ }
518
+ generateMLDSASignature() {
519
+ if (!this.mldsaSigner) {
520
+ throw new Error('MLDSA signer is not defined');
521
+ }
522
+ this.tweakSigner();
523
+ if (!this.tweakedSigner) {
524
+ throw new Error('Tweaked signer is not defined');
525
+ }
526
+ const tweakedKey = toXOnly(this.tweakedSigner.publicKey);
527
+ const chainId = getChainId(this.network);
528
+ const level = getLevelFromPublicKeyLength(this.mldsaSigner.publicKey.length);
529
+ if (level !== MLDSASecurityLevel.LEVEL2) {
530
+ throw new Error('Only MLDSA level 2 is supported for link requests');
531
+ }
532
+ const writer = new BinaryWriter();
533
+ writer.writeU8(level);
534
+ writer.writeBytes(this.hashedPublicKey);
535
+ writer.writeBytes(this.mldsaSigner.publicKey);
536
+ writer.writeBytes(tweakedKey);
537
+ writer.writeBytes(BITCOIN_PROTOCOL_ID);
538
+ writer.writeBytes(chainId);
539
+ const message = writer.getBuffer();
540
+ const signature = MessageSigner.signMLDSAMessage(this.mldsaSigner, message);
541
+ const isValid = MessageSigner.verifyMLDSASignature(this.mldsaSigner, message, signature.signature);
542
+ if (!isValid) {
543
+ throw new Error('Could not verify generated MLDSA signature for link request');
544
+ }
545
+ return Buffer.from(signature.signature);
546
+ }
547
+ generateMLDSALinkRequest(parameters, features) {
548
+ const mldsaSigner = this.mldsaSigner;
549
+ const legacySignature = this.generateLegacySignature();
550
+ let mldsaSignature = null;
551
+ if (parameters.revealMLDSAPublicKey) {
552
+ mldsaSignature = this.generateMLDSASignature();
553
+ }
554
+ const mldsaRequest = {
555
+ opcode: Features.MLDSA_LINK_PUBKEY,
556
+ data: {
557
+ verifyRequest: !!parameters.revealMLDSAPublicKey,
558
+ publicKey: mldsaSigner.publicKey,
559
+ hashedPublicKey: this.hashedPublicKey,
560
+ level: getLevelFromPublicKeyLength(mldsaSigner.publicKey.length),
561
+ legacySignature: legacySignature,
562
+ mldsaSignature: mldsaSignature,
563
+ },
564
+ };
565
+ features.push(mldsaRequest);
566
+ }
490
567
  getTransactionOPNetFee() {
491
568
  const totalFee = this.priorityFee + this.gasSatFee;
492
569
  if (totalFee > TransactionBuilder.MINIMUM_DUST) {
@@ -10,6 +10,8 @@ export interface ITransactionParameters extends ITweakedTransactionData {
10
10
  readonly from?: string;
11
11
  readonly to?: string;
12
12
  readonly debugFees?: boolean;
13
+ readonly revealMLDSAPublicKey?: boolean;
14
+ readonly linkMLDSAPublicKeyToAddress?: boolean;
13
15
  utxos: UTXO[];
14
16
  nonWitnessUtxo?: Buffer;
15
17
  estimatedFees?: bigint;
@@ -22,6 +24,7 @@ export interface ITransactionParameters extends ITweakedTransactionData {
22
24
  readonly feeRate: number;
23
25
  readonly priorityFee: bigint;
24
26
  readonly gasSatFee: bigint;
27
+ readonly compiledTargetScript?: Buffer | string;
25
28
  }
26
29
  export interface IFundingTransactionParameters extends ITransactionParameters {
27
30
  amount: bigint;
@@ -15,6 +15,7 @@ export class P2TR_MS {
15
15
  receiver: 'a',
16
16
  requestedAmount: 1n,
17
17
  refundVault: 'a',
18
+ mldsaSigner: null,
18
19
  };
19
20
  const address = new MultiSignTransaction(multiSignParams).getScriptAddress();
20
21
  if (!address) {
@@ -6,8 +6,10 @@ import { TapLeafScript } from '../interfaces/Tap.js';
6
6
  import { ChainId } from '../../network/ChainId.js';
7
7
  import { UnisatSigner } from '../browser/extensions/UnisatSigner.js';
8
8
  import { Buffer } from 'buffer';
9
+ import { QuantumBIP32Interface } from '@btc-vision/bip32';
9
10
  export type SupportedTransactionVersion = 1 | 2 | 3;
10
11
  export interface ITweakedTransactionData {
12
+ readonly mldsaSigner: QuantumBIP32Interface | null;
11
13
  readonly signer: Signer | ECPairInterface | UnisatSigner;
12
14
  readonly network: Network;
13
15
  readonly chainId?: ChainId;
@@ -47,7 +49,11 @@ export declare abstract class TweakedTransaction extends Logger {
47
49
  protected noSignatures: boolean;
48
50
  protected unlockScript: Buffer[] | undefined;
49
51
  protected txVersion: SupportedTransactionVersion;
52
+ protected readonly _mldsaSigner: QuantumBIP32Interface | null;
53
+ protected readonly _hashedPublicKey: Buffer | null;
50
54
  protected constructor(data: ITweakedTransactionData);
55
+ protected get mldsaSigner(): QuantumBIP32Interface;
56
+ protected get hashedPublicKey(): Buffer;
51
57
  static readScriptWitnessToWitnessStack(buffer: Buffer): Buffer[];
52
58
  static preEstimateTaprootTransactionFees(feeRate: bigint, numInputs: bigint, numOutputs: bigint, numWitnessElements: bigint, witnessElementSize: bigint, emptyWitness: bigint, taprootControlWitnessSize?: bigint, taprootScriptSize?: bigint): bigint;
53
59
  protected static signInput(transaction: Psbt, input: PsbtInput, i: number, signer: Signer | ECPairInterface, sighashTypes: number[]): void;
@@ -5,6 +5,7 @@ import { canSignNonTaprootInput, isTaprootInput, pubkeyInScript, } from '../../s
5
5
  import { TransactionBuilder } from '../builders/TransactionBuilder.js';
6
6
  import { Buffer } from 'buffer';
7
7
  import { P2WDADetector } from '../../p2wda/P2WDADetector.js';
8
+ import { MessageSigner } from '../../keypair/MessageSigner.js';
8
9
  export var TransactionSequence;
9
10
  (function (TransactionSequence) {
10
11
  TransactionSequence[TransactionSequence["REPLACE_BY_FEE"] = 4294967293] = "REPLACE_BY_FEE";
@@ -34,6 +35,8 @@ export class TweakedTransaction extends Logger {
34
35
  this.ignoreSignatureErrors = false;
35
36
  this.noSignatures = false;
36
37
  this.txVersion = 2;
38
+ this._mldsaSigner = null;
39
+ this._hashedPublicKey = null;
37
40
  this.customFinalizerP2SH = (inputIndex, input, scriptA, isSegwit, isP2SH, isP2WSH) => {
38
41
  const inputDecoded = this.inputs[inputIndex];
39
42
  if (isP2SH && input.partialSig && inputDecoded && inputDecoded.redeemScript) {
@@ -78,6 +81,22 @@ export class TweakedTransaction extends Logger {
78
81
  if (data.txVersion) {
79
82
  this.txVersion = data.txVersion;
80
83
  }
84
+ if (data.mldsaSigner) {
85
+ this._mldsaSigner = data.mldsaSigner;
86
+ this._hashedPublicKey = MessageSigner.sha256(this._mldsaSigner.publicKey);
87
+ }
88
+ }
89
+ get mldsaSigner() {
90
+ if (!this._mldsaSigner) {
91
+ throw new Error('MLDSA Signer is not set');
92
+ }
93
+ return this._mldsaSigner;
94
+ }
95
+ get hashedPublicKey() {
96
+ if (!this._hashedPublicKey) {
97
+ throw new Error('Hashed public key is not set');
98
+ }
99
+ return this._hashedPublicKey;
81
100
  }
82
101
  static readScriptWitnessToWitnessStack(buffer) {
83
102
  let offset = 0;
@@ -6,6 +6,7 @@ export interface WalletUTXOs {
6
6
  readonly confirmed: RawUTXOResponse[];
7
7
  readonly pending: RawUTXOResponse[];
8
8
  readonly spentTransactions: RawUTXOResponse[];
9
+ readonly raw: string[];
9
10
  }
10
11
  export declare class OPNetLimitedProvider {
11
12
  private readonly opnetAPIUrl;
@@ -24,6 +24,7 @@ export class OPNetLimitedProvider {
24
24
  throw new Error(`Failed to fetch UTXO data: ${resp.statusText}`);
25
25
  }
26
26
  const fetchedData = (await resp.json());
27
+ const rawTransactions = fetchedData.raw ?? [];
27
28
  const allUtxos = settings.usePendingUTXO
28
29
  ? [...fetchedData.confirmed, ...fetchedData.pending]
29
30
  : fetchedData.confirmed;
@@ -52,13 +53,21 @@ export class OPNetLimitedProvider {
52
53
  if (utxoValue <= 0n) {
53
54
  continue;
54
55
  }
56
+ const rawIndex = utxo.raw;
57
+ if (rawIndex === undefined || rawIndex === null) {
58
+ throw new Error(`Missing raw index for UTXO ${utxo.transactionId}:${utxo.outputIndex}`);
59
+ }
60
+ const rawHex = rawTransactions[rawIndex];
61
+ if (!rawHex) {
62
+ throw new Error(`Invalid raw index ${rawIndex} - not found in raw transactions array`);
63
+ }
55
64
  currentAmount += utxoValue;
56
65
  finalUTXOs.push({
57
66
  transactionId: utxo.transactionId,
58
67
  outputIndex: utxo.outputIndex,
59
68
  value: utxoValue,
60
69
  scriptPubKey: utxo.scriptPubKey,
61
- nonWitnessUtxo: Buffer.from(utxo.raw, 'base64'),
70
+ nonWitnessUtxo: Buffer.from(rawHex, 'base64'),
62
71
  });
63
72
  if (currentAmount > amountRequested) {
64
73
  break;
@@ -124,6 +133,7 @@ export class OPNetLimitedProvider {
124
133
  splitInputsInto,
125
134
  priorityFee: 0n,
126
135
  gasSatFee: 330n,
136
+ mldsaSigner: null,
127
137
  };
128
138
  const transactionFactory = new TransactionFactory();
129
139
  const fundingTx = await transactionFactory.createBTCTransfer(fundingTransactionParameters);
package/eslint.config.js CHANGED
@@ -29,7 +29,8 @@ export default tseslint.config(
29
29
  '@typescript-eslint/no-duplicate-enum-values': 'off',
30
30
  'prefer-spread': 'off',
31
31
  '@typescript-eslint/no-empty-object-type': 'off',
32
- '@typescript-eslint/prefer-literal-enum-member': 'off'
32
+ '@typescript-eslint/prefer-literal-enum-member': 'off',
33
+ '@typescript-eslint/related-getter-setter-pairs': 'off'
33
34
  },
34
35
  },
35
36
  {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@btc-vision/transaction",
3
3
  "type": "module",
4
- "version": "1.7.6",
4
+ "version": "1.7.10",
5
5
  "author": "BlobMaster41",
6
6
  "description": "OPNet transaction library allows you to create and sign transactions for the OPNet network.",
7
7
  "engines": {
package/src/_version.ts CHANGED
@@ -1 +1 @@
1
- export const version = '1.7.1';
1
+ export const version = '1.7.10';
@@ -0,0 +1,32 @@
1
+ import { Network, networks } from '@btc-vision/bitcoin';
2
+
3
+ function objectEqual<T>(obj1: T, obj2: T): boolean {
4
+ return JSON.stringify(obj1) === JSON.stringify(obj2);
5
+ }
6
+
7
+ export function getChainIdHex(network: Network): string {
8
+ if (objectEqual(network, networks.bitcoin)) {
9
+ return '000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f';
10
+ }
11
+
12
+ if (objectEqual(network, networks.testnet)) {
13
+ return '000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943';
14
+ }
15
+
16
+ if (objectEqual(network, networks.regtest)) {
17
+ return '0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206';
18
+ }
19
+
20
+ throw new Error('Unsupported network for chain ID retrieval');
21
+ }
22
+
23
+ export function getChainId(network: Network): Uint8Array {
24
+ return Uint8Array.from(Buffer.from(getChainIdHex(network), 'hex'));
25
+ }
26
+
27
+ export const BITCOIN_PROTOCOL_ID = Uint8Array.from(
28
+ Buffer.from(
29
+ 'e784995a412d773988c4b8e333d7b39dfb3cabf118d0d645411a916ca2407939', // sha256("OP_NET")
30
+ 'hex',
31
+ ),
32
+ );
@@ -1,11 +1,11 @@
1
1
  import { Address } from '../keypair/Address.js';
2
- import { Map } from './Map.js';
2
+ import { FastMap } from './FastMap.js';
3
3
 
4
4
  export class AddressMap<V> {
5
- private items: Map<bigint, V>;
5
+ private items: FastMap<bigint, V>;
6
6
 
7
7
  constructor(iterable?: ReadonlyArray<readonly [Address, V]> | null) {
8
- this.items = new Map();
8
+ this.items = new FastMap();
9
9
 
10
10
  if (iterable) {
11
11
  for (const [key, value] of iterable) {
@@ -1,11 +1,11 @@
1
- import { Map } from './Map.js';
1
+ import { FastMap, PropertyExtendedKey } from './FastMap.js';
2
2
 
3
- export class DeterministicMap<K, V> {
4
- private map: Map<K, V>;
3
+ export class DeterministicMap<K extends PropertyExtendedKey, V> {
4
+ private map: FastMap<K, V>;
5
5
  #keys: K[];
6
6
 
7
7
  constructor(private compareFn: (a: K, b: K) => number) {
8
- this.map = new Map<K, V>();
8
+ this.map = new FastMap<K, V>();
9
9
  this.#keys = [];
10
10
  }
11
11
 
@@ -13,8 +13,8 @@ export class DeterministicMap<K, V> {
13
13
  return this.map.size;
14
14
  }
15
15
 
16
- public static fromMap<K, V>(
17
- map: Map<K, V>,
16
+ public static fromMap<K extends PropertyExtendedKey, V>(
17
+ map: FastMap<K, V>,
18
18
  compareFn: (a: K, b: K) => number,
19
19
  ): DeterministicMap<K, V> {
20
20
  const deterministicMap = new DeterministicMap<K, V>(compareFn);
@@ -29,6 +29,7 @@ export class DeterministicMap<K, V> {
29
29
  // Binary search for insertion position
30
30
  let left = 0,
31
31
  right = this.#keys.length;
32
+
32
33
  while (left < right) {
33
34
  const mid = Math.floor((left + right) / 2);
34
35
  if (this.compareFn(this.#keys[mid], key) < 0) {
@@ -39,6 +40,7 @@ export class DeterministicMap<K, V> {
39
40
  }
40
41
  this.#keys.splice(left, 0, key);
41
42
  }
43
+
42
44
  this.map.set(key, value);
43
45
  }
44
46
 
@@ -78,6 +80,7 @@ export class DeterministicMap<K, V> {
78
80
  // Binary search to find the key's index
79
81
  let left = 0,
80
82
  right = this.#keys.length - 1;
83
+
81
84
  while (left <= right) {
82
85
  const mid = Math.floor((left + right) / 2);
83
86
  const cmp = this.compareFn(this.#keys[mid], key);
@@ -1,9 +1,21 @@
1
- export class Map<K, V> {
1
+ export type PropertyExtendedKey = PropertyKey | bigint;
2
+
3
+ /**
4
+ * Like Record, but supports bigint keys (which JS auto-converts to strings).
5
+ * Reflects actual JavaScript behavior where obj[123n] becomes obj["123"].
6
+ */
7
+ export type FastRecord<V> = {
8
+ [key: string]: V;
9
+ };
10
+
11
+ export type IndexKey = string | number;
12
+
13
+ export class FastMap<K extends PropertyExtendedKey, V> {
2
14
  protected _keys: K[] = [];
3
- protected _values: Record<string, V> = {};
15
+ protected _values: FastRecord<V> = {};
4
16
 
5
- constructor(iterable?: ReadonlyArray<readonly [K, V]> | null | Map<K, V>) {
6
- if (iterable instanceof Map) {
17
+ constructor(iterable?: ReadonlyArray<readonly [K, V]> | null | FastMap<K, V>) {
18
+ if (iterable instanceof FastMap) {
7
19
  this.setAll(iterable);
8
20
  } else {
9
21
  if (iterable) {
@@ -18,13 +30,12 @@ export class Map<K, V> {
18
30
  return this._keys.length;
19
31
  }
20
32
 
21
- public setAll(map: Map<K, V>): void {
22
- for (const [key, value] of map) {
23
- this.set(key, value);
24
- }
33
+ public setAll(map: FastMap<K, V>): void {
34
+ this._keys = [...map._keys];
35
+ this._values = { ...map._values };
25
36
  }
26
37
 
27
- public addAll(map: Map<K, V>): void {
38
+ public addAll(map: FastMap<K, V>): void {
28
39
  for (const [key, value] of map.entries()) {
29
40
  this.set(key, value);
30
41
  }
@@ -36,52 +47,58 @@ export class Map<K, V> {
36
47
 
37
48
  public *values(): IterableIterator<V> {
38
49
  for (const key of this._keys) {
39
- yield this._values[this.keyToString(key)];
50
+ yield this._values[key as IndexKey];
40
51
  }
41
52
  }
42
53
 
43
54
  public *entries(): IterableIterator<[K, V]> {
44
55
  for (const key of this._keys) {
45
- yield [key, this._values[this.keyToString(key)]];
56
+ yield [key, this._values[key as IndexKey]];
46
57
  }
47
58
  }
48
59
 
49
- public set(key: K, value: V): void {
50
- const keyStr = this.keyToString(key);
60
+ public set(key: K, value: V): this {
51
61
  if (!this.has(key)) {
52
62
  this._keys.push(key);
53
63
  }
54
64
 
55
- this._values[keyStr] = value;
65
+ this._values[key as IndexKey] = value;
66
+
67
+ return this;
56
68
  }
57
69
 
58
70
  public indexOf(key: K): number {
71
+ if (!this.has(key)) {
72
+ return -1;
73
+ }
74
+
59
75
  for (let i = 0; i < this._keys.length; i++) {
60
76
  if (this._keys[i] === key) {
61
77
  return i;
62
78
  }
63
79
  }
64
- return -1;
80
+
81
+ throw new Error('Key not found, this should not happen.');
65
82
  }
66
83
 
67
84
  public get(key: K): V | undefined {
68
- return this._values[this.keyToString(key)];
85
+ return this._values[key as IndexKey];
69
86
  }
70
87
 
71
88
  public has(key: K): boolean {
72
- return Object.prototype.hasOwnProperty.call(this._values, this.keyToString(key));
89
+ return Object.prototype.hasOwnProperty.call(this._values, key as IndexKey);
73
90
  }
74
91
 
75
92
  public delete(key: K): boolean {
76
- const index = this.indexOf(key);
77
- if (index === -1) {
93
+ if (!this.has(key)) {
78
94
  return false;
79
95
  }
80
96
 
81
- const keyStr = this.keyToString(key);
97
+ const index = this.indexOf(key);
82
98
  this._keys.splice(index, 1);
99
+
83
100
  // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
84
- delete this._values[keyStr];
101
+ delete this._values[key as IndexKey];
85
102
  return true;
86
103
  }
87
104
 
@@ -90,22 +107,18 @@ export class Map<K, V> {
90
107
  this._values = {};
91
108
  }
92
109
 
93
- *[Symbol.iterator](): IterableIterator<[K, V]> {
110
+ public forEach(
111
+ callback: (value: V, key: K, map: FastMap<K, V>) => void,
112
+ thisArg?: unknown,
113
+ ): void {
94
114
  for (const key of this._keys) {
95
- yield [key, this._values[this.keyToString(key)]];
115
+ callback.call(thisArg, this._values[key as IndexKey], key, this);
96
116
  }
97
117
  }
98
118
 
99
- private keyToString(key: K): string {
100
- if (typeof key === 'string') {
101
- return key;
102
- }
103
- if (typeof key === 'number' || typeof key === 'boolean') {
104
- return String(key);
105
- }
106
- if (typeof key === 'object' && key !== null) {
107
- return JSON.stringify(key);
119
+ *[Symbol.iterator](): IterableIterator<[K, V]> {
120
+ for (const key of this._keys) {
121
+ yield [key, this._values[key as IndexKey]];
108
122
  }
109
- return String(key);
110
123
  }
111
124
  }
@@ -42,7 +42,7 @@ export class ChallengeSubmission implements IChallengeSubmission {
42
42
  data: RawChallengeSubmission,
43
43
  public readonly epochNumber: bigint,
44
44
  ) {
45
- this.publicKey = Address.fromString(data.publicKey, data.classicPublicKey);
45
+ this.publicKey = Address.fromString(data.mldsaPublicKey, data.legacyPublicKey);
46
46
  this.solution = stringToBuffer(data.solution);
47
47
  this.graffiti = data.graffiti ? stringToBuffer(data.graffiti) : undefined;
48
48
  this.signature = stringToBuffer(data.signature);
@@ -76,7 +76,7 @@ export class ChallengeSolution implements IChallengeSolution {
76
76
 
77
77
  constructor(data: RawChallenge) {
78
78
  this.epochNumber = BigInt(data.epochNumber);
79
- this.publicKey = Address.fromString(data.publicKey, data.classicPublicKey);
79
+ this.publicKey = Address.fromString(data.mldsaPublicKey, data.legacyPublicKey);
80
80
  this.solution = stringToBuffer(data.solution);
81
81
  this.salt = stringToBuffer(data.salt);
82
82
  this.graffiti = stringToBuffer(data.graffiti);
@@ -144,8 +144,8 @@ export class ChallengeSolution implements IChallengeSolution {
144
144
  public toRaw(): RawChallenge {
145
145
  return {
146
146
  epochNumber: this.epochNumber.toString(),
147
- publicKey: this.publicKey.toHex(),
148
- classicPublicKey: this.publicKey.tweakedToHex(),
147
+ mldsaPublicKey: this.publicKey.toHex(),
148
+ legacyPublicKey: this.publicKey.tweakedToHex(),
149
149
  solution: this.toHex(),
150
150
  salt: '0x' + this.salt.toString('hex'),
151
151
  graffiti: '0x' + this.graffiti.toString('hex'),
@@ -31,8 +31,8 @@ export interface RawChallengeVerification {
31
31
  }
32
32
 
33
33
  export interface RawChallengeSubmission {
34
- readonly classicPublicKey: string;
35
- readonly publicKey: string;
34
+ readonly mldsaPublicKey: string;
35
+ readonly legacyPublicKey: string;
36
36
  readonly solution: string;
37
37
  readonly graffiti?: string;
38
38
  readonly signature: string;
@@ -47,8 +47,8 @@ export interface IChallengeSubmission {
47
47
 
48
48
  export interface RawChallenge {
49
49
  readonly epochNumber: string;
50
- readonly classicPublicKey: string;
51
- readonly publicKey: string;
50
+ readonly mldsaPublicKey: string;
51
+ readonly legacyPublicKey: string;
52
52
  readonly solution: string;
53
53
  readonly salt: string;
54
54
  readonly graffiti: string;
@@ -1,9 +1,11 @@
1
1
  import { LoadedStorage } from '../transaction/interfaces/ITransactionParameters.js';
2
2
  import { ChallengeSubmission } from '../epoch/ChallengeSolution.js';
3
+ import { MLDSARequestData } from './MLDSAData.js';
3
4
 
4
5
  export enum Features {
5
- ACCESS_LIST = 1,
6
- EPOCH_SUBMISSION = 2,
6
+ ACCESS_LIST = 0b1,
7
+ EPOCH_SUBMISSION = 0b10,
8
+ MLDSA_LINK_PUBKEY = 0b100,
7
9
  }
8
10
 
9
11
  export interface Feature<T extends Features> {
@@ -18,3 +20,7 @@ export interface AccessListFeature extends Feature<Features.ACCESS_LIST> {
18
20
  export interface EpochSubmissionFeature extends Feature<Features.EPOCH_SUBMISSION> {
19
21
  data: ChallengeSubmission;
20
22
  }
23
+
24
+ export interface MLDSALinkRequest extends Feature<Features.MLDSA_LINK_PUBKEY> {
25
+ data: MLDSARequestData;
26
+ }