Skip to content

Commit e798eb1

Browse files
committed
Backend: addressed comments
Refactoring: addressed comments to the PR.
1 parent ddf8b92 commit e798eb1

File tree

3 files changed

+43
-35
lines changed

3 files changed

+43
-35
lines changed

src/GWallet.Backend.Tests/SilentPayments.fs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ type SilentPayments() =
7676
let stream = BitcoinStream(DataEncoders.Encoders.Hex.DecodeData hex)
7777
Some <| WitScript.Load stream
7878
let spInput =
79-
SilentPayments.convertToSilentPaymentInput
79+
SilentPayments.ConvertToSilentPaymentInput
8080
(Script.FromHex input.ScriptPubKey)
8181
(DataEncoders.Encoders.Hex.DecodeData input.ScriptSig)
8282
witness
@@ -104,9 +104,9 @@ type SilentPayments() =
104104
| [], Some _ ->
105105
Assert.Fail(sprintf "No inputs for shared secret derivation in test case '%s'" testCaseName)
106106
| _, Some expectedOutputString ->
107-
let output = SilentPayments.createOutput privateKeys outpoints recipients.[0]
107+
let output = SilentPayments.CreateOutput privateKeys outpoints recipients.[0]
108108
let outputString = output.GetEncoded() |> DataEncoders.Encoders.Hex.EncodeData
109109
Assert.AreEqual(expectedOutputString, outputString, sprintf "Failure in test case '%s'" testCaseName)
110110
| _, None ->
111-
Assert.Throws(fun () -> SilentPayments.createOutput privateKeys outpoints recipients.[0] |> ignore)
111+
Assert.Throws(fun () -> SilentPayments.CreateOutput privateKeys outpoints recipients.[0] |> ignore)
112112
|> ignore

src/GWallet.Backend/UtxoCoin/SilentPayments.fs

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ type SilentPaymentAddress =
2929
static member MainNetPrefix = "sp"
3030
static member TestNetPrefix = "tsp"
3131

32+
// https://github.com/bitcoin/bips/blob/master/bip-0352.mediawiki#address-encoding
33+
static member MinimumEncodedLength = 116u
34+
static member MaximumEncodedLength = 1023u
35+
3236
static member private GetEncoder(chainName: ChainName) =
3337
let hrp =
3438
if chainName = ChainName.Mainnet then
@@ -81,20 +85,20 @@ type SilentPaymentInput =
8185
| InputJustForSpending
8286

8387
module SilentPayments =
84-
let private secp256k1 = EC.CustomNamedCurves.GetByName("secp256k1")
88+
let private secp256k1 = EC.CustomNamedCurves.GetByName "secp256k1"
8589

8690
let private scalarOrder = BigInteger("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16)
8791

88-
let private NUMS_H_bytes =
92+
let private NUMS_H_BYTES =
8993
[| 0x50uy; 0x92uy; 0x9buy; 0x74uy; 0xc1uy; 0xa0uy; 0x49uy; 0x54uy; 0xb7uy; 0x8buy; 0x4buy; 0x60uy; 0x35uy; 0xe9uy; 0x7auy; 0x5euy;
9094
0x07uy; 0x8auy; 0x5auy; 0x0fuy; 0x28uy; 0xecuy; 0x96uy; 0xd5uy; 0x47uy; 0xbfuy; 0xeeuy; 0x9auy; 0xceuy; 0x80uy; 0x3auy; 0xc0uy; |]
9195

92-
type BigInteger with
93-
static member FromByteArrayUnsigned (bytes: array<byte>) =
96+
module BigInteger =
97+
let FromByteArrayUnsigned (bytes: array<byte>) =
9498
BigInteger(1, bytes)
9599

96100
// see https://github.com/bitcoin/bips/blob/master/bip-0352.mediawiki#selecting-inputs
97-
let convertToSilentPaymentInput (scriptPubKey: Script) (scriptSig: array<byte>) (witness: Option<WitScript>): SilentPaymentInput =
101+
let ConvertToSilentPaymentInput (scriptPubKey: Script) (scriptSig: array<byte>) (witness: Option<WitScript>): SilentPaymentInput =
98102
if scriptPubKey.IsScriptType ScriptType.P2PKH then
99103
// skip the first 3 op_codes and grab the 20 byte hash
100104
// from the scriptPubKey
@@ -144,7 +148,7 @@ module SilentPayments =
144148
let controlBlock = witnessStack.Peek()
145149
// controlBlock is <control byte> <32 byte internal key> and 0 or more <32 byte hash>
146150
let internalKey = controlBlock.[1..32]
147-
internalKey = NUMS_H_bytes
151+
internalKey = NUMS_H_BYTES
148152
else
149153
false
150154
if internalKeyIsH then
@@ -165,7 +169,7 @@ module SilentPayments =
165169
else
166170
InvalidInput
167171

168-
let taggedHash (tag: string) (data: array<byte>) : array<byte> =
172+
let TaggedHash (tag: string) (data: array<byte>) : array<byte> =
169173
let sha256 = Digests.Sha256Digest()
170174

171175
let tag = Text.ASCIIEncoding.ASCII.GetBytes tag
@@ -181,12 +185,12 @@ module SilentPayments =
181185
sha256.DoFinal(result, 0) |> ignore
182186
result
183187

184-
let getInputHash (outpoints: List<OutPoint>) (sumInputPubKeys: EC.ECPoint) : array<byte> =
188+
let GetInputHash (outpoints: List<OutPoint>) (sumInputPubKeys: EC.ECPoint) : array<byte> =
185189
let lowestOutpoint = outpoints |> List.map (fun outpoint -> outpoint.ToBytes()) |> List.min
186190
let hashInput = Array.append lowestOutpoint (sumInputPubKeys.GetEncoded true)
187-
taggedHash "BIP0352/Inputs" hashInput
191+
TaggedHash "BIP0352/Inputs" hashInput
188192

189-
let createOutput (privateKeys: List<Key * bool>) (outpoints: List<OutPoint>) (spAddress: SilentPaymentAddress) =
193+
let CreateOutput (privateKeys: List<Key * bool>) (outpoints: List<OutPoint>) (spAddress: SilentPaymentAddress) =
190194
if privateKeys.IsEmpty then
191195
failwith "privateKeys should not be empty"
192196

@@ -211,7 +215,7 @@ module SilentPayments =
211215
if aSum = BigInteger.Zero then
212216
failwith "Input privkeys sum is zero"
213217

214-
let inputHash = getInputHash outpoints (secp256k1.G.Multiply aSum)
218+
let inputHash = GetInputHash outpoints (secp256k1.G.Multiply aSum)
215219

216220
let tweak = BigInteger.FromByteArrayUnsigned inputHash
217221
let tweakedSumSeckey = aSum.Multiply(tweak).Mod(scalarOrder)
@@ -220,11 +224,21 @@ module SilentPayments =
220224

221225
let k = 0u
222226
let tK =
223-
taggedHash
227+
TaggedHash
224228
"BIP0352/SharedSecret"
225229
(Array.append (ecdhSharedSecret.GetEncoded true) (BitConverter.GetBytes k))
226230
|> BigInteger.FromByteArrayUnsigned
227-
let Bm = secp256k1.Curve.DecodePoint <| spAddress.SpendPublicKey.ToBytes()
228-
let sharedSecret = Bm.Add(secp256k1.G.Multiply tK)
231+
let bM = secp256k1.Curve.DecodePoint <| spAddress.SpendPublicKey.ToBytes()
232+
let sharedSecret = bM.Add(secp256k1.G.Multiply tK)
229233

230234
sharedSecret.Normalize().AffineXCoord
235+
236+
let GetFinalDestination (privateKey: Key) (outpoints: List<OutPoint>) (destination: string) (network: Network) : string =
237+
let privateKeys =
238+
outpoints
239+
|> List.map (fun _ -> (privateKey, false))
240+
241+
let output = CreateOutput privateKeys outpoints (SilentPaymentAddress.Decode destination)
242+
let taprootAddress = TaprootAddress(TaprootPubKey(output.GetEncoded()), network)
243+
244+
taprootAddress.ToString()

src/GWallet.Backend/UtxoCoin/UtxoCoinAccount.fs

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ module Account =
291291

292292
let private CalculateSilentPaymentDestination (account: IUtxoAccount)
293293
(transactionInputs: List<TransactionInputOutpointInfo>)
294-
(destination: string)
294+
(reusableAddress: string)
295295
(privateKey: Key) =
296296
// Since we can only receive P2WPKH-P2SH or P2WPKH transactions, and
297297
// non-compressed keys are not accepted as default policy
@@ -302,15 +302,8 @@ module Account =
302302
let outpoints =
303303
transactionInputs
304304
|> List.map (fun input -> (ConvertToICoin account input).Outpoint)
305-
306-
let privateKeys =
307-
outpoints
308-
|> List.map (fun _ -> (privateKey, false))
309-
310-
let output = SilentPayments.createOutput privateKeys outpoints (SilentPaymentAddress.Decode destination)
311-
let taprootAddress = TaprootAddress(TaprootPubKey(output.GetEncoded()), GetNetwork (account:>IAccount).Currency)
312-
313-
taprootAddress.ToString()
305+
306+
SilentPayments.GetFinalDestination privateKey outpoints reusableAddress (GetNetwork (account:>IAccount).Currency)
314307

315308
let private CheckSilentPaymentTransactionInputValidity (finalTransaction: Transaction)
316309
(txMetadataInputs: List<TransactionInputOutpointInfo>) =
@@ -324,11 +317,11 @@ module Account =
324317
| None -> failwith (SPrintF1 "Could not find output with index=%d in txMetadataInputs" input.PrevOut.N)
325318
let scriptPubKey =
326319
Script(NBitcoin.DataEncoders.Encoders.Hex.DecodeData inputOutpointInfo.DestinationInHex)
327-
match SilentPayments.convertToSilentPaymentInput scriptPubKey (input.ScriptSig.ToBytes()) (Some input.WitScript) with
320+
match SilentPayments.ConvertToSilentPaymentInput scriptPubKey (input.ScriptSig.ToBytes()) (Some input.WitScript) with
328321
| InputForSharedSecretDerivation _ -> ()
329322
| _ ->
330323
let errorMessage = SPrintF1 "One of the inputs is not valid for shared secret derivation: %A" inputOutpointInfo
331-
failwith ("Error creating silent payment transaction:\n" + errorMessage)
324+
failwith (SPrintF1 "Error creating silent payment transaction: %s" errorMessage)
332325

333326
let internal EstimateTransferFee
334327
(account: IUtxoAccount)
@@ -427,7 +420,7 @@ module Account =
427420
raise <| Exception(SPrintF1 "Could not create fee rate from %s btc per KB"
428421
(btcPerKiloByteForFastTrans.ToString()), ex)
429422

430-
let destination =
423+
let finalDestination =
431424
if SilentPaymentAddress.IsSilentPaymentAddress destination then
432425
// calculate bogus silent payment destinantion using throwaway private key,
433426
// as it will only be used for fee estimation
@@ -438,7 +431,7 @@ module Account =
438431

439432
let transactionBuilder = CreateTransactionAndCoinsToBeSigned account
440433
initiallyUsedInputs
441-
destination
434+
finalDestination
442435
amount
443436

444437
try
@@ -486,13 +479,13 @@ module Account =
486479

487480
let isSilentPayment = SilentPaymentAddress.IsSilentPaymentAddress destination
488481

489-
let destination =
482+
let finalDestination =
490483
if isSilentPayment then
491484
CalculateSilentPaymentDestination account txMetadata.Inputs destination privateKey
492485
else
493486
destination
494487

495-
let finalTransactionBuilder = CreateTransactionAndCoinsToBeSigned account txMetadata.Inputs destination amount
488+
let finalTransactionBuilder = CreateTransactionAndCoinsToBeSigned account txMetadata.Inputs finalDestination amount
496489

497490
finalTransactionBuilder.AddKeys privateKey |> ignore
498491
finalTransactionBuilder.SendFees (Money.Satoshis btcMinerFee.EstimatedFeeInSatoshis)
@@ -725,8 +718,9 @@ module Account =
725718
// (FIXME: this is only valid for the first version of segwit, fix it!)
726719
Fixed [ 42u; 62u ]
727720
| Currency.BTC, _ when SilentPaymentAddress.IsSilentPaymentAddress address ->
728-
// https://github.com/bitcoin/bips/blob/master/bip-0352.mediawiki#address-encoding
729-
Variable { Minimum = 116u; Maximum = 1023u }
721+
Variable
722+
{ Minimum = SilentPaymentAddress.MinimumEncodedLength
723+
Maximum = SilentPaymentAddress.MaximumEncodedLength }
730724
| Currency.LTC, _ when address.StartsWith LITECOIN_ADDRESS_BECH32_PREFIX ->
731725
// taken from https://coin.space/all-about-address-types/, e.g. ltc1q3qkpj5s4ru3cx9t7dt27pdfmz5aqy3wplamkns
732726
// FIXME: hopefully someone replies/documents https://bitcoin.stackexchange.com/questions/110975/how-long-can-bech32-addresses-be-in-the-litecoin-mainnet

0 commit comments

Comments
 (0)