Skip to content

Status of the riscv32im-risc0-zkvm-elf target #135376

@Noratrieb

Description

@Noratrieb
Member

We currently have a target called riscv32im-risc0-zkvm-elf, which targets the RISC Zero Zero Knowledge VM. This target is maintained by @SchmErik, @jbruestle, @flaub #134721 has revealed some issues in this target.

The biggest issue is that the target sets target_os = "zkvm". A "Zero Knowledge VM" is a generic concept and not an operating system. The correct target_os would be risc0.

But there is another question, whether this target should exist in the first place. The alternative to this target would be using the existing riscv32im-unknown-none-elf target with a RISC0-provided crate for the system calls.

The thing that is currently gained from having this target is that it can have std, where the very few syscalls that exist are used to implement some standard library interfaces.
Concretely, the following functionality is provided:

  • program arguments
  • environment variables (read-only)
  • stdio
  • the system global allocator
  • and of course HashMap
  • (no_threads) std::sync

other features like std::fs, std::io, std::process, std::thread, std::time, std::net are not supported.

@SchmErik, who is a maintainer of the target, highlights how the std support is useful in #134721 (comment):

Having std support is important to us because it allows developers to use crates outside of no_std. This has enabled many others to use our target much more easily with existing crates

Additionally, they mentioned how having the target allows them to add cfgs to forked ecosystem crates to make them use more of RISC Zero's APIs (though this could also be implemented without a target and a normal custom cfg).

It is always unsatisfactory to have targets with such incomplete standard libraries (at least it's not as bad as wasm32-unknown-unknown in this case). On the other hand, (just like the wasm target) the APIs that are implemented are likely useful.

This issue is about figuring out what to do with this target, whether to keep it (renamed) or remove it alltogether.

Activity

added
I-compiler-nominatedNominated for discussion during a compiler team meeting.
T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
on Jan 11, 2025
added
needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.
on Jan 11, 2025
added
O-risc0Operating system: RISC0 zkVM https://risczero.com/
and removed
needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.
on Jan 11, 2025
workingjubilee

workingjubilee commented on Jan 11, 2025

@workingjubilee
Member

As far as target APIs we would consider as a minimum basis, notably, in the recent discussion on a prospective VexOS target, having at least a rudimentary form of std::time was considered important.

@SchmErik In general, people use Rust because "if it compiles, it works". However, we have already encountered this problem with wasm32-unknown-unknown: by having an almost-entirely-stubbed-out stdlib implementation, we create a situation where if it compiles, it DOESN'T work.

And it seems to me many people will discover their code doesn't work at significant expense! That is, because this is a target designed primarily for computation on expensive-to-operate distributed systems, even the cheapest executions can be significantly more costly than simply running the compiler and executing a built program on my local machine. Time, if nothing else.

The model for the wasm32-unknown-unknown target is a quagmire that is due to a unique situation for wasm32 and does not seem to apply in your case. It exists because there was an unwillingness to commit to e.g. having both a wasm32-wasi and a wasm32-web target... and also, wasm32-wasi didn't even exist yet. A lot was in-flux and still being designed at the time.

Regarding the target_os matter: I think you have somewhat misunderstood how to use the compiler's configuration features if you think a target_os or even target_vendor is required, honestly.

Urgau

Urgau commented on Jan 11, 2025

@Urgau
Member

We (T-compiler) should probably always involve T-libs when a target can only have "incomplete standard libraries" before accepting/merging a new target (with/without std).

As @workingjubilee already mentioned, T-libs was in the loop regarding the recent VexOS target, and even-through that target is only missing std::process, std::thread and std::net it was deemed insufficient for Tier >= 2 (the target was allowed for Tier 3).

We discussed this in the libs meeting today. While this is indeed missing a lot of what would normally be present in a std target, it does at least have the basics down like support for Instant (which is one of the biggest issues with wasm32-unknown-unknown). We're happy for this to be accepted at tier 3 but would likely reject it for higher tiers.

Based on that I would be in favour of removing std support and fixing target_os, which if I understand correctly would be equivalent to riscv32im-unknown-none-elf, therefore rendering the target irrelevant (and so should just be removed?).

Noratrieb

Noratrieb commented on Jan 11, 2025

@Noratrieb
MemberAuthor

Removing std would imply removing the target alltogether, as std is the only point of the target.

Noratrieb

Noratrieb commented on Jan 14, 2025

@Noratrieb
MemberAuthor

I'm also nominating for libs discussion about whether libs wants to have a target with std like this.

Amanieu

Amanieu commented on Jan 15, 2025

@Amanieu
Member

From the target tier policy document:

Tier 3:

std for targets with an operating system or equivalent layer of system-provided functionality), but may leave some code unimplemented (either unavailable or stubbed out as appropriate), whether because the target makes it impossible to implement or challenging to implement.

Tier 2:

Tier 2 targets must not leave any significant portions of core or the standard library unimplemented or stubbed out, unless they cannot possibly be supported on the target.

The libs team is happy to have as a tier 3 target but would block it from any higher tier.

removed
I-libs-nominatedNominated for discussion during a libs team meeting.
on Jan 15, 2025
apiraino

apiraino commented on Jan 16, 2025

@apiraino
Contributor

Discussed in T-compiler triage.

So, we're fine with a stubbed std implementation. The question is rather about the target_os, changing that would break the target (comment).

One solution could be to giving them large time (say, 6 months) to fix the target_os and then swtich the compile target (comment).

@rustbot label -I-compiler-nominated

4 remaining items

workingjubilee

workingjubilee commented on Jan 18, 2025

@workingjubilee
Member

Is there anything more you can say about this? What would you recommend is a better approach?

Well, you have rzup, and cargo risczero, and all that, and it seems like you require custom environment variables, and all in all it seems like all this lets you just... interpose and inject whatever configuration stuff you want? like --cfg risc0, as Nora said.

Like... that, plus the dependence on forks, means you basically have a parallel ecosystem going already? The target tuple being in rustc seems useful if you want to stop having a parallel ecosystem. Which does seem slightly preferable from our perspective, to be clear.

qethu

qethu commented on Jan 22, 2025

@qethu

I feel that it may be a good option if we can standardize the zkvm OS.
So that we can share the same syscall list between riscv32im-risc0-zkvm-elf and mips-zkm-zkvm-elf.

Currently these are the syscall list in zkvm/abi.rs

    pub fn sys_halt();
    pub fn sys_output(output_id: u32, output_value: u32);
    pub fn sys_sha_compress(
    pub fn sys_sha_buffer(
    pub fn sys_rand(recv_buf: *mut u32, words: usize);
    pub fn sys_panic(msg_ptr: *const u8, len: usize) -> !;
    pub fn sys_log(msg_ptr: *const u8, len: usize);
    pub fn sys_cycle_count() -> usize;
    pub fn sys_read(fd: u32, recv_buf: *mut u8, nrequested: usize) -> usize;
    pub fn sys_write(fd: u32, write_buf: *const u8, nbytes: usize);
    pub fn sys_getenv(
    pub fn sys_argc() -> usize;
    pub fn sys_argv(out_words: *mut u32, out_nwords: usize, arg_index: usize) -> usize;
    pub fn sys_alloc_words(nwords: usize) -> *mut u32;
    pub fn sys_alloc_aligned(nwords: usize, align: usize) -> *mut u8;

In our zkm prover https://github.com/zkMIPS/zkm
The fellow syscalls have been implemented

sys_rand
sys_panic
sys_getenv
sys_alloc_words
sys_write
sys_alloc_aligned

We are working on implementing more syscalls and make it sync with the function signatures.

Noratrieb

Noratrieb commented on Jan 22, 2025

@Noratrieb
MemberAuthor

No, the entire point is to move away from "zkvm" as the target_os to having the actual platform name, because there's clearly no standard.

jeswr

jeswr commented on Feb 13, 2025

@jeswr
Noratrieb

Noratrieb commented on Feb 14, 2025

@Noratrieb
Author
workingjubilee

workingjubilee commented on Feb 16, 2025

@workingjubilee
Member

@qethu You agreeing to do the same is useless to us if a third arrives. A standard needs to exist outside its Rust implementation.

Noratrieb

Noratrieb commented on Feb 16, 2025

@Noratrieb
MemberAuthor

@SchmErik, @jbruestle, @flaub do you have any updates here? While we don't want to set a needless deadline, we would like to see this happen in the near future, or at least like to know your expected timeline of this.

SchmErik

SchmErik commented on Feb 25, 2025

@SchmErik
Contributor

@SchmErik, @jbruestle, @flaub do you have any updates here? While we don't want to set a needless deadline, we would like to see this happen in the near future, or at least like to know your expected timeline of this.

Hi, apologies for the late response. This slipped through the cracks. I'll chat about this internally and try to get an answer to you by the end of the week

flaub

flaub commented on Feb 25, 2025

@flaub
Contributor

Would it be OK to keep as is for the time being?

Noratrieb

Noratrieb commented on Feb 25, 2025

@Noratrieb
MemberAuthor

We'd really like to see getting this fixed, and don't want to keep this long term. That said, if you don't have time right now we can work with that, but this really should be done.

nhtyy

nhtyy commented on Mar 4, 2025

@nhtyy

Too add a few points to this conversation as I intend to attempt to upstream a new tier-3 riscv32im target also for a zkVM.

  1. std library support is very important to us.
  2. Standardizing ABI (even for just risc32 zkvms) seems impossible under a single target-os given the nature of the "os", and many teams are already working on 64-bit targets, which would I think would definitely require a different ABI.
  3. We'd be happy with a "custom os name", like <vendor>-zkvm or really whatever you all are supportive of, including adding custom cfg, although I am not sure how the latter would work when building std.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    O-risc0Operating system: RISC0 zkVM https://risczero.com/T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @flaub@Amanieu@Urgau@apiraino@SchmErik

        Issue actions

          Status of the riscv32im-risc0-zkvm-elf target · Issue #135376 · rust-lang/rust