Skip to content

Commit 4cf3b3d

Browse files
committed
Merge branch 'btc-sign-refactor'
2 parents 71aad45 + 430dde8 commit 4cf3b3d

File tree

4 files changed

+27
-17
lines changed

4 files changed

+27
-17
lines changed

backend/coins/btc/sign.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ type ProposedTransaction struct {
3333
TXProposal *maketx.TxProposal
3434
// List of signing configurations that might be used in the tx inputs.
3535
AccountSigningConfigurations []*signing.Configuration
36-
GetAddress func(blockchain.ScriptHashHex) *addresses.AccountAddress
36+
GetAccountAddress func(blockchain.ScriptHashHex) *addresses.AccountAddress
3737
GetPrevTx func(chainhash.Hash) (*wire.MsgTx, error)
3838
// Signatures collects the signatures, one per transaction input.
3939
Signatures []*types.Signature
@@ -56,7 +56,7 @@ func (account *Account) signTransaction(
5656
proposedTransaction := &ProposedTransaction{
5757
TXProposal: txProposal,
5858
AccountSigningConfigurations: signingConfigs,
59-
GetAddress: account.getAddress,
59+
GetAccountAddress: account.getAddress,
6060
GetPrevTx: getPrevTx,
6161
Signatures: make([]*types.Signature, len(txProposal.Transaction.TxIn)),
6262
SigHashes: txscript.NewTxSigHashes(txProposal.Transaction, previousOutputs),
@@ -73,7 +73,7 @@ func (account *Account) signTransaction(
7373

7474
for index, input := range txProposal.Transaction.TxIn {
7575
spentOutput := previousOutputs[input.PreviousOutPoint]
76-
address := proposedTransaction.GetAddress(spentOutput.ScriptHashHex())
76+
address := proposedTransaction.GetAccountAddress(spentOutput.ScriptHashHex())
7777
signature := proposedTransaction.Signatures[index]
7878
if signature == nil {
7979
return errp.New("Signature missing")

backend/devices/bitbox/keystore.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ func (keystore *keystore) signBTCTransaction(btcProposedTx *btc.ProposedTransact
160160
keystore.log.Error("There needs to be exactly one output being spent per input.")
161161
return errp.New("There needs to be exactly one output being spent per input.")
162162
}
163-
address := btcProposedTx.GetAddress(spentOutput.ScriptHashHex())
163+
address := btcProposedTx.GetAccountAddress(spentOutput.ScriptHashHex())
164164
isSegwit, subScript := address.ScriptForHashToSign()
165165
var signatureHash []byte
166166
if isSegwit {

backend/devices/bitbox02/keystore.go

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,8 @@ func (keystore *keystore) ExtendedPublicKey(
293293
func (keystore *keystore) signBTCTransaction(btcProposedTx *btc.ProposedTransaction) error {
294294
tx := btcProposedTx.TXProposal.Transaction
295295

296+
// scriptConfigs represent the script configurations of a specific account and include the
297+
// script type (e.g. p2wpkh, p2tr..) and the account keypath
296298
scriptConfigs := []*messages.BTCScriptConfigWithKeypath{}
297299
// addScriptConfig returns the index of the scriptConfig in scriptConfigs, adding it if it isn't
298300
// present. Must be a Simple configuration.
@@ -312,6 +314,7 @@ func (keystore *keystore) signBTCTransaction(btcProposedTx *btc.ProposedTransact
312314
return errp.Newf("coin not supported: %s", coin.Code())
313315
}
314316

317+
// iterate over the tx inputs to add the related scriptconfigs and translate into `firmware.BTCTxInput` format.
315318
inputs := make([]*firmware.BTCTxInput, len(tx.TxIn))
316319
for inputIndex, txIn := range tx.TxIn {
317320
prevOut, ok := btcProposedTx.TXProposal.PreviousOutputs[txIn.PreviousOutPoint]
@@ -320,7 +323,7 @@ func (keystore *keystore) signBTCTransaction(btcProposedTx *btc.ProposedTransact
320323
return errp.New("There needs to be exactly one output being spent per input.")
321324
}
322325

323-
inputAddress := btcProposedTx.GetAddress(prevOut.ScriptHashHex())
326+
inputAddress := btcProposedTx.GetAccountAddress(prevOut.ScriptHashHex())
324327

325328
accountConfiguration := inputAddress.AccountConfiguration
326329
msgScriptType, ok := btcMsgScriptTypeMap[accountConfiguration.ScriptType()]
@@ -344,14 +347,18 @@ func (keystore *keystore) signBTCTransaction(btcProposedTx *btc.ProposedTransact
344347
}
345348
}
346349

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.
347354
outputs := make([]*messages.BTCSignOutputRequest, len(tx.TxOut))
348355
for index, txOut := range tx.TxOut {
349-
address, err := util.AddressFromPkScript(txOut.PkScript, coin.Net())
356+
outputAddress, err := util.AddressFromPkScript(txOut.PkScript, coin.Net())
350357
if err != nil {
351358
return err
352359
}
353360
var msgOutputType messages.BTCOutputType
354-
switch address.(type) {
361+
switch outputAddress.(type) {
355362
case *btcutil.AddressPubKeyHash:
356363
msgOutputType = messages.BTCOutputType_P2PKH
357364
case *btcutil.AddressScriptHash:
@@ -363,18 +370,20 @@ func (keystore *keystore) signBTCTransaction(btcProposedTx *btc.ProposedTransact
363370
case *btcutil.AddressTaproot:
364371
msgOutputType = messages.BTCOutputType_P2TR
365372
default:
366-
return errp.Newf("unsupported output type: %v", address)
373+
return errp.Newf("unsupported output type: %v", outputAddress)
367374
}
368-
outputAddress := btcProposedTx.GetAddress(blockchain.NewScriptHashHex(txOut.PkScript))
369375

370-
changeAddress := btcProposedTx.TXProposal.ChangeAddress
371376
// 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(),
374379
txOut.PkScript,
375380
)
376381

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
378387
if !isChange && !keystore.device.Version().AtLeast(semver.NewSemVer(9, 15, 0)) {
379388
// For firmware older than 9.15.0, non-change outputs cannot be marked internal.
380389
isOurs = false
@@ -383,8 +392,8 @@ func (keystore *keystore) signBTCTransaction(btcProposedTx *btc.ProposedTransact
383392
var keypath []uint32
384393
var scriptConfigIndex int
385394
if isOurs {
386-
keypath = outputAddress.Configuration.AbsoluteKeypath().ToUInt32()
387-
accountConfiguration := outputAddress.AccountConfiguration
395+
keypath = outputAccountAddress.Configuration.AbsoluteKeypath().ToUInt32()
396+
accountConfiguration := outputAccountAddress.AccountConfiguration
388397
msgScriptType, ok := btcMsgScriptTypeMap[accountConfiguration.ScriptType()]
389398
if !ok {
390399
return errp.Newf("Unsupported script type %s", accountConfiguration.ScriptType())
@@ -399,7 +408,7 @@ func (keystore *keystore) signBTCTransaction(btcProposedTx *btc.ProposedTransact
399408
Ours: isOurs,
400409
Type: msgOutputType,
401410
Value: uint64(txOut.Value),
402-
Payload: address.ScriptAddress(),
411+
Payload: outputAddress.ScriptAddress(),
403412
Keypath: keypath,
404413
ScriptConfigIndex: uint32(scriptConfigIndex),
405414
}
@@ -438,6 +447,7 @@ func (keystore *keystore) signBTCTransaction(btcProposedTx *btc.ProposedTransact
438447
}
439448
}
440449

450+
// Handle displaying formatting in btc or sats.
441451
formatUnit := messages.BTCSignInitRequest_DEFAULT
442452
if btcProposedTx.FormatUnit == coinpkg.BtcUnitSats {
443453
formatUnit = messages.BTCSignInitRequest_SAT

backend/keystore/software/software.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ func (keystore *Keystore) SignTransaction(
197197
keystore.log.Error("There needs to be exactly one output being spent per input.")
198198
return errp.New("There needs to be exactly one output being spent per input.")
199199
}
200-
address := btcProposedTx.GetAddress(spentOutput.ScriptHashHex())
200+
address := btcProposedTx.GetAccountAddress(spentOutput.ScriptHashHex())
201201

202202
xprv, err := address.Configuration.AbsoluteKeypath().Derive(keystore.master)
203203
if err != nil {

0 commit comments

Comments
 (0)