@@ -293,6 +293,8 @@ func (keystore *keystore) ExtendedPublicKey(
293
293
func (keystore * keystore ) signBTCTransaction (btcProposedTx * btc.ProposedTransaction ) error {
294
294
tx := btcProposedTx .TXProposal .Transaction
295
295
296
+ // scriptConfigs represent the script configurations of a specific account and include the
297
+ // script type (e.g. p2wpkh, p2tr..) and the account keypath
296
298
scriptConfigs := []* messages.BTCScriptConfigWithKeypath {}
297
299
// addScriptConfig returns the index of the scriptConfig in scriptConfigs, adding it if it isn't
298
300
// present. Must be a Simple configuration.
@@ -312,6 +314,7 @@ func (keystore *keystore) signBTCTransaction(btcProposedTx *btc.ProposedTransact
312
314
return errp .Newf ("coin not supported: %s" , coin .Code ())
313
315
}
314
316
317
+ // iterate over the tx inputs to add the related scriptconfigs and translate into `firmware.BTCTxInput` format.
315
318
inputs := make ([]* firmware.BTCTxInput , len (tx .TxIn ))
316
319
for inputIndex , txIn := range tx .TxIn {
317
320
prevOut , ok := btcProposedTx .TXProposal .PreviousOutputs [txIn .PreviousOutPoint ]
@@ -320,7 +323,7 @@ func (keystore *keystore) signBTCTransaction(btcProposedTx *btc.ProposedTransact
320
323
return errp .New ("There needs to be exactly one output being spent per input." )
321
324
}
322
325
323
- inputAddress := btcProposedTx .GetAddress (prevOut .ScriptHashHex ())
326
+ inputAddress := btcProposedTx .GetAccountAddress (prevOut .ScriptHashHex ())
324
327
325
328
accountConfiguration := inputAddress .AccountConfiguration
326
329
msgScriptType , ok := btcMsgScriptTypeMap [accountConfiguration .ScriptType ()]
@@ -344,14 +347,18 @@ func (keystore *keystore) signBTCTransaction(btcProposedTx *btc.ProposedTransact
344
347
}
345
348
}
346
349
350
+ txChangeAddress := btcProposedTx .TXProposal .ChangeAddress
351
+
352
+ // iterate over tx outputs to add the related scriptconfigs, flag internal addresses and build
353
+ // the output signing requests.
347
354
outputs := make ([]* messages.BTCSignOutputRequest , len (tx .TxOut ))
348
355
for index , txOut := range tx .TxOut {
349
- address , err := util .AddressFromPkScript (txOut .PkScript , coin .Net ())
356
+ outputAddress , err := util .AddressFromPkScript (txOut .PkScript , coin .Net ())
350
357
if err != nil {
351
358
return err
352
359
}
353
360
var msgOutputType messages.BTCOutputType
354
- switch address .(type ) {
361
+ switch outputAddress .(type ) {
355
362
case * btcutil.AddressPubKeyHash :
356
363
msgOutputType = messages .BTCOutputType_P2PKH
357
364
case * btcutil.AddressScriptHash :
@@ -363,18 +370,20 @@ func (keystore *keystore) signBTCTransaction(btcProposedTx *btc.ProposedTransact
363
370
case * btcutil.AddressTaproot :
364
371
msgOutputType = messages .BTCOutputType_P2TR
365
372
default :
366
- return errp .Newf ("unsupported output type: %v" , address )
373
+ return errp .Newf ("unsupported output type: %v" , outputAddress )
367
374
}
368
- outputAddress := btcProposedTx .GetAddress (blockchain .NewScriptHashHex (txOut .PkScript ))
369
375
370
- changeAddress := btcProposedTx .TXProposal .ChangeAddress
371
376
// Could also determine change using `outputAddress != nil AND second-to-last keypath element of outputAddress is 1`.
372
- isChange := changeAddress != nil && bytes .Equal (
373
- changeAddress .PubkeyScript (),
377
+ isChange := txChangeAddress != nil && bytes .Equal (
378
+ txChangeAddress .PubkeyScript (),
374
379
txOut .PkScript ,
375
380
)
376
381
377
- isOurs := outputAddress != nil
382
+ // outputAccountAddress represents the same address as outputAddress, but embeds the account configuration.
383
+ // It is nil if the address is external.
384
+ outputAccountAddress := btcProposedTx .GetAccountAddress (blockchain .NewScriptHashHex (txOut .PkScript ))
385
+
386
+ isOurs := outputAccountAddress != nil
378
387
if ! isChange && ! keystore .device .Version ().AtLeast (semver .NewSemVer (9 , 15 , 0 )) {
379
388
// For firmware older than 9.15.0, non-change outputs cannot be marked internal.
380
389
isOurs = false
@@ -383,8 +392,8 @@ func (keystore *keystore) signBTCTransaction(btcProposedTx *btc.ProposedTransact
383
392
var keypath []uint32
384
393
var scriptConfigIndex int
385
394
if isOurs {
386
- keypath = outputAddress .Configuration .AbsoluteKeypath ().ToUInt32 ()
387
- accountConfiguration := outputAddress .AccountConfiguration
395
+ keypath = outputAccountAddress .Configuration .AbsoluteKeypath ().ToUInt32 ()
396
+ accountConfiguration := outputAccountAddress .AccountConfiguration
388
397
msgScriptType , ok := btcMsgScriptTypeMap [accountConfiguration .ScriptType ()]
389
398
if ! ok {
390
399
return errp .Newf ("Unsupported script type %s" , accountConfiguration .ScriptType ())
@@ -399,7 +408,7 @@ func (keystore *keystore) signBTCTransaction(btcProposedTx *btc.ProposedTransact
399
408
Ours : isOurs ,
400
409
Type : msgOutputType ,
401
410
Value : uint64 (txOut .Value ),
402
- Payload : address .ScriptAddress (),
411
+ Payload : outputAddress .ScriptAddress (),
403
412
Keypath : keypath ,
404
413
ScriptConfigIndex : uint32 (scriptConfigIndex ),
405
414
}
@@ -438,6 +447,7 @@ func (keystore *keystore) signBTCTransaction(btcProposedTx *btc.ProposedTransact
438
447
}
439
448
}
440
449
450
+ // Handle displaying formatting in btc or sats.
441
451
formatUnit := messages .BTCSignInitRequest_DEFAULT
442
452
if btcProposedTx .FormatUnit == coinpkg .BtcUnitSats {
443
453
formatUnit = messages .BTCSignInitRequest_SAT
0 commit comments