@btc-vision/transaction 1.5.3 → 1.6.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.
- package/browser/_version.d.ts +1 -1
- package/browser/abi/ABICoder.d.ts +1 -0
- package/browser/buffer/BinaryWriter.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/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/browser/types/Unisat.d.ts +1 -1
- 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/verification/TapscriptVerificator.d.ts +4 -1
- package/build/_version.d.ts +1 -1
- package/build/_version.js +1 -1
- package/build/abi/ABICoder.d.ts +1 -0
- package/build/abi/ABICoder.js +4 -0
- package/build/buffer/BinaryWriter.d.ts +1 -1
- package/build/buffer/BinaryWriter.js +11 -9
- 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 +5 -3
- package/build/keypair/Address.d.ts +2 -0
- package/build/keypair/Address.js +12 -0
- package/build/keypair/EcKeyPair.js +10 -7
- 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/browser/types/Unisat.d.ts +1 -1
- 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 +19 -7
- 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/verification/TapscriptVerificator.d.ts +4 -1
- package/build/verification/TapscriptVerificator.js +2 -2
- package/package.json +16 -16
- package/src/_version.ts +1 -1
- package/src/abi/ABICoder.ts +4 -0
- package/src/buffer/BinaryWriter.ts +13 -11
- 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/keypair/Address.ts +34 -0
- package/src/keypair/EcKeyPair.ts +13 -8
- package/src/opnet.ts +6 -3
- package/src/transaction/TransactionFactory.ts +7 -62
- package/src/transaction/browser/Web3Provider.ts +3 -3
- package/src/transaction/browser/types/Unisat.ts +1 -1
- package/src/transaction/builders/ChallengeSolutionTransaction.ts +3 -4
- package/src/transaction/builders/CustomScriptTransaction.ts +2 -1
- package/src/transaction/builders/DeploymentTransaction.ts +27 -9
- 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/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
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { ChallengeSolution } from '../ChallengeSolution.js';
|
|
2
|
+
export class EpochValidator {
|
|
3
|
+
static bufferToUint8Array(buffer) {
|
|
4
|
+
return new Uint8Array(buffer);
|
|
5
|
+
}
|
|
6
|
+
static uint8ArrayToBuffer(array) {
|
|
7
|
+
return Buffer.from(array);
|
|
8
|
+
}
|
|
9
|
+
static async sha1(data) {
|
|
10
|
+
const hashBuffer = await crypto.subtle.digest('SHA-1', data);
|
|
11
|
+
return new Uint8Array(hashBuffer);
|
|
12
|
+
}
|
|
13
|
+
static calculatePreimage(checksumRoot, publicKey, salt) {
|
|
14
|
+
if (checksumRoot.length !== 32 || publicKey.length !== 32 || salt.length !== 32) {
|
|
15
|
+
throw new Error('All inputs must be 32 bytes');
|
|
16
|
+
}
|
|
17
|
+
const preimage = Buffer.alloc(32);
|
|
18
|
+
for (let i = 0; i < 32; i++) {
|
|
19
|
+
preimage[i] = checksumRoot[i] ^ publicKey[i] ^ salt[i];
|
|
20
|
+
}
|
|
21
|
+
return preimage;
|
|
22
|
+
}
|
|
23
|
+
static countMatchingBits(hash1, hash2) {
|
|
24
|
+
let matchingBits = 0;
|
|
25
|
+
if (hash1.length !== hash2.length) {
|
|
26
|
+
throw new Error('Hashes must be of the same length');
|
|
27
|
+
}
|
|
28
|
+
const minLength = Math.min(hash1.length, hash2.length);
|
|
29
|
+
for (let i = 0; i < minLength; i++) {
|
|
30
|
+
const byte1 = hash1[i];
|
|
31
|
+
const byte2 = hash2[i];
|
|
32
|
+
if (byte1 === byte2) {
|
|
33
|
+
matchingBits += 8;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
for (let bit = 7; bit >= 0; bit--) {
|
|
37
|
+
if (((byte1 >> bit) & 1) === ((byte2 >> bit) & 1)) {
|
|
38
|
+
matchingBits++;
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
return matchingBits;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return matchingBits;
|
|
47
|
+
}
|
|
48
|
+
static async verifySolution(preimage, log = false) {
|
|
49
|
+
try {
|
|
50
|
+
const verification = preimage.verification;
|
|
51
|
+
const calculatedPreimage = this.calculatePreimage(verification.targetChecksum, preimage.publicKey.toBuffer(), preimage.salt);
|
|
52
|
+
const computedSolution = await this.sha1(this.bufferToUint8Array(calculatedPreimage));
|
|
53
|
+
const computedSolutionBuffer = this.uint8ArrayToBuffer(computedSolution);
|
|
54
|
+
if (!computedSolutionBuffer.equals(preimage.solution)) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
const matchingBits = this.countMatchingBits(computedSolutionBuffer, verification.targetHash);
|
|
58
|
+
if (matchingBits !== preimage.difficulty) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
const expectedStartBlock = preimage.epochNumber * this.BLOCKS_PER_EPOCH;
|
|
62
|
+
const expectedEndBlock = expectedStartBlock + this.BLOCKS_PER_EPOCH - 1n;
|
|
63
|
+
return !(verification.startBlock !== expectedStartBlock ||
|
|
64
|
+
verification.endBlock !== expectedEndBlock);
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
if (log)
|
|
68
|
+
console.error('Verification error:', error);
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
static getMiningTargetBlock(epochNumber) {
|
|
73
|
+
if (epochNumber === 0n) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
return epochNumber * this.BLOCKS_PER_EPOCH - 1n;
|
|
77
|
+
}
|
|
78
|
+
static async validateEpochWinner(epochData) {
|
|
79
|
+
const preimage = new ChallengeSolution(epochData);
|
|
80
|
+
return await this.verifySolution(preimage);
|
|
81
|
+
}
|
|
82
|
+
static async validatePreimage(preimage) {
|
|
83
|
+
return await this.verifySolution(preimage);
|
|
84
|
+
}
|
|
85
|
+
static async calculateSolution(targetChecksum, publicKey, salt) {
|
|
86
|
+
const preimage = this.calculatePreimage(targetChecksum, publicKey, salt);
|
|
87
|
+
const hash = await this.sha1(this.bufferToUint8Array(preimage));
|
|
88
|
+
return this.uint8ArrayToBuffer(hash);
|
|
89
|
+
}
|
|
90
|
+
static checkDifficulty(solution, targetHash, minDifficulty) {
|
|
91
|
+
const difficulty = this.countMatchingBits(solution, targetHash);
|
|
92
|
+
return {
|
|
93
|
+
valid: difficulty >= minDifficulty,
|
|
94
|
+
difficulty,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
EpochValidator.BLOCKS_PER_EPOCH = 5n;
|
|
99
|
+
EpochValidator.GRAFFITI_LENGTH = 16;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { LoadedStorage } from '../transaction/interfaces/ITransactionParameters.js';
|
|
2
|
+
import { ChallengeSubmission } from '../epoch/ChallengeSolution.js';
|
|
2
3
|
export declare enum Features {
|
|
3
|
-
ACCESS_LIST = 1
|
|
4
|
+
ACCESS_LIST = 1,
|
|
5
|
+
EPOCH_SUBMISSION = 2
|
|
4
6
|
}
|
|
5
7
|
export interface Feature<T extends Features> {
|
|
6
8
|
opcode: T;
|
|
@@ -9,3 +11,6 @@ export interface Feature<T extends Features> {
|
|
|
9
11
|
export interface AccessListFeature extends Feature<Features.ACCESS_LIST> {
|
|
10
12
|
data: LoadedStorage;
|
|
11
13
|
}
|
|
14
|
+
export interface EpochSubmissionFeature extends Feature<Features.EPOCH_SUBMISSION> {
|
|
15
|
+
data: ChallengeSubmission;
|
|
16
|
+
}
|
|
@@ -14,4 +14,5 @@ export declare abstract class Generator {
|
|
|
14
14
|
protected splitBufferIntoChunks(buffer: Buffer, chunkSize?: number): Array<Buffer[]>;
|
|
15
15
|
protected encodeFeature(feature: Feature<Features>): Buffer[][];
|
|
16
16
|
private encodeAccessListFeature;
|
|
17
|
+
private encodeChallengeSubmission;
|
|
17
18
|
}
|
|
@@ -40,8 +40,12 @@ export class Generator {
|
|
|
40
40
|
}
|
|
41
41
|
encodeFeature(feature) {
|
|
42
42
|
switch (feature.opcode) {
|
|
43
|
-
case Features.ACCESS_LIST:
|
|
43
|
+
case Features.ACCESS_LIST: {
|
|
44
44
|
return this.splitBufferIntoChunks(this.encodeAccessListFeature(feature));
|
|
45
|
+
}
|
|
46
|
+
case Features.EPOCH_SUBMISSION: {
|
|
47
|
+
return this.splitBufferIntoChunks(this.encodeChallengeSubmission(feature));
|
|
48
|
+
}
|
|
45
49
|
default:
|
|
46
50
|
throw new Error(`Unknown feature type: ${feature.opcode}`);
|
|
47
51
|
}
|
|
@@ -64,6 +68,18 @@ export class Generator {
|
|
|
64
68
|
}
|
|
65
69
|
return Compressor.compress(Buffer.from(writer.getBuffer()));
|
|
66
70
|
}
|
|
71
|
+
encodeChallengeSubmission(feature) {
|
|
72
|
+
if ('verifySignature' in feature.data && !feature.data.verifySignature()) {
|
|
73
|
+
throw new Error('Invalid signature in challenge submission feature');
|
|
74
|
+
}
|
|
75
|
+
const writer = new BinaryWriter();
|
|
76
|
+
writer.writeBytes(feature.data.publicKey.originalPublicKeyBuffer());
|
|
77
|
+
writer.writeBytes(feature.data.solution);
|
|
78
|
+
if (feature.data.graffiti) {
|
|
79
|
+
writer.writeBytesWithLength(feature.data.graffiti);
|
|
80
|
+
}
|
|
81
|
+
return Buffer.from(writer.getBuffer());
|
|
82
|
+
}
|
|
67
83
|
}
|
|
68
84
|
Generator.DATA_CHUNK_SIZE = 512;
|
|
69
85
|
Generator.MAGIC = Buffer.from('op', 'utf-8');
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Network } from '@btc-vision/bitcoin';
|
|
2
2
|
import { Feature, Features } from '../Features.js';
|
|
3
3
|
import { Generator } from '../Generator.js';
|
|
4
|
+
import { ChallengeSolution } from '../../epoch/ChallengeSolution.js';
|
|
4
5
|
export declare class CalldataGenerator extends Generator {
|
|
5
6
|
constructor(senderPubKey: Buffer, contractSaltPubKey: Buffer, network?: Network);
|
|
6
7
|
static getPubKeyAsBuffer(witnessKeys: Buffer[], network: Network): Buffer;
|
|
7
|
-
compile(calldata: Buffer, contractSecret: Buffer,
|
|
8
|
+
compile(calldata: Buffer, contractSecret: Buffer, challenge: ChallengeSolution, maxPriority: bigint, features?: Feature<Features>[]): Buffer;
|
|
8
9
|
}
|
|
@@ -24,7 +24,7 @@ export class CalldataGenerator extends Generator {
|
|
|
24
24
|
}
|
|
25
25
|
return compressed;
|
|
26
26
|
}
|
|
27
|
-
compile(calldata, contractSecret,
|
|
27
|
+
compile(calldata, contractSecret, challenge, maxPriority, features = []) {
|
|
28
28
|
if (!this.contractSaltPubKey)
|
|
29
29
|
throw new Error('Contract salt public key not set');
|
|
30
30
|
const dataChunks = this.splitBufferIntoChunks(calldata);
|
|
@@ -41,7 +41,9 @@ export class CalldataGenerator extends Generator {
|
|
|
41
41
|
let compiledData = [
|
|
42
42
|
this.getHeader(maxPriority, featuresList),
|
|
43
43
|
opcodes.OP_TOALTSTACK,
|
|
44
|
-
|
|
44
|
+
challenge.publicKey.originalPublicKeyBuffer(),
|
|
45
|
+
opcodes.OP_TOALTSTACK,
|
|
46
|
+
challenge.solution,
|
|
45
47
|
opcodes.OP_TOALTSTACK,
|
|
46
48
|
this.xSenderPubKey,
|
|
47
49
|
opcodes.OP_DUP,
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { Network } from '@btc-vision/bitcoin';
|
|
2
2
|
import { Generator } from '../Generator.js';
|
|
3
|
+
import { Feature, Features } from '../Features.js';
|
|
4
|
+
import { ChallengeSolution } from '../../epoch/ChallengeSolution.js';
|
|
3
5
|
export declare const OPNET_DEPLOYMENT_VERSION = 0;
|
|
4
6
|
export declare const versionBuffer: Buffer<ArrayBuffer>;
|
|
5
7
|
export declare class DeploymentGenerator extends Generator {
|
|
6
8
|
constructor(senderPubKey: Buffer, contractSaltPubKey: Buffer, network?: Network);
|
|
7
|
-
compile(contractBytecode: Buffer, contractSalt: Buffer, preimage:
|
|
9
|
+
compile(contractBytecode: Buffer, contractSalt: Buffer, preimage: ChallengeSolution, maxPriority: bigint, calldata?: Buffer, features?: Feature<Features>[]): Buffer;
|
|
8
10
|
private getAsm;
|
|
9
11
|
}
|
|
@@ -6,8 +6,8 @@ export class DeploymentGenerator extends Generator {
|
|
|
6
6
|
constructor(senderPubKey, contractSaltPubKey, network = networks.bitcoin) {
|
|
7
7
|
super(senderPubKey, contractSaltPubKey, network);
|
|
8
8
|
}
|
|
9
|
-
compile(contractBytecode, contractSalt, preimage, maxPriority, calldata) {
|
|
10
|
-
const asm = this.getAsm(contractBytecode, contractSalt, preimage, maxPriority, calldata);
|
|
9
|
+
compile(contractBytecode, contractSalt, preimage, maxPriority, calldata, features) {
|
|
10
|
+
const asm = this.getAsm(contractBytecode, contractSalt, preimage, maxPriority, calldata, features);
|
|
11
11
|
const compiled = script.compile(asm);
|
|
12
12
|
const decompiled = script.decompile(compiled);
|
|
13
13
|
if (!decompiled) {
|
|
@@ -33,7 +33,9 @@ export class DeploymentGenerator extends Generator {
|
|
|
33
33
|
const compiledData = [
|
|
34
34
|
this.getHeader(maxPriority, featuresList),
|
|
35
35
|
opcodes.OP_TOALTSTACK,
|
|
36
|
-
preimage,
|
|
36
|
+
preimage.publicKey.originalPublicKeyBuffer(),
|
|
37
|
+
opcodes.OP_TOALTSTACK,
|
|
38
|
+
preimage.solution,
|
|
37
39
|
opcodes.OP_TOALTSTACK,
|
|
38
40
|
this.xSenderPubKey,
|
|
39
41
|
opcodes.OP_DUP,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Network } from '@btc-vision/bitcoin';
|
|
2
|
+
import { ITimeLockOutput } from '../transaction/mineable/TimelockGenerator.js';
|
|
2
3
|
export declare class Address extends Uint8Array {
|
|
3
4
|
#private;
|
|
4
5
|
constructor(bytes?: ArrayLike<number>);
|
|
@@ -28,6 +29,7 @@ export declare class Address extends Uint8Array {
|
|
|
28
29
|
toString(): string;
|
|
29
30
|
toJSON(): string;
|
|
30
31
|
p2tr(network: Network): string;
|
|
32
|
+
toCSV(duration: bigint | number | string, network: Network): ITimeLockOutput;
|
|
31
33
|
p2op(network: Network): string;
|
|
32
34
|
toTweakedHybridPublicKeyHex(): string;
|
|
33
35
|
toTweakedHybridPublicKeyBuffer(): Buffer;
|
package/build/keypair/Address.js
CHANGED
|
@@ -16,6 +16,7 @@ import { AddressVerificator } from './AddressVerificator.js';
|
|
|
16
16
|
import { EcKeyPair } from './EcKeyPair.js';
|
|
17
17
|
import { ContractAddress } from '../transaction/ContractAddress.js';
|
|
18
18
|
import { BitcoinUtils } from '../utils/BitcoinUtils.js';
|
|
19
|
+
import { TimeLockGenerator } from '../transaction/mineable/TimelockGenerator.js';
|
|
19
20
|
export class Address extends Uint8Array {
|
|
20
21
|
constructor(bytes) {
|
|
21
22
|
super(ADDRESS_BYTE_LENGTH);
|
|
@@ -194,6 +195,17 @@ export class Address extends Uint8Array {
|
|
|
194
195
|
}
|
|
195
196
|
throw new Error('Public key not set');
|
|
196
197
|
}
|
|
198
|
+
toCSV(duration, network) {
|
|
199
|
+
const n = Number(duration);
|
|
200
|
+
if (n < 1 || n > 65535) {
|
|
201
|
+
throw new Error('CSV block number must be between 1 and 65535');
|
|
202
|
+
}
|
|
203
|
+
if (!__classPrivateFieldGet(this, _Address_originalPublicKey, "f")) {
|
|
204
|
+
throw new Error('Cannot create CSV address: public key not set');
|
|
205
|
+
}
|
|
206
|
+
const publicKeyBuffer = Buffer.from(__classPrivateFieldGet(this, _Address_originalPublicKey, "f"));
|
|
207
|
+
return TimeLockGenerator.generateTimeLockAddress(publicKeyBuffer, network, n);
|
|
208
|
+
}
|
|
197
209
|
p2op(network) {
|
|
198
210
|
if (__classPrivateFieldGet(this, _Address_p2op, "f") && __classPrivateFieldGet(this, _Address_network, "f") === network) {
|
|
199
211
|
return __classPrivateFieldGet(this, _Address_p2op, "f");
|
|
@@ -11,8 +11,8 @@ const BIP32factory = typeof bip32 === 'function' ? bip32 : BIP32Factory;
|
|
|
11
11
|
if (!BIP32factory) {
|
|
12
12
|
throw new Error('Failed to load BIP32 library');
|
|
13
13
|
}
|
|
14
|
-
secp256k1.
|
|
15
|
-
const
|
|
14
|
+
const Point = secp256k1.Point;
|
|
15
|
+
const CURVE_N = Point.Fn.ORDER;
|
|
16
16
|
const TAP_TAG = utf8ToBytes('TapTweak');
|
|
17
17
|
const TAP_TAG_HASH = sha256(TAP_TAG);
|
|
18
18
|
function tapTweakHash(x) {
|
|
@@ -113,19 +113,19 @@ export class EcKeyPair {
|
|
|
113
113
|
pub = pub.slice(2);
|
|
114
114
|
const P = Point.fromHex(pub);
|
|
115
115
|
const Peven = (P.y & 1n) === 0n ? P : P.negate();
|
|
116
|
-
const xBytes = Peven.
|
|
116
|
+
const xBytes = Peven.toBytes(true).subarray(1);
|
|
117
117
|
const tBytes = tapTweakHash(xBytes);
|
|
118
|
-
const t = mod(bytesToNumberBE(tBytes),
|
|
118
|
+
const t = mod(bytesToNumberBE(tBytes), CURVE_N);
|
|
119
119
|
const Q = Peven.add(Point.BASE.multiply(t));
|
|
120
|
-
return Buffer.from(Q.
|
|
120
|
+
return Buffer.from(Q.toBytes(true));
|
|
121
121
|
}
|
|
122
122
|
static tweakBatchSharedT(pubkeys, tweakScalar) {
|
|
123
123
|
const T = Point.BASE.multiply(tweakScalar);
|
|
124
124
|
return pubkeys.map((bytes) => {
|
|
125
125
|
const P = Point.fromHex(bytes);
|
|
126
|
-
const P_even = P.
|
|
126
|
+
const P_even = P.y % 2n === 0n ? P : P.negate();
|
|
127
127
|
const Q = P_even.add(T);
|
|
128
|
-
return Q.
|
|
128
|
+
return Q.toBytes(true);
|
|
129
129
|
});
|
|
130
130
|
}
|
|
131
131
|
static generateWallet(network = networks.bitcoin) {
|
|
@@ -214,3 +214,6 @@ export class EcKeyPair {
|
|
|
214
214
|
}
|
|
215
215
|
EcKeyPair.BIP32 = BIP32factory(ecc);
|
|
216
216
|
EcKeyPair.ECPair = ECPairFactory(ecc);
|
|
217
|
+
(() => {
|
|
218
|
+
Point.BASE.precompute(8);
|
|
219
|
+
})();
|
package/build/opnet.d.ts
CHANGED
|
@@ -5,11 +5,10 @@ export * from './generators/builders/CalldataGenerator.js';
|
|
|
5
5
|
export * from './generators/builders/CustomGenerator.js';
|
|
6
6
|
export * from './generators/builders/DeploymentGenerator.js';
|
|
7
7
|
export * from './generators/builders/LegacyCalldataGenerator.js';
|
|
8
|
-
export * from './generators/builders/MineableReward.js';
|
|
9
8
|
export * from './generators/builders/MultiSignGenerator.js';
|
|
10
9
|
export * from './generators/Features.js';
|
|
11
10
|
export * from './generators/Generator.js';
|
|
12
|
-
export * from './transaction/mineable/
|
|
11
|
+
export * from './transaction/mineable/TimelockGenerator.js';
|
|
13
12
|
export * from './generators/AddressGenerator.js';
|
|
14
13
|
export * from './verification/TapscriptVerificator.js';
|
|
15
14
|
export * from './keypair/AddressVerificator.js';
|
|
@@ -24,7 +23,6 @@ export * from './transaction/enums/TransactionType.js';
|
|
|
24
23
|
export * from './transaction/interfaces/ITransactionParameters.js';
|
|
25
24
|
export * from './transaction/interfaces/Tap.js';
|
|
26
25
|
export * from './transaction/TransactionFactory.js';
|
|
27
|
-
export * from './transaction/builders/ChallengeSolutionTransaction.js';
|
|
28
26
|
export * from './transaction/builders/CustomScriptTransaction.js';
|
|
29
27
|
export * from './transaction/builders/DeploymentTransaction.js';
|
|
30
28
|
export * from './transaction/builders/FundingTransaction.js';
|
|
@@ -32,6 +30,9 @@ export * from './transaction/builders/InteractionTransaction.js';
|
|
|
32
30
|
export * from './transaction/builders/MultiSignTransaction.js';
|
|
33
31
|
export * from './transaction/builders/SharedInteractionTransaction.js';
|
|
34
32
|
export * from './transaction/builders/TransactionBuilder.js';
|
|
33
|
+
export * from './epoch/interfaces/IChallengeSolution.js';
|
|
34
|
+
export * from './epoch/validator/EpochValidator.js';
|
|
35
|
+
export * from './epoch/ChallengeSolution.js';
|
|
35
36
|
export * from './utils/BitcoinUtils.js';
|
|
36
37
|
export * from './utils/lengths.js';
|
|
37
38
|
export * from './utxo/interfaces/IUTXO.js';
|
package/build/opnet.js
CHANGED
|
@@ -4,11 +4,10 @@ export * from './generators/builders/CalldataGenerator.js';
|
|
|
4
4
|
export * from './generators/builders/CustomGenerator.js';
|
|
5
5
|
export * from './generators/builders/DeploymentGenerator.js';
|
|
6
6
|
export * from './generators/builders/LegacyCalldataGenerator.js';
|
|
7
|
-
export * from './generators/builders/MineableReward.js';
|
|
8
7
|
export * from './generators/builders/MultiSignGenerator.js';
|
|
9
8
|
export * from './generators/Features.js';
|
|
10
9
|
export * from './generators/Generator.js';
|
|
11
|
-
export * from './transaction/mineable/
|
|
10
|
+
export * from './transaction/mineable/TimelockGenerator.js';
|
|
12
11
|
export * from './generators/AddressGenerator.js';
|
|
13
12
|
export * from './verification/TapscriptVerificator.js';
|
|
14
13
|
export * from './keypair/AddressVerificator.js';
|
|
@@ -23,7 +22,6 @@ export * from './transaction/enums/TransactionType.js';
|
|
|
23
22
|
export * from './transaction/interfaces/ITransactionParameters.js';
|
|
24
23
|
export * from './transaction/interfaces/Tap.js';
|
|
25
24
|
export * from './transaction/TransactionFactory.js';
|
|
26
|
-
export * from './transaction/builders/ChallengeSolutionTransaction.js';
|
|
27
25
|
export * from './transaction/builders/CustomScriptTransaction.js';
|
|
28
26
|
export * from './transaction/builders/DeploymentTransaction.js';
|
|
29
27
|
export * from './transaction/builders/FundingTransaction.js';
|
|
@@ -31,6 +29,9 @@ export * from './transaction/builders/InteractionTransaction.js';
|
|
|
31
29
|
export * from './transaction/builders/MultiSignTransaction.js';
|
|
32
30
|
export * from './transaction/builders/SharedInteractionTransaction.js';
|
|
33
31
|
export * from './transaction/builders/TransactionBuilder.js';
|
|
32
|
+
export * from './epoch/interfaces/IChallengeSolution.js';
|
|
33
|
+
export * from './epoch/validator/EpochValidator.js';
|
|
34
|
+
export * from './epoch/ChallengeSolution.js';
|
|
34
35
|
export * from './utils/BitcoinUtils.js';
|
|
35
36
|
export * from './utils/lengths.js';
|
|
36
37
|
export * from './utxo/interfaces/IUTXO.js';
|
|
@@ -4,14 +4,14 @@ import { ICustomTransactionParameters } from './builders/CustomScriptTransaction
|
|
|
4
4
|
import { FundingTransaction } from './builders/FundingTransaction.js';
|
|
5
5
|
import { TransactionBuilder } from './builders/TransactionBuilder.js';
|
|
6
6
|
import { TransactionType } from './enums/TransactionType.js';
|
|
7
|
-
import {
|
|
8
|
-
import { ChallengeSolutionTransaction } from './builders/ChallengeSolutionTransaction.js';
|
|
7
|
+
import { IDeploymentParameters, IFundingTransactionParameters, IInteractionParameters } from './interfaces/ITransactionParameters.js';
|
|
9
8
|
import { InteractionParametersWithoutSigner } from './browser/Web3Provider.js';
|
|
9
|
+
import { RawChallenge } from '../epoch/interfaces/IChallengeSolution.js';
|
|
10
10
|
export interface DeploymentResult {
|
|
11
11
|
readonly transaction: [string, string];
|
|
12
12
|
readonly contractAddress: string;
|
|
13
13
|
readonly contractPubKey: string;
|
|
14
|
-
readonly preimage:
|
|
14
|
+
readonly preimage: RawChallenge;
|
|
15
15
|
readonly utxos: UTXO[];
|
|
16
16
|
}
|
|
17
17
|
export interface FundingTransactionResponse {
|
|
@@ -20,12 +20,6 @@ export interface FundingTransactionResponse {
|
|
|
20
20
|
readonly estimatedFees: bigint;
|
|
21
21
|
readonly nextUTXOs: UTXO[];
|
|
22
22
|
}
|
|
23
|
-
export interface ChallengeSolutionResponse {
|
|
24
|
-
readonly tx: Transaction;
|
|
25
|
-
readonly original: ChallengeSolutionTransaction;
|
|
26
|
-
readonly estimatedFees: bigint;
|
|
27
|
-
readonly nextUTXOs: UTXO[];
|
|
28
|
-
}
|
|
29
23
|
export interface BitcoinTransferBase {
|
|
30
24
|
readonly tx: string;
|
|
31
25
|
readonly estimatedFees: bigint;
|
|
@@ -36,10 +30,7 @@ export interface InteractionResponse {
|
|
|
36
30
|
readonly interactionTransaction: string;
|
|
37
31
|
readonly estimatedFees: bigint;
|
|
38
32
|
readonly nextUTXOs: UTXO[];
|
|
39
|
-
readonly preimage:
|
|
40
|
-
}
|
|
41
|
-
export interface ChallengeSolution extends BitcoinTransferBase {
|
|
42
|
-
readonly original: ChallengeSolutionTransaction;
|
|
33
|
+
readonly preimage: RawChallenge;
|
|
43
34
|
}
|
|
44
35
|
export interface BitcoinTransferResponse extends BitcoinTransferBase {
|
|
45
36
|
readonly original: FundingTransaction;
|
|
@@ -49,12 +40,10 @@ export declare class TransactionFactory {
|
|
|
49
40
|
signInteraction(interactionParameters: IInteractionParameters | InteractionParametersWithoutSigner): Promise<InteractionResponse>;
|
|
50
41
|
signDeployment(deploymentParameters: IDeploymentParameters): Promise<DeploymentResult>;
|
|
51
42
|
createBTCTransfer(parameters: IFundingTransactionParameters): Promise<BitcoinTransferResponse>;
|
|
52
|
-
createChallengeSolution(parameters: IChallengeSolutionTransactionParameters): Promise<ChallengeSolution>;
|
|
53
43
|
getAllNewUTXOs(original: TransactionBuilder<TransactionType>, tx: Transaction, to: string): UTXO[];
|
|
54
44
|
private parseOptionalInputs;
|
|
55
45
|
private detectInteractionOPWallet;
|
|
56
46
|
private detectDeploymentOPWallet;
|
|
57
|
-
private _createChallengeSolution;
|
|
58
47
|
private createFundTransaction;
|
|
59
48
|
private writePSBTHeader;
|
|
60
49
|
private getPriorityFee;
|
|
@@ -4,7 +4,6 @@ import { DeploymentTransaction } from './builders/DeploymentTransaction.js';
|
|
|
4
4
|
import { FundingTransaction } from './builders/FundingTransaction.js';
|
|
5
5
|
import { InteractionTransaction } from './builders/InteractionTransaction.js';
|
|
6
6
|
import { TransactionBuilder } from './builders/TransactionBuilder.js';
|
|
7
|
-
import { ChallengeSolutionTransaction } from './builders/ChallengeSolutionTransaction.js';
|
|
8
7
|
export class TransactionFactory {
|
|
9
8
|
async createCustomScriptTransaction(interactionParameters) {
|
|
10
9
|
if (!interactionParameters.to) {
|
|
@@ -122,7 +121,7 @@ export class TransactionFactory {
|
|
|
122
121
|
...this.getUTXOAsTransaction(signedTransaction.tx, interactionParameters.to, 0),
|
|
123
122
|
],
|
|
124
123
|
randomBytes: preTransaction.getRndBytes(),
|
|
125
|
-
|
|
124
|
+
challenge: preTransaction.getPreimage(),
|
|
126
125
|
nonWitnessUtxo: signedTransaction.tx.toBuffer(),
|
|
127
126
|
estimatedFees: preTransaction.estimatedFees,
|
|
128
127
|
optionalInputs: inputs,
|
|
@@ -134,7 +133,7 @@ export class TransactionFactory {
|
|
|
134
133
|
interactionTransaction: outTx.toHex(),
|
|
135
134
|
estimatedFees: preTransaction.estimatedFees,
|
|
136
135
|
nextUTXOs: this.getUTXOAsTransaction(signedTransaction.tx, interactionParameters.from, 1),
|
|
137
|
-
preimage: preTransaction.getPreimage().
|
|
136
|
+
preimage: preTransaction.getPreimage().toRaw(),
|
|
138
137
|
};
|
|
139
138
|
}
|
|
140
139
|
async signDeployment(deploymentParameters) {
|
|
@@ -190,7 +189,7 @@ export class TransactionFactory {
|
|
|
190
189
|
...deploymentParameters,
|
|
191
190
|
utxos: [newUtxo],
|
|
192
191
|
randomBytes: preTransaction.getRndBytes(),
|
|
193
|
-
|
|
192
|
+
challenge: preTransaction.getPreimage(),
|
|
194
193
|
nonWitnessUtxo: signedTransaction.toBuffer(),
|
|
195
194
|
estimatedFees: preTransaction.estimatedFees,
|
|
196
195
|
optionalInputs: inputs,
|
|
@@ -212,7 +211,7 @@ export class TransactionFactory {
|
|
|
212
211
|
contractAddress: finalTransaction.getContractAddress(),
|
|
213
212
|
contractPubKey: finalTransaction.contractPubKey,
|
|
214
213
|
utxos: [refundUTXO],
|
|
215
|
-
preimage: preTransaction.getPreimage().
|
|
214
|
+
preimage: preTransaction.getPreimage().toRaw(),
|
|
216
215
|
};
|
|
217
216
|
}
|
|
218
217
|
async createBTCTransfer(parameters) {
|
|
@@ -227,18 +226,6 @@ export class TransactionFactory {
|
|
|
227
226
|
nextUTXOs: this.getAllNewUTXOs(resp.original, resp.tx, parameters.from),
|
|
228
227
|
};
|
|
229
228
|
}
|
|
230
|
-
async createChallengeSolution(parameters) {
|
|
231
|
-
if (!parameters.from) {
|
|
232
|
-
throw new Error('Field "from" not provided.');
|
|
233
|
-
}
|
|
234
|
-
const resp = await this._createChallengeSolution(parameters);
|
|
235
|
-
return {
|
|
236
|
-
estimatedFees: resp.estimatedFees,
|
|
237
|
-
original: resp.original,
|
|
238
|
-
tx: resp.tx.toHex(),
|
|
239
|
-
nextUTXOs: this.getAllNewUTXOs(resp.original, resp.tx, parameters.from),
|
|
240
|
-
};
|
|
241
|
-
}
|
|
242
229
|
getAllNewUTXOs(original, tx, to) {
|
|
243
230
|
const outputs = original.getOutputs();
|
|
244
231
|
const utxos = [];
|
|
@@ -305,21 +292,6 @@ export class TransactionFactory {
|
|
|
305
292
|
}
|
|
306
293
|
return deployment;
|
|
307
294
|
}
|
|
308
|
-
async _createChallengeSolution(parameters) {
|
|
309
|
-
if (!parameters.to)
|
|
310
|
-
throw new Error('Field "to" not provided.');
|
|
311
|
-
const challengeTransaction = new ChallengeSolutionTransaction(parameters);
|
|
312
|
-
const signedTransaction = await challengeTransaction.signTransaction();
|
|
313
|
-
if (!signedTransaction) {
|
|
314
|
-
throw new Error('Could not sign funding transaction.');
|
|
315
|
-
}
|
|
316
|
-
return {
|
|
317
|
-
tx: signedTransaction,
|
|
318
|
-
original: challengeTransaction,
|
|
319
|
-
estimatedFees: challengeTransaction.estimatedFees,
|
|
320
|
-
nextUTXOs: this.getUTXOAsTransaction(signedTransaction, parameters.to, 0),
|
|
321
|
-
};
|
|
322
|
-
}
|
|
323
295
|
async createFundTransaction(parameters) {
|
|
324
296
|
if (!parameters.to)
|
|
325
297
|
throw new Error('Field "to" not provided.');
|
|
@@ -2,9 +2,9 @@ import { IDeploymentParameters, IInteractionParameters } from '../interfaces/ITr
|
|
|
2
2
|
import { UTXO } from '../../utxo/interfaces/IUTXO.js';
|
|
3
3
|
import { DeploymentResult, InteractionResponse } from '../TransactionFactory';
|
|
4
4
|
import { ICustomTransactionParameters } from '../builders/CustomScriptTransaction.js';
|
|
5
|
-
export type InteractionParametersWithoutSigner = Omit<IInteractionParameters, 'signer' | '
|
|
6
|
-
export type IDeploymentParametersWithoutSigner = Omit<IDeploymentParameters, 'signer' | 'network' | '
|
|
7
|
-
export type CustomTransactionWithoutSigner = Omit<ICustomTransactionParameters, 'signer' | '
|
|
5
|
+
export type InteractionParametersWithoutSigner = Omit<IInteractionParameters, 'signer' | 'challenge'>;
|
|
6
|
+
export type IDeploymentParametersWithoutSigner = Omit<IDeploymentParameters, 'signer' | 'network' | 'challenge'>;
|
|
7
|
+
export type CustomTransactionWithoutSigner = Omit<ICustomTransactionParameters, 'signer' | 'challenge'>;
|
|
8
8
|
export interface BroadcastTransactionOptions {
|
|
9
9
|
raw: string;
|
|
10
10
|
psbt: boolean;
|
|
@@ -63,7 +63,7 @@ export interface Unisat {
|
|
|
63
63
|
switchNetwork(network: UnisatNetwork): Promise<void>;
|
|
64
64
|
getPublicKey(): Promise<string>;
|
|
65
65
|
getBalance(): Promise<Balance>;
|
|
66
|
-
signMessage(message: string, type?: MessageType): Promise<string>;
|
|
66
|
+
signMessage(message: string | Buffer, type?: MessageType): Promise<string>;
|
|
67
67
|
signData(hex: string, type?: SignatureType): Promise<string>;
|
|
68
68
|
pushTx(options: {
|
|
69
69
|
rawtx: string;
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { TransactionType } from '../enums/TransactionType.js';
|
|
2
|
-
import { IChallengeSolutionTransactionParameters } from '../interfaces/ITransactionParameters.js';
|
|
3
|
-
import { Psbt, PsbtInput, Signer } from '@btc-vision/bitcoin';
|
|
4
|
-
import { TransactionBuilder } from './TransactionBuilder.js';
|
|
5
|
-
import { ECPairInterface } from 'ecpair';
|
|
6
|
-
export declare class ChallengeSolutionTransaction extends TransactionBuilder<TransactionType.CHALLENGE_SOLUTION> {
|
|
7
|
-
readonly type: TransactionType.CHALLENGE_SOLUTION;
|
|
8
|
-
protected amount: bigint;
|
|
9
|
-
protected readonly challengeSolution: Buffer;
|
|
10
|
-
constructor(parameters: IChallengeSolutionTransactionParameters);
|
|
11
|
-
protected buildTransaction(): Promise<void>;
|
|
12
|
-
protected signInput(transaction: Psbt, input: PsbtInput, i: number, signer: Signer | ECPairInterface, reverse?: boolean, errored?: boolean): Promise<void>;
|
|
13
|
-
protected customFinalizerP2SH: (inputIndex: number, input: PsbtInput, scriptA: Buffer, isSegwit: boolean, isP2SH: boolean, isP2WSH: boolean) => {
|
|
14
|
-
finalScriptSig: Buffer | undefined;
|
|
15
|
-
finalScriptWitness: Buffer | undefined;
|
|
16
|
-
};
|
|
17
|
-
protected getSignerKey(): Signer | ECPairInterface;
|
|
18
|
-
}
|
|
@@ -1,51 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { getFinalScripts, opcodes, script } from '@btc-vision/bitcoin';
|
|
3
|
-
import { TransactionBuilder } from './TransactionBuilder.js';
|
|
4
|
-
export class ChallengeSolutionTransaction extends TransactionBuilder {
|
|
5
|
-
constructor(parameters) {
|
|
6
|
-
super(parameters);
|
|
7
|
-
this.type = TransactionType.CHALLENGE_SOLUTION;
|
|
8
|
-
this.customFinalizerP2SH = (inputIndex, input, scriptA, isSegwit, isP2SH, isP2WSH) => {
|
|
9
|
-
const inputDecoded = this.inputs[inputIndex];
|
|
10
|
-
if (isP2SH && inputDecoded && inputDecoded.redeemScript) {
|
|
11
|
-
const scriptSig = script.compile([this.challengeSolution, inputDecoded.redeemScript]);
|
|
12
|
-
return {
|
|
13
|
-
finalScriptSig: scriptSig,
|
|
14
|
-
finalScriptWitness: undefined,
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
return getFinalScripts(inputIndex, input, scriptA, isSegwit, isP2SH, isP2WSH, false);
|
|
18
|
-
};
|
|
19
|
-
this.amount = parameters.amount;
|
|
20
|
-
this.challengeSolution = parameters.challengeSolution;
|
|
21
|
-
this.internalInit();
|
|
22
|
-
}
|
|
23
|
-
async buildTransaction() {
|
|
24
|
-
if (!this.to) {
|
|
25
|
-
throw new Error('Recipient address is required');
|
|
26
|
-
}
|
|
27
|
-
this.addInputsFromUTXO();
|
|
28
|
-
if (this.isPubKeyDestination) {
|
|
29
|
-
const pubKeyScript = script.compile([
|
|
30
|
-
Buffer.from(this.to.replace('0x', ''), 'hex'),
|
|
31
|
-
opcodes.OP_CHECKSIG,
|
|
32
|
-
]);
|
|
33
|
-
this.addOutput({
|
|
34
|
-
value: Number(this.amount),
|
|
35
|
-
script: pubKeyScript,
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
else {
|
|
39
|
-
this.addOutput({
|
|
40
|
-
value: Number(this.amount),
|
|
41
|
-
address: this.to,
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
await this.addRefundOutput(this.amount + this.addOptionalOutputsAndGetAmount());
|
|
45
|
-
}
|
|
46
|
-
async signInput(transaction, input, i, signer, reverse = false, errored = false) {
|
|
47
|
-
}
|
|
48
|
-
getSignerKey() {
|
|
49
|
-
return this.signer;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
1
|
+
"use strict";
|
|
@@ -3,7 +3,7 @@ import { TransactionType } from '../enums/TransactionType.js';
|
|
|
3
3
|
import { TapLeafScript } from '../interfaces/Tap.js';
|
|
4
4
|
import { SharedInteractionParameters } from '../interfaces/ITransactionParameters.js';
|
|
5
5
|
import { TransactionBuilder } from './TransactionBuilder.js';
|
|
6
|
-
export interface ICustomTransactionParameters extends SharedInteractionParameters {
|
|
6
|
+
export interface ICustomTransactionParameters extends Omit<SharedInteractionParameters, 'challenge'> {
|
|
7
7
|
script: (Buffer | Stack)[];
|
|
8
8
|
witnesses: Buffer[];
|
|
9
9
|
annex?: Buffer;
|