Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/taiko-client--test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,9 @@ jobs:
SHASTA_FORK_TAIKO_MONO_DIR: shasta-fork-taiko-mono

strategy:
fail-fast: false
matrix:
execution_node: [l2_geth]
execution_node: [l2_geth, l2_nmc]

steps:
- name: Cancel Previous Runs
Expand Down
2 changes: 2 additions & 0 deletions packages/taiko-client/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,5 @@ integration_test/nodes/deployments/mainnet.json
.claude/
.code/
.bmad/
# Generated NMC chainspec (generated from template at runtime)
internal/docker/nodes/nmc/chainspec/taiko-devnet.json
4 changes: 4 additions & 0 deletions packages/taiko-client/integration_test/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ source scripts/common.sh
check_command "cast"
check_command "forge"
check_command "docker"
# jq is required for NMC to dynamically inject shastaTimestamp into chainspec
if [ "${L2_NODE:-}" == "l2_nmc" ]; then
Comment thread
jmadibekov marked this conversation as resolved.
check_command "jq"
fi

# Ensure Shasta fork activation times are set for taiko-geth (L2) and Anvil (L1).
if [ -z "${TAIKO_INTERNAL_SHASTA_TIME:-}" ] || [ -z "${ANVIL_INTERNAL_SHASTA_TIME:-}" ]; then
Expand Down
20 changes: 20 additions & 0 deletions packages/taiko-client/internal/docker/nodes/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,23 @@ services:
- --taiko
- --taiko.internal-shasta-time
- "${TAIKO_INTERNAL_SHASTA_TIME}"

l2_nmc:
container_name: l2_nmc
image: nethermindeth/nethermind:master
restart: unless-stopped
pull_policy: always
volumes:
- .:/host
- ./nmc:/nethermind/configs
ports:
- "8545"
- "8546"
- "8551"
command:
- --config
- /nethermind/configs/taiko-devnet.cfg
- --datadir
- /nethermind/data
- --log
- DEBUG

Large diffs are not rendered by default.

40 changes: 40 additions & 0 deletions packages/taiko-client/internal/docker/nodes/nmc/taiko-devnet.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"Init": {
"ChainSpecPath": "/nethermind/configs/chainspec/taiko-devnet.json",
"BaseDbPath": "/nethermind/data/taiko-devnet",
"LogFileName": "taiko-devnet.log",
"IsMining": false,
"DiscoveryEnabled": false
},
"TxPool": {
"Size": 2048,
"BlobsSupport": "Disabled"
},
"Sync": {
"FastSync": false,
"SnapSync": false,
"PivotNumber": 0
},
"Pruning": {
"Mode": "None"
},
"JsonRpc": {
"Enabled": true,
"Host": "0.0.0.0",
"Port": 8545,
"WebSocketsPort": 8546,
"EngineHost": "0.0.0.0",
"EnginePort": 8551,
"EngineEnabledModules": ["engine"],
"JwtSecretFile": "/host/jwt.hex",
"EnabledModules": ["eth", "net", "web3", "txpool", "debug", "taiko", "admin", "subscribe"]
},
"Network": {
"DiscoveryPort": 30303,
"P2PPort": 30303
},
"Metrics": {
"NodeName": "Taiko Devnet NMC"
}
}

29 changes: 25 additions & 4 deletions packages/taiko-client/internal/docker/start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,32 @@

source scripts/common.sh

if [ "$L2_NODE" == "l2_geth" ];then
# Support multiple L2 node types
case "$L2_NODE" in
l2_geth)
DOCKER_SERVICE_LIST=("l1_node" "l2_geth")
else
DOCKER_SERVICE_LIST=("l1_node")
fi
;;
l2_nmc)
DOCKER_SERVICE_LIST=("l1_node" "l2_nmc")
# For NMC, we need to dynamically inject the shastaTimestamp into the chainspec
# because Nethermind uses a static chainspec file unlike taiko-geth which uses CLI flags.
# We use a template file to avoid modifying the original and to ensure clean state on each run.
NMC_CHAINSPEC_DIR="internal/docker/nodes/nmc/chainspec"
NMC_CHAINSPEC_TEMPLATE="${NMC_CHAINSPEC_DIR}/taiko-devnet.template.json"
NMC_CHAINSPEC="${NMC_CHAINSPEC_DIR}/taiko-devnet.json"

if [ -n "${TAIKO_INTERNAL_SHASTA_TIME:-}" ] && [ -f "$NMC_CHAINSPEC_TEMPLATE" ]; then
SHASTA_HEX=$(printf "0x%x" "$TAIKO_INTERNAL_SHASTA_TIME")
echo "Generating NMC chainspec with shastaTimestamp=$SHASTA_HEX (decimal: $TAIKO_INTERNAL_SHASTA_TIME)"
# Generate chainspec from template with dynamic shastaTimestamp
jq --arg ts "$SHASTA_HEX" '.engine.Taiko.shastaTimestamp = $ts' "$NMC_CHAINSPEC_TEMPLATE" > "$NMC_CHAINSPEC"
Comment thread
jmadibekov marked this conversation as resolved.
fi
Comment thread
jmadibekov marked this conversation as resolved.
;;
*)
echo "Error: Unknown L2_NODE: '$L2_NODE'. Supported values: l2_geth, l2_nmc"
exit 1
;;
Comment thread
jmadibekov marked this conversation as resolved.
esac

# start docker compose services
echo "starting docker compose service: ${DOCKER_SERVICE_LIST[*]}"
Expand Down
16 changes: 12 additions & 4 deletions packages/taiko-client/internal/docker/stop.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,19 @@

source scripts/common.sh

if [ "$L2_NODE" == "l2_geth" ];then
# Support multiple L2 node types
case "$L2_NODE" in
l2_geth)
DOCKER_SERVICE_LIST=("l1_node" "l2_geth")
else
DOCKER_SERVICE_LIST=("l1_node")
fi
;;
l2_nmc)
DOCKER_SERVICE_LIST=("l1_node" "l2_nmc")
;;
*)
echo "Error: Unknown L2_NODE: '$L2_NODE'. Supported values: l2_geth, l2_nmc"
exit 1
;;
Comment thread
jmadibekov marked this conversation as resolved.
esac

echo "stop docker compose service: ${DOCKER_SERVICE_LIST[*]}"

Expand Down
9 changes: 7 additions & 2 deletions packages/taiko-client/internal/testutils/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,13 @@ func (s *ClientTestSuite) ProposeAndInsertValidBlock(
s.Nil(err)
err = s.RPCClient.L2.SendTransaction(context.Background(), signedTx)
if err != nil {
// If the transaction is underpriced, we just ignore it.
s.Equal("replacement transaction underpriced", err.Error())
// If the transaction is underpriced or a replacement is not allowed, we just ignore it.
// Geth returns "replacement transaction underpriced", Nethermind returns "ReplacementNotAllowed"
Comment thread
jmadibekov marked this conversation as resolved.
if os.Getenv("L2_NODE") == "l2_nmc" {
Comment thread
jmadibekov marked this conversation as resolved.
s.Equal("ReplacementNotAllowed", err.Error())
Comment thread
jmadibekov marked this conversation as resolved.
} else {
s.Equal("replacement transaction underpriced", err.Error())
}
}

s.InitShastaGenesisProposal()
Expand Down
16 changes: 16 additions & 0 deletions packages/taiko-client/internal/testutils/suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -369,4 +369,20 @@ func (s *ClientTestSuite) forkTo(attributes *engine.PayloadAttributes, parentHas
s.Nil(err)

s.Equal(attributes.L1Origin.BlockID.Uint64(), head.Number.Uint64())

// For Nethermind: clear txpool state after chain reorg
// After a reorg, stale txpool caches would reject transaction resubmissions
// with "already known" or "nonce too low". This clears hash cache, account cache, and pending txs.
// Pending txs must be cleared because tests resubmit transactions with the same hash/nonce,
// which would be rejected as "ReplacementNotAllowed" if they remain in the pool.
if os.Getenv("L2_NODE") == "l2_nmc" {
Comment thread
jmadibekov marked this conversation as resolved.
var cleared bool
err := s.RPCClient.L2Engine.CallContext(
context.Background(),
&cleared,
"taikoDebug_clearTxPoolForReorg",
)
s.Nil(err)
s.True(cleared, "TxPool clear failed after forkTo")
}
}
6 changes: 5 additions & 1 deletion packages/taiko-client/proposer/proposer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,11 @@ func (s *ProposerTestSuite) TestProposeMultiBlobsInOneBatch() {
[]byte{1},
)
if err != nil {
s.Equal("replacement transaction underpriced", err.Error())
if os.Getenv("L2_NODE") == "l2_nmc" {
Comment thread
jmadibekov marked this conversation as resolved.
s.Equal("ReplacementNotAllowed", err.Error())
Comment thread
jmadibekov marked this conversation as resolved.
} else {
s.Equal("replacement transaction underpriced", err.Error())
}
}
txsBatch[i] = append(txsBatch[i], tx)
}
Expand Down
Loading