From 0bcfaf4c878f62b8aef2926318690b925efcba30 Mon Sep 17 00:00:00 2001 From: Anmol Sharma Date: Sun, 3 Mar 2024 11:07:39 +0530 Subject: [PATCH] feat: update labelled address creation logic to match BIP352 Signed-off-by: Anmol Sharma --- packages/core/src/encoding.ts | 31 +++++++++++---- packages/core/test/encoding.spec.ts | 10 ++--- packages/core/test/fixtures/encoding.ts | 50 +++++++++++++++++-------- 3 files changed, 62 insertions(+), 29 deletions(-) diff --git a/packages/core/src/encoding.ts b/packages/core/src/encoding.ts index 0f29ff9..fba6105 100644 --- a/packages/core/src/encoding.ts +++ b/packages/core/src/encoding.ts @@ -3,14 +3,15 @@ import secp256k1 from 'secp256k1'; import { Buffer } from 'buffer'; import { Network } from 'bitcoinjs-lib'; import { bitcoin } from 'bitcoinjs-lib/src/networks'; +import { createTaggedHash, serialiseUint32 } from './utility'; export const encodeSilentPaymentAddress = ( - scanKey: Uint8Array, - spendKey: Uint8Array, + scanPubKey: Uint8Array, + spendPubKey: Uint8Array, network: Network = bitcoin, version: number = 0, ): string => { - const data = bech32m.toWords(Buffer.concat([scanKey, spendKey])); + const data = bech32m.toWords(Buffer.concat([scanPubKey, spendPubKey])); data.unshift(version); return bech32m.encode(hrpFromNetwork(network), data, 1023); @@ -35,14 +36,28 @@ export const decodeSilentPaymentAddress = ( }; export const createLabeledSilentPaymentAddress = ( - scanKey: Uint8Array, - spendKey: Uint8Array, - m: Buffer, + scanPrivKey: Uint8Array, + spendPubKey: Uint8Array, + m: number, network: Network = bitcoin, version: number = 0, ) => { - spendKey = secp256k1.publicKeyTweakAdd(spendKey, m, true); - return encodeSilentPaymentAddress(scanKey, spendKey, network, version); + const label = createTaggedHash( + 'BIP0352/Label', + Buffer.concat([scanPrivKey, serialiseUint32(m)]), + ); + const scanPubKey = secp256k1.publicKeyCreate(scanPrivKey); + const tweakedSpendPubKey = secp256k1.publicKeyTweakAdd( + spendPubKey, + label, + true, + ); + return encodeSilentPaymentAddress( + scanPubKey, + tweakedSpendPubKey, + network, + version, + ); }; const hrpFromNetwork = (network: Network): string => { diff --git a/packages/core/test/encoding.spec.ts b/packages/core/test/encoding.spec.ts index 2b7fb83..dc95b6c 100644 --- a/packages/core/test/encoding.spec.ts +++ b/packages/core/test/encoding.spec.ts @@ -27,14 +27,14 @@ describe('Encoding', () => { it.each(labelled)( 'should create a labeled silent payment address', - (data) => { + ({ scanPrivKey, spendPubKey, label, address }) => { expect( createLabeledSilentPaymentAddress( - Buffer.from(data.scanKey, 'hex'), - Buffer.from(data.spendKey, 'hex'), - Buffer.from(data.label, 'hex'), + Buffer.from(scanPrivKey, 'hex'), + Buffer.from(spendPubKey, 'hex'), + label, ), - ).toBe(data.address); + ).toBe(address); }, ); }); diff --git a/packages/core/test/fixtures/encoding.ts b/packages/core/test/fixtures/encoding.ts index 7cdaa53..3cf33bf 100644 --- a/packages/core/test/fixtures/encoding.ts +++ b/packages/core/test/fixtures/encoding.ts @@ -27,30 +27,48 @@ export const unlabelled = [ export const labelled = [ { - scanKey: - '0220bcfac5b99e04ad1a06ddfb016ee13582609d60b6291e98d01a9bc9a16c96d4', - spendKey: + scanPrivKey: + '11b7a82e06ca2648d5fded2366478078ec4fc9dc1d8ff487518226f229d768fd', + spendPubKey: + '03bc95144daf15336db3456825c70ced0a4462f89aca42c4921ee7ccb2b3a44796', + label: 0, + address: + 'sp1qqw6vczcfpdh5nf5y2ky99kmqae0tr30hgdfg88parz50cp80wd2wqqlv6saelkk5snl4wfutyxrchpzzwm8rjp3z6q7apna59z9huq4x754e5atr', + }, + { + scanPrivKey: + '0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c', + spendPubKey: '025cc9856d6f8375350e123978daac200c260cb5b5ae83106cab90484dcd8fcf36', - label: '0000000000000000000000000000000000000000000000000000000000000001', + label: 1, address: - 'sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqah4hxfsjdwyaeel4g8x2npkj7qlvf2692l5760z5ut0ggnlrhdzsy3cvsj', + 'sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqaxww2fnhrx05cghth75n0qcj59e3e2anscr0q9wyknjxtxycg07y3pevyj', }, { - scanKey: - '0220bcfac5b99e04ad1a06ddfb016ee13582609d60b6291e98d01a9bc9a16c96d4', - spendKey: + scanPrivKey: + '0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c', + spendPubKey: '025cc9856d6f8375350e123978daac200c260cb5b5ae83106cab90484dcd8fcf36', - label: '0000000000000000000000000000000000000000000000000000000000000539', + label: 2, address: - 'sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgq562yg7htxyg8eq60rl37uul37jy62apnf5ru62uef0eajpdfrnp5cmqndj', + 'sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjex54dmqmmv6rw353tsuqhs99ydvadxzrsy9nuvk74epvee55drs734pqq', }, { - scanKey: - '03b4cc0b090b6f49a684558852db60ee5eb1c5f74352839c3d18a8fc04ef7354e0', - spendKey: - '03bc95144daf15336db3456825c70ced0a4462f89aca42c4921ee7ccb2b3a44796', - label: '91cb04398a508c9d995ff4a18e5eae24d5e9488309f189120a3fdbb977978c46', + scanPrivKey: + '0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c', + spendPubKey: + '025cc9856d6f8375350e123978daac200c260cb5b5ae83106cab90484dcd8fcf36', + label: 3, address: - 'sp1qqw6vczcfpdh5nf5y2ky99kmqae0tr30hgdfg88parz50cp80wd2wqqll5497pp2gcr4cmq0v5nv07x8u5jswmf8ap2q0kxmx8628mkqanyu63ck8', + 'sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqsg59z2rppn4qlkx0yz9sdltmjv3j8zgcqadjn4ug98m3t6plujsq9qvu5n', + }, + { + scanPrivKey: + '0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c', + spendPubKey: + '025cc9856d6f8375350e123978daac200c260cb5b5ae83106cab90484dcd8fcf36', + label: 1001337, + address: + 'sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgq7c2zfthc6x3a5yecwc52nxa0kfd20xuz08zyrjpfw4l2j257yq6qgnkdh5', }, ];