@@ -72,27 +72,28 @@ module Account =
7272 // TODO: measure how long does it take to get the script hash and if it's too long, cache it at app startup?
7373 BitcoinAddress.Create( publicAddress, GetNetwork currency) |> GetElectrumScriptHashFromAddress
7474
75- let internal GetSegwitP2shPublicAddressFromPublicKey currency ( publicKey : PubKey ) =
75+ let internal GetNestedSegwitPublicAddressFromPublicKey currency ( publicKey : PubKey ): BitcoinAddress =
7676 publicKey
7777 .GetScriptPubKey( ScriptPubKeyType.SegwitP2SH)
7878 .GetDestinationAddress( GetNetwork currency)
79- .ToString()
8079
81- let internal GetNativeSegwitPublicAddressFromPublicKey currency ( publicKey : PubKey ) =
80+ let internal GetNativeSegwitPublicAddressFromPublicKey currency ( publicKey : PubKey ): BitcoinAddress =
8281 publicKey
8382 .GetScriptPubKey( ScriptPubKeyType.Segwit)
8483 .GetDestinationAddress( GetNetwork currency)
85- .ToString()
8684
87- let internal GetPublicAddressFromPublicKey =
85+ let private GetUtxoPublicAddressFromPublicKey =
8886 if Config.UseNativeSegwit then
8987 GetNativeSegwitPublicAddressFromPublicKey
9088 else
91- GetSegwitP2shPublicAddressFromPublicKey
89+ GetNestedSegwitPublicAddressFromPublicKey
90+
91+ let internal GetPublicAddressFromPublicKey currency pubKey =
92+ ( GetUtxoPublicAddressFromPublicKey currency pubKey) .ToString()
9293
9394 let internal GetPublicAddressFromNormalAccountFile ( currency : Currency ) ( accountFile : FileRepresentation ): string =
9495 let pubKey = PubKey( accountFile.Name)
95- GetPublicAddressFromPublicKey currency pubKey
96+ ( GetUtxoPublicAddressFromPublicKey currency pubKey) .ToString ()
9697
9798 let internal GetPublicKeyFromNormalAccountFile ( accountFile : FileRepresentation ): PubKey =
9899 PubKey accountFile.Name
@@ -102,7 +103,7 @@ module Account =
102103
103104 let internal GetPublicAddressFromUnencryptedPrivateKey ( currency : Currency ) ( privateKey: string ) =
104105 let privateKey = Key.Parse( privateKey, GetNetwork currency)
105- GetPublicAddressFromPublicKey currency privateKey.PubKey
106+ ( GetUtxoPublicAddressFromPublicKey currency privateKey.PubKey) .ToString ()
106107
107108 let internal GetAccountFromFile ( accountFile : FileRepresentation ) ( currency : Currency ) kind : IAccount =
108109 if not ( currency.IsUtxo()) then
@@ -152,9 +153,9 @@ module Account =
152153 : Async < BlockchainScriptHashGetBalanceInnerResult > =
153154 let scriptHashesHex =
154155 [
155- GetNativeSegwitPublicAddressFromPublicKey account.Currency account.PublicKey
156+ ( GetNativeSegwitPublicAddressFromPublicKey account.Currency account.PublicKey) .ToString ()
156157 |> GetElectrumScriptHashFromPublicAddress account.Currency
157- GetSegwitP2shPublicAddressFromPublicKey account.Currency account.PublicKey
158+ ( GetNestedSegwitPublicAddressFromPublicKey account.Currency account.PublicKey) .ToString ()
158159 |> GetElectrumScriptHashFromPublicAddress account.Currency
159160 ]
160161
@@ -200,9 +201,9 @@ module Account =
200201 let sourceAddress = scriptPubKey.GetDestinationAddress( GetNetwork account.Currency) .ToString()
201202 let coin =
202203 Coin( txHash, uint32 inputOutpointInfo.OutputIndex, Money( inputOutpointInfo.ValueInSatoshis), scriptPubKey)
203- if sourceAddress = GetSegwitP2shPublicAddressFromPublicKey account.Currency account.PublicKey then
204+ if sourceAddress = ( GetNestedSegwitPublicAddressFromPublicKey account.Currency account.PublicKey) .ToString () then
204205 coin.ToScriptCoin( account.PublicKey.WitHash.ScriptPubKey) :> ICoin
205- elif sourceAddress = GetNativeSegwitPublicAddressFromPublicKey account.Currency account.PublicKey then
206+ elif sourceAddress = ( GetNativeSegwitPublicAddressFromPublicKey account.Currency account.PublicKey) .ToString () then
206207 coin :> ICoin
207208 else
208209 //We filter utxos based on scriptPubKey when retrieving from electrum
@@ -325,9 +326,9 @@ module Account =
325326
326327 let currency = account.Currency
327328
328- let getUtxos ( publicAddress : string ) =
329+ let getUtxos ( publicAddress : BitcoinAddress ) =
329330 async {
330- let job = GetElectrumScriptHashFromPublicAddress currency publicAddress
331+ let job = GetElectrumScriptHashFromPublicAddress currency ( publicAddress.ToString ())
331332 |> ElectrumClient.GetUnspentTransactionOutputs
332333
333334 return ! Server.Query currency ( QuerySettings.Default ServerSelectionMode.Fast) job None
@@ -340,7 +341,7 @@ module Account =
340341 |> getUtxos
341342
342343 let! legacySegwitUtxos =
343- GetSegwitP2shPublicAddressFromPublicKey currency account.PublicKey
344+ GetNestedSegwitPublicAddressFromPublicKey currency account.PublicKey
344345 |> getUtxos
345346
346347 return Seq.concat [ nativeSegwitUtxos; legacySegwitUtxos ]
@@ -707,11 +708,23 @@ module Account =
707708 failwith " transaction has multiple different inputs"
708709 origin
709710
710- let matchOriginToAccount ( account : ReadOnlyUtxoAccount ): bool =
711- let accountAddress = ( account :> IAccount) .PublicAddress
712- let bitcoinAddress = BitcoinAddress.Create( accountAddress, network)
713- let destination = bitcoinAddress.ScriptPubKey.GetDestination()
714- ( destination :> IDestination) = origin
711+ let anyAccountAddressesMatch ( originOrDestination : IDestination ) ( account : IUtxoAccount ) ( throwIfNot : bool ): bool =
712+ let nativeSegWitAddress =
713+ GetNativeSegwitPublicAddressFromPublicKey account.Currency account.PublicKey
714+ :> IDestination
715+ let nestedSegWitAddress =
716+ GetNestedSegwitPublicAddressFromPublicKey account.Currency account.PublicKey
717+ :> IDestination
718+ let network = GetNetwork account.Currency
719+ let originOrDestinationAddress = originOrDestination.ScriptPubKey.GetDestinationAddress network :> IDestination
720+ let anyMatch =
721+ nativeSegWitAddress = originOrDestinationAddress || nestedSegWitAddress = originOrDestinationAddress
722+ if not anyMatch then
723+ if throwIfNot then
724+ failwith
725+ <| SPrintF3 " ReadOnly account's addresses (%s and %s ) don't match with the source adress of the signed transaction (%s )"
726+ ( nativeSegWitAddress.ToString()) ( nestedSegWitAddress.ToString()) ( originOrDestinationAddress.ToString())
727+ anyMatch
715728
716729 let account =
717730 let accountOpt =
@@ -721,22 +734,20 @@ module Account =
721734 GetAccountFromFile accountFile currency AccountKind.ReadOnly
722735 :?> ReadOnlyUtxoAccount
723736 )
724- |> Seq.filter matchOriginToAccount
725737 |> Seq.tryExactlyOne
726738 match accountOpt with
727- | Some account -> account
728- | None -> failwith " unknown origin account"
729- let originAddress =
730- let accountAddress = ( account :> IAccount) .PublicAddress
731- let bitcoinAddress = BitcoinAddress.Create( accountAddress, network)
732- bitcoinAddress
739+ | None -> failwith " Cannot broadcast transactions from a wallet instance that doesn't have read-only accounts"
740+ | Some account ->
741+ let utxoAccount = account :> IUtxoAccount
742+ anyAccountAddressesMatch origin utxoAccount true |> ignore< bool>
743+ account
733744
734745 let destinationAddress , value =
735746 let filterChangeTxOuts ( txOut : TxOut ): Option < BitcoinAddress * Money > =
736747 let scriptPubKey = txOut.ScriptPubKey
737748 let destinationAddress = scriptPubKey.GetDestinationAddress network
738749 let destination = destinationAddress.ScriptPubKey.GetDestination()
739- if ( destination :> IDestination ) = origin then
750+ if anyAccountAddressesMatch destination account false then
740751 None
741752 else
742753 Some ( destinationAddress, txOut.Value)
@@ -748,7 +759,7 @@ module Account =
748759 failwith " expected a single destination address"
749760
750761 {
751- OriginAddress = originAddress.ToString ()
762+ OriginAddress = ( account :> IAccount ). PublicAddress
752763 DestinationAddress = destinationAddress.ToString()
753764 Amount = value.ToDecimal MoneyUnit.BTC
754765 Currency = currency
0 commit comments