Skip to content

Conversation

@rubo
Copy link
Contributor

@rubo rubo commented Dec 26, 2025

Note

These changes are preliminary. The idea is to start a discussion on how to apply/re-implement the required changes correctly.

Changes

  • Brought the work done on the stateless execution from the mmenshikov/feature/stateless_execv2 branch
  • Added another version of Nethermind.Numerics.Int256 package for zkVM without randomization source like in Hash256. It'd be good to find a better solution.
  • Introduced conditional compilation to activate the abovementioned changes when needed (partially done)
  • Added workflows to test the build and execution of zkVM-specific code

Types of changes

What types of changes does your code introduce?

  • Bugfix (a non-breaking change that fixes an issue)
  • New feature (a non-breaking change that adds functionality)
  • Breaking change (a change that causes existing functionality not to work as expected)
  • Optimization
  • Refactoring
  • Documentation update
  • Build-related changes
  • Other: Description

Testing

Requires testing

  • Yes
  • No

If yes, did you write tests?

  • Yes
  • No

@rubo rubo changed the title Implement ZKVM compatibility Implement zkVM compatibility Dec 26, 2025
Comment on lines +342 to +397
static int Main(string[] args)
{
Witness witness = new Witness()
{
Codes = ToByteArrays(codes),
Headers = ToByteArrays(headers),
Keys = ToByteArrays(keys),
State = ToByteArrays(state)
};

BlockHeader suggestedBlockHeader = new BlockHeader(
suggestedBlockForRpc.ParentHash,
suggestedBlockForRpc.Sha3Uncles,
suggestedBlockForRpc.Miner,
suggestedBlockForRpc.Difficulty,
suggestedBlockForRpc.Number!.Value,
suggestedBlockForRpc.GasLimit,
(ulong)suggestedBlockForRpc.Timestamp,
suggestedBlockForRpc.ExtraData,
suggestedBlockForRpc.BlobGasUsed,
suggestedBlockForRpc.ExcessBlobGas,
suggestedBlockForRpc.ParentBeaconBlockRoot,
suggestedBlockForRpc.RequestsHash)
{
StateRoot = suggestedBlockForRpc.StateRoot,
TxRoot = suggestedBlockForRpc.TransactionsRoot,
ReceiptsRoot = suggestedBlockForRpc.ReceiptsRoot,
Bloom = suggestedBlockForRpc.LogsBloom,
GasUsed = suggestedBlockForRpc.GasUsed,
MixHash = suggestedBlockForRpc.MixHash,
BaseFeePerGas = suggestedBlockForRpc.BaseFeePerGas!.Value,
WithdrawalsRoot = suggestedBlockForRpc.WithdrawalsRoot,
ParentBeaconBlockRoot = suggestedBlockForRpc.ParentBeaconBlockRoot,
RequestsHash = suggestedBlockForRpc.RequestsHash,
BlobGasUsed = suggestedBlockForRpc.BlobGasUsed,
ExcessBlobGas = suggestedBlockForRpc.ExcessBlobGas,
Hash = suggestedBlockForRpc.Hash,
};

// suggestedBlockHeader.Hash = suggestedBlockHeader.CalculateHash();

BlockHeader? baseBlock = null;
foreach (var header in witness.DecodedHeaders)
{
if (header.Hash == suggestedBlockHeader.ParentHash)
{
baseBlock = header;
}
}

if (baseBlock is null)
{
// Invalid witness headers
return 4;
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a hardcoded block? Looks weird.
Can we make it proper?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link

@maximmenshikov maximmenshikov Dec 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@LukaszRozmej I believe for ease of testing it was hardcoded. We can eventually make blocks passed through zk input arguments.
(NOT through args - current args will break NativeAOT actually).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it should be passed through arguments.
What is the difference - arguments vs args that you mean?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There must be zkVM-specific mechanism to pass inputs/outputs. args[] can't be used because there is no actualy storage for it anywhere. Having args[] in the code will break the NativeAOT bootstrap in runtime.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, we had the version that took in arguments for witness and block through arguments, but we need something different for zkVM (as @maximmenshikov pointed out)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think what we can do here is seperate this part in two tools?

  1. StatelessExecution
  • this takes input through CLI and decodes it
  • then call the stateless execution module with these input
  1. zkVM execution
  • the input is hardcodesd( can be changed when we have proper logic to provide input to zkVm)
  • then call the same stateless module as before

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, the 2. Will probably be different per zkVM, we already have a hook how to do it for ZISK

#if ZKVM
98316501; // TODO: remove ssl
#else
(uint)System.Security.Cryptography.RandomNumberGenerator.GetInt32(int.MinValue, int.MaxValue);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could be that it is solved by minipal fix, but need to double check

@LukaszRozmej
Copy link
Member

LukaszRozmej commented Dec 29, 2025

pushed a commit, things to still be done:

  • Change Int256 package and unify it
  • Check SHA2 and potentially remove it -- replaced
  • Proper I/O read and write - this needs to be ZISK only -- needs clarification
  • Why we need to change PathUtils? -- removed
  • Pipeline to build and verify
  • Optional: Randomness, but we can do without it

@rubo rubo requested review from Copilot and removed request for tanishqjasoria January 13, 2026 22:18
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Comment on lines +46 to +48
public void RegisterDecoder(ITxDecoder decoder) => RegisterDecoder(decoder.Type, decoder);

public void RegisterDecoder(TxType type, ITxDecoder decoder) => _decoders[(int)type] = decoder;
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The RegisterDecoder method now has two overloads. The original method that takes only an ITxDecoder now delegates to the new method that takes both TxType and ITxDecoder. While this maintains backward compatibility, the implementation extracts the type from the decoder and then passes it back. Consider whether this indirection is necessary or if callers should be updated to use the explicit type parameter.

Copilot uses AI. Check for mistakes.
Comment on lines +20 to +22
private static readonly uint s_instanceRandom =
#if ZKVM
2098026241U;
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fixed value 2098026241U used for zkVM appears to be arbitrary. This should be documented with a comment explaining why this specific value was chosen, or consider using a named constant with a descriptive name.

Suggested change
private static readonly uint s_instanceRandom =
#if ZKVM
2098026241U;
#if ZKVM
// Fixed, deterministic seed used in zkVM builds where randomness must be reproducible and/or secure RNG
// may be restricted. The specific value is arbitrary but must remain constant across zkVM runs.
private const uint ZkvmInstanceRandomSeed = 2098026241U;
#endif
private static readonly uint s_instanceRandom =
#if ZKVM
ZkvmInstanceRandomSeed;

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants