Skip to content

Commit 66cd753

Browse files
committed
feat(cli): add PRT consensus to deploy application (WIP)
1 parent ab6f86b commit 66cd753

5 files changed

Lines changed: 207 additions & 10 deletions

File tree

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ env:
9797
@echo export CARTESI_CONTRACTS_AUTHORITY_FACTORY_ADDRESS="0xC7003566dD09Aa0fC0Ce201aC2769aFAe3BF0051"
9898
@echo export CARTESI_CONTRACTS_APPLICATION_FACTORY_ADDRESS="0xc7006f70875BaDe89032001262A846D3Ee160051"
9999
@echo export CARTESI_CONTRACTS_SELF_HOSTED_APPLICATION_FACTORY_ADDRESS="0xc700285Ab555eeB5201BC00CFD4b2CC8DED90051"
100+
@echo export CARTESI_CONTRACTS_PRT_FACTORY_ADDRESS="0x6e362c9458fE812D4aA796651C64D02C87AbD1cB"
100101
@echo export CARTESI_AUTH_MNEMONIC=\"test test test test test test test test test test test junk\"
101102
@echo export CARTESI_DATABASE_CONNECTION="postgres://postgres:password@localhost:5432/rollupsdb?sslmode=disable"
102103
@echo export CARTESI_SNAPSHOTS_DIR="snapshots"

cmd/cartesi-rollups-cli/root/deploy/application.go

Lines changed: 63 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ var (
2929
applicationRegisterParam bool
3030
applicationTemplateHashParam string
3131
factoryAddressParam string
32+
prtFactoryAddressParam string
33+
deploymentTypePRT bool
3234
)
3335

3436
var applicationCmd = &cobra.Command{
@@ -59,6 +61,9 @@ const applicationExamples = `
5961
# deploy an application contract using an existing consensus, then register the application
6062
- cli deploy application echo-dapp applications/echo-dapp/ --consensus=0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
6163
64+
# deploy an application contract with a PRT consensus, then register the application
65+
- cli deploy application echo-dapp applications/echo-dapp/ --prt
66+
6267
# deploy but don't register into the database
6368
- cli deploy application echo-dapp applications/echo-dapp/ --register=false
6469
@@ -73,6 +78,8 @@ func init() {
7378
"Consensus address. A new authority consensus will be created if this field is left empty.")
7479
applicationCmd.Flags().StringVarP(&factoryAddressParam, "factory", "f", "",
7580
"Application factory address. Default value is retrieved from configuration.")
81+
applicationCmd.Flags().StringVarP(&prtFactoryAddressParam, "prt-factory", "", "",
82+
"PRT Application factory address. Default value is retrieved from configuration.")
7683
applicationCmd.Flags().StringVarP(&applicationOwnerAddressParam, "application-owner", "o", "",
7784
"Application owner address. If not defined, it will be derived from the auth method.")
7885
applicationCmd.Flags().StringVarP(&applicationDataAvailabilityParam, "data-availability", "d", "",
@@ -85,6 +92,8 @@ func init() {
8592
"Start processing the application, requires 'register=true'.")
8693
applicationCmd.Flags().StringVarP(&authorityOwnerAddressParam, "authority-owner", "O", "",
8794
"Authority Owner address. If not defined, it will be derived from the auth method.")
95+
applicationCmd.Flags().BoolVarP(&deploymentTypePRT, "prt", "", false,
96+
"Deploy a PRT application.")
8897

8998
origHelpFunc := applicationCmd.HelpFunc()
9099
applicationCmd.SetHelpFunc(func(command *cobra.Command, strings []string) {
@@ -141,7 +150,9 @@ func runDeployApplication(cmd *cobra.Command, args []string) {
141150
}
142151

143152
var deployment ethutil.IApplicationDeployment
144-
if deploySelfhosted := !cmd.Flags().Changed("consensus"); deploySelfhosted {
153+
if deploymentTypePRT {
154+
deployment, err = buildPrtApplicationDeployment(cmd, args, client, txOpts)
155+
} else if deploySelfhosted := !cmd.Flags().Changed("consensus"); deploySelfhosted {
145156
deployment, err = buildSelfhostedApplicationDeployment(cmd, args, client, txOpts)
146157
} else {
147158
deployment, err = buildApplicationOnlyDeployment(cmd, args, client, txOpts)
@@ -339,7 +350,7 @@ func buildSelfhostedApplicationDeployment(
339350
return request, nil
340351
}
341352

342-
func buildApplicationOnlyDeployment(
353+
func buildApplicationOnlyDeploymentWithoutConsensus(
343354
cmd *cobra.Command,
344355
args []string,
345356
client *ethclient.Client,
@@ -360,11 +371,6 @@ func buildApplicationOnlyDeployment(
360371
return nil, fmt.Errorf("error on parameter factory: %w", err)
361372
}
362373

363-
request.Consensus, err = parseHexAddress(applicationConsensusAddressParam)
364-
if err != nil {
365-
return nil, fmt.Errorf("error on parameter consensus: %w", err)
366-
}
367-
368374
if !cmd.Flags().Changed("template-hash") {
369375
if len(args) >= 2 { // args[1] is mandatory if `template-hash` was absent
370376
request.TemplateHash, err = readHash(args[1])
@@ -402,17 +408,64 @@ func buildApplicationOnlyDeployment(
402408
return nil, fmt.Errorf("error on parameter data-availability: %w", err)
403409
}
404410

411+
request.Salt, err = ethutil.ParseSalt(saltParam)
412+
if err != nil {
413+
return nil, fmt.Errorf("error on parameter salt: %w", err)
414+
}
415+
416+
request.Verbose = verboseParam
417+
return request, nil
418+
}
419+
420+
func buildApplicationOnlyDeployment(
421+
cmd *cobra.Command,
422+
args []string,
423+
client *ethclient.Client,
424+
txOpts *bind.TransactOpts,
425+
) (
426+
*ethutil.ApplicationDeployment,
427+
error,
428+
) {
429+
request, err := buildApplicationOnlyDeploymentWithoutConsensus(cmd, args, client, txOpts)
430+
431+
request.Consensus, err = parseHexAddress(applicationConsensusAddressParam)
432+
if err != nil {
433+
return nil, fmt.Errorf("error on parameter consensus: %w", err)
434+
}
435+
405436
request.Consensus, request.EpochLength, err = customConsensus(client, applicationConsensusAddressParam)
406437
if err != nil {
407438
return nil, fmt.Errorf("error on parameter consensus: %w", err)
408439
}
409440

410-
request.Salt, err = ethutil.ParseSalt(saltParam)
441+
return request, nil
442+
}
443+
444+
func buildPrtApplicationDeployment(
445+
cmd *cobra.Command,
446+
args []string,
447+
client *ethclient.Client,
448+
txOpts *bind.TransactOpts,
449+
) (
450+
*ethutil.PRTDeployment,
451+
error,
452+
) {
453+
var err error
454+
request := &ethutil.PRTDeployment{}
455+
if !cmd.Flags().Changed("prt-factory") {
456+
request.FactoryAddress, err = config.GetContractsPrtFactoryAddress()
457+
} else {
458+
request.FactoryAddress, err = parseHexAddress(factoryAddressParam)
459+
}
411460
if err != nil {
412-
return nil, fmt.Errorf("error on parameter salt: %w", err)
461+
return nil, fmt.Errorf("error on parameter factory: %w", err)
462+
}
463+
464+
request.App, err = buildApplicationOnlyDeploymentWithoutConsensus(cmd, args, client, txOpts)
465+
if err != nil {
466+
return nil, fmt.Errorf("error on application: %w", err)
413467
}
414468

415-
request.Verbose = verboseParam
416469
return request, nil
417470
}
418471

internal/config/generate/Config.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,13 @@ Address of the SelfHostedApplicationFactory contract. Not required, used only by
194194
omit = true
195195
used-by = ["cli"]
196196

197+
[contracts.CARTESI_CONTRACTS_PRT_CONSENSUS_FACTORY_ADDRESS]
198+
go-type = "Address"
199+
description = """
200+
Address of the PRT consensus contract. Not required, used only by the CLI and tests"""
201+
omit = true
202+
used-by = ["cli"]
203+
197204
#
198205
# Snapshot
199206
#

internal/config/generated.go

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/ethutil/prt.go

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// (c) Cartesi and individual authors (see AUTHORS)
2+
// SPDX-License-Identifier: Apache-2.0 (see LICENSE)
3+
package ethutil
4+
5+
import (
6+
"context"
7+
"fmt"
8+
"math/big"
9+
10+
"github.com/cartesi/rollups-node/pkg/contracts/daveconsensusfactory"
11+
"github.com/cartesi/rollups-node/pkg/contracts/iapplication"
12+
"github.com/ethereum/go-ethereum/accounts/abi/bind"
13+
"github.com/ethereum/go-ethereum/common"
14+
"github.com/ethereum/go-ethereum/core/types"
15+
"github.com/ethereum/go-ethereum/ethclient"
16+
)
17+
18+
type PRTDeployment struct {
19+
App *ApplicationDeployment
20+
FactoryAddress common.Address
21+
}
22+
23+
type PRTDeploymentResult struct {
24+
}
25+
26+
func (me *PRTDeployment) String() string {
27+
result := ""
28+
result += me.App.String()
29+
if me.App.Verbose {
30+
result += fmt.Sprintf("\tPRT factory address: %v\n", me.FactoryAddress)
31+
result += fmt.Sprintf("\tPRT consensus address: %v\n", me.App.Consensus)
32+
}
33+
return result
34+
}
35+
36+
func (me *PRTDeployment) deployPRT(
37+
ctx context.Context,
38+
client *ethclient.Client,
39+
txOpts *bind.TransactOpts,
40+
applicationAddress common.Address,
41+
) (common.Address, error) {
42+
zero := common.Address{}
43+
44+
factory, err := daveconsensusfactory.NewDaveConsensusFactory(me.FactoryAddress, client)
45+
if err != nil {
46+
return zero, fmt.Errorf("failed to instantiate contract: %v", err)
47+
}
48+
tx, err := factory.NewDaveConsensus(txOpts, applicationAddress, me.App.TemplateHash, me.App.Salt)
49+
if err != nil {
50+
return zero, fmt.Errorf("transaction failed: %v", err)
51+
}
52+
53+
receipt, err := bind.WaitMined(ctx, client, tx)
54+
if err != nil {
55+
return zero, fmt.Errorf("failed to wait for transaction mining: %v", err)
56+
}
57+
58+
if receipt.Status != 1 {
59+
return zero, fmt.Errorf("transaction failed")
60+
}
61+
62+
// Look for the specific event in the receipt logs
63+
for _, vLog := range receipt.Logs {
64+
// Parse log for DaveConsensusCreated event
65+
event, err := factory.ParseDaveConsensusCreated(*vLog)
66+
if err != nil {
67+
continue // Skip logs that don't match
68+
}
69+
return event.DaveConsensus, nil
70+
}
71+
return zero, fmt.Errorf("failed to find DaveConsensusCreated event in receipt logs")
72+
}
73+
74+
// Do the consensus/application dance based on: https://github.com/cartesi/dave/blob/v1.0.0/cartesi-rollups/contracts/cannonfile.prod-instance.toml
75+
func (me *PRTDeployment) Deploy(
76+
ctx context.Context,
77+
client *ethclient.Client,
78+
txOpts *bind.TransactOpts,
79+
) (common.Address, IApplicationDeploymentResult, error) {
80+
zero := common.Address{}
81+
82+
applicationAddress, result, err := me.App.Deploy(ctx, client, txOpts)
83+
if err != nil {
84+
return zero, nil, err
85+
}
86+
87+
me.App.Consensus, err = me.deployPRT(ctx, client, txOpts, applicationAddress)
88+
if err != nil {
89+
return zero, nil, fmt.Errorf("failed to deploy PRT contract: %w", err)
90+
}
91+
92+
application, err := iapplication.NewIApplication(applicationAddress, client)
93+
if err != nil {
94+
return zero, nil, fmt.Errorf("failed to instantiate application: %v", err)
95+
}
96+
97+
_, err = sendTransaction(ctx, client, txOpts, big.NewInt(0), GasLimit,
98+
func(txOpts *bind.TransactOpts) (*types.Transaction, error) {
99+
return application.MigrateToOutputsMerkleRootValidator(txOpts, me.App.Consensus)
100+
},
101+
)
102+
if err != nil {
103+
return zero, nil, fmt.Errorf("failed to create a self hosted application: execution reverted")
104+
}
105+
106+
_, err = sendTransaction(ctx, client, txOpts, big.NewInt(0), GasLimit,
107+
func(txOpts *bind.TransactOpts) (*types.Transaction, error) {
108+
return application.RenounceOwnership(txOpts)
109+
},
110+
)
111+
if err != nil {
112+
return zero, nil, fmt.Errorf("failed to create a self hosted application: execution reverted")
113+
}
114+
115+
return applicationAddress, result, nil
116+
}
117+
118+
func (me *PRTDeployment) GetFactoryAddress() common.Address {
119+
return me.FactoryAddress
120+
}

0 commit comments

Comments
 (0)