Skip to content

Commit

Permalink
feat:add pour
Browse files Browse the repository at this point in the history
  • Loading branch information
Nickqiaoo committed Dec 11, 2023
1 parent b0b179e commit eab39f4
Show file tree
Hide file tree
Showing 8 changed files with 253 additions and 90 deletions.
14 changes: 8 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ edition = "2021"

[dependencies]
hex = "0.4"
sha2 = "0.9.5"
num = "0.2"
sha2 = "0.10.8"
num = "0.4.1"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
sled = "0.34.6"
structopt = "0.3"
bs58 = "0.4"
secp256k1 = "0.14"
ripemd160 = "0.8"
rand = "0.8"
bs58 = "0.5.0"
secp256k1 ={ version = "0.28.0",features = ["rand-std"] }
ripemd = "0.1.3"
rand = "0.8"
halo2_gadgets = "0.3.0"
ecies = "0.2.6"
22 changes: 22 additions & 0 deletions src/circuit.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use serde::{Deserialize, Serialize};

use crate::coin::Coin;

#[derive(Serialize, Deserialize)]
pub struct WitnessX {
pub rt: Vec<u8>,
pub old_sn: Vec<u8>,
pub new_cm: Vec<u8>,
pub public_value: u64,
pub h_sig: Vec<u8>,
pub h: Vec<u8>,
}

pub struct WitnessA {
pub path: Vec<Vec<u8>>,
pub old_coin: Coin,
pub secret_key: String,
pub new_coin: Coin,
}

pub fn create_proof(x: WitnessX, a: WitnessA) -> Vec<u8> {}
77 changes: 77 additions & 0 deletions src/coin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
use rand::Rng;
use secp256k1::{PublicKey, Secp256k1};
use sha2::{Digest, Sha256};

#[derive(Clone)]
pub struct Coin {
addr_pk: String,
pub rho: Vec<u8>,
pub v: u64,
pub r: Vec<u8>,
cm: Vec<u8>,
}

impl Coin {
pub fn new(public_key: String, value: u64) -> Self {
let rho = generate_random_bytes(256);
let r = generate_random_bytes(384);

let k = Self::get_k_inner(public_key, &rho, &r);
let cm = Self::get_cm(&k, value);
Coin {
addr_pk: public_key,
rho,
v: value,
r,
cm,
}
}
pub fn get_k(&self) -> Vec<u8> {
Self::get_k_inner(self.addr_pk, &self.rho, &self.r)
}

//H(r || H(pk || rho))
fn get_k_inner(public_key: String, rho: &Vec<u8>, r: &Vec<u8>) -> Vec<u8> {
let public_key_bytes = hex::decode(public_key).expect("Failed to decode public key");
let secp = Secp256k1::new();
let public_key = PublicKey::from_slice(&public_key_bytes).expect("Invalid public key");

let mut combined_data = Vec::new();
combined_data.extend_from_slice(&public_key.serialize_uncompressed());
combined_data.extend(rho);

let midk = Sha256::digest(&combined_data).to_vec();
let truncated_hash: Vec<u8> = midk.iter().take(128 / 8).cloned().collect();

combined_data = Vec::new();
combined_data.extend(truncated_hash);
combined_data.extend(r);

Sha256::digest(&combined_data).to_vec()
}

pub fn cm(&self) -> Vec<u8> {
self.cm.clone()
}

pub fn get_cm(k: &Vec<u8>, v: u64) -> Vec<u8> {
let zero_padding: Vec<u8> = vec![0; 192 / 8];

let mut combined_data = Vec::new();
combined_data.extend(k);
combined_data.extend(zero_padding);
combined_data.extend_from_slice(&v.to_be_bytes());

Sha256::digest(&combined_data).to_vec()
}
}

pub fn generate_random_bytes(bits: usize) -> Vec<u8> {
let mut rng = rand::thread_rng();

let byte_count = (bits + 7) / 8;

let random_bytes: Vec<u8> = (0..byte_count).map(|_| rng.gen()).collect();

random_bytes
}
4 changes: 4 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@ use structopt::StructOpt;

mod block;
mod blockchain;
mod circuit;
mod cli;
mod coin;
mod iterator;
mod mint;
mod pour;
mod pow;
mod transaction;
mod transaction_input;
Expand Down
67 changes: 9 additions & 58 deletions src/mint.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,4 @@
use secp256k1::{PublicKey, Secp256k1};
use sha2::{Digest, Sha256};

use crate::{util, wallets::Wallets};

pub struct Coin {
addr_pk: String,
rho: Vec<u8>,
v: u64,
r: Vec<u8>,
cm: Vec<u8>,
}
use crate::{coin::Coin, wallets::Wallets};

pub struct TXMint {
v: u64,
Expand All @@ -26,60 +15,22 @@ pub fn mint(address: String, value: u64) -> (Coin, MintTransaction) {
let wallets = Wallets::new();
let wallet = wallets.get_wallet(&address).unwrap();

let rho = util::generate_random_bytes(256);
let r = util::generate_random_bytes(384);

let k = create_k(wallet.public_key, &rho, &r);
let cm = create_cm(&k, value);

let c = Coin {
addr_pk: wallet.public_key,
rho,
v: value,
r,
cm,
};
let c = Coin::new(wallet.public_key, value);
let k = c.get_k();
(
c,
MintTransaction {
id: vec![],
vout: TXMint { v: value, k, cm },
vout: TXMint {
v: value,
k,
cm: c.cm(),
},
},
)
}

//H(r || H(pk || rho))
fn create_k(public_key: String, rho: &Vec<u8>, r: &Vec<u8>) -> Vec<u8> {
let public_key_bytes = hex::decode(public_key).expect("Failed to decode public key");
let secp = Secp256k1::new();
let public_key = PublicKey::from_slice(&public_key_bytes).expect("Invalid public key");

let mut combined_data = Vec::new();
combined_data.extend_from_slice(&public_key.serialize_uncompressed());
combined_data.extend_from_slice(&rho);

let midk = Sha256::digest(&combined_data).to_vec();
let truncated_hash: Vec<u8> = midk.iter().take(128 / 8).cloned().collect();

combined_data = Vec::new();
combined_data.extend_from_slice(&truncated_hash);
combined_data.extend_from_slice(&r);

Sha256::digest(&combined_data).to_vec()
}

fn create_cm(k: &Vec<u8>, v: u64) -> Vec<u8> {
let zero_padding: Vec<u8> = vec![0; 192 / 8];

let mut combined_data = Vec::new();
combined_data.extend_from_slice(&k);
combined_data.extend_from_slice(&zero_padding);
combined_data.extend_from_slice(&v.to_be_bytes());

Sha256::digest(&combined_data).to_vec()
}

pub fn verify_mint(tx: &MintTransaction) -> bool {
let cm = create_cm(&tx.vout.k, tx.vout.v);
let cm = Coin::get_cm(&tx.vout.k, tx.vout.v);
cm == tx.vout.cm
}
120 changes: 120 additions & 0 deletions src/pour.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
use crate::{
circuit::{self, WitnessA, WitnessX},
coin::Coin,
wallet::Wallet,
wallets::Wallets,
};
use ecies::{decrypt, encrypt};
use sha2::{Digest, Sha256};

pub struct TXPour {
rt: Vec<u8>,
old_sn: Vec<u8>,
new_cm: Vec<u8>,
public_value: u64,
info: String,
pk_sig: String,
h: Vec<u8>,
pi_pour: Vec<u8>,
c_info: Vec<u8>,
sigma: Vec<u8>,
}

pub struct PourTransaction {
pub id: Vec<u8>,
pub vout: TXPour,
}

pub fn pour(
merkle_root: &Vec<u8>,
old_coin: &Coin,
old_adress: String,
merkle_path: &Vec<Vec<u8>>,
new_value: u64,
new_address: String,
public_value: u64,
info: String,
) -> (Coin, PourTransaction) {
let wallets = Wallets::new();
let wallet_new = wallets.get_wallet(&new_address).unwrap();
let wallet_old = wallets.get_wallet(&old_adress).unwrap();

let sn_msg = wallet_old.private_key.as_bytes().to_vec();
sn_msg.extend(old_coin.rho);
let old_sn = Sha256::digest(sn_msg).to_vec();

let c = Coin::new(wallet_new.public_key, new_value);
let c_info = create_c_info(&wallet_new.public_key, &c.rho, c.v, &c.r);

let sig_wallet = Wallet::new();
let h_sig = Sha256::digest(&sig_wallet.public_key).to_vec();

let h_msg = wallet_old.private_key.as_bytes().to_vec();
h_msg.extend(h_sig);
let h = Sha256::digest(h_msg).to_vec();

let wx = WitnessX {
rt: merkle_root.clone(),
old_sn: old_sn.clone(),
new_cm: c.cm(),
public_value,
h_sig: h_sig.clone(),
h: h.clone(),
};
let wa = WitnessA {
path: merkle_path.clone(),
old_coin: old_coin.clone(),
secret_key: wallet_old.private_key.clone(),
new_coin: c,
};

let pi_pour = circuit::create_proof(wx, wa);
let sigma = create_sig(&sig_wallet.private_key, &wx, &pi_pour, &info, &c_info);

(
c,
PourTransaction {
id: vec![],
vout: TXPour {
rt: merkle_root.clone(),
old_sn,
new_cm: c.cm(),
public_value,
info,
pk_sig: sig_wallet.public_key,
h,
pi_pour,
c_info,
sigma,
},
},
)
}

fn create_c_info(public_key: &String, rho: &Vec<u8>, v: u64, r: &Vec<u8>) -> Vec<u8> {
let mut message = Vec::new();
message.extend(rho);
message.extend(&v.to_be_bytes().to_vec());
message.extend(r);

encrypt(public_key.as_bytes(), &message).unwrap()
}

fn create_sig(
sk: &String,
x: &WitnessX,
pi_pour: &Vec<u8>,
info: &String,
c_info: &Vec<u8>,
) -> Vec<u8> {
let priv_key = secp256k1::SecretKey::from_slice(hex::decode(sk).unwrap().as_slice()).unwrap();

let msg = serde_json::to_string(x).unwrap();
msg = format!("{}{:?}{}{:?}", msg, pi_pour, info, c_info);
let sig_message = secp256k1::Message::from_digest_slice(&msg.as_bytes()).unwrap();

let secp = secp256k1::Secp256k1::new();
secp.sign_ecdsa(&sig_message, &priv_key)
.serialize_compact()
.to_vec()
}
10 changes: 5 additions & 5 deletions src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@ impl Transaction {
tx_copy.id = tx_copy.hash();
tx_copy.vin[in_id].pub_key = vec![];

let tx_copy_message = secp256k1::Message::from_slice(&tx_copy.id).unwrap();
let tx_copy_message = secp256k1::Message::from_digest_slice(&tx_copy.id).unwrap();
let context = secp256k1::Secp256k1::new();
let signature = context.sign(&tx_copy_message, &private_key);
let signature = context.sign_ecdsa(&tx_copy_message, &private_key);
let sig = signature.serialize_compact();

self.vin[in_id].signature = sig.to_vec();
Expand All @@ -113,14 +113,14 @@ impl Transaction {
tx_copy.id = tx_copy.hash();
tx_copy.vin[in_id].pub_key = vec![];

let tx_copy_message = secp256k1::Message::from_slice(&tx_copy.id).unwrap();
let tx_copy_message = secp256k1::Message::from_digest_slice(&tx_copy.id).unwrap();

let pk =
secp256k1::PublicKey::from_slice(hex::decode(&vin.pub_key).unwrap().as_slice())
.unwrap();

let sig = secp256k1::Signature::from_compact(&vin.signature).unwrap();
if secp.verify(&tx_copy_message, &sig, &pk).is_err() {
let sig = secp256k1::ecdsa::Signature::from_compact(&vin.signature).unwrap();
if secp.verify_ecdsa(&tx_copy_message, &sig, &pk).is_err() {
return false;
}
}
Expand Down
Loading

0 comments on commit eab39f4

Please sign in to comment.