Skip to content

Commit 5fba3ec

Browse files
Adam GibsonAdam Gibson
Adam Gibson
authored and
Adam Gibson
committed
Add serialization module and simplify lib.rs
This commit substantially refactors the parts of the code concerned with serializing and deserializing keys and points, and isolates the handling of the conversion between BIP340 and ark-ec to a module "serialization".
1 parent 0058246 commit 5fba3ec

7 files changed

+303
-385
lines changed

src/autctactions.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::key_processing::create_fake_privkeys_values_files;
77
use crate::rpcclient;
88
//use crate::rpcserver;
99
use crate::config::{AutctConfig, get_params_from_config_string};
10-
use crate::utils::write_file_string;
10+
use crate::serialization::{write_file_string, read_file_string};
1111
use std::io::Write;
1212
use std::error::Error;
1313
use base64::prelude::*;
@@ -42,7 +42,7 @@ pub async fn create_test_data(autctcfg: AutctConfig) -> Result<(), Box<dyn Error
4242
pub async fn request_encrypt_key(autctcfg: AutctConfig) -> Result<(), Box<dyn Error>> {
4343
let password = rpassword::prompt_password("Enter a password to encrypt the private key: ").unwrap();
4444
let privkey_file_str = autctcfg.privkey_file_str.clone().unwrap();
45-
let plaintext_priv_wif = crate::utils::read_file_string(&privkey_file_str)?;
45+
let plaintext_priv_wif = read_file_string(&privkey_file_str)?;
4646
let mut buf: Vec<u8> = Vec::new();
4747
write!(&mut buf, "{}", plaintext_priv_wif)?;
4848
let encrypted_data = encrypt(&buf, &password.as_bytes())?;

src/key_processing.rs

+9-85
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,25 @@
11
#![allow(non_snake_case)]
22

3-
/// Processing bitcoin private keys, public keys
4-
/// Two main tasks are addressed by this module:
5-
/// 1. creating sets of privkey test values and the
6-
/// corresponding pubkey files.
7-
/// 2. handling conversions between WIF, hex BIP340
8-
/// and ark_ec serialization formats.
3+
/// Processing bitcoin private key files
94
105
extern crate bulletproofs;
116
extern crate merlin;
127
extern crate rand;
138

14-
use ark_ec::{AffineRepr, CurveGroup};
9+
use ark_ec::AffineRepr;
1510
use ark_serialize::CanonicalSerialize;
1611
use bitcoin::secp256k1::All;
1712
use rand::Rng;
1813
use std::iter::zip;
1914

2015
use std::error::Error;
21-
use std::ops::{Mul, Add};
2216
use std::io::Write;
2317
use ark_ec::short_weierstrass::Affine;
2418
use ark_secp256k1::Config as SecpConfig;
25-
use ark_secp256k1::Fq as SecpBase;
26-
use bitcoin::key::{Secp256k1, TapTweak, UntweakedKeypair};
27-
use bitcoin::{PrivateKey, XOnlyPublicKey};
19+
use bitcoin::key::Secp256k1;
20+
use bitcoin::PrivateKey;
2821
use crate::auditor::get_audit_generators;
29-
use crate::utils::*;
30-
use ark_ff::BigInteger256;
22+
use crate::serialization::{self, *};
3123

3224

3325
type F = <ark_secp256k1::Affine as AffineRepr>::ScalarField;
@@ -52,7 +44,7 @@ pub fn create_fake_privkeys_values_files(num_privs: u64,
5244
&buf, bitcoin::Network::Signet).unwrap();
5345
let privhex = hex::encode(&privk2.to_bytes());
5446

55-
let x = decode_hex_le_to_F::<F>(&privhex);
47+
let x = decode_hex_le_to_F::<F>(&privhex)?;
5648
privkey_wifs.push(get_wif_from_field_elem(x)?);
5749
}
5850

@@ -121,29 +113,6 @@ output_filename: &str) -> Result<(), Box<dyn Error>> {
121113
write_file_string(output_filename, buf);
122114
Ok(())
123115
}
124-
/// Currently not in use:
125-
/// A functoin to write the commitments to a keyset
126-
/// file, but in BIP340 format:
127-
pub fn write_keyset_file_from_commitments_UNUSED(comms: Vec<Affine<SecpConfig>>,
128-
output_filename: &str) -> Result<(), Box<dyn Error>> {
129-
let mut buf: Vec<u8> = Vec::new();
130-
let mut commslist: Vec<String> = Vec::new();
131-
for comm in comms {
132-
let mut buf2: Vec<u8> = Vec::new();
133-
comm.serialize_with_mode(&mut buf2,
134-
ark_serialize::Compress::Yes)?;
135-
// ignore the final byte which is the sign byte in ark:
136-
let buf3 = &mut buf2[0..32];
137-
// ark uses LE, so stop that nonsense:
138-
buf3.reverse();
139-
let bin_bip340_pubkey = XOnlyPublicKey::from_slice(&buf3)?.serialize();
140-
let hex_bip340_pubkey = hex::encode(bin_bip340_pubkey);
141-
commslist.push(hex_bip340_pubkey);
142-
}
143-
write!(&mut buf, "{}", commslist.join(" "))?;
144-
write_file_string(output_filename, buf);
145-
Ok(())
146-
}
147116

148117
pub fn get_commitments_from_wif_and_sats_file(privkeys_values_file_loc: &str,
149118
secp: &Secp256k1::<All>) -> Result<
@@ -158,60 +127,15 @@ pub fn get_commitments_from_wif_and_sats(privkeys_wif: Vec<String>,
158127
values: Vec<u64>, secp: &Secp256k1<All>)
159128
-> Result<Vec<Affine<SecpConfig>>, Box<dyn Error>> {
160129
let (_, J) = get_audit_generators();
161-
//Form list of commitments as xG + vJ
162130
let mut comms: Vec<Affine<SecpConfig>> = Vec::new();
163131
for i in 0..privkeys_wif.len() {
164-
let privk2: PrivateKey = PrivateKey::from_wif(
165-
&privkeys_wif[i])?;
166-
let untweaked_key_pair: UntweakedKeypair =
167-
UntweakedKeypair::from_secret_key(
168-
&secp, &privk2.inner);
169-
let tweaked_key_pair = untweaked_key_pair
170-
.tap_tweak(&secp, None);
171-
let privkey_bytes = tweaked_key_pair
172-
.to_inner().secret_bytes();
173-
let privhex = hex::encode(&privkey_bytes);
174-
let x: F = decode_hex_le_to_F(&privhex);
175-
let v = F::from(values[i]);
176-
let P: Affine<SecpConfig>;
177-
(_, P) = get_pub_and_flip_if_necessary(x)?;
178-
// C = xG + vJ (note *un*blinded)
179-
comms.push(P.add(J.mul(v)).into_affine());
132+
let (_, comm) = serialization::privkey_val_to_taproot_ark_ec(
133+
&privkeys_wif[i], values[i], J, secp)?;
134+
comms.push(comm);
180135
}
181136
Ok(comms)
182137
}
183138

184-
pub fn get_wif_from_field_elem(x: F) -> Result<String, Box<dyn Error>>{
185-
let mut buf: Vec<u8> = Vec::new();
186-
x.serialize_compressed(&mut buf)?;
187-
buf.reverse();
188-
let privk2: PrivateKey = PrivateKey::from_slice(&buf, bitcoin::Network::Signet).unwrap();
189-
return Ok(privk2.to_wif());
190-
}
191-
192-
pub fn get_field_elem_from_wif(wif: &String) -> Result<F, Box<dyn Error>> {
193-
let privk = PrivateKey::from_wif(wif)?;
194-
let privkey_bytes = privk.to_bytes();
195-
let privhex = hex::encode(&privkey_bytes);
196-
Ok(decode_hex_le_to_F::<F>(&privhex))
197-
}
198-
199-
/// Since we are using BIP340 pubkeys on chain, we must use the correct
200-
/// sign of x, such that the parity of x*G is even.
201-
/// This is because, the public servers/verifiers have no choice
202-
/// but to assume that the public representation (a BIP340 key)
203-
/// corresponds to that parity, when they do the P +vG arithmetic.
204-
pub fn get_pub_and_flip_if_necessary(mut x: F) -> Result<(F, Affine<SecpConfig>), Box<dyn Error>> {
205-
let (G, _) = get_audit_generators();
206-
let mut P = G.mul(x).into_affine();
207-
let yval: SecpBase = *P.y().unwrap();
208-
let yvalint: BigInteger256 = BigInteger256::from(yval);
209-
if yvalint.0[0] % 2 == 1 {
210-
x = -x;
211-
P = -P;}
212-
Ok((x, P))
213-
}
214-
215139
pub fn get_privkeys_and_values(fileloc: &str) -> Result<(Vec<String>, Vec<u64>), Box<dyn Error>>{
216140
let ptext = read_file_string(&fileloc)?;
217141
let lines = ptext.lines();

src/keyimagestore.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ use ark_ec::short_weierstrass::{Affine, SWCurveConfig};
1111

1212
use crate::config::AutctConfig;
1313
use crate::utils::{APP_DOMAIN_LABEL,
14-
get_generators, write_file_string2};
14+
get_generators};
15+
use crate::serialization::write_file_string2;
1516

1617
pub const KEYIMAGE_FILE_EXTENSION: &[u8] = b".aki";
1718

src/lib.rs

+22-57
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ pub mod generalschnorr;
1313
pub mod key_processing;
1414
pub mod sumrangeproof;
1515
pub mod auditor;
16+
pub mod serialization;
1617
extern crate rand;
1718
extern crate alloc;
1819
extern crate ark_secp256k1;
@@ -55,8 +56,8 @@ pub mod rpc {
5556

5657
use super::*;
5758
use std::{sync::{Arc, Mutex}, u64};
58-
use ark_ff::BigInteger256;
5959
use relations::curve_tree::{CurveTree, SelRerandParameters};
60+
use serialization::privkey_val_to_taproot_ark_ec;
6061

6162
pub struct RPCProverVerifierArgs {
6263
pub keyset_file_locs: Vec<String>,
@@ -138,7 +139,8 @@ impl Clone for RPCProverVerifierArgs {
138139
// failing is a logic error):
139140
let encrypted_data = encrypt(&buf, &args.encryption_password.as_bytes())
140141
.expect("Failed to encrypt");
141-
write_file_string(&resp.privkey_file_loc.clone().unwrap(), encrypted_data);
142+
serialization::write_file_string(&resp.privkey_file_loc.clone().unwrap(),
143+
encrypted_data);
142144
let secp = Secp256k1::new();
143145
// this is the standard way to generate plain-vanilla taproot addresses:
144146
// it is not "raw" (rawtr in descriptors) but it applies a merkle root of
@@ -215,61 +217,20 @@ impl Clone for RPCProverVerifierArgs {
215217
type F = <ark_secp256k1::Affine as AffineRepr>::ScalarField;
216218
let mut privkeys: Vec<F> = Vec::new();
217219
for i in 0..privkeys_wif.len() {
218-
let privkeyres1 =
219-
PrivateKey::from_wif(
220-
&privkeys_wif[i]);
221-
let privkey: PrivateKey = privkeyres1.unwrap();
222-
let untweaked_key_pair: UntweakedKeypair =
223-
UntweakedKeypair::from_secret_key(
224-
&secp, &privkey.inner);
225-
let tweaked_key_pair =
226-
untweaked_key_pair.tap_tweak(&secp, None);
227-
let privkey_bytes = tweaked_key_pair.
228-
to_inner().secret_bytes();
229-
let privhex = hex::encode(&privkey_bytes);
230-
231-
let mut x =
232-
decode_hex_le_to_F::<F>(&privhex);
233-
let mut P = G.mul(x).into_affine();
234-
// Since we are using BIP340 pubkeys on chain, we must use the correct
235-
// sign of x, such that the parity of x*G is even.
236-
// This is because, the public servers/verifiers have no choice
237-
// but to assume that the public representation (a BIP340 key)
238-
// corresponds to that parity, when they do the P +vG arithmetic.
239-
// TODO refactor this, it is reused in key_processing.rs:
240-
let yval: SecpBase = *P.y().unwrap();
241-
let yvalint: BigInteger256 = BigInteger256::from(yval);
242-
if yvalint.0[0] % 2 == 1 {
243-
x = -x;
244-
P = -P;}
220+
let pvres = privkey_val_to_taproot_ark_ec(
221+
&privkeys_wif[i], values[i], J, &secp);
222+
if pvres.is_err(){
223+
resp.accepted = -1;
224+
return Ok(resp);
225+
}
226+
let (x, comm) = pvres.unwrap();
245227
privkeys.push(x);
246-
let v = F::from(values[i]);
247-
// C = xG + vJ (note *un*blinded)
248-
comms.push(P.add(J.mul(v)).into_affine());
228+
comms.push(comm);
249229
}
250230
// 1b. Find the indices of each of the above commitments
251231
// in the pks file.
252-
/*
253-
let filestr:String = read_file_string(&keyset)
254-
.expect("Failed to read pubkey file");
255-
let hex_keys_vec = filestr.split_whitespace().collect::<Vec<_>>();
256-
// replace with convert_pt_to_hex_bip340
257-
let hex_bip340_pubkey = match convert_pt_to_hex_bip340(P) {
258-
Err(_) => {resp.accepted = -8;
259-
return Ok(resp);}
260-
Ok(hp) => hp
261-
};
262-
let key_index =
263-
match get_key_index_from_hex_leaves(
264-
&hex_keys_vec, hex_bip340_pubkey){
265-
Err(_) => {resp.accepted = -8;
266-
return Ok(resp);}
267-
Ok(ki) =>
268-
ki
269-
};
270-
*/
271232
let mut comms_indices: Vec<i32> = Vec::new();
272-
let filestr = read_file_string(&pva.keyset_file_locs[0])
233+
let filestr = serialization::read_file_string(&pva.keyset_file_locs[0])
273234
.expect("Failed to read pubkey file");
274235
let hex_keys_vec = filestr.split_whitespace().collect::<Vec<_>>();
275236
// for each of the points in comms, search for its serialization
@@ -324,7 +285,6 @@ impl Clone for RPCProverVerifierArgs {
324285
resp.accepted = -2;
325286
return Ok(resp);
326287
}
327-
//let verifres = auditproof
328288
// 5. Update the response object and return the serialization of the proof.
329289
let mut buf = Vec::with_capacity(prf.serialized_size(Compress::Yes));
330290
if prf.serialize_compressed(&mut buf).is_err(){
@@ -467,7 +427,12 @@ impl Clone for RPCProverVerifierArgs {
467427
let privkey_bytes = tweaked_key_pair.to_inner().secret_bytes();
468428
let privhex = hex::encode(&privkey_bytes);
469429

470-
let x = decode_hex_le_to_F::<F>(&privhex);
430+
let xres = serialization::decode_hex_le_to_F::<F>(&privhex);
431+
if xres.is_err(){
432+
resp.accepted = -7;
433+
return Ok(resp);
434+
}
435+
let x = xres.unwrap();
471436
let G = SecpConfig::GENERATOR;
472437
let P = G.mul(x).into_affine();
473438
print_affine_compressed(P, "request pubkey");
@@ -478,11 +443,11 @@ impl Clone for RPCProverVerifierArgs {
478443
// TODO the correct solution here is to make all serializations
479444
// read at this level be ark- type and in binary and relegate
480445
// both hex and BIP340 formats to external modules.
481-
let filestr:String = read_file_string(&keyset)
446+
let filestr:String = serialization::read_file_string(&keyset)
482447
.expect("Failed to read pubkey file");
483448
let hex_keys_vec = filestr.split_whitespace().collect::<Vec<_>>();
484-
// replace with convert_pt_to_hex_bip340
485-
let hex_bip340_pubkey = match convert_pt_to_hex_bip340(P) {
449+
let hex_bip340_pubkey = match
450+
serialization::convert_pt_to_hex_bip340(P) {
486451
Err(_) => {resp.accepted = -8;
487452
return Ok(resp);}
488453
Ok(hp) => hp

src/rpcserver.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use ark_serialize::{ CanonicalDeserialize,
44
Compress, Validate};
55
use crate::rpc::{RPCAuditProofVerifier, RPCAuditProver,
66
RPCCreateKeys, RPCProverVerifierArgs, RPCEcho};
7-
use crate::utils::{get_curve_tree,
8-
convert_keys, APP_DOMAIN_LABEL};
7+
use crate::utils::{get_curve_tree, APP_DOMAIN_LABEL};
8+
use crate::serialization::convert_keys;
99
use tokio::{task, net::TcpListener};
1010
use std::fs;
1111
use std::error::Error;

0 commit comments

Comments
 (0)