Skip to content

Commit f704d4d

Browse files
committed
bitcoinjs#1552 playing around, can be ignored
1 parent 64fbf13 commit f704d4d

File tree

8 files changed

+116
-8
lines changed

8 files changed

+116
-8
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ __removed__
149149
- Removed `networks.litecoin`, BYO non-Bitcoin networks instead (#1095)
150150
- Removed `script.isCanonicalSignature`, use `script.isCanonicalScriptSignature` instead (#1094)
151151
- Removed `script.*.input/output/check` functions (`templates`), use `payments.*` instead (`templates` previously added in #681, #682) (#1119)
152+
//
152153
- Removed dependency `bigi`, uses `bn.js` internally now (via `tiny-secp256k1`) (#1070, #1112)
153154
- Removed public access to `ECPair` constructor, use exported functions `ECPair.fromPrivateKey`, `ECPair.fromWIF`, `ECPair.makeRandom`, or `ECPair.fromPublicKey` (#1070)
154155

p2tr-witness.js

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
const BN = require('bn.js'); // TODO: remove? see changelog bn.js
2+
3+
const ANNEX_PREFIX = 0x50;
4+
const EC_P = Buffer.from('fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f', 'hex');
5+
const P = new BN(EC_P);
6+
const P_QUADRATIC_RESIDUE = P.addn(1).divn(4);
7+
const BN_3 = new BN(3);
8+
const BN_7 = new BN(7);
9+
10+
const witnessHex = [
11+
"9675a9982c6398ea9d441cb7a943bcd6ff033cc3a2e01a0178a7d3be4575be863871c6bf3eef5ecd34721c784259385ca9101c3a313e010ac942c99de05aaaa602",
12+
"5799cf4b193b730fb99580b186f7477c2cca4d28957326f6f1a5d14116438530e7ec0ce1cd465ad96968ae8a6a09d4d37a060a115919f56fcfebe7b2277cc2df5cc08fb6cda9105ee2512b2e22635aba",
13+
"7520c7b5db9562078049719228db2ac80cb9643ec96c8055aa3b29c2c03d4d99edb0ac",
14+
"c1a7957acbaaf7b444c53d9e0c9436e8a8a3247fd515095d66ddf6201918b40a3668f9a4ccdffcf778da624dca2dda0b08e763ec52fd4ad403ec7563a3504d0cc168b9a77a410029e01dac89567c9b2e6cd726e840351df3f2f58fefe976200a19244150d04153909f660184d656ee95fa7bf8e1d4ec83da1fca34f64bc279b76d257ec623e08baba2cfa4ea9e99646e88f1eb1668c00c0f15b7443c8ab83481611cc3ae85eb89a7bfc40067eb1d2e6354a32426d0ce710e88bc4cc0718b99c325509c9d02a6a980d675a8969be10ee9bef82cafee2fc913475667ccda37b1bc7f13f64e56c449c532658ba8481631c02ead979754c809584a875951619cec8fb040c33f06468ae0266cd8693d6a64cea5912be32d8de95a6da6300b0c50fdcd6001ea41126e7b7e5280d455054a816560028f5ca53c9a50ee52f10e15c5337315bad1f5277acb109a1418649dc6ead2fe14699742fee7182f2f15e54279c7d932ed2799d01d73c97e68bbc94d6f7f56ee0a80efd7c76e3169e10d1a1ba3b5f1eb02369dc43af687461c7a2a3344d13eb5485dca29a67f16b4cb988923060fd3b65d0f0352bb634bcc44f2fe668836dcd0f604150049835135dc4b4fbf90fb334b3938a1f137eb32f047c65b85e6c1173b890b6d0162b48b186d1f1af8521945924ac8ac8efec321bf34f1d4b3d4a304a10313052c652d53f6ecb8a55586614e8950cde9ab6fe8e22802e93b3b9139112250b80ebc589aba231af535bb20f7eeec2e412f698c17f3fdc0a2e20924a5e38b21a628a9e3b2a61e35958e60c7f5087c"
15+
];
16+
17+
const witness = witnessHex.map(w => Buffer.from(w, 'hex'));
18+
19+
if (!witness || !witness.length) {
20+
throw new Error('The witness stack has 0 elements');
21+
}
22+
23+
// check for annex
24+
if (witness.length >= 2 && (witness[witness.length - 1][0] === ANNEX_PREFIX)) {
25+
witness.pop(); // remove annex, ignored by taproot
26+
}
27+
28+
// key path spending
29+
if (witness.length === 1) {
30+
// the only element is the signature
31+
// must be checked against the tweaked public key
32+
// TODO
33+
return
34+
}
35+
36+
// script path spending
37+
const controlBlock = witness[witness.length - 1];
38+
if (controlBlock.length < 33) {
39+
throw new Error(`The control-block length is too small. Got ${controlBlock.length}, expected 33.`);
40+
}
41+
if ((controlBlock.length - 33) % 32 !== 0) {
42+
throw new Error('The control-block length is incorrect!');
43+
}
44+
if ((controlBlock.length - 33) / 32 > 128) {
45+
throw new Error(`The control-block length is too large. Got ${controlBlock.length}.`);
46+
}
47+
const script = witness[witness.length - 2];
48+
49+
const pxxx = controlBlock.slice(1, 33);
50+
51+
52+
const leafVersion = controlBlock[0] & 0xfe;
53+
54+
55+
56+
function liftX(b) {
57+
console.log('liftX IN');
58+
// check if x instance of buffer and length 32
59+
const x = new BN(b);
60+
if (x.gte(P)) return null;
61+
const yy = x.pow(BN_3).add(BN_7).mod(P);
62+
// const y = yy.pow(P_QUADRATIC_RESIDUE).mod(P);
63+
64+
console.log('liftX OUT');
65+
return yy;
66+
}
67+
68+
69+
// const p = BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f');
70+
// const q = (p + 1n) / 4n;
71+
72+
// function liftX(hex) {
73+
// console.log('liftX IN');
74+
75+
// const x = BigInt(hex);
76+
77+
// if (x >= p) return null;
78+
// const yy = (x ** 3n + 7n) % p;
79+
// // const y = (yy ** q) % p;
80+
81+
82+
// console.log('liftX OUT');
83+
// return yy;
84+
// }
85+
86+
const x = '0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798';
87+
const y = liftX(x);
88+
console.log('y', y.toJSON());

package-lock.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
"bip32": "^2.0.4",
5555
"bip66": "^1.1.0",
5656
"bitcoin-ops": "^1.4.0",
57+
"bn": "^1.0.5",
5758
"bs58check": "^2.0.0",
5859
"create-hash": "^1.1.0",
5960
"create-hmac": "^1.1.3",

play.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
const bscript = require('./src/script');
2+
const {
3+
Transaction
4+
} = require('./src/transaction')
5+
6+
const hex = '4da5fbaa000000002251206d1cb3f7811934f57a680ce8cabda34527cbcebf218a0fdc833b7a8e7df361ee';
7+
const prevout = Buffer.from(hex, 'hex');
8+
const prevsScriptOut = prevout.slice(9)
9+
10+
const asm = bscript.toASM(prevsScriptOut)
11+
console.log('######## asm: ', asm)

test/fixtures/p2tr.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
"comment": "tapscript/input80limit"
6161
},
6262
{
63+
6364
"tx": "02000000010ab81a3da7f63b84ecc2f61f43ec9f28fceac00c4e4b5ed68dd6da20771c540e1400000000eea0cdf0010ce5b000000000001600145aef668a7ef2d6515eec21e83a80866bc0eea46e16000000",
6465
"prevouts": [
6566
"2b606c01000000002251206acd3cc9529163c83c8726287e171bc36722ca3aee50cf068ad424487797c506"

ts_src/payments/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,15 @@ export interface Payment {
1414
data?: Buffer[];
1515
m?: number;
1616
n?: number;
17-
pubkeys?: Buffer[];
17+
pubkeys?: Buffer[]; // <-- can be used for taproot
1818
input?: Buffer;
1919
signatures?: Buffer[];
2020
pubkey?: Buffer;
2121
signature?: Buffer;
2222
address?: string;
2323
hash?: Buffer;
2424
redeem?: Payment;
25+
taprootRedeems?: Payment[];
2526
witness?: Buffer[];
2627
}
2728

ts_src/payments/p2tr.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const typef = require('typeforce');
77
const OPS = bscript.OPS;
88
const ecc = require('tiny-secp256k1');
99

10-
const { bech32 } = require('bech32');
10+
const { bech32, bech32m } = require('bech32');
1111

1212
const EMPTY_BUFFER = Buffer.alloc(0);
1313

@@ -34,8 +34,8 @@ function chunkHasUncompressedPubkey(chunk: StackElement): boolean {
3434

3535
// input: <>
3636
// witness: [redeemScriptSig ...] {redeemScript}
37-
// output: OP_0 {sha256(redeemScript)}
38-
export function p2wsh(a: Payment, opts?: PaymentOpts): Payment {
37+
// output: OP_1 {publicKey}
38+
export function p2tr(a: Payment, opts?: PaymentOpts): Payment {
3939
if (!a.address && !a.hash && !a.output && !a.redeem && !a.witness)
4040
throw new TypeError('Not enough data');
4141
opts = Object.assign({ validate: true }, opts || {});
@@ -61,9 +61,9 @@ export function p2wsh(a: Payment, opts?: PaymentOpts): Payment {
6161
);
6262

6363
const _address = lazy.value(() => {
64-
const result = bech32.decode(a.address);
64+
const result = bech32m.decode(a.address);
6565
const version = result.words.shift();
66-
const data = bech32.fromWords(result.words);
66+
const data = bech32m.fromWords(result.words);
6767
return {
6868
version,
6969
prefix: result.prefix,
@@ -94,12 +94,12 @@ export function p2wsh(a: Payment, opts?: PaymentOpts): Payment {
9494
});
9595
lazy.prop(o, 'output', () => {
9696
if (!o.hash) return;
97-
return bscript.compile([OPS.OP_0, o.hash]);
97+
return bscript.compile([OPS.OP_1, o.hash]);
9898
});
9999
lazy.prop(o, 'redeem', () => {
100100
if (!a.witness) return;
101101
return {
102-
output: a.witness[a.witness.length - 1],
102+
output: a.witness[a.witness.length - 1], // <-- last on the stack is the reedem lock script
103103
input: EMPTY_BUFFER,
104104
witness: a.witness.slice(0, -1),
105105
};

0 commit comments

Comments
 (0)