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

bn254_syscalls #828

Merged
merged 29 commits into from
Feb 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
7229a4b
add secp256k1 emulation logic
mcalancea Jan 10, 2025
21ce13f
add test for add
mcalancea Jan 13, 2025
68440a1
debug addressing
mcalancea Jan 13, 2025
0ca4ce7
get example working
mcalancea Jan 13, 2025
cabd104
integrate corresponding LargeEcallDummy instances in DummyExtraConfig
mcalancea Jan 14, 2025
ab183c1
cosmetic
mcalancea Jan 14, 2025
d94672f
add utils
mcalancea Jan 15, 2025
66dbda8
fix some comments
mcalancea Jan 15, 2025
62a2e9d
add point doubling
mcalancea Jan 16, 2025
0e168a9
decompress wip
mcalancea Jan 16, 2025
6787072
add checks on effects
mcalancea Jan 22, 2025
07bdd9d
refactor utils
mcalancea Jan 22, 2025
3df34fe
clippy
mcalancea Jan 23, 2025
9ab492d
clippy
mcalancea Jan 23, 2025
8ce6b6e
add sha_extend
mcalancea Jan 23, 2025
912a0e8
address comments
mcalancea Jan 31, 2025
c3d63eb
Merge branch 'mihai/sha-extend-syscall' into mihai/secp256k1-add-doub…
mcalancea Jan 31, 2025
59f4cc1
work on sha256-extend
mcalancea Jan 31, 2025
5cb1e9b
refactor specs
mcalancea Jan 31, 2025
cf31cf0
view with mem_ops
mcalancea Jan 31, 2025
cd9bed7
lints
mcalancea Feb 4, 2025
b216981
Merge branch 'master' into mihai/secp256k1-add-double-syscalls
mcalancea Feb 4, 2025
defde58
work in progress
mcalancea Feb 5, 2025
4719f94
support non-contiguous mem-ops
mcalancea Feb 7, 2025
f00f723
refactor
mcalancea Feb 7, 2025
931a058
Merge branch 'master' into mihai/bn254-syscalls
mcalancea Feb 7, 2025
fe89bdf
refactor
mcalancea Feb 7, 2025
a2f3d4e
refactor & clean-up
mcalancea Feb 9, 2025
c8e3e00
Merge branch 'master' into mihai/bn254-syscalls
mcalancea Feb 26, 2025
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
24 changes: 24 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ cfg-if = "1.0"
criterion = { version = "0.5", features = ["html_reports"] }
crossbeam-channel = "0.5"
itertools = "0.13"
num-bigint = { version = "0.4.6" }
num-derive = "0.4"
num-traits = "0.2"
p3-challenger = { git = "https://github.com/scroll-tech/plonky3", rev = "8d2be81" }
Expand All @@ -57,12 +58,14 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
strum = "0.26"
strum_macros = "0.26"
substrate-bn = { version = "0.6.0" }
tiny-keccak = { version = "2.0.2", features = ["keccak"] }
tracing = { version = "0.1", features = [
"attributes",
] }
tracing-forest = { version = "0.1.6" }
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
uint = "0.8"

[profile.dev]
lto = "thin"
Expand Down
2 changes: 2 additions & 0 deletions ceno_emul/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ anyhow.workspace = true
ceno_rt = { path = "../ceno_rt" }
elf = "0.7"
itertools.workspace = true
num-bigint.workspace = true
num-derive.workspace = true
num-traits.workspace = true
rrs_lib = { package = "rrs-succinct", version = "0.1.0" }
secp.workspace = true
strum.workspace = true
strum_macros.workspace = true
substrate-bn.workspace = true
tiny-keccak.workspace = true
tracing.workspace = true

Expand Down
17 changes: 16 additions & 1 deletion ceno_emul/src/host_utils.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use std::iter::from_fn;

use crate::{ByteAddr, EmuContext, VMState, WordAddr};
use itertools::Itertools;

use crate::{ByteAddr, EmuContext, VMState, Word, WordAddr};

const WORD_SIZE: usize = 4;
const INFO_OUT_ADDR: WordAddr = ByteAddr(0xC000_0000).waddr();
Expand All @@ -17,6 +19,19 @@ pub fn read_all_messages(state: &VMState) -> Vec<Vec<u8>> {
.collect()
}

pub fn read_all_messages_as_words(state: &VMState) -> Vec<Vec<Word>> {
read_all_messages(state)
.iter()
.map(|message| {
assert_eq!(message.len() % WORD_SIZE, 0);
message
.chunks_exact(WORD_SIZE)
.map(|chunk| Word::from_le_bytes(chunk.try_into().unwrap()))
.collect_vec()
})
.collect_vec()
}

fn read_message(state: &VMState, offset: WordAddr) -> Vec<u8> {
let out_addr = INFO_OUT_ADDR + offset;
let byte_len = state.peek_memory(out_addr) as usize;
Expand Down
4 changes: 4 additions & 0 deletions ceno_emul/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ pub mod disassemble;
mod syscalls;
pub use syscalls::{
KECCAK_PERMUTE, SECP256K1_ADD, SECP256K1_DECOMPRESS, SECP256K1_DOUBLE, SHA_EXTEND, SyscallSpec,
bn254::{
BN254_FP_WORDS, BN254_FP2_WORDS, BN254_POINT_WORDS, Bn254AddSpec, Bn254DoubleSpec,
Bn254Fp2AddSpec, Bn254Fp2MulSpec, Bn254FpAddSpec, Bn254FpMulSpec,
},
keccak_permute::{KECCAK_WORDS, KeccakSpec},
secp256k1::{
COORDINATE_WORDS, SECP256K1_ARG_WORDS, Secp256k1AddSpec, Secp256k1DecompressSpec,
Expand Down
16 changes: 9 additions & 7 deletions ceno_emul/src/syscalls.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::{RegIdx, Tracer, VMState, Word, WordAddr, WriteOp};
use anyhow::Result;

pub mod bn254;
pub mod keccak_permute;
pub mod secp256k1;
pub mod sha256;
Expand All @@ -9,6 +10,7 @@ pub mod sha256;
// https://github.com/succinctlabs/sp1/blob/013c24ea2fa15a0e7ed94f7d11a7ada4baa39ab9/crates/core/executor/src/syscalls/code.rs

pub use ceno_rt::syscalls::{
BN254_ADD, BN254_DOUBLE, BN254_FP_ADD, BN254_FP_MUL, BN254_FP2_ADD, BN254_FP2_MUL,
KECCAK_PERMUTE, SECP256K1_ADD, SECP256K1_DECOMPRESS, SECP256K1_DOUBLE, SHA_EXTEND,
};

Expand All @@ -28,12 +30,19 @@ pub fn handle_syscall(vm: &VMState, function_code: u32) -> Result<SyscallEffects
SECP256K1_DOUBLE => Ok(secp256k1::secp256k1_double(vm)),
SECP256K1_DECOMPRESS => Ok(secp256k1::secp256k1_decompress(vm)),
SHA_EXTEND => Ok(sha256::extend(vm)),
BN254_ADD => Ok(bn254::bn254_add(vm)),
BN254_DOUBLE => Ok(bn254::bn254_double(vm)),
BN254_FP_ADD => Ok(bn254::bn254_fp_add(vm)),
BN254_FP_MUL => Ok(bn254::bn254_fp_mul(vm)),
BN254_FP2_ADD => Ok(bn254::bn254_fp2_add(vm)),
BN254_FP2_MUL => Ok(bn254::bn254_fp2_mul(vm)),
// TODO: introduce error types.
_ => Err(anyhow::anyhow!("Unknown syscall: {}", function_code)),
}
}

/// A syscall event, available to the circuit witness generators.
/// TODO: separate mem_ops into two stages: reads-and-writes
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct SyscallWitness {
pub mem_ops: Vec<WriteOp>,
Expand All @@ -43,13 +52,6 @@ pub struct SyscallWitness {

impl SyscallWitness {
fn new(mem_ops: Vec<WriteOp>, reg_ops: Vec<WriteOp>) -> SyscallWitness {
for (i, op) in mem_ops.iter().enumerate() {
assert_eq!(
op.addr,
mem_ops[0].addr + i,
"Dummy circuit expects that mem_ops addresses are consecutive."
);
}
SyscallWitness {
mem_ops,
reg_ops,
Expand Down
109 changes: 109 additions & 0 deletions ceno_emul/src/syscalls/bn254/bn254_curve.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
use crate::{
Change, EmuContext, Platform, SyscallSpec, VMState, Word, WriteOp,
syscalls::{SyscallEffects, SyscallWitness, bn254::types::Bn254Point},
utils::MemoryView,
};

use super::types::BN254_POINT_WORDS;
use itertools::Itertools;

pub struct Bn254AddSpec;
impl SyscallSpec for Bn254AddSpec {
const NAME: &'static str = "BN254_ADD";

const REG_OPS_COUNT: usize = 2;
const MEM_OPS_COUNT: usize = 2 * BN254_POINT_WORDS;
const CODE: u32 = ceno_rt::syscalls::BN254_ADD;
}

pub struct Bn254DoubleSpec;
impl SyscallSpec for Bn254DoubleSpec {
const NAME: &'static str = "BN254_DOUBLE";

const REG_OPS_COUNT: usize = 2;
const MEM_OPS_COUNT: usize = BN254_POINT_WORDS;
const CODE: u32 = ceno_rt::syscalls::BN254_DOUBLE;
}

pub fn bn254_add(vm: &VMState) -> SyscallEffects {
let p_ptr = vm.peek_register(Platform::reg_arg0());
let q_ptr = vm.peek_register(Platform::reg_arg1());

// Read the argument pointers
let reg_ops = vec![
WriteOp::new_register_op(
Platform::reg_arg0(),
Change::new(p_ptr, p_ptr),
0, // Cycle set later in finalize().
),
WriteOp::new_register_op(
Platform::reg_arg1(),
Change::new(q_ptr, q_ptr),
0, // Cycle set later in finalize().
),
];

// Memory segments of P and Q
let [mut p_view, q_view] =
[p_ptr, q_ptr].map(|start| MemoryView::<BN254_POINT_WORDS>::new(vm, start));

// Read P and Q from words via wrapper type
let [p, q] = [&p_view, &q_view].map(|view| Bn254Point::from(view.words()));

// TODO: what does sp1 do with invalid points? equal points?
// Compute the sum and convert back to words
let output_words: [Word; BN254_POINT_WORDS] = (p + q).into();

p_view.write(output_words);

let mem_ops = p_view
.mem_ops()
.into_iter()
.chain(q_view.mem_ops())
.collect_vec();

assert_eq!(mem_ops.len(), 2 * BN254_POINT_WORDS);
SyscallEffects {
witness: SyscallWitness::new(mem_ops, reg_ops),
next_pc: None,
}
}

pub fn bn254_double(vm: &VMState) -> SyscallEffects {
let p_ptr = vm.peek_register(Platform::reg_arg0());

// for compatibility with sp1 spec
assert_eq!(vm.peek_register(Platform::reg_arg1()), 0);

// Read the argument pointers
let reg_ops = vec![
WriteOp::new_register_op(
Platform::reg_arg0(),
Change::new(p_ptr, p_ptr),
0, // Cycle set later in finalize().
),
WriteOp::new_register_op(
Platform::reg_arg1(),
Change::new(0, 0),
0, // Cycle set later in finalize().
),
];

// P's memory segment
let mut p_view = MemoryView::<BN254_POINT_WORDS>::new(vm, p_ptr);
// Create point from words via wrapper type
let p = Bn254Point::from(p_view.words());

let result = p.double();
let output_words: [Word; BN254_POINT_WORDS] = result.into();

p_view.write(output_words);

let mem_ops = p_view.mem_ops().to_vec();

assert_eq!(mem_ops.len(), BN254_POINT_WORDS);
SyscallEffects {
witness: SyscallWitness::new(mem_ops, reg_ops),
next_pc: None,
}
}
Loading