-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathmain.rs
98 lines (82 loc) · 3.03 KB
/
main.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use clap::Parser;
use fibonacci_verifier_contract::SP1Groth16Proof;
use solana_program_test::{processor, ProgramTest};
use solana_sdk::{
instruction::{AccountMeta, Instruction},
pubkey::Pubkey,
signer::Signer,
transaction::Transaction,
};
use sp1_sdk::{include_elf, utils, ProverClient, SP1ProofWithPublicValues, SP1Stdin};
#[derive(clap::Parser)]
#[command(name = "zkVM Proof Generator")]
struct Cli {
#[arg(
long,
value_name = "prove",
default_value = "false",
help = "Specifies whether to generate a proof for the program."
)]
prove: bool,
}
/// The ELF binary of the SP1 program.
const ELF: &[u8] = include_elf!("fibonacci-program");
/// Invokes the solana program using Solana Program Test.
async fn run_verify_instruction(groth16_proof: SP1Groth16Proof) {
let program_id = Pubkey::new_unique();
// Create program test environment
let (banks_client, payer, recent_blockhash) = ProgramTest::new(
"fibonacci-verifier-contract",
program_id,
processor!(fibonacci_verifier_contract::process_instruction),
)
.start()
.await;
let instruction = Instruction::new_with_borsh(
program_id,
&groth16_proof,
vec![AccountMeta::new(payer.pubkey(), false)],
);
// Create and send transaction
let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey()));
transaction.sign(&[&payer], recent_blockhash);
banks_client.process_transaction(transaction).await.unwrap();
}
#[tokio::main]
async fn main() {
// Setup logging for the application.
utils::setup_logger();
// Where to save / load the sp1 proof from.
let proof_file = "../../proofs/fibonacci_proof.bin";
// Parse command line arguments.
let args = Cli::parse();
// Only generate a proof if the prove flag is set.
if args.prove {
// Initialize the prover client
let client = ProverClient::new();
let (pk, vk) = client.setup(ELF);
println!(
"Program Verification Key Bytes {:?}",
sp1_sdk::HashableKey::bytes32(&vk)
);
// In our SP1 program, compute the 20th fibonacci number.
let mut stdin = SP1Stdin::new();
stdin.write(&20u32);
// Generate a proof for the fibonacci program.
let proof = client
.prove(&pk, stdin)
.groth16()
.run()
.expect("Groth16 proof generation failed");
// Save the generated proof to `proof_file`.
proof.save(&proof_file).unwrap();
}
// Load the proof from the file, and convert it to a Borsh-serializable `SP1Groth16Proof`.
let sp1_proof_with_public_values = SP1ProofWithPublicValues::load(&proof_file).unwrap();
let groth16_proof = SP1Groth16Proof {
proof: sp1_proof_with_public_values.bytes(),
sp1_public_inputs: sp1_proof_with_public_values.public_values.to_vec(),
};
// Send the proof to the contract, and verify it on `solana-program-test`.
run_verify_instruction(groth16_proof).await;
}