Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
d2bcdcf
refactor(contracts): rename vars in Makefile
guidanoli Jul 3, 2025
1f92e01
feat(contracts): download Rollups PRT contracts artifact
guidanoli Jul 3, 2025
5b6bfe2
refactor(contracts): rename vars in Go bindings generation code
guidanoli Jul 3, 2025
41c9a33
feat(contracts): generate bindings for Rollups PRT contracts
guidanoli Jul 3, 2025
ea2fcd0
feat(devnet): add Rollups PRT contracts to devnet
guidanoli Jul 3, 2025
24ecd9d
feat(cli): add PRT consensus to deploy application
mpolitzer Jul 10, 2025
63e48da
feat(prt): add PRT service boilerplate
vfusco Aug 15, 2025
2535ebf
feat(prt): modify database and models to support PRT epoch data
vfusco Sep 6, 2025
910d30d
fix(evmreader): handle misconfigured app with epoch length of zero
vfusco Sep 10, 2025
6bc7e33
feat(evmreader): add support for PRT applications
vfusco Sep 17, 2025
015c3bd
feat(prt): modify database and models to support PRT tournament data
vfusco Sep 20, 2025
ecd0ecd
feat(prt): initial implementation of the PRT service
vfusco Sep 20, 2025
e7c964e
fix: ethutil filter comment typo
vfusco Oct 6, 2025
1183e9f
feat(merkle): add builder on merkle trees data structure
mpolitzer Sep 9, 2025
2f5b00b
feat: build PRT epoch commitment
vfusco Dec 17, 2025
166b186
fix: type of time values is Duration
mpolitzer Dec 17, 2025
434d59c
fix: respect max_retries and subscription_timeout
mpolitzer Dec 17, 2025
6854500
feat: add build root children from proof
mpolitzer Dec 18, 2025
0d5827b
feat: DaveConsensus initial settle and joinTournament
vfusco Dec 22, 2025
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
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ cartesi-rollups-node
cartesi-rollups-advancer
cartesi-rollups-validator
/rollups-contracts
/rollups-prt-contracts
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ machine-snapshot/**
/cartesi-rollups-validator
/cartesi-rollups-claimer
/cartesi-rollups-jsonrpc-api
/cartesi-rollups-prt
/rollups-contracts
/rollups-prt-contracts
/applications
/test/downloads
/snapshots
67 changes: 52 additions & 15 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,14 @@ TARGET_OS?=$(shell uname)
export TARGET_OS

ROLLUPS_NODE_VERSION := 2.0.0-alpha.8
CONTRACTS_VERSION := 2.1.1
CONTRACTS_URL:=https://github.com/cartesi/rollups-contracts/releases/download/
CONTRACTS_ARTIFACT:=rollups-contracts-$(CONTRACTS_VERSION)-artifacts.tar.gz
CONTRACTS_SHA256:=2e7a105d656de2adafad6439a5ff00f35b997aaf27972bd1becc33dea8817861
ROLLUPS_CONTRACTS_VERSION := 2.1.1
ROLLUPS_CONTRACTS_URL:=https://github.com/cartesi/rollups-contracts/releases/download/
ROLLUPS_CONTRACTS_ARTIFACT:=rollups-contracts-$(ROLLUPS_CONTRACTS_VERSION)-artifacts.tar.gz
ROLLUPS_CONTRACTS_SHA256:=2e7a105d656de2adafad6439a5ff00f35b997aaf27972bd1becc33dea8817861
ROLLUPS_PRT_CONTRACTS_VERSION := 2.0.1
ROLLUPS_PRT_CONTRACTS_URL:=https://github.com/cartesi/dave/releases/download/
ROLLUPS_PRT_CONTRACTS_ARTIFACT:=cartesi-rollups-prt-contract-artifacts.tar.gz
ROLLUPS_PRT_CONTRACTS_SHA256:=8625acd474b0d2ca5613028d0896b72f1b7cdda8a10a889e90e7c68c671006df

IMAGE_TAG ?= devel

Expand Down Expand Up @@ -55,7 +59,7 @@ DOCKER_PLATFORM=--platform $(BUILD_PLATFORM)
endif

# Go artifacts
GO_ARTIFACTS := cartesi-rollups-node cartesi-rollups-cli cartesi-rollups-evm-reader cartesi-rollups-advancer cartesi-rollups-validator cartesi-rollups-claimer cartesi-rollups-jsonrpc-api
GO_ARTIFACTS := $(addprefix cartesi-rollups-,node cli evm-reader advancer validator claimer jsonrpc-api prt)

# fixme(vfusco): path on all oses
CGO_CFLAGS:= -I$(PREFIX)/include
Expand All @@ -72,8 +76,27 @@ ifeq ($(BUILD_TYPE),debug)
endif

GO_TEST_PACKAGES ?= ./...
GO_TEST_FLAGS ?=

VERBOSE ?=
ifeq ($(VERBOSE),true)
GO_BUILD_PARAMS += -v
GO_TEST_FLAGS += -v
endif

TEST_PATTERN ?=
ifneq ($(TEST_PATTERN),)
GO_TEST_FLAGS += -run $(TEST_PATTERN)
endif

TEST_PACKAGES ?=
ifneq ($(TEST_PACKAGES),)
GO_TEST_PACKAGES := $(addprefix ./, $(addsuffix /..., $(subst :, ,$(TEST_PACKAGES))))
endif


ROLLUPS_CONTRACTS_ABI_BASEDIR:= rollups-contracts/
ROLLUPS_PRT_CONTRACTS_ABI_BASEDIR:= rollups-prt-contracts/

all: build

Expand All @@ -91,11 +114,12 @@ env:
@echo export CARTESI_BLOCKCHAIN_DEFAULT_BLOCK="latest"
@echo export CARTESI_BLOCKCHAIN_HTTP_ENDPOINT="http://localhost:8545"
@echo export CARTESI_BLOCKCHAIN_WS_ENDPOINT="ws://localhost:8545"
@echo export CARTESI_BLOCKCHAIN_ID="13370"
@echo export CARTESI_BLOCKCHAIN_ID="31337"
@echo export CARTESI_CONTRACTS_INPUT_BOX_ADDRESS="0x1b51e2992A2755Ba4D6F7094032DF91991a0Cfac"
@echo export CARTESI_CONTRACTS_AUTHORITY_FACTORY_ADDRESS="0x5a3368b30174d389aFd205a46bAd35BBE6709b8a"
@echo export CARTESI_CONTRACTS_APPLICATION_FACTORY_ADDRESS="0x26E758238CB6eC5aB70ce0dd52aF2d7b82e1972E"
@echo export CARTESI_CONTRACTS_SELF_HOSTED_APPLICATION_FACTORY_ADDRESS="0x870240e83b1181b419f18303D4ccC56574De2931"
@echo export CARTESI_CONTRACTS_DAVE_APP_FACTORY_ADDRESS="0x96cD319eBD67DF6b753766ec000fe639dFba9F6b"
@echo export CARTESI_AUTH_MNEMONIC=\"test test test test test test test test test test test junk\"
@echo export CARTESI_DATABASE_CONNECTION="postgres://postgres:password@localhost:5432/rollupsdb?sslmode=disable"
@echo export CARTESI_SNAPSHOTS_DIR="snapshots"
Expand All @@ -113,7 +137,7 @@ $(GO_ARTIFACTS):
tidy-go:
@go mod tidy

generate: $(ROLLUPS_CONTRACTS_ABI_BASEDIR)/.stamp ## Generate the file that are committed to the repo
generate: contracts ## Generate the file that are committed to the repo
@echo "Generating Go files"
@go generate ./internal/... ./pkg/...

Expand All @@ -126,16 +150,25 @@ check-generate: generate ## Check whether the generated files are in sync
exit 1; \
fi

contracts: $(ROLLUPS_CONTRACTS_ABI_BASEDIR)/.stamp ## Export the rollups-contracts artifacts
contracts: $(ROLLUPS_CONTRACTS_ABI_BASEDIR)/.stamp $(ROLLUPS_PRT_CONTRACTS_ABI_BASEDIR)/.stamp ## Export the contract artifacts

$(ROLLUPS_CONTRACTS_ABI_BASEDIR)/.stamp:
@echo "Downloading rollups-contracts artifacts"
@mkdir -p $(ROLLUPS_CONTRACTS_ABI_BASEDIR)
@curl -sSL $(CONTRACTS_URL)/v$(CONTRACTS_VERSION)/$(CONTRACTS_ARTIFACT) -o $(CONTRACTS_ARTIFACT)
@echo "$(CONTRACTS_SHA256) $(CONTRACTS_ARTIFACT)" | shasum -a 256 --check > /dev/null
@tar -zxf $(CONTRACTS_ARTIFACT) -C $(ROLLUPS_CONTRACTS_ABI_BASEDIR)
@curl -sSL $(ROLLUPS_CONTRACTS_URL)/v$(ROLLUPS_CONTRACTS_VERSION)/$(ROLLUPS_CONTRACTS_ARTIFACT) -o $(ROLLUPS_CONTRACTS_ARTIFACT)
@echo "$(ROLLUPS_CONTRACTS_SHA256) $(ROLLUPS_CONTRACTS_ARTIFACT)" | shasum -a 256 --check > /dev/null
@tar -zxf $(ROLLUPS_CONTRACTS_ARTIFACT) -C $(ROLLUPS_CONTRACTS_ABI_BASEDIR)
@touch $@
@rm -f $(ROLLUPS_CONTRACTS_ARTIFACT)

$(ROLLUPS_PRT_CONTRACTS_ABI_BASEDIR)/.stamp:
@echo "Downloading rollups-prt-contracts artifacts"
@mkdir -p $(ROLLUPS_PRT_CONTRACTS_ABI_BASEDIR)
@curl -sSL $(ROLLUPS_PRT_CONTRACTS_URL)/v$(ROLLUPS_PRT_CONTRACTS_VERSION)/$(ROLLUPS_PRT_CONTRACTS_ARTIFACT) -o $(ROLLUPS_PRT_CONTRACTS_ARTIFACT)
@echo "$(ROLLUPS_PRT_CONTRACTS_SHA256) $(ROLLUPS_PRT_CONTRACTS_ARTIFACT)" | shasum -a 256 --check > /dev/null
@tar -zxf $(ROLLUPS_PRT_CONTRACTS_ARTIFACT) -C $(ROLLUPS_PRT_CONTRACTS_ABI_BASEDIR)
@touch $@
@rm -f $(CONTRACTS_ARTIFACT)
@rm $(ROLLUPS_PRT_CONTRACTS_ARTIFACT)

migrate: ## Run migration on development database
@echo "Running PostgreSQL migration"
Expand All @@ -160,8 +193,8 @@ clean-go: ## Clean Go artifacts

clean-contracts: ## Clean contract artifacts
@echo "Cleaning contract artifacts"
@rm -rf rollups-contracts
@rm -f $(CONTRACTS_ARTIFACT)
@rm -rf $(ROLLUPS_CONTRACTS_ABI_BASEDIR) $(ROLLUPS_PRT_CONTRACTS_ABI_BASEDIR)
@rm -f $(ROLLUPS_CONTRACTS_ARTIFACT) $(ROLLUPS_PRT_CONTRACTS_ARTIFACT)

clean-docs: ## Clean the documentation
@echo "Cleaning the documentation"
Expand Down Expand Up @@ -191,7 +224,7 @@ test: unit-test ## Execute all tests
unit-test: ## Execute go unit tests
@echo "Running go unit tests"
@go clean -testcache
@go test -p 1 $(GO_BUILD_PARAMS) $(GO_TEST_PACKAGES)
@go test -p 1 $(GO_BUILD_PARAMS) $(GO_TEST_FLAGS) $(GO_TEST_PACKAGES)

integration-test: ## Execute e2e tests
@echo "Running end-to-end tests"
Expand Down Expand Up @@ -230,6 +263,10 @@ deploy-exception-dapp: applications/exception-dapp ## Deploy exception-dapp test
@echo "Deploying exception-dapp test application"
@./cartesi-rollups-cli deploy application exception-dapp applications/exception-dapp/

deploy-prt-echo-dapp: applications/echo-dapp ## Deploy echo-dapp test application
@echo "Deploying echo-dapp test application"
@./cartesi-rollups-cli deploy application prt-echo-dapp applications/echo-dapp/ --prt

# Temporary test dependencies target while we are not using distribution packages
DOWNLOADS_DIR = test/downloads
CARTESI_TEST_MACHINE_IMAGES = $(DOWNLOADS_DIR)/linux.bin
Expand Down
39 changes: 25 additions & 14 deletions cmd/cartesi-rollups-cli/root/app/register/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ var (
inputBoxAddressFromEnv bool
dataAvailability string
enableMachineHashCheck bool
applicationTypePRT bool
disabled bool
printAsJSON bool
executionParametersFileParam string
Expand All @@ -75,7 +76,7 @@ func init() {
"Application template hash. (DO NOT USE IN PRODUCTION)\nThis value is retrieved from the application contract",
)

Cmd.Flags().Uint64VarP(&epochLength, "epoch-length", "e", 10, // nolint: mnd
Cmd.Flags().Uint64VarP(&epochLength, "epoch-length", "e", 0, // nolint: mnd
"Consensus Epoch length. (DO NOT USE IN PRODUCTION)\nThis value is retrieved from the consensus contract",
)

Expand All @@ -97,6 +98,8 @@ func init() {
"Enable or disable machine hash check (DO NOT DISABLE IN PRODUCTION)")
cobra.CheckErr(viper.BindPFlag(config.FEATURE_MACHINE_HASH_CHECK_ENABLED, Cmd.Flags().Lookup("machine-hash-check")))

Cmd.Flags().BoolVarP(&applicationTypePRT, "prt", "", false, "Register as PRT application.")

origHelpFunc := Cmd.HelpFunc()
Cmd.SetHelpFunc(func(command *cobra.Command, strings []string) {
command.Flags().Lookup("verbose").Hidden = false
Expand Down Expand Up @@ -165,7 +168,7 @@ func run(cmd *cobra.Command, args []string) {
}
}

if !cmd.Flags().Changed("epoch-length") {
if !cmd.Flags().Changed("epoch-length") && !applicationTypePRT {
epochLength, err = getEpochLength(ctx, consensus)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to get epoch length from consensus: %v\n", err)
Expand Down Expand Up @@ -201,19 +204,27 @@ func run(cmd *cobra.Command, args []string) {
os.Exit(1)
}

consensusType := model.Consensus_Authority
if applicationTypePRT {
consensusType = model.Consensus_PRT
}

application := model.Application{
Name: validName,
IApplicationAddress: address,
IConsensusAddress: consensus,
IInputBoxAddress: *inputBoxAddress,
TemplateURI: templatePath,
TemplateHash: parsedTemplateHash,
EpochLength: epochLength,
DataAvailability: encodedDA,
State: applicationState,
IInputBoxBlock: inputBoxBlockNumber,
LastInputCheckBlock: 0,
LastOutputCheckBlock: 0,
Name: validName,
IApplicationAddress: address,
IConsensusAddress: consensus,
IInputBoxAddress: *inputBoxAddress,
TemplateURI: templatePath,
TemplateHash: parsedTemplateHash,
EpochLength: epochLength,
DataAvailability: encodedDA,
ConsensusType: consensusType,
State: applicationState,
IInputBoxBlock: inputBoxBlockNumber,
LastEpochCheckBlock: 0,
LastInputCheckBlock: 0,
LastOutputCheckBlock: 0,
LastTournamentCheckBlock: 0,
}

// load execution parameters from a file?
Expand Down
68 changes: 66 additions & 2 deletions cmd/cartesi-rollups-cli/root/deploy/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ var (
applicationTemplateHashParam string
factoryAddressParam string
executionParametersFileParam string
prtFactoryAddressParam string
deploymentTypePRT bool
)

var applicationCmd = &cobra.Command{
Expand All @@ -52,7 +54,8 @@ Supported Environment Variables:
CARTESI_BLOCKCHAIN_HTTP_ENDPOINT Blockchain HTTP endpoint
CARTESI_CONTRACTS_INPUT_BOX_ADDRESS Input Box contract address
CARTESI_CONTRACTS_APPLICATION_FACTORY_ADDRESS Application Factory address
CARTESI_CONTRACTS_SELF_HOSTED_APPLICATION_FACTORY_ADDRESS Self Hosted Application Factory address`,
CARTESI_CONTRACTS_SELF_HOSTED_APPLICATION_FACTORY_ADDRESS Self Hosted Application Factory address
CARTESI_CONTRACTS_DAVE_APP_FACTORY_ADDRESS Dave Application Factory address`,
}

const applicationExamples = `
Expand All @@ -62,6 +65,9 @@ const applicationExamples = `
# deploy an application contract using an existing consensus, then register the application
- cartesi-rollups-cli deploy application echo-dapp applications/echo-dapp/ --consensus=0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

# deploy an application contract with a PRT consensus, then register the application
- cli deploy application echo-dapp applications/echo-dapp/ --prt

# deploy but don't register into the database
- cartesi-rollups-cli deploy application echo-dapp applications/echo-dapp/ --register=false

Expand All @@ -76,6 +82,8 @@ func init() {
"Consensus address. A new authority consensus will be created if this field is left empty.")
applicationCmd.Flags().StringVarP(&factoryAddressParam, "factory", "f", "",
"Application factory address. Default value is retrieved from configuration.")
applicationCmd.Flags().StringVarP(&prtFactoryAddressParam, "prt-factory", "", "",
"PRT Application factory address. Default value is retrieved from configuration.")
applicationCmd.Flags().StringVarP(&applicationOwnerAddressParam, "application-owner", "o", "",
"Application owner address. If not defined, it will be derived from the auth method.")
applicationCmd.Flags().StringVarP(&applicationDataAvailabilityParam, "data-availability", "d", "",
Expand All @@ -90,6 +98,8 @@ func init() {
"Start processing the application, requires 'register=true'.")
applicationCmd.Flags().StringVarP(&authorityOwnerAddressParam, "authority-owner", "O", "",
"Authority Owner address. If not defined, it will be derived from the auth method.")
applicationCmd.Flags().BoolVarP(&deploymentTypePRT, "prt", "", false,
"Deploy a PRT application.")

origHelpFunc := applicationCmd.HelpFunc()
applicationCmd.SetHelpFunc(func(command *cobra.Command, strings []string) {
Expand Down Expand Up @@ -146,7 +156,9 @@ func runDeployApplication(cmd *cobra.Command, args []string) {
}

var deployment ethutil.IApplicationDeployment
if deploySelfhosted := !cmd.Flags().Changed("consensus"); deploySelfhosted {
if deploymentTypePRT {
deployment, err = buildPrtApplicationDeployment(cmd, args)
} else if deploySelfhosted := !cmd.Flags().Changed("consensus"); deploySelfhosted {
deployment, err = buildSelfhostedApplicationDeployment(ctx, cmd, args, client, txOpts)
} else {
deployment, err = buildApplicationOnlyDeployment(ctx, cmd, args, client, txOpts)
Expand All @@ -162,6 +174,7 @@ func runDeployApplication(cmd *cobra.Command, args []string) {
application.Name = applicationName
application.TemplateURI = templateURI
application.State = model.ApplicationState_Disabled
application.ConsensusType = model.Consensus_Authority
if applicationEnableParam {
application.State = model.ApplicationState_Enabled
}
Expand Down Expand Up @@ -235,6 +248,16 @@ func runDeployApplication(cmd *cobra.Command, args []string) {
application.EpochLength = res.Deployment.EpochLength
application.DataAvailability = res.Deployment.DataAvailability
application.IInputBoxBlock = res.Deployment.IInputBoxBlock

case *ethutil.PRTApplicationDeploymentResult:
application.IApplicationAddress = res.ApplicationAddress
application.IConsensusAddress = res.DaveConsensusAddress
application.IInputBoxAddress = res.InputBoxAddress
application.TemplateHash = res.Deployment.TemplateHash
application.EpochLength = res.Deployment.EpochLength
application.DataAvailability = res.DataAvailability
application.IInputBoxBlock = res.IInputBoxBlock
application.ConsensusType = model.Consensus_PRT
default:
panic("unimplemented deployment type\n")
}
Expand Down Expand Up @@ -444,11 +467,52 @@ func buildApplicationOnlyDeployment(
return nil, fmt.Errorf("error input box address has no code: %v", request.InputBoxAddress)
}

request.Salt, err = ethutil.ParseSalt(saltParam)
if err != nil {
return nil, fmt.Errorf("error on parameter salt: %w", err)
}

request.Verbose = verboseParam

request.Consensus, request.EpochLength, err = customConsensus(client, applicationConsensusAddressParam)
if err != nil {
return nil, fmt.Errorf("error on parameter consensus: %w", err)
}

return request, nil
}

func buildPrtApplicationDeployment(
cmd *cobra.Command,
args []string,
) (
*ethutil.PRTApplicationDeployment,
error,
) {
var err error
request := &ethutil.PRTApplicationDeployment{}
if !cmd.Flags().Changed("prt-factory") {
request.FactoryAddress, err = config.GetContractsDaveAppFactoryAddress()
} else {
request.FactoryAddress, err = parseHexAddress(factoryAddressParam)
}
if err != nil {
return nil, fmt.Errorf("error on parameter factory: %w", err)
}

if !cmd.Flags().Changed("template-hash") {
if len(args) >= 2 { // args[1] is mandatory if `template-hash` was absent
request.TemplateHash, err = readHash(args[1])
} else {
err = fmt.Errorf("missing argument. One of `template-path` or `template-hash` is required")
}
} else {
request.TemplateHash, err = parseHexHash(applicationTemplateHashParam)
}
if err != nil {
return nil, fmt.Errorf("error on parameter template-hash: %w", err)
}

request.Salt, err = ethutil.ParseSalt(saltParam)
if err != nil {
return nil, fmt.Errorf("error on parameter salt: %w", err)
Expand Down
2 changes: 1 addition & 1 deletion cmd/cartesi-rollups-cli/root/read/epochs/epochs.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func run(cmd *cobra.Command, args []string) {
if err := status.Scan(statusFilter); err != nil {
cobra.CheckErr(fmt.Errorf("invalid status filter: %w", err))
}
filter.Status = &status
filter.Status = []model.EpochStatus{status}
}

// Limit is validated in PreRunE
Expand Down
Loading
Loading