@btc-vision/transaction 1.5.4 → 1.6.1
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/browser/_version.d.ts +1 -1
- package/browser/epoch/ChallengeSolution.d.ts +45 -0
- package/browser/epoch/interfaces/IChallengeSolution.d.ts +50 -0
- package/browser/epoch/validator/EpochValidator.d.ts +19 -0
- package/browser/generators/Features.d.ts +6 -1
- package/browser/generators/Generator.d.ts +1 -0
- package/browser/generators/builders/CalldataGenerator.d.ts +2 -1
- package/browser/generators/builders/DeploymentGenerator.d.ts +3 -1
- package/browser/generators/builders/LegacyCalldataGenerator.d.ts +1 -1
- package/browser/index.js +1 -1
- package/browser/keypair/Address.d.ts +2 -0
- package/browser/opnet.d.ts +4 -3
- package/browser/transaction/TransactionFactory.d.ts +4 -15
- package/browser/transaction/browser/Web3Provider.d.ts +3 -3
- package/browser/transaction/builders/ChallengeSolutionTransaction.d.ts +1 -18
- package/browser/transaction/builders/CustomScriptTransaction.d.ts +1 -1
- package/browser/transaction/builders/DeploymentTransaction.d.ts +6 -4
- package/browser/transaction/builders/SharedInteractionTransaction.d.ts +5 -4
- package/browser/transaction/builders/TransactionBuilder.d.ts +2 -0
- package/browser/transaction/interfaces/ITransactionParameters.d.ts +4 -6
- package/browser/transaction/mineable/TimelockGenerator.d.ts +9 -0
- package/browser/utils/StringToBuffer.d.ts +1 -0
- package/browser/utxo/OPNetLimitedProvider.d.ts +0 -4
- package/browser/verification/TapscriptVerificator.d.ts +4 -1
- package/build/_version.d.ts +1 -1
- package/build/_version.js +1 -1
- package/build/epoch/ChallengeSolution.d.ts +45 -0
- package/build/epoch/ChallengeSolution.js +105 -0
- package/build/epoch/interfaces/IChallengeSolution.d.ts +50 -0
- package/build/epoch/interfaces/IChallengeSolution.js +1 -0
- package/build/epoch/validator/EpochValidator.d.ts +19 -0
- package/build/epoch/validator/EpochValidator.js +99 -0
- package/build/generators/Features.d.ts +6 -1
- package/build/generators/Features.js +1 -0
- package/build/generators/Generator.d.ts +1 -0
- package/build/generators/Generator.js +17 -1
- package/build/generators/builders/CalldataGenerator.d.ts +2 -1
- package/build/generators/builders/CalldataGenerator.js +4 -2
- package/build/generators/builders/DeploymentGenerator.d.ts +3 -1
- package/build/generators/builders/DeploymentGenerator.js +6 -4
- package/build/generators/builders/LegacyCalldataGenerator.d.ts +1 -1
- package/build/generators/builders/LegacyCalldataGenerator.js +2 -2
- package/build/keypair/Address.d.ts +2 -0
- package/build/keypair/Address.js +12 -0
- package/build/keypair/EcKeyPair.js +6 -3
- package/build/opnet.d.ts +4 -3
- package/build/opnet.js +4 -3
- package/build/transaction/TransactionFactory.d.ts +4 -15
- package/build/transaction/TransactionFactory.js +4 -32
- package/build/transaction/browser/Web3Provider.d.ts +3 -3
- package/build/transaction/builders/ChallengeSolutionTransaction.d.ts +0 -18
- package/build/transaction/builders/ChallengeSolutionTransaction.js +1 -51
- package/build/transaction/builders/CustomScriptTransaction.d.ts +1 -1
- package/build/transaction/builders/DeploymentTransaction.d.ts +6 -4
- package/build/transaction/builders/DeploymentTransaction.js +20 -8
- package/build/transaction/builders/InteractionTransaction.js +8 -1
- package/build/transaction/builders/SharedInteractionTransaction.d.ts +5 -4
- package/build/transaction/builders/SharedInteractionTransaction.js +7 -7
- package/build/transaction/builders/TransactionBuilder.d.ts +2 -0
- package/build/transaction/builders/TransactionBuilder.js +31 -3
- package/build/transaction/interfaces/ITransactionParameters.d.ts +4 -6
- package/build/transaction/mineable/TimelockGenerator.d.ts +9 -0
- package/build/transaction/mineable/TimelockGenerator.js +24 -0
- package/build/utils/StringToBuffer.d.ts +1 -0
- package/build/utils/StringToBuffer.js +3 -0
- package/build/utxo/OPNetLimitedProvider.d.ts +0 -4
- package/build/utxo/OPNetLimitedProvider.js +0 -7
- package/build/verification/TapscriptVerificator.d.ts +4 -1
- package/build/verification/TapscriptVerificator.js +2 -2
- package/package.json +15 -15
- package/src/_version.ts +1 -1
- package/src/epoch/ChallengeSolution.ts +196 -0
- package/src/epoch/interfaces/IChallengeSolution.ts +56 -0
- package/src/epoch/validator/EpochValidator.ts +180 -0
- package/src/generators/Features.ts +6 -0
- package/src/generators/Generator.ts +24 -2
- package/src/generators/builders/CalldataGenerator.ts +7 -3
- package/src/generators/builders/DeploymentGenerator.ts +18 -6
- package/src/generators/builders/LegacyCalldataGenerator.ts +3 -3
- package/src/keypair/Address.ts +34 -0
- package/src/keypair/EcKeyPair.ts +9 -4
- package/src/opnet.ts +6 -3
- package/src/transaction/TransactionFactory.ts +7 -62
- package/src/transaction/browser/Web3Provider.ts +3 -3
- package/src/transaction/builders/ChallengeSolutionTransaction.ts +3 -4
- package/src/transaction/builders/CustomScriptTransaction.ts +2 -1
- package/src/transaction/builders/DeploymentTransaction.ts +29 -11
- package/src/transaction/builders/InteractionTransaction.ts +10 -2
- package/src/transaction/builders/SharedInteractionTransaction.ts +12 -28
- package/src/transaction/builders/TransactionBuilder.ts +40 -2
- package/src/transaction/interfaces/ITransactionParameters.ts +5 -8
- package/src/transaction/mineable/TimelockGenerator.ts +42 -0
- package/src/utils/StringToBuffer.ts +3 -0
- package/src/utxo/OPNetLimitedProvider.ts +0 -17
- package/src/verification/TapscriptVerificator.ts +8 -4
- package/browser/generators/builders/MineableReward.d.ts +0 -7
- package/browser/transaction/mineable/ChallengeGenerator.d.ts +0 -9
- package/build/generators/builders/MineableReward.d.ts +0 -7
- package/build/generators/builders/MineableReward.js +0 -48
- package/build/transaction/mineable/ChallengeGenerator.d.ts +0 -9
- package/build/transaction/mineable/ChallengeGenerator.js +0 -28
- package/src/generators/builders/MineableReward.ts +0 -66
- package/src/transaction/mineable/ChallengeGenerator.ts +0 -39
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { TransactionType } from '../enums/TransactionType.js';
|
|
2
|
-
import { IChallengeSolutionTransactionParameters } from '../interfaces/ITransactionParameters.js';
|
|
1
|
+
/*import { TransactionType } from '../enums/TransactionType.js';
|
|
3
2
|
import { getFinalScripts, opcodes, Psbt, PsbtInput, script, Signer } from '@btc-vision/bitcoin';
|
|
4
3
|
import { TransactionBuilder } from './TransactionBuilder.js';
|
|
5
4
|
import { ECPairInterface } from 'ecpair';
|
|
@@ -69,7 +68,7 @@ export class ChallengeSolutionTransaction extends TransactionBuilder<Transaction
|
|
|
69
68
|
finalScriptWitness: Buffer | undefined;
|
|
70
69
|
} => {
|
|
71
70
|
const inputDecoded = this.inputs[inputIndex];
|
|
72
|
-
|
|
71
|
+
|
|
73
72
|
if (isP2SH && inputDecoded && inputDecoded.redeemScript) {
|
|
74
73
|
const scriptSig = script.compile([this.challengeSolution, inputDecoded.redeemScript]);
|
|
75
74
|
|
|
@@ -85,4 +84,4 @@ export class ChallengeSolutionTransaction extends TransactionBuilder<Transaction
|
|
|
85
84
|
protected override getSignerKey(): Signer | ECPairInterface {
|
|
86
85
|
return this.signer;
|
|
87
86
|
}
|
|
88
|
-
}
|
|
87
|
+
}*/
|
|
@@ -20,7 +20,8 @@ import { EcKeyPair } from '../../keypair/EcKeyPair.js';
|
|
|
20
20
|
import { AddressGenerator } from '../../generators/AddressGenerator.js';
|
|
21
21
|
import { ECPairInterface } from 'ecpair';
|
|
22
22
|
|
|
23
|
-
export interface ICustomTransactionParameters
|
|
23
|
+
export interface ICustomTransactionParameters
|
|
24
|
+
extends Omit<SharedInteractionParameters, 'challenge'> {
|
|
24
25
|
script: (Buffer | Stack)[];
|
|
25
26
|
witnesses: Buffer[];
|
|
26
27
|
|
|
@@ -27,15 +27,18 @@ import { SharedInteractionTransaction } from './SharedInteractionTransaction.js'
|
|
|
27
27
|
import { ECPairInterface } from 'ecpair';
|
|
28
28
|
import { Address } from '../../keypair/Address.js';
|
|
29
29
|
import { UnisatSigner } from '../browser/extensions/UnisatSigner.js';
|
|
30
|
-
import {
|
|
30
|
+
import { ITimeLockOutput, TimeLockGenerator } from '../mineable/TimelockGenerator.js';
|
|
31
|
+
import { ChallengeSolution } from '../../epoch/ChallengeSolution.js';
|
|
32
|
+
import { Feature, Features } from '../../generators/Features.js';
|
|
31
33
|
|
|
32
34
|
export class DeploymentTransaction extends TransactionBuilder<TransactionType.DEPLOYMENT> {
|
|
33
35
|
public static readonly MAXIMUM_CONTRACT_SIZE = 128 * 1024;
|
|
34
36
|
|
|
35
37
|
public type: TransactionType.DEPLOYMENT = TransactionType.DEPLOYMENT;
|
|
36
38
|
|
|
37
|
-
protected readonly
|
|
38
|
-
protected readonly
|
|
39
|
+
protected readonly challenge: ChallengeSolution;
|
|
40
|
+
protected readonly epochChallenge: ITimeLockOutput;
|
|
41
|
+
|
|
39
42
|
/**
|
|
40
43
|
* The contract address
|
|
41
44
|
* @protected
|
|
@@ -122,13 +125,13 @@ export class DeploymentTransaction extends TransactionBuilder<TransactionType.DE
|
|
|
122
125
|
this.verifyCalldata();
|
|
123
126
|
}
|
|
124
127
|
|
|
125
|
-
if (!parameters.
|
|
128
|
+
if (!parameters.challenge) throw new Error('Challenge solution is required');
|
|
126
129
|
|
|
127
130
|
this.randomBytes = parameters.randomBytes || BitcoinUtils.rndBytes();
|
|
128
|
-
this.
|
|
131
|
+
this.challenge = parameters.challenge;
|
|
129
132
|
|
|
130
|
-
this.
|
|
131
|
-
this.
|
|
133
|
+
this.epochChallenge = TimeLockGenerator.generateTimeLockAddress(
|
|
134
|
+
this.challenge.publicKey.originalPublicKeyBuffer(),
|
|
132
135
|
this.network,
|
|
133
136
|
);
|
|
134
137
|
|
|
@@ -144,9 +147,10 @@ export class DeploymentTransaction extends TransactionBuilder<TransactionType.DE
|
|
|
144
147
|
this.compiledTargetScript = this.deploymentGenerator.compile(
|
|
145
148
|
this.bytecode,
|
|
146
149
|
this.randomBytes,
|
|
147
|
-
this.
|
|
150
|
+
this.challenge,
|
|
148
151
|
this.priorityFee,
|
|
149
152
|
this.calldata,
|
|
153
|
+
this.generateFeatures(parameters),
|
|
150
154
|
);
|
|
151
155
|
|
|
152
156
|
this.scriptTree = this.getScriptTree();
|
|
@@ -190,8 +194,8 @@ export class DeploymentTransaction extends TransactionBuilder<TransactionType.DE
|
|
|
190
194
|
* Get the contract bytecode
|
|
191
195
|
* @returns {Buffer} The contract bytecode
|
|
192
196
|
*/
|
|
193
|
-
public getPreimage():
|
|
194
|
-
return this.
|
|
197
|
+
public getPreimage(): ChallengeSolution {
|
|
198
|
+
return this.challenge;
|
|
195
199
|
}
|
|
196
200
|
|
|
197
201
|
public getContractAddress(): string {
|
|
@@ -271,7 +275,7 @@ export class DeploymentTransaction extends TransactionBuilder<TransactionType.DE
|
|
|
271
275
|
) {
|
|
272
276
|
this.addOutput({
|
|
273
277
|
value: Number(amountSpent - amountToCA),
|
|
274
|
-
address: this.
|
|
278
|
+
address: this.epochChallenge.address,
|
|
275
279
|
});
|
|
276
280
|
}
|
|
277
281
|
|
|
@@ -376,6 +380,20 @@ export class DeploymentTransaction extends TransactionBuilder<TransactionType.DE
|
|
|
376
380
|
};
|
|
377
381
|
}
|
|
378
382
|
|
|
383
|
+
private generateFeatures(parameters: IDeploymentParameters): Feature<Features>[] {
|
|
384
|
+
const features: Feature<Features>[] = [];
|
|
385
|
+
|
|
386
|
+
const submission = parameters.challenge.getSubmission();
|
|
387
|
+
if (submission) {
|
|
388
|
+
features.push({
|
|
389
|
+
opcode: Features.EPOCH_SUBMISSION,
|
|
390
|
+
data: submission,
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
return features;
|
|
395
|
+
}
|
|
396
|
+
|
|
379
397
|
private verifyCalldata(): void {
|
|
380
398
|
if (
|
|
381
399
|
this.calldata &&
|
|
@@ -31,7 +31,7 @@ export class InteractionTransaction extends SharedInteractionTransaction<Transac
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
this.contractSecret = Buffer.from(parameters.contract.replace('0x', ''), 'hex');
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
if (this.contractSecret.length !== 32) {
|
|
36
36
|
throw new Error('Invalid contract secret length. Expected 32 bytes.');
|
|
37
37
|
}
|
|
@@ -39,7 +39,7 @@ export class InteractionTransaction extends SharedInteractionTransaction<Transac
|
|
|
39
39
|
this.compiledTargetScript = this.calldataGenerator.compile(
|
|
40
40
|
this.calldata,
|
|
41
41
|
this.contractSecret,
|
|
42
|
-
this.
|
|
42
|
+
this.challenge,
|
|
43
43
|
this.priorityFee,
|
|
44
44
|
this.generateFeatures(parameters),
|
|
45
45
|
);
|
|
@@ -58,6 +58,14 @@ export class InteractionTransaction extends SharedInteractionTransaction<Transac
|
|
|
58
58
|
});
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
const submission = parameters.challenge.getSubmission();
|
|
62
|
+
if (submission) {
|
|
63
|
+
features.push({
|
|
64
|
+
opcode: Features.EPOCH_SUBMISSION,
|
|
65
|
+
data: submission,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
61
69
|
return features;
|
|
62
70
|
}
|
|
63
71
|
}
|
|
@@ -8,7 +8,8 @@ import { Compressor } from '../../bytecode/Compressor.js';
|
|
|
8
8
|
import { EcKeyPair } from '../../keypair/EcKeyPair.js';
|
|
9
9
|
import { BitcoinUtils } from '../../utils/BitcoinUtils.js';
|
|
10
10
|
import { UnisatSigner } from '../browser/extensions/UnisatSigner.js';
|
|
11
|
-
import {
|
|
11
|
+
import { ITimeLockOutput, TimeLockGenerator } from '../mineable/TimelockGenerator.js';
|
|
12
|
+
import { ChallengeSolution } from '../../epoch/ChallengeSolution.js';
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Shared interaction transaction
|
|
@@ -31,8 +32,8 @@ export abstract class SharedInteractionTransaction<
|
|
|
31
32
|
protected abstract readonly compiledTargetScript: Buffer;
|
|
32
33
|
protected abstract readonly scriptTree: Taptree;
|
|
33
34
|
|
|
34
|
-
protected readonly
|
|
35
|
-
protected readonly
|
|
35
|
+
protected readonly challenge: ChallengeSolution;
|
|
36
|
+
protected readonly epochChallenge: ITimeLockOutput;
|
|
36
37
|
|
|
37
38
|
protected calldataGenerator: CalldataGenerator;
|
|
38
39
|
|
|
@@ -67,15 +68,15 @@ export abstract class SharedInteractionTransaction<
|
|
|
67
68
|
throw new Error('Calldata is required');
|
|
68
69
|
}
|
|
69
70
|
|
|
70
|
-
if (!parameters.
|
|
71
|
-
throw new Error('
|
|
71
|
+
if (!parameters.challenge) {
|
|
72
|
+
throw new Error('Challenge solution is required');
|
|
72
73
|
}
|
|
73
74
|
|
|
74
|
-
this.
|
|
75
|
+
this.challenge = parameters.challenge;
|
|
75
76
|
|
|
76
77
|
this.disableAutoRefund = parameters.disableAutoRefund || false;
|
|
77
|
-
this.
|
|
78
|
-
this.
|
|
78
|
+
this.epochChallenge = TimeLockGenerator.generateTimeLockAddress(
|
|
79
|
+
this.challenge.publicKey.originalPublicKeyBuffer(),
|
|
79
80
|
this.network,
|
|
80
81
|
);
|
|
81
82
|
|
|
@@ -110,27 +111,10 @@ export abstract class SharedInteractionTransaction<
|
|
|
110
111
|
/**
|
|
111
112
|
* Get the preimage
|
|
112
113
|
*/
|
|
113
|
-
public getPreimage():
|
|
114
|
-
return this.
|
|
114
|
+
public getPreimage(): ChallengeSolution {
|
|
115
|
+
return this.challenge;
|
|
115
116
|
}
|
|
116
117
|
|
|
117
|
-
/**
|
|
118
|
-
* Generate the secret for the interaction
|
|
119
|
-
* @protected
|
|
120
|
-
* @returns {Buffer} The secret
|
|
121
|
-
* @throws {Error} If the to address is invalid
|
|
122
|
-
*/
|
|
123
|
-
|
|
124
|
-
/*protected generateSecret(): Buffer {
|
|
125
|
-
if (!this.to) throw new Error('To address is required');
|
|
126
|
-
|
|
127
|
-
if (this.to.startsWith('0x')) {
|
|
128
|
-
throw new Error(`Legacy not support at this time. Reserved for future use.`);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
return address.fromBech32(this.to).data;
|
|
132
|
-
}*/
|
|
133
|
-
|
|
134
118
|
/**
|
|
135
119
|
* Get the internal pubkey as an x-only key
|
|
136
120
|
* @protected
|
|
@@ -381,7 +365,7 @@ export abstract class SharedInteractionTransaction<
|
|
|
381
365
|
) {
|
|
382
366
|
this.addOutput({
|
|
383
367
|
value: Number(amountSpent - amountToCA),
|
|
384
|
-
address: this.
|
|
368
|
+
address: this.epochChallenge.address,
|
|
385
369
|
});
|
|
386
370
|
}
|
|
387
371
|
|
|
@@ -148,6 +148,8 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
|
|
|
148
148
|
*/
|
|
149
149
|
protected isPubKeyDestination: boolean;
|
|
150
150
|
|
|
151
|
+
protected note?: Buffer;
|
|
152
|
+
|
|
151
153
|
protected constructor(parameters: ITransactionParameters) {
|
|
152
154
|
super(parameters);
|
|
153
155
|
|
|
@@ -164,6 +166,14 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
|
|
|
164
166
|
this.optionalInputs = parameters.optionalInputs || [];
|
|
165
167
|
this.to = parameters.to || undefined;
|
|
166
168
|
|
|
169
|
+
if (parameters.note) {
|
|
170
|
+
if (typeof parameters.note === 'string') {
|
|
171
|
+
this.note = Buffer.from(parameters.note, 'utf8');
|
|
172
|
+
} else {
|
|
173
|
+
this.note = parameters.note;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
167
177
|
this.isPubKeyDestination = this.to
|
|
168
178
|
? AddressVerificator.isValidPublicKey(this.to, this.network)
|
|
169
179
|
: false;
|
|
@@ -228,6 +238,15 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
|
|
|
228
238
|
return buffer;
|
|
229
239
|
}
|
|
230
240
|
|
|
241
|
+
public addOPReturn(buffer: Buffer): void {
|
|
242
|
+
const compileScript = script.compile([opcodes.OP_RETURN, buffer]);
|
|
243
|
+
|
|
244
|
+
this.addOutput({
|
|
245
|
+
value: 0,
|
|
246
|
+
script: compileScript,
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
|
|
231
250
|
public async getFundingTransactionParameters(): Promise<IFundingTransactionParameters> {
|
|
232
251
|
if (!this.estimatedFees) {
|
|
233
252
|
this.estimatedFees = await this.estimateTransactionFees();
|
|
@@ -368,8 +387,23 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
|
|
|
368
387
|
* @returns {void}
|
|
369
388
|
*/
|
|
370
389
|
public addOutput(output: PsbtOutputExtended): void {
|
|
371
|
-
if (output.value === 0)
|
|
372
|
-
|
|
390
|
+
if (output.value === 0) {
|
|
391
|
+
const script = output as {
|
|
392
|
+
script: Buffer;
|
|
393
|
+
};
|
|
394
|
+
|
|
395
|
+
if (!script.script || script.script.length === 0) {
|
|
396
|
+
throw new Error('Output value is 0 and no script provided');
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
if (script.script.length < 2) {
|
|
400
|
+
throw new Error('Output script is too short');
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
if (script.script[0] !== opcodes.OP_RETURN) {
|
|
404
|
+
throw new Error('Output script must start with OP_RETURN when value is 0');
|
|
405
|
+
}
|
|
406
|
+
} else if (output.value < TransactionBuilder.MINIMUM_DUST) {
|
|
373
407
|
throw new Error(
|
|
374
408
|
`Output value is less than the minimum dust ${output.value} < ${TransactionBuilder.MINIMUM_DUST}`,
|
|
375
409
|
);
|
|
@@ -479,6 +513,10 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
|
|
|
479
513
|
* @returns {Promise<void>}
|
|
480
514
|
*/
|
|
481
515
|
protected async addRefundOutput(amountSpent: bigint): Promise<void> {
|
|
516
|
+
if (this.note) {
|
|
517
|
+
this.addOPReturn(this.note);
|
|
518
|
+
}
|
|
519
|
+
|
|
482
520
|
/** Add the refund output */
|
|
483
521
|
const sendBackAmount: bigint = this.totalInputAmount - amountSpent;
|
|
484
522
|
if (sendBackAmount >= TransactionBuilder.MINIMUM_DUST) {
|
|
@@ -2,6 +2,7 @@ import { UTXO } from '../../utxo/interfaces/IUTXO.js';
|
|
|
2
2
|
import { ITweakedTransactionData } from '../shared/TweakedTransaction.js';
|
|
3
3
|
import { ChainId } from '../../network/ChainId.js';
|
|
4
4
|
import { PsbtOutputExtended } from '@btc-vision/bitcoin';
|
|
5
|
+
import { ChallengeSolution } from '../../epoch/ChallengeSolution.js';
|
|
5
6
|
|
|
6
7
|
export interface LoadedStorage {
|
|
7
8
|
[key: string]: string[];
|
|
@@ -22,6 +23,8 @@ export interface ITransactionParameters extends ITweakedTransactionData {
|
|
|
22
23
|
chainId?: ChainId;
|
|
23
24
|
noSignatures?: boolean;
|
|
24
25
|
|
|
26
|
+
readonly note?: string | Buffer;
|
|
27
|
+
|
|
25
28
|
readonly feeRate: number;
|
|
26
29
|
readonly priorityFee: bigint;
|
|
27
30
|
readonly gasSatFee: bigint;
|
|
@@ -33,17 +36,11 @@ export interface IFundingTransactionParameters extends ITransactionParameters {
|
|
|
33
36
|
splitInputsInto?: number;
|
|
34
37
|
}
|
|
35
38
|
|
|
36
|
-
export interface IChallengeSolutionTransactionParameters extends ITransactionParameters {
|
|
37
|
-
amount: bigint;
|
|
38
|
-
|
|
39
|
-
readonly challengeSolution: Buffer;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
39
|
export interface SharedInteractionParameters extends ITransactionParameters {
|
|
43
40
|
calldata?: Buffer;
|
|
44
41
|
disableAutoRefund?: boolean;
|
|
45
42
|
|
|
46
|
-
readonly
|
|
43
|
+
readonly challenge: ChallengeSolution;
|
|
47
44
|
readonly randomBytes?: Buffer;
|
|
48
45
|
|
|
49
46
|
readonly loadedStorage?: LoadedStorage;
|
|
@@ -61,5 +58,5 @@ export interface IDeploymentParameters extends Omit<ITransactionParameters, 'to'
|
|
|
61
58
|
readonly calldata?: Buffer;
|
|
62
59
|
|
|
63
60
|
readonly randomBytes?: Buffer;
|
|
64
|
-
readonly
|
|
61
|
+
readonly challenge: ChallengeSolution;
|
|
65
62
|
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import bitcoin, { Network, networks, opcodes, script } from '@btc-vision/bitcoin';
|
|
2
|
+
|
|
3
|
+
export interface ITimeLockOutput {
|
|
4
|
+
address: string;
|
|
5
|
+
witnessScript: Buffer;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export class TimeLockGenerator {
|
|
9
|
+
private static readonly CSV_BLOCKS = 75;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Generate a P2WSH address with CSV timelock
|
|
13
|
+
* Note: This uses ECDSA, not Schnorr (Schnorr only available in Taproot)
|
|
14
|
+
*/
|
|
15
|
+
public static generateTimeLockAddress(
|
|
16
|
+
publicKey: Buffer,
|
|
17
|
+
network: Network = networks.bitcoin,
|
|
18
|
+
csvBlocks: number = TimeLockGenerator.CSV_BLOCKS,
|
|
19
|
+
): ITimeLockOutput {
|
|
20
|
+
const witnessScript = script.compile([
|
|
21
|
+
script.number.encode(csvBlocks),
|
|
22
|
+
opcodes.OP_CHECKSEQUENCEVERIFY,
|
|
23
|
+
opcodes.OP_DROP,
|
|
24
|
+
publicKey,
|
|
25
|
+
opcodes.OP_CHECKSIG,
|
|
26
|
+
]);
|
|
27
|
+
|
|
28
|
+
const p2wsh = bitcoin.payments.p2wsh({
|
|
29
|
+
redeem: { output: witnessScript },
|
|
30
|
+
network,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
if (!p2wsh.address) {
|
|
34
|
+
throw new Error('Failed to generate P2WSH address');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
address: p2wsh.address,
|
|
39
|
+
witnessScript: witnessScript,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -14,10 +14,6 @@ export interface WalletUTXOs {
|
|
|
14
14
|
readonly spentTransactions: RawUTXOResponse[];
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
export interface PreimageData {
|
|
18
|
-
readonly preimage: Buffer;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
17
|
/**
|
|
22
18
|
* Allows to fetch UTXO data from any OPNET node
|
|
23
19
|
*/
|
|
@@ -181,19 +177,6 @@ export class OPNetLimitedProvider {
|
|
|
181
177
|
return result as BroadcastResponse;
|
|
182
178
|
}
|
|
183
179
|
|
|
184
|
-
/**
|
|
185
|
-
* Fetches the preimage from the OPNET node
|
|
186
|
-
* @returns {Promise<PreimageData | undefined>} - The preimage fetched
|
|
187
|
-
*/
|
|
188
|
-
public async getPreimage(): Promise<PreimageData | undefined> {
|
|
189
|
-
const result = await this.rpcMethod('btc_preimage', []);
|
|
190
|
-
if (!result) {
|
|
191
|
-
return;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
return result as PreimageData;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
180
|
/**
|
|
198
181
|
* Splits UTXOs into smaller UTXOs
|
|
199
182
|
* @param {Wallet} wallet - The wallet to split UTXOs
|
|
@@ -9,14 +9,17 @@ import {
|
|
|
9
9
|
} from '@btc-vision/bitcoin';
|
|
10
10
|
import { DeploymentGenerator } from '../generators/builders/DeploymentGenerator.js';
|
|
11
11
|
import { TransactionBuilder } from '../transaction/builders/TransactionBuilder.js';
|
|
12
|
+
import { ChallengeSolution } from '../epoch/ChallengeSolution.js';
|
|
13
|
+
import { Feature, Features } from '../generators/Features.js';
|
|
12
14
|
|
|
13
15
|
export interface ContractAddressVerificationParams {
|
|
14
16
|
readonly deployerPubKey: Buffer;
|
|
15
17
|
readonly contractSaltPubKey: Buffer;
|
|
16
18
|
readonly originalSalt: Buffer;
|
|
17
19
|
readonly bytecode: Buffer;
|
|
18
|
-
readonly
|
|
20
|
+
readonly challenge: ChallengeSolution;
|
|
19
21
|
readonly priorityFee: bigint;
|
|
22
|
+
readonly features: Feature<Features>[];
|
|
20
23
|
readonly calldata?: Buffer;
|
|
21
24
|
readonly network?: Network;
|
|
22
25
|
}
|
|
@@ -37,9 +40,10 @@ export class TapscriptVerificator {
|
|
|
37
40
|
const compiledTargetScript: Buffer = scriptBuilder.compile(
|
|
38
41
|
params.bytecode,
|
|
39
42
|
params.originalSalt,
|
|
40
|
-
params.
|
|
43
|
+
params.challenge,
|
|
41
44
|
params.priorityFee,
|
|
42
45
|
params.calldata,
|
|
46
|
+
params.features,
|
|
43
47
|
);
|
|
44
48
|
|
|
45
49
|
const scriptTree: Taptree = [
|
|
@@ -70,9 +74,10 @@ export class TapscriptVerificator {
|
|
|
70
74
|
const compiledTargetScript: Buffer = scriptBuilder.compile(
|
|
71
75
|
params.bytecode,
|
|
72
76
|
params.originalSalt,
|
|
73
|
-
params.
|
|
77
|
+
params.challenge,
|
|
74
78
|
params.priorityFee,
|
|
75
79
|
params.calldata,
|
|
80
|
+
params.features,
|
|
76
81
|
);
|
|
77
82
|
|
|
78
83
|
const scriptTree: Taptree = [
|
|
@@ -91,7 +96,6 @@ export class TapscriptVerificator {
|
|
|
91
96
|
network: network,
|
|
92
97
|
scriptTree: scriptTree,
|
|
93
98
|
redeem: {
|
|
94
|
-
//pubkeys: [params.deployerPubKey, params.contractSaltPubKey],
|
|
95
99
|
output: compiledTargetScript,
|
|
96
100
|
redeemVersion: TapscriptVerificator.TAP_SCRIPT_VERSION,
|
|
97
101
|
},
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { Network } from '@btc-vision/bitcoin';
|
|
2
|
-
import { Generator } from '../Generator.js';
|
|
3
|
-
export declare class MineableReward extends Generator {
|
|
4
|
-
constructor(senderPubKey: Buffer, network?: Network);
|
|
5
|
-
compile(preimage1: Buffer): Buffer;
|
|
6
|
-
private isTestnet;
|
|
7
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { Network } from '@btc-vision/bitcoin';
|
|
2
|
-
export interface IMineableReward {
|
|
3
|
-
address: string;
|
|
4
|
-
p2shOutputScript: Buffer;
|
|
5
|
-
redeemScript: Buffer;
|
|
6
|
-
}
|
|
7
|
-
export declare class ChallengeGenerator {
|
|
8
|
-
static generateMineableReward(preimage1: Buffer, network: Network): IMineableReward;
|
|
9
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { Network } from '@btc-vision/bitcoin';
|
|
2
|
-
import { Generator } from '../Generator.js';
|
|
3
|
-
export declare class MineableReward extends Generator {
|
|
4
|
-
constructor(senderPubKey: Buffer, network?: Network);
|
|
5
|
-
compile(preimage1: Buffer): Buffer;
|
|
6
|
-
private isTestnet;
|
|
7
|
-
}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { networks, opcodes, script } from '@btc-vision/bitcoin';
|
|
2
|
-
import { Generator } from '../Generator.js';
|
|
3
|
-
export class MineableReward extends Generator {
|
|
4
|
-
constructor(senderPubKey, network = networks.bitcoin) {
|
|
5
|
-
super(senderPubKey, Buffer.alloc(0), network);
|
|
6
|
-
}
|
|
7
|
-
compile(preimage1) {
|
|
8
|
-
let compiledData;
|
|
9
|
-
if (this.isTestnet()) {
|
|
10
|
-
compiledData = [
|
|
11
|
-
preimage1,
|
|
12
|
-
opcodes.OP_SHA1,
|
|
13
|
-
opcodes.OP_SHA1,
|
|
14
|
-
opcodes.OP_SWAP,
|
|
15
|
-
opcodes.OP_SHA1,
|
|
16
|
-
opcodes.OP_SHA1,
|
|
17
|
-
opcodes.OP_EQUAL,
|
|
18
|
-
];
|
|
19
|
-
}
|
|
20
|
-
else {
|
|
21
|
-
compiledData = [
|
|
22
|
-
preimage1,
|
|
23
|
-
opcodes.OP_SWAP,
|
|
24
|
-
opcodes.OP_2DUP,
|
|
25
|
-
opcodes.OP_EQUAL,
|
|
26
|
-
opcodes.OP_NOT,
|
|
27
|
-
opcodes.OP_VERIFY,
|
|
28
|
-
opcodes.OP_SHA1,
|
|
29
|
-
opcodes.OP_SHA1,
|
|
30
|
-
opcodes.OP_SWAP,
|
|
31
|
-
opcodes.OP_SHA1,
|
|
32
|
-
opcodes.OP_SHA1,
|
|
33
|
-
opcodes.OP_EQUAL,
|
|
34
|
-
];
|
|
35
|
-
}
|
|
36
|
-
const asm = compiledData.flat();
|
|
37
|
-
const compiled = script.compile(asm);
|
|
38
|
-
const decompiled = script.decompile(compiled);
|
|
39
|
-
if (!decompiled) {
|
|
40
|
-
throw new Error('Failed to decompile script??');
|
|
41
|
-
}
|
|
42
|
-
return compiled;
|
|
43
|
-
}
|
|
44
|
-
isTestnet() {
|
|
45
|
-
return (this.network.bech32 === networks.testnet.bech32 ||
|
|
46
|
-
this.network.bech32 === networks.regtest.bech32);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { Network } from '@btc-vision/bitcoin';
|
|
2
|
-
export interface IMineableReward {
|
|
3
|
-
address: string;
|
|
4
|
-
p2shOutputScript: Buffer;
|
|
5
|
-
redeemScript: Buffer;
|
|
6
|
-
}
|
|
7
|
-
export declare class ChallengeGenerator {
|
|
8
|
-
static generateMineableReward(preimage1: Buffer, network: Network): IMineableReward;
|
|
9
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import bitcoin from '@btc-vision/bitcoin';
|
|
2
|
-
import { MineableReward } from '../../generators/builders/MineableReward.js';
|
|
3
|
-
export class ChallengeGenerator {
|
|
4
|
-
static generateMineableReward(preimage1, network) {
|
|
5
|
-
const mineableReward = new MineableReward(Buffer.alloc(0), network);
|
|
6
|
-
const redeemScript = mineableReward.compile(preimage1);
|
|
7
|
-
const p2sh = bitcoin.payments.p2sh({
|
|
8
|
-
redeem: { output: redeemScript },
|
|
9
|
-
network,
|
|
10
|
-
});
|
|
11
|
-
const outputRedeem = p2sh.redeem?.output;
|
|
12
|
-
if (!outputRedeem) {
|
|
13
|
-
throw new Error('Output redeem is required');
|
|
14
|
-
}
|
|
15
|
-
if (!p2sh.address) {
|
|
16
|
-
throw new Error('P2SH address is required');
|
|
17
|
-
}
|
|
18
|
-
const p2shOutputScript = p2sh?.redeem?.output;
|
|
19
|
-
if (!p2shOutputScript) {
|
|
20
|
-
throw new Error('No redeem output');
|
|
21
|
-
}
|
|
22
|
-
return {
|
|
23
|
-
address: p2sh.address,
|
|
24
|
-
p2shOutputScript,
|
|
25
|
-
redeemScript: redeemScript,
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { Network, networks, opcodes, script } from '@btc-vision/bitcoin';
|
|
2
|
-
import { Generator } from '../Generator.js';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Class to generate bitcoin script for interaction transactions
|
|
6
|
-
*/
|
|
7
|
-
export class MineableReward extends Generator {
|
|
8
|
-
constructor(senderPubKey: Buffer, network: Network = networks.bitcoin) {
|
|
9
|
-
super(senderPubKey, Buffer.alloc(0), network);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Compile an interaction bitcoin script
|
|
14
|
-
* @param {Buffer} preimage1 - Preimage 1
|
|
15
|
-
* @returns {Buffer} - The compiled script
|
|
16
|
-
* @throws {Error} - If something goes wrong
|
|
17
|
-
*/
|
|
18
|
-
public compile(preimage1: Buffer): Buffer {
|
|
19
|
-
let compiledData: (number | Buffer)[];
|
|
20
|
-
|
|
21
|
-
if (this.isTestnet()) {
|
|
22
|
-
compiledData = [
|
|
23
|
-
preimage1,
|
|
24
|
-
opcodes.OP_SHA1,
|
|
25
|
-
opcodes.OP_SHA1,
|
|
26
|
-
opcodes.OP_SWAP,
|
|
27
|
-
opcodes.OP_SHA1,
|
|
28
|
-
opcodes.OP_SHA1,
|
|
29
|
-
opcodes.OP_EQUAL,
|
|
30
|
-
];
|
|
31
|
-
} else {
|
|
32
|
-
compiledData = [
|
|
33
|
-
preimage1,
|
|
34
|
-
opcodes.OP_SWAP,
|
|
35
|
-
opcodes.OP_2DUP,
|
|
36
|
-
opcodes.OP_EQUAL,
|
|
37
|
-
opcodes.OP_NOT,
|
|
38
|
-
opcodes.OP_VERIFY,
|
|
39
|
-
opcodes.OP_SHA1,
|
|
40
|
-
opcodes.OP_SHA1,
|
|
41
|
-
opcodes.OP_SWAP,
|
|
42
|
-
opcodes.OP_SHA1,
|
|
43
|
-
opcodes.OP_SHA1,
|
|
44
|
-
opcodes.OP_EQUAL,
|
|
45
|
-
];
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const asm = compiledData.flat();
|
|
49
|
-
const compiled = script.compile(asm);
|
|
50
|
-
|
|
51
|
-
/** Verify the validity of the script */
|
|
52
|
-
const decompiled = script.decompile(compiled);
|
|
53
|
-
if (!decompiled) {
|
|
54
|
-
throw new Error('Failed to decompile script??');
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return compiled;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
private isTestnet(): boolean {
|
|
61
|
-
return (
|
|
62
|
-
this.network.bech32 === networks.testnet.bech32 ||
|
|
63
|
-
this.network.bech32 === networks.regtest.bech32
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
}
|