-
-
Save marekyggdrasil/45b164e8976e211cf7a6f982b16ba53d to your computer and use it in GitHub Desktop.
How to produce a Mimblewimble rangeproof and rewind it by @renzokuken
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
secp256k1_zkp_mw | |
bip32 | |
hashlib |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
from typing import List | |
from bip32 import BIP32 | |
from hashlib import blake2b | |
from secp256k1_zkp_mw import SECP256K1_CONTEXT_SIGN | |
from secp256k1_zkp_mw import SECP256K1_CONTEXT_VERIFY | |
from secp256k1_zkp_mw import secp256k1_generator_const_h | |
from secp256k1_zkp_mw import secp256k1_generator_const_g | |
from secp256k1_zkp_mw import secp256k1_context_create | |
from secp256k1_zkp_mw import secp256k1_context_destroy | |
from secp256k1_zkp_mw import secp256k1_context_randomize | |
from secp256k1_zkp_mw import secp256k1_scratch_space_create | |
from secp256k1_zkp_mw import secp256k1_scratch_space_destroy | |
from secp256k1_zkp_mw import secp256k1_pedersen_commit | |
from secp256k1_zkp_mw import secp256k1_pedersen_commitment_serialize | |
from secp256k1_zkp_mw import secp256k1_bulletproof_generators_create | |
from secp256k1_zkp_mw import secp256k1_bulletproof_rangeproof_prove | |
from secp256k1_zkp_mw import secp256k1_bulletproof_rangeproof_rewind | |
from secp256k1_zkp_mw import secp256k1_ec_pubkey_parse | |
from secp256k1_zkp_mw import secp256k1_blind_switch | |
def getKeyIndices(path: str): | |
key_indices = [] | |
for v in path.split('/'): | |
try: | |
i = int(v) | |
except: | |
continue | |
key_indices.append(i) | |
return key_indices | |
def proofMessageFromKeyIndices( | |
key_indices: List[int], is_enhanced=False): | |
padded_path = [0x00 for i in range(20)] | |
if is_enhanced: | |
# padded_path[0] 0x00 reserved | |
# padded_path[1] 0x00 is wallet type | |
padded_path[2] = 0x01 # switch commits | |
padded_path[3] = len(key_indices) | |
for i, key_index in enumerate(key_indices): | |
padded_path[i + 4] = key_index | |
return bytes(padded_path) | |
ctx = secp256k1_context_create( | |
SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY) | |
MAX_WIDTH = 1 << 20 | |
SCRATCH_SPACE_SIZE = 256 * MAX_WIDTH | |
MAX_GENERATORS = 256 | |
x = bytes.fromhex( | |
'b860f56795fc03f3c21685383d1b5a2f2954f49b7e398b8d2a0193933621155f') | |
y = bytes.fromhex( | |
'a43f09d32caa8f53423f427403a56a3165a5a69a74cf56fc5901a2dca6c5c43a') | |
generator_j_pub = secp256k1_ec_pubkey_parse( | |
ctx, bytes([0x04]) + x + y) | |
generators = secp256k1_bulletproof_generators_create( | |
ctx, secp256k1_generator_const_g, MAX_GENERATORS); | |
amount = 45 | |
path = 'm/0/1/0' | |
master_key = os.urandom(32) | |
key_indices = getKeyIndices(path) | |
bulletproof_nonce = secp256k1_blind_switch( | |
ctx, | |
master_key, | |
0, | |
secp256k1_generator_const_h, | |
secp256k1_generator_const_g, | |
generator_j_pub) | |
bip32 = BIP32( | |
chaincode=master_key[32:], privkey=master_key[:32]) | |
secret_key = bip32.get_privkey_from_path(path) | |
assert secret_key == bip32.get_privkey_from_path(key_indices) | |
blinding_factor = secp256k1_blind_switch( | |
ctx, | |
secret_key, | |
amount, | |
secp256k1_generator_const_h, | |
secp256k1_generator_const_g, | |
generator_j_pub) | |
commitment = secp256k1_pedersen_commit( | |
ctx, | |
blinding_factor, | |
amount, | |
secp256k1_generator_const_h, | |
secp256k1_generator_const_g) | |
commitment_serialized = secp256k1_pedersen_commitment_serialize( | |
ctx, commitment) | |
nonce = blake2b( | |
commitment_serialized + bulletproof_nonce, | |
digest_size=32).digest() | |
proof_message = proofMessageFromKeyIndices(key_indices) | |
### GENERATE RANGEPROOF | |
seed = os.urandom(32) | |
secp256k1_context_randomize(ctx, seed) | |
scratch = secp256k1_scratch_space_create( | |
ctx, SCRATCH_SPACE_SIZE) | |
proof_bytes = secp256k1_bulletproof_rangeproof_prove( | |
ctx, | |
scratch, | |
generators, | |
None, | |
None, | |
None, | |
[amount], | |
None, | |
[blinding_factor], | |
None, | |
secp256k1_generator_const_h, | |
64, | |
nonce, | |
nonce, | |
None, | |
proof_message) | |
secp256k1_scratch_space_destroy(scratch) | |
### REWIND RANGEPROOF | |
value, blind, message_bytes = secp256k1_bulletproof_rangeproof_rewind( | |
ctx, proof_bytes, 0, commitment, | |
secp256k1_generator_const_h, nonce, None) | |
### TEST | |
assert value == amount | |
assert blind == blinding_factor | |
assert message_bytes == proof_message | |
print('everything works!') | |
secp256k1_context_destroy(ctx) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment