Skip to content

Conversation

@pmikolajczyk41
Copy link
Member

  1. Move the receiver side of the protocol from jit to validation crate.
  2. Make it more generic (work over Read and Write traits, rather than concrete types).
  3. Add the sender side implementation.
  4. Add tests.

Note: the API is synchronous. We don't need async ops at the moment.


closes NIT-4364

@github-actions
Copy link
Contributor

github-actions bot commented Jan 27, 2026

❌ 9 Tests Failed:

Tests completed Failed Passed Skipped
4015 9 4006 0
View the top 3 failed tests by shortest run time
TestEndToEnd_TwoEvilValidators
Stack Traces | -0.000s run time
... [CONTENT TRUNCATED: Keeping last 20 lines]

goroutine 98694 [select, 2 minutes]:
github.com/ethereum/go-ethereum/eth.(*dropper).loop(0xc0024ce200)
	/home/runner/work/nitro/nitro/go-ethereum/eth/dropper.go:156 +0x174
created by github.com/ethereum/go-ethereum/eth.(*dropper).Start in goroutine 98615
	/home/runner/work/nitro/nitro/go-ethereum/eth/dropper.go:96 +0x125

goroutine 126704 [select]:
github.com/offchainlabs/nitro/bold/containers/events.(*Subscription[...]).Next(0x1fdd280, {0x1fdd280?, 0xc001f27ea0?})
	/home/runner/work/nitro/nitro/bold/containers/events/producer.go:130 +0xd0
github.com/offchainlabs/nitro/bold/challenge/tracker.(*Tracker).Spawn(0xc0077c8140, {0x1fdd280, 0xc001f27ea0})
	/home/runner/work/nitro/nitro/bold/challenge/tracker/tracker.go:204 +0x235
created by github.com/offchainlabs/nitro/bold/challenge/tracker.(*Tracker).Act in goroutine 123323
	/home/runner/work/nitro/nitro/bold/challenge/tracker/tracker.go:356 +0x10bf

goroutine 98661 [select, 3 minutes]:
github.com/ethereum/go-ethereum/eth/filters.(*FilterAPI).timeoutLoop(0xc00277ade0, 0x0?)
	/home/runner/work/nitro/nitro/go-ethereum/eth/filters/api.go:104 +0x14a
created by github.com/ethereum/go-ethereum/eth/filters.NewFilterAPI in goroutine 98615
	/home/runner/work/nitro/nitro/go-ethereum/eth/filters/api.go:92 +0x125
TestEndToEnd_TwoEvilValidators/honest_essential_edges_confirmed_by_challenge_win
Stack Traces | -0.000s run time
... [CONTENT TRUNCATED: Keeping last 20 lines]

goroutine 98694 [select, 2 minutes]:
github.com/ethereum/go-ethereum/eth.(*dropper).loop(0xc0024ce200)
	/home/runner/work/nitro/nitro/go-ethereum/eth/dropper.go:156 +0x174
created by github.com/ethereum/go-ethereum/eth.(*dropper).Start in goroutine 98615
	/home/runner/work/nitro/nitro/go-ethereum/eth/dropper.go:96 +0x125

goroutine 126704 [select]:
github.com/offchainlabs/nitro/bold/containers/events.(*Subscription[...]).Next(0x1fdd280, {0x1fdd280?, 0xc001f27ea0?})
	/home/runner/work/nitro/nitro/bold/containers/events/producer.go:130 +0xd0
github.com/offchainlabs/nitro/bold/challenge/tracker.(*Tracker).Spawn(0xc0077c8140, {0x1fdd280, 0xc001f27ea0})
	/home/runner/work/nitro/nitro/bold/challenge/tracker/tracker.go:204 +0x235
created by github.com/offchainlabs/nitro/bold/challenge/tracker.(*Tracker).Act in goroutine 123323
	/home/runner/work/nitro/nitro/bold/challenge/tracker/tracker.go:356 +0x10bf

goroutine 98661 [select, 3 minutes]:
github.com/ethereum/go-ethereum/eth/filters.(*FilterAPI).timeoutLoop(0xc00277ade0, 0x0?)
	/home/runner/work/nitro/nitro/go-ethereum/eth/filters/api.go:104 +0x14a
created by github.com/ethereum/go-ethereum/eth/filters.NewFilterAPI in goroutine 98615
	/home/runner/work/nitro/nitro/go-ethereum/eth/filters/api.go:92 +0x125
TestRedisProduceComplex/two_producers,_some_consumers_killed,_one_retrying_consumer_take_over_their_work,_unequal_number_of_requests_from_producers
Stack Traces | 2.080s run time
... [CONTENT TRUNCATED: Keeping last 20 lines]
�[36mDEBUG�[0m[01-28|14:58:05.151] request timed out waiting for response   �[36mmsgId�[0m=1769612283145-19 �[36mallowedOldestId�[0m=1769612283148-0
�[36mDEBUG�[0m[01-28|14:58:05.151] request timed out waiting for response   �[36mmsgId�[0m=1769612283145-21 �[36mallowedOldestId�[0m=1769612283148-0
�[36mDEBUG�[0m[01-28|14:58:05.152] request timed out waiting for response   �[36mmsgId�[0m=1769612283145-17 �[36mallowedOldestId�[0m=1769612283148-0
�[36mDEBUG�[0m[01-28|14:58:05.152] request timed out waiting for response   �[36mmsgId�[0m=1769612283145-18 �[36mallowedOldestId�[0m=1769612283148-0
�[36mDEBUG�[0m[01-28|14:58:05.152] request timed out waiting for response   �[36mmsgId�[0m=1769612283145-13 �[36mallowedOldestId�[0m=1769612283148-0
�[36mDEBUG�[0m[01-28|14:58:05.152] request timed out waiting for response   �[36mmsgId�[0m=1769612283145-14 �[36mallowedOldestId�[0m=1769612283148-0
�[36mDEBUG�[0m[01-28|14:58:05.152] request timed out waiting for response   �[36mmsgId�[0m=1769612283145-20 �[36mallowedOldestId�[0m=1769612283148-0
�[36mDEBUG�[0m[01-28|14:58:05.152] checkResponses                           �[36mresponded�[0m=0   �[36merrored�[0m=10 �[36mchecked�[0m=10
    pubsub_test.go:385: Unexpected error while awaiting responses, producer: 0, response: 42, err: error getting response, request has been waiting for too long
    pubsub_test.go:385: Unexpected error while awaiting responses, producer: 0, response: 43, err: error getting response, request has been waiting for too long
    pubsub_test.go:385: Unexpected error while awaiting responses, producer: 0, response: 44, err: error getting response, request has been waiting for too long
    pubsub_test.go:385: Unexpected error while awaiting responses, producer: 0, response: 45, err: error getting response, request has been waiting for too long
    pubsub_test.go:385: Unexpected error while awaiting responses, producer: 0, response: 46, err: error getting response, request has been waiting for too long
    pubsub_test.go:385: Unexpected error while awaiting responses, producer: 0, response: 47, err: error getting response, request has been waiting for too long
    pubsub_test.go:385: Unexpected error while awaiting responses, producer: 0, response: 48, err: error getting response, request has been waiting for too long
    pubsub_test.go:385: Unexpected error while awaiting responses, producer: 0, response: 49, err: error getting response, request has been waiting for too long
    pubsub_test.go:385: Unexpected error while awaiting responses, producer: 0, response: 50, err: error getting response, request has been waiting for too long
    pubsub_test.go:385: Unexpected error while awaiting responses, producer: 0, response: 51, err: error getting response, request has been waiting for too long
�[36mDEBUG�[0m[01-28|14:58:05.218] Error destroying a stream group          �[36merror�[0m="dial tcp 127.0.0.1:41517: connect: connection refused"
--- FAIL: TestRedisProduceComplex/two_producers,_some_consumers_killed,_one_retrying_consumer_take_over_their_work,_unequal_number_of_requests_from_producers (2.08s)

📣 Thoughts on this report? Let Codecov know! | Powered by Codecov

@codecov
Copy link

codecov bot commented Jan 27, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 32.59%. Comparing base (db29e55) to head (9da625e).

❗ There is a different number of reports uploaded between BASE (db29e55) and HEAD (9da625e). Click for more details.

HEAD has 1 upload less than BASE
Flag BASE (db29e55) HEAD (9da625e)
5 4
Additional details and impacted files
@@             Coverage Diff             @@
##           master    #4280       +/-   ##
===========================================
- Coverage   57.12%   32.59%   -24.54%     
===========================================
  Files         476      476               
  Lines       56785    56785               
===========================================
- Hits        32441    18511    -13930     
- Misses      19506    35038    +15532     
+ Partials     4838     3236     -1602     

Copy link
Contributor

@bragaigor bragaigor left a comment

Choose a reason for hiding this comment

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

Overall looks good and seems that most of my comments are nitpicks :)

@@ -0,0 +1,3 @@
### Ignored
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
### Ignored
### Internal

Copy link
Member Author

Choose a reason for hiding this comment

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

I missed that we added this section, thanks! fixed in eab1044

Copy link
Contributor

Choose a reason for hiding this comment

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

The idea is that the ones introduced in #4269 to be substituted for these ones right?

Copy link
Member Author

Choose a reason for hiding this comment

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

exactly - actually, I was partly basing this PR on your code

Comment on lines +293 to 296
if input.has_delayed_msg {
env.delayed_messages
.insert(input.delayed_msg_nr, input.delayed_msg);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

will there always be just one delayed_message? Asking because before, just like sequencer_messages, delayed_messages was wrapped in a while loop

Copy link
Member Author

Choose a reason for hiding this comment

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

citing Tsahi:

Currently - it can only contain a single delayed message. There are future thoughs about having multiple delayed messages in a single block but that'll only happen after MEL and we could tackle it then.

Copy link
Member Author

Choose a reason for hiding this comment

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

so there's some lack of consistency in the code, but right now I tried to persist the existing behavior and data structs

Copy link
Contributor

Choose a reason for hiding this comment

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

ah got it, thanks!

let hash = socket::read_bytes32(stream)?;
let preimage = socket::read_bytes(stream)?;
for (preimage_type, preimages) in input.preimages {
let map = env.preimages.entry(preimage_type).or_default();
Copy link
Contributor

Choose a reason for hiding this comment

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

nitpick: map is a bit too generic and I know it was already there, maybe we could rename to something like preimage_map? Up to you

Copy link
Member Author

Choose a reason for hiding this comment

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

renamed in 043c73f

batch_info: inbox,
delayed_msg: delayed_message.data,
start_state,
user_wasms: HashMap::from([(local_target(), user_wasms)]),
Copy link
Contributor

Choose a reason for hiding this comment

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

why having a HashMap instead of just user_wasms?

Copy link
Member Author

Choose a reason for hiding this comment

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

because ValidationInput has HashMap here, in case someone wants to pass wasms for multiple different archs

Comment on lines 12 to 18
pub type IOResult<T> = Result<T, io::Error>;

const SUCCESS: u8 = 0x0;
const FAILURE: u8 = 0x1;
// const PREIMAGE: u8 = 0x2; // legacy, not used
const ANOTHER: u8 = 0x3;
const READY: u8 = 0x4;
Copy link
Contributor

Choose a reason for hiding this comment

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

nitpick: I don't have a strong opinion but maybe these could go into their own file constants.rs? and keep mod.rs with just the mods?

Copy link
Member Author

Choose a reason for hiding this comment

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

moved to markers.rs to make it more explicit what constants they are

Comment on lines 106 to 113
if self.has_delayed_msg {
Some(BatchInfo {
number: self.delayed_msg_nr,
data: self.delayed_msg.clone(),
})
} else {
None
}
Copy link
Contributor

Choose a reason for hiding this comment

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

nitpick suggestion

Suggested change
if self.has_delayed_msg {
Some(BatchInfo {
number: self.delayed_msg_nr,
data: self.delayed_msg.clone(),
})
} else {
None
}
self.has_delayed_msg.then(|| BatchInfo {
number: self.delayed_msg_nr,
data: self.delayed_msg.clone(),
})

Copy link
Member Author

Choose a reason for hiding this comment

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

image

Comment on lines 16 to 23
pub fn local_target() -> String {
match (env::consts::OS, env::consts::ARCH) {
("linux", "aarch64") => "arm64",
("linux", "x86_64") => "amd64",
_ => "host",
}
.to_string()
}
Copy link
Contributor

Choose a reason for hiding this comment

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

nitpick suggestion coming from #4269

Suggested change
pub fn local_target() -> String {
match (env::consts::OS, env::consts::ARCH) {
("linux", "aarch64") => "arm64",
("linux", "x86_64") => "amd64",
_ => "host",
}
.to_string()
}
pub fn local_target() -> &'static str {
if cfg!(all(target_os = "linux", target_arch = "aarch64")) {
TARGET_ARM_64
} else if cfg!(all(target_os = "linux", target_arch = "x86_64")) {
TARGET_AMD_64
} else {
TARGET_HOST
}
}

then the const can go into the contstants.rs file if you decide to create one:

pub(crate) const TARGET_ARM_64: &str = "arm64";
pub(crate) const TARGET_AMD_64: &str = "amd64";
pub(crate) const TARGET_HOST: &str = "host";

Again up to you

Copy link
Member Author

Choose a reason for hiding this comment

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

applied suggestion ✅

use std::io::ErrorKind::InvalidData;
use std::io::{Error, Write};

pub fn send_validation_input(writer: &mut impl Write, input: &ValidationInput) -> IOResult<()> {
Copy link
Contributor

Choose a reason for hiding this comment

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

it seems like this and send_batches, send_preimages, and send_user_wasms are only used in tests? Unless I missed their caller? If so, wouldn't it be best to move them down to the test file itself? Or we have plans to use them in the future somewhere?

Copy link
Member Author

Choose a reason for hiding this comment

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

hopefully all these will be used in your continuous mode (replacing existing inlined protocol) :)

Copy link
Contributor

Choose a reason for hiding this comment

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

true, that would simplify things

@pmikolajczyk41 pmikolajczyk41 removed their assignment Jan 28, 2026
Copy link
Contributor

@bragaigor bragaigor left a comment

Choose a reason for hiding this comment

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

LGTM

@bragaigor bragaigor assigned eljobe and unassigned bragaigor Jan 28, 2026
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.

4 participants