Skip to content

Commit f67e576

Browse files
theStackjosibake
authored andcommitted
silentpayments: implement output pubkey creation
Add methods for creating an xonly output from a shared secret. This involves adding a tagged hash for creating the output. This function will be exposed in the API in a later commit for the receiver to use when scanning as a light client.
1 parent 944bf76 commit f67e576

File tree

1 file changed

+50
-0
lines changed

1 file changed

+50
-0
lines changed

src/modules/silentpayments/main_impl.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,4 +123,54 @@ int secp256k1_silentpayments_create_shared_secret(const secp256k1_context *ctx,
123123
return 1;
124124
}
125125

126+
/** Set hash state to the BIP340 tagged hash midstate for "BIP0352/SharedSecret". */
127+
static void secp256k1_silentpayments_sha256_init_sharedsecret(secp256k1_sha256* hash) {
128+
secp256k1_sha256_initialize(hash);
129+
hash->s[0] = 0x88831537ul;
130+
hash->s[1] = 0x5127079bul;
131+
hash->s[2] = 0x69c2137bul;
132+
hash->s[3] = 0xab0303e6ul;
133+
hash->s[4] = 0x98fa21faul;
134+
hash->s[5] = 0x4a888523ul;
135+
hash->s[6] = 0xbd99daabul;
136+
hash->s[7] = 0xf25e5e0aul;
137+
138+
hash->bytes = 64;
139+
}
140+
141+
static void secp256k1_silentpayments_create_t_k(secp256k1_scalar *t_k_scalar, const unsigned char *shared_secret33, unsigned int k) {
142+
secp256k1_sha256 hash;
143+
unsigned char hash_ser[32];
144+
unsigned char k_serialized[4];
145+
146+
/* Compute t_k = hash(shared_secret || ser_32(k)) [sha256 with tag "BIP0352/SharedSecret"] */
147+
secp256k1_silentpayments_sha256_init_sharedsecret(&hash);
148+
secp256k1_sha256_write(&hash, shared_secret33, 33);
149+
secp256k1_write_be32(k_serialized, k);
150+
secp256k1_sha256_write(&hash, k_serialized, sizeof(k_serialized));
151+
secp256k1_sha256_finalize(&hash, hash_ser);
152+
secp256k1_scalar_set_b32(t_k_scalar, hash_ser, NULL);
153+
}
154+
155+
int secp256k1_silentpayments_create_output_pubkey(const secp256k1_context *ctx, secp256k1_xonly_pubkey *P_output_xonly, const unsigned char *shared_secret33, const secp256k1_pubkey *recipient_spend_pubkey, unsigned int k) {
156+
secp256k1_ge P_output_ge;
157+
secp256k1_scalar t_k_scalar;
158+
159+
/* Sanity check inputs */
160+
VERIFY_CHECK(ctx != NULL);
161+
ARG_CHECK(P_output_xonly != NULL);
162+
ARG_CHECK(shared_secret33 != NULL);
163+
ARG_CHECK(recipient_spend_pubkey != NULL);
164+
165+
/* Calculate and return P_output_xonly = B_spend + t_k * G */
166+
secp256k1_silentpayments_create_t_k(&t_k_scalar, shared_secret33, k);
167+
secp256k1_pubkey_load(ctx, &P_output_ge, recipient_spend_pubkey);
168+
if (!secp256k1_eckey_pubkey_tweak_add(&P_output_ge, &t_k_scalar)) {
169+
return 0;
170+
}
171+
secp256k1_xonly_pubkey_save(P_output_xonly, &P_output_ge);
172+
173+
return 1;
174+
}
175+
126176
#endif

0 commit comments

Comments
 (0)