From 0188f22ffd565b040248203ee7655ced1c22f768 Mon Sep 17 00:00:00 2001 From: David Kaplan Date: Mon, 23 Jan 2023 13:20:44 -0500 Subject: [PATCH 1/2] feat: bump bip174 BG-54756 --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 73ded9fb5..6c606efde 100644 --- a/package-lock.json +++ b/package-lock.json @@ -595,9 +595,9 @@ "dev": true }, "bip174": { - "version": "npm:@bitgo/bip174@3.0.0", - "resolved": "https://registry.npmjs.org/@bitgo/bip174/-/bip174-3.0.0.tgz", - "integrity": "sha512-Qv98vy6l1WgZwrxKx7IPYY91/+Z3tpALVSDn+Ic9qCsxygCq9gYw5eL8q3kd7LYTFLy/HgcqhcMOa83Spbp4JA==" + "version": "npm:@bitgo-forks/bip174@3.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@bitgo-forks/bip174/-/bip174-3.0.0-rc.1.tgz", + "integrity": "sha512-eGi5die7Q7O3yPtkcGF1gD7qLlJLiLnYI4DpFTF6tUhUo71gy3RoXAAeeJA2fLpnVoJofXnLdLfpcO6OEZAsvw==" }, "bip32": { "version": "3.0.1", diff --git a/package.json b/package.json index 8507e45c8..2f8113267 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ ], "dependencies": { "bech32": "^2.0.0", - "bip174": "npm:@bitgo/bip174@3.0.0", + "bip174": "npm:@bitgo-forks/bip174@3.0.0-rc.1", "bs58check": "^2.1.2", "create-hash": "^1.1.0", "fastpriorityqueue": "^0.7.1", From 4a88a1eb9edc32c8986fcef5afeab0b644e799de Mon Sep 17 00:00:00 2001 From: David Kaplan Date: Mon, 23 Jan 2023 13:21:34 -0500 Subject: [PATCH 2/2] feat: pass through bip32PathsAbsolute flag into bip174 psbt BG-54756 --- src/psbt.d.ts | 9 ++++++--- src/psbt.js | 4 +++- test/psbt.spec.ts | 24 ++++++++++++++++++++++++ ts_src/psbt.ts | 20 ++++++++++++++++---- 4 files changed, 49 insertions(+), 8 deletions(-) diff --git a/src/psbt.d.ts b/src/psbt.d.ts index cb3bda457..8b8e29437 100644 --- a/src/psbt.d.ts +++ b/src/psbt.d.ts @@ -53,9 +53,9 @@ export declare type ValidateSigFunction = (pubkey: Buffer, msghash: Buffer, sign */ export declare class Psbt { readonly data: PsbtBase; - static fromBase64(data: string, opts?: PsbtOptsOptional): Psbt; - static fromHex(data: string, opts?: PsbtOptsOptional): Psbt; - static fromBuffer(buffer: Buffer, opts?: PsbtOptsOptional): Psbt; + static fromBase64(data: string, opts?: PsbtDeserializeOptsOptional): Psbt; + static fromHex(data: string, opts?: PsbtDeserializeOptsOptional): Psbt; + static fromBuffer(buffer: Buffer, opts?: PsbtDeserializeOptsOptional): Psbt; protected static transactionFromBuffer(buffer: Buffer, _network: Network): Transaction; private __CACHE; private opts; @@ -112,6 +112,9 @@ interface PsbtOptsOptional { network?: Network; maximumFeeRate?: number; } +interface PsbtDeserializeOptsOptional extends PsbtOptsOptional { + bip32PathsAbsolute?: boolean; +} interface PsbtInputExtended extends PsbtInput, TransactionInput { } declare type PsbtOutputExtended = PsbtOutputExtendedAddress | PsbtOutputExtendedScript; diff --git a/src/psbt.js b/src/psbt.js index 7c8dd2fd4..03bc1ae89 100644 --- a/src/psbt.js +++ b/src/psbt.js @@ -100,7 +100,9 @@ class Psbt { return this.fromBuffer(buffer, opts); } static fromBuffer(buffer, opts = {}) { - const psbtBase = bip174_1.Psbt.fromBuffer(buffer, transactionFromBuffer); + const psbtBase = bip174_1.Psbt.fromBuffer(buffer, transactionFromBuffer, { + bip32PathsAbsolute: opts.bip32PathsAbsolute, + }); const psbt = new Psbt(opts, psbtBase); checkTxForDupeIns(psbt.__CACHE.__TX, psbt.__CACHE); return psbt; diff --git a/test/psbt.spec.ts b/test/psbt.spec.ts index 8c7c5206e..6e9eb9169 100644 --- a/test/psbt.spec.ts +++ b/test/psbt.spec.ts @@ -396,6 +396,30 @@ describe(`Psbt`, () => { }); }); + describe('deserialization', () => { + [true, false].forEach((bip32PathsAbsolute: boolean) => { + it(`bip32Derivation paths are ${ + bip32PathsAbsolute ? '' : 'not' + } absolute`, async () => { + const psbt = Psbt.fromBase64( + fixtures.signInputHD.checks[0].shouldSign.psbt, + { bip32PathsAbsolute }, + ); + const input = psbt.data.inputs[0]; + assert(input); + const bip32Derivations = input.bip32Derivation; + assert(bip32Derivations); + const bip32Derivation = bip32Derivations[0]; + assert(bip32Derivation); + const pathString = bip32Derivation.path; + assert(pathString); + const path = pathString.split('/'); + const bip32PathPrefix = bip32PathsAbsolute ? 'm' : `44'`; + assert(path[0] === bip32PathPrefix); + }); + }); + }); + describe('signAllInputsHDAsync', () => { fixtures.signInputHD.checks.forEach(f => { it(f.description, async () => { diff --git a/ts_src/psbt.ts b/ts_src/psbt.ts index e494c2b9b..865ad1818 100644 --- a/ts_src/psbt.ts +++ b/ts_src/psbt.ts @@ -97,18 +97,26 @@ const DEFAULT_OPTS: PsbtOpts = { * Transaction object. Such as fee rate not being larger than maximumFeeRate etc. */ export class Psbt { - static fromBase64(data: string, opts: PsbtOptsOptional = {}): Psbt { + static fromBase64( + data: string, + opts: PsbtDeserializeOptsOptional = {}, + ): Psbt { const buffer = Buffer.from(data, 'base64'); return this.fromBuffer(buffer, opts); } - static fromHex(data: string, opts: PsbtOptsOptional = {}): Psbt { + static fromHex(data: string, opts: PsbtDeserializeOptsOptional = {}): Psbt { const buffer = Buffer.from(data, 'hex'); return this.fromBuffer(buffer, opts); } - static fromBuffer(buffer: Buffer, opts: PsbtOptsOptional = {}): Psbt { - const psbtBase = PsbtBase.fromBuffer(buffer, transactionFromBuffer); + static fromBuffer( + buffer: Buffer, + opts: PsbtDeserializeOptsOptional = {}, + ): Psbt { + const psbtBase = PsbtBase.fromBuffer(buffer, transactionFromBuffer, { + bip32PathsAbsolute: opts.bip32PathsAbsolute, + }); const psbt = new Psbt(opts, psbtBase); checkTxForDupeIns(psbt.__CACHE.__TX, psbt.__CACHE); return psbt; @@ -775,6 +783,10 @@ interface PsbtOptsOptional { maximumFeeRate?: number; } +interface PsbtDeserializeOptsOptional extends PsbtOptsOptional { + bip32PathsAbsolute?: boolean; +} + interface PsbtOpts { network: Network; maximumFeeRate: number;