Skip to content

Conversation

KolbyML
Copy link
Member

@KolbyML KolbyML commented Sep 10, 2025

Fixes NIT-2567

I have implemented the JSON-RPC interface for the consensus and execution layer.

I setup a basic cli-arg setup has --node.interconnect which has 2 options

  • direct the default uses the pre-existing interfaces
  • jsonrpc runs the Consensus and Execution interfaces over a json rpc

I run direct and it works fine.

jsonrpc fails with "failed to create node err="not connected" which to fix this I assume we need to ensure

  • the client is connecting to the right jsonrpc server
  • start the clients after the server is started

^ so basically ensuring the server's are running and properly connect before trying to use the interfaces

In terms of scope Have configuration to use existing interface or new RPC interface I set things up with this in mind. In the future I assume that we will allow users to specify running exclusively the consensus side so that a different execution layer client can be chosen, but to my knowledge that task was out of scope of this issue/pr and will definitely require some re-arranging and refactoring of how things are initialized.

So I believe this Issue is more of a V1 before we add more complexity to how the node is initialized.

If anybody has any questions feel free to ask me

Updated description

#3617 (comment)

@ganeshvanahalli
Copy link
Contributor

ganeshvanahalli commented Sep 18, 2025

This PR has been changed from its initial design. Execution and Consensus each have capability to enable connections to them via json-rpc through the flags --execution.rpc-server.* and --node.rpc-server.* respectively, and they are allowed to connect to external such counterparts via json-rpc facilitated by flags --execution.consensus-rpc-client.* and --node.execution-rpc-client.* respectively.

Nitro has two new flags that determine

--execution-node=<bool>
--consensus-execution-use-rpc=<bool>
  • if an execution node is to be created or instead consensus would prefer connecting over an RPC to execution.ExecutionClient interface implementer and
  • if we have execution and consensus nodes both starting then if they should communicate over rpc (used for testing) respectively

Testing done

A new CI step has been added to run current system tests with json rpc interconnect enabled.

Resolves NIT-2567

Copy link
Contributor

@diegoximenes diegoximenes left a comment

Choose a reason for hiding this comment

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

Nice 🙂, this is quite important for the alternative clients effort!

The way I see the UX on how to run a Nitro node, implemented in this repo, is something like this:

  1. Node operator runs only Execution ./nitro --consensus-node=false --execution-node=true. In that case Execution will connect with Consensus through RPC. We don't even create a arbnode.Node object in this scenario.
  2. Node operator runs only Consensus ./nitro --consensus-node=true --execution-node=false. In that case Consensus will connect with Execution through RPC.
  3. Node operator runs Execution and Consensus ./nitro --execution-node=true --consensus-node=true --consensus-execution-use-rpc=bool. A single process will run both Execution and Consensus.

I don't like the --consensus-execution-use-rpc flag on option 3 BTW, but it is worth having it for testing, at least for a while.
I don't see an advantage of running Option 3 over RPC in production if we have an option to have Consensus and Execution living in the same process.
But without this flag, to test this PR we would need to run two ./nitros, have an external component similar to consensusexecution_consensus.InitAndStartExecutionAndConsensusNodes, coordinating Execution/Consensus to handle the egg/chicken problem related to which component to start first.

It is a little bit different from what this PR is proposing.
WDYT?

ConsensusExecutionSyncer: DefaultConsensusExecutionSyncerConfig,
SnapSyncTest: DefaultSnapSyncConfig,
RPCServer: DefaultRPCServerConfig,
ExecutionRPCClient: rpcclient.ClientConfig{
Copy link
Contributor

Choose a reason for hiding this comment

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

Any specific reason for not using rpcclient.DefaultClientConfig?

Copy link
Contributor

Choose a reason for hiding this comment

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

rpcclient.DefaultClientConfig has URL = "self-auth" we dont want that as default so

Comment on lines +1300 to +1303
if configFetcher.Get().ExecutionRPCClient.URL != "" {
execConfigFetcher := func() *rpcclient.ClientConfig { return &configFetcher.Get().ExecutionRPCClient }
executionClient = executionrpcclient.NewExecutionRpcClient(execConfigFetcher, nil)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

nitpick: This code block is replicated in CreateNodeFullExecutionClient.
How about abstracting that into a function and calling it here and in CreateNodeFullExecutionClient?

Copy link
Contributor

Choose a reason for hiding this comment

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

implementation has changed now and I feel like this is a small enough code diff to not warrant defining a function over...


var ErrSequencerInsertLockTaken = errors.New("insert lock taken")

type MessageResult struct {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this defined in consensus instead of execution?

Copy link
Contributor

Choose a reason for hiding this comment

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

not sure, i've removed it

@diegoximenes
Copy link
Contributor

To keep in mind:

  • The main goal of this PR is to enable our current Nitro golang Consensus node to run with Erigon and Nethermind execution clients. The first milestone for Erigon and Nethermind is to only implement simple execution clients, i.e., execution clients that implement the ExecutionClient interface, so we are not worried about other behaviors that are described by the ExecutionRecorder/ExecutionSequencer/ExecutionBatchPoster interfaces.
  • Also, we should not be worried, for now at least, about the scenario in which our current Nitro golang Execution node connects with a Consensus node that is not the one that is implemented in this repo.

By not worry I mean that we don't need to cover them in this PR, but we should definitely consider that those scenarios, could, and ideally will happen 🙂, so changes here shouldn't make our lives too difficult when covering them in the future.

There is this test, in which is possible to create a Nitro node with an execution client that only implements the ExecutionClient interface, and not ExecutionRecorder, etc.
It uses CreateNodeExecutionClient, instead of CreateNodeFullExecutionClient, under the hood.

That said, for this PR, the minimal requirements could be:

  1. If --consensus-node==false then fail during config validation step. Or don't even add this --consensus-node config for now, it can be easier 🙂
  2. If --execution-node==false
  • We can assume that there will be an external execution client interacting with this Consensus node.
  • Use CreateNodeExecutionClient instead of CreateNodeFullExecutionClient
  • Consensus will need to have an RPC server so an external execution client can "connect" to it.
  • We should avoid creating an execution.ExecutionNode object, or at least not set the consensus client to the execution.ExecutionNode object. It can become a weird situation if this ExecutionNode starts calling Consensus, which will already be called by the external execution client. Two execution clients will be connected with this Consensus node, it can become a mess 😬.
  1. If --execution-node==true and --consensus-execution-use-rpc==true then:
  • We will need to validate Execution config, to fail if it is trying to use Sequencer/Recorder/BatchPoster behavior.
  • use CreateNodeExecutionClient instead of CreateNodeFullExecutionClient
  • Consensus will need to have an RPC server
  • Execution will need to have an RPC server
  1. Else we do what is already being done on master.

I am OK with covering all execution behaviors with the RPC approach right now TBH, it seems the way to go long term wise, but it is definitely not a requirement.
In this way CreateNodeFullExecutionClient can still be used for those scenarios, and there will be less config validation steps.
Code diff of this PR will be a little bit bigger though.
If you want to follow this approach I would first get I buy in from Tsahi, he mentioned some times that he doesn't want to implement the RPC interfaces for other behaviors right now.

We could have the same behavior without the --execution-node and --consensus-execution-use-rpc flags BTW, only relying on the rpc flags such as --execution-rpc-server and --execution-rpc-client.
But it becomes less explicit, and more confusing IMO, e.g.:

  • --execution-rpc-server and --execution-rpc-client are set is analogous to: --execution-node==true and --consensus-execution-use-rpc==true
  • --execution-rpc-server is not set and --execution-rpc-client is set is analogous to: --execution-node==false

WDYT?

@ganeshvanahalli
Copy link
Contributor

To keep in mind:

...

I've addressed your comments and added two new flags to nitro -

--execution-node=<bool>
--consensus-execution-use-rpc=<bool>
  • that determine if an execution node is to be created or instead consensus would prefer connecting over an RPC to execution.ExecutionClient interface implementer and
  • if we have execution and consensus nodes both starting then if they should communicate over rpc (used for testing)

@tsahee tsahee assigned tsahee and unassigned diegoximenes Oct 8, 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.

4 participants