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