@btc-vision/transaction 1.2.2 → 1.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/browser/_version.d.ts +1 -1
- package/browser/crypto/crypto-browser.d.ts +1 -1
- package/browser/generators/builders/CalldataGenerator.d.ts +1 -1
- package/browser/generators/builders/DeploymentGenerator.d.ts +1 -1
- package/browser/generators/builders/MineableReward.d.ts +7 -0
- package/browser/index.js +1 -1
- package/browser/opnet.d.ts +4 -0
- package/browser/transaction/TransactionFactory.d.ts +19 -4
- package/browser/transaction/browser/WalletConnection.d.ts +18 -0
- package/browser/transaction/browser/types/Xverse.d.ts +24 -10
- package/browser/transaction/builders/ChallengeSolutionTransaction.d.ts +18 -0
- package/browser/transaction/builders/DeploymentTransaction.d.ts +4 -0
- package/browser/transaction/builders/SharedInteractionTransaction.d.ts +5 -0
- package/browser/transaction/builders/TransactionBuilder.d.ts +2 -0
- package/browser/transaction/enums/TransactionType.d.ts +3 -4
- package/browser/transaction/interfaces/ITransactionParameters.d.ts +6 -0
- package/browser/transaction/mineable/ChallengeGenerator.d.ts +9 -0
- package/browser/utxo/interfaces/IUTXO.d.ts +1 -1
- package/browser/verification/TapscriptVerificator.d.ts +1 -1
- package/build/_version.d.ts +1 -1
- package/build/_version.js +1 -1
- package/build/generators/Generator.js +1 -1
- package/build/generators/builders/CalldataGenerator.d.ts +1 -1
- package/build/generators/builders/CalldataGenerator.js +7 -26
- package/build/generators/builders/DeploymentGenerator.d.ts +1 -1
- package/build/generators/builders/DeploymentGenerator.js +9 -6
- package/build/generators/builders/LegacyCalldataGenerator.js +5 -1
- package/build/generators/builders/MineableReward.d.ts +7 -0
- package/build/generators/builders/MineableReward.js +48 -0
- package/build/opnet.d.ts +4 -0
- package/build/opnet.js +4 -0
- package/build/transaction/TransactionFactory.d.ts +19 -4
- package/build/transaction/TransactionFactory.js +32 -0
- package/build/transaction/browser/WalletConnection.d.ts +18 -0
- package/build/transaction/browser/WalletConnection.js +95 -0
- package/build/transaction/browser/extensions/UnisatSigner.js +5 -2
- package/build/transaction/browser/extensions/XverseSigner.js +15 -9
- package/build/transaction/browser/types/Xverse.d.ts +24 -10
- package/build/transaction/builders/ChallengeSolutionTransaction.d.ts +18 -0
- package/build/transaction/builders/ChallengeSolutionTransaction.js +51 -0
- package/build/transaction/builders/DeploymentTransaction.d.ts +4 -0
- package/build/transaction/builders/DeploymentTransaction.js +23 -4
- package/build/transaction/builders/InteractionTransaction.js +1 -1
- package/build/transaction/builders/SharedInteractionTransaction.d.ts +5 -0
- package/build/transaction/builders/SharedInteractionTransaction.js +35 -13
- package/build/transaction/builders/TransactionBuilder.d.ts +2 -0
- package/build/transaction/builders/TransactionBuilder.js +2 -0
- package/build/transaction/enums/TransactionType.d.ts +3 -4
- package/build/transaction/enums/TransactionType.js +3 -4
- package/build/transaction/interfaces/ITransactionParameters.d.ts +6 -0
- package/build/transaction/mineable/ChallengeGenerator.d.ts +9 -0
- package/build/transaction/mineable/ChallengeGenerator.js +28 -0
- package/build/transaction/shared/TweakedTransaction.js +1 -1
- package/build/utxo/interfaces/IUTXO.d.ts +1 -1
- package/build/verification/TapscriptVerificator.d.ts +1 -1
- package/build/verification/TapscriptVerificator.js +2 -8
- package/package.json +3 -3
- package/src/_version.ts +1 -1
- package/src/generators/Generator.ts +1 -1
- package/src/generators/builders/CalldataGenerator.ts +10 -41
- package/src/generators/builders/DeploymentGenerator.ts +18 -7
- package/src/generators/builders/LegacyCalldataGenerator.ts +5 -1
- package/src/generators/builders/MineableReward.ts +66 -0
- package/src/opnet.ts +5 -0
- package/src/transaction/TransactionFactory.ts +66 -3
- package/src/transaction/browser/WalletConnection.ts +110 -0
- package/src/transaction/browser/extensions/UnisatSigner.ts +7 -3
- package/src/transaction/browser/extensions/XverseSigner.ts +24 -23
- package/src/transaction/browser/types/Xverse.ts +50 -36
- package/src/transaction/builders/ChallengeSolutionTransaction.ts +88 -0
- package/src/transaction/builders/DeploymentTransaction.ts +46 -3
- package/src/transaction/builders/InteractionTransaction.ts +1 -0
- package/src/transaction/builders/SharedInteractionTransaction.ts +54 -14
- package/src/transaction/builders/TransactionBuilder.ts +3 -0
- package/src/transaction/enums/TransactionType.ts +3 -4
- package/src/transaction/interfaces/ITransactionParameters.ts +8 -15
- package/src/transaction/mineable/ChallengeGenerator.ts +39 -0
- package/src/transaction/shared/TweakedTransaction.ts +1 -1
- package/src/utxo/interfaces/IUTXO.ts +1 -1
- package/src/verification/TapscriptVerificator.ts +3 -18
|
@@ -4,8 +4,7 @@ export var TransactionType;
|
|
|
4
4
|
TransactionType[TransactionType["FUNDING"] = 1] = "FUNDING";
|
|
5
5
|
TransactionType[TransactionType["DEPLOYMENT"] = 2] = "DEPLOYMENT";
|
|
6
6
|
TransactionType[TransactionType["INTERACTION"] = 3] = "INTERACTION";
|
|
7
|
-
TransactionType[TransactionType["
|
|
8
|
-
TransactionType[TransactionType["
|
|
9
|
-
TransactionType[TransactionType["
|
|
10
|
-
TransactionType[TransactionType["CUSTOM_CODE"] = 7] = "CUSTOM_CODE";
|
|
7
|
+
TransactionType[TransactionType["MULTI_SIG"] = 4] = "MULTI_SIG";
|
|
8
|
+
TransactionType[TransactionType["CUSTOM_CODE"] = 5] = "CUSTOM_CODE";
|
|
9
|
+
TransactionType[TransactionType["CHALLENGE_SOLUTION"] = 6] = "CHALLENGE_SOLUTION";
|
|
11
10
|
})(TransactionType || (TransactionType = {}));
|
|
@@ -17,9 +17,14 @@ export interface IFundingTransactionParameters extends ITransactionParameters {
|
|
|
17
17
|
amount: bigint;
|
|
18
18
|
splitInputsInto?: number;
|
|
19
19
|
}
|
|
20
|
+
export interface IChallengeSolutionTransactionParameters extends ITransactionParameters {
|
|
21
|
+
amount: bigint;
|
|
22
|
+
readonly challengeSolution: Buffer;
|
|
23
|
+
}
|
|
20
24
|
export interface SharedInteractionParameters extends ITransactionParameters {
|
|
21
25
|
calldata?: Buffer;
|
|
22
26
|
disableAutoRefund?: boolean;
|
|
27
|
+
readonly preimage?: Buffer;
|
|
23
28
|
readonly randomBytes?: Buffer;
|
|
24
29
|
}
|
|
25
30
|
export interface IInteractionParameters extends SharedInteractionParameters {
|
|
@@ -30,4 +35,5 @@ export interface IDeploymentParameters extends Omit<ITransactionParameters, 'to'
|
|
|
30
35
|
readonly bytecode: Buffer;
|
|
31
36
|
readonly calldata?: Buffer;
|
|
32
37
|
readonly randomBytes?: Buffer;
|
|
38
|
+
readonly preimage?: Buffer;
|
|
33
39
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
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
|
+
}
|
|
@@ -24,7 +24,7 @@ export class TweakedTransaction extends Logger {
|
|
|
24
24
|
this.customFinalizerP2SH = (inputIndex, input, scriptA, isSegwit, isP2SH, isP2WSH) => {
|
|
25
25
|
const inputDecoded = this.inputs[inputIndex];
|
|
26
26
|
if (isP2SH && input.partialSig && inputDecoded && inputDecoded.redeemScript) {
|
|
27
|
-
const signatures = input.partialSig.map((sig) => sig.signature);
|
|
27
|
+
const signatures = input.partialSig.map((sig) => sig.signature) || [];
|
|
28
28
|
const scriptSig = script.compile([...signatures, inputDecoded.redeemScript]);
|
|
29
29
|
return {
|
|
30
30
|
finalScriptSig: scriptSig,
|
|
@@ -4,6 +4,7 @@ export interface ContractAddressVerificationParams {
|
|
|
4
4
|
readonly contractSaltPubKey: Buffer;
|
|
5
5
|
readonly originalSalt: Buffer;
|
|
6
6
|
readonly bytecode: Buffer;
|
|
7
|
+
readonly preimage: Buffer;
|
|
7
8
|
readonly calldata?: Buffer;
|
|
8
9
|
readonly network?: Network;
|
|
9
10
|
}
|
|
@@ -12,6 +13,5 @@ export declare class TapscriptVerificator {
|
|
|
12
13
|
static getContractAddress(params: ContractAddressVerificationParams): string | undefined;
|
|
13
14
|
static verifyControlBlock(params: ContractAddressVerificationParams, controlBlock: Buffer): boolean;
|
|
14
15
|
static getContractSeed(deployerPubKey: Buffer, bytecode: Buffer, saltHash: Buffer): Buffer;
|
|
15
|
-
static generateContractVirtualAddress(deployerPubKey: Buffer, bytecode: Buffer, saltHash: Buffer, network?: Network): string;
|
|
16
16
|
static generateAddressFromScript(params: ContractAddressVerificationParams, scriptTree: Taptree): string | undefined;
|
|
17
17
|
}
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { crypto as bitCrypto, networks, payments, toXOnly, } from '@btc-vision/bitcoin';
|
|
2
2
|
import { DeploymentGenerator } from '../generators/builders/DeploymentGenerator.js';
|
|
3
3
|
import { TransactionBuilder } from '../transaction/builders/TransactionBuilder.js';
|
|
4
|
-
import { Address } from '../keypair/Address.js';
|
|
5
4
|
export class TapscriptVerificator {
|
|
6
5
|
static getContractAddress(params) {
|
|
7
6
|
const network = params.network || networks.bitcoin;
|
|
8
7
|
const scriptBuilder = new DeploymentGenerator(params.deployerPubKey, toXOnly(params.contractSaltPubKey), network);
|
|
9
|
-
const compiledTargetScript = scriptBuilder.compile(params.bytecode, params.originalSalt, params.calldata);
|
|
8
|
+
const compiledTargetScript = scriptBuilder.compile(params.bytecode, params.originalSalt, params.preimage, params.calldata);
|
|
10
9
|
const scriptTree = [
|
|
11
10
|
{
|
|
12
11
|
output: compiledTargetScript,
|
|
@@ -22,7 +21,7 @@ export class TapscriptVerificator {
|
|
|
22
21
|
static verifyControlBlock(params, controlBlock) {
|
|
23
22
|
const network = params.network || networks.bitcoin;
|
|
24
23
|
const scriptBuilder = new DeploymentGenerator(params.deployerPubKey, toXOnly(params.contractSaltPubKey), network);
|
|
25
|
-
const compiledTargetScript = scriptBuilder.compile(params.bytecode, params.originalSalt, params.calldata);
|
|
24
|
+
const compiledTargetScript = scriptBuilder.compile(params.bytecode, params.originalSalt, params.preimage, params.calldata);
|
|
26
25
|
const scriptTree = [
|
|
27
26
|
{
|
|
28
27
|
output: compiledTargetScript,
|
|
@@ -55,11 +54,6 @@ export class TapscriptVerificator {
|
|
|
55
54
|
const buf = Buffer.concat([deployerPubKey, saltHash, sha256OfBytecode]);
|
|
56
55
|
return bitCrypto.hash256(buf);
|
|
57
56
|
}
|
|
58
|
-
static generateContractVirtualAddress(deployerPubKey, bytecode, saltHash, network = networks.bitcoin) {
|
|
59
|
-
const virtualAddress = TapscriptVerificator.getContractSeed(deployerPubKey, bytecode, saltHash);
|
|
60
|
-
const address = new Address(virtualAddress);
|
|
61
|
-
return address.p2tr(network);
|
|
62
|
-
}
|
|
63
57
|
static generateAddressFromScript(params, scriptTree) {
|
|
64
58
|
const network = params.network || networks.bitcoin;
|
|
65
59
|
const transactionData = {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@btc-vision/transaction",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.2.
|
|
4
|
+
"version": "1.2.4",
|
|
5
5
|
"author": "BlobMaster41",
|
|
6
6
|
"description": "OPNet transaction library allows you to create and sign transactions for the OPNet network.",
|
|
7
7
|
"engines": {
|
|
@@ -89,8 +89,8 @@
|
|
|
89
89
|
"dependencies": {
|
|
90
90
|
"@babel/plugin-proposal-object-rest-spread": "^7.20.7",
|
|
91
91
|
"@bitcoinerlab/secp256k1": "^1.1.1",
|
|
92
|
-
"@btc-vision/bitcoin": "^6.3.
|
|
93
|
-
"@btc-vision/
|
|
92
|
+
"@btc-vision/bitcoin": "^6.3.3",
|
|
93
|
+
"@btc-vision/bitcoin-rpc": "^1.0.0",
|
|
94
94
|
"@btc-vision/logger": "^1.0.6",
|
|
95
95
|
"@eslint/js": "^9.14.0",
|
|
96
96
|
"@noble/secp256k1": "^2.1.0",
|
package/src/_version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '1.2.
|
|
1
|
+
export const version = '1.2.3';
|
|
@@ -10,7 +10,7 @@ export abstract class Generator {
|
|
|
10
10
|
/**
|
|
11
11
|
* The magic number of OPNet
|
|
12
12
|
*/
|
|
13
|
-
public static readonly MAGIC: Buffer = Buffer.from('
|
|
13
|
+
public static readonly MAGIC: Buffer = Buffer.from('op', 'utf-8');
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* The public key of the sender
|
|
@@ -56,18 +56,16 @@ export class CalldataGenerator extends Generator {
|
|
|
56
56
|
* Compile an interaction bitcoin script
|
|
57
57
|
* @param {Buffer} calldata - The calldata to use
|
|
58
58
|
* @param {Buffer} contractSecret - The contract secret
|
|
59
|
+
* @param preimage
|
|
59
60
|
* @param {number[]} [features=[]] - The features to use (optional)
|
|
60
|
-
* @param {Buffer[]} [vaultPublicKeys=[]] - The public keys of the vault (optional)
|
|
61
|
-
* @param {number} [minimumSignatures=0] - The minimum number of signatures (optional)
|
|
62
61
|
* @returns {Buffer} - The compiled script
|
|
63
62
|
* @throws {Error} - If something goes wrong
|
|
64
63
|
*/
|
|
65
64
|
public compile(
|
|
66
65
|
calldata: Buffer,
|
|
67
66
|
contractSecret: Buffer,
|
|
67
|
+
preimage: Buffer,
|
|
68
68
|
features: Features[] = [],
|
|
69
|
-
vaultPublicKeys: Buffer[] = [],
|
|
70
|
-
minimumSignatures: number = 0,
|
|
71
69
|
): Buffer {
|
|
72
70
|
if (!this.contractSaltPubKey) throw new Error('Contract salt public key not set');
|
|
73
71
|
|
|
@@ -78,16 +76,20 @@ export class CalldataGenerator extends Generator {
|
|
|
78
76
|
this.senderFirstByte,
|
|
79
77
|
opcodes.OP_TOALTSTACK,
|
|
80
78
|
|
|
79
|
+
// CHALLENGE PREIMAGE FOR REWARD,
|
|
80
|
+
preimage,
|
|
81
|
+
opcodes.OP_TOALTSTACK,
|
|
82
|
+
|
|
81
83
|
this.xSenderPubKey,
|
|
84
|
+
opcodes.OP_DUP,
|
|
85
|
+
opcodes.OP_HASH256,
|
|
86
|
+
crypto.hash256(this.xSenderPubKey),
|
|
87
|
+
opcodes.OP_EQUALVERIFY,
|
|
82
88
|
opcodes.OP_CHECKSIGVERIFY,
|
|
83
89
|
|
|
84
90
|
this.contractSaltPubKey,
|
|
85
91
|
opcodes.OP_CHECKSIGVERIFY,
|
|
86
92
|
|
|
87
|
-
opcodes.OP_HASH160,
|
|
88
|
-
crypto.hash160(this.xSenderPubKey),
|
|
89
|
-
opcodes.OP_EQUALVERIFY,
|
|
90
|
-
|
|
91
93
|
opcodes.OP_HASH160,
|
|
92
94
|
crypto.hash160(contractSecret),
|
|
93
95
|
opcodes.OP_EQUALVERIFY,
|
|
@@ -100,39 +102,6 @@ export class CalldataGenerator extends Generator {
|
|
|
100
102
|
Generator.MAGIC,
|
|
101
103
|
];
|
|
102
104
|
|
|
103
|
-
// write pub keys, when requested.
|
|
104
|
-
if (vaultPublicKeys.length > 0) {
|
|
105
|
-
const pubKeyBuffer = CalldataGenerator.getPubKeyAsBuffer(vaultPublicKeys, this.network);
|
|
106
|
-
const pubKeyDataChunks: Buffer[][] = this.splitBufferIntoChunks(pubKeyBuffer);
|
|
107
|
-
|
|
108
|
-
compiledData = compiledData.concat(
|
|
109
|
-
...[
|
|
110
|
-
opcodes.OP_0, // provide opnet public keys
|
|
111
|
-
...pubKeyDataChunks,
|
|
112
|
-
],
|
|
113
|
-
);
|
|
114
|
-
|
|
115
|
-
if (minimumSignatures) {
|
|
116
|
-
// verify that the minimum is not greater than 255
|
|
117
|
-
if (minimumSignatures > 255) {
|
|
118
|
-
throw new Error('Minimum signatures cannot exceed 255');
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// we use a 2 bytes buffer even if we limit to 255 so it does not use an opcode for the number
|
|
122
|
-
const minSigBuffer = Buffer.alloc(2);
|
|
123
|
-
minSigBuffer.writeUint16LE(minimumSignatures, 0);
|
|
124
|
-
|
|
125
|
-
compiledData = compiledData.concat(
|
|
126
|
-
...[
|
|
127
|
-
opcodes.OP_1, // provide minimum signatures
|
|
128
|
-
minSigBuffer,
|
|
129
|
-
],
|
|
130
|
-
);
|
|
131
|
-
} else {
|
|
132
|
-
throw new Error('Minimum signatures must be provided');
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
105
|
const featureOpcodes = features.map((feature) => FeatureOpCodes[feature]); // Get the opcodes for the features
|
|
137
106
|
|
|
138
107
|
// Write calldata
|
|
@@ -14,11 +14,17 @@ export class DeploymentGenerator extends Generator {
|
|
|
14
14
|
* Compile a bitcoin script representing a contract deployment
|
|
15
15
|
* @param {Buffer} contractBytecode - The contract bytecode
|
|
16
16
|
* @param {Buffer} contractSalt - The contract salt
|
|
17
|
+
* @param {Buffer} preimage - The preimage for reward
|
|
17
18
|
* @param {Buffer} [calldata] - The calldata to be passed to the contract
|
|
18
19
|
* @returns {Buffer} - The compiled script
|
|
19
20
|
*/
|
|
20
|
-
public compile(
|
|
21
|
-
|
|
21
|
+
public compile(
|
|
22
|
+
contractBytecode: Buffer,
|
|
23
|
+
contractSalt: Buffer,
|
|
24
|
+
preimage: Buffer,
|
|
25
|
+
calldata?: Buffer,
|
|
26
|
+
): Buffer {
|
|
27
|
+
const asm = this.getAsm(contractBytecode, contractSalt, preimage, calldata);
|
|
22
28
|
const compiled = script.compile(asm);
|
|
23
29
|
|
|
24
30
|
/**
|
|
@@ -35,27 +41,32 @@ export class DeploymentGenerator extends Generator {
|
|
|
35
41
|
private getAsm(
|
|
36
42
|
contractBytecode: Buffer,
|
|
37
43
|
contractSalt: Buffer,
|
|
44
|
+
preimage: Buffer,
|
|
38
45
|
calldata?: Buffer,
|
|
39
46
|
): (number | Buffer)[] {
|
|
40
47
|
if (!this.contractSaltPubKey) throw new Error('Contract salt public key not set');
|
|
41
48
|
|
|
42
49
|
const dataChunks: Buffer[][] = this.splitBufferIntoChunks(contractBytecode);
|
|
43
50
|
const calldataChunks: Buffer[][] = calldata ? this.splitBufferIntoChunks(calldata) : [];
|
|
44
|
-
|
|
51
|
+
|
|
45
52
|
const compiledData = [
|
|
46
53
|
this.senderFirstByte,
|
|
47
54
|
opcodes.OP_TOALTSTACK,
|
|
48
55
|
|
|
56
|
+
// CHALLENGE PREIMAGE FOR REWARD,
|
|
57
|
+
preimage,
|
|
58
|
+
opcodes.OP_TOALTSTACK,
|
|
59
|
+
|
|
49
60
|
this.xSenderPubKey,
|
|
61
|
+
opcodes.OP_DUP,
|
|
62
|
+
opcodes.OP_HASH256,
|
|
63
|
+
crypto.hash256(this.xSenderPubKey),
|
|
64
|
+
opcodes.OP_EQUALVERIFY,
|
|
50
65
|
opcodes.OP_CHECKSIGVERIFY,
|
|
51
66
|
|
|
52
67
|
this.contractSaltPubKey,
|
|
53
68
|
opcodes.OP_CHECKSIGVERIFY,
|
|
54
69
|
|
|
55
|
-
opcodes.OP_HASH160,
|
|
56
|
-
crypto.hash160(this.xSenderPubKey),
|
|
57
|
-
opcodes.OP_EQUALVERIFY,
|
|
58
|
-
|
|
59
70
|
opcodes.OP_HASH256,
|
|
60
71
|
crypto.hash256(contractSalt),
|
|
61
72
|
opcodes.OP_EQUALVERIFY,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Network, networks, opcodes, script } from '@btc-vision/bitcoin';
|
|
1
|
+
import { crypto, Network, networks, opcodes, script } from '@btc-vision/bitcoin';
|
|
2
2
|
import { ECPairInterface } from 'ecpair';
|
|
3
3
|
import { Compressor } from '../../bytecode/Compressor.js';
|
|
4
4
|
import { EcKeyPair } from '../../keypair/EcKeyPair.js';
|
|
@@ -70,6 +70,10 @@ export class LegacyCalldataGenerator extends Generator {
|
|
|
70
70
|
|
|
71
71
|
let compiledData = [
|
|
72
72
|
this.senderPubKey,
|
|
73
|
+
opcodes.OP_DUP,
|
|
74
|
+
opcodes.OP_HASH256,
|
|
75
|
+
crypto.hash256(this.senderPubKey),
|
|
76
|
+
opcodes.OP_EQUALVERIFY,
|
|
73
77
|
opcodes.OP_CHECKSIGVERIFY,
|
|
74
78
|
|
|
75
79
|
contractSecret,
|
|
@@ -0,0 +1,66 @@
|
|
|
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
|
+
}
|
package/src/opnet.ts
CHANGED
|
@@ -9,9 +9,12 @@ export * from './generators/builders/CustomGenerator.js';
|
|
|
9
9
|
export * from './generators/builders/DeploymentGenerator.js';
|
|
10
10
|
export * from './generators/builders/LegacyCalldataGenerator.js';
|
|
11
11
|
export * from './generators/builders/MultiSignGenerator.js';
|
|
12
|
+
export * from './generators/builders/MineableReward.js';
|
|
12
13
|
export * from './generators/Features.js';
|
|
13
14
|
export * from './generators/Generator.js';
|
|
14
15
|
|
|
16
|
+
export * from './transaction/mineable/ChallengeGenerator.js';
|
|
17
|
+
|
|
15
18
|
/** Address */
|
|
16
19
|
export * from './generators/AddressGenerator.js';
|
|
17
20
|
export * from './verification/TapscriptVerificator.js';
|
|
@@ -44,6 +47,7 @@ export * from './transaction/builders/InteractionTransaction.js';
|
|
|
44
47
|
export * from './transaction/builders/MultiSignTransaction.js';
|
|
45
48
|
export * from './transaction/builders/SharedInteractionTransaction.js';
|
|
46
49
|
export * from './transaction/builders/TransactionBuilder.js';
|
|
50
|
+
export * from './transaction/builders/ChallengeSolutionTransaction.js';
|
|
47
51
|
|
|
48
52
|
/** Utils */
|
|
49
53
|
export * from './utils/BitcoinUtils.js';
|
|
@@ -87,6 +91,7 @@ export * from './transaction/browser/extensions/UnisatSigner.js';
|
|
|
87
91
|
export * from './transaction/browser/extensions/XverseSigner.js';
|
|
88
92
|
export * from './transaction/browser/types/Unisat.js';
|
|
89
93
|
export * from './transaction/browser/types/Xverse.js';
|
|
94
|
+
export * from './transaction/browser/WalletConnection.js';
|
|
90
95
|
|
|
91
96
|
export * from './metadata/tokens.js';
|
|
92
97
|
export * from './transaction/browser/Web3Provider.js';
|
|
@@ -11,12 +11,14 @@ import { InteractionTransaction } from './builders/InteractionTransaction.js';
|
|
|
11
11
|
import { TransactionBuilder } from './builders/TransactionBuilder.js';
|
|
12
12
|
import { TransactionType } from './enums/TransactionType.js';
|
|
13
13
|
import {
|
|
14
|
+
IChallengeSolutionTransactionParameters,
|
|
14
15
|
IDeploymentParameters,
|
|
15
16
|
IFundingTransactionParameters,
|
|
16
17
|
IInteractionParameters,
|
|
17
18
|
ITransactionParameters,
|
|
18
19
|
} from './interfaces/ITransactionParameters.js';
|
|
19
20
|
import { PSBTTypes } from './psbt/PSBTTypes.js';
|
|
21
|
+
import { ChallengeSolutionTransaction } from './builders/ChallengeSolutionTransaction.js';
|
|
20
22
|
|
|
21
23
|
export interface DeploymentResult {
|
|
22
24
|
readonly transaction: [string, string];
|
|
@@ -25,6 +27,8 @@ export interface DeploymentResult {
|
|
|
25
27
|
readonly contractPubKey: string;
|
|
26
28
|
readonly p2trAddress: string;
|
|
27
29
|
|
|
30
|
+
readonly preimage: string;
|
|
31
|
+
|
|
28
32
|
readonly utxos: UTXO[];
|
|
29
33
|
}
|
|
30
34
|
|
|
@@ -43,13 +47,27 @@ export interface FundingTransactionResponse {
|
|
|
43
47
|
readonly nextUTXOs: UTXO[];
|
|
44
48
|
}
|
|
45
49
|
|
|
46
|
-
export interface
|
|
50
|
+
export interface ChallengeSolutionResponse {
|
|
51
|
+
readonly tx: Transaction;
|
|
52
|
+
readonly original: ChallengeSolutionTransaction;
|
|
53
|
+
readonly estimatedFees: bigint;
|
|
54
|
+
readonly nextUTXOs: UTXO[];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface BitcoinTransferBase {
|
|
47
58
|
readonly tx: string;
|
|
48
|
-
readonly original: FundingTransaction;
|
|
49
59
|
readonly estimatedFees: bigint;
|
|
50
60
|
readonly nextUTXOs: UTXO[];
|
|
51
61
|
}
|
|
52
62
|
|
|
63
|
+
export interface ChallengeSolution extends BitcoinTransferBase {
|
|
64
|
+
readonly original: ChallengeSolutionTransaction;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface BitcoinTransferResponse extends BitcoinTransferBase {
|
|
68
|
+
readonly original: FundingTransaction;
|
|
69
|
+
}
|
|
70
|
+
|
|
53
71
|
export class TransactionFactory {
|
|
54
72
|
/**
|
|
55
73
|
* @description Generate a transaction with a custom script.
|
|
@@ -127,7 +145,7 @@ export class TransactionFactory {
|
|
|
127
145
|
*/
|
|
128
146
|
public async signInteraction(
|
|
129
147
|
interactionParameters: IInteractionParameters,
|
|
130
|
-
): Promise<[string, string, UTXO[]]> {
|
|
148
|
+
): Promise<[string, string, UTXO[], string]> {
|
|
131
149
|
if (!interactionParameters.to) {
|
|
132
150
|
throw new Error('Field "to" not provided.');
|
|
133
151
|
}
|
|
@@ -185,6 +203,7 @@ export class TransactionFactory {
|
|
|
185
203
|
...interactionParameters,
|
|
186
204
|
utxos: this.getUTXOAsTransaction(signedTransaction.tx, interactionParameters.to, 0), // always 0
|
|
187
205
|
randomBytes: preTransaction.getRndBytes(),
|
|
206
|
+
preimage: preTransaction.getPreimage(),
|
|
188
207
|
nonWitnessUtxo: signedTransaction.tx.toBuffer(),
|
|
189
208
|
estimatedFees: preTransaction.estimatedFees,
|
|
190
209
|
};
|
|
@@ -197,6 +216,7 @@ export class TransactionFactory {
|
|
|
197
216
|
signedTransaction.tx.toHex(),
|
|
198
217
|
outTx.toHex(),
|
|
199
218
|
this.getUTXOAsTransaction(signedTransaction.tx, interactionParameters.from, 1), // always 1
|
|
219
|
+
preTransaction.getPreimage().toString('hex'),
|
|
200
220
|
];
|
|
201
221
|
}
|
|
202
222
|
|
|
@@ -244,6 +264,7 @@ export class TransactionFactory {
|
|
|
244
264
|
...deploymentParameters,
|
|
245
265
|
utxos: [newUtxo],
|
|
246
266
|
randomBytes: preTransaction.getRndBytes(),
|
|
267
|
+
preimage: preTransaction.getPreimage(),
|
|
247
268
|
nonWitnessUtxo: signedTransaction.toBuffer(),
|
|
248
269
|
optionalOutputs: [],
|
|
249
270
|
};
|
|
@@ -270,6 +291,7 @@ export class TransactionFactory {
|
|
|
270
291
|
contractPubKey: finalTransaction.contractPubKey,
|
|
271
292
|
p2trAddress: finalTransaction.p2trAddress,
|
|
272
293
|
utxos: [refundUTXO],
|
|
294
|
+
preimage: preTransaction.getPreimage().toString('hex'),
|
|
273
295
|
};
|
|
274
296
|
}
|
|
275
297
|
|
|
@@ -286,7 +308,27 @@ export class TransactionFactory {
|
|
|
286
308
|
}
|
|
287
309
|
|
|
288
310
|
const resp = await this.createFundTransaction(parameters);
|
|
311
|
+
return {
|
|
312
|
+
estimatedFees: resp.estimatedFees,
|
|
313
|
+
original: resp.original,
|
|
314
|
+
tx: resp.tx.toHex(),
|
|
315
|
+
nextUTXOs: this.getAllNewUTXOs(resp.original, resp.tx, parameters.from),
|
|
316
|
+
};
|
|
317
|
+
}
|
|
289
318
|
|
|
319
|
+
/**
|
|
320
|
+
* @description Creates a challenge solution transaction.
|
|
321
|
+
* @param {IChallengeSolutionTransactionParameters} parameters - The challenge solution transaction parameters
|
|
322
|
+
* @returns {Promise<ChallengeSolution>} - The signed transaction
|
|
323
|
+
*/
|
|
324
|
+
public async createChallengeSolution(
|
|
325
|
+
parameters: IChallengeSolutionTransactionParameters,
|
|
326
|
+
): Promise<ChallengeSolution> {
|
|
327
|
+
if (!parameters.from) {
|
|
328
|
+
throw new Error('Field "from" not provided.');
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
const resp = await this._createChallengeSolution(parameters);
|
|
290
332
|
return {
|
|
291
333
|
estimatedFees: resp.estimatedFees,
|
|
292
334
|
original: resp.original,
|
|
@@ -323,6 +365,27 @@ export class TransactionFactory {
|
|
|
323
365
|
return utxos;
|
|
324
366
|
}
|
|
325
367
|
|
|
368
|
+
private async _createChallengeSolution(
|
|
369
|
+
parameters: IChallengeSolutionTransactionParameters,
|
|
370
|
+
): Promise<ChallengeSolutionResponse> {
|
|
371
|
+
if (!parameters.to) throw new Error('Field "to" not provided.');
|
|
372
|
+
|
|
373
|
+
const challengeTransaction: ChallengeSolutionTransaction = new ChallengeSolutionTransaction(
|
|
374
|
+
parameters,
|
|
375
|
+
);
|
|
376
|
+
const signedTransaction: Transaction = await challengeTransaction.signTransaction();
|
|
377
|
+
if (!signedTransaction) {
|
|
378
|
+
throw new Error('Could not sign funding transaction.');
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
return {
|
|
382
|
+
tx: signedTransaction,
|
|
383
|
+
original: challengeTransaction,
|
|
384
|
+
estimatedFees: challengeTransaction.estimatedFees,
|
|
385
|
+
nextUTXOs: this.getUTXOAsTransaction(signedTransaction, parameters.to, 0),
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
|
|
326
389
|
private async createFundTransaction(
|
|
327
390
|
parameters: IFundingTransactionParameters,
|
|
328
391
|
): Promise<FundingTransactionResponse> {
|