@@ -72,12 +72,23 @@ module Account =
72
72
// TODO: measure how long does it take to get the script hash and if it's too long, cache it at app startup?
73
73
BitcoinAddress.Create( publicAddress, GetNetwork currency) |> GetElectrumScriptHashFromAddress
74
74
75
- let internal GetPublicAddressFromPublicKey currency ( publicKey : PubKey ) =
75
+ let internal GetSegwitP2shPublicAddressFromPublicKey currency ( publicKey : PubKey ) =
76
+ publicKey
77
+ .GetScriptPubKey( ScriptPubKeyType.SegwitP2SH)
78
+ .GetDestinationAddress( GetNetwork currency)
79
+ .ToString()
80
+
81
+ let internal GetNativeSegwitPublicAddressFromPublicKey currency ( publicKey : PubKey ) =
76
82
publicKey
77
83
.GetScriptPubKey( ScriptPubKeyType.Segwit)
78
- .Hash
79
- .GetAddress( GetNetwork currency)
84
+ .GetDestinationAddress( GetNetwork currency)
80
85
.ToString()
86
+
87
+ let internal GetPublicAddressFromPublicKey =
88
+ if Config.UseNativeSegwit then
89
+ GetNativeSegwitPublicAddressFromPublicKey
90
+ else
91
+ GetSegwitP2shPublicAddressFromPublicKey
81
92
82
93
let internal GetPublicAddressFromNormalAccountFile ( currency : Currency ) ( accountFile : FileRepresentation ): string =
83
94
let pubKey = PubKey( accountFile.Name)
@@ -139,11 +150,17 @@ module Account =
139
150
( mode : ServerSelectionMode )
140
151
( cancelSourceOption : Option < CustomCancelSource >)
141
152
: Async < BlockchainScriptHashGetBalanceInnerResult > =
142
- let scriptHashHex = GetElectrumScriptHashFromPublicAddress account.Currency account.PublicAddress
153
+ let scriptHashesHex =
154
+ [
155
+ GetNativeSegwitPublicAddressFromPublicKey account.Currency account.PublicKey
156
+ |> GetElectrumScriptHashFromPublicAddress account.Currency
157
+ GetSegwitP2shPublicAddressFromPublicKey account.Currency account.PublicKey
158
+ |> GetElectrumScriptHashFromPublicAddress account.Currency
159
+ ]
143
160
144
161
let querySettings =
145
162
QuerySettings.Balance( mode,( BalanceMatchWithCacheOrInitialBalance account.PublicAddress account.Currency))
146
- let balanceJob = ElectrumClient.GetBalance scriptHashHex
163
+ let balanceJob = ElectrumClient.GetBalances scriptHashesHex
147
164
Server.Query account.Currency querySettings balanceJob cancelSourceOption
148
165
149
166
let private GetBalancesFromServer ( account : IUtxoAccount )
@@ -176,9 +193,21 @@ module Account =
176
193
let txHash = uint256 inputOutpointInfo.TransactionHash
177
194
let scriptPubKeyInBytes = NBitcoin.DataEncoders.Encoders.Hex.DecodeData inputOutpointInfo.DestinationInHex
178
195
let scriptPubKey = Script( scriptPubKeyInBytes)
196
+ // We convert the scriptPubKey to address temporarily to compare it with
197
+ // our own addresses, we could compare scriptPubKeys directly but we would
198
+ // need functions that return scriptPubKey of our addresses instead of a
199
+ // string.
200
+ let sourceAddress = scriptPubKey.GetDestinationAddress( GetNetwork account.Currency) .ToString()
179
201
let coin =
180
202
Coin( txHash, uint32 inputOutpointInfo.OutputIndex, Money( inputOutpointInfo.ValueInSatoshis), scriptPubKey)
181
- coin.ToScriptCoin account.PublicKey.WitHash.ScriptPubKey :> ICoin
203
+ if sourceAddress = GetSegwitP2shPublicAddressFromPublicKey account.Currency account.PublicKey then
204
+ coin.ToScriptCoin( account.PublicKey.WitHash.ScriptPubKey) :> ICoin
205
+ elif sourceAddress = GetNativeSegwitPublicAddressFromPublicKey account.Currency account.PublicKey then
206
+ coin :> ICoin
207
+ else
208
+ //We filter utxos based on scriptPubKey when retrieving from electrum
209
+ //so this is unreachable.
210
+ failwith " Unreachable: unrecognized scriptPubKey"
182
211
183
212
let private CreateTransactionAndCoinsToBeSigned ( account : IUtxoAccount )
184
213
( transactionInputs : List < TransactionInputOutpointInfo >)
@@ -294,9 +323,28 @@ module Account =
294
323
else
295
324
newAcc, tail
296
325
297
- let job = GetElectrumScriptHashFromPublicAddress account.Currency account.PublicAddress
298
- |> ElectrumClient.GetUnspentTransactionOutputs
299
- let! utxos = Server.Query account.Currency ( QuerySettings.Default ServerSelectionMode.Fast) job None
326
+ let currency = account.Currency
327
+
328
+ let getUtxos ( publicAddress : string ) =
329
+ async {
330
+ let job = GetElectrumScriptHashFromPublicAddress currency publicAddress
331
+ |> ElectrumClient.GetUnspentTransactionOutputs
332
+
333
+ return ! Server.Query currency ( QuerySettings.Default ServerSelectionMode.Fast) job None
334
+ }
335
+
336
+ let! utxos =
337
+ async {
338
+ let! nativeSegwitUtxos =
339
+ GetNativeSegwitPublicAddressFromPublicKey currency account.PublicKey
340
+ |> getUtxos
341
+
342
+ let! legacySegwitUtxos =
343
+ GetSegwitP2shPublicAddressFromPublicKey currency account.PublicKey
344
+ |> getUtxos
345
+
346
+ return Seq.concat [ nativeSegwitUtxos; legacySegwitUtxos ]
347
+ }
300
348
301
349
if not ( utxos.Any()) then
302
350
failwith " No UTXOs found!"
0 commit comments