Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
4502af1
fix(kms): make the AWS KMS signer support dynamic-fee transactions
renatomaia Jul 21, 2026
7c06bd0
test(kms): add unit test for AWS KMS authentication
renatomaia Aug 25, 2026
38ad265
test(integration): add make target to run AWS LocalStack
renatomaia Jul 22, 2026
3abc81a
test(integration): fix AWS KMS subtest execution
renatomaia Aug 27, 2026
186055b
test(integration): use new style for Ethereum transactions for better…
renatomaia Aug 27, 2026
48c2a3a
test(integration): only run AWS Local Stack for required tests
renatomaia Aug 27, 2026
7b1d009
test(integration): fix clean up of configurations used in tests
renatomaia Aug 27, 2026
914dace
test(integration): isolate AWS KMS funding account
renatomaia Aug 27, 2026
78d2ed4
test(integration): allow built-in readness check of AWS LocalStack image
renatomaia Aug 27, 2026
588fec0
test(integration): clean up AWS KMS test resources
renatomaia Aug 27, 2026
8eac70d
test(integration): fail AWS KMS test when misconfigured
renatomaia Sep 1, 2026
2531d77
fix(kms): remove redundant configuration variables for AWS KMS
renatomaia Aug 25, 2026
b0057fb
fix(kms): handle invalid AWS KMS authentication
renatomaia Aug 26, 2026
d2b092f
test(kms): improve test coverage of AWS KMS authentication
renatomaia Aug 26, 2026
7c354c8
test(kms): fix test environment config cleanup
renatomaia Sep 1, 2026
1ea8e25
refactor(kms): fix small details in implementation and tests
renatomaia Aug 26, 2026
763847d
style(kms): avoid lint errors
renatomaia Aug 26, 2026
68f345a
feat(claimer,prt): log submitter identity on service startup
renatomaia Aug 24, 2026
550b164
fix(cli): use a single authentication for all deposit transactions
renatomaia Aug 26, 2026
a522db5
docs(services): remove outdated comment
renatomaia May 11, 2026
c5008b7
refactor(services): improve the framework for implementing services
renatomaia Apr 16, 2026
b3a67b4
fix(evmreader): EVM Reader is ready only when polling sucessfully
renatomaia Jul 16, 2026
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: 3 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
version: "2"
run:
build-tags:
- endtoendtests
linters:
enable:
- exhaustive
Expand Down
34 changes: 31 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,17 @@ start-postgres: ## Run the PostgreSQL 16 docker container
@docker run --rm --name postgres -p 5432:5432 -d -e POSTGRES_PASSWORD=password -e POSTGRES_DB=rollupsdb -v $(CURDIR)/test/postgres/init-test-db.sh:/docker-entrypoint-initdb.d/init-test-db.sh postgres:18-alpine
@$(MAKE) migrate

start-awslocalstack: ## Run the AWS LocalStack docker container
@echo "Starting AWS localstack"
@docker run --rm --name awslocalstack -p 127.0.0.1:4566:4566 -d -e SERVICES=kms localstack/localstack:4.14.0
@echo "Add the following variables to run integration test with AWS services:"
@echo " export AWS_ACCESS_KEY_ID=test"
@echo " export AWS_SECRET_ACCESS_KEY=test"
@echo " export AWS_REGION=us-east-1"
@echo " export AWS_ENDPOINT_URL_KMS=http://localhost:4566"
@echo " export LOCALSTACK_KMS_ENDPOINT=http://localhost:4566"
@echo " export LOCALSTACK_KMS_REQUIRED=true"

start: start-postgres start-devnet ## Start the anvil devnet and PostgreSQL 16 docker containers

stop-devnet: ## Stop the anvil devnet docker container
Expand All @@ -524,7 +535,10 @@ stop-devnet: ## Stop the anvil devnet docker container
stop-postgres: ## Stop the PostgreSQL 16 docker container
@docker stop postgres || true

stop: stop-devnet stop-postgres ## Stop all running docker containers
stop-awslocalstack: ## Stop the AWS LocalStack docker container
@docker stop awslocalstack || true

stop: stop-devnet stop-postgres ## Stop the anvil devnet and PostgreSQL 16 docker containers

restart-devnet: ## Restart the anvil devnet docker container
@$(MAKE) stop-devnet
Expand Down Expand Up @@ -571,14 +585,15 @@ check-license: ## Verify license headers on Go source files
# Discovery (integration-test-shard-check) lists tests with a plain Go
# toolchain, so the integration package must stay free of the Cartesi CGo
# dependency for the check to build on the CI setup runner.
INTEGRATION_SHARDS := basic quorum prt replay restart withdrawal
INTEGRATION_SHARDS := basic quorum prt replay restart withdrawal awskms

INTEGRATION_SHARD_basic := ^Test(EchoAuthority|RejectException|MultiApp|EchoAuthorityStaging)$$
INTEGRATION_SHARD_quorum := ^Test(EchoQuorum|SameBlockInputs)$$
INTEGRATION_SHARD_prt := ^Test(EchoPrt|RejectExceptionPrt|ForeclosePrt)$$
INTEGRATION_SHARD_replay := ^Test(Foreclose|ForecloseReplay|DivergentClaim)$$
INTEGRATION_SHARD_restart := ^Test(Restart|SnapshotPolicy)$$
INTEGRATION_SHARD_withdrawal := ^TestWithdrawalLifecycle$$
INTEGRATION_SHARD_awskms := ^TestLocalStackAWSIntegration$$

# -----------------------------------------------------------------------------
# Node topology axis — orthogonal to shards.
Expand All @@ -600,7 +615,7 @@ INTEGRATION_TOPOLOGIES := standalone multiprocess
NODE_TOPOLOGY ?= standalone

INTEGRATION_SHARDS_standalone := $(INTEGRATION_SHARDS)
INTEGRATION_SHARDS_multiprocess := $(INTEGRATION_SHARDS)
INTEGRATION_SHARDS_multiprocess := $(filter-out awskms,$(INTEGRATION_SHARDS))

# The CI matrix is the set of (shard, topology) cells, encoded "shard:topology".
INTEGRATION_CELLS := $(foreach t,$(INTEGRATION_TOPOLOGIES),$(foreach s,$(INTEGRATION_SHARDS_$(t)),$(s):$(t)))
Expand All @@ -624,6 +639,9 @@ TOPOLOGIES_SELECTED = $(if $(filter all,$(NODE_TOPOLOGY)),$(INTEGRATION_TOPOLOGI
shards_for = $(filter $(if $(strip $(SHARD)),$(SHARD),$(INTEGRATION_SHARDS_$(1))),$(INTEGRATION_SHARDS_$(1)))
# run_pattern(topology): the selected shards' -run regexes as one alternation.
run_pattern = $(subst $(space),|,$(strip $(foreach s,$(call shards_for,$(1)),$(INTEGRATION_SHARD_$(s)))))
# compose_profiles(topology): activate optional infrastructure required by the
# selected shards for this topology.
compose_profiles = $(if $(filter awskms,$(call shards_for,$(1))),awskms,)
# Selected (shard:topology) cells, for PARALLEL fan-out.
SELECTED_CELLS = $(foreach t,$(TOPOLOGIES_SELECTED),$(foreach s,$(call shards_for,$(t)),$(s):$(t)))
# Label for project/log names: the SHARD filter joined by '-', or "all".
Expand Down Expand Up @@ -671,6 +689,7 @@ _compose-topology-%:
COMPOSE_PROJECT='$(if $(filter rollups-node-integration,$(COMPOSE_PROJECT)),rollups-node-integration-$(SUITE_LABEL)-$*,$(COMPOSE_PROJECT))' \
INTEGRATION_LOGS='integration-logs-$(SUITE_LABEL)-$*.txt' \
TEST_PATTERN="$$pattern" SHARD_NAME='$(SUITE_LABEL)-$*' NODE_TOPOLOGY='$*' \
COMPOSE_PROFILES='$(call compose_profiles,$*)' \
GOTESTSUM_FORMAT='$(COMPOSE_TOPOLOGY_GOTESTSUM_FORMAT)' \
scripts/compose-integration-run.sh

Expand All @@ -681,6 +700,7 @@ _compose-cell-%:
TEST_PATTERN='$(INTEGRATION_SHARD_$(firstword $(subst :, ,$*)))' \
SHARD_NAME='$(firstword $(subst :, ,$*))' \
NODE_TOPOLOGY='$(lastword $(subst :, ,$*))' \
COMPOSE_PROFILES='$(if $(filter awskms,$(firstword $(subst :, ,$*))),awskms,)' \
GOTESTSUM_FORMAT='$(GOTESTSUM_FORMAT)' \
scripts/compose-integration-run.sh

Expand Down Expand Up @@ -714,6 +734,14 @@ integration-test-local: build cartesi-rollups-machine-tool echo-dapp reject-loop
_local-topology-%:
@pattern='$(call run_pattern,$*)'; \
if [ -z "$$pattern" ]; then echo "skip: no applicable shards for topology '$*' (SHARD filter excludes all)"; exit 0; fi; \
if [ -n "$(filter awskms,$(SHARD))" ]; then \
if [ -z "$$LOCALSTACK_KMS_ENDPOINT" ]; then \
echo "ERROR: LOCALSTACK_KMS_ENDPOINT is required when SHARD includes awskms." >&2; \
echo "Run 'make start-awslocalstack' and export the variables it prints." >&2; \
exit 1; \
fi; \
export LOCALSTACK_KMS_REQUIRED=true; \
fi; \
cartesi-rollups-cli db init; \
test_ports="10000 10001 10002 10003 10004 10005 10006 10011 10012"; \
busy_pids="$$(for p in $$test_ports; do lsof -tiTCP:$$p -sTCP:LISTEN 2>/dev/null || true; done | sort -u | tr '\n' ' ')"; \
Expand Down
71 changes: 51 additions & 20 deletions cmd/cartesi-rollups-advancer/root/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
"github.com/cartesi/rollups-node/internal/advancer"
"github.com/cartesi/rollups-node/internal/cli"
"github.com/cartesi/rollups-node/internal/config"
"github.com/cartesi/rollups-node/internal/inspect"
"github.com/cartesi/rollups-node/internal/manager"
"github.com/cartesi/rollups-node/internal/repository/factory"
"github.com/cartesi/rollups-node/internal/version"
"github.com/cartesi/rollups-node/pkg/service"
Expand Down Expand Up @@ -79,29 +81,58 @@ func run(cmd *cobra.Command, args []string) {
ctx, cancel := context.WithTimeout(context.Background(), cfg.MaxStartupTime)
defer cancel()

createInfo := advancer.CreateInfo{
CreateInfo: service.CreateInfo{
Name: config.ServiceAdvancer,
LogLevel: config.ResolveServiceLogLevel(config.ServiceAdvancer, cfg.LogLevel),
LogColor: cfg.LogColor,
EnableSignalHandling: true,
TelemetryCreate: true,
TelemetryAddress: cfg.AdvancerTelemetryAddress,
PollInterval: cfg.AdvancerPollingInterval,
// Create shared components

name := config.ServiceAdvancer
logger := service.NewLogger(name, cfg.LogLevel, cfg.LogColor)

repo, err := factory.NewRepositoryFromConnectionString(ctx, cfg.DatabaseConnection.Raw())
cli.CheckErr(logger, err)
defer repo.Close()

machineManager := manager.NewMachineManager(
repo,
logger,
cfg.FeatureMachineHashCheckEnabled,
cfg.AdvancerInputBatchSize,
)
defer machineManager.Close()

// Create factories of services

factories := []service.FactoryFunction{
func(ctx context.Context, sup *service.Supervisor) (service.SupervisedService, error) {
return advancer.Create(ctx, &advancer.CreateInfo{
Config: *cfg,
Repository: repo,
Machines: machineManager,
Supervisor: sup,
Logger: sup.Logger,
})
},
Config: *cfg,
}
logger := service.NewServiceLogger(&createInfo.CreateInfo)
createInfo.CreateInfo.Logger = logger

var err error
createInfo.Repository, err = factory.NewRepositoryFromConnectionString(ctx, cfg.DatabaseConnection.Raw())
cli.CheckErr(logger, err)
defer createInfo.Repository.Close()
if cfg.FeatureInspectEnabled {
factories = append(factories,
func(ctx context.Context, sup *service.Supervisor) (service.SupervisedService, error) {
return inspect.Create(ctx, &inspect.CreateInfo{
Config: *cfg,
Repository: repo,
Machines: machineManager,
})
},
)
}

advancerService, err := advancer.Create(ctx, &createInfo)
supCfg := &service.SupervisorConfigs{
BaseConfigs: service.BaseConfigs{Name: name, Logger: logger},
EnableSignalHandling: true,
TelemetryCreate: true,
TelemetryAddress: cfg.AdvancerTelemetryAddress,
Factories: factories,
}
sup, err := service.NewSupervisor(ctx, supCfg)
cli.CheckErr(logger, err)
advancerService.LogConfig(createInfo.Config)

cli.CheckErr(logger, advancerService.Serve())
defer sup.Close()
cli.CheckErr(logger, sup.Serve())
}
58 changes: 23 additions & 35 deletions cmd/cartesi-rollups-claimer/root/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"github.com/cartesi/rollups-node/internal/config"
"github.com/cartesi/rollups-node/internal/repository/factory"
"github.com/cartesi/rollups-node/internal/version"
"github.com/cartesi/rollups-node/pkg/ethutil"
"github.com/cartesi/rollups-node/pkg/service"

"github.com/spf13/cobra"
Expand Down Expand Up @@ -80,41 +79,30 @@ func run(cmd *cobra.Command, args []string) {
ctx, cancel := context.WithTimeout(context.Background(), cfg.MaxStartupTime)
defer cancel()

createInfo := claimer.CreateInfo{
CreateInfo: service.CreateInfo{
Name: config.ServiceClaimer,
LogLevel: config.ResolveServiceLogLevel(config.ServiceClaimer, cfg.LogLevel),
LogColor: cfg.LogColor,
EnableSignalHandling: true,
TelemetryCreate: true,
TelemetryAddress: cfg.ClaimerTelemetryAddress,
PollInterval: cfg.ClaimerPollingInterval,
},
Config: *cfg,
}
logger := service.NewServiceLogger(&createInfo.CreateInfo)
createInfo.CreateInfo.Logger = logger

authOpt, err := config.HTTPAuthorizationOption()
cli.CheckErr(logger, err)
createInfo.EthConn, err = ethutil.NewEthClient(
ctx, cfg.BlockchainHttpEndpoint.Raw(), logger,
ethutil.RetryConfig{
MaxRetries: cfg.BlockchainHttpMaxRetries,
RetryMinWait: cfg.BlockchainHttpRetryMinWait,
RetryMaxWait: cfg.BlockchainHttpRetryMaxWait,
RequestTimeout: cfg.BlockchainHttpRequestTimeout,
}, authOpt)
cli.CheckErr(logger, err)
name := config.ServiceClaimer
logger := service.NewLogger(name, cfg.LogLevel, cfg.LogColor)

createInfo.Repository, err = factory.NewRepositoryFromConnectionString(ctx, cfg.DatabaseConnection.Raw())
repo, err := factory.NewRepositoryFromConnectionString(ctx, cfg.DatabaseConnection.Raw())
cli.CheckErr(logger, err)
defer createInfo.Repository.Close()

claimerService, err := claimer.Create(ctx, &createInfo)
cli.CheckErr(logger, err)
claimerService.LogConfig(createInfo.Config)

err = claimerService.Serve()
defer repo.Close()

supCfg := &service.SupervisorConfigs{
BaseConfigs: service.BaseConfigs{Name: name, Logger: logger},
EnableSignalHandling: true,
TelemetryCreate: true,
TelemetryAddress: cfg.ClaimerTelemetryAddress,
Factories: []service.FactoryFunction{
func(ctx context.Context, sup *service.Supervisor) (service.SupervisedService, error) {
return claimer.Create(ctx, &claimer.CreateInfo{
Config: *cfg,
Logger: sup.Logger,
Repository: repo,
})
},
},
}
sup, err := service.NewSupervisor(ctx, supCfg)
cli.CheckErr(logger, err)
defer sup.Close()
cli.CheckErr(logger, sup.Serve())
}
9 changes: 5 additions & 4 deletions cmd/cartesi-rollups-cli/root/deposit/deposit.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/cartesi/rollups-node/cmd/cartesi-rollups-cli/util"
"github.com/cartesi/rollups-node/internal/cli"
"github.com/cartesi/rollups-node/internal/config"
"github.com/cartesi/rollups-node/internal/config/auth"
"github.com/cartesi/rollups-node/pkg/contracts/iapplication"
"github.com/cartesi/rollups-node/pkg/contracts/ierc20errors"
"github.com/cartesi/rollups-node/pkg/contracts/ierc20metadata"
Expand Down Expand Up @@ -113,7 +114,7 @@ func runERC20(cmd *cobra.Command, args []string) {
cobra.CheckErr(err)
chainID, err := client.ChainID(ctx)
cobra.CheckErr(err)
txOpts, err := cli.GetTransactOpts(ctx, chainID)
txOptsFactory, err := auth.GetTransactOptsFactory(ctx, chainID)
cobra.CheckErr(err)

if !skipConfirmation {
Expand All @@ -124,7 +125,7 @@ func runERC20(cmd *cobra.Command, args []string) {
" token: %s\n"+
" amount: %s\n"+
" approve: %t\n",
txOpts.From, appAddr, portalAddr, tokenAddr, amount.String(), approveParam)
txOptsFactory.From(), appAddr, portalAddr, tokenAddr, amount.String(), approveParam)
confirmed, promptErr := cli.ConfirmPrompt("Do you want to continue?")
cobra.CheckErr(promptErr)
if !confirmed {
Expand All @@ -137,7 +138,7 @@ func runERC20(cmd *cobra.Command, args []string) {
if approveParam {
token, err := ierc20metadata.NewIERC20Metadata(tokenAddr, client)
cobra.CheckErr(err)
approveOpts, err := cli.GetTransactOpts(ctx, chainID)
approveOpts, err := cli.GetTransactOptsFromFactory(ctx, txOptsFactory)
cobra.CheckErr(err)
tx, err := token.Approve(approveOpts, portalAddr, amount)
cobra.CheckErr(cli.DecorateRevert(err,
Expand All @@ -153,7 +154,7 @@ func runERC20(cmd *cobra.Command, args []string) {

portal, err := ierc20portal.NewIERC20Portal(portalAddr, client)
cobra.CheckErr(err)
depositOpts, err := cli.GetTransactOpts(ctx, chainID)
depositOpts, err := cli.GetTransactOptsFromFactory(ctx, txOptsFactory)
cobra.CheckErr(err)
tx, err := portal.DepositERC20Tokens(depositOpts, tokenAddr, appAddr, amount, execData)
// The revert can come from three layers: the portal itself
Expand Down
53 changes: 20 additions & 33 deletions cmd/cartesi-rollups-evm-reader/root/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"github.com/cartesi/rollups-node/internal/evmreader"
"github.com/cartesi/rollups-node/internal/repository/factory"
"github.com/cartesi/rollups-node/internal/version"
"github.com/cartesi/rollups-node/pkg/ethutil"
"github.com/cartesi/rollups-node/pkg/service"

"github.com/spf13/cobra"
Expand Down Expand Up @@ -80,42 +79,30 @@ func run(cmd *cobra.Command, args []string) {
ctx, cancel := context.WithTimeout(context.Background(), cfg.MaxStartupTime)
defer cancel()

createInfo := evmreader.CreateInfo{
CreateInfo: service.CreateInfo{
Name: config.ServiceEvmReader,
LogLevel: config.ResolveServiceLogLevel(config.ServiceEvmReader, cfg.LogLevel),
LogColor: cfg.LogColor,
EnableSignalHandling: true,
TelemetryCreate: true,
TelemetryAddress: cfg.EvmReaderTelemetryAddress,
PollInterval: cfg.EvmReaderPollingInterval,
},
Config: *cfg,
}
logger := service.NewServiceLogger(&createInfo.CreateInfo)
createInfo.CreateInfo.Logger = logger

var err error
authOpt, err := config.HTTPAuthorizationOption()
cli.CheckErr(logger, err)
createInfo.EthClient, err = ethutil.NewEthClient(
ctx, cfg.BlockchainHttpEndpoint.Raw(), logger,
ethutil.RetryConfig{
MaxRetries: cfg.BlockchainHttpMaxRetries,
RetryMinWait: cfg.BlockchainHttpRetryMinWait,
RetryMaxWait: cfg.BlockchainHttpRetryMaxWait,
RequestTimeout: cfg.BlockchainHttpRequestTimeout,
}, authOpt)
cli.CheckErr(logger, err)
name := config.ServiceEvmReader
logger := service.NewLogger(name, cfg.LogLevel, cfg.LogColor)

repo, err := factory.NewRepositoryFromConnectionString(ctx, cfg.DatabaseConnection.Raw())
cli.CheckErr(logger, err)
defer repo.Close()
createInfo.Repository = repo

readerService, err := evmreader.Create(ctx, &createInfo)
supCfg := &service.SupervisorConfigs{
BaseConfigs: service.BaseConfigs{Name: name, Logger: logger},
EnableSignalHandling: true,
TelemetryCreate: true,
TelemetryAddress: cfg.EvmReaderTelemetryAddress,
Factories: []service.FactoryFunction{
func(ctx context.Context, sup *service.Supervisor) (service.SupervisedService, error) {
return evmreader.Create(ctx, &evmreader.CreateInfo{
Config: *cfg,
Logger: sup.Logger,
Repository: repo,
})
},
},
}
sup, err := service.NewSupervisor(ctx, supCfg)
cli.CheckErr(logger, err)
readerService.LogConfig(createInfo.Config)

cli.CheckErr(logger, readerService.Serve())
defer sup.Close()
cli.CheckErr(logger, sup.Serve())
}
Loading