Compare commits
9 commits
Author | SHA1 | Date | |
---|---|---|---|
07c143b65e | |||
f57af0519d | |||
34c5b9044d | |||
724a19bddb | |||
0cbe93246b | |||
dc4f9eb80f | |||
92a83bb58e | |||
01ec9bdf7d | |||
e9b276de83 |
13 changed files with 6397 additions and 0 deletions
16
.gitignore
vendored
Normal file
16
.gitignore
vendored
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
# Cargo build
|
||||||
|
**/target
|
||||||
|
|
||||||
|
# Cargo config
|
||||||
|
.cargo
|
||||||
|
|
||||||
|
# Profile-guided optimization
|
||||||
|
/tmp
|
||||||
|
pgo-data.profdata
|
||||||
|
|
||||||
|
# MacOS nuisances
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Proofs
|
||||||
|
**/proof-with-pis.json
|
||||||
|
**/proof-with-io.json
|
9
core/Cargo.toml
Normal file
9
core/Cargo.toml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
[package]
|
||||||
|
name = "mtcs-core"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
serde = { version = "1.0", default-features = false, features = ["derive", "alloc"] }
|
37
core/src/lib.rs
Normal file
37
core/src/lib.rs
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||||
|
pub struct PrivateKey {
|
||||||
|
pub key: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||||
|
pub struct Proof {
|
||||||
|
pub bytes: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||||
|
pub struct MerkleData {
|
||||||
|
pub merkle_root: [u8; 32],
|
||||||
|
pub indexes: Vec<usize>,
|
||||||
|
pub len: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Address = [u8; 20];
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||||
|
pub struct Obligation {
|
||||||
|
pub from: Address,
|
||||||
|
pub to: Address,
|
||||||
|
pub value: u8, // TODO: make this u32 or higher
|
||||||
|
pub salt: [u8; 32],
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type ObligationList = Vec<Obligation>;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||||
|
pub struct Cycle {
|
||||||
|
pub setoff: u8,
|
||||||
|
pub size: usize,
|
||||||
|
pub obligations: ObligationList,
|
||||||
|
}
|
123
cycle.json
Normal file
123
cycle.json
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
{
|
||||||
|
"setoff": 103,
|
||||||
|
"size": 3,
|
||||||
|
"obligations": [
|
||||||
|
{
|
||||||
|
"from": [155, 161, 188, 216, 142, 153, 214, 225, 224, 50, 82, 167, 10, 99, 254, 168, 59, 241, 32, 140],
|
||||||
|
"to": [111, 248, 64, 238, 239, 254, 192, 195, 95, 82, 187, 96, 49, 169, 174, 52, 82, 74, 5, 182],
|
||||||
|
"value": 103,
|
||||||
|
"salt": [
|
||||||
|
134,
|
||||||
|
104,
|
||||||
|
222,
|
||||||
|
91,
|
||||||
|
13,
|
||||||
|
97,
|
||||||
|
183,
|
||||||
|
43,
|
||||||
|
190,
|
||||||
|
29,
|
||||||
|
199,
|
||||||
|
203,
|
||||||
|
206,
|
||||||
|
17,
|
||||||
|
241,
|
||||||
|
117,
|
||||||
|
145,
|
||||||
|
238,
|
||||||
|
154,
|
||||||
|
201,
|
||||||
|
79,
|
||||||
|
48,
|
||||||
|
188,
|
||||||
|
175,
|
||||||
|
205,
|
||||||
|
156,
|
||||||
|
218,
|
||||||
|
223,
|
||||||
|
93,
|
||||||
|
208,
|
||||||
|
253,
|
||||||
|
13
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": [111, 248, 64, 238, 239, 254, 192, 195, 95, 82, 187, 96, 49, 169, 174, 52, 82, 74, 5, 182],
|
||||||
|
"to": [66, 206, 221, 229, 17, 152, 209, 119, 53, 144, 49, 30, 42, 52, 13, 192, 107, 36, 203, 55],
|
||||||
|
"value": 197,
|
||||||
|
"salt": [
|
||||||
|
47,
|
||||||
|
45,
|
||||||
|
177,
|
||||||
|
118,
|
||||||
|
3,
|
||||||
|
36,
|
||||||
|
136,
|
||||||
|
70,
|
||||||
|
238,
|
||||||
|
148,
|
||||||
|
143,
|
||||||
|
56,
|
||||||
|
140,
|
||||||
|
115,
|
||||||
|
20,
|
||||||
|
16,
|
||||||
|
235,
|
||||||
|
102,
|
||||||
|
188,
|
||||||
|
236,
|
||||||
|
119,
|
||||||
|
192,
|
||||||
|
25,
|
||||||
|
103,
|
||||||
|
197,
|
||||||
|
72,
|
||||||
|
237,
|
||||||
|
170,
|
||||||
|
40,
|
||||||
|
203,
|
||||||
|
125,
|
||||||
|
227
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": [66, 206, 221, 229, 17, 152, 209, 119, 53, 144, 49, 30, 42, 52, 13, 192, 107, 36, 203, 55],
|
||||||
|
"to": [155, 161, 188, 216, 142, 153, 214, 225, 224, 50, 82, 167, 10, 99, 254, 168, 59, 241, 32, 140],
|
||||||
|
"value": 252,
|
||||||
|
"salt": [
|
||||||
|
10,
|
||||||
|
136,
|
||||||
|
55,
|
||||||
|
248,
|
||||||
|
203,
|
||||||
|
115,
|
||||||
|
181,
|
||||||
|
120,
|
||||||
|
254,
|
||||||
|
162,
|
||||||
|
89,
|
||||||
|
219,
|
||||||
|
109,
|
||||||
|
241,
|
||||||
|
31,
|
||||||
|
169,
|
||||||
|
203,
|
||||||
|
202,
|
||||||
|
197,
|
||||||
|
34,
|
||||||
|
2,
|
||||||
|
240,
|
||||||
|
234,
|
||||||
|
36,
|
||||||
|
28,
|
||||||
|
103,
|
||||||
|
3,
|
||||||
|
184,
|
||||||
|
190,
|
||||||
|
156,
|
||||||
|
151,
|
||||||
|
252
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
119
obligations.json
Normal file
119
obligations.json
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"from": [155, 161, 188, 216, 142, 153, 214, 225, 224, 50, 82, 167, 10, 99, 254, 168, 59, 241, 32, 140],
|
||||||
|
"to": [111, 248, 64, 238, 239, 254, 192, 195, 95, 82, 187, 96, 49, 169, 174, 52, 82, 74, 5, 182],
|
||||||
|
"value": 103,
|
||||||
|
"salt": [
|
||||||
|
134,
|
||||||
|
104,
|
||||||
|
222,
|
||||||
|
91,
|
||||||
|
13,
|
||||||
|
97,
|
||||||
|
183,
|
||||||
|
43,
|
||||||
|
190,
|
||||||
|
29,
|
||||||
|
199,
|
||||||
|
203,
|
||||||
|
206,
|
||||||
|
17,
|
||||||
|
241,
|
||||||
|
117,
|
||||||
|
145,
|
||||||
|
238,
|
||||||
|
154,
|
||||||
|
201,
|
||||||
|
79,
|
||||||
|
48,
|
||||||
|
188,
|
||||||
|
175,
|
||||||
|
205,
|
||||||
|
156,
|
||||||
|
218,
|
||||||
|
223,
|
||||||
|
93,
|
||||||
|
208,
|
||||||
|
253,
|
||||||
|
13
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": [111, 248, 64, 238, 239, 254, 192, 195, 95, 82, 187, 96, 49, 169, 174, 52, 82, 74, 5, 182],
|
||||||
|
"to": [66, 206, 221, 229, 17, 152, 209, 119, 53, 144, 49, 30, 42, 52, 13, 192, 107, 36, 203, 55],
|
||||||
|
"value": 197,
|
||||||
|
"salt": [
|
||||||
|
47,
|
||||||
|
45,
|
||||||
|
177,
|
||||||
|
118,
|
||||||
|
3,
|
||||||
|
36,
|
||||||
|
136,
|
||||||
|
70,
|
||||||
|
238,
|
||||||
|
148,
|
||||||
|
143,
|
||||||
|
56,
|
||||||
|
140,
|
||||||
|
115,
|
||||||
|
20,
|
||||||
|
16,
|
||||||
|
235,
|
||||||
|
102,
|
||||||
|
188,
|
||||||
|
236,
|
||||||
|
119,
|
||||||
|
192,
|
||||||
|
25,
|
||||||
|
103,
|
||||||
|
197,
|
||||||
|
72,
|
||||||
|
237,
|
||||||
|
170,
|
||||||
|
40,
|
||||||
|
203,
|
||||||
|
125,
|
||||||
|
227
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": [66, 206, 221, 229, 17, 152, 209, 119, 53, 144, 49, 30, 42, 52, 13, 192, 107, 36, 203, 55],
|
||||||
|
"to": [155, 161, 188, 216, 142, 153, 214, 225, 224, 50, 82, 167, 10, 99, 254, 168, 59, 241, 32, 140],
|
||||||
|
"value": 252,
|
||||||
|
"salt": [
|
||||||
|
10,
|
||||||
|
136,
|
||||||
|
55,
|
||||||
|
248,
|
||||||
|
203,
|
||||||
|
115,
|
||||||
|
181,
|
||||||
|
120,
|
||||||
|
254,
|
||||||
|
162,
|
||||||
|
89,
|
||||||
|
219,
|
||||||
|
109,
|
||||||
|
241,
|
||||||
|
31,
|
||||||
|
169,
|
||||||
|
203,
|
||||||
|
202,
|
||||||
|
197,
|
||||||
|
34,
|
||||||
|
2,
|
||||||
|
240,
|
||||||
|
234,
|
||||||
|
36,
|
||||||
|
28,
|
||||||
|
103,
|
||||||
|
3,
|
||||||
|
184,
|
||||||
|
190,
|
||||||
|
156,
|
||||||
|
151,
|
||||||
|
252
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
1089
program/Cargo.lock
generated
Normal file
1089
program/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
22
program/Cargo.toml
Normal file
22
program/Cargo.toml
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
[workspace]
|
||||||
|
[package]
|
||||||
|
version = "0.1.0"
|
||||||
|
name = "mtcs-sp1-program"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
sp1-zkvm = { git = "https://github.com/succinctlabs/sp1.git" }
|
||||||
|
mtcs-core = {path = "../core"}
|
||||||
|
rs_merkle = "1.4.2"
|
||||||
|
bincode = "1.3.3"
|
||||||
|
ed25519-consensus = "2.1"
|
||||||
|
rand = "0.8.5"
|
||||||
|
|
||||||
|
[patch.crates-io]
|
||||||
|
sha2-v0-9-8 = { git = "https://github.com/sp1-patches/RustCrypto-hashes", package = "sha2", branch = "patch-v0.9.8" }
|
||||||
|
sha2-v0-10-6 = { git = "https://github.com/sp1-patches/RustCrypto-hashes", package = "sha2", branch = "patch-v0.10.6" }
|
||||||
|
sha2-v0-10-8 = { git = "https://github.com/sp1-patches/RustCrypto-hashes", package = "sha2", branch = "patch-v0.10.8" }
|
||||||
|
curve25519-dalek = { git = "https://github.com/sp1-patches/curve25519-dalek", branch = "patch-v4.1.1" }
|
||||||
|
curve25519-dalek-ng = { git = "https://github.com/sp1-patches/curve25519-dalek-ng", branch = "patch-v4.1.1" }
|
||||||
|
ed25519-consensus = { git = "https://github.com/sp1-patches/ed25519-consensus", branch = "patch-v2.1.0" }
|
||||||
|
tiny-keccak = { git = "https://github.com/sp1-patches/tiny-keccak", branch = "patch-v2.0.2" }
|
70
program/src/main.rs
Normal file
70
program/src/main.rs
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
use bincode::serialize;
|
||||||
|
use ed25519_consensus::*;
|
||||||
|
use mtcs_core::*;
|
||||||
|
use rs_merkle::{algorithms::Sha256, Hasher, MerkleProof};
|
||||||
|
sp1_zkvm::entrypoint!(main);
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
println!("reading inputs into guest...");
|
||||||
|
|
||||||
|
let cycle: Cycle = sp1_zkvm::io::read::<Cycle>();
|
||||||
|
let key: SigningKey = sp1_zkvm::io::read::<SigningKey>();
|
||||||
|
let proof: Proof = sp1_zkvm::io::read::<Proof>();
|
||||||
|
let merkle_data: MerkleData = sp1_zkvm::io::read::<MerkleData>();
|
||||||
|
assert_eq!(
|
||||||
|
cycle.size,
|
||||||
|
cycle.obligations.len(),
|
||||||
|
"cycle size does not match number of obligations"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
cycle.size > 2,
|
||||||
|
"invalid cycle, length is {}, should be atleast 3",
|
||||||
|
cycle.size
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut leaves: Vec<[u8; 32]> = vec![];
|
||||||
|
println!("running validity checks...");
|
||||||
|
|
||||||
|
let from = &cycle.obligations.first().unwrap().from;
|
||||||
|
|
||||||
|
let to = &cycle.obligations.iter().fold(from, |acc, x| {
|
||||||
|
if &x.from == acc && &x.value >= &cycle.setoff {
|
||||||
|
leaves.push(Sha256::hash(&serialize(&x).unwrap()));
|
||||||
|
&x.to
|
||||||
|
} else {
|
||||||
|
panic!("cycle invalid")
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_eq!(&from, to);
|
||||||
|
let indexes = merkle_data.indexes;
|
||||||
|
let proof: MerkleProof<Sha256> = MerkleProof::<Sha256>::try_from(proof.bytes).unwrap();
|
||||||
|
assert!(proof.verify(
|
||||||
|
merkle_data.merkle_root,
|
||||||
|
&indexes,
|
||||||
|
leaves.get(..).ok_or("couldn't fetch leaves").unwrap(),
|
||||||
|
merkle_data.len
|
||||||
|
));
|
||||||
|
println!("creating commitments for public data...");
|
||||||
|
|
||||||
|
let message = {
|
||||||
|
let hashed_cycle = Sha256::hash(&serialize(&cycle).unwrap());
|
||||||
|
// Generate a signing key and sign the message
|
||||||
|
|
||||||
|
let sig = key.sign(&bincode::serialize(&hashed_cycle).unwrap()[..]);
|
||||||
|
|
||||||
|
let vk_bytes: [u8; 32] = VerificationKey::from(&key).into();
|
||||||
|
|
||||||
|
(hashed_cycle, vk_bytes, sig)
|
||||||
|
};
|
||||||
|
|
||||||
|
sp1_zkvm::io::commit(&message);
|
||||||
|
println!("cryptography magic happening...")
|
||||||
|
}
|
||||||
|
// TODO: for every edge involved in clearing, the total offsets of all cycles
|
||||||
|
// passing through that edge should be less than the value of that edge
|
||||||
|
|
||||||
|
// TODO:need to make sure that the same cycle doesn't appear
|
||||||
|
// twice in the same clearing epoch
|
4791
script/Cargo.lock
generated
Normal file
4791
script/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
18
script/Cargo.toml
Normal file
18
script/Cargo.toml
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
[workspace]
|
||||||
|
[package]
|
||||||
|
version = "0.1.0"
|
||||||
|
name = "mtcs-sp1-script"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
sp1-sdk = { git = "https://github.com/succinctlabs/sp1.git" }
|
||||||
|
mtcs-core = {path = "../core"}
|
||||||
|
rs_merkle = "1.4.2"
|
||||||
|
bincode = "1.3.3"
|
||||||
|
hex = "0.4.3"
|
||||||
|
serde_json = "1.0"
|
||||||
|
ed25519-consensus = "2.1.0"
|
||||||
|
rand = "0.8.5"
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
sp1-helper = { git = "https://github.com/succinctlabs/sp1.git" }
|
5
script/build.rs
Normal file
5
script/build.rs
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
use sp1_helper::build_program;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
build_program("../program")
|
||||||
|
}
|
3
script/rust-toolchain
Normal file
3
script/rust-toolchain
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[toolchain]
|
||||||
|
channel = "nightly-x86_64-unknown-linux-gnu"
|
||||||
|
components = ["llvm-tools", "rustc-dev"]
|
95
script/src/main.rs
Normal file
95
script/src/main.rs
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
use bincode::serialize;
|
||||||
|
use ed25519_consensus::*;
|
||||||
|
use mtcs_core::*;
|
||||||
|
use rand::thread_rng;
|
||||||
|
use rs_merkle::{algorithms::Sha256 as MerkleSha256, Hasher, MerkleTree};
|
||||||
|
use std::fs;
|
||||||
|
use std::time::SystemTime;
|
||||||
|
|
||||||
|
use sp1_sdk::{utils, ProverClient, SP1Stdin};
|
||||||
|
|
||||||
|
const ELF: &[u8] = include_bytes!("../../program/elf/riscv32im-succinct-zkvm-elf");
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
utils::setup_logger();
|
||||||
|
let start_time = SystemTime::now();
|
||||||
|
|
||||||
|
println!("generating guest inputs...");
|
||||||
|
// For example:
|
||||||
|
let cycle_data: String = fs::read_to_string("../cycle.json").unwrap();
|
||||||
|
|
||||||
|
let all_obligation_data: String = fs::read_to_string("../obligations.json").unwrap();
|
||||||
|
|
||||||
|
let cycle: Cycle =
|
||||||
|
serde_json::from_str(&cycle_data.to_owned()).expect("JSON not well formatted");
|
||||||
|
|
||||||
|
let all_obligations: ObligationList =
|
||||||
|
serde_json::from_str(&all_obligation_data.to_owned()).expect("JSON not well formatted");
|
||||||
|
|
||||||
|
let mut indexes: Vec<usize> = Vec::new();
|
||||||
|
cycle.obligations.iter().for_each(|&i| {
|
||||||
|
let index = all_obligations.iter().position(|&x| x == i).unwrap();
|
||||||
|
indexes.push(index)
|
||||||
|
});
|
||||||
|
|
||||||
|
let leaves: Vec<[u8; 32]> = all_obligations
|
||||||
|
.iter()
|
||||||
|
.map(|x| MerkleSha256::hash(&serialize(&x).unwrap()[..]))
|
||||||
|
.collect();
|
||||||
|
let len = leaves.len();
|
||||||
|
|
||||||
|
let merkle_tree = MerkleTree::<MerkleSha256>::from_leaves(&leaves);
|
||||||
|
|
||||||
|
let merkle_root = merkle_tree.root().ok_or("could not find root").unwrap();
|
||||||
|
|
||||||
|
let merkle_proof = merkle_tree.proof(&indexes);
|
||||||
|
|
||||||
|
let bytes = merkle_proof.to_bytes();
|
||||||
|
|
||||||
|
let proof: Proof = Proof {
|
||||||
|
bytes: bytes.as_slice().try_into().unwrap(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let aux: MerkleData = MerkleData {
|
||||||
|
merkle_root,
|
||||||
|
indexes: indexes.try_into().unwrap(),
|
||||||
|
len,
|
||||||
|
};
|
||||||
|
let key = SigningKey::new(thread_rng());
|
||||||
|
let mut stdin = SP1Stdin::new();
|
||||||
|
let client = ProverClient::new();
|
||||||
|
|
||||||
|
println!("writing inputs to guest...");
|
||||||
|
stdin.write(&cycle);
|
||||||
|
stdin.write(&key);
|
||||||
|
stdin.write(&proof);
|
||||||
|
stdin.write(&aux);
|
||||||
|
|
||||||
|
let mut proof = client.prove(ELF, stdin).expect("proving failed");
|
||||||
|
|
||||||
|
println!("proof generation completed!");
|
||||||
|
|
||||||
|
println!("verifying receipt...");
|
||||||
|
client.verify(ELF, &proof).expect("verification failed");
|
||||||
|
println!("verification completed!");
|
||||||
|
|
||||||
|
let end_time = SystemTime::now();
|
||||||
|
let difference = end_time
|
||||||
|
.duration_since(start_time)
|
||||||
|
.expect("Clock may have gone backwards");
|
||||||
|
println!("Total prover time: {difference:?}");
|
||||||
|
|
||||||
|
println!("validating digital signature...");
|
||||||
|
|
||||||
|
let (hash, verification_key, sign): &([u8; 32], VerificationKey, Signature) =
|
||||||
|
&proof.public_values.read();
|
||||||
|
|
||||||
|
let sig_verify = verification_key.verify(sign, hash).is_ok();
|
||||||
|
assert!(sig_verify);
|
||||||
|
|
||||||
|
proof
|
||||||
|
.save("proof-with-io.json")
|
||||||
|
.expect("saving proof failed");
|
||||||
|
|
||||||
|
println!("successfully generated and verified proof for cycle validity!")
|
||||||
|
}
|
Loading…
Reference in a new issue