-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add DLEQ proof based on BIP374 and use it for silent payments #1651
base: master
Are you sure you want to change the base?
Conversation
Add a routine for the entire sending flow which takes a set of private keys, the smallest outpoint, and list of recipients and returns a list of x-only public keys by performing the following steps: 1. Sum up the private keys 2. Calculate the input_hash 3. For each recipient group: 3a. Calculate a shared secret 3b. Create the requested number of outputs This function assumes a single sender context in that it requires the sender to have access to all of the private keys. In the future, this API may be expanded to allow for a multiple senders or for a single sender who does not have access to all private keys at any given time, but for now these modes are considered out of scope / unsafe. Internal to the library, add: 1. A function for creating shared secrets (i.e., a*B or b*A) 2. A function for generating the "SharedSecret" tagged hash 3. A function for creating a single output public key Finally, add tests for the sender API.
Add function for creating a label tweak. This requires a tagged hash function for labels. This function is used by the receiver for creating labels to be used for a) creating labelled addresses and b) to populate a labels cache when scanning. Add function for creating a labelled spend pubkey. This involves taking a label tweak, turning it into a public key and adding it to the spend public key. This function is used by the receiver to create a labelled silent payment address. Add tests for the label API.
Add routine for scanning a transaction and returning the necessary spending data for any found outputs. This function works with labels via a lookup callback and requires access to the transaction outputs. Requiring access to the transaction outputs is not suitable for light clients, but light client support is enabled by exposing the `_create_shared_secret` and `_create_output_pubkey` functions in the API. This means the light client will need to manage their own scanning state, so wherever possible it is preferrable to use the `_recipient_scan_ouputs` function. Add an opaque data type for passing around the summed input public key (A_sum) and the input hash tweak (input_hash). This data is passed to the scanner before the ECDH step as two separate elements so that the scanner can multiply b_scan * input_hash before doing ECDH. Add functions for deserializing / serializing a public_data object to and from a public key. When serializing a public_data object, the input_hash is multplied into A_sum. This is so the object can be stored as public key for wallet rescanning later, or to vend to light clients. For the light client, a `_parse` function is added which parses the compressed public key serialization into a `public_data` object. Finally, add test coverage for the recieiving API.
Demonstrate sending, scanning, and light client scanning.
Add a benchmark for a full transaction scan and for scanning a single output. Only benchmarks for scanning are added as this is the most performance critical portion of the protocol.
Add the BIP-352 test vectors. The vectors are generated with a Python script that converts the .json file from the BIP to C code: $ ./tools/tests_silentpayments_generate.py test_vectors.json > ./src/modules/silentpayments/vectors.h
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concept ACK, nice! Left some initial comments for the BIP374-only parts (first two commits).
if (!secp256k1_eckey_pubkey_serialize(p, buf, &size, 1)) { | ||
return 0; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pubkey serialization should always succeed here (as it would only fail if p
is point at inifinity), so could VERIFY_CHECK that instead, like e.g.
secp256k1/src/modules/musig/keyagg_impl.h
Lines 131 to 138 in 00774d0
ret = secp256k1_eckey_pubkey_serialize(pk, buf, &buflen, 1); | |
#ifdef VERIFY | |
/* Serialization does not fail since the pk is not the point at infinity | |
* (according to this function's precondition). */ | |
VERIFY_CHECK(ret && buflen == sizeof(buf)); | |
#else | |
(void) ret; | |
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm true. but since input to this function is secp256k1_ge
and not secp256k1_pubkey
, unsure if it makes sense to restrict possible values of secp256k1_ge
here? (in the musig example, input to the function is secp256k1_pubkey
)
- modify secp256k1-zkp's dleq implementation to be consistent with BIP 374. - use BIP374 notations. - add DLEQ tests
Add BIP374 test vectors. The vectors are generated with a Python script that converts the 2 csv files from the BIP - test_vectors_generate_proof.csv and test_vectors_verify_proof.csv to C code: $ ./tools/test_vectors_dleq_generate.py bips/bip-0374 > ./src/modules/silentpayments/dleq_vectors.h
- add new internal function which returns both DLEQ proof and shared secret. - the existing secp256k1_silentpayments_create_shared_secret API is refactored to use secp256k1_silentpayments_create_shared_secret_with_proof.
- structure contains 33-byte shared secret point + 64-byte DLEQ proof + index of recipient in original unsorted array of silent payment recipients - add functions to serialise and parse the structure to/from bytes
- add new API which returns DLEQ proofs along with outputs for recipients - the existing API secp256k1_silentpayments_sender_create_outputs simply calls secp256k1_silentpayments_sender_create_outputs_with_proof internally.
- in examples/silentpayments.c - sender now generates outputs with proof and verifies the proof - proof can be serialised to bytes and sent to recipient - bytes can be parsed back to proof by recipient as well - recipient can verify proof - in tests_recipients_helper, run_silentpayments_test_vector_send - along with output checks, generate DLEQ proofs and verify them add detailed examples showing parsing/serialisation
built on top of f42e0dd.
(from BIP 374)
This PR:
secp256k1_dleq_prove
,secp256k1_dleq_verify
based on implementation in secp256k1-zkpsecp256k1_silentpayments_dleq_data
which stores the shared secret computed using ECDH, DLEQ proof and also the index of which recipient in the original unsorted recipient array the proof refers to.secp256k1_silentpayments_sender_create_outputs_with_proof
secp256k1_silentpayments_sender_create_outputs
API, output pubkey is created by iterating over all the recipients and computing ECDH for each unique recipient.secp256k1_silentpayments_sender_create_outputs_with_proof
.secp256k1_silentpayments_sender_create_outputs
can usesecp256k1_silentpayments_sender_create_outputs_with_proof
internally.secp256k1_silentpayments_verify_proof
secp256k1_silentpayments_dleq_data_serialize
) serialisessecp256k1_silentpayments_dleq_data
structure into bytes.secp256k1_silentpayments_dleq_data_parse
parses the bytes back intosecp256k1_silentpayments_dleq_data
structure.secp256k1_silentpayments_dleq_data
structure can be serialised into bytes usingsecp256k1_silentpayments_dleq_data_serialize
and then the bytes can be sent from 1 device to another.secp256k1_silentpayments_dleq_data_parse
can reconstruct the bytes back intosecp256k1_silentpayments_dleq_data
structure which can then be used for proof verification.open questions:
examples/silentpayments.c
for 2 scenarios in which proof verification could be useful. (Alice sends bitcoins to Bob and Carol in 1 silent payment transaction)secp256k1_silentpayments_sender_create_outputs
andsecp256k1_silentpayments_sender_create_outputs_with_proof
for backward compatibility.Huge thanks to @ theStack for brainstorming and discussing this with me! ❤️