@@ -22,6 +22,7 @@ import (
22
22
ourbtcutil "github.com/BitBoxSwiss/bitbox-wallet-app/backend/coins/btc/util"
23
23
"github.com/BitBoxSwiss/bitbox-wallet-app/backend/signing"
24
24
"github.com/BitBoxSwiss/bitbox-wallet-app/util/errp"
25
+ "github.com/btcsuite/btcd/btcec/v2"
25
26
"github.com/btcsuite/btcd/btcec/v2/schnorr"
26
27
"github.com/btcsuite/btcd/btcutil"
27
28
"github.com/btcsuite/btcd/chaincfg"
@@ -37,9 +38,9 @@ type AccountAddress struct {
37
38
38
39
// AccountConfiguration is the account level configuration from which this address was derived.
39
40
AccountConfiguration * signing.Configuration
40
- // Configuration contains the absolute keypath and the extended public keys of the address.
41
- Configuration * signing. Configuration
42
- Derivation types.Derivation
41
+ // publicKey is the public key of a single-sig address.
42
+ publicKey * btcec. PublicKey
43
+ Derivation types.Derivation
43
44
44
45
// redeemScript stores the redeem script of a BIP16 P2SH output or nil if address type is P2PKH.
45
46
redeemScript []byte
@@ -55,25 +56,29 @@ func NewAccountAddress(
55
56
log * logrus.Entry ,
56
57
) * AccountAddress {
57
58
58
- var address btcutil.Address
59
- var redeemScript []byte
60
- configuration , err := accountConfiguration .Derive (
61
- signing .NewEmptyRelativeKeypath ().
62
- Child (derivation .SimpleChainIndex (), signing .NonHardened ).
63
- Child (derivation .AddressIndex , signing .NonHardened ),
64
- )
65
- if err != nil {
66
- log .WithError (err ).Panic ("Failed to derive the configuration." )
67
- }
68
59
log = log .WithFields (logrus.Fields {
69
60
"accountConfiguration" : accountConfiguration .String (),
70
61
"change" : derivation .Change ,
71
62
"addressIndex" : derivation .AddressIndex ,
72
63
})
73
64
log .Debug ("Creating new account address" )
74
65
75
- publicKeyHash := btcutil .Hash160 (configuration .PublicKey ().SerializeCompressed ())
76
- switch configuration .ScriptType () {
66
+ var address btcutil.Address
67
+ var redeemScript []byte
68
+ relativeKeypath := signing .NewEmptyRelativeKeypath ().
69
+ Child (derivation .SimpleChainIndex (), signing .NonHardened ).
70
+ Child (derivation .AddressIndex , signing .NonHardened )
71
+ derivedXpub , err := relativeKeypath .Derive (accountConfiguration .ExtendedPublicKey ())
72
+ if err != nil {
73
+ log .WithError (err ).Panic ("Failed to derive xpub." )
74
+ }
75
+ publicKey , err := derivedXpub .ECPubKey ()
76
+ if err != nil {
77
+ log .WithError (err ).Panic ("Failed to convert an extended public key to a normal public key." )
78
+ }
79
+
80
+ publicKeyHash := btcutil .Hash160 (publicKey .SerializeCompressed ())
81
+ switch accountConfiguration .ScriptType () {
77
82
case signing .ScriptTypeP2PKH :
78
83
address , err = btcutil .NewAddressPubKeyHash (publicKeyHash , net )
79
84
if err != nil {
@@ -99,19 +104,19 @@ func NewAccountAddress(
99
104
log .WithError (err ).Panic ("Failed to get p2wpkh addr. from publ. key hash." )
100
105
}
101
106
case signing .ScriptTypeP2TR :
102
- outputKey := txscript .ComputeTaprootKeyNoScript (configuration . PublicKey () )
107
+ outputKey := txscript .ComputeTaprootKeyNoScript (publicKey )
103
108
address , err = btcutil .NewAddressTaproot (schnorr .SerializePubKey (outputKey ), net )
104
109
if err != nil {
105
110
log .WithError (err ).Panic ("Failed to get p2tr addr" )
106
111
}
107
112
default :
108
- log .Panic (fmt .Sprintf ("Unrecognized script type: %s" , configuration .ScriptType ()))
113
+ log .Panic (fmt .Sprintf ("Unrecognized script type: %s" , accountConfiguration .ScriptType ()))
109
114
}
110
115
111
116
return & AccountAddress {
112
117
Address : address ,
113
118
AccountConfiguration : accountConfiguration ,
114
- Configuration : configuration ,
119
+ publicKey : publicKey ,
115
120
Derivation : derivation ,
116
121
redeemScript : redeemScript ,
117
122
log : log ,
@@ -128,8 +133,8 @@ func (address *AccountAddress) ID() string {
128
133
// - 32 byte x-only public key for p2tr
129
134
// See https://github.com/bitcoin/bips/blob/master/bip-0352.mediawiki#user-content-Inputs_For_Shared_Secret_Derivation.
130
135
func (address * AccountAddress ) BIP352Pubkey () ([]byte , error ) {
131
- publicKey := address .Configuration . PublicKey ()
132
- switch address .Configuration .ScriptType () {
136
+ publicKey := address .publicKey
137
+ switch address .AccountConfiguration .ScriptType () {
133
138
case signing .ScriptTypeP2PKH , signing .ScriptTypeP2WPKHP2SH , signing .ScriptTypeP2WPKH :
134
139
return publicKey .SerializeCompressed (), nil
135
140
case signing .ScriptTypeP2TR :
@@ -145,9 +150,11 @@ func (address *AccountAddress) EncodeForHumans() string {
145
150
return address .EncodeAddress ()
146
151
}
147
152
148
- // AbsoluteKeypath implements coin.AbsoluteKeypath .
153
+ // AbsoluteKeypath implements accounts.Address .
149
154
func (address * AccountAddress ) AbsoluteKeypath () signing.AbsoluteKeypath {
150
- return address .Configuration .AbsoluteKeypath ()
155
+ return address .AccountConfiguration .AbsoluteKeypath ().
156
+ Child (address .Derivation .SimpleChainIndex (), false ).
157
+ Child (address .Derivation .AddressIndex , false )
151
158
}
152
159
153
160
// PubkeyScript returns the pubkey script of this address. Use this in a tx output to receive funds.
@@ -169,7 +176,7 @@ func (address *AccountAddress) PubkeyScriptHashHex() blockchain.ScriptHashHex {
169
176
// calculating the hash to be signed in a transaction. This info is needed when trying to spend
170
177
// from this address.
171
178
func (address * AccountAddress ) ScriptForHashToSign () (bool , []byte ) {
172
- switch address .Configuration .ScriptType () {
179
+ switch address .AccountConfiguration .ScriptType () {
173
180
case signing .ScriptTypeP2PKH :
174
181
return false , address .PubkeyScript ()
175
182
case signing .ScriptTypeP2WPKHP2SH :
@@ -187,8 +194,8 @@ func (address *AccountAddress) ScriptForHashToSign() (bool, []byte) {
187
194
func (address * AccountAddress ) SignatureScript (
188
195
signature types.Signature ,
189
196
) ([]byte , wire.TxWitness ) {
190
- publicKey := address .Configuration . PublicKey ()
191
- switch address .Configuration .ScriptType () {
197
+ publicKey := address .publicKey
198
+ switch address .AccountConfiguration .ScriptType () {
192
199
case signing .ScriptTypeP2PKH :
193
200
signatureScript , err := txscript .NewScriptBuilder ().
194
201
AddData (append (signature .SerializeDER (), byte (txscript .SigHashAll ))).
0 commit comments