Skip to content

Commit

Permalink
feat(halo2_proofs): add SnarkVerifierPoseidonWriter rust binding
Browse files Browse the repository at this point in the history
  • Loading branch information
chokobole committed Jul 18, 2024
1 parent 0a99794 commit ba32078
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 0 deletions.
2 changes: 2 additions & 0 deletions halo2_proofs/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ fn main() {
"src/bn254_rational_evals.cc",
"src/bn254_rational_evals_view.cc",
"src/bn254_sha256_writer.cc",
"src/bn254_snark_verifier_poseidon_writer.cc",
"src/cha_cha20_rng.cc",
"src/xor_shift_rng.cc",
];
Expand All @@ -31,6 +32,7 @@ fn main() {
"include/bn254_rational_evals.h",
"include/bn254_rational_evals_view.h",
"include/bn254_sha256_writer.h",
"include/bn254_snark_verifier_poseidon_writer.h",
"include/cha_cha20_rng.h",
"include/xor_shift_rng.h",
"src/bn254.rs",
Expand Down
38 changes: 38 additions & 0 deletions halo2_proofs/include/bn254_snark_verifier_poseidon_writer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#ifndef HALO2_PROOFS_INCLUDE_BN254_SNARK_VERIFIER_POSEIDON_WRITER_H_
#define HALO2_PROOFS_INCLUDE_BN254_SNARK_VERIFIER_POSEIDON_WRITER_H_

#include <stdint.h>

#include <memory>

#include <tachyon/c/zk/plonk/halo2/bn254_transcript.h>

#include "rust/cxx.h"

namespace tachyon::halo2_api::bn254 {

struct Fr;

class SnarkVerifierPoseidonWriter {
public:
SnarkVerifierPoseidonWriter();
SnarkVerifierPoseidonWriter(const SnarkVerifierPoseidonWriter& other) =
delete;
SnarkVerifierPoseidonWriter& operator=(
const SnarkVerifierPoseidonWriter& other) = delete;
~SnarkVerifierPoseidonWriter();

void update(rust::Slice<const uint8_t> data);
rust::Box<Fr> squeeze();
rust::Vec<uint8_t> state() const;

private:
tachyon_halo2_bn254_transcript_writer* writer_;
};

std::unique_ptr<SnarkVerifierPoseidonWriter>
new_snark_verifier_poseidon_writer();

} // namespace tachyon::halo2_api::bn254

#endif // HALO2_PROOFS_INCLUDE_BN254_SNARK_VERIFIER_POSEIDON_WRITER_H_
112 changes: 112 additions & 0 deletions halo2_proofs/src/bn254.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,17 @@ pub mod ffi {
fn state(&self) -> Vec<u8>;
}

unsafe extern "C++" {
include!("halo2_proofs/include/bn254_snark_verifier_poseidon_writer.h");

type SnarkVerifierPoseidonWriter;

fn new_snark_verifier_poseidon_writer() -> UniquePtr<SnarkVerifierPoseidonWriter>;
fn update(self: Pin<&mut SnarkVerifierPoseidonWriter>, data: &[u8]);
fn squeeze(self: Pin<&mut SnarkVerifierPoseidonWriter>) -> Box<Fr>;
fn state(&self) -> Vec<u8>;
}

unsafe extern "C++" {
include!("halo2_proofs/include/bn254_proving_key.h");

Expand Down Expand Up @@ -626,6 +637,107 @@ impl<W: Write, C: CurveAffine, E: EncodedChallenge<C>> Sha256Write<W, C, E> {
}
}

pub struct SnarkVerifierPoseidonWrite<W: Write, C: CurveAffine, E: EncodedChallenge<C>> {
state: cxx::UniquePtr<ffi::SnarkVerifierPoseidonWriter>,
writer: W,
_marker: PhantomData<(W, C, E)>,
}

impl<W: Write, C: CurveAffine> Transcript<C, Challenge255<C>>
for SnarkVerifierPoseidonWrite<W, C, Challenge255<C>>
where
C::Scalar: FromUniformBytes<64>,
{
fn squeeze_challenge(&mut self) -> Challenge255<C> {
let scalar = *unsafe {
std::mem::transmute::<_, Box<halo2curves::bn256::Fr>>(self.state.pin_mut().squeeze())
};
let mut scalar_bytes = scalar.to_repr().as_ref().to_vec();
scalar_bytes.resize(64, 0u8);
Challenge255::<C>::new(&scalar_bytes.try_into().unwrap())
}

fn common_point(&mut self, point: C) -> io::Result<()> {
let coords: Coordinates<C> = Option::from(point.coordinates()).ok_or_else(|| {
io::Error::new(
io::ErrorKind::Other,
"cannot write points at infinity to the transcript",
)
})?;
let x = coords.x();
let y = coords.y();
let slice = &[base_to_scalar::<C>(x), base_to_scalar::<C>(y)];
let bytes = std::mem::size_of::<C::Scalar>() * 2;
unsafe {
self.state.pin_mut().update(std::slice::from_raw_parts(
slice.as_ptr() as *const u8,
bytes,
));
}

Ok(())
}

fn common_scalar(&mut self, scalar: C::Scalar) -> io::Result<()> {
let slice = &[scalar];
let bytes = std::mem::size_of::<C::Scalar>();
unsafe {
self.state.pin_mut().update(std::slice::from_raw_parts(
slice.as_ptr() as *const u8,
bytes,
));
}

Ok(())
}
}

impl<W: Write, C: CurveAffine> TranscriptWrite<C, Challenge255<C>>
for SnarkVerifierPoseidonWrite<W, C, Challenge255<C>>
where
C::Scalar: FromUniformBytes<64>,
{
fn write_point(&mut self, point: C) -> io::Result<()> {
self.common_point(point)?;
let compressed = point.to_bytes();
self.writer.write_all(compressed.as_ref())
}

fn write_scalar(&mut self, scalar: C::Scalar) -> io::Result<()> {
self.common_scalar(scalar)?;
let data = scalar.to_repr();
self.writer.write_all(data.as_ref())
}
}

impl<W: Write, C: CurveAffine, E: EncodedChallenge<C>> SnarkVerifierPoseidonWrite<W, C, E> {
/// Initialize a transcript given an output buffer.
pub fn init(writer: W) -> Self {
SnarkVerifierPoseidonWrite {
state: ffi::new_snark_verifier_poseidon_writer(),
writer,
_marker: PhantomData,
}
}

/// Conclude the interaction and return the output buffer (writer).
pub fn finalize(self) -> W {
// TODO: handle outstanding scalars?
// See https://github.com/zcash/halo2/issues/138.
self.writer
}
}

impl<W: Write, C: CurveAffine> TranscriptWriteState<C, Challenge255<C>>
for SnarkVerifierPoseidonWrite<W, C, Challenge255<C>>
where
C::Scalar: FromUniformBytes<64>,
{
fn state(&self) -> Vec<u8> {
self.state.state()
}
}

#[derive(Debug)]
pub struct ProvingKey<C: CurveAffine> {
inner: cxx::UniquePtr<ffi::ProvingKey>,
Expand Down
44 changes: 44 additions & 0 deletions halo2_proofs/src/bn254_snark_verifier_poseidon_writer.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#include "halo2_proofs/include/bn254_snark_verifier_poseidon_writer.h"

namespace tachyon::halo2_api::bn254 {

SnarkVerifierPoseidonWriter::SnarkVerifierPoseidonWriter()
: writer_(tachyon_halo2_bn254_transcript_writer_create(
TACHYON_HALO2_SNARK_VERIFIER_POSEIDON_TRANSCRIPT)) {}

SnarkVerifierPoseidonWriter::~SnarkVerifierPoseidonWriter() {
tachyon_halo2_bn254_transcript_writer_destroy(writer_);
}

void SnarkVerifierPoseidonWriter::update(rust::Slice<const uint8_t> data) {
tachyon_halo2_bn254_transcript_writer_update(writer_, data.data(),
data.size());
}

rust::Box<Fr> SnarkVerifierPoseidonWriter::squeeze() {
tachyon_bn254_fr* ret = new tachyon_bn254_fr;
*ret = tachyon_halo2_bn254_transcript_writer_squeeze(writer_);
return rust::Box<Fr>::from_raw(reinterpret_cast<Fr*>(ret));
}

rust::Vec<uint8_t> SnarkVerifierPoseidonWriter::state() const {
size_t state_size;
tachyon_halo2_bn254_transcript_writer_get_state(writer_, nullptr,
&state_size);
rust::Vec<uint8_t> ret;
// NOTE(chokobole): |rust::Vec<uint8_t>| doesn't have |resize()|.
ret.reserve(state_size);
for (size_t i = 0; i < state_size; ++i) {
ret.push_back(0);
}
tachyon_halo2_bn254_transcript_writer_get_state(writer_, ret.data(),
&state_size);
return ret;
}

std::unique_ptr<SnarkVerifierPoseidonWriter>
new_snark_verifier_poseidon_writer() {
return std::make_unique<SnarkVerifierPoseidonWriter>();
}

} // namespace tachyon::halo2_api::bn254
1 change: 1 addition & 0 deletions halo2_proofs/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub enum TranscriptType {
Blake2b,
Poseidon,
Sha256,
SnarkVerifierPoseidon,
}

#[derive(Debug)]
Expand Down

0 comments on commit ba32078

Please sign in to comment.