Skip to content

Commit

Permalink
add circuit
Browse files Browse the repository at this point in the history
  • Loading branch information
Nickqiaoo committed Dec 14, 2023
1 parent eab39f4 commit e3dfab0
Show file tree
Hide file tree
Showing 5 changed files with 187 additions and 26 deletions.
10 changes: 8 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ name = "linar"
version = "0.1.0"
edition = "2021"

[features]
dev-graph = ["halo2_proofs/dev-graph", "plotters", "plotters/bitmap_backend","plotters/bitmap_encoder"]

[dependencies]
hex = "0.4"
sha2 = "0.10.8"
Expand All @@ -15,5 +18,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"
halo2_gadgets = { version = "0.3.0",features = ["unstable-sha256-gadget"] }
ecies = "0.2.6"
halo2_proofs = "0.3.0"
plotters = { version = "0.3.0", default-features = true, optional = true }
pasta_curves = "0.5"
158 changes: 154 additions & 4 deletions src/circuit.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
use serde::{Deserialize, Serialize};

use crate::coin::Coin;
use halo2_gadgets::sha256::{BlockWord,Bits,AssignedBits, Table16Chip, Table16Config};
use halo2_proofs::{
arithmetic::Field,
circuit::{AssignedCell, Layouter, SimpleFloorPlanner, Value},
plonk::{Advice, Assigned, Circuit, Column, ConstraintSystem, Error, Instance, Selector},
poly::Rotation,
};
use pasta_curves::{arithmetic::CurveAffine, pallas, vesta};
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
pub struct WitnessX {
pub struct InstanceX {
pub rt: Vec<u8>,
pub old_sn: Vec<u8>,
pub new_cm: Vec<u8>,
Expand All @@ -19,4 +26,147 @@ pub struct WitnessA {
pub new_coin: Coin,
}

pub fn create_proof(x: WitnessX, a: WitnessA) -> Vec<u8> {}
pub fn create_proof(x: &InstanceX, a: &WitnessA) -> Vec<u8> {
vec![]
}

#[derive(Debug, Clone)]
struct CircuitConfig {
advice: Column<Advice>,
instance: Column<Instance>,
sha_config: Table16Config,
}

#[derive(Default)]
struct PourCircuit {
pk: [BlockWord;16],
sk: [BlockWord;8],
}

impl PourCircuit {
fn load_private(
&self,
config: &CircuitConfig,
mut layouter: impl Layouter<pallas::Base>,
values: [BlockWord;16]
) -> Result<Vec<AssignedBits<32>>, Error> {
layouter.assign_region(
|| "assign private values",
|mut region| {
values
.iter()
.enumerate()
.map(|(i, value)| {
// Check that each cell of the input is a binary value
// Assign the private input value to an advice cell
region
.assign_advice(|| "assign private input", config.advice, i, || -> Bits<32> {value.0.into()})
}
)
.collect()
}
)
}
}


impl Circuit<pallas::Base> for PourCircuit {
type Config = CircuitConfig;
type FloorPlanner = SimpleFloorPlanner;

fn without_witnesses(&self) -> Self {
Self::default()
}

fn configure(meta: &mut ConstraintSystem<pallas::Base>) -> Self::Config {
let sha_config = Table16Chip::configure(meta);

let advice = meta.advice_column();
let instance = meta.instance_column();

meta.enable_equality(instance);
meta.enable_equality(advice);

CircuitConfig {
advice,
instance,
sha_config,
}
}

fn synthesize(
&self,
config: Self::Config,
mut layouter: impl Layouter<pallas::Base>,
) -> Result<(), Error> {
Table16Chip::load(config.sha_config.clone(), &mut layouter)?;
let table16_chip = Table16Chip::construct(config.sha_config);

let a = self.load_private(&config, layouter, self.pk);
Ok(())
}
}

#[cfg(test)]
mod tests {
use super::*;
use halo2_proofs::{dev::MockProver, pasta::Fp};
#[test]
fn test_chap_1() {
// ANCHOR: test-circuit
// The number of rows in our circuit cannot exceed 2^k. Since our example
// circuit is very small, we can pick a very small value here.
let k = 5;

// Prepare the private and public inputs to the circuit!
let c = Fp::from(1);
let a = Fp::from(2);
let b = Fp::from(3);
let out = c * a.square() * b.square();
println!("out=:{:?}", out);

// Instantiate the circuit with the private inputs.
let circuit = PourCircuit {};

// Arrange the public input. We expose the multiplication result in row 0
// of the instance column, so we position it there in our public inputs.
let mut public_inputs = vec![out];

// Given the correct public input, our circuit will verify.
let prover = MockProver::run(k, &circuit, vec![public_inputs.clone()]).unwrap();
assert_eq!(prover.verify(), Ok(()));

// If we try some other public input, the proof will fail!
public_inputs[0] += Fp::one();
let prover = MockProver::run(k, &circuit, vec![public_inputs]).unwrap();
assert!(prover.verify().is_err());
println!("\n\n\n!!!!!OHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH!!!!!\n simple example success !\n!!!!!OHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH!!!!!\n\n\n")
// ANCHOR_END: test-circuit
}

#[cfg(feature = "dev-graph")]
//cargo test plot_chap_1_circuit --features dev-graph
#[test]
fn plot_chap_1_circuit() {
// Instantiate the circuit with the private inputs.
let circuit = PourCircuit::<Fp>::default();
// Create the area you want to draw on.
// Use SVGBackend if you want to render to .svg instead.
use plotters::prelude::*;
let root = BitMapBackend::new("./chap_1_simple.png", (1024, 768)).into_drawing_area();
root.fill(&WHITE).unwrap();
let root = root
.titled("Simple Circuit without chip", ("sans-serif", 60))
.unwrap();
halo2_proofs::dev::CircuitLayout::default()
// You can optionally render only a section of the circuit.
// .view_width(0..2)
// .view_height(0..16)
// You can hide labels, which can be useful with smaller areas.
.show_labels(true)
// Render the circuit onto your area!
// The first argument is the size parameter for the circuit.
.render(5, &circuit, &root)
.unwrap();
}
}
8 changes: 4 additions & 4 deletions src/coin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,26 @@ pub struct Coin {
}

impl Coin {
pub fn new(public_key: String, value: u64) -> Self {
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,
addr_pk: public_key.clone(),
rho,
v: value,
r,
cm,
}
}
pub fn get_k(&self) -> Vec<u8> {
Self::get_k_inner(self.addr_pk, &self.rho, &self.r)
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> {
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");
Expand Down
5 changes: 3 additions & 2 deletions src/mint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ pub fn mint(address: String, value: u64) -> (Coin, MintTransaction) {
let wallets = Wallets::new();
let wallet = wallets.get_wallet(&address).unwrap();

let c = Coin::new(wallet.public_key, value);
let c = Coin::new(&wallet.public_key, value);
let cm = c.cm();
let k = c.get_k();
(
c,
Expand All @@ -24,7 +25,7 @@ pub fn mint(address: String, value: u64) -> (Coin, MintTransaction) {
vout: TXMint {
v: value,
k,
cm: c.cm(),
cm: cm,
},
},
)
Expand Down
32 changes: 18 additions & 14 deletions src/pour.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
circuit::{self, WitnessA, WitnessX},
circuit::{self, WitnessA, InstanceX},
coin::Coin,
wallet::Wallet,
wallets::Wallets,
Expand Down Expand Up @@ -39,21 +39,21 @@ pub fn pour(
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 mut 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 = 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 mut 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 {
let wx = InstanceX {
rt: merkle_root.clone(),
old_sn: old_sn.clone(),
new_cm: c.cm(),
Expand All @@ -65,20 +65,20 @@ pub fn pour(
path: merkle_path.clone(),
old_coin: old_coin.clone(),
secret_key: wallet_old.private_key.clone(),
new_coin: c,
new_coin: c.clone(),
};

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

let cm = c.cm();
(
c,
PourTransaction {
id: vec![],
vout: TXPour {
rt: merkle_root.clone(),
old_sn,
new_cm: c.cm(),
new_cm: cm,
public_value,
info,
pk_sig: sig_wallet.public_key,
Expand All @@ -102,14 +102,14 @@ fn create_c_info(public_key: &String, rho: &Vec<u8>, v: u64, r: &Vec<u8>) -> Vec

fn create_sig(
sk: &String,
x: &WitnessX,
x: &InstanceX,
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();
let mut 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();

Expand All @@ -118,3 +118,7 @@ fn create_sig(
.serialize_compact()
.to_vec()
}

pub fn verify_pour(tx: &PourTransaction) -> bool {
false
}

0 comments on commit e3dfab0

Please sign in to comment.