@btc-vision/transaction 1.2.1 → 1.2.3
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/ContractAddress.d.ts +1 -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 +47 -0
- package/build/opnet.d.ts +4 -0
- package/build/opnet.js +4 -0
- package/build/transaction/ContractAddress.d.ts +1 -0
- package/build/transaction/ContractAddress.js +4 -1
- 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 +63 -0
- package/src/opnet.ts +5 -0
- package/src/transaction/ContractAddress.ts +5 -1
- 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
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { address, toXOnly } from '@btc-vision/bitcoin';
|
|
2
|
-
import { TransactionBuilder } from './TransactionBuilder.js';
|
|
2
|
+
import { MINIMUM_AMOUNT_CA, MINIMUM_AMOUNT_REWARD, TransactionBuilder } from './TransactionBuilder.js';
|
|
3
3
|
import { CalldataGenerator } from '../../generators/builders/CalldataGenerator.js';
|
|
4
4
|
import { Compressor } from '../../bytecode/Compressor.js';
|
|
5
5
|
import { EcKeyPair } from '../../keypair/EcKeyPair.js';
|
|
6
6
|
import { BitcoinUtils } from '../../utils/BitcoinUtils.js';
|
|
7
|
+
import { ChallengeGenerator } from '../mineable/ChallengeGenerator.js';
|
|
7
8
|
export class SharedInteractionTransaction extends TransactionBuilder {
|
|
8
9
|
constructor(parameters) {
|
|
9
10
|
super(parameters);
|
|
@@ -27,7 +28,9 @@ export class SharedInteractionTransaction extends TransactionBuilder {
|
|
|
27
28
|
if (!parameters.calldata) {
|
|
28
29
|
throw new Error('Calldata is required');
|
|
29
30
|
}
|
|
31
|
+
this.preimage = parameters.preimage || BitcoinUtils.getSafeRandomValues(128);
|
|
30
32
|
this.disableAutoRefund = parameters.disableAutoRefund || false;
|
|
33
|
+
this.rewardChallenge = ChallengeGenerator.generateMineableReward(this.preimage, this.network);
|
|
31
34
|
this.calldata = Compressor.compress(parameters.calldata);
|
|
32
35
|
this.randomBytes = parameters.randomBytes || BitcoinUtils.rndBytes();
|
|
33
36
|
this.scriptSigner = this.generateKeyPairFromSeed();
|
|
@@ -39,6 +42,9 @@ export class SharedInteractionTransaction extends TransactionBuilder {
|
|
|
39
42
|
getRndBytes() {
|
|
40
43
|
return this.randomBytes;
|
|
41
44
|
}
|
|
45
|
+
getPreimage() {
|
|
46
|
+
return this.preimage;
|
|
47
|
+
}
|
|
42
48
|
generateSecret() {
|
|
43
49
|
if (!this.to)
|
|
44
50
|
throw new Error('To address is required');
|
|
@@ -51,8 +57,6 @@ export class SharedInteractionTransaction extends TransactionBuilder {
|
|
|
51
57
|
return EcKeyPair.fromSeedKeyPair(this.randomBytes, this.network);
|
|
52
58
|
}
|
|
53
59
|
async buildTransaction() {
|
|
54
|
-
if (!this.to)
|
|
55
|
-
throw new Error('To address is required');
|
|
56
60
|
const selectedRedeem = this.scriptSigner
|
|
57
61
|
? this.targetScriptRedeem
|
|
58
62
|
: this.leftOverFundsScriptRedeem;
|
|
@@ -73,15 +77,7 @@ export class SharedInteractionTransaction extends TransactionBuilder {
|
|
|
73
77
|
if (!this.regenerated) {
|
|
74
78
|
this.addInputsFromUTXO();
|
|
75
79
|
}
|
|
76
|
-
|
|
77
|
-
this.addOutput({
|
|
78
|
-
value: Number(amountSpent),
|
|
79
|
-
address: this.to,
|
|
80
|
-
});
|
|
81
|
-
const amount = this.addOptionalOutputsAndGetAmount();
|
|
82
|
-
if (!this.disableAutoRefund) {
|
|
83
|
-
await this.addRefundOutput(amountSpent + amount);
|
|
84
|
-
}
|
|
80
|
+
await this.createMineableRewardOutputs();
|
|
85
81
|
}
|
|
86
82
|
async signInputs(transaction) {
|
|
87
83
|
if (!this.scriptSigner) {
|
|
@@ -125,7 +121,6 @@ export class SharedInteractionTransaction extends TransactionBuilder {
|
|
|
125
121
|
}
|
|
126
122
|
return [
|
|
127
123
|
this.contractSecret,
|
|
128
|
-
this.internalPubKeyToXOnly(),
|
|
129
124
|
input.tapScriptSig[0].signature,
|
|
130
125
|
input.tapScriptSig[1].signature,
|
|
131
126
|
];
|
|
@@ -159,6 +154,33 @@ export class SharedInteractionTransaction extends TransactionBuilder {
|
|
|
159
154
|
}
|
|
160
155
|
}
|
|
161
156
|
}
|
|
157
|
+
async createMineableRewardOutputs() {
|
|
158
|
+
if (!this.to)
|
|
159
|
+
throw new Error('To address is required');
|
|
160
|
+
const amountSpent = this.getTransactionOPNetFee();
|
|
161
|
+
let amountToCA;
|
|
162
|
+
if (amountSpent > MINIMUM_AMOUNT_REWARD + MINIMUM_AMOUNT_CA) {
|
|
163
|
+
amountToCA = MINIMUM_AMOUNT_CA;
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
amountToCA = amountSpent;
|
|
167
|
+
}
|
|
168
|
+
this.addOutput({
|
|
169
|
+
value: Number(amountToCA),
|
|
170
|
+
address: this.to,
|
|
171
|
+
});
|
|
172
|
+
if (amountToCA === MINIMUM_AMOUNT_CA &&
|
|
173
|
+
amountSpent - MINIMUM_AMOUNT_CA > MINIMUM_AMOUNT_REWARD) {
|
|
174
|
+
this.addOutput({
|
|
175
|
+
value: Number(amountSpent - amountToCA),
|
|
176
|
+
address: this.rewardChallenge.address,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
const amount = this.addOptionalOutputsAndGetAmount();
|
|
180
|
+
if (!this.disableAutoRefund) {
|
|
181
|
+
await this.addRefundOutput(amountSpent + amount);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
162
184
|
async signInputsNonWalletBased(transaction) {
|
|
163
185
|
for (let i = 0; i < transaction.data.inputs.length; i++) {
|
|
164
186
|
if (i === 0) {
|
|
@@ -6,6 +6,8 @@ import { UTXO } from '../../utxo/interfaces/IUTXO.js';
|
|
|
6
6
|
import { ECPairInterface } from 'ecpair';
|
|
7
7
|
import { TweakedTransaction } from '../shared/TweakedTransaction.js';
|
|
8
8
|
import { UnisatSigner } from '../browser/extensions/UnisatSigner.js';
|
|
9
|
+
export declare const MINIMUM_AMOUNT_REWARD: bigint;
|
|
10
|
+
export declare const MINIMUM_AMOUNT_CA: bigint;
|
|
9
11
|
export declare abstract class TransactionBuilder<T extends TransactionType> extends TweakedTransaction {
|
|
10
12
|
static readonly LOCK_LEAF_SCRIPT: Buffer;
|
|
11
13
|
static readonly MINIMUM_DUST: bigint;
|
|
@@ -4,6 +4,8 @@ import { EcKeyPair } from '../../keypair/EcKeyPair.js';
|
|
|
4
4
|
import { AddressVerificator } from '../../keypair/AddressVerificator.js';
|
|
5
5
|
import { TweakedTransaction } from '../shared/TweakedTransaction.js';
|
|
6
6
|
initEccLib(ecc);
|
|
7
|
+
export const MINIMUM_AMOUNT_REWARD = 540n;
|
|
8
|
+
export const MINIMUM_AMOUNT_CA = 330n;
|
|
7
9
|
export class TransactionBuilder extends TweakedTransaction {
|
|
8
10
|
constructor(parameters) {
|
|
9
11
|
super(parameters);
|
|
@@ -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.3",
|
|
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,63 @@
|
|
|
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 this.network === networks.testnet || this.network === networks.regtest;
|
|
62
|
+
}
|
|
63
|
+
}
|
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';
|
|
@@ -4,10 +4,14 @@ class ContractAddressBase {
|
|
|
4
4
|
private readonly deriver: Secp256k1PointDeriver = new Secp256k1PointDeriver();
|
|
5
5
|
|
|
6
6
|
public generateHybridKeyFromHash(input: Buffer): Buffer {
|
|
7
|
-
const p = this.deriver.findOrDeriveValidPoint(
|
|
7
|
+
const p = this.deriver.findOrDeriveValidPoint(this.cloneBuffer(input), false);
|
|
8
8
|
const y = this.deriver.getCanonicalY(p.y1, p.y2);
|
|
9
9
|
return Buffer.from(this.deriver.getHybridPublicKey(p.x, y));
|
|
10
10
|
}
|
|
11
|
+
|
|
12
|
+
private cloneBuffer(buffer: Buffer): Buffer {
|
|
13
|
+
return Buffer.from(buffer);
|
|
14
|
+
}
|
|
11
15
|
}
|
|
12
16
|
|
|
13
17
|
export const ContractAddress = new ContractAddressBase();
|