1+ import * as assert from 'assert'
2+ import { decodeProprietaryKey } from 'bip174/src/lib/proprietaryKeyVal' ;
3+ import { KeyValue } from 'bip174/src/lib/interfaces' ;
4+ import { checkForOutput } from 'bip174/src/lib/utils' ;
5+
6+ import { bip32 , networks , testutil } from '../../../src'
7+ import { addPaygoAddressProof , verifyPaygoAddressProof , getPaygoAddressProofOutputIndex , psbtOutputIncludesPaygoAddressProof } from "../../../src/bitgo/psbt/paygoAddressProof" ;
8+ import { generatePayGoAttestationProof , inputScriptTypes , outputScriptTypes } from '../../../src/testutil' ;
9+ import { ProprietaryKeySubtype , PSBT_PROPRIETARY_IDENTIFIER , RootWalletKeys } from '../../../src/bitgo' ;
10+
11+
12+ const network = networks . bitcoin ;
13+ const keys = [ 1 , 2 , 3 ] . map ( ( v ) => bip32 . fromSeed ( Buffer . alloc ( 16 , `test/2/${ v } ` ) , network ) )
14+ const rootWalletKeys = new RootWalletKeys ( [ keys [ 0 ] , keys [ 1 ] , keys [ 2 ] ] )
15+ // const dummyKey1 = rootWalletKeys.deriveForChainAndIndex(50, 200);
16+ const dummyKey2 = rootWalletKeys . deriveForChainAndIndex ( 60 , 201 ) ;
17+
18+ const psbtInputs = inputScriptTypes . map ( ( scriptType ) => ( { scriptType, value : BigInt ( 1000 ) } ) )
19+ const psbtOutputs = outputScriptTypes . map ( ( scriptType ) => ( { scriptType, value : BigInt ( 900 ) } ) )
20+ // const dummy1PubKey = dummyKey1.user.publicKey;
21+ // This generatePayGoAttestationProof function should be returning the bitcoin signed message
22+ const sig2 = dummyKey2 . user . privateKey ! ;
23+
24+ // wallet pub and priv key for tbtc
25+ const attestationPubKey = "xpub661MyMwAqRbcFU2Qx7pvGmmiQpVj8NcR7dSVpgqNChMkQyobpVWWERcrTb47WicmXwkhAY2VrC3hb29s18FDQWJf5pLm3saN6uLXAXpw1GV" ;
26+ const attestationPrvKey = "red" ;
27+ const nilUUID = '00000000-0000-0000-0000-000000000000' ;
28+ const addressProofBuffer = generatePayGoAttestationProof ( Buffer . from ( attestationPrvKey ) , nilUUID , Buffer . from ( address ) )
29+
30+
31+ function getTestPsbt ( ) {
32+ return testutil . constructPsbt (
33+ psbtInputs , psbtOutputs , network , rootWalletKeys , 'unsigned'
34+ )
35+ }
36+
37+ describe ( 'addPaygoAddressProof and verifyPaygoAddressProof' , ( ) => {
38+ function getPaygoProprietaryKey ( proprietaryKeyVals : KeyValue [ ] ) {
39+ return proprietaryKeyVals . map ( ( { key, value} ) => {
40+ return { key : decodeProprietaryKey ( key ) , value } ;
41+ } ) . filter ( ( keyValue ) => {
42+ return keyValue . key . identifier === PSBT_PROPRIETARY_IDENTIFIER && keyValue . key . subtype === ProprietaryKeySubtype . PAYGO_ADDRESS_ATTESTATION_PROOF
43+ } ) ;
44+ }
45+
46+ it ( "should fail a proof verification if the proof isn't valid" , ( ) => {
47+ const outputIndex = 0 ;
48+ const psbt = getTestPsbt ( ) ;
49+ addPaygoAddressProof ( psbt , outputIndex , Buffer . from ( addressProofBuffer ) , Buffer . from ( attestationPubKey ) ) ;
50+ const output = checkForOutput ( psbt . data . outputs , outputIndex ) ;
51+ const proofInPsbt = getPaygoProprietaryKey ( output . unknownKeyVals ! ) ;
52+ assert ( proofInPsbt . length === 1 )
53+ assert . throws ( ( ) => verifyPaygoAddressProof ( psbt , 0 , dummyKey2 . user . publicKey ) , ( e : any ) => e . message === 'Cannot verify the paygo address signature with the provided pubkey.' ) ;
54+ } ) ;
55+
56+ it ( "should add and verify a valid paygo address proof on the PSBT" , ( ) => {
57+ const outputIndex = 0 ;
58+ const psbt = getTestPsbt ( ) ;
59+ addPaygoAddressProof ( psbt , outputIndex , Buffer . from ( addressProofBuffer ) , Buffer . from ( attestationPubKey ) ) ;
60+ // should verify function return a boolean? that way we can assert
61+ // if this is verified, throws an error otherwise or false + error msg as an object
62+ verifyPaygoAddressProof ( psbt , outputIndex , Buffer . from ( attestationPubKey ) ) ;
63+ } ) ;
64+
65+ it ( "should throw an error if there are multiple PayGo proprietary keys in the PSBT" , ( ) => {
66+ const outputIndex = 0 ;
67+ const psbt = getTestPsbt ( ) ;
68+ addPaygoAddressProof ( psbt , outputIndex , Buffer . from ( addressProofBuffer ) , Buffer . from ( attestationPubKey ) ) ;
69+ addPaygoAddressProof ( psbt , outputIndex , Buffer . from ( sig2 ) , Buffer . from ( attestationPubKey ) ) ;
70+ const output = checkForOutput ( psbt . data . outputs , outputIndex ) ;
71+ const proofInPsbt = getPaygoProprietaryKey ( output . unknownKeyVals ! ) ;
72+ assert ( proofInPsbt . length !== 0 )
73+ assert ( proofInPsbt . length <= 1 )
74+ assert . throws ( ( ) => verifyPaygoAddressProof ( psbt , outputIndex , Buffer . from ( attestationPubKey ) ) , ( e : any ) => e . message === 'There are multiple paygo address proofs encoded in the PSBT. Something went wrong.' ) ;
75+ } ) ;
76+ } ) ;
77+
78+
79+ describe ( 'verifyPaygoAddressProof' , ( ) => {
80+ it ( 'should throw an error if there is no PayGo address in PSBT' , ( ) => {
81+ const psbt = getTestPsbt ( ) ;
82+ assert . throws ( ( ) => verifyPaygoAddressProof ( psbt , 0 , Buffer . from ( attestationPubKey ) ) , ( e : any ) => e . message === 'here is no paygo address proof encoded in the PSBT.' ) ;
83+ } ) ;
84+ } ) ;
85+
86+ describe ( 'getPaygoAddressProofIndex' , ( ) => {
87+ it ( 'should get PayGo address proof index from PSBT if there is one' , ( ) => {
88+ const psbt = getTestPsbt ( ) ;
89+ const outputIndex = 0 ;
90+ addPaygoAddressProof ( psbt , outputIndex , Buffer . from ( addressProofBuffer ) , Buffer . from ( attestationPubKey ) ) ;
91+ assert ( psbtOutputIncludesPaygoAddressProof ( psbt ) ) ;
92+ assert ( getPaygoAddressProofOutputIndex ( psbt ) === 0 )
93+ } ) ;
94+
95+ it ( "should return undefined if there is no PayGo address proof in PSBT" , ( ) => {
96+ const psbt = getTestPsbt ( ) ;
97+ assert ( getPaygoAddressProofOutputIndex ( psbt ) === undefined )
98+ assert ( ! psbtOutputIncludesPaygoAddressProof ( psbt ) )
99+ } ) ;
100+ } ) ;
0 commit comments