Skip to content

Commit 27a7b17

Browse files
committed
bitcoinjs#1522 bla, bla
1 parent 4bb70c7 commit 27a7b17

File tree

7 files changed

+61
-48
lines changed

7 files changed

+61
-48
lines changed

play/p2tr-witness.js

+33-38
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
const BN = require('bn.js'); // TODO: remove? see changelog bn.js
2+
const ecpair = require('../src/ecpair')
3+
const taggedHash = require('../src/crypto').taggedHash;
24

35
const ANNEX_PREFIX = 0x50;
4-
const EC_P = Buffer.from('fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f', 'hex');
5-
const P = new BN(EC_P);
6-
const P_REDUCTION = BN.red(P);
7-
const P_QUADRATIC_RESIDUE = P.addn(1).divn(4);
8-
const BN_3 = new BN(3);
9-
const BN_7 = new BN(7);
6+
const EC_N = Buffer.from('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141', 'hex');
7+
8+
const TAP_LEAF_TAG = Buffer.from('TapLeaf', 'utf8');
9+
const TAP_BRANCH_TAG = Buffer.from('TapBranch', 'utf8');
10+
const TAP_TWEAK_TAG = Buffer.from('TapTweak', 'utf8');
1011

1112
const witnessHex = [
1213
"9675a9982c6398ea9d441cb7a943bcd6ff033cc3a2e01a0178a7d3be4575be863871c6bf3eef5ecd34721c784259385ca9101c3a313e010ac942c99de05aaaa602",
@@ -42,48 +43,42 @@ if (controlBlock.length < 33) {
4243
if ((controlBlock.length - 33) % 32 !== 0) {
4344
throw new Error('The control-block length is incorrect!');
4445
}
45-
if ((controlBlock.length - 33) / 32 > 128) {
46+
const m = (controlBlock.length - 33) / 32;
47+
if (m > 128) {
4648
throw new Error(`The control-block length is too large. Got ${controlBlock.length}.`);
4749
}
4850
const script = witness[witness.length - 2];
4951

50-
const pxxx = controlBlock.slice(1, 33);
51-
52+
const p = controlBlock.slice(1, 33);
53+
const v = controlBlock[0] & 0xfe; // leaf version
5254

53-
const leafVersion = controlBlock[0] & 0xfe;
55+
const P = ecpair.liftX(p) // TODO: representation
5456

5557

58+
const k = [];
59+
const e = [];
60+
const xxx = Buffer.concat(Buffer.from(v), Buffer.from(compactSize(script.length)), script);
61+
k[0] = taggedHash(TAP_LEAF_TAG, xxx);
5662

57-
function liftX(b) {
58-
// check if x instance of buffer and length 32
59-
const x = new BN(b).toRed(P_REDUCTION);
60-
if (x.gte(P)) return null;
61-
const ySq = x.redPow(BN_3).add(BN_7).mod(P);
62-
const y = ySq.redPow(P_QUADRATIC_RESIDUE).mod(P);
6363

64-
console.log('ySq', ySq.toJSON());
65-
console.log('y2', y.redPow(new BN(2)).mod(P).toJSON());
66-
console.log('y', y.toJSON());
67-
return y;
64+
for (let j = 0; j < m - 1; j++) {
65+
e[j] = controlBlock.slice(33 + 32 * j, 65 + 32 * j);
66+
if (k[j].compare(e[j]) < 0) {
67+
k[j + 1] = taggedHash(TAP_BRANCH_TAG, k[j] || e[j]);
68+
} else {
69+
k[j + 1] = taggedHash(TAP_BRANCH_TAG, e[j] || k[j]);
70+
}
6871
}
6972

73+
const t = taggedHash(TAP_TWEAK_TAG, k[m + 1]);
74+
if (t.compare(EC_N) >= 0) {
75+
throw new Error('Over the order of secp256k1')
76+
}
7077

71-
// const p = BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f');
72-
// const q = (p + 1n) / 4n;
73-
74-
// function liftX(hex) {
75-
// console.log('liftX IN');
76-
77-
// const x = BigInt(hex);
78-
79-
// if (x >= p) return null;
80-
// const yy = (x ** 3n + 7n) % p;
81-
// // const y = (yy ** q) % p;
82-
83-
84-
// console.log('liftX OUT');
85-
// return yy;
86-
// }
78+
//pointFromScalar
79+
const T = ecpair.pointFromScalar(t);
80+
const Q = ecpair.addPoints(P, T);
8781

88-
const x = '0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798';
89-
const y = liftX(x);
82+
if (q !== x(Q) || (c[0] & 1) !== (y(Q) % 2)) {
83+
throw new Error('xxxxxx')
84+
}

play/play.js

+9-6
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
const bscript = require('../src/script');
2-
const {
3-
Transaction
4-
} = require('../src/transaction')
52

6-
const hex = '4da5fbaa000000002251206d1cb3f7811934f57a680ce8cabda34527cbcebf218a0fdc833b7a8e7df361ee';
3+
const hex = '7520c7b5db9562078049719228db2ac80cb9643ec96c8055aa3b29c2c03d4d99edb0ac';
74
const prevout = Buffer.from(hex, 'hex');
8-
const prevsScriptOut = prevout.slice(9)
5+
const prevsScriptOut = prevout; //.slice(9)
96

107
const asm = bscript.toASM(prevsScriptOut)
11-
console.log('######## asm: ', asm)
8+
console.log('######## asm: ', asm)
9+
10+
const taggedHash = require('../src/crypto').taggedHash;
11+
12+
const tag = Buffer.from('TapBranch', 'utf8')
13+
const hash = taggedHash(tag, prevout)
14+
console.log('hash', hash.toString('hex'));

src/crypto.js

+5
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,8 @@ function hash256(buffer) {
3333
return sha256(sha256(buffer));
3434
}
3535
exports.hash256 = hash256;
36+
function taggedHash(tag, buffer) {
37+
const tagHash = sha256(tag);
38+
return sha256(Buffer.concat([tagHash, tagHash, buffer]));
39+
}
40+
exports.taggedHash = taggedHash;

src/ecpair.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ function liftX(buffer) {
8787
typeforce(types.Buffer256bit, buffer);
8888
const x = new BN(buffer);
8989
if (x.gte(EC_P)) return null;
90-
const xRed = x.toRed(EC_P_REDUCTION);
91-
const ySq = xRed
90+
const x1 = x.toRed(EC_P_REDUCTION);
91+
const ySq = x1
9292
.redPow(BN_3)
9393
.add(BN_7)
9494
.mod(EC_P);
@@ -97,8 +97,9 @@ function liftX(buffer) {
9797
return null;
9898
}
9999
const y1 = (y & 1) === 0 ? y : EC_P.sub(y);
100+
// TODO: which is the best format to return the coordinates?
100101
return Buffer.concat([
101-
Buffer.from(x.toBuffer('be')),
102+
Buffer.from(x1.toBuffer('be')),
102103
Buffer.from(y1.toBuffer('be')),
103104
]);
104105
}

ts_src/crypto.ts

+5
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,8 @@ export function hash160(buffer: Buffer): Buffer {
3131
export function hash256(buffer: Buffer): Buffer {
3232
return sha256(sha256(buffer));
3333
}
34+
35+
export function taggedHash(tag: Buffer, buffer: Buffer): Buffer {
36+
const tagHash = sha256(tag);
37+
return sha256(Buffer.concat([tagHash, tagHash, buffer]));
38+
}

ts_src/ecpair.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -194,4 +194,7 @@ function makeRandom(options?: ECPairOptions): ECPair {
194194
return fromPrivateKey(d, options);
195195
}
196196

197-
export { makeRandom, fromPrivateKey, fromPublicKey, fromWIF, liftX };
197+
const pointFromScalar = ecc.pointFromScalar; // could use the fromPrivateKey...
198+
const pointAdd = ecc.pointAdd;
199+
200+
export { makeRandom, fromPrivateKey, fromPublicKey, fromWIF, liftX, pointFromScalar, pointAdd };

types/crypto.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ export declare function sha1(buffer: Buffer): Buffer;
33
export declare function sha256(buffer: Buffer): Buffer;
44
export declare function hash160(buffer: Buffer): Buffer;
55
export declare function hash256(buffer: Buffer): Buffer;
6+
export declare function taggedHash(tag: Buffer, buffer: Buffer): Buffer;

0 commit comments

Comments
 (0)