Skip to content

Commit 4670b45

Browse files
chore(utxo-core): added helper function to create attestation
TICKET: BTC-2047
1 parent 9c73ac1 commit 4670b45

File tree

2 files changed

+39
-20
lines changed

2 files changed

+39
-20
lines changed

modules/utxo-core/src/paygo/psbt/PayGoUtils.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import {
1111
ErrorPayGoAddressProofFailedVerification,
1212
} from './Errors';
1313

14+
const NILLUUID = '00000000-0000-0000-0000-000000000000';
15+
1416
/** This function adds the entropy and signature into the PSBT output unknown key vals.
1517
* We store the entropy so that we reconstruct the message <ENTROPY><ADDRESS><UUID>
1618
* to later verify.
@@ -45,7 +47,6 @@ export function addPayGoAddressProof(
4547
export function verifyPayGoAddressProof(
4648
psbt: utxolib.bitgo.UtxoPsbt,
4749
outputIndex: number,
48-
uuid: string,
4950
verificationPubkey: Buffer
5051
): void {
5152
const psbtOutputs = checkForOutput(psbt.data.outputs, outputIndex);
@@ -74,7 +75,7 @@ export function verifyPayGoAddressProof(
7475
const addressFromOutput = utxolib.address.fromOutputScript(output.script, psbt.network);
7576

7677
// We construct our message <ENTROPY><ADDRESS><UUID>
77-
const message = Buffer.concat([entropy, Buffer.from(addressFromOutput), Buffer.from(uuid)]);
78+
const message = createPayGoAttestationBuffer(addressFromOutput, entropy);
7879

7980
if (!verifyMessage(message.toString(), verificationPubkey, signature, utxolib.networks.bitcoin)) {
8081
throw new ErrorPayGoAddressProofFailedVerification();
@@ -108,3 +109,15 @@ export function getPayGoAddressProofOutputIndex(psbt: utxolib.bitgo.UtxoPsbt): n
108109
export function psbtOutputIncludesPaygoAddressProof(psbt: utxolib.bitgo.UtxoPsbt): boolean {
109110
return getPayGoAddressProofOutputIndex(psbt) !== undefined;
110111
}
112+
113+
/** This function reconstructs the proof <ENTROPY><ADDRESS><UUID>
114+
* given the address and entropy.
115+
*
116+
* @param address
117+
* @param entropy
118+
* @returns
119+
*/
120+
export function createPayGoAttestationBuffer(address: string, entropy: Buffer): Buffer {
121+
const addressBuffer = Buffer.from(address);
122+
return Buffer.concat([entropy, addressBuffer, Buffer.from(NILLUUID)]);
123+
}

modules/utxo-core/test/paygo/psbt/PayGoUtils.ts

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { checkForOutput } from 'bip174/src/lib/utils';
88

99
import {
1010
addPayGoAddressProof,
11+
createPayGoAttestationBuffer,
1112
getPayGoAddressProofOutputIndex,
1213
psbtOutputIncludesPaygoAddressProof,
1314
verifyPayGoAddressProof,
@@ -37,7 +38,7 @@ const attestationPubKey = dummyPub1.user.publicKey;
3738
const attestationPrvKey = dummyPub1.user.privateKey!;
3839

3940
// UUID structure
40-
const nilUUID = '00000000-0000-0000-0000-000000000000';
41+
const nillUUID = '00000000-0000-0000-0000-000000000000';
4142

4243
// our xpub converted to base58 address
4344
const addressToVerify = utxolib.address.toBase58Check(
@@ -47,7 +48,7 @@ const addressToVerify = utxolib.address.toBase58Check(
4748
);
4849

4950
// this should be retuning a Buffer
50-
const addressProofBuffer = generatePayGoAttestationProof(nilUUID, Buffer.from(addressToVerify));
51+
const addressProofBuffer = generatePayGoAttestationProof(nillUUID, Buffer.from(addressToVerify));
5152
const addressProofMsgBuffer = parseVaspProof(addressProofBuffer);
5253
// We know that that the entropy is a set 64 bytes.
5354
const addressProofEntropy = addressProofMsgBuffer.subarray(0, 65);
@@ -73,25 +74,12 @@ describe('addPaygoAddressProof and verifyPaygoAddressProof', () => {
7374
});
7475
}
7576

76-
it('should fail a proof verification with wrong UUID', () => {
77-
const outputIndex = 0;
78-
const psbt = getTestPsbt();
79-
addPayGoAddressProof(psbt, outputIndex, sig, addressProofEntropy);
80-
const output = checkForOutput(psbt.data.outputs, outputIndex);
81-
const proofInPsbt = getPaygoProprietaryKey(output.unknownKeyVals!);
82-
assert(proofInPsbt.length === 1);
83-
assert.throws(
84-
() => verifyPayGoAddressProof(psbt, 0, '00000000-0000-0000-0000-000000000001', attestationPubKey),
85-
(e: any) => e.message === 'Cannot verify the paygo address signature with the provided pubkey.'
86-
);
87-
});
88-
8977
it('should add and verify a valid paygo address proof on the PSBT', () => {
9078
const psbt = getTestPsbt();
9179
psbt.addOutput({ script: utxolib.address.toOutputScript(addressToVerify, network), value: BigInt(10000) });
9280
const outputIndex = psbt.data.outputs.length - 1;
9381
addPayGoAddressProof(psbt, outputIndex, sig, addressProofEntropy);
94-
verifyPayGoAddressProof(psbt, outputIndex, nilUUID, attestationPubKey);
82+
verifyPayGoAddressProof(psbt, outputIndex, attestationPubKey);
9583
});
9684

9785
it('should throw an error if there are multiple PayGo proprietary keys in the PSBT', () => {
@@ -104,7 +92,7 @@ describe('addPaygoAddressProof and verifyPaygoAddressProof', () => {
10492
assert(proofInPsbt.length !== 0);
10593
assert(proofInPsbt.length > 1);
10694
assert.throws(
107-
() => verifyPayGoAddressProof(psbt, outputIndex, nilUUID, attestationPubKey),
95+
() => verifyPayGoAddressProof(psbt, outputIndex, attestationPubKey),
10896
(e: any) => e.message === 'There are multiple paygo address proofs encoded in the PSBT. Something went wrong.'
10997
);
11098
});
@@ -114,7 +102,7 @@ describe('verifyPaygoAddressProof', () => {
114102
it('should throw an error if there is no PayGo address in PSBT', () => {
115103
const psbt = getTestPsbt();
116104
assert.throws(
117-
() => verifyPayGoAddressProof(psbt, 0, nilUUID, attestationPubKey),
105+
() => verifyPayGoAddressProof(psbt, 0, attestationPubKey),
118106
(e: any) => e.message === 'There is no paygo address proof encoded in the PSBT at output 0.'
119107
);
120108
});
@@ -146,3 +134,21 @@ describe('getPaygoAddressProofIndex', () => {
146134
);
147135
});
148136
});
137+
138+
describe('createPayGoAttestationBuffer', () => {
139+
it('should create a PayGo Attestation proof matching with original proof', () => {
140+
const payGoAttestationProof = createPayGoAttestationBuffer(addressToVerify, addressProofEntropy);
141+
assert.strictEqual(payGoAttestationProof.toString(), addressProofMsgBuffer.toString());
142+
assert(Buffer.compare(payGoAttestationProof, addressProofMsgBuffer) === 0);
143+
});
144+
145+
it('should create a PayGo Attestation proof that does not match with different uuid', () => {
146+
const addressProofBufferDiffUuid = generatePayGoAttestationProof(
147+
'00000000-0000-0000-0000-000000000001',
148+
Buffer.from(addressToVerify)
149+
);
150+
const payGoAttestationProof = createPayGoAttestationBuffer(addressToVerify, addressProofEntropy);
151+
assert.notStrictEqual(payGoAttestationProof.toString(), addressProofBufferDiffUuid.toString());
152+
assert(Buffer.compare(payGoAttestationProof, addressProofBufferDiffUuid) !== 0);
153+
});
154+
});

0 commit comments

Comments
 (0)