Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for pay to taproot #1742

Merged
merged 96 commits into from
Nov 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
96 commits
Select commit Hold shift + click to select a range
5cf1e43
chore: add bn.js to dependencies (previously it was present in devDep…
motorina0 Oct 28, 2021
083c8c1
feat: add liftX() function (first version)
motorina0 Oct 28, 2021
ef8a4c8
feat: update the Payment interface with taproot specific fields
motorina0 Oct 28, 2021
93185d4
feat: add first version of p2tr; basic logic for key path construct/s…
motorina0 Oct 28, 2021
d1e35e4
test: add first tests for p2tr
motorina0 Oct 28, 2021
f39812c
feat: add generated files
motorina0 Oct 28, 2021
2a2b403
feat: compute "taproot output key" when "taoroot internal key" is kno…
motorina0 Oct 29, 2021
e12f187
tests: improve test coverage
motorina0 Oct 29, 2021
7760b9f
feat: add function `computeMastRoot()`
motorina0 Nov 1, 2021
d142e02
feat: compute p2tr hash based on the script tree
motorina0 Nov 1, 2021
d1c7b05
feat: add scriptsTree field to Payment interface; export p2tr
motorina0 Nov 1, 2021
46e3ce7
feat: convert `scriptsTree` output to Buffer
motorina0 Nov 1, 2021
3f1be32
tests: add tests for script tree
motorina0 Nov 1, 2021
b6a0048
feat: add simple type for TaprootLeaf and TaprootNode
motorina0 Nov 1, 2021
7bc0c8e
feat: check for hash mismatch between the input hash and the computed…
motorina0 Nov 1, 2021
61511d4
feat: validate witness data (partial)
motorina0 Nov 2, 2021
725d96a
refactor: split `computeTweakFromScriptPath()` into `rootHash()` and …
motorina0 Nov 2, 2021
c309ff8
feat: compute hash from witness control-block
motorina0 Nov 2, 2021
d0ae719
refactor: extract taproot related logic to taproot.ts file
motorina0 Nov 2, 2021
a8c3f1d
chore: code format and lint
motorina0 Nov 2, 2021
6fa79d6
refactor: compare GROUP_ORDER as buffer (instead of using BN.js)
motorina0 Nov 2, 2021
cafcde0
refactor: rename `rootHash` to `rootHashFromPath` and `computeMastRoo…
motorina0 Nov 3, 2021
5068223
tests: add bib341 tests by @sipa; plus refactoring
motorina0 Nov 3, 2021
04a50c0
refactor: extract `tapBranchHash()` rename `leafHash()` to `tapBranch…
motorina0 Nov 3, 2021
a98e76b
feat: build control-block as part of witness; update tests
motorina0 Nov 3, 2021
bf41ac7
chore: lint & format; fix: discovered bug in findScriptPath() after lint
motorina0 Nov 3, 2021
b307379
chore: code clean-up; fix o.scriptLeaf (needs tests)
motorina0 Nov 3, 2021
a3bfa84
chore: update taggedHash() prefix after rebase
motorina0 Nov 12, 2021
0519d2b
fix: rebase issues
motorina0 Jan 12, 2022
2efc51e
chore: remove the bn.js dependency
motorina0 Jan 13, 2022
4fd8a34
refactor: use injectable ecc lib
motorina0 Jan 13, 2022
a8644a8
chore: code format
motorina0 Jan 13, 2022
b866a80
refactor: move taproot utils file
motorina0 Jan 13, 2022
fac6c90
refactor: move non-exported function to the bottom
motorina0 Jan 13, 2022
6578097
fix: lint & gitdiff issues
motorina0 Jan 13, 2022
1577f66
chore: removed un-used exports
motorina0 Jan 13, 2022
af72a78
chore: add docs, simplify code
motorina0 Jan 13, 2022
f2a0c1d
feat: pass the ECC library as an optional parameter to p2tr
motorina0 Jan 14, 2022
2e5965d
refactor: move eccLib to PaymentOptions
motorina0 Jan 18, 2022
e292387
fix: remove `TinySecp256k1Interface` from `PaymentCreator`
motorina0 Jan 20, 2022
06fc272
chore: keep ecc test vectors to a minimum
motorina0 Jan 20, 2022
2526642
fix: taproot signature is 64 bytes
motorina0 Jan 27, 2022
fa1e1c3
feat: add Key Spend support for taproot to PSBT (more in commit descr…
motorina0 Jan 27, 2022
04d0be9
feat: extract `tiny-secp256k1` out of the Psbt module
motorina0 Jan 28, 2022
222022a
chore: take the garbage out. Remove `tweakSigner()` and ecpair dep fr…
motorina0 Feb 10, 2022
4eee26b
feat: add taproot check for signInputAsync()
motorina0 Feb 18, 2022
e91c77d
feat: add stricter validation for taproot addresses
motorina0 Feb 18, 2022
6816f51
fix: fix integration test
motorina0 Feb 18, 2022
7da1dd5
feat: correctly identify P2TR (pass `eccLib` to `toOutputScript` and …
motorina0 Feb 22, 2022
e033a6f
add integration tests for taproot (#3)
motorina0 Mar 9, 2022
1e6aec5
refactor: move tapscript finalizer check; add unit test
motorina0 Mar 9, 2022
08cf664
fix: fix integration test
motorina0 Mar 9, 2022
3e02a63
fix: revert package lock version upgrade
motorina0 Mar 9, 2022
fde11c9
refactor: change code to original version
motorina0 Mar 9, 2022
060630b
fix: make `FinalScriptsFunc` backwards compatible by moving `isTaps…
motorina0 Mar 9, 2022
b17dc51
fix: tap tree branch sorting; improve unit test
motorina0 Mar 10, 2022
032201a
refactor: add Taptree interface
motorina0 Mar 18, 2022
fee9fa1
refactor: rename `testecc` to `verifyecc` (avoid confusing it with un…
motorina0 Mar 18, 2022
67028cf
Declare tapscript version mask like the BIP
reardencode Mar 18, 2022
da61c66
Correct Taptree type
reardencode Mar 18, 2022
d29ada6
Consistent capitalization of tapleaf
reardencode Mar 18, 2022
cf18dfd
Don't use constants for tag prefixes
reardencode Mar 18, 2022
f76b954
Simplify HashTree processing, remove footgun
reardencode Mar 18, 2022
18bcadd
Support p2tr with 1 script and no tree
reardencode Mar 18, 2022
c02ed1b
Remove unnecessary arrays of values
reardencode Mar 18, 2022
6b9f776
Improve tapleah hash parameter name
reardencode Mar 18, 2022
95d0f51
Fix indentation
reardencode Mar 18, 2022
e557a99
Add validation for redeem in scriptTree
reardencode Mar 21, 2022
c3053e7
Improve comments and code clarity
reardencode Mar 21, 2022
6f70c88
refactor: add explicit initialisation of the ecc library (#5)
motorina0 Mar 28, 2022
4fd164e
refactor: move tweakKey() to taproot utils
motorina0 Apr 1, 2022
9d4fdcd
fix: use witness without annex for o.signature
motorina0 Apr 1, 2022
3af7c11
feat: use BIP371 fields for taproot inputs
motorina0 May 20, 2022
6cbac53
feat: add to/from Psbt TapTree conversion
motorina0 May 24, 2022
9eb0790
test: add tests for taptree conversion to tapleaf
motorina0 May 24, 2022
bc3dc46
chore: code lint
motorina0 May 24, 2022
d7e24cb
test: use `tapInternalKey` to generate the address
motorina0 May 25, 2022
58258a7
feat: do taproot checks for `addOutput()`
motorina0 May 25, 2022
8ca34c0
refactor: simplify `addOutput()` checks
motorina0 May 25, 2022
e17e2bd
feat: do taproot checks for `updateOutput()`
motorina0 May 25, 2022
057cdc5
feat: check if taproot signature are present before allowing psbt cha…
motorina0 May 26, 2022
f32d706
refactor: move out some utils
motorina0 May 26, 2022
c9b334b
test: add custom taproot finalizer (partial)
motorina0 May 26, 2022
8b4cee9
chore: code clean-up
motorina0 May 26, 2022
94f5291
Fix integration test
junderw May 26, 2022
724be84
Fix test lints
junderw May 26, 2022
4db8455
Fix audit
junderw May 26, 2022
7839476
refactor: rename `taprootutils` to `bip341`
motorina0 Jun 1, 2022
6f40ec8
chore: fix typo
motorina0 Nov 29, 2022
80a31db
fix: add check for `controlBlock` length
motorina0 Nov 29, 2022
d5181df
chore: typo in comment
motorina0 Nov 29, 2022
9960306
chore: remove `any` type
motorina0 Nov 29, 2022
57f915e
chore: add explicit type for returned signatures
motorina0 Nov 29, 2022
c3b5173
chore: sync `package-lock.json`
motorina0 Nov 29, 2022
a72be91
fix: audit issue for `minimatch`
motorina0 Nov 29, 2022
b994d46
6.1.0-rc.0
motorina0 Nov 29, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
309 changes: 120 additions & 189 deletions package-lock.json

Large diffs are not rendered by default.

7 changes: 3 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "bitcoinjs-lib",
"version": "6.0.2",
"version": "6.1.0-rc.0",
"description": "Client-side Bitcoin JavaScript library",
"main": "./src/index.js",
"types": "./src/index.d.ts",
Expand Down Expand Up @@ -50,7 +50,7 @@
],
"dependencies": {
"bech32": "^2.0.0",
"bip174": "^2.0.1",
"bip174": "^2.1.0",
"bs58check": "^2.1.2",
"create-hash": "^1.1.0",
"ripemd160": "^2.0.2",
Expand All @@ -73,7 +73,6 @@
"bip39": "^3.0.2",
"bip65": "^1.0.1",
"bip68": "^1.0.3",
"bn.js": "^4.11.8",
"bs58": "^4.0.0",
"dhttp": "^3.0.0",
"ecpair": "^2.0.1",
Expand All @@ -86,7 +85,7 @@
"randombytes": "^2.1.0",
"regtest-client": "0.2.0",
"rimraf": "^2.6.3",
"tiny-secp256k1": "^2.1.2",
"tiny-secp256k1": "^2.2.0",
"ts-node": "^8.3.0",
"tslint": "^6.1.3",
"typescript": "^4.4.4"
Expand Down
16 changes: 12 additions & 4 deletions src/address.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ exports.toOutputScript = exports.fromOutputScript = exports.toBech32 = exports.t
const networks = require('./networks');
const payments = require('./payments');
const bscript = require('./script');
const types = require('./types');
const types_1 = require('./types');
const bech32_1 = require('bech32');
const bs58check = require('bs58check');
const { typeforce } = types;
const FUTURE_SEGWIT_MAX_SIZE = 40;
const FUTURE_SEGWIT_MIN_SIZE = 2;
const FUTURE_SEGWIT_MAX_VERSION = 16;
const FUTURE_SEGWIT_MIN_VERSION = 1;
const FUTURE_SEGWIT_MIN_VERSION = 2;
const FUTURE_SEGWIT_VERSION_DIFF = 0x50;
const FUTURE_SEGWIT_VERSION_WARNING =
'WARNING: Sending to a future segwit version address can lead to loss of funds. ' +
Expand Down Expand Up @@ -69,7 +68,10 @@ function fromBech32(address) {
}
exports.fromBech32 = fromBech32;
function toBase58Check(hash, version) {
typeforce(types.tuple(types.Hash160bit, types.UInt8), arguments);
(0, types_1.typeforce)(
(0, types_1.tuple)(types_1.Hash160bit, types_1.UInt8),
arguments,
);
const payload = Buffer.allocUnsafe(21);
payload.writeUInt8(version, 0);
hash.copy(payload, 1);
Expand Down Expand Up @@ -99,6 +101,9 @@ function fromOutputScript(output, network) {
try {
return payments.p2wsh({ output, network }).address;
} catch (e) {}
try {
return payments.p2tr({ output, network }).address;
} catch (e) {}
try {
return _toFutureSegwitAddress(output, network);
} catch (e) {}
Expand Down Expand Up @@ -129,6 +134,9 @@ function toOutputScript(address, network) {
return payments.p2wpkh({ hash: decodeBech32.data }).output;
if (decodeBech32.data.length === 32)
return payments.p2wsh({ hash: decodeBech32.data }).output;
} else if (decodeBech32.version === 1) {
if (decodeBech32.data.length === 32)
return payments.p2tr({ pubkey: decodeBech32.data }).output;
} else if (
decodeBech32.version >= FUTURE_SEGWIT_MIN_VERSION &&
decodeBech32.version <= FUTURE_SEGWIT_MAX_VERSION &&
Expand Down
3 changes: 3 additions & 0 deletions src/ecc_lib.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { TinySecp256k1Interface } from './types';
export declare function initEccLib(eccLib: TinySecp256k1Interface | undefined): void;
export declare function getEccLib(): TinySecp256k1Interface;
91 changes: 91 additions & 0 deletions src/ecc_lib.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
exports.getEccLib = exports.initEccLib = void 0;
const _ECCLIB_CACHE = {};
function initEccLib(eccLib) {
if (!eccLib) {
// allow clearing the library
_ECCLIB_CACHE.eccLib = eccLib;
} else if (eccLib !== _ECCLIB_CACHE.eccLib) {
// new instance, verify it
verifyEcc(eccLib);
_ECCLIB_CACHE.eccLib = eccLib;
}
}
exports.initEccLib = initEccLib;
function getEccLib() {
if (!_ECCLIB_CACHE.eccLib)
throw new Error(
'No ECC Library provided. You must call initEccLib() with a valid TinySecp256k1Interface instance',
);
return _ECCLIB_CACHE.eccLib;
}
exports.getEccLib = getEccLib;
const h = hex => Buffer.from(hex, 'hex');
function verifyEcc(ecc) {
assert(typeof ecc.isXOnlyPoint === 'function');
assert(
ecc.isXOnlyPoint(
h('79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'),
),
);
assert(
ecc.isXOnlyPoint(
h('fffffffffffffffffffffffffffffffffffffffffffffffffffffffeeffffc2e'),
),
);
assert(
ecc.isXOnlyPoint(
h('f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9'),
),
);
assert(
ecc.isXOnlyPoint(
h('0000000000000000000000000000000000000000000000000000000000000001'),
),
);
assert(
!ecc.isXOnlyPoint(
h('0000000000000000000000000000000000000000000000000000000000000000'),
),
);
assert(
!ecc.isXOnlyPoint(
h('fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f'),
),
);
assert(typeof ecc.xOnlyPointAddTweak === 'function');
tweakAddVectors.forEach(t => {
const r = ecc.xOnlyPointAddTweak(h(t.pubkey), h(t.tweak));
if (t.result === null) {
assert(r === null);
} else {
assert(r !== null);
assert(r.parity === t.parity);
assert(Buffer.from(r.xOnlyPubkey).equals(h(t.result)));
}
});
}
function assert(bool) {
if (!bool) throw new Error('ecc library invalid');
}
const tweakAddVectors = [
{
pubkey: '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798',
tweak: 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140',
parity: -1,
result: null,
},
{
pubkey: '1617d38ed8d8657da4d4761e8057bc396ea9e4b9d29776d4be096016dbd2509b',
tweak: 'a8397a935f0dfceba6ba9618f6451ef4d80637abf4e6af2669fbc9de6a8fd2ac',
parity: 1,
result: 'e478f99dab91052ab39a33ea35fd5e6e4933f4d28023cd597c9a1f6760346adf',
},
{
pubkey: '2c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991',
tweak: '823c3cd2142744b075a87eade7e1b8678ba308d566226a0056ca2b7a76f86b47',
parity: 0,
result: '9534f8dc8c6deda2dc007655981c78b49c5d96c778fbf363462a11ec9dfd948c',
},
];
1 change: 1 addition & 0 deletions src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ export { Transaction } from './transaction';
export { Network } from './networks';
export { Payment, PaymentCreator, PaymentOpts, Stack, StackElement, } from './payments';
export { Input as TxInput, Output as TxOutput } from './transaction';
export { initEccLib } from './ecc_lib';
9 changes: 8 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
exports.Transaction = exports.opcodes = exports.Psbt = exports.Block = exports.script = exports.payments = exports.networks = exports.crypto = exports.address = void 0;
exports.initEccLib = exports.Transaction = exports.opcodes = exports.Psbt = exports.Block = exports.script = exports.payments = exports.networks = exports.crypto = exports.address = void 0;
const address = require('./address');
exports.address = address;
const crypto = require('./crypto');
Expand Down Expand Up @@ -39,3 +39,10 @@ Object.defineProperty(exports, 'Transaction', {
return transaction_1.Transaction;
},
});
var ecc_lib_1 = require('./ecc_lib');
Object.defineProperty(exports, 'initEccLib', {
enumerable: true,
get: function() {
return ecc_lib_1.initEccLib;
},
});
1 change: 1 addition & 0 deletions src/ops.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ const OPS = {
OP_NOP8: 183,
OP_NOP9: 184,
OP_NOP10: 185,
OP_CHECKSIGADD: 186,
OP_PUBKEYHASH: 253,
OP_PUBKEY: 254,
OP_INVALIDOPCODE: 255,
Expand Down
42 changes: 42 additions & 0 deletions src/payments/bip341.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/// <reference types="node" />
import { Tapleaf, Taptree } from '../types';
export declare const LEAF_VERSION_TAPSCRIPT = 192;
export declare const MAX_TAPTREE_DEPTH = 128;
interface HashLeaf {
hash: Buffer;
}
interface HashBranch {
hash: Buffer;
left: HashTree;
right: HashTree;
}
interface TweakedPublicKey {
parity: number;
x: Buffer;
}
/**
* Binary tree representing leaf, branch, and root node hashes of a Taptree.
* Each node contains a hash, and potentially left and right branch hashes.
* This tree is used for 2 purposes: Providing the root hash for tweaking,
* and calculating merkle inclusion proofs when constructing a control block.
*/
export declare type HashTree = HashLeaf | HashBranch;
export declare function rootHashFromPath(controlBlock: Buffer, leafHash: Buffer): Buffer;
/**
* Build a hash tree of merkle nodes from the scripts binary tree.
* @param scriptTree - the tree of scripts to pairwise hash.
*/
export declare function toHashTree(scriptTree: Taptree): HashTree;
/**
* Given a HashTree, finds the path from a particular hash to the root.
* @param node - the root of the tree
* @param hash - the hash to search for
* @returns - array of sibling hashes, from leaf (inclusive) to root
* (exclusive) needed to prove inclusion of the specified hash. undefined if no
* path is found
*/
export declare function findScriptPath(node: HashTree, hash: Buffer): Buffer[] | undefined;
export declare function tapleafHash(leaf: Tapleaf): Buffer;
export declare function tapTweakHash(pubKey: Buffer, h: Buffer | undefined): Buffer;
export declare function tweakKey(pubKey: Buffer, h: Buffer | undefined): TweakedPublicKey | null;
export {};
108 changes: 108 additions & 0 deletions src/payments/bip341.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
exports.tweakKey = exports.tapTweakHash = exports.tapleafHash = exports.findScriptPath = exports.toHashTree = exports.rootHashFromPath = exports.MAX_TAPTREE_DEPTH = exports.LEAF_VERSION_TAPSCRIPT = void 0;
const buffer_1 = require('buffer');
const ecc_lib_1 = require('../ecc_lib');
const bcrypto = require('../crypto');
const bufferutils_1 = require('../bufferutils');
const types_1 = require('../types');
exports.LEAF_VERSION_TAPSCRIPT = 0xc0;
exports.MAX_TAPTREE_DEPTH = 128;
const isHashBranch = ht => 'left' in ht && 'right' in ht;
function rootHashFromPath(controlBlock, leafHash) {
if (controlBlock.length < 33)
throw new TypeError(
`The control-block length is too small. Got ${
controlBlock.length
}, expected min 33.`,
);
const m = (controlBlock.length - 33) / 32;
let kj = leafHash;
for (let j = 0; j < m; j++) {
const ej = controlBlock.slice(33 + 32 * j, 65 + 32 * j);
if (kj.compare(ej) < 0) {
kj = tapBranchHash(kj, ej);
} else {
kj = tapBranchHash(ej, kj);
}
}
return kj;
}
exports.rootHashFromPath = rootHashFromPath;
/**
* Build a hash tree of merkle nodes from the scripts binary tree.
* @param scriptTree - the tree of scripts to pairwise hash.
*/
function toHashTree(scriptTree) {
if ((0, types_1.isTapleaf)(scriptTree))
return { hash: tapleafHash(scriptTree) };
const hashes = [toHashTree(scriptTree[0]), toHashTree(scriptTree[1])];
hashes.sort((a, b) => a.hash.compare(b.hash));
const [left, right] = hashes;
return {
hash: tapBranchHash(left.hash, right.hash),
left,
right,
};
}
exports.toHashTree = toHashTree;
/**
* Given a HashTree, finds the path from a particular hash to the root.
* @param node - the root of the tree
* @param hash - the hash to search for
* @returns - array of sibling hashes, from leaf (inclusive) to root
* (exclusive) needed to prove inclusion of the specified hash. undefined if no
* path is found
*/
function findScriptPath(node, hash) {
if (isHashBranch(node)) {
const leftPath = findScriptPath(node.left, hash);
if (leftPath !== undefined) return [...leftPath, node.right.hash];
const rightPath = findScriptPath(node.right, hash);
if (rightPath !== undefined) return [...rightPath, node.left.hash];
} else if (node.hash.equals(hash)) {
return [];
}
return undefined;
}
exports.findScriptPath = findScriptPath;
function tapleafHash(leaf) {
const version = leaf.version || exports.LEAF_VERSION_TAPSCRIPT;
return bcrypto.taggedHash(
'TapLeaf',
buffer_1.Buffer.concat([
buffer_1.Buffer.from([version]),
serializeScript(leaf.output),
]),
);
}
exports.tapleafHash = tapleafHash;
function tapTweakHash(pubKey, h) {
return bcrypto.taggedHash(
'TapTweak',
buffer_1.Buffer.concat(h ? [pubKey, h] : [pubKey]),
);
}
exports.tapTweakHash = tapTweakHash;
function tweakKey(pubKey, h) {
if (!buffer_1.Buffer.isBuffer(pubKey)) return null;
if (pubKey.length !== 32) return null;
if (h && h.length !== 32) return null;
const tweakHash = tapTweakHash(pubKey, h);
const res = (0, ecc_lib_1.getEccLib)().xOnlyPointAddTweak(pubKey, tweakHash);
if (!res || res.xOnlyPubkey === null) return null;
return {
parity: res.parity,
x: buffer_1.Buffer.from(res.xOnlyPubkey),
};
}
exports.tweakKey = tweakKey;
function tapBranchHash(a, b) {
return bcrypto.taggedHash('TapBranch', buffer_1.Buffer.concat([a, b]));
}
function serializeScript(s) {
const varintLen = bufferutils_1.varuint.encodingLength(s.length);
const buffer = buffer_1.Buffer.allocUnsafe(varintLen); // better
bufferutils_1.varuint.encode(s.length, buffer);
return buffer_1.Buffer.concat([buffer, s]);
}
7 changes: 6 additions & 1 deletion src/payments/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
/// <reference types="node" />
import { Network } from '../networks';
import { Taptree } from '../types';
import { p2data as embed } from './embed';
import { p2ms } from './p2ms';
import { p2pk } from './p2pk';
import { p2pkh } from './p2pkh';
import { p2sh } from './p2sh';
import { p2wpkh } from './p2wpkh';
import { p2wsh } from './p2wsh';
import { p2tr } from './p2tr';
export interface Payment {
name?: string;
network?: Network;
Expand All @@ -17,11 +19,14 @@ export interface Payment {
pubkeys?: Buffer[];
input?: Buffer;
signatures?: Buffer[];
internalPubkey?: Buffer;
pubkey?: Buffer;
signature?: Buffer;
address?: string;
hash?: Buffer;
redeem?: Payment;
redeemVersion?: number;
scriptTree?: Taptree;
witness?: Buffer[];
}
export declare type PaymentCreator = (a: Payment, opts?: PaymentOpts) => Payment;
Expand All @@ -33,4 +38,4 @@ export interface PaymentOpts {
export declare type StackElement = Buffer | number;
export declare type Stack = StackElement[];
export declare type StackFunction = () => Stack;
export { embed, p2ms, p2pk, p2pkh, p2sh, p2wpkh, p2wsh };
export { embed, p2ms, p2pk, p2pkh, p2sh, p2wpkh, p2wsh, p2tr };
Loading