Skip to content

Enable NullAway static null-safety analysis for util module#10046

Merged
siladu merged 55 commits intobesu-eth:mainfrom
Apisapple:main
Apr 17, 2026
Merged

Enable NullAway static null-safety analysis for util module#10046
siladu merged 55 commits intobesu-eth:mainfrom
Apisapple:main

Conversation

@Apisapple
Copy link
Copy Markdown
Contributor

@Apisapple Apisapple commented Mar 14, 2026

PR description

This PR enables NullAway static null-safety analysis for the util module as a pilot and fixes all violations surfaced by the check.

Summary of changes

  • Enable NullAway at ERROR severity for util production compilation via Error Prone.
  • Disable NullAway for util test compilation for this pilot.
  • Add dependency verification metadata entries required by NullAway and related transitive artifacts.
  • Apply null-safety fixes and JSpecify nullable contracts across util classes, including PlatformDetector, BesuVersionUtils, ExceptionUtils, MemoryBoundCache, RollingFileWriter, and StackTraceMatchFilter.
  • NullAway is compiler-only via Error Prone and does not add runtime artifacts to util.

Developer setup

  • In IntelliJ, set Build and run using to Gradle so NullAway diagnostics appear during normal IDE builds.
  • No additional Gradle wiring is required beyond the current Error Prone plus NullAway setup for this pilot.
  • If we expand to other modules later, shared NullAway options can be centralized in a common convention plugin.

Validation

  • spotless: ./gradlew spotlessApply
  • module build with NullAway: ./gradlew :util:build
  • optional broader compile check: ./gradlew build -x test

Fixed Issue(s)

fixes #10004

Thanks for sending a pull request! Have you done the following?

  • Checked out our contribution guidelines?
  • Considered documentation and added the doc-change-required label to this PR if updates are required.
  • Considered the changelog and included an update if required.
  • For database changes (e.g. KeyValueSegmentIdentifier) considered compatibility and performed forwards and backwards compatibility tests

Locally, you can run these tests to catch failures early:

  • spotless: ./gradlew spotlessApply
  • unit tests: ./gradlew build
  • acceptance tests: ./gradlew acceptanceTest
  • integration tests: ./gradlew integrationTest
  • reference tests: ./gradlew ethereum:referenceTests:referenceTests
  • hive tests: Engine or other RPCs modified?

Apisapple and others added 27 commits March 7, 2026 03:15
- Replace javax.annotation.Nullable and javax.annotation.CheckForNull with org.jspecify.annotations.Nullable across 18 Java files
- Update platform constraint to org.jspecify:jspecify:1.0.0
- Replace compileOnly com.google.code.findbugs:jsr305 with compileOnly org.jspecify:jspecify in affected modules

Signed-off-by: Mykim <38449976+Apisapple@users.noreply.github.com>
Migrate JSR305 nullness annotations to JSpecify
Signed-off-by: mykim <kimminyong2034@gmail.com>
- Add NullAway 0.12.4 to util errorprone dependencies
- Annotate nullable fields/returns in 6 util classes with @nullable
- Fix nullable dereferences: RollingFileWriter, StackTraceMatchFilter, PlatformDetector
- Enable NullAway:ERROR for util main compile, OFF for tests
- Add optional CI job (run-nullaway label) for gradual monitoring
- All util compilation passes with NullAway ERROR by default

Fixes:
  - MemoryBoundCache: mark getIfPresent() return as @nullable
  - ExceptionUtils: annotate rootCause() for nullable input/output
  - RollingFileWriter: guard Path.getParent() null dereference
  - PlatformDetector: make static fields @nullable, add fallback to UNKNOWN
  - BesuVersionUtils: mark VERSION/COMMIT fields as @nullable
  - StackTraceMatchFilter: fix nullable message comparison, builder fields
Signed-off-by: mykim <kimminyong2034@gmail.com>
…ilter

Signed-off-by: mykim <kimminyong2034@gmail.com>
… null

Replace null return with UNKNOWN to satisfy NullAway @nonnull contract.

Signed-off-by: mykim <kimminyong2034@gmail.com>
- Return null to account for existing code that expects and handles null values.

Signed-off-by: mykim <kimminyong2034@gmail.com>
- Remove the unnecessary -PenableNullAway flag

Signed-off-by: mykim <kimminyong2034@gmail.com>
- Update the Javadoc to reflect the actual behavior of the getGlibc function.

Signed-off-by: mykim <kimminyong2034@gmail.com>
Signed-off-by: mykim <kimminyong2034@gmail.com>
Signed-off-by: mykim <kimminyong2034@gmail.com>
Signed-off-by: mykim <kimminyong2034@gmail.com>
Copilot AI review requested due to automatic review settings March 14, 2026 19:16
@Apisapple Apisapple marked this pull request as draft March 14, 2026 19:16
Adjust indentation of GRADLEW_UNIT_TEST_ARGS in .github/workflows/pre-review.yml under unitTests.env to align with surrounding keys.

Signed-off-by: mykim <kimminyong2034@gmail.com>
Copy link
Copy Markdown
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 9 out of 9 changed files in this pull request and generated 6 comments.

public void versionStringIsEthstatsFriendly() {
assertThat(BesuVersionUtils.version())
.matches("[^/]+/v(\\d+\\.\\d+\\.\\d+[^/]*|null)/[^/]+/[^/]+");
.matches("[^/]+/v(\\d+\\.\\d+\\.\\d+[^/]*|UNKNOWN)/[^/]+/[^/]+");
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

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

These tests hardcode the sentinel string UNKNOWN. Since BesuVersionUtils.UNKNOWN is now a public constant, consider referencing it (e.g., via string concatenation in the regex) to prevent tests drifting if the sentinel value changes.

Copilot uses AI. Check for mistakes.
public void noIdentityNodeNameIsEthstatsFriendly() {
assertThat(BesuVersionUtils.nodeName(Optional.empty()))
.matches("[^/]+/v(\\d+\\.\\d+\\.\\d+[^/]*|null)/[^/]+/[^/]+");
.matches("[^/]+/v(\\d+\\.\\d+\\.\\d+[^/]*|UNKNOWN)/[^/]+/[^/]+");
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

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

These tests hardcode the sentinel string UNKNOWN. Since BesuVersionUtils.UNKNOWN is now a public constant, consider referencing it (e.g., via string concatenation in the regex) to prevent tests drifting if the sentinel value changes.

Copilot uses AI. Check for mistakes.
public void userIdentityNodeNameIsEthstatsFriendly() {
assertThat(BesuVersionUtils.nodeName(Optional.of("TestUserIdentity")))
.matches("[^/]+/[^/]+/v(\\d+\\.\\d+\\.\\d+[^/]*|null)/[^/]+/[^/]+");
.matches("[^/]+/[^/]+/v(\\d+\\.\\d+\\.\\d+[^/]*|UNKNOWN)/[^/]+/[^/]+");
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

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

These tests hardcode the sentinel string UNKNOWN. Since BesuVersionUtils.UNKNOWN is now a public constant, consider referencing it (e.g., via string concatenation in the regex) to prevent tests drifting if the sentinel value changes.

Copilot uses AI. Check for mistakes.
Comment on lines 28 to 33
* @param throwable the throwable whose root cause we want to find
* @return The root cause
*/
public static Throwable rootCause(final Throwable throwable) {
public static @Nullable Throwable rootCause(final @Nullable Throwable throwable) {
return throwable != null ? Throwables.getRootCause(throwable) : null;
}
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

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

The Javadoc no longer matches the method contract: the parameter and return value are now nullable. Update the @param and @return docs to reflect that null is accepted and that the method may return null when passed null.

Copilot uses AI. Check for mistakes.
Comment on lines +331 to 332
final Pattern pattern = Pattern.compile("[-+]?[\\d]*\\.?[\\d]+");
final Matcher matcher = pattern.matcher(rawGlibcVersion);
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

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

This method compiles a regex Pattern on each call. Since the pattern is constant, make it a private static final Pattern to avoid repeated compilation overhead and simplify the method.

Copilot uses AI. Check for mistakes.
Comment on lines 66 to 71
public static String getOS() {
if (_os == null) {
detect();
}
return _os;
return _os == null ? UNKNOWN : _os;
}
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

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

The lazy initialization of mutable static fields is not thread-safe (no synchronization/volatile). With the new UNKNOWN fallback, a thread can observe _os as null during/after another thread’s detect() and return UNKNOWN even though detection will eventually set a real value. Consider making the cached fields volatile and/or synchronizing detect() + reads (or using an initialization-on-demand holder) to ensure safe publication and consistent results under concurrency.

Copilot uses AI. Check for mistakes.
Replace hardcoded "UNKNOWN" literal in regex assertions with BesuVersionUtils.UNKNOWN constant in three unit tests (versionStringIsEthstatsFriendly, noIdentityNodeNameIsEthstatsFriendly, userIdentityNodeNameIsEthstatsFriendly) in BesuVersionUtilsTest. This keeps the tests consistent with the source constant and avoids duplicating the literal value; no behavioral change.

Signed-off-by: mykim <kimminyong2034@gmail.com>
Remove the local BESU_VERSION_UNKNOWN constant and use BesuVersionUtils.UNKNOWN instead. Simplify getRuntimeVersionString() to return BesuVersionUtils.shortVersion() directly, construct VersionMetadata with BesuVersionUtils.UNKNOWN on FileNotFoundException, and compare metadata versions against BesuVersionUtils.UNKNOWN. Centralizes the unknown-version sentinel in BesuVersionUtils.

Signed-off-by: mykim <kimminyong2034@gmail.com>
Update Javadoc for ExceptionUtils.rootCause to state it returns the root cause or {@code null} when the input throwable is {@code null}. This documents the method's existing behavior, which already returns null for a null input.

Signed-off-by: mykim <kimminyong2034@gmail.com>
Reformat the long regex in userIdentityNodeNameIsEthstatsFriendly test to improve readability by splitting the string across lines. This is a purely formatting change in util/src/test/java/org/hyperledger/besu/util/BesuVersionUtilsTest.java and does not alter test behavior.

Signed-off-by: mykim <kimminyong2034@gmail.com>
@Apisapple Apisapple requested a review from Copilot April 8, 2026 08:01
Copy link
Copy Markdown
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 10 out of 10 changed files in this pull request and generated 7 comments.

Comment thread util/build.gradle Outdated
implementation 'org.bouncycastle:bcpkix-jdk18on'
implementation 'org.xerial.snappy:snappy-java'

compileOnly 'org.jspecify:jspecify'
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

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

org.jspecify.annotations.Nullable is now part of util’s public API surface (annotations appear in public method signatures/fields). Using compileOnly means downstream modules/consumers may not have the annotation type available on their compile classpath, which can break static analysis tooling and (depending on build tooling) compilation when reading annotated signatures. Prefer compileOnlyApi 'org.jspecify:jspecify' (with the java-library plugin) so consumers get the annotation on their compile classpath without adding a runtime dependency.

Suggested change
compileOnly 'org.jspecify:jspecify'
compileOnlyApi 'org.jspecify:jspecify'

Copilot uses AI. Check for mistakes.
Comment on lines +121 to 122
public StackTraceMatchFilter.Builder setStackContains(final @Nullable String text) {
this.stackContains = text;
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

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

The builder setter setStackContains(@Nullable String) allows explicitly passing null, but build() then unconditionally fails via requireNonNull. This makes the API easier to misuse and shifts validation to a later point. Consider making the setter parameter non-null (and annotating it accordingly), or validate immediately in setStackContains (e.g., requireNonNull(text, ...)) so failures are earlier and closer to the source of the misuse.

Suggested change
public StackTraceMatchFilter.Builder setStackContains(final @Nullable String text) {
this.stackContains = text;
public StackTraceMatchFilter.Builder setStackContains(final String text) {
this.stackContains = Objects.requireNonNull(text, "stackContains must be provided");

Copilot uses AI. Check for mistakes.
Comment on lines +139 to +140
final String nonNullStackContains =
Objects.requireNonNull(stackContains, "stackContains must be provided");
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

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

The builder setter setStackContains(@Nullable String) allows explicitly passing null, but build() then unconditionally fails via requireNonNull. This makes the API easier to misuse and shifts validation to a later point. Consider making the setter parameter non-null (and annotating it accordingly), or validate immediately in setStackContains (e.g., requireNonNull(text, ...)) so failures are earlier and closer to the source of the misuse.

Copilot uses AI. Check for mistakes.
Comment on lines +58 to +62
} catch (final IOException e) {
final FileNotFoundException fnfe =
new FileNotFoundException("Unable to create directory for rolling file: " + parentPath);
fnfe.initCause(e);
throw fnfe;
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

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

Wrapping a directory-creation IOException as a FileNotFoundException is a bit misleading (the directory may be unreadable, permission denied, invalid path, etc., not “file not found”). If the constructor/method signature allows, prefer throwing IOException directly (or UncheckedIOException if you can’t). If you must keep FileNotFoundException, consider using a message that clearly indicates this is a directory creation failure and ensure callers can still distinguish it (e.g., via a dedicated exception type or documented cause inspection).

Copilot uses AI. Check for mistakes.
public void versionStringIsEthstatsFriendly() {
assertThat(BesuVersionUtils.version())
.matches("[^/]+/v(\\d+\\.\\d+\\.\\d+[^/]*|null)/[^/]+/[^/]+");
.matches("[^/]+/v(\\d+\\.\\d+\\.\\d+[^/]*|" + BesuVersionUtils.UNKNOWN + ")/[^/]+/[^/]+");
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

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

These tests interpolate BesuVersionUtils.UNKNOWN directly into a regex. Today it’s safe ("UNKNOWN"), but if the sentinel ever changes to contain regex metacharacters, these patterns will become brittle. Wrapping the interpolated token with regex quoting (e.g., Pattern.quote(...)) would make the tests resilient to future sentinel changes.

Copilot uses AI. Check for mistakes.
public void noIdentityNodeNameIsEthstatsFriendly() {
assertThat(BesuVersionUtils.nodeName(Optional.empty()))
.matches("[^/]+/v(\\d+\\.\\d+\\.\\d+[^/]*|null)/[^/]+/[^/]+");
.matches("[^/]+/v(\\d+\\.\\d+\\.\\d+[^/]*|" + BesuVersionUtils.UNKNOWN + ")/[^/]+/[^/]+");
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

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

These tests interpolate BesuVersionUtils.UNKNOWN directly into a regex. Today it’s safe ("UNKNOWN"), but if the sentinel ever changes to contain regex metacharacters, these patterns will become brittle. Wrapping the interpolated token with regex quoting (e.g., Pattern.quote(...)) would make the tests resilient to future sentinel changes.

Copilot uses AI. Check for mistakes.
Comment on lines +62 to +63
.matches(
"[^/]+/[^/]+/v(\\d+\\.\\d+\\.\\d+[^/]*|" + BesuVersionUtils.UNKNOWN + ")/[^/]+/[^/]+");
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

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

These tests interpolate BesuVersionUtils.UNKNOWN directly into a regex. Today it’s safe ("UNKNOWN"), but if the sentinel ever changes to contain regex metacharacters, these patterns will become brittle. Wrapping the interpolated token with regex quoting (e.g., Pattern.quote(...)) would make the tests resilient to future sentinel changes.

Copilot uses AI. Check for mistakes.
Replace compileOnly with compileOnlyApi for org.jspecify:jspecify in util/build.gradle so jspecify annotations are exposed on the compile classpath to consumers of this module. This ensures downstream modules compiling against this artifact can see the jspecify types without packaging the dependency.

Signed-off-by: mykim <kimminyong2034@gmail.com>
Use Pattern.quote(BesuVersionUtils.UNKNOWN) in regex assertions to ensure the UNKNOWN token is matched literally and not treated as a regex. Added import java.util.regex.Pattern and updated three assertions in BesuVersionUtilsTest (versionStringIsEthstatsFriendly, noIdentityNodeNameIsEthstatsFriendly, userIdentityNodeNameIsEthstatsFriendly) to avoid accidental regex interpretation and potential test flakiness.

Signed-off-by: mykim <kimminyong2034@gmail.com>
Apply Spotless formatting

Signed-off-by: mykim <kimminyong2034@gmail.com>
@Apisapple Apisapple requested a review from Copilot April 8, 2026 08:48
Copy link
Copy Markdown
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 10 out of 10 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

util/src/main/java/org/hyperledger/besu/util/BesuVersionUtils.java:87

  • The Javadoc for shortVersion() claims it returns strings like \"v23.1.0\", but (based on the ethstats format/tests using /v as a prefix) shortVersion() is likely intended to return the version without a leading v. Please update the examples/wording to match the actual format (e.g., \"23.1.0\" / \"23.1.1-dev-ac23d311\"), while keeping the UNKNOWN part.
  /**
   * Generate version-only Besu version
   *
   * @return Besu version in format such as "v23.1.0" or "v23.1.1-dev-ac23d311", or {@value
   *     #UNKNOWN} if not available
   */
  public static String shortVersion() {
    return VERSION;
  }


private static String normalizeGLibcVersion(final String rawGlibcVersion) {
final Pattern pattern = Pattern.compile("[-+]?[0-9]*\\.?[0-9]+");
final Pattern pattern = Pattern.compile("[-+]?[\\d]*\\.?[\\d]+");
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

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

The regex change from [0-9] to [\\d] is both redundant (a character class around \\d isn’t needed) and subtly changes matching semantics (Unicode digits vs ASCII digits). If the intent is to parse glibc versions, consider reverting to [0-9] (original behavior) or using \\d without square brackets if Unicode digits are explicitly desired.

Suggested change
final Pattern pattern = Pattern.compile("[-+]?[\\d]*\\.?[\\d]+");
final Pattern pattern = Pattern.compile("[-+]?[0-9]*\\.?[0-9]+");

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Kind of agree with copilot on this but I'm not sure there's any noticeable difference, so it's a nitpick, won't request another review cycle for just this.

@Apisapple Apisapple marked this pull request as ready for review April 8, 2026 11:53
@Apisapple Apisapple requested a review from siladu April 9, 2026 01:02
@Apisapple
Copy link
Copy Markdown
Contributor Author

@siladu I've incorporated all the feedback you provided.
I'd be grateful if you could review the updates when you get a chance.

Copy link
Copy Markdown
Contributor

@siladu siladu left a comment

Choose a reason for hiding this comment

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

Tested happy path version string in:

  • startup logs
  • VERSION_METADATA.json
  • RPCs
  • evmtool
  • docker tag
  • docker startup logs
  • docker with custom version ./gradlew testDocker -Prelease.releaseVersion=26.x.x -Pversion=26.x.x

Have not tested plugins or variations where parts of the version might be null/unknown.

Looking good 🎉 Just a couple of nitpicks left for me so feel free to ignore. Will merge PR tomorrow if no further changes/comments.

Comment thread util/build.gradle
implementation 'org.bouncycastle:bcpkix-jdk18on'
implementation 'org.xerial.snappy:snappy-java'

compileOnlyApi 'org.jspecify:jspecify'
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: think I still prefer compileOnly since I expect every module to eventually add this anyway. Is there a reason I've missed why compileOnlyApi is better?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thank you for the review. I decided to keep compileOnlyApi for now, as it is currently used only in the util module. Adding compileOnly manually to every module could lead to omissions, so I felt this was the safer choice at this stage. Once all modules adopt it consistently, we can switch to a shared compileOnly configuration.

Copy link
Copy Markdown
Contributor Author

@Apisapple Apisapple Apr 16, 2026

Choose a reason for hiding this comment

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

I’ve verified that updating the section you pointed out to compileOnly does not cause any issues during the build.

Copy link
Copy Markdown
Contributor

@siladu siladu Apr 17, 2026

Choose a reason for hiding this comment

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

it is currently used only in the util module

that's not the case, we have it in a few places already after your first PR.
I'm trying to avoid relying on transitive but I do see some advantages to compileOnlyApi.
However, my main concern is a consistent approach and currently it is mixed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks for raising this. I agree that we currently have a mixed approach (api / compileOnly / compileOnlyApi) for org.jspecify:jspecify.

To keep the scope of this PR focused, I suggest addressing JSpecify dependency consistency in a dedicated follow-up PR. In that PR, we can update all modules in one pass based on an agreed rule (for example, avoiding transitive dependencies and requiring explicit declarations, with documented exceptions).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

If the changes needed this time are small, I can update the current compileOnlyApi entries to compileOnly and submit the PR again.

Comment on lines 282 to 285
static String getJavaVersionProperty(final String javaVersionProperty) {
// Get the java version from system properties using the provided key
return System.getProperty(javaVersionProperty);
}
Copy link
Copy Markdown
Contributor

@siladu siladu Apr 15, 2026

Choose a reason for hiding this comment

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

nit: technically this can result null as well so it's either missing a method annotation or a fallback to "unknown".
Not a blocker as ending up with "null" in the version string isn't the end of the world.

@siladu siladu enabled auto-merge (squash) April 17, 2026 09:46
@siladu siladu merged commit eaba57a into besu-eth:main Apr 17, 2026
34 of 64 checks passed
daniellehrner added a commit that referenced this pull request Apr 21, 2026
* enable bal parallelization for all blocks and not only head (#10234)

Signed-off-by: Karim Taam <karim.t2am@gmail.com>

* Add MULMOD to EVMv2 (#10168)

- Add MulModOperationV2, tests and benchmarks
- Rename c -> m in benchmarks following (a * b) % m formula
- Add MulModOperationV2Test covering stack management and underflow

Tests verify correct stack depth reduction (3→1), result placement, zero-modulus special case, cross-limb arithmetic, and that underflow with 0 or 2 items returns INSUFFICIENT_STACK_ITEMS without mutating the stack.

---------

Signed-off-by: Simon Dudley <simon.dudley@consensys.net>

* BlockSimulator fix (#10251)

* BlockSimulator fix

Signed-off-by: Roman <4833306+Filter94@users.noreply.github.com>

Signed-off-by: Roman <4833306+Filter94@users.noreply.github.com>
Co-authored-by: garyschulte <garyschulte@gmail.com>

* Enable NullAway static null-safety analysis for util module (#10046)

* Migrate JSR305 nullness annotations to JSpecify

- Replace javax.annotation.Nullable and javax.annotation.CheckForNull with org.jspecify.annotations.Nullable across 18 Java files
- Update platform constraint to org.jspecify:jspecify:1.0.0
- Replace compileOnly com.google.code.findbugs:jsr305 with compileOnly org.jspecify:jspecify in affected modules

Signed-off-by: Mykim <38449976+Apisapple@users.noreply.github.com>

* feat(util): add opt-in NullAway configuration for Error Prone

Signed-off-by: mykim <kimminyong2034@gmail.com>

* feat(util): enable NullAway with comprehensive nullability fixes

- Add NullAway 0.12.4 to util errorprone dependencies
- Annotate nullable fields/returns in 6 util classes with @nullable
- Fix nullable dereferences: RollingFileWriter, StackTraceMatchFilter, PlatformDetector
- Enable NullAway:ERROR for util main compile, OFF for tests
- Add optional CI job (run-nullaway label) for gradual monitoring
- All util compilation passes with NullAway ERROR by default

Fixes:
  - MemoryBoundCache: mark getIfPresent() return as @nullable
  - ExceptionUtils: annotate rootCause() for nullable input/output
  - RollingFileWriter: guard Path.getParent() null dereference
  - PlatformDetector: make static fields @nullable, add fallback to UNKNOWN
  - BesuVersionUtils: mark VERSION/COMMIT fields as @nullable
  - StackTraceMatchFilter: fix nullable message comparison, builder fields
Signed-off-by: mykim <kimminyong2034@gmail.com>

* style(util): format code for improved readability in StackTraceMatchFilter

Signed-off-by: mykim <kimminyong2034@gmail.com>

* fix(util): PlatformDetector.normalizeGLibcVersion returns UNKNOWN not null

Replace null return with UNKNOWN to satisfy NullAway @nonnull contract.

Signed-off-by: mykim <kimminyong2034@gmail.com>

* fix(util): update getGlibc to return null instead of UNKNOWN

- Return null to account for existing code that expects and handles null values.

Signed-off-by: mykim <kimminyong2034@gmail.com>

* fix(util): remove NullAway flag from util compile command

- Remove the unnecessary -PenableNullAway flag

Signed-off-by: mykim <kimminyong2034@gmail.com>

* docs(util): update getGlibc Javadoc to clarify return value can be null

- Update the Javadoc to reflect the actual behavior of the getGlibc function.

Signed-off-by: mykim <kimminyong2034@gmail.com>

* docs(util): update NullAway optional check job name for clarity

Signed-off-by: mykim <kimminyong2034@gmail.com>

* fix(util): update getGlibc to always return a value instead of null

Signed-off-by: mykim <kimminyong2034@gmail.com>

* fix(util): remove NullAway optional check job from pre-review workflow

Signed-off-by: mykim <kimminyong2034@gmail.com>

* Fix YAML indentation in pre-review workflow

Adjust indentation of GRADLEW_UNIT_TEST_ARGS in .github/workflows/pre-review.yml under unitTests.env to align with surrounding keys.

Signed-off-by: mykim <kimminyong2034@gmail.com>

* feat: Improve version metadata null-safety and bump NullAway to 0.13.1

Signed-off-by: mykim <kimminyong2034@gmail.com>

* chroe: Add jspecify compileOnly dependency

Add org.jspecify:jspecify as a compileOnly dependency to util/build.gradle. This brings JSpecify annotations into the module for static nullness/type-checking without introducing a runtime dependency.

Signed-off-by: mykim <kimminyong2034@gmail.com>

* feat: Use shortVersion() and improve StackTraceMatchFilter

Update acceptance tests to call BesuVersionUtils.shortVersion() directly instead of using orElse("unknown"). In StackTraceMatchFilter, mark the Throwable parameter as @nullable and simplify toString() to return stackContains directly. These changes clarify nullability and streamline version usage/representation.

Signed-off-by: mykim <kimminyong2034@gmail.com>

* docs: Fix Javadoc reference for UNKNOWN constant

Update Javadoc in util/src/main/java/org/hyperledger/besu/util/BesuVersionUtils.java to use {@value #UNKNOWN} instead of {@value UNKNOWN} in shortVersion() and commit() docs so the UNKNOWN field is referenced correctly. No behavioral changes.

Signed-off-by: mykim <kimminyong2034@gmail.com>

* chroe: Remove old verification metadata entries

Delete verification-metadata entries for com.uber.nullaway:nullaway:0.12.4 and org.checkerframework:dataflow-nullaway:3.48.0 (their artifact SHA entries were removed). These versions are superseded in the file by nullaway:0.13.1 and dataflow-nullaway:3.53.0, so the stale metadata was cleaned up.

Signed-off-by: mykim <kimminyong2034@gmail.com>

* Merge pull request #7 from Apisapple/feature/nullaway-util

Feature/nullaway util

Signed-off-by: mykim <kimminyong2034@gmail.com>

* Use UNKNOWN constant in version regex tests

Replace hardcoded "UNKNOWN" literal in regex assertions with BesuVersionUtils.UNKNOWN constant in three unit tests (versionStringIsEthstatsFriendly, noIdentityNodeNameIsEthstatsFriendly, userIdentityNodeNameIsEthstatsFriendly) in BesuVersionUtilsTest. This keeps the tests consistent with the source constant and avoids duplicating the literal value; no behavioral change.

Signed-off-by: mykim <kimminyong2034@gmail.com>

* Use BesuVersionUtils.UNKNOWN constant

Remove the local BESU_VERSION_UNKNOWN constant and use BesuVersionUtils.UNKNOWN instead. Simplify getRuntimeVersionString() to return BesuVersionUtils.shortVersion() directly, construct VersionMetadata with BesuVersionUtils.UNKNOWN on FileNotFoundException, and compare metadata versions against BesuVersionUtils.UNKNOWN. Centralizes the unknown-version sentinel in BesuVersionUtils.

Signed-off-by: mykim <kimminyong2034@gmail.com>

* docs: Clarify rootCause javadoc null behavior

Update Javadoc for ExceptionUtils.rootCause to state it returns the root cause or {@code null} when the input throwable is {@code null}. This documents the method's existing behavior, which already returns null for a null input.

Signed-off-by: mykim <kimminyong2034@gmail.com>

* style: Wrap long regex in BesuVersionUtilsTest

Reformat the long regex in userIdentityNodeNameIsEthstatsFriendly test to improve readability by splitting the string across lines. This is a purely formatting change in util/src/test/java/org/hyperledger/besu/util/BesuVersionUtilsTest.java and does not alter test behavior.

Signed-off-by: mykim <kimminyong2034@gmail.com>

* chore: Use compileOnlyApi for jspecify dependency

Replace compileOnly with compileOnlyApi for org.jspecify:jspecify in util/build.gradle so jspecify annotations are exposed on the compile classpath to consumers of this module. This ensures downstream modules compiling against this artifact can see the jspecify types without packaging the dependency.

Signed-off-by: mykim <kimminyong2034@gmail.com>

* feat: Quote UNKNOWN in version regex tests

Use Pattern.quote(BesuVersionUtils.UNKNOWN) in regex assertions to ensure the UNKNOWN token is matched literally and not treated as a regex. Added import java.util.regex.Pattern and updated three assertions in BesuVersionUtilsTest (versionStringIsEthstatsFriendly, noIdentityNodeNameIsEthstatsFriendly, userIdentityNodeNameIsEthstatsFriendly) to avoid accidental regex interpretation and potential test flakiness.

Signed-off-by: mykim <kimminyong2034@gmail.com>

* style: Apply Spotless formatting

Apply Spotless formatting

Signed-off-by: mykim <kimminyong2034@gmail.com>

---------

Signed-off-by: Mykim <38449976+Apisapple@users.noreply.github.com>
Signed-off-by: mykim <kimminyong2034@gmail.com>
Co-authored-by: Simon Dudley <simon.dudley@consensys.net>

* Layered txpool: enable balance check by default (#10175)

Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
Co-authored-by: Justin Florentine <justin+github@florentine.us>

* remove pre EIP8 handshake support (#10257)

Signed-off-by: stefan.pingel@consensys.net <stefan.pingel@consensys.net>
Co-authored-by: Justin Florentine <justin+github@florentine.us>

* Minor Mulmod v2 refactor (#10253)

* Refactor stack index logic
* Refactor test helper
* Remove redundant stack param
* Inline mulmod method

---------

Signed-off-by: Simon Dudley <simon.dudley@consensys.net>

* Increase disconnect await timeout in flaky P2P rejection tests (#10267)

Under full test suite load, the multi-hop async disconnect path
(local denies inbound → TCP close → remote Netty event loop →
subscriber callback) can exceed 5s due to thread pool contention.
Raise peerFuture/reasonFuture timeouts to 30s in P2PNetworkTest
and P2PPlainNetworkTest to tolerate CI load without masking bugs.

Signed-off-by: Simon Dudley <simon.dudley@consensys.net>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* Include slotNumber in payloadIdentifier generation (#10242)

Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
Co-authored-by: Usman Saleem <usman@usmans.info>

* Update Gradle plugin for Besu plugin development to 0.2.0 (#10263)

Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>

* Change block access list index to uint32 (#10279)

Signed-off-by: Karim Taam <karim.t2am@gmail.com>

* SystemCallProcessor: remove duplicate logging (#10152)

* remove duplicate logging

Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>

---------

Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>

* EVMv2 AddOperationV2 (#10255)

* AddOperationV2

Signed-off-by: Simon Dudley <simon.dudley@consensys.net>

* AddOperationV2Test: structural coverage

Drop redundant arithmetic cases (covered by UInt256PropertyBasedTest) and
focus on structural concerns: stack arity, limb-level read/write wiring,
256-bit wrap, deep-slot preservation, and gas cost.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: Simon Dudley <simon.dudley@consensys.net>

* Optimize for JIT

Signed-off-by: Luis Pinto <luis.pinto@consensys.net>

* Address review comments

Don't mutate top
Don't use fromHexStringLenient

Signed-off-by: Simon Dudley <simon.dudley@consensys.net>

---------

Signed-off-by: Simon Dudley <simon.dudley@consensys.net>
Signed-off-by: Luis Pinto <luis.pinto@consensys.net>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: Luis Pinto <luis.pinto@consensys.net>

* [CHANGELOG] add unreleased section (#10286)

Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>

* Enforce that blob_versioned_hashes match blobs (#10278)

Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>

* Implement BaseFee, blobBaseFee, CallValue, GasPrice, Balance and SelfBalance for EVM v2 (#10229)

* Migrate wei operations to EVM v2 (first commit)

Signed-off-by: Ameziane H. <ameziane.hamlat@consensys.net>

* Update SelfBalance benchmarks

Signed-off-by: Ameziane H. <ameziane.hamlat@consensys.net>

* spotless

Signed-off-by: Ameziane H. <ameziane.hamlat@consensys.net>

* Address comments.

Signed-off-by: Ameziane H. <ameziane.hamlat@consensys.net>

* Add Javadoc

Signed-off-by: Ameziane H. <ameziane.hamlat@consensys.net>

* Add unit tests

Signed-off-by: Ameziane H. <ameziane.hamlat@consensys.net>

* spotless

Signed-off-by: Ameziane H. <ameziane.hamlat@consensys.net>

* Update datatypes/src/main/java/org/hyperledger/besu/datatypes/Wei.java

Co-authored-by: Simon Dudley <simon.dudley@consensys.net>
Signed-off-by: ahamlat <ameziane.hamlat@consensys.net>

* Update evm/src/main/java/org/hyperledger/besu/evm/frame/MessageFrame.java

Co-authored-by: Simon Dudley <simon.dudley@consensys.net>
Signed-off-by: ahamlat <ameziane.hamlat@consensys.net>

* Update evm/src/main/java/org/hyperledger/besu/evm/frame/MessageFrame.java

Co-authored-by: Simon Dudley <simon.dudley@consensys.net>
Signed-off-by: ahamlat <ameziane.hamlat@consensys.net>

* Update datatypes/src/main/java/org/hyperledger/besu/datatypes/Wei.java

Co-authored-by: Simon Dudley <simon.dudley@consensys.net>
Signed-off-by: ahamlat <ameziane.hamlat@consensys.net>

* Apply refactoring changes

Signed-off-by: Ameziane H. <ameziane.hamlat@consensys.net>

* remove basefee field

Signed-off-by: Ameziane H. <ameziane.hamlat@consensys.net>

* Fix merge issue

Signed-off-by: Ameziane H. <ameziane.hamlat@consensys.net>

* Address more comments

Signed-off-by: Ameziane H. <ameziane.hamlat@consensys.net>

* Remove not used field

Signed-off-by: Ameziane H. <ameziane.hamlat@consensys.net>

* spotless

Signed-off-by: Ameziane H. <ameziane.hamlat@consensys.net>

* Undo Balance operation change and add more unit tests

Signed-off-by: Ameziane H. <ameziane.hamlat@consensys.net>

* Update AddOperationV2 after merge with main

Signed-off-by: Ameziane H. <ameziane.hamlat@consensys.net>

---------

Signed-off-by: Ameziane H. <ameziane.hamlat@consensys.net>
Signed-off-by: ahamlat <ameziane.hamlat@consensys.net>
Co-authored-by: Simon Dudley <simon.dudley@consensys.net>

---------

Signed-off-by: Karim Taam <karim.t2am@gmail.com>
Signed-off-by: Simon Dudley <simon.dudley@consensys.net>
Signed-off-by: Roman <4833306+Filter94@users.noreply.github.com>
Signed-off-by: Mykim <38449976+Apisapple@users.noreply.github.com>
Signed-off-by: mykim <kimminyong2034@gmail.com>
Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
Signed-off-by: stefan.pingel@consensys.net <stefan.pingel@consensys.net>
Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>
Signed-off-by: Luis Pinto <luis.pinto@consensys.net>
Signed-off-by: Ameziane H. <ameziane.hamlat@consensys.net>
Signed-off-by: ahamlat <ameziane.hamlat@consensys.net>
Co-authored-by: Karim Taam <karim.t2am@gmail.com>
Co-authored-by: Simon Dudley <simon.dudley@consensys.net>
Co-authored-by: Roman Vaseev <4833306+Filter94@users.noreply.github.com>
Co-authored-by: garyschulte <garyschulte@gmail.com>
Co-authored-by: Mykim <kimminyong2034@gmail.com>
Co-authored-by: Fabio Di Fabio <fabio.difabio@consensys.net>
Co-authored-by: Justin Florentine <justin+github@florentine.us>
Co-authored-by: Stefan Pingel <16143240+pinges@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Usman Saleem <usman@usmans.info>
Co-authored-by: Sally MacFarlane <macfarla.github@gmail.com>
Co-authored-by: Luis Pinto <luis.pinto@consensys.net>
Co-authored-by: ahamlat <ameziane.hamlat@consensys.net>
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.

Integrate NullAway for build-time null-safety checks

4 participants