@btc-vision/transaction 1.1.17 → 1.2.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/crypto/crypto-browser.d.ts +2 -2
- package/browser/index.js +1 -1
- package/browser/index.js.LICENSE.txt +2 -0
- package/browser/keypair/Address.d.ts +8 -0
- package/browser/keypair/Secp256k1PointDeriver.d.ts +16 -0
- package/browser/opnet.d.ts +2 -0
- package/browser/signer/SignerUtils.d.ts +0 -1
- package/browser/transaction/ContractAddress.d.ts +6 -0
- package/browser/transaction/builders/CustomScriptTransaction.d.ts +1 -1
- package/browser/transaction/builders/InteractionTransaction.d.ts +1 -1
- package/browser/transaction/builders/MultiSignTransaction.d.ts +3 -4
- package/browser/transaction/builders/SharedInteractionTransaction.d.ts +2 -3
- package/browser/verification/TapscriptVerificator.d.ts +1 -2
- package/build/_version.d.ts +1 -1
- package/build/_version.js +1 -1
- package/build/buffer/BinaryReader.js +2 -2
- package/build/buffer/BinaryWriter.js +1 -1
- package/build/generators/AddressGenerator.js +1 -2
- package/build/generators/Generator.js +1 -2
- package/build/generators/builders/CalldataGenerator.js +1 -1
- package/build/generators/builders/LegacyCalldataGenerator.js +1 -1
- package/build/generators/builders/MultiSignGenerator.js +1 -2
- package/build/keypair/Address.d.ts +8 -0
- package/build/keypair/Address.js +67 -7
- package/build/keypair/AddressVerificator.js +5 -2
- package/build/keypair/EcKeyPair.js +3 -4
- package/build/keypair/MessageSigner.js +1 -2
- package/build/keypair/Secp256k1PointDeriver.d.ts +16 -0
- package/build/keypair/Secp256k1PointDeriver.js +80 -0
- package/build/keypair/Wallet.js +1 -2
- package/build/opnet.d.ts +2 -0
- package/build/opnet.js +2 -0
- package/build/signer/SignerUtils.d.ts +0 -1
- package/build/signer/SignerUtils.js +1 -17
- package/build/signer/TweakedSigner.js +1 -3
- package/build/transaction/ContractAddress.d.ts +6 -0
- package/build/transaction/ContractAddress.js +12 -0
- package/build/transaction/browser/extensions/UnisatSigner.js +1 -2
- package/build/transaction/browser/extensions/XverseSigner.js +1 -2
- package/build/transaction/builders/CustomScriptTransaction.d.ts +1 -1
- package/build/transaction/builders/CustomScriptTransaction.js +1 -2
- package/build/transaction/builders/DeploymentTransaction.js +2 -2
- package/build/transaction/builders/FundingTransaction.js +2 -2
- package/build/transaction/builders/InteractionTransaction.d.ts +1 -1
- package/build/transaction/builders/MultiSignTransaction.d.ts +3 -4
- package/build/transaction/builders/MultiSignTransaction.js +1 -2
- package/build/transaction/builders/SharedInteractionTransaction.d.ts +2 -3
- package/build/transaction/builders/SharedInteractionTransaction.js +1 -2
- package/build/transaction/builders/TransactionBuilder.js +11 -2
- package/build/transaction/shared/TweakedTransaction.js +1 -4
- package/build/utils/BufferHelper.js +1 -1
- package/build/verification/TapscriptVerificator.d.ts +1 -2
- package/build/verification/TapscriptVerificator.js +1 -2
- package/package.json +9 -9
- package/src/_version.ts +1 -1
- package/src/buffer/BinaryReader.ts +2 -2
- package/src/buffer/BinaryWriter.ts +1 -1
- package/src/generators/AddressGenerator.ts +1 -2
- package/src/generators/Generator.ts +1 -2
- package/src/generators/builders/CalldataGenerator.ts +5 -1
- package/src/generators/builders/LegacyCalldataGenerator.ts +5 -1
- package/src/generators/builders/MultiSignGenerator.ts +1 -2
- package/src/keypair/Address.ts +91 -10
- package/src/keypair/AddressVerificator.ts +6 -2
- package/src/keypair/EcKeyPair.ts +14 -5
- package/src/keypair/MessageSigner.ts +1 -2
- package/src/keypair/Secp256k1PointDeriver.ts +170 -0
- package/src/keypair/Wallet.ts +1 -2
- package/src/opnet.ts +2 -0
- package/src/signer/SignerUtils.ts +7 -19
- package/src/signer/TweakedSigner.ts +1 -3
- package/src/transaction/ContractAddress.ts +13 -0
- package/src/transaction/TransactionFactory.ts +4 -5
- package/src/transaction/browser/extensions/UnisatSigner.ts +1 -1
- package/src/transaction/browser/extensions/XverseSigner.ts +1 -2
- package/src/transaction/builders/CustomScriptTransaction.ts +10 -3
- package/src/transaction/builders/DeploymentTransaction.ts +13 -3
- package/src/transaction/builders/FundingTransaction.ts +2 -2
- package/src/transaction/builders/InteractionTransaction.ts +1 -1
- package/src/transaction/builders/MultiSignTransaction.ts +2 -2
- package/src/transaction/builders/SharedInteractionTransaction.ts +1 -3
- package/src/transaction/builders/TransactionBuilder.ts +11 -1
- package/src/transaction/shared/TweakedTransaction.ts +9 -93
- package/src/utils/BufferHelper.ts +1 -1
- package/src/verification/TapscriptVerificator.ts +9 -3
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
const P = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fn;
|
|
2
|
+
|
|
3
|
+
export class Secp256k1PointDeriver {
|
|
4
|
+
/**
|
|
5
|
+
* The maximum increments to try before giving up on deriving a valid x.
|
|
6
|
+
*/
|
|
7
|
+
private maxTries: number;
|
|
8
|
+
|
|
9
|
+
constructor(maxTries = 10000) {
|
|
10
|
+
this.maxTries = maxTries;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Main entry point.
|
|
15
|
+
* Given a 32-byte input, ensures we obtain a "real" x on secp256k1.
|
|
16
|
+
* - If the given x is valid, we use it.
|
|
17
|
+
* - Otherwise, we increment x (mod p) until we find one whose (x^3 + 7) is a quadratic residue.
|
|
18
|
+
* Then we return { x, y1, y2 } for that valid point.
|
|
19
|
+
*
|
|
20
|
+
* @param xBytes A 32-byte Uint8Array for the candidate x
|
|
21
|
+
* @param failOnInvalidX (optional) whether to throw if the given x is not a valid curve point, defaults to true
|
|
22
|
+
* @param maxTries (optional) number of increments to attempt, defaults to this.maxTries
|
|
23
|
+
* @returns An object { x: bigint; y1: bigint; y2: bigint } describing a valid curve point
|
|
24
|
+
* @throws If no valid x found within maxTries
|
|
25
|
+
*/
|
|
26
|
+
public findOrDeriveValidPoint(
|
|
27
|
+
xBytes: Uint8Array,
|
|
28
|
+
failOnInvalidX: boolean = true,
|
|
29
|
+
maxTries: number = this.maxTries,
|
|
30
|
+
): { x: bigint; y1: bigint; y2: bigint } {
|
|
31
|
+
if (xBytes.length !== 32) {
|
|
32
|
+
throw new Error('xBytes must be exactly 32 bytes.');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Convert input to a BigInt in [0, p-1]
|
|
36
|
+
let xCandidate = this.bytesToBigInt(xBytes) % P;
|
|
37
|
+
|
|
38
|
+
// 2. Loop up to maxTries to find a valid x
|
|
39
|
+
let sqrtVal = this.isValidX(xCandidate);
|
|
40
|
+
if (failOnInvalidX && sqrtVal === null) {
|
|
41
|
+
throw new Error(`The given x is not a valid curve point.`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
let tries = 0;
|
|
45
|
+
while (sqrtVal === null) {
|
|
46
|
+
xCandidate = (xCandidate + 1n) % P;
|
|
47
|
+
sqrtVal = this.isValidX(xCandidate);
|
|
48
|
+
|
|
49
|
+
tries++;
|
|
50
|
+
if (tries > maxTries) {
|
|
51
|
+
throw new Error(`Could not find a valid X point within ${maxTries} increments.`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Now, sqrtVal is a valid 'r' for alpha = x^3 + 7
|
|
56
|
+
// The two roots for y are: r and p-r
|
|
57
|
+
const y1 = sqrtVal;
|
|
58
|
+
const y2 = (P - y1) % P;
|
|
59
|
+
|
|
60
|
+
return { x: xCandidate, y1, y2 };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Given two candidate y values, returns the one with the smaller y-coordinate.
|
|
65
|
+
* @param {bigint} y
|
|
66
|
+
* @param {bigint} y2
|
|
67
|
+
*/
|
|
68
|
+
public getCanonicalY(y: bigint, y2: bigint): bigint {
|
|
69
|
+
return y < y2 ? y : y2;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Creates a 65-byte "hybrid public key" from the specified x and y.
|
|
74
|
+
* - First byte:
|
|
75
|
+
* - 0x06 if y is even
|
|
76
|
+
* - 0x07 if y is odd
|
|
77
|
+
* - Next 32 bytes: x
|
|
78
|
+
* - Last 32 bytes: y
|
|
79
|
+
*
|
|
80
|
+
* @param x X-coordinate as a bigint
|
|
81
|
+
* @param y Y-coordinate as a bigint
|
|
82
|
+
* @returns A Uint8Array of length 65
|
|
83
|
+
*/
|
|
84
|
+
public getHybridPublicKey(x: bigint, y: bigint): Uint8Array {
|
|
85
|
+
// Determine prefix based on parity of y
|
|
86
|
+
const prefix = y % 2n === 0n ? 0x06 : 0x07;
|
|
87
|
+
|
|
88
|
+
// Convert x and y to 32-byte big-endian arrays
|
|
89
|
+
const xBytes = this.bigIntTo32Bytes(x);
|
|
90
|
+
const yBytes = this.bigIntTo32Bytes(y);
|
|
91
|
+
|
|
92
|
+
// Allocate 65 bytes: 1 for prefix + 32 for x + 32 for y
|
|
93
|
+
const hybrid = new Uint8Array(65);
|
|
94
|
+
hybrid[0] = prefix;
|
|
95
|
+
hybrid.set(xBytes, 1);
|
|
96
|
+
hybrid.set(yBytes, 33);
|
|
97
|
+
|
|
98
|
+
return hybrid;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Checks if (x^3 + 7) is a quadratic residue mod p.
|
|
103
|
+
* Returns the square root if it is, or null if not.
|
|
104
|
+
*/
|
|
105
|
+
private isValidX(x: bigint): bigint | null {
|
|
106
|
+
// alpha = (x^3 + 7) mod p
|
|
107
|
+
const alpha = (this.modPow(x, 3n, P) + 7n) % P;
|
|
108
|
+
return this.sqrtModP(alpha, P);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Computes base^exp (mod m) using exponentiation by squaring.
|
|
113
|
+
*/
|
|
114
|
+
private modPow(base: bigint, exp: bigint, m: bigint): bigint {
|
|
115
|
+
let result = 1n;
|
|
116
|
+
let cur = base % m;
|
|
117
|
+
let e = exp;
|
|
118
|
+
|
|
119
|
+
while (e > 0) {
|
|
120
|
+
if ((e & 1n) === 1n) {
|
|
121
|
+
result = (result * cur) % m;
|
|
122
|
+
}
|
|
123
|
+
cur = (cur * cur) % m;
|
|
124
|
+
e >>= 1n;
|
|
125
|
+
}
|
|
126
|
+
return result;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* sqrtModP(a, p):
|
|
131
|
+
* Attempts to compute the square root of `a` modulo prime `p`.
|
|
132
|
+
* Returns the root if it exists, or null if `a` is not a quadratic residue.
|
|
133
|
+
*
|
|
134
|
+
* Since p ≡ 3 (mod 4), we can do:
|
|
135
|
+
* sqrt(a) = a^((p+1)/4) mod p
|
|
136
|
+
*/
|
|
137
|
+
private sqrtModP(a: bigint, prime: bigint): bigint | null {
|
|
138
|
+
// Candidate root
|
|
139
|
+
const root = this.modPow(a, (prime + 1n) >> 2n, prime);
|
|
140
|
+
|
|
141
|
+
// Check if it's truly a root
|
|
142
|
+
if ((root * root) % prime !== a % prime) {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
return root;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Convert a 32-byte Uint8Array (big-endian) to a BigInt.
|
|
150
|
+
*/
|
|
151
|
+
private bytesToBigInt(bytes: Uint8Array): bigint {
|
|
152
|
+
let b = 0n;
|
|
153
|
+
for (const byte of bytes) {
|
|
154
|
+
b = (b << 8n) | BigInt(byte);
|
|
155
|
+
}
|
|
156
|
+
return b;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Convert a BigInt to a 32-byte array (big-endian).
|
|
161
|
+
*/
|
|
162
|
+
private bigIntTo32Bytes(value: bigint): Uint8Array {
|
|
163
|
+
const bytes = new Uint8Array(32);
|
|
164
|
+
for (let i = 31; i >= 0; i--) {
|
|
165
|
+
bytes[i] = Number(value & 0xffn);
|
|
166
|
+
value >>= 8n;
|
|
167
|
+
}
|
|
168
|
+
return bytes;
|
|
169
|
+
}
|
|
170
|
+
}
|
package/src/keypair/Wallet.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { IWallet } from './interfaces/IWallet.js';
|
|
2
2
|
import { ECPairInterface } from 'ecpair';
|
|
3
3
|
import { EcKeyPair } from './EcKeyPair.js';
|
|
4
|
-
import { Network, networks } from '@btc-vision/bitcoin';
|
|
5
|
-
import { toXOnly } from '@btc-vision/bitcoin/src/psbt/bip371.js';
|
|
4
|
+
import { Network, networks, toXOnly } from '@btc-vision/bitcoin';
|
|
6
5
|
import { Address } from './Address.js';
|
|
7
6
|
|
|
8
7
|
/**
|
package/src/opnet.ts
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
// Helper functions
|
|
2
|
-
import {
|
|
3
|
-
import { isP2TR } from '@btc-vision/bitcoin/src/psbt/psbtutils.js';
|
|
4
|
-
import { toXOnly } from '@btc-vision/bitcoin/src/psbt/bip371.js';
|
|
5
|
-
import * as bscript from '@btc-vision/bitcoin/src/script.js';
|
|
2
|
+
import { isP2TR, PsbtInput, pubkeyPositionInScript } from '@btc-vision/bitcoin';
|
|
6
3
|
|
|
7
4
|
export function isTaprootInput(input: PsbtInput): boolean {
|
|
8
5
|
return (
|
|
@@ -58,21 +55,12 @@ export function canSignNonTaprootInput(input: PsbtInput, publicKey: Buffer): boo
|
|
|
58
55
|
return false;
|
|
59
56
|
}
|
|
60
57
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const a = decompiled.findIndex((element) => {
|
|
69
|
-
if (typeof element === 'number') return false;
|
|
70
|
-
return element.equals(pubkey) || element.equals(pubkeyHash) || element.equals(pubkeyXOnly);
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
return a;
|
|
74
|
-
}
|
|
75
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Checks if a public key is present in a script.
|
|
60
|
+
* @param pubkey The public key to check.
|
|
61
|
+
* @param script The script to search in.
|
|
62
|
+
* @returns A boolean indicating whether the public key is present in the script.
|
|
63
|
+
*/
|
|
76
64
|
export function pubkeyInScript(pubkey: Buffer, script: Buffer): boolean {
|
|
77
65
|
return pubkeyPositionInScript(pubkey, script) !== -1;
|
|
78
66
|
}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import * as ecc from '@bitcoinerlab/secp256k1';
|
|
2
|
-
import { initEccLib, Network, Signer } from '@btc-vision/bitcoin';
|
|
3
|
-
import { tapTweakHash } from '@btc-vision/bitcoin/src/payments/bip341.js';
|
|
4
|
-
import { toXOnly } from '@btc-vision/bitcoin/src/psbt/bip371.js';
|
|
2
|
+
import { initEccLib, Network, Signer, tapTweakHash, toXOnly } from '@btc-vision/bitcoin';
|
|
5
3
|
import { ECPairInterface } from 'ecpair';
|
|
6
4
|
import { EcKeyPair } from '../keypair/EcKeyPair.js';
|
|
7
5
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Secp256k1PointDeriver } from '../keypair/Secp256k1PointDeriver.js';
|
|
2
|
+
|
|
3
|
+
class ContractAddressBase {
|
|
4
|
+
private readonly deriver: Secp256k1PointDeriver = new Secp256k1PointDeriver();
|
|
5
|
+
|
|
6
|
+
public generateHybridKeyFromHash(input: Buffer): Buffer {
|
|
7
|
+
const p = this.deriver.findOrDeriveValidPoint(input, false);
|
|
8
|
+
const y = this.deriver.getCanonicalY(p.y1, p.y2);
|
|
9
|
+
return Buffer.from(this.deriver.getHybridPublicKey(p.x, y));
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const ContractAddress = new ContractAddressBase();
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { Transaction } from '@btc-vision/bitcoin';
|
|
2
|
-
import { Output } from '@btc-vision/bitcoin/src/transaction.js';
|
|
1
|
+
import { Transaction, TxOutput } from '@btc-vision/bitcoin';
|
|
3
2
|
import { currentConsensus } from '../consensus/ConsensusConfig.js';
|
|
4
3
|
import { UTXO } from '../utxo/interfaces/IUTXO.js';
|
|
5
4
|
import {
|
|
@@ -230,7 +229,7 @@ export class TransactionFactory {
|
|
|
230
229
|
throw new Error('Could not sign funding transaction.');
|
|
231
230
|
}
|
|
232
231
|
|
|
233
|
-
const out:
|
|
232
|
+
const out: TxOutput = signedTransaction.outs[0];
|
|
234
233
|
const newUtxo: UTXO = {
|
|
235
234
|
transactionId: signedTransaction.getId(),
|
|
236
235
|
outputIndex: 0, // always 0
|
|
@@ -254,7 +253,7 @@ export class TransactionFactory {
|
|
|
254
253
|
// We have to regenerate using the new utxo
|
|
255
254
|
const outTx: Transaction = await finalTransaction.signTransaction();
|
|
256
255
|
|
|
257
|
-
const out2:
|
|
256
|
+
const out2: TxOutput = signedTransaction.outs[1];
|
|
258
257
|
const refundUTXO: UTXO = {
|
|
259
258
|
transactionId: signedTransaction.getId(),
|
|
260
259
|
outputIndex: 1, // always 1
|
|
@@ -364,7 +363,7 @@ export class TransactionFactory {
|
|
|
364
363
|
private getUTXOAsTransaction(tx: Transaction, to: string, index: number): UTXO[] {
|
|
365
364
|
if (!tx.outs[index]) return [];
|
|
366
365
|
|
|
367
|
-
const out:
|
|
366
|
+
const out: TxOutput = tx.outs[index];
|
|
368
367
|
const newUtxo: UTXO = {
|
|
369
368
|
transactionId: tx.getId(),
|
|
370
369
|
outputIndex: index,
|
|
@@ -5,13 +5,13 @@ import {
|
|
|
5
5
|
Psbt,
|
|
6
6
|
script as bitScript,
|
|
7
7
|
TapScriptSig,
|
|
8
|
+
toXOnly,
|
|
8
9
|
} from '@btc-vision/bitcoin';
|
|
9
10
|
import { ECPairInterface } from 'ecpair';
|
|
10
11
|
import { EcKeyPair } from '../../../keypair/EcKeyPair.js';
|
|
11
12
|
import { CustomKeypair } from '../BrowserSignerBase.js';
|
|
12
13
|
import { PsbtSignatureOptions, Unisat, UnisatNetwork } from '../types/Unisat.js';
|
|
13
14
|
import { PartialSig } from 'bip174/src/lib/interfaces.js';
|
|
14
|
-
import { toXOnly } from '@btc-vision/bitcoin/src/psbt/bip371.js';
|
|
15
15
|
import { canSignNonTaprootInput, isTaprootInput } from '../../../signer/SignerUtils.js';
|
|
16
16
|
|
|
17
17
|
declare global {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { Network, networks, Psbt, TapScriptSig } from '@btc-vision/bitcoin';
|
|
2
|
-
import { toXOnly } from '@btc-vision/bitcoin/src/psbt/bip371.js';
|
|
1
|
+
import { Network, networks, Psbt, TapScriptSig, toXOnly } from '@btc-vision/bitcoin';
|
|
3
2
|
import { PartialSig } from 'bip174/src/lib/interfaces.js';
|
|
4
3
|
import { ECPairInterface } from 'ecpair';
|
|
5
4
|
import { EcKeyPair } from '../../../keypair/EcKeyPair.js';
|
|
@@ -1,14 +1,21 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
crypto as bitCrypto,
|
|
3
|
+
Payment,
|
|
4
|
+
Psbt,
|
|
5
|
+
PsbtInput,
|
|
6
|
+
Signer,
|
|
7
|
+
Stack,
|
|
8
|
+
Taptree,
|
|
9
|
+
toXOnly,
|
|
10
|
+
} from '@btc-vision/bitcoin';
|
|
2
11
|
import { TransactionType } from '../enums/TransactionType.js';
|
|
3
12
|
import { TapLeafScript } from '../interfaces/Tap.js';
|
|
4
13
|
import { SharedInteractionParameters } from '../interfaces/ITransactionParameters.js';
|
|
5
|
-
import { crypto as bitCrypto, Payment, Psbt, PsbtInput, Signer, Stack } from '@btc-vision/bitcoin';
|
|
6
14
|
import { TransactionBuilder } from './TransactionBuilder.js';
|
|
7
15
|
import { CustomGenerator } from '../../generators/builders/CustomGenerator.js';
|
|
8
16
|
import { BitcoinUtils } from '../../utils/BitcoinUtils.js';
|
|
9
17
|
import { EcKeyPair } from '../../keypair/EcKeyPair.js';
|
|
10
18
|
import { AddressGenerator } from '../../generators/AddressGenerator.js';
|
|
11
|
-
import { toXOnly } from '@btc-vision/bitcoin/src/psbt/bip371.js';
|
|
12
19
|
import { ECPairInterface } from 'ecpair';
|
|
13
20
|
|
|
14
21
|
export interface ICustomTransactionParameters extends SharedInteractionParameters {
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import { TransactionType } from '../enums/TransactionType.js';
|
|
2
2
|
import { IDeploymentParameters } from '../interfaces/ITransactionParameters.js';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
crypto as bitCrypto,
|
|
5
|
+
Payment,
|
|
6
|
+
Psbt,
|
|
7
|
+
PsbtInput,
|
|
8
|
+
Signer,
|
|
9
|
+
Taptree,
|
|
10
|
+
toXOnly,
|
|
11
|
+
} from '@btc-vision/bitcoin';
|
|
4
12
|
import { TransactionBuilder } from './TransactionBuilder.js';
|
|
5
|
-
import { Taptree } from '@btc-vision/bitcoin/src/types.js';
|
|
6
13
|
import { TapLeafScript } from '../interfaces/Tap.js';
|
|
7
14
|
import { DeploymentGenerator } from '../../generators/builders/DeploymentGenerator.js';
|
|
8
|
-
import { toXOnly } from '@btc-vision/bitcoin/src/psbt/bip371.js';
|
|
9
15
|
import { EcKeyPair } from '../../keypair/EcKeyPair.js';
|
|
10
16
|
import { BitcoinUtils } from '../../utils/BitcoinUtils.js';
|
|
11
17
|
import { Compressor } from '../../bytecode/Compressor.js';
|
|
@@ -14,6 +20,8 @@ import { ECPairInterface } from 'ecpair';
|
|
|
14
20
|
import { Address } from '../../keypair/Address.js';
|
|
15
21
|
import { UnisatSigner } from '../browser/extensions/UnisatSigner.js';
|
|
16
22
|
|
|
23
|
+
const p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fn;
|
|
24
|
+
|
|
17
25
|
export class DeploymentTransaction extends TransactionBuilder<TransactionType.DEPLOYMENT> {
|
|
18
26
|
public static readonly MAXIMUM_CONTRACT_SIZE = 128 * 1024;
|
|
19
27
|
public type: TransactionType.DEPLOYMENT = TransactionType.DEPLOYMENT;
|
|
@@ -90,6 +98,7 @@ export class DeploymentTransaction extends TransactionBuilder<TransactionType.DE
|
|
|
90
98
|
private readonly randomBytes: Buffer;
|
|
91
99
|
|
|
92
100
|
public constructor(parameters: IDeploymentParameters) {
|
|
101
|
+
// TODO: Add legacy deployment, this is only p2tr.
|
|
93
102
|
super(parameters);
|
|
94
103
|
|
|
95
104
|
this.bytecode = Compressor.compress(parameters.bytecode);
|
|
@@ -317,6 +326,7 @@ export class DeploymentTransaction extends TransactionBuilder<TransactionType.DE
|
|
|
317
326
|
throw new Error('Bytecode is required');
|
|
318
327
|
}
|
|
319
328
|
|
|
329
|
+
// Concatenate deployer pubkey, salt, and sha256(bytecode)
|
|
320
330
|
const deployerPubKey: Buffer = this.internalPubKeyToXOnly();
|
|
321
331
|
const salt: Buffer = bitCrypto.hash256(this.randomBytes);
|
|
322
332
|
const sha256OfBytecode: Buffer = bitCrypto.hash256(this.bytecode);
|
|
@@ -29,14 +29,14 @@ export class FundingTransaction extends TransactionBuilder<TransactionType.FUNDI
|
|
|
29
29
|
if (this.splitInputsInto > 1) {
|
|
30
30
|
this.splitInputs(this.amount);
|
|
31
31
|
} else if (this.isPubKeyDestination) {
|
|
32
|
-
const
|
|
32
|
+
const pubKeyScript = script.compile([
|
|
33
33
|
Buffer.from(this.to.replace('0x', ''), 'hex'),
|
|
34
34
|
opcodes.OP_CHECKSIG,
|
|
35
35
|
]);
|
|
36
36
|
|
|
37
37
|
this.addOutput({
|
|
38
38
|
value: Number(this.amount),
|
|
39
|
-
script:
|
|
39
|
+
script: pubKeyScript,
|
|
40
40
|
});
|
|
41
41
|
} else {
|
|
42
42
|
this.addOutput({
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Taptree } from '@btc-vision/bitcoin
|
|
1
|
+
import { Taptree } from '@btc-vision/bitcoin';
|
|
2
2
|
import { TransactionType } from '../enums/TransactionType.js';
|
|
3
3
|
import { TapLeafScript } from '../interfaces/Tap.js';
|
|
4
4
|
import { IInteractionParameters } from '../interfaces/ITransactionParameters.js';
|
|
@@ -9,14 +9,14 @@ import {
|
|
|
9
9
|
script,
|
|
10
10
|
Signer,
|
|
11
11
|
TapScriptSig,
|
|
12
|
+
Taptree,
|
|
13
|
+
toXOnly,
|
|
12
14
|
} from '@btc-vision/bitcoin';
|
|
13
|
-
import { Taptree } from '@btc-vision/bitcoin/src/types.js';
|
|
14
15
|
import { TransactionBuilder } from './TransactionBuilder.js';
|
|
15
16
|
import { TransactionType } from '../enums/TransactionType.js';
|
|
16
17
|
import { ITransactionParameters } from '../interfaces/ITransactionParameters.js';
|
|
17
18
|
import { MultiSignGenerator } from '../../generators/builders/MultiSignGenerator.js';
|
|
18
19
|
import { UTXO } from '../../utxo/interfaces/IUTXO.js';
|
|
19
|
-
import { toXOnly } from '@btc-vision/bitcoin/src/psbt/bip371.js';
|
|
20
20
|
import { EcKeyPair } from '../../keypair/EcKeyPair.js';
|
|
21
21
|
import { ECPairInterface } from 'ecpair';
|
|
22
22
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { address, Payment, Psbt, PsbtInput, Signer } from '@btc-vision/bitcoin';
|
|
2
|
-
import { Taptree } from '@btc-vision/bitcoin/src/types.js';
|
|
1
|
+
import { address, Payment, Psbt, PsbtInput, Signer, Taptree, toXOnly } from '@btc-vision/bitcoin';
|
|
3
2
|
import { ECPairInterface } from 'ecpair';
|
|
4
3
|
import { TransactionBuilder } from './TransactionBuilder.js';
|
|
5
4
|
import { TransactionType } from '../enums/TransactionType.js';
|
|
@@ -8,7 +7,6 @@ import { SharedInteractionParameters } from '../interfaces/ITransactionParameter
|
|
|
8
7
|
import { Compressor } from '../../bytecode/Compressor.js';
|
|
9
8
|
import { EcKeyPair } from '../../keypair/EcKeyPair.js';
|
|
10
9
|
import { BitcoinUtils } from '../../utils/BitcoinUtils.js';
|
|
11
|
-
import { toXOnly } from '@btc-vision/bitcoin/src/psbt/bip371.js';
|
|
12
10
|
import { UnisatSigner } from '../browser/extensions/UnisatSigner.js';
|
|
13
11
|
|
|
14
12
|
/**
|
|
@@ -8,8 +8,8 @@ import {
|
|
|
8
8
|
script,
|
|
9
9
|
Signer,
|
|
10
10
|
Transaction,
|
|
11
|
+
varuint,
|
|
11
12
|
} from '@btc-vision/bitcoin';
|
|
12
|
-
import { varuint } from '@btc-vision/bitcoin/src/bufferutils.js';
|
|
13
13
|
import * as ecc from '@bitcoinerlab/secp256k1';
|
|
14
14
|
import { UpdateInput } from '../interfaces/Tap.js';
|
|
15
15
|
import { TransactionType } from '../enums/TransactionType.js';
|
|
@@ -473,6 +473,16 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
|
|
|
473
473
|
address: this.from,
|
|
474
474
|
tapInternalKey: this.internalPubKeyToXOnly(),
|
|
475
475
|
});
|
|
476
|
+
} else if (AddressVerificator.isValidPublicKey(this.from, this.network)) {
|
|
477
|
+
const pubKeyScript = script.compile([
|
|
478
|
+
Buffer.from(this.from.replace('0x', ''), 'hex'),
|
|
479
|
+
opcodes.OP_CHECKSIG,
|
|
480
|
+
]);
|
|
481
|
+
|
|
482
|
+
await this.setFeeOutput({
|
|
483
|
+
value: Number(sendBackAmount),
|
|
484
|
+
script: pubKeyScript,
|
|
485
|
+
});
|
|
476
486
|
} else {
|
|
477
487
|
await this.setFeeOutput({
|
|
478
488
|
value: Number(sendBackAmount),
|
|
@@ -3,6 +3,13 @@ import {
|
|
|
3
3
|
address as bitAddress,
|
|
4
4
|
crypto as bitCrypto,
|
|
5
5
|
getFinalScripts,
|
|
6
|
+
isP2MS,
|
|
7
|
+
isP2PK,
|
|
8
|
+
isP2PKH,
|
|
9
|
+
isP2SHScript,
|
|
10
|
+
isP2TR,
|
|
11
|
+
isP2WPKH,
|
|
12
|
+
isP2WSHScript,
|
|
6
13
|
Network,
|
|
7
14
|
opcodes,
|
|
8
15
|
Payment,
|
|
@@ -12,31 +19,22 @@ import {
|
|
|
12
19
|
PsbtInputExtended,
|
|
13
20
|
script,
|
|
14
21
|
Signer,
|
|
22
|
+
toXOnly,
|
|
15
23
|
Transaction,
|
|
24
|
+
varuint,
|
|
16
25
|
} from '@btc-vision/bitcoin';
|
|
17
26
|
|
|
18
27
|
import { TweakedSigner, TweakSettings } from '../../signer/TweakedSigner.js';
|
|
19
28
|
import { ECPairInterface } from 'ecpair';
|
|
20
|
-
import { toXOnly } from '@btc-vision/bitcoin/src/psbt/bip371.js';
|
|
21
29
|
import { UTXO } from '../../utxo/interfaces/IUTXO.js';
|
|
22
30
|
import { TapLeafScript } from '../interfaces/Tap.js';
|
|
23
31
|
import { ChainId } from '../../network/ChainId.js';
|
|
24
|
-
import { varuint } from '@btc-vision/bitcoin/src/bufferutils.js';
|
|
25
32
|
import { UnisatSigner } from '../browser/extensions/UnisatSigner.js';
|
|
26
33
|
import {
|
|
27
34
|
canSignNonTaprootInput,
|
|
28
35
|
isTaprootInput,
|
|
29
36
|
pubkeyInScript,
|
|
30
37
|
} from '../../signer/SignerUtils.js';
|
|
31
|
-
import {
|
|
32
|
-
isP2MS,
|
|
33
|
-
isP2PK,
|
|
34
|
-
isP2PKH,
|
|
35
|
-
isP2SHScript,
|
|
36
|
-
isP2TR,
|
|
37
|
-
isP2WPKH,
|
|
38
|
-
isP2WSHScript,
|
|
39
|
-
} from '@btc-vision/bitcoin/src/psbt/psbtutils.js';
|
|
40
38
|
|
|
41
39
|
export interface ITweakedTransactionData {
|
|
42
40
|
readonly signer: Signer | ECPairInterface | UnisatSigner;
|
|
@@ -803,88 +801,6 @@ export abstract class TweakedTransaction extends Logger {
|
|
|
803
801
|
return input;
|
|
804
802
|
}
|
|
805
803
|
|
|
806
|
-
/*protected generatePsbtInputExtended(utxo: UTXO, i: number): PsbtInputExtended {
|
|
807
|
-
const input: PsbtInputExtended = {
|
|
808
|
-
hash: utxo.transactionId,
|
|
809
|
-
index: utxo.outputIndex,
|
|
810
|
-
sequence: this.sequence,
|
|
811
|
-
witnessUtxo: {
|
|
812
|
-
value: Number(utxo.value),
|
|
813
|
-
script: Buffer.from(utxo.scriptPubKey.hex, 'hex'),
|
|
814
|
-
},
|
|
815
|
-
};
|
|
816
|
-
|
|
817
|
-
if (utxo.scriptPubKey.address) {
|
|
818
|
-
// auto detect for potential p2sh utxos
|
|
819
|
-
try {
|
|
820
|
-
const addressType: AddressTypes | null = AddressVerificator.detectAddressType(
|
|
821
|
-
utxo.scriptPubKey.address,
|
|
822
|
-
this.network,
|
|
823
|
-
);
|
|
824
|
-
|
|
825
|
-
if (addressType === AddressTypes.P2SH_OR_P2SH_P2WPKH) {
|
|
826
|
-
// We can automatically reconstruct the redeem script.
|
|
827
|
-
const redeemScript = this.generateP2SHRedeemScriptLegacy(
|
|
828
|
-
utxo.scriptPubKey.address,
|
|
829
|
-
);
|
|
830
|
-
|
|
831
|
-
if (!redeemScript) {
|
|
832
|
-
throw new Error('Failed to generate redeem script');
|
|
833
|
-
}
|
|
834
|
-
|
|
835
|
-
input.redeemScript = redeemScript.outputScript;
|
|
836
|
-
input.witnessScript = redeemScript.redeemScript;
|
|
837
|
-
}
|
|
838
|
-
} catch (e) {
|
|
839
|
-
this.error(`Failed to detect address type for ${utxo.scriptPubKey.address} - ${e}`);
|
|
840
|
-
}
|
|
841
|
-
}
|
|
842
|
-
|
|
843
|
-
// LEGACY P2SH SUPPORT
|
|
844
|
-
if (utxo.nonWitnessUtxo) {
|
|
845
|
-
input.nonWitnessUtxo = Buffer.isBuffer(utxo.nonWitnessUtxo)
|
|
846
|
-
? utxo.nonWitnessUtxo
|
|
847
|
-
: Buffer.from(utxo.nonWitnessUtxo, 'hex');
|
|
848
|
-
}
|
|
849
|
-
|
|
850
|
-
// SEGWIT SUPPORT
|
|
851
|
-
if (utxo.redeemScript) {
|
|
852
|
-
input.redeemScript = Buffer.isBuffer(utxo.redeemScript)
|
|
853
|
-
? utxo.redeemScript
|
|
854
|
-
: Buffer.from(utxo.redeemScript, 'hex');
|
|
855
|
-
|
|
856
|
-
if (utxo.witnessScript) {
|
|
857
|
-
input.witnessScript = Buffer.isBuffer(utxo.witnessScript)
|
|
858
|
-
? utxo.witnessScript
|
|
859
|
-
: Buffer.from(utxo.witnessScript, 'hex');
|
|
860
|
-
}
|
|
861
|
-
}
|
|
862
|
-
|
|
863
|
-
// TAPROOT.
|
|
864
|
-
if (this.sighashTypes) {
|
|
865
|
-
const inputSign = TweakedTransaction.calculateSignHash(this.sighashTypes);
|
|
866
|
-
if (inputSign) input.sighashType = inputSign;
|
|
867
|
-
}
|
|
868
|
-
|
|
869
|
-
if (i === 0 && this.nonWitnessUtxo) {
|
|
870
|
-
input.nonWitnessUtxo = this.nonWitnessUtxo;
|
|
871
|
-
}
|
|
872
|
-
|
|
873
|
-
// Automatically detect P2TR inputs.
|
|
874
|
-
if (
|
|
875
|
-
utxo.scriptPubKey.address &&
|
|
876
|
-
AddressVerificator.isValidP2TRAddress(utxo.scriptPubKey.address, this.network)
|
|
877
|
-
) {
|
|
878
|
-
this.tweakSigner();
|
|
879
|
-
|
|
880
|
-
input.tapInternalKey = this.internalPubKeyToXOnly();
|
|
881
|
-
}
|
|
882
|
-
|
|
883
|
-
console.log(input);
|
|
884
|
-
|
|
885
|
-
return input;
|
|
886
|
-
}*/
|
|
887
|
-
|
|
888
804
|
protected customFinalizerP2SH = (
|
|
889
805
|
inputIndex: number,
|
|
890
806
|
input: PsbtInput,
|
|
@@ -21,7 +21,7 @@ export class BufferHelper {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
public static uint8ArrayToHex(input: Uint8Array): string {
|
|
24
|
-
return Buffer.from(input, 0, input.byteLength).toString('hex');
|
|
24
|
+
return Buffer.from(input.buffer, 0, input.byteLength).toString('hex');
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
public static hexToUint8Array(input: string): Uint8Array {
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import {
|
|
2
|
+
crypto as bitCrypto,
|
|
3
|
+
Network,
|
|
4
|
+
networks,
|
|
5
|
+
Payment,
|
|
6
|
+
payments,
|
|
7
|
+
Taptree,
|
|
8
|
+
toXOnly,
|
|
9
|
+
} from '@btc-vision/bitcoin';
|
|
4
10
|
import { DeploymentGenerator } from '../generators/builders/DeploymentGenerator.js';
|
|
5
11
|
import { TransactionBuilder } from '../transaction/builders/TransactionBuilder.js';
|
|
6
12
|
import { Address } from '../keypair/Address.js';
|