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