11import {
22 BitGoBase ,
3- getTxRequest ,
4- offerUserToBitgoRShare ,
5- getBitgoToUserRShare ,
6- sendUserToBitgoGShare ,
73 Wallet ,
84 IRequestTracer ,
95 EddsaUtils ,
106 BaseCoin ,
117 ApiKeyShare ,
128 TxRequest ,
9+ CommitmentShareRecord ,
10+ EncryptedSignerShareRecord ,
11+ SignShare ,
12+ SignatureShareRecord ,
13+ CustomCommitmentGeneratingFunction ,
14+ CustomRShareGeneratingFunction ,
15+ CustomGShareGeneratingFunction ,
1316} from '@bitgo/sdk-core' ;
14- import { EnclavedExpressClient } from '../clients/enclavedExpressClient' ;
15- import { exchangeEddsaCommitments } from '@bitgo/sdk-core/dist/src/bitgo/tss/common' ;
16- import logger from '../../../logger' ;
17+ import { EnclavedExpressClient , SignMpcCommitmentResponse } from '../clients/enclavedExpressClient' ;
18+
19+ /**
20+ * Creates custom EdDSA signing functions for use with enclaved express client
21+ */
22+ export function createEddsaCustomSigningFunctions (
23+ enclavedExpressClient : EnclavedExpressClient ,
24+ source : 'user' | 'backup' ,
25+ commonKeychain : string ,
26+ ) : {
27+ customCommitmentGenerator : CustomCommitmentGeneratingFunction ;
28+ customRShareGenerator : CustomRShareGeneratingFunction ;
29+ customGShareGenerator : CustomGShareGeneratingFunction ;
30+ } {
31+ // Create state to maintain data between rounds
32+ let commitmentResponse : SignMpcCommitmentResponse ;
33+
34+ // Create custom signing methods that maintain state
35+ const customCommitmentGenerator : CustomCommitmentGeneratingFunction = async ( params : {
36+ txRequest : TxRequest ;
37+ bitgoGpgPubKey ?: string ;
38+ } ) => {
39+ if ( ! params . bitgoGpgPubKey ) {
40+ throw new Error ( 'bitgoGpgPubKey is required for commitment share generation' ) ;
41+ }
42+ const response = await enclavedExpressClient . signMpcCommitment ( {
43+ txRequest : params . txRequest ,
44+ bitgoPublicGpgKey : params . bitgoGpgPubKey ,
45+ source,
46+ pub : commonKeychain ,
47+ } ) ;
48+ commitmentResponse = response ;
49+ return response ;
50+ } ;
51+
52+ const customRShareGenerator : CustomRShareGeneratingFunction = async ( params : {
53+ txRequest : TxRequest ;
54+ encryptedUserToBitgoRShare : EncryptedSignerShareRecord ;
55+ } ) => {
56+ if ( ! commitmentResponse ) {
57+ throw new Error ( 'Commitment must be completed before R-share generation' ) ;
58+ }
59+ const response = await enclavedExpressClient . signMpcRShare ( {
60+ txRequest : params . txRequest ,
61+ encryptedUserToBitgoRShare : params . encryptedUserToBitgoRShare ,
62+ encryptedDataKey : commitmentResponse . encryptedDataKey ,
63+ source,
64+ pub : commonKeychain ,
65+ } ) ;
66+ return { rShare : response . rShare } ;
67+ } ;
68+
69+ const customGShareGenerator : CustomGShareGeneratingFunction = async ( params : {
70+ txRequest : TxRequest ;
71+ userToBitgoRShare : SignShare ;
72+ bitgoToUserRShare : SignatureShareRecord ;
73+ bitgoToUserCommitment : CommitmentShareRecord ;
74+ } ) => {
75+ if ( ! commitmentResponse ) {
76+ throw new Error ( 'Commitment must be completed before G-share generation' ) ;
77+ }
78+ const response = await enclavedExpressClient . signMpcGShare ( {
79+ txRequest : params . txRequest ,
80+ bitgoToUserRShare : params . bitgoToUserRShare ,
81+ userToBitgoRShare : params . userToBitgoRShare ,
82+ bitgoToUserCommitment : params . bitgoToUserCommitment ,
83+ source,
84+ pub : commonKeychain ,
85+ } ) ;
86+ return response . gShare ;
87+ } ;
88+
89+ return {
90+ customCommitmentGenerator,
91+ customRShareGenerator,
92+ customGShareGenerator,
93+ } ;
94+ }
1795
1896export async function handleEddsaSigning (
1997 bitgo : BitGoBase ,
@@ -24,70 +102,15 @@ export async function handleEddsaSigning(
24102 reqId ?: IRequestTracer ,
25103) {
26104 const eddsaUtils = new EddsaUtils ( bitgo , wallet . baseCoin , wallet ) ;
27-
28- const { apiVersion } = txRequest ;
29- const bitgoGpgKey = await eddsaUtils . getBitgoPublicGpgKey ( ) ;
30-
31- const {
32- userToBitgoCommitment,
33- encryptedSignerShare,
34- encryptedUserToBitgoRShare,
35- encryptedDataKey,
36- } = await enclavedExpressClient . signMpcCommitment ( {
105+ const { customCommitmentGenerator, customRShareGenerator, customGShareGenerator } =
106+ createEddsaCustomSigningFunctions ( enclavedExpressClient , 'user' , commonKeychain ) ;
107+ return await eddsaUtils . signEddsaTssUsingExternalSigner (
37108 txRequest ,
38- bitgoPublicGpgKey : bitgoGpgKey . armor ( ) ,
39- source : 'user' ,
40- pub : commonKeychain ,
41- } ) ;
42-
43- const { commitmentShare : bitgoToUserCommitment } = await exchangeEddsaCommitments (
44- bitgo ,
45- wallet . id ( ) ,
46- txRequest . txRequestId ,
47- userToBitgoCommitment ,
48- encryptedSignerShare ,
49- apiVersion ,
50- reqId ,
51- ) ;
52-
53- const { rShare } = await enclavedExpressClient . signMpcRShare ( {
54- txRequest,
55- encryptedUserToBitgoRShare,
56- encryptedDataKey,
57- source : 'user' ,
58- pub : commonKeychain ,
59- } ) ;
60-
61- await offerUserToBitgoRShare (
62- bitgo ,
63- wallet . id ( ) ,
64- txRequest . txRequestId ,
65- rShare ,
66- encryptedSignerShare . share ,
67- apiVersion ,
109+ customCommitmentGenerator ,
110+ customRShareGenerator ,
111+ customGShareGenerator ,
68112 reqId ,
69113 ) ;
70- const bitgoToUserRShare = await getBitgoToUserRShare (
71- bitgo ,
72- wallet . id ( ) ,
73- txRequest . txRequestId ,
74- reqId ,
75- ) ;
76- const gSignShareTransactionParams = {
77- txRequest,
78- bitgoToUserRShare : bitgoToUserRShare ,
79- userToBitgoRShare : rShare ,
80- bitgoToUserCommitment,
81- } ;
82- const { gShare } = await enclavedExpressClient . signMpcGShare ( {
83- ...gSignShareTransactionParams ,
84- source : 'user' ,
85- pub : commonKeychain ,
86- } ) ;
87-
88- await sendUserToBitgoGShare ( bitgo , wallet . id ( ) , txRequest . txRequestId , gShare , apiVersion , reqId ) ;
89- logger . debug ( 'Successfully completed signing!' ) ;
90- return await getTxRequest ( bitgo , wallet . id ( ) , txRequest . txRequestId , reqId ) ;
91114}
92115
93116interface OrchestrateEddsaKeyGenParams {
0 commit comments