Skip to content

Conversation

@fmacleal
Copy link
Collaborator

This PR adds the BlockHeader extension to save the BridgeEvent. This is essential for the union bridge verification from the pegin events.

This PR still a work in progress.

Description

Motivation and Context

How Has This Been Tested?

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • Tests for the changes have been added (for bug fixes / features)
  • Requires Activation Code (Hard Fork)
  • Other information:

@github-actions
Copy link

github-actions bot commented Oct 13, 2025

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@fmacleal fmacleal force-pushed the fmacleal/superevent-blockheader-extension branch 2 times, most recently from 8093f04 to 0a5090f Compare October 17, 2025 17:11
@fmacleal fmacleal changed the title Bridge event blockheader extension RSKIP-535 - Addition of Base event in the BlockHeader Oct 20, 2025
@fmacleal fmacleal force-pushed the fmacleal/superevent-blockheader-extension branch from 64dc5cb to 0b8c673 Compare October 20, 2025 17:29
@fmacleal fmacleal force-pushed the fmacleal/superevent-blockheader-extension branch 6 times, most recently from 15b20f6 to e612a04 Compare October 26, 2025 17:53
@fmacleal fmacleal force-pushed the fmacleal/superevent-blockheader-extension branch from 32ea855 to 935b3ab Compare December 4, 2025 11:02
@sonarqubecloud
Copy link

sonarqubecloud bot commented Dec 4, 2025

@fmacleal fmacleal force-pushed the fmacleal/superevent-blockheader-extension branch from fbcb422 to 3d5fa64 Compare December 4, 2025 13:33

private void smokeTest(String contentType, String host, InetAddress rpcAddress, List<String> rpcHost, List<ModuleDescription> filteredModules, Function<Config, Config> decorator, String mockResult, String method) throws Exception {
private void smokeTest(String contentType, String host, InetAddress rpcAddress, List<String> rpcHost,
List<ModuleDescription> filteredModules, Function<Config, Config> decorator, String mockResult,

Check notice

Code scanning / CodeQL

Useless parameter Note test

The parameter 'decorator' is never used.

Copilot Autofix

AI 7 days ago

The best way to fix this is to remove the unused decorator parameter from all the overloaded smokeTest methods where it is present, and adjust all calls to these methods as needed. This means:

  • Remove Function<Config, Config> decorator from:
    • Line 579: private void smokeTest(...)
    • Line 585: private void smokeTest(...)
    • Line 600: private void smokeTest(...)
  • Remove the passing of decorator argument in all internal calls within these methods.
  • If these methods are called externally anywhere else (within the shown code), update call sites accordingly.

In this case, only edits to the shown code within rskj-core/src/test/java/co/rsk/rpc/netty/Web3HttpServerTest.java are needed.

Suggested changeset 1
rskj-core/src/test/java/co/rsk/rpc/netty/Web3HttpServerTest.java

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/rskj-core/src/test/java/co/rsk/rpc/netty/Web3HttpServerTest.java b/rskj-core/src/test/java/co/rsk/rpc/netty/Web3HttpServerTest.java
--- a/rskj-core/src/test/java/co/rsk/rpc/netty/Web3HttpServerTest.java
+++ b/rskj-core/src/test/java/co/rsk/rpc/netty/Web3HttpServerTest.java
@@ -577,14 +577,14 @@
     }
 
     private void smokeTest(String contentType, String host, List<ModuleDescription> filteredModules,
-            Function<Config, Config> decorator, String mockResult, String method) throws Exception {
-        smokeTest(contentType, host, InetAddress.getLoopbackAddress(), new ArrayList<>(), filteredModules, decorator,
+            String mockResult, String method) throws Exception {
+        smokeTest(contentType, host, InetAddress.getLoopbackAddress(), new ArrayList<>(), filteredModules,
                 mockResult, method);
     }
 
     private void smokeTest(String contentType, String host, List<ModuleDescription> filteredModules,
-            Function<Config, Config> decorator, String mockResult) throws Exception {
-        smokeTest(contentType, host, InetAddress.getLoopbackAddress(), new ArrayList<>(), filteredModules, decorator,
+            String mockResult) throws Exception {
+        smokeTest(contentType, host, InetAddress.getLoopbackAddress(), new ArrayList<>(), filteredModules,
                 mockResult, "web3_sha3");
     }
 
@@ -598,7 +594,7 @@
     }
 
     private void smokeTest(String contentType, String host, InetAddress rpcAddress, List<String> rpcHost,
-            List<ModuleDescription> filteredModules, Function<Config, Config> decorator, String mockResult,
+            List<ModuleDescription> filteredModules, String mockResult,
             String method) throws Exception {
         Web3 web3Mock = Mockito.mock(Web3.class);
         Mockito.when(web3Mock.web3_sha3(anyString())).thenReturn(mockResult);
EOF
@@ -577,14 +577,14 @@
}

private void smokeTest(String contentType, String host, List<ModuleDescription> filteredModules,
Function<Config, Config> decorator, String mockResult, String method) throws Exception {
smokeTest(contentType, host, InetAddress.getLoopbackAddress(), new ArrayList<>(), filteredModules, decorator,
String mockResult, String method) throws Exception {
smokeTest(contentType, host, InetAddress.getLoopbackAddress(), new ArrayList<>(), filteredModules,
mockResult, method);
}

private void smokeTest(String contentType, String host, List<ModuleDescription> filteredModules,
Function<Config, Config> decorator, String mockResult) throws Exception {
smokeTest(contentType, host, InetAddress.getLoopbackAddress(), new ArrayList<>(), filteredModules, decorator,
String mockResult) throws Exception {
smokeTest(contentType, host, InetAddress.getLoopbackAddress(), new ArrayList<>(), filteredModules,
mockResult, "web3_sha3");
}

@@ -598,7 +594,7 @@
}

private void smokeTest(String contentType, String host, InetAddress rpcAddress, List<String> rpcHost,
List<ModuleDescription> filteredModules, Function<Config, Config> decorator, String mockResult,
List<ModuleDescription> filteredModules, String mockResult,
String method) throws Exception {
Web3 web3Mock = Mockito.mock(Web3.class);
Mockito.when(web3Mock.web3_sha3(anyString())).thenReturn(mockResult);
Copilot is powered by AI and may make mistakes. Always verify output.
nagarev
nagarev previously approved these changes Dec 4, 2025
Copy link
Contributor

@nagarev nagarev left a comment

Choose a reason for hiding this comment

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

LGTM! 🚢

italo-sampaio
italo-sampaio previously approved these changes Dec 5, 2025
Copy link
Collaborator

@italo-sampaio italo-sampaio left a comment

Choose a reason for hiding this comment

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

LGTM!

if (block != null && header != null && activationConfig.isActive(ConsensusRule.RSKIP535, block.getNumber())) {
try {
Repository repo = repositoryLocator.startTrackingAt(header);
if (repo != null) {
Copy link
Contributor

Choose a reason for hiding this comment

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

can the repo be null? 🤔

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think I added this because it was hard to mock during tests. Also it's a protection, since it's out of core control. Do you think we should handle the exception?

profiler.stop(metric);
}

private void setBaseEventIfRskip535IsActive(Block block, BlockHeader header) {
Copy link
Contributor

Choose a reason for hiding this comment

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

should we move this to a helper class? as for header.setTransactionsRoot(BlockHashesHelper.getTxTrieRoot(block.getTransactionsList(), isRskip126Enabled));

marcos-iov
marcos-iov previously approved these changes Dec 5, 2025
Comment on lines 25 to 26
rskip144 = 1
rskip351 = 1
Copy link
Contributor

Choose a reason for hiding this comment

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

These 2 are already part of reed810 so this can be removed

rskipUMM = 1
rskip144 = 1
rskip351 = 1
rskip535 = 1
Copy link
Contributor

Choose a reason for hiding this comment

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

If this is part of Vetiver then no need to add it here

},
consensusRules = {
rskip97 = -1 # disable orchid difficulty drop
rskipUMM = 1
Copy link
Contributor

Choose a reason for hiding this comment

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

And this one is part of papyrus

Comment on lines +188 to +195
if (!activationConfig.isActive(ConsensusRule.RSKIP351, blockNumber) || !compressed) {
if (rlpHeader.size() > r && activationConfig.isActive(ConsensusRule.RSKIP144, blockNumber)) {
txExecutionSublistsEdges = ByteUtil.rlpToShorts(rlpHeader.get(r++).getRLPRawData());
}

if ((!activationConfig.isActive(ConsensusRule.RSKIP351, blockNumber) || !compressed) &&
(rlpHeader.size() > r && activationConfig.isActive(ConsensusRule.RSKIP144, blockNumber))) {
txExecutionSublistsEdges = ByteUtil.rlpToShorts(rlpHeader.get(r++).getRLPRawData());
if (rlpHeader.size() > r && activationConfig.isActive(ConsensusRule.RSKIP535, blockNumber)) {
baseEvent = rlpHeader.get(r++).getRLPRawData();
}
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 this should be reviewed, rskip351 and rskip535 will probably be active at the same time
if thats the case, then the baseEvent wont ever be updated, since the if condition (!activationConfig.isActive(ConsensusRule.RSKIP351, blockNumber)) wont be met

Copy link
Contributor

Choose a reason for hiding this comment

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

Might wanna review this logic @fmacleal @nagarev, according to the code base event will only be set if PTE is not active. Is that the intention?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I would have to take a deeper look, and it's probably easier to add a test. Maybe I added a test where both were active. By looking to this if I don't see why it wouldn't set the baseEvent. RSKIP-351 it's mandatory for PTE and for baseEvent. Because it's the one that add the possibility to have header extension. If RSKIP-351 it's active, the next field in RLP can be the txSublist from PTE or the baseEvent. If PTE it's enabled, we will set it and increment the index from RLP, then we check baseEvent. Why it wouldn't set the baseEvent if PTE it's enabled in this logic here?

Comment on lines +45 to +53
ConsensusRule.RSKIP85,
ConsensusRule.RSKIP87,
ConsensusRule.RSKIP88,
ConsensusRule.RSKIP89,
ConsensusRule.RSKIP90,
ConsensusRule.RSKIP91,
ConsensusRule.RSKIP92,
ConsensusRule.RSKIP97,
ConsensusRule.RSKIP98
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we undo all these changes? I think we have consensus to use one tab (4 spaces) for indentation

ConsensusRule.RSKIP351,
ConsensusRule.RSKIP502,
ConsensusRule.RSKIP529,
ConsensusRule.RSKIP535,
Copy link
Contributor

Choose a reason for hiding this comment

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

This one should go with Vetiver not reed810

Copy link
Contributor

Choose a reason for hiding this comment

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

agree with marcos

Comment on lines +39 to +50
"hardforkActivationHeights: {",
" genesis: 0",
" bahamas: 0",
" afterBridgeSync: 0,",
" orchid: 0,",
" orchid060: 0,",
" wasabi100: 0",
" papyrus200: 0",
" twoToThree: 0",
" iris300: 0",
" hop400: 0",
" hop401: 0",
Copy link
Contributor

Choose a reason for hiding this comment

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

All these tabs don't help with reviewing the actual changes

Copy link
Contributor

Choose a reason for hiding this comment

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

agree with marcos

@marcos-iov marcos-iov self-requested a review December 5, 2025 16:26
);
}
}
default -> new BlockHeaderV0(
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
default -> new BlockHeaderV0(
case 0x0 -> new BlockHeaderV0(

just a suggestion


@Override
public void setBaseEvent(byte[] baseEvent) {
if (baseEvent != null) {
Copy link
Contributor

Choose a reason for hiding this comment

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

should we also check

        if (this.sealed) {
            throw new SealedBlockHeaderException("trying to alter baseEvent");
        }

here? As in BlockHeaderV0

makeExtension(compressed, extensionData, txExecutionSublistsEdges, baseEvent), compressed);
}

private static BlockHeaderExtensionV1 makeExtension(boolean compressed,
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
private static BlockHeaderExtensionV1 makeExtension(boolean compressed,
private static BlockHeaderExtensionV2 makeExtension(boolean compressed,

?

}

@Test
void testSetBaseEventWithVeryLargeValueThrowsException() {
Copy link
Contributor

Choose a reason for hiding this comment

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

we should probaby test the first wrong value too (i.e. 129 bytes), wdyt?

Copy link
Contributor

@julia-zack julia-zack Dec 5, 2025

Choose a reason for hiding this comment

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

we should probably add tests for decodeHeader for when base event is active, right?
that way we can test the internal flow when decoding from the block factory

}

@Test
void createHeaderWithVersion2AfterRskip351() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
void createHeaderWithVersion2AfterRskip351() {
void createHeaderWithVersion2AfterRskip535() {

?

}

@Test
void testBridgeEventWithMaxSize() {
Copy link
Contributor

Choose a reason for hiding this comment

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

do we want this? when setting baseEvent calling blockHeader.setBaseEvent we dont allow large values

Copy link
Contributor

Choose a reason for hiding this comment

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

check test names, a bunch of them say bridgeEvent instead of baseEvent

@nagarev nagarev dismissed stale reviews from marcos-iov, italo-sampaio, and themself via 40f1e00 December 8, 2025 16:49
@sonarqubecloud
Copy link

sonarqubecloud bot commented Dec 9, 2025

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