From b5e62c81c034f2428fb9242a405a9e560d291d8f Mon Sep 17 00:00:00 2001 From: Yeastplume Date: Tue, 29 Aug 2017 17:27:01 +0100 Subject: [PATCH] Switch commitments in libsecp fork (#109) * first pass at switch committment generator * create sage generator script --- core/src/core/block.rs | 1 + grin.toml | 2 +- .../depend/secp256k1-zkp/sage/generators.sage | 34 ++++++++++++++++++ .../src/modules/rangeproof/main_impl.h | 34 +++++++++++++++++- .../src/modules/rangeproof/pedersen.h | 5 +-- .../src/modules/rangeproof/pedersen_impl.h | 5 +-- .../src/modules/rangeproof/switch.h | 19 ++++++++++ .../src/modules/rangeproof/switch_impl.h | 35 +++++++++++++++++++ .../depend/secp256k1-zkp/src/secp256k1.c | 1 + secp256k1zkp/src/ffi.rs | 8 +++++ secp256k1zkp/src/lib.rs | 1 + secp256k1zkp/src/pedersen.rs | 14 ++++++++ 12 files changed, 153 insertions(+), 6 deletions(-) create mode 100644 secp256k1zkp/depend/secp256k1-zkp/sage/generators.sage create mode 100644 secp256k1zkp/depend/secp256k1-zkp/src/modules/rangeproof/switch.h create mode 100644 secp256k1zkp/depend/secp256k1-zkp/src/modules/rangeproof/switch_impl.h diff --git a/core/src/core/block.rs b/core/src/core/block.rs index e14e2df9d..9fb015e16 100644 --- a/core/src/core/block.rs +++ b/core/src/core/block.rs @@ -457,6 +457,7 @@ impl Block { let msg = try!(secp::Message::from_slice(&[0; secp::constants::MESSAGE_SIZE])); let sig = try!(secp.sign(&msg, &skey)); let commit = secp.commit(REWARD, skey).unwrap(); + //let switch_commit = secp.switch_commit(skey).unwrap(); let rproof = secp.range_proof(0, REWARD, skey, commit); let output = Output { diff --git a/grin.toml b/grin.toml index fca845ce0..ece77855f 100644 --- a/grin.toml +++ b/grin.toml @@ -72,7 +72,7 @@ cuckoo_miner_async_mode = false #if not specified, grin will look in the directory /deps relative #to the executable -#cuckoo_miner_plugin_dir = "target/debug/deps" +#cuckoo_miner_plugin_dir = "target/debug/plugins" #if using cuckoo_miner, the implementation to use.. currently #just filters for this word in the filenames in the plugin diff --git a/secp256k1zkp/depend/secp256k1-zkp/sage/generators.sage b/secp256k1zkp/depend/secp256k1-zkp/sage/generators.sage new file mode 100644 index 000000000..5a521fb5c --- /dev/null +++ b/secp256k1zkp/depend/secp256k1-zkp/sage/generators.sage @@ -0,0 +1,34 @@ +import sys +import hashlib +from sage.all import * + +for t in xrange(1023, -1, -1): + p = 2**256 -2**32 - t + if p.is_prime(): + print '%x'%p + break +a = 0 +b = 7 +F = FiniteField(p) + +o = '%x' % (EllipticCurve ([F (a), F(b)]).order()) +print o + +gen2 = hashlib.sha256('0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8'.decode('hex')) +gH = EllipticCurve ([F (0), F(7)]).lift_x(int(gen2.hexdigest(),16)) +print 'gH: %s' % gH +gen_h = '%x %x'%gH.xy() +print 'GENERATOR H: %s'%gen_h + +#this doesn't create a point on the curve +#gen_j_input = '04%x%x'%gG.xy() + +#this does +gen_j_input = gen2.hexdigest() + +print 'gen_j_input: %s'%gen_j_input +gen3 = hashlib.sha256(gen_j_input.decode('hex')) +gJ = EllipticCurve ([F (0), F(7)]).lift_x(int(gen3.hexdigest(),16)) +print 'gJ: %s' % gJ +gen_j = '%x %x'%gJ.xy() +print 'GENERATOR J: %s'%gen_j diff --git a/secp256k1zkp/depend/secp256k1-zkp/src/modules/rangeproof/main_impl.h b/secp256k1zkp/depend/secp256k1-zkp/src/modules/rangeproof/main_impl.h index 28761678a..df783819d 100644 --- a/secp256k1zkp/depend/secp256k1-zkp/src/modules/rangeproof/main_impl.h +++ b/secp256k1zkp/depend/secp256k1-zkp/src/modules/rangeproof/main_impl.h @@ -10,9 +10,41 @@ #include "modules/rangeproof/pedersen_impl.h" #include "modules/rangeproof/borromean_impl.h" #include "modules/rangeproof/rangeproof_impl.h" +#include "modules/rangeproof/switch_impl.h" + +void secp256k1_switch_context_initialize(secp256k1_context* ctx) { + secp256k1_pedersen_context_build(&ctx->switch_ctx, secp256k1_ge_const_g3, &ctx->error_callback); +} + +/* Generates a simple switch commitment: *commit = blind * G3. The commitment is 33 bytes, the blinding factor is 32 bytes.*/ +int secp256k1_switch_commit(const secp256k1_context* ctx, unsigned char *commit, unsigned char *blind) { + secp256k1_gej rj; + secp256k1_ge r; + secp256k1_scalar sec; + size_t sz; + int overflow; + int ret = 0; + ARG_CHECK(ctx != NULL); + ARG_CHECK(secp256k1_pedersen_context_is_built(&ctx->switch_ctx)); + ARG_CHECK(commit != NULL); + ARG_CHECK(blind != NULL); + secp256k1_scalar_set_b32(&sec, blind, &overflow); + if (!overflow) { + secp256k1_switch_ecmult(&ctx->switch_ctx, &rj, &sec); + if (!secp256k1_gej_is_infinity(&rj)) { + secp256k1_ge_set_gej(&r, &rj); + sz = 33; + ret = secp256k1_eckey_pubkey_serialize(&r, commit, &sz, 1); + } + secp256k1_gej_clear(&rj); + secp256k1_ge_clear(&r); + } + secp256k1_scalar_clear(&sec); + return ret; +} void secp256k1_pedersen_context_initialize(secp256k1_context* ctx) { - secp256k1_pedersen_context_build(&ctx->pedersen_ctx, &ctx->error_callback); + secp256k1_pedersen_context_build(&ctx->pedersen_ctx, secp256k1_ge_const_g2, &ctx->error_callback); } /* Generates a pedersen commitment: *commit = blind * G + value * G2. The commitment is 33 bytes, the blinding factor is 32 bytes.*/ diff --git a/secp256k1zkp/depend/secp256k1-zkp/src/modules/rangeproof/pedersen.h b/secp256k1zkp/depend/secp256k1-zkp/src/modules/rangeproof/pedersen.h index f167d4dfb..61e1d333f 100644 --- a/secp256k1zkp/depend/secp256k1-zkp/src/modules/rangeproof/pedersen.h +++ b/secp256k1zkp/depend/secp256k1-zkp/src/modules/rangeproof/pedersen.h @@ -1,5 +1,5 @@ /********************************************************************** - * Copyright (c) 2014, 2015 Gregory Maxwell * + * Copyright (c) 2014, 2015 Gregory Maxwell * * Distributed under the MIT software license, see the accompanying * * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ @@ -17,7 +17,8 @@ typedef struct { } secp256k1_pedersen_context; static void secp256k1_pedersen_context_init(secp256k1_pedersen_context* ctx); -static void secp256k1_pedersen_context_build(secp256k1_pedersen_context* ctx, const secp256k1_callback* cb); +static void secp256k1_pedersen_context_build(secp256k1_pedersen_context* ctx, const secp256k1_ge ge, + const secp256k1_callback* cb); static void secp256k1_pedersen_context_clone(secp256k1_pedersen_context *dst, const secp256k1_pedersen_context* src, const secp256k1_callback* cb); static void secp256k1_pedersen_context_clear(secp256k1_pedersen_context* ctx); diff --git a/secp256k1zkp/depend/secp256k1-zkp/src/modules/rangeproof/pedersen_impl.h b/secp256k1zkp/depend/secp256k1-zkp/src/modules/rangeproof/pedersen_impl.h index 561fd9917..82d912b8f 100644 --- a/secp256k1zkp/depend/secp256k1-zkp/src/modules/rangeproof/pedersen_impl.h +++ b/secp256k1zkp/depend/secp256k1-zkp/src/modules/rangeproof/pedersen_impl.h @@ -13,6 +13,7 @@ * sage: G2 = EllipticCurve ([F (0), F (7)]).lift_x(int(hashlib.sha256('0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8'.decode('hex')).hexdigest(),16)) * sage: '%x %x'%G2.xy() */ + static const secp256k1_ge secp256k1_ge_const_g2 = SECP256K1_GE_CONST( 0x50929b74UL, 0xc1a04954UL, 0xb78b4b60UL, 0x35e97a5eUL, 0x078a5a0fUL, 0x28ec96d5UL, 0x47bfee9aUL, 0xce803ac0UL, @@ -24,7 +25,7 @@ static void secp256k1_pedersen_context_init(secp256k1_pedersen_context *ctx) { ctx->prec = NULL; } -static void secp256k1_pedersen_context_build(secp256k1_pedersen_context *ctx, const secp256k1_callback *cb) { +static void secp256k1_pedersen_context_build(secp256k1_pedersen_context *ctx, const secp256k1_ge ge, const secp256k1_callback *cb) { secp256k1_ge prec[256]; secp256k1_gej gj; secp256k1_gej nums_gej; @@ -37,7 +38,7 @@ static void secp256k1_pedersen_context_build(secp256k1_pedersen_context *ctx, co ctx->prec = (secp256k1_ge_storage (*)[16][16])checked_malloc(cb, sizeof(*ctx->prec)); /* get the generator */ - secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g2); + secp256k1_gej_set_ge(&gj, &ge); /* Construct a group element with no known corresponding scalar (nothing up my sleeve). */ { diff --git a/secp256k1zkp/depend/secp256k1-zkp/src/modules/rangeproof/switch.h b/secp256k1zkp/depend/secp256k1-zkp/src/modules/rangeproof/switch.h new file mode 100644 index 000000000..2d7f6d380 --- /dev/null +++ b/secp256k1zkp/depend/secp256k1-zkp/src/modules/rangeproof/switch.h @@ -0,0 +1,19 @@ +/********************************************************************** + * Copyright (c) 2014, 2017 Gregory Maxwell * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_SWITCH_H_ +#define _SECP256K1_SWITCH_H_ + +#include "group.h" +#include "scalar.h" + +#include + +/* sec * G3. */ +static void secp256k1_switch_ecmult(const secp256k1_pedersen_context *switch_ctx, + secp256k1_gej *rj, + const secp256k1_scalar *sec); +#endif diff --git a/secp256k1zkp/depend/secp256k1-zkp/src/modules/rangeproof/switch_impl.h b/secp256k1zkp/depend/secp256k1-zkp/src/modules/rangeproof/switch_impl.h new file mode 100644 index 000000000..866b04f5a --- /dev/null +++ b/secp256k1zkp/depend/secp256k1-zkp/src/modules/rangeproof/switch_impl.h @@ -0,0 +1,35 @@ +/*********************************************************************** + * Copyright (c) 2017 Gregory Maxwell * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php. * + ***********************************************************************/ + +#ifndef _SECP256K1_SWITCH_IMPL_H_ +#define _SECP256K1_SWITCH_IMPL_H_ + +#include "switch.h" + +/** Alternative-alternative generator for secp256k1. + * This is the sha256 of the sha256 of 'g' after DER encoding (without compression), + * which happens to be a point on the curve. + * sage: gen_h = hashlib.sha256('0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8'.decode('hex')) + * sage: gen_j_input = gen_h.hexdigest() + * sage: gen_j = hashlib.sha256(gen_j_input.decode('hex')) + * sage: G3 = EllipticCurve ([F (0), F (7)]).lift_x(int(gen_j.hexdigest(),16)) + * sage: '%x %x'%G3.xy() + */ + +static const secp256k1_ge secp256k1_ge_const_g3 = SECP256K1_GE_CONST( + 0xb860f567UL, 0x95fc03f3UL, 0xc2168538UL, 0x3d1b5a2fUL, + 0x2954f49bUL, 0x7e398b8dUL, 0x2a019393UL, 0x3621155fUL, + 0x5bc0f62cUL, 0xd35570acUL, 0xbdc0bd8bUL, 0xfc5a95ceUL, + 0x9a5a5965UL, 0x8b30a903UL, 0xa6fe5d22UL, 0x593a37f5UL +); + +/* sec * G3 */ +SECP256K1_INLINE static void secp256k1_switch_ecmult(const secp256k1_pedersen_context *switch_ctx, + secp256k1_gej *rj, const secp256k1_scalar *sec) { + secp256k1_pedersen_ecmult_small(switch_ctx, rj, sec); +} + +#endif diff --git a/secp256k1zkp/depend/secp256k1-zkp/src/secp256k1.c b/secp256k1zkp/depend/secp256k1-zkp/src/secp256k1.c index ec565d233..edcf3fc18 100644 --- a/secp256k1zkp/depend/secp256k1-zkp/src/secp256k1.c +++ b/secp256k1zkp/depend/secp256k1-zkp/src/secp256k1.c @@ -58,6 +58,7 @@ struct secp256k1_context_struct { secp256k1_ecmult_gen_context ecmult_gen_ctx; #ifdef ENABLE_MODULE_RANGEPROOF secp256k1_pedersen_context pedersen_ctx; + secp256k1_pedersen_context switch_ctx; secp256k1_rangeproof_context rangeproof_ctx; #endif secp256k1_callback illegal_callback; diff --git a/secp256k1zkp/src/ffi.rs b/secp256k1zkp/src/ffi.rs index f9217e844..836c2d6ac 100644 --- a/secp256k1zkp/src/ffi.rs +++ b/secp256k1zkp/src/ffi.rs @@ -137,6 +137,7 @@ extern "C" { pub fn secp256k1_context_randomize(cx: *mut Context, seed32: *const c_uchar) -> c_int; pub fn secp256k1_pedersen_context_initialize(ctx: *mut Context); + pub fn secp256k1_switch_context_initialize(ctx: *mut Context); pub fn secp256k1_rangeproof_context_initialize(ctx: *mut Context); // TODO secp256k1_context_set_illegal_callback @@ -292,6 +293,13 @@ extern "C" { scalar: *const c_uchar) -> c_int; + // Generates a switch commitment: *commit = blind * J + // The commitment is 33 bytes, the blinding factor is 32 bytes. + pub fn secp256k1_switch_commit(ctx: *const Context, + commit: *mut c_uchar, + blind: *const c_uchar) + -> c_int; + // Generates a pedersen commitment: *commit = blind * G + value * G2. // The commitment is 33 bytes, the blinding factor is 32 bytes. pub fn secp256k1_pedersen_commit(ctx: *const Context, diff --git a/secp256k1zkp/src/lib.rs b/secp256k1zkp/src/lib.rs index 5a7fce20d..515488e1e 100644 --- a/secp256k1zkp/src/lib.rs +++ b/secp256k1zkp/src/lib.rs @@ -462,6 +462,7 @@ impl Secp256k1 { if caps == ContextFlag::Commit { unsafe { ffi::secp256k1_pedersen_context_initialize(ctx); + ffi::secp256k1_switch_context_initialize(ctx); ffi::secp256k1_rangeproof_context_initialize(ctx); } } diff --git a/secp256k1zkp/src/pedersen.rs b/secp256k1zkp/src/pedersen.rs index fb4c29928..47e4a03af 100644 --- a/secp256k1zkp/src/pedersen.rs +++ b/secp256k1zkp/src/pedersen.rs @@ -199,6 +199,20 @@ impl ::std::fmt::Debug for RangeProof { } impl Secp256k1 { + + /// Creates a switch commitment from a blinding factor + pub fn switch_commit(&self, blind: SecretKey) -> Result { + + if self.caps != ContextFlag::Commit { + return Err(Error::IncapableContext); + } + let mut commit = [0; 33]; + unsafe { + ffi::secp256k1_switch_commit(self.ctx, commit.as_mut_ptr(), blind.as_ptr()) + }; + Ok(Commitment(commit)) + } + /// Creates a pedersen commitment from a value and a blinding factor pub fn commit(&self, value: u64, blind: SecretKey) -> Result {