@@ -15,13 +15,46 @@ public extension secp256k1.Signing.PrivateKey {
1515 /// Create a new `PrivateKey` by adding tweak to the secret key.
1616 /// - Parameter tweak: the 32-byte tweak object
1717 /// - Returns: tweaked `PrivateKey` object
18- func tweak( _ tweak: [ UInt8 ] ) throws -> Self {
18+ func add( _ tweak: [ UInt8 ] ) throws -> Self {
19+ var privateBytes = key. bytes
20+
21+ guard secp256k1_ec_seckey_tweak_add ( secp256k1. Context. raw, & privateBytes, tweak) . boolValue,
22+ secp256k1_ec_seckey_verify ( secp256k1. Context. raw, privateBytes) . boolValue else {
23+ throw secp256k1Error. underlyingCryptoError
24+ }
25+
26+ return try Self ( rawRepresentation: privateBytes)
27+ }
28+
29+ /// Create a new `PrivateKey` by adding tweak to the secret key. When tweaking x-only keys,
30+ /// the implicit negations are handled when odd Y coordinates are reached.
31+ /// [REF](https://github.com/bitcoin-core/secp256k1/issues/1021#issuecomment-983021759)
32+ /// - Parameter tweak: the 32-byte tweak object
33+ /// - Returns: tweaked `PrivateKey` object
34+ func add( xonly tweak: [ UInt8 ] ) throws -> Self {
1935 var keypair = secp256k1_keypair ( )
2036 var privateBytes = [ UInt8] ( repeating: 0 , count: secp256k1. ByteDetails. count)
37+ var xonly = secp256k1_xonly_pubkey ( )
38+ var keyParity = Int32 ( )
2139
2240 guard secp256k1_keypair_create ( secp256k1. Context. raw, & keypair, key. bytes) . boolValue,
2341 secp256k1_keypair_xonly_tweak_add ( secp256k1. Context. raw, & keypair, tweak) . boolValue,
24- secp256k1_keypair_sec ( secp256k1. Context. raw, & privateBytes, & keypair) . boolValue else {
42+ secp256k1_keypair_sec ( secp256k1. Context. raw, & privateBytes, & keypair) . boolValue,
43+ secp256k1_keypair_xonly_pub ( secp256k1. Context. raw, & xonly, & keyParity, & keypair) . boolValue else {
44+ throw secp256k1Error. underlyingCryptoError
45+ }
46+
47+ return try Self ( rawRepresentation: privateBytes)
48+ }
49+
50+ /// Create a new `PrivateKey` by multiplying tweak to the secret key.
51+ /// - Parameter tweak: the 32-byte tweak object
52+ /// - Returns: tweaked `PrivateKey` object
53+ func multiply( _ tweak: [ UInt8 ] ) throws -> Self {
54+ var privateBytes = key. bytes
55+
56+ guard secp256k1_ec_seckey_tweak_mul ( secp256k1. Context. raw, & privateBytes, tweak) . boolValue,
57+ secp256k1_ec_seckey_verify ( secp256k1. Context. raw, privateBytes) . boolValue else {
2558 throw secp256k1Error. underlyingCryptoError
2659 }
2760
@@ -35,23 +68,71 @@ public extension secp256k1.Signing.PublicKey {
3568 /// - tweak: the 32-byte tweak object
3669 /// - format: the format of the tweaked `PublicKey` object
3770 /// - Returns: tweaked `PublicKey` object
38- func tweak( _ tweak: [ UInt8 ] , format: secp256k1 . Format = . compressed) throws -> Self {
39- var xonlyPubKey = secp256k1_xonly_pubkey ( )
71+ func add( _ tweak: [ UInt8 ] , format: secp256k1 . Format = . compressed) throws -> Self {
72+ var pubKey = secp256k1_pubkey ( )
73+ var pubKeyLen = format. length
74+ var pubKeyBytes = [ UInt8] ( repeating: 0 , count: pubKeyLen)
75+ var xonlyKey = secp256k1_xonly_pubkey ( )
76+ var xonlyBytes = [ UInt8] ( repeating: 0 , count: secp256k1. Schnorr. xonlyByteCount)
77+ var keyParity = Int32 ( )
78+
79+ guard secp256k1_ec_pubkey_parse ( secp256k1. Context. raw, & pubKey, bytes, pubKeyLen) . boolValue,
80+ secp256k1_ec_pubkey_tweak_add ( secp256k1. Context. raw, & pubKey, tweak) . boolValue,
81+ secp256k1_ec_pubkey_serialize ( secp256k1. Context. raw, & pubKeyBytes, & pubKeyLen, & pubKey, format. rawValue) . boolValue,
82+ secp256k1_xonly_pubkey_from_pubkey ( secp256k1. Context. raw, & xonlyKey, & keyParity, & pubKey) . boolValue,
83+ secp256k1_xonly_pubkey_serialize ( secp256k1. Context. raw, & xonlyBytes, & xonlyKey) . boolValue else {
84+ throw secp256k1Error. underlyingCryptoError
85+ }
86+
87+ return Self ( rawRepresentation: pubKeyBytes, xonly: xonlyBytes, keyParity: keyParity, format: format)
88+ }
89+
90+ /// Create a new `PublicKey` by multiplying tweak to the public key.
91+ /// - Parameters:
92+ /// - tweak: the 32-byte tweak object
93+ /// - format: the format of the tweaked `PublicKey` object
94+ /// - Returns: tweaked `PublicKey` object
95+ func multiply( _ tweak: [ UInt8 ] , format: secp256k1 . Format = . compressed) throws -> Self {
4096 var pubKey = secp256k1_pubkey ( )
4197 var pubKeyLen = format. length
42- var pubBytes = [ UInt8] ( repeating: 0 , count: pubKeyLen)
43- var xonlyPubKeyOutput = secp256k1_xonly_pubkey ( )
98+ var pubKeyBytes = [ UInt8] ( repeating: 0 , count: pubKeyLen)
99+ var xonlyKey = secp256k1_xonly_pubkey ( )
100+ var xonlyBytes = [ UInt8] ( repeating: 0 , count: secp256k1. Schnorr. xonlyByteCount)
101+ var keyParity = Int32 ( )
102+
103+ guard secp256k1_ec_pubkey_parse ( secp256k1. Context. raw, & pubKey, bytes, pubKeyLen) . boolValue,
104+ secp256k1_ec_pubkey_tweak_mul ( secp256k1. Context. raw, & pubKey, tweak) . boolValue,
105+ secp256k1_ec_pubkey_serialize ( secp256k1. Context. raw, & pubKeyBytes, & pubKeyLen, & pubKey, format. rawValue) . boolValue,
106+ secp256k1_xonly_pubkey_from_pubkey ( secp256k1. Context. raw, & xonlyKey, & keyParity, & pubKey) . boolValue,
107+ secp256k1_xonly_pubkey_serialize ( secp256k1. Context. raw, & xonlyBytes, & xonlyKey) . boolValue else {
108+ throw secp256k1Error. underlyingCryptoError
109+ }
110+
111+ return Self ( rawRepresentation: pubKeyBytes, xonly: xonlyBytes, keyParity: keyParity, format: format)
112+ }
113+ }
114+
115+ public extension secp256k1 . Signing . XonlyKey {
116+ /// Create a new `XonlyKey` by adding tweak to the x-only public key.
117+ /// - Parameters:
118+ /// - tweak: the 32-byte tweak object
119+ /// - format: the format of the tweaked `XonlyKey` object
120+ /// - Returns: tweaked `PublicKey` object
121+ func add( _ tweak: [ UInt8 ] ) throws -> Self {
122+ var pubKey = secp256k1_pubkey ( )
123+ var inXonlyPubKey = secp256k1_xonly_pubkey ( )
124+ var outXonlyPubKey = secp256k1_xonly_pubkey ( )
44125 var xonlyBytes = [ UInt8] ( repeating: 0 , count: secp256k1. Schnorr. xonlyByteCount)
45126 var keyParity = Int32 ( )
46127
47- guard secp256k1_xonly_pubkey_parse ( secp256k1. Context. raw, & xonlyPubKey , xonly . bytes) . boolValue,
48- secp256k1_xonly_pubkey_tweak_add ( secp256k1. Context. raw, & pubKey, & xonlyPubKey , tweak) . boolValue,
49- secp256k1_ec_pubkey_serialize ( secp256k1. Context. raw, & pubBytes , & pubKeyLen , & pubKey, format . rawValue ) . boolValue,
50- secp256k1_xonly_pubkey_from_pubkey ( secp256k1. Context. raw, & xonlyPubKeyOutput , & keyParity , & pubKey ) . boolValue,
51- secp256k1_xonly_pubkey_serialize ( secp256k1. Context. raw, & xonlyBytes, & xonlyPubKeyOutput ) . boolValue else {
128+ guard secp256k1_xonly_pubkey_parse ( secp256k1. Context. raw, & inXonlyPubKey , bytes) . boolValue,
129+ secp256k1_xonly_pubkey_tweak_add ( secp256k1. Context. raw, & pubKey, & inXonlyPubKey , tweak) . boolValue,
130+ secp256k1_xonly_pubkey_from_pubkey ( secp256k1. Context. raw, & outXonlyPubKey , & keyParity , & pubKey) . boolValue,
131+ secp256k1_xonly_pubkey_serialize ( secp256k1. Context. raw, & xonlyBytes , & outXonlyPubKey ) . boolValue,
132+ secp256k1_xonly_pubkey_tweak_add_check ( secp256k1. Context. raw, & xonlyBytes, keyParity , & inXonlyPubKey , tweak ) . boolValue else {
52133 throw secp256k1Error. underlyingCryptoError
53134 }
54135
55- return Self ( rawRepresentation: pubBytes , xonly : xonlyBytes, format : format )
136+ return Self ( rawRepresentation: xonlyBytes, keyParity : keyParity )
56137 }
57138}
0 commit comments