@@ -277,22 +277,29 @@ type BTCTx struct {
277
277
PaymentRequests []* messages.BTCPaymentRequestRequest
278
278
}
279
279
280
+ // BTCSignResult is the result of `BTCSign()`.
281
+ type BTCSignResult struct {
282
+ // Signatures contains the input signatures. One 64 byte signature per input.
283
+ Signatures [][]byte
284
+ // GeneratedOutputs contains the outputs generated (silent payments). The map key is the input
285
+ // index, the map value is the generated pkScript.
286
+ GeneratedOutputs map [int ][]byte
287
+ }
288
+
280
289
// BTCSign signs a bitcoin or bitcoin-like transaction. The previous transactions of the inputs
281
290
// need to be provided if `BTCSignNeedsPrevTxs()` returns true.
282
- //
283
- // Returns one 64 byte signature per input.
284
291
func (device * Device ) BTCSign (
285
292
coin messages.BTCCoin ,
286
293
scriptConfigs []* messages.BTCScriptConfigWithKeypath ,
287
294
outputScriptConfigs []* messages.BTCScriptConfigWithKeypath ,
288
295
tx * BTCTx ,
289
296
formatUnit messages.BTCSignInitRequest_FormatUnit ,
290
- ) ([][] byte , map [ int ][] byte , error ) {
297
+ ) (* BTCSignResult , error ) {
291
298
generatedOutputs := map [int ][]byte {}
292
299
if ! device .version .AtLeast (semver .NewSemVer (9 , 10 , 0 )) {
293
300
for _ , sc := range scriptConfigs {
294
301
if isTaproot (sc ) {
295
- return nil , nil , UnsupportedError ("9.10.0" )
302
+ return nil , UnsupportedError ("9.10.0" )
296
303
}
297
304
}
298
305
}
@@ -308,11 +315,11 @@ func (device *Device) BTCSign(
308
315
}
309
316
310
317
if containsSilentPaymentOutputs && ! device .version .AtLeast (semver .NewSemVer (9 , 21 , 0 )) {
311
- return nil , nil , UnsupportedError ("9.21.0" )
318
+ return nil , UnsupportedError ("9.21.0" )
312
319
}
313
320
314
321
if len (outputScriptConfigs ) > 0 && ! device .version .AtLeast (semver .NewSemVer (9 , 22 , 0 )) {
315
- return nil , nil , UnsupportedError ("9.22.0" )
322
+ return nil , UnsupportedError ("9.22.0" )
316
323
}
317
324
318
325
signatures := make ([][]byte , len (tx .Inputs ))
@@ -330,7 +337,7 @@ func (device *Device) BTCSign(
330
337
OutputScriptConfigs : outputScriptConfigs ,
331
338
}}})
332
339
if err != nil {
333
- return nil , nil , err
340
+ return nil , err
334
341
}
335
342
336
343
isInputsPass2 := false
@@ -349,7 +356,7 @@ func (device *Device) BTCSign(
349
356
if performAntiklepto {
350
357
nonce , err := generateHostNonce ()
351
358
if err != nil {
352
- return nil , nil , err
359
+ return nil , err
353
360
}
354
361
hostNonce = nonce
355
362
input .HostNonceCommitment = & messages.AntiKleptoHostNonceCommitment {
@@ -361,12 +368,12 @@ func (device *Device) BTCSign(
361
368
BtcSignInput : input ,
362
369
}})
363
370
if err != nil {
364
- return nil , nil , err
371
+ return nil , err
365
372
}
366
373
367
374
if performAntiklepto {
368
375
if next .Type != messages .BTCSignNextResponse_HOST_NONCE || next .AntiKleptoSignerCommitment == nil {
369
- return nil , nil , errp .New ("unexpected response; expected signer nonce commitment" )
376
+ return nil , errp .New ("unexpected response; expected signer nonce commitment" )
370
377
}
371
378
signerCommitment := next .AntiKleptoSignerCommitment .Commitment
372
379
next , err = device .nestedQueryBtcSign (
@@ -378,20 +385,20 @@ func (device *Device) BTCSign(
378
385
},
379
386
})
380
387
if err != nil {
381
- return nil , nil , err
388
+ return nil , err
382
389
}
383
390
err := antikleptoVerify (
384
391
hostNonce ,
385
392
signerCommitment ,
386
393
next .Signature ,
387
394
)
388
395
if err != nil {
389
- return nil , nil , err
396
+ return nil , err
390
397
}
391
398
}
392
399
if isInputsPass2 {
393
400
if ! next .HasSignature {
394
- return nil , nil , errp .New ("unexpected response; expected signature" )
401
+ return nil , errp .New ("unexpected response; expected signature" )
395
402
}
396
403
signatures [inputIndex ] = next .Signature
397
404
}
@@ -413,7 +420,7 @@ func (device *Device) BTCSign(
413
420
},
414
421
})
415
422
if err != nil {
416
- return nil , nil , err
423
+ return nil , err
417
424
}
418
425
case messages .BTCSignNextResponse_PREVTX_INPUT :
419
426
prevtxInput := tx .Inputs [next .Index ].PrevTx .Inputs [next .PrevIndex ]
@@ -424,7 +431,7 @@ func (device *Device) BTCSign(
424
431
},
425
432
})
426
433
if err != nil {
427
- return nil , nil , err
434
+ return nil , err
428
435
}
429
436
case messages .BTCSignNextResponse_PREVTX_OUTPUT :
430
437
prevtxOutput := tx .Inputs [next .Index ].PrevTx .Outputs [next .PrevIndex ]
@@ -435,7 +442,7 @@ func (device *Device) BTCSign(
435
442
},
436
443
})
437
444
if err != nil {
438
- return nil , nil , err
445
+ return nil , err
439
446
}
440
447
case messages .BTCSignNextResponse_OUTPUT :
441
448
outputIndex := next .Index
@@ -444,7 +451,7 @@ func (device *Device) BTCSign(
444
451
BtcSignOutput : tx .Outputs [outputIndex ],
445
452
}})
446
453
if err != nil {
447
- return nil , nil , err
454
+ return nil , err
448
455
}
449
456
if next .GeneratedOutputPkscript != nil {
450
457
generatedOutputs [int (outputIndex )] = next .GeneratedOutputPkscript
@@ -455,13 +462,13 @@ func (device *Device) BTCSign(
455
462
next .GeneratedOutputPkscript ,
456
463
)
457
464
if err != nil {
458
- return nil , nil , err
465
+ return nil , err
459
466
}
460
467
}
461
468
case messages .BTCSignNextResponse_PAYMENT_REQUEST :
462
469
paymentRequestIndex := next .Index
463
470
if int (paymentRequestIndex ) >= len (tx .PaymentRequests ) {
464
- return nil , nil , errp .New ("payment request index out of bounds" )
471
+ return nil , errp .New ("payment request index out of bounds" )
465
472
}
466
473
paymentRequest := tx .PaymentRequests [paymentRequestIndex ]
467
474
next , err = device .nestedQueryBtcSign (
@@ -472,10 +479,13 @@ func (device *Device) BTCSign(
472
479
},
473
480
)
474
481
if err != nil {
475
- return nil , nil , err
482
+ return nil , err
476
483
}
477
484
case messages .BTCSignNextResponse_DONE :
478
- return signatures , generatedOutputs , nil
485
+ return & BTCSignResult {
486
+ Signatures : signatures ,
487
+ GeneratedOutputs : generatedOutputs ,
488
+ }, nil
479
489
}
480
490
}
481
491
}
@@ -542,18 +552,28 @@ func (device *Device) BTCRegisterScriptConfig(
542
552
return nil
543
553
}
544
554
555
+ // BTCSignMessageResult is the result of `BTCSignMessage()`.
556
+ type BTCSignMessageResult struct {
557
+ // Signature is the 64 byte raw signature.
558
+ Signature []byte
559
+ // RecID is the recoverable ID.
560
+ RecID byte
561
+ // ElectrumSig65 is the 65 byte signature in Electrum format.
562
+ ElectrumSig65 []byte
563
+ }
564
+
545
565
// BTCSignMessage signs a Bitcoin message. The 64 byte raw signature, the recoverable ID and the 65
546
566
// byte signature in Electrum format are returned.
547
567
func (device * Device ) BTCSignMessage (
548
568
coin messages.BTCCoin ,
549
569
scriptConfig * messages.BTCScriptConfigWithKeypath ,
550
570
message []byte ,
551
- ) (raw [] byte , recID byte , electrum65 [] byte , err error ) {
571
+ ) (* BTCSignMessageResult , error ) {
552
572
if isTaproot (scriptConfig ) {
553
- return nil , 0 , nil , errp .New ("taproot not supported" )
573
+ return nil , errp .New ("taproot not supported" )
554
574
}
555
575
if ! device .version .AtLeast (semver .NewSemVer (9 , 2 , 0 )) {
556
- return nil , 0 , nil , UnsupportedError ("9.2.0" )
576
+ return nil , UnsupportedError ("9.2.0" )
557
577
}
558
578
559
579
supportsAntiklepto := device .version .AtLeast (semver .NewSemVer (9 , 5 , 0 ))
@@ -564,7 +584,7 @@ func (device *Device) BTCSignMessage(
564
584
var err error
565
585
hostNonce , err = generateHostNonce ()
566
586
if err != nil {
567
- return nil , 0 , nil , err
587
+ return nil , err
568
588
}
569
589
hostNonceCommitment = & messages.AntiKleptoHostNonceCommitment {
570
590
Commitment : antikleptoHostCommit (hostNonce ),
@@ -583,14 +603,14 @@ func (device *Device) BTCSignMessage(
583
603
}
584
604
response , err := device .queryBTC (request )
585
605
if err != nil {
586
- return nil , 0 , nil , err
606
+ return nil , err
587
607
}
588
608
589
609
var signature []byte
590
610
if supportsAntiklepto {
591
611
signerCommitment , ok := response .Response .(* messages.BTCResponse_AntikleptoSignerCommitment )
592
612
if ! ok {
593
- return nil , 0 , nil , errp .New ("unexpected response" )
613
+ return nil , errp .New ("unexpected response" )
594
614
}
595
615
response , err := device .queryBTC (& messages.BTCRequest {
596
616
Request : & messages.BTCRequest_AntikleptoSignature {
@@ -600,12 +620,12 @@ func (device *Device) BTCSignMessage(
600
620
},
601
621
})
602
622
if err != nil {
603
- return nil , 0 , nil , err
623
+ return nil , err
604
624
}
605
625
606
626
signResponse , ok := response .Response .(* messages.BTCResponse_SignMessage )
607
627
if ! ok {
608
- return nil , 0 , nil , errp .New ("unexpected response" )
628
+ return nil , errp .New ("unexpected response" )
609
629
}
610
630
signature = signResponse .SignMessage .Signature
611
631
err = antikleptoVerify (
@@ -614,12 +634,12 @@ func (device *Device) BTCSignMessage(
614
634
signature [:64 ],
615
635
)
616
636
if err != nil {
617
- return nil , 0 , nil , err
637
+ return nil , err
618
638
}
619
639
} else {
620
640
signResponse , ok := response .Response .(* messages.BTCResponse_SignMessage )
621
641
if ! ok {
622
- return nil , 0 , nil , errp .New ("unexpected response" )
642
+ return nil , errp .New ("unexpected response" )
623
643
}
624
644
signature = signResponse .SignMessage .Signature
625
645
}
@@ -628,5 +648,9 @@ func (device *Device) BTCSignMessage(
628
648
// See https://github.com/spesmilo/electrum/blob/84dc181b6e7bb20e88ef6b98fb8925c5f645a765/electrum/ecc.py#L521-L523
629
649
const compressed = 4 // BitBox02 uses only compressed pubkeys
630
650
electrumSig65 := append ([]byte {27 + compressed + recID }, sig ... )
631
- return sig , recID , electrumSig65 , nil
651
+ return & BTCSignMessageResult {
652
+ Signature : sig ,
653
+ RecID : recID ,
654
+ ElectrumSig65 : electrumSig65 ,
655
+ }, nil
632
656
}
0 commit comments