Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plonky2 proofs verification #4393

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
175 changes: 145 additions & 30 deletions Cargo.lock

Large diffs are not rendered by default.

10 changes: 9 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ members = [
"examples/waiter",
"examples/waiting-proxy",
"examples/wat",
"examples/plonky2-verifier",
"galloc",
"gbuiltins/*",
"gcli",
Expand All @@ -91,6 +92,7 @@ members = [
"gmeta",
"gmeta/codegen",
"gprimitives",
"gprimitives/client",
"gsdk",
"gsdk/codegen",
"gsdk/api-gen",
Expand Down Expand Up @@ -136,7 +138,7 @@ dirs = "4.0.0"
dyn-clonable = "0.9.0"
enum-iterator = "1.5.0"
env_logger = "0.10"
environmental = "1.1.3"
environmental = { version = "1.1.4", default-features = false }
futures = { version = "0.3", default-features = false }
futures-timer = "3.0.3"
futures-util = "0.3.30"
Expand All @@ -148,11 +150,14 @@ impl-serde = "0.4.0"
jsonrpsee = { version = "^0.24" }
libc = { version = "0.2", default-features = false }
log = { version = "0.4.22", default-features = false }
num = { version = "0.4", default-features = false }
num_enum = { version = "0.6.1", default-features = false }
parity-scale-codec = { version = "3.6.4", default-features = false }
parity-wasm = "0.45.0"
parking_lot = "0.12.3"
path-clean = "1.0.1"
plonky2 = { git = "https://github.com/gear-tech/plonky2.git", branch = "fix-getrandom", default-features = false }
plonky2_field = { git = "https://github.com/gear-tech/plonky2.git", branch = "fix-getrandom", default-features = false }
primitive-types = { version = "0.12.2", default-features = false }
proc-macro2 = { version = "1", default-features = false }
proptest = "1.5.0"
Expand All @@ -176,6 +181,7 @@ syn = "2.0.71"
thiserror = "1.0.62"
tokio = { version = "1.38.0" }
uluru = "3.1.0"
unroll = { version = "0.1.5", default-features = false }
url = "2.5.2"
# wasmer 4.3.4 for some reason have wat's version "=1.0.71" nailed down, so we have to do the same
wat = "1.0.71"
Expand Down Expand Up @@ -234,6 +240,7 @@ gtest = { path = "gtest" }
gmeta = { path = "gmeta" }
gmeta-codegen = { path = "gmeta/codegen" }
gprimitives = { path = "gprimitives", default-features = false }
gprimitives-client = { path = "gprimitives/client", default-features = false }
gear-authorship = { path = "node/authorship" }
gear-core-backend = { path = "core-backend", default-features = false }
gear-call-gen = { path = "utils/call-gen" }
Expand Down Expand Up @@ -504,6 +511,7 @@ demo-wait-wake = { path = "examples/wait_wake" }
demo-waiting-proxy = { path = "examples/waiting-proxy" }
demo-stack-allocations = { path = "examples/stack-allocations" }
demo-wat = { path = "examples/wat" }
demo-plonky2-verifier = { path = "examples/plonky2-verifier" }

# Dependencies that only used in one package
#
Expand Down
1 change: 1 addition & 0 deletions core-backend/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ where
builder.add_func(ReservationReplyCommit, wrap_syscall!(reservation_reply_commit));
builder.add_func(ReservationSend, wrap_syscall!(reservation_send));
builder.add_func(ReservationSendCommit, wrap_syscall!(reservation_send_commit));
builder.add_func(Permute, wrap_syscall!(permute));
builder.add_func(SystemBreak, wrap_syscall!(system_break));

builder.add_func(Alloc, wrap_syscall!(alloc));
Expand Down
17 changes: 16 additions & 1 deletion core-backend/src/funcs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ use gear_wasm_instrument::SystemBreakCode;
use gsys::{
BlockNumberWithHash, ErrorBytes, ErrorWithGas, ErrorWithHandle, ErrorWithHash,
ErrorWithReplyCode, ErrorWithSignalCode, ErrorWithTwoHashes, Gas, Hash, HashWithValue,
TwoHashesWithValue,
PoseidonInOut, TwoHashesWithValue,
};

/// BLAKE2b-256 hasher state.
Expand Down Expand Up @@ -1425,4 +1425,19 @@ where
Err(HostError)
})
}

pub fn permute(input_ptr: u32, output_ptr: u32) -> impl Syscall<Caller> {
InfallibleSyscall::new(CostToken::Permute, move |ctx: &mut CallerWrap<Caller>| {
let mut registry = MemoryAccessRegistry::default();
let input_reader = registry.register_read_decoded(input_ptr);
let output_writer = registry.register_write_as(output_ptr);
let mut io = registry.pre_process(ctx)?;

let input_data: PoseidonInOut = io.read_decoded(ctx, input_reader)?;
let hash_out = ctx.ext_mut().permute(&input_data)?;

io.write_as(ctx, output_writer, hash_out)
.map_err(Into::into)
})
}
}
4 changes: 4 additions & 0 deletions core-backend/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,10 @@ impl Externalities for MockExt {
Ok(MessageId::default())
}

fn permute(&self, _input: &[u64]) -> Result<[u64; 12], Self::UnrecoverableError> {
Ok([0u64; 12])
}

fn signal_from(&self) -> Result<MessageId, Self::UnrecoverableError> {
Ok(MessageId::default())
}
Expand Down
6 changes: 5 additions & 1 deletion core-processor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ gear-core-errors = { workspace = true, features = ["codec"] }
gear-core-backend.workspace = true
gear-wasm-instrument.workspace = true
gear-lazy-pages-common.workspace = true
gear-runtime-interface.workspace = true
gsys.workspace = true

scale-info = { workspace = true, features = ["derive"] }
Expand All @@ -32,7 +33,10 @@ enum-iterator.workspace = true

[features]
default = ["std"]
std = ["gear-core-backend/std"]
std = [
"gear-core-backend/std",
"gear-runtime-interface/std",
]
strict = []
mock = []
gtest = []
7 changes: 7 additions & 0 deletions core-processor/src/ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ use gear_core_errors::{
ReplyCode, ReservationError, SignalCode,
};
use gear_lazy_pages_common::{GlobalsAccessConfig, LazyPagesInterface, ProcessAccessError, Status};
use gear_runtime_interface::poseidon_hash::poseidon;
use gear_wasm_instrument::syscalls::SyscallName;

/// Processor context.
Expand Down Expand Up @@ -1411,6 +1412,12 @@ impl<LP: LazyPagesInterface> Externalities for Ext<LP> {
})
}

fn permute(&self, input: &[u64]) -> Result<[u64; 12], Self::UnrecoverableError> {
Ok(poseidon(input.to_vec())
.try_into()
.expect("poseidon always returns 12 elements"))
}

fn random(&self) -> Result<(&[u8], u32), Self::UnrecoverableError> {
Ok((&self.context.random_data.0, self.context.random_data.1))
}
Expand Down
6 changes: 6 additions & 0 deletions core/src/costs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,9 @@ pub struct SyscallCosts {

/// Cost per salt byte by `gr_create_program_wgas`.
pub gr_create_program_wgas_salt_per_byte: CostOf<BytesAmount>,

/// Cost of calling `gr_permute`.
pub gr_permute: CostOf<CallsAmount>,
}

/// Enumerates syscalls that can be charged by gas meter.
Expand Down Expand Up @@ -420,6 +423,8 @@ pub enum CostToken {
CreateProgram(BytesAmount, BytesAmount),
/// Cost of calling `gr_create_program_wgas`, taking in account payload and salt size.
CreateProgramWGas(BytesAmount, BytesAmount),
/// Cost of calling `gr_permute`
Permute,
}

impl SyscallCosts {
Expand Down Expand Up @@ -498,6 +503,7 @@ impl SyscallCosts {
.cost_for_with_bytes(self.gr_create_program_wgas_payload_per_byte, payload),
)
.cost_for_with_bytes(self.gr_create_program_wgas_salt_per_byte, salt),
Permute => self.gr_permute.cost_for_one(),
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions core/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -391,4 +391,7 @@ pub trait Externalities {

/// Return the set of functions that are forbidden to be called.
fn forbidden_funcs(&self) -> &BTreeSet<SyscallName>;

/// Do data permutation and return a slice of the same shape.
fn permute(&self, input: &[u64]) -> Result<[u64; 12], Self::UnrecoverableError>;
}
7 changes: 7 additions & 0 deletions core/src/gas_metering/schedule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,8 @@ pub struct SyscallWeights {
pub gr_create_program_wgas_payload_per_byte: Weight,
#[doc = " Weight per salt byte by `create_program_wgas`."]
pub gr_create_program_wgas_salt_per_byte: Weight,
#[doc = " Weight of calling `gr_permute`."]
pub gr_permute: Weight,
}

impl Default for SyscallWeights {
Expand Down Expand Up @@ -810,6 +812,10 @@ impl Default for SyscallWeights {
ref_time: 1591,
proof_size: 0,
},
gr_permute: Weight {
ref_time: 4901557,
proof_size: 0,
},
}
}
}
Expand Down Expand Up @@ -1189,6 +1195,7 @@ impl From<SyscallWeights> for SyscallCosts {
.gr_create_program_wgas_salt_per_byte
.ref_time()
.into(),
gr_permute: val.gr_permute.ref_time().into(),
}
}
}
Expand Down
24 changes: 24 additions & 0 deletions examples/plonky2-verifier/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[package]
name = "demo-plonky2-verifier"
version = "0.1.0"
authors.workspace = true
edition.workspace = true
license.workspace = true
homepage.workspace = true
repository.workspace = true

[dependencies]
gcore = { workspace = true, features = ["codec"] }
gstd.workspace = true
num = { workspace = true, features = ["alloc"] }
plonky2.workspace = true
plonky2_field.workspace = true
serde = { workspace = true, features = ["derive", "alloc"] }

[build-dependencies]
gear-wasm-builder.workspace = true

[features]
debug = ["gstd/debug"]
std = []
default = ["std"]
29 changes: 29 additions & 0 deletions examples/plonky2-verifier/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// This file is part of Gear.

// Copyright (C) 2024 Gear Technologies Inc.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use gear_wasm_builder::WasmBuilder;

fn main() {
// We are forcing recommended nightly toolchain due to the need to compile this
// program with `oom-handler` feature. The WASM binary of this program is then
// used by the `oom_handler_works` pallet test.
WasmBuilder::new()
.exclude_features(vec!["std"])
.with_forced_recommended_toolchain() // NOTE: Don't use this in production programs!
.build();
}
32 changes: 32 additions & 0 deletions examples/plonky2-verifier/src/circuit.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// This file is part of Gear.

// Copyright (C) 2024 Gear Technologies Inc.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

//! Circuit config for a custom `Goldilocks` field implementation from `gstd`.

use super::goldilocks_field::GoldilocksFieldWrapper;
use plonky2::{hash::poseidon::PoseidonHash, plonk::config::GenericConfig};
use plonky2_field::extension::quadratic::QuadraticExtension;

#[derive(Debug, Copy, Clone, Default, Eq, PartialEq)]
pub struct CustomPoseidonGoldilocksConfig;
impl GenericConfig<2> for CustomPoseidonGoldilocksConfig {
type F = GoldilocksFieldWrapper;
type FE = QuadraticExtension<Self::F>;
type Hasher = PoseidonHash;
type InnerHasher = PoseidonHash;
}
Loading
Loading