Skip to content

Add AppContext switch to allow hash seed to be deterministic#79

Merged
rubo merged 13 commits intomainfrom
feature/zkvm
Jan 7, 2026
Merged

Add AppContext switch to allow hash seed to be deterministic#79
rubo merged 13 commits intomainfrom
feature/zkvm

Conversation

@rubo
Copy link
Collaborator

@rubo rubo commented Dec 29, 2025

Added AppContext switch to control hash seed randomization for zkVM-compatibility.

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.

Pull request overview

This PR makes the hash seed mutable to enable zkVM compatibility by allowing external control over the hash seed used in GetHashCode(). The change removes the automatic random initialization and replaces it with a mutable static field that can be set via a new public API.

  • Replaces readonly random hash seed initialization with a mutable static field
  • Adds a public SetHashSeed method to allow external configuration
  • Updates hash code computation to use the mutable seed

return true;
}

public static void SetHashSeed(uint seed) => _hashSeed = seed;
Copy link

Copilot AI Dec 29, 2025

Choose a reason for hiding this comment

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

Changing the hash seed after UInt256 instances have been added to hash-based collections (Dictionary, HashSet, etc.) will break those collections, as the hash codes will change. The API design should either document this critical constraint clearly, or consider making the seed settable only once (e.g., check if it's already been set and throw an exception). Additionally, there's no validation of the seed parameter, and allowing a seed value of 0 may reduce hash distribution quality compared to the previous random initialization.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@LukaszRozmej I thought about this. Better to make init-once.

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.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

Copy link
Member

@benaadams benaadams left a comment

Choose a reason for hiding this comment

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

Since UInt256 are essentially user supplied keys to internal dictionaries mean a bad actor could offline generate a hash flood DoS attack once which would knock every node offline

A random seed means they can't generate it offline (but need to do it against a specific node) and if they find a DoS collision it will only effect that node and not any others

@rubo
Copy link
Collaborator Author

rubo commented Dec 29, 2025

Since UInt256 are essentially user supplied keys to internal dictionaries mean a bad actor could offline generate a hash flood DoS attack once which would knock every node offline

A random seed means they can't generate it offline (but need to do it against a specific node) and if they find a DoS collision it will only effect that node and not any others

I'm not sure what you're getting at.

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.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 2 comments.

@benaadams benaadams changed the title Make hash seed mutable Add AppContext switch to allow hash seed to be deterministic Dec 31, 2025
Copy link
Member

@benaadams benaadams left a comment

Choose a reason for hiding this comment

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

Wait shouldn't this be inverted?

private static readonly uint s_instanceRandom = (uint)System.Security.Cryptography.RandomNumberGenerator.GetInt32(int.MinValue, int.MaxValue);
// Constant by default for zkVM-compatibility.
private static readonly uint _hashSeed =
AppContext.TryGetSwitch("Nethermind.Int256.UseRandomSeed", out var useRandomSeed) && useRandomSeed
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't this be inverted so is random by default and can be switched off; rather than off by default?

private static readonly uint s_instanceRandom = (uint)System.Security.Cryptography.RandomNumberGenerator.GetInt32(int.MinValue, int.MaxValue);
// Constant by default for zkVM-compatibility.
private static readonly uint _hashSeed =
AppContext.TryGetSwitch("Nethermind.Int256.UseRandomSeed", out var useRandomSeed) && useRandomSeed
Copy link
Member

Choose a reason for hiding this comment

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

You probably want it behind a static property with FeatureSwitchDefinitionAttribute on it so it can be resolved at compile time: https://medium.com/@malarsharmila/feature-switches-in-net-9-73b1cb96c13f

@rubo rubo marked this pull request as draft December 31, 2025 17:16
@rubo rubo marked this pull request as ready for review January 6, 2026 12:49
@rubo rubo marked this pull request as draft January 6, 2026 12:58
@rubo
Copy link
Collaborator Author

rubo commented Jan 6, 2026

Unfortunately, AppContext switch doesn't work with our bflat approach, hitting the devirtualization issue. This said, it won't be possible to keep things intact for regular .NET and have a switch for the zkVM. Thus, the approach is the opposite -- having the default for zkVM and a switch to set for regulat .NET runtime. This will hopefully change if we solve the devirtualization issue.

@rubo rubo marked this pull request as ready for review January 6, 2026 13:56
Copy link
Member

@LukaszRozmej LukaszRozmej left a comment

Choose a reason for hiding this comment

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

Does it work in our zkVM compiler?

@rubo
Copy link
Collaborator Author

rubo commented Jan 7, 2026

Does it work in our zkVM compiler?

Sure it does. Otherwise this PR wouldn't make sense.

@rubo rubo merged commit 897ba8f into main Jan 7, 2026
22 checks passed
@rubo rubo deleted the feature/zkvm branch January 7, 2026 12:49
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.

3 participants