Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions bip-0374.mediawiki
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ It uses a vendored copy of the [https://github.com/secp256k1lab/secp256k1lab/ se
(commit [https://github.com/secp256k1lab/secp256k1lab/commit/44dc4bd893b8f03e621585e3bf255253e0e0fbfb
44dc4bd893b8f03e621585e3bf255253e0e0fbfb]).

'''Note:''' BIP375 is a downstream consumer of this reference implementation; it loads the DLEQ functions from <code>reference.py</code> and uses the vendored secp256k1lab subtree. Before making functional changes to <code>reference.py</code> or the secp256k1lab subtree, please run BIP375’s test suite (<code>python bip-0375/test_runner.py</code>) to check for regressions.

Test vectors can be generated by running <code>./bip-0374/gen_test_vectors.py</code> which will produce a CSV file of random test vectors for both generating and verifying proofs. These can be run against the reference implementation with <code>./bip-0374/run_test_vectors.py</code>.

== Changelog ==
Expand Down
6 changes: 6 additions & 0 deletions bip-0374/reference.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

"""Reference implementation of DLEQ BIP for secp256k1 with unit tests."""

# Note: BIP375 is a downstream consumer of this reference implementation;
# it loads the DLEQ functions from this file and uses the vendored
# secp256k1lab subtree. Before making functional changes to this file
# or the secp256k1lab subtree, please run BIP375’s test suite
# (python bip-0375/test_runner.py) to check for regressions.

from pathlib import Path
import random
import sys
Expand Down
3 changes: 1 addition & 2 deletions bip-0375/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ A reference validation implementation for BIP-375: Sending Silent Payments with
## Dependencies
- **`deps/bitcoin_test/psbt.py`** - Bitcoin test framework PSBT module - [PR #21283](https://github.com/bitcoin/bitcoin/pull/21283)
- **`deps/bitcoin_test/messages.py`** - Bitcoin test framework primitives and message structures
- **`deps/dleq.py`** - Reference DLEQ implementation from BIP-374
- **`deps/secp256k1lab/`** - vendored copy of [secp256k1lab](https://github.com/secp256k1lab/secp256k1lab/commit/44dc4bd893b8f03e621585e3bf255253e0e0fbfb) library at version 1.0.0
- **`deps/dleq.py`** - Import/re-export `dleq_*` functions from `bip-0374/reference.py` in BIP-374

## Testing

Expand Down
102 changes: 23 additions & 79 deletions bip-0375/deps/dleq.py
Original file line number Diff line number Diff line change
@@ -1,88 +1,32 @@
#!/usr/bin/env python3
"""
Handle DLEQ proof generation and verification
Import/re-export BIP-374 DLEQ functions from bip-0374/reference.py
for proof generation and verification.

Adapted from bip-0374 reference.py
Used by the BIP-375 validator for PSBT_GLOBAL_SP_DLEQ / PSBT_IN_SP_DLEQ.
"""

from secp256k1lab.secp256k1 import G, GE
from secp256k1lab.util import tagged_hash, xor_bytes
from importlib.util import module_from_spec, spec_from_file_location
from pathlib import Path


DLEQ_TAG_AUX = "BIP0374/aux"
DLEQ_TAG_NONCE = "BIP0374/nonce"
DLEQ_TAG_CHALLENGE = "BIP0374/challenge"


def dleq_challenge(
A: GE, B: GE, C: GE, R1: GE, R2: GE, m: bytes | None, G: GE,
) -> int:
if m is not None:
assert len(m) == 32
m = bytes([]) if m is None else m
return int.from_bytes(
tagged_hash(
DLEQ_TAG_CHALLENGE,
A.to_bytes_compressed()
+ B.to_bytes_compressed()
+ C.to_bytes_compressed()
+ G.to_bytes_compressed()
+ R1.to_bytes_compressed()
+ R2.to_bytes_compressed()
+ m,
),
"big",
) % GE.ORDER


def dleq_generate_proof(
a: int, B: GE, r: bytes, G: GE = G, m: bytes | None = None
) -> bytes | None:
assert len(r) == 32
if not (0 < a < GE.ORDER):
return None
if B.infinity:
return None
if m is not None:
assert len(m) == 32
A = a * G
C = a * B
t = xor_bytes(a.to_bytes(32, "big"), tagged_hash(DLEQ_TAG_AUX, r))
m_prime = bytes([]) if m is None else m
rand = tagged_hash(
DLEQ_TAG_NONCE, t + A.to_bytes_compressed() + C.to_bytes_compressed() + m_prime
_REFERENCE = Path(__file__).resolve().parents[2] / "bip-0374" / "reference.py"
if not _REFERENCE.is_file():
raise ImportError(
f"BIP-374 reference not found at {_REFERENCE}. "
"Run the BIP-375 tests from a full bips checkout."
)
k = int.from_bytes(rand, "big") % GE.ORDER
if k == 0:
return None
R1 = k * G
R2 = k * B
e = dleq_challenge(A, B, C, R1, R2, m, G)
s = (k + e * a) % GE.ORDER
proof = e.to_bytes(32, "big") + s.to_bytes(32, "big")
if not dleq_verify_proof(A, B, C, proof, G=G, m=m):
return None
return proof

_spec = spec_from_file_location("bip0374_reference", _REFERENCE)
_mod = module_from_spec(_spec)
assert _spec.loader is not None
_spec.loader.exec_module(_mod)

dleq_challenge = _mod.dleq_challenge
dleq_generate_proof = _mod.dleq_generate_proof
dleq_verify_proof = _mod.dleq_verify_proof

def dleq_verify_proof(
A: GE, B: GE, C: GE, proof: bytes, G: GE = G, m: bytes | None = None
) -> bool:
if A.infinity or B.infinity or C.infinity or G.infinity:
return False
assert len(proof) == 64
e = int.from_bytes(proof[:32], "big")
if e >= GE.ORDER:
return False
s = int.from_bytes(proof[32:], "big")
if s >= GE.ORDER:
return False
R1 = s * G - e * A
if R1.infinity:
return False
R2 = s * B - e * C
if R2.infinity:
return False
if e != dleq_challenge(A, B, C, R1, R2, m, G):
return False
return True
__all__ = [
"dleq_challenge",
"dleq_generate_proof",
"dleq_verify_proof",
]
17 changes: 0 additions & 17 deletions bip-0375/deps/secp256k1lab/.github/workflows/main.yml

This file was deleted.

1 change: 0 additions & 1 deletion bip-0375/deps/secp256k1lab/.python-version

This file was deleted.

10 changes: 0 additions & 10 deletions bip-0375/deps/secp256k1lab/CHANGELOG.md

This file was deleted.

23 changes: 0 additions & 23 deletions bip-0375/deps/secp256k1lab/COPYING

This file was deleted.

13 changes: 0 additions & 13 deletions bip-0375/deps/secp256k1lab/README.md

This file was deleted.

34 changes: 0 additions & 34 deletions bip-0375/deps/secp256k1lab/pyproject.toml

This file was deleted.

Empty file.
73 changes: 0 additions & 73 deletions bip-0375/deps/secp256k1lab/src/secp256k1lab/bip340.py

This file was deleted.

16 changes: 0 additions & 16 deletions bip-0375/deps/secp256k1lab/src/secp256k1lab/ecdh.py

This file was deleted.

15 changes: 0 additions & 15 deletions bip-0375/deps/secp256k1lab/src/secp256k1lab/keys.py

This file was deleted.

Empty file.
Loading
Loading