@@ -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 = 116 u
34+ static member MaximumEncodedLength = 1023 u
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
8387module 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 [| 0x50 uy; 0x92 uy; 0x9b uy; 0x74 uy; 0xc1 uy; 0xa0 uy; 0x49 uy; 0x54 uy; 0xb7 uy; 0x8b uy; 0x4b uy; 0x60 uy; 0x35 uy; 0xe9 uy; 0x7a uy; 0x5e uy;
9094 0x07 uy; 0x8a uy; 0x5a uy; 0x0f uy; 0x28 uy; 0xec uy; 0x96 uy; 0xd5 uy; 0x47 uy; 0xbf uy; 0xee uy; 0x9a uy; 0xce uy; 0x80 uy; 0x3a uy; 0xc0 uy; |]
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 = 0 u
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()
0 commit comments