Skip to content

Commit

Permalink
feat: Add Echo App end-to-end test
Browse files Browse the repository at this point in the history
Update CHANGELOG.md

Co-authored-by: Victor Yves <[email protected]>

Update CHANGELOG.md

Co-authored-by: Victor Yves <[email protected]>

Update cmd/cartesi-rollups-cli/root/send/send.go

Co-authored-by: Gabriel de Quadros Ligneul <[email protected]>

Update end-to-end-tests/client_util.go

Co-authored-by: Gabriel de Quadros Ligneul <[email protected]>

Update end-to-end-tests/echo_test.go

Co-authored-by: Victor Yves <[email protected]>

Update end-to-end-tests/client_util.go

Co-authored-by: Gabriel de Quadros Ligneul <[email protected]>
  • Loading branch information
fmoura and gligneul committed Mar 28, 2024
1 parent 8af46c9 commit 3c71fb5
Show file tree
Hide file tree
Showing 9 changed files with 541 additions and 39 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added verification to ensure the Cartesi Machine snapshot hash matches the template hash from the CartesiDApp contract
- Added support for `CARTESI_AUTH_PRIVATE_KEY` and `CARTESI_AUTH_PRIVATE_KEY_FILE`
- Added `CARTESI_AUTH_KIND` environment variable to select the blockchain authetication method
- Added structured logging with slog. Colored logs can now be enabled with `CARTESI_LOG_PRETTY` environment variable.
- Added structured logging with slog. Colored logs can now be enabled with `CARTESI_LOG_PRETTY` environment variable
- Added Rollps end-to-end test using Echo Dapp

### Changed

Expand Down
24 changes: 23 additions & 1 deletion cmd/cartesi-rollups-cli/root/deps/deps.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ package deps
import (
"context"
"log/slog"
"os"
"os/signal"
"syscall"

"github.com/cartesi/rollups-node/internal/deps"
"github.com/lmittmann/tint"
"github.com/mattn/go-isatty"
"github.com/spf13/cobra"
)

Expand All @@ -24,6 +27,7 @@ const examples = `# Run all deps:
cartesi-rollups-cli run-deps`

var depsConfig = deps.NewDefaultDepsConfig()
var verbose = false

func init() {
Cmd.Flags().StringVar(&depsConfig.Postgres.DockerImage, "postgres-docker-image",
Expand All @@ -44,13 +48,31 @@ func init() {

Cmd.Flags().StringVar(&depsConfig.Devnet.Port, "devnet-mapped-port",
deps.DefaultDevnetPort,
"devnet local listening port number")
"Devnet local listening port number")

Cmd.Flags().StringVar(&depsConfig.Devnet.BlockTime, "devnet-block-time",
deps.DefaultBlockTime,
"Devnet mining block time")

Cmd.Flags().BoolVarP(&verbose, "verbose", "v", false, "verbose logs")
}

func run(cmd *cobra.Command, args []string) {
ctx, cancel := signal.NotifyContext(cmd.Context(), syscall.SIGINT, syscall.SIGTERM)
defer cancel()

if verbose {
// setup log
opts := &tint.Options{
Level: slog.LevelDebug,
AddSource: true,
NoColor: false || !isatty.IsTerminal(os.Stdout.Fd()),
}
handler := tint.NewHandler(os.Stdout, opts)
logger := slog.New(handler)
slog.SetDefault(logger)
}

depsContainers, err := deps.Run(ctx, *depsConfig)
cobra.CheckErr(err)

Expand Down
32 changes: 7 additions & 25 deletions cmd/cartesi-rollups-cli/root/increasetime/increasetime.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@
package increasetime

import (
"fmt"
"io"
"net/http"
"strconv"
"strings"
"context"
"log/slog"

"github.com/cartesi/rollups-node/pkg/ethutil"
"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -39,24 +37,8 @@ func init() {
}

func run(cmd *cobra.Command, args []string) {
client := &http.Client{}
var data = strings.NewReader(`{
"id":1337,
"jsonrpc":"2.0",
"method":"evm_increaseTime",
"params":[` + strconv.Itoa(time) + `]
}`)

req, err := http.NewRequest("POST", anvilEndpoint, data)
cobra.CheckErr(err)

req.Header.Set("Content-Type", "application/json")
resp, err := client.Do(req)
cobra.CheckErr(err)

defer resp.Body.Close()
bodyText, err := io.ReadAll(resp.Body)
cobra.CheckErr(err)

fmt.Printf("%s\n", bodyText)

cobra.CheckErr(ethutil.AdvanceDevnetTime(context.Background(), anvilEndpoint, time))

slog.Info("Ok")
}
43 changes: 31 additions & 12 deletions internal/deps/deps.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const (
DefaultPostgresPassword = "password"
DefaultDevnetDockerImage = "cartesi/rollups-node-devnet:devel"
DefaultDevnetPort = "8545"
DefaultBlockTime = "1"

numPostgresCheckReadyAttempts = 2
pollInterval = 5 * time.Second
Expand All @@ -42,6 +43,7 @@ type PostgresConfig struct {
type DevnetConfig struct {
DockerImage string
Port string
BlockTime string
}

// Builds a DepsConfig struct with default values
Expand All @@ -55,6 +57,7 @@ func NewDefaultDepsConfig() *DepsConfig {
&DevnetConfig{
DefaultDevnetDockerImage,
DefaultDevnetPort,
DefaultBlockTime,
},
}
}
Expand All @@ -73,12 +76,20 @@ func (d debugLogging) Printf(format string, v ...interface{}) {
slog.Debug(fmt.Sprintf(format, v...))
}

func createHook(waitGroup *sync.WaitGroup) []testcontainers.ContainerLifecycleHooks {
func createHook(containerName string,
finishedWaitGroup *sync.WaitGroup,
startedWaitGroup *sync.WaitGroup) []testcontainers.ContainerLifecycleHooks {
return []testcontainers.ContainerLifecycleHooks{
{
PostStarts: []testcontainers.ContainerHook{
func(ctx context.Context, container testcontainers.Container) error {
startedWaitGroup.Done()
return nil
},
},
PostTerminates: []testcontainers.ContainerHook{
func(ctx context.Context, container testcontainers.Container) error {
waitGroup.Done()
finishedWaitGroup.Done()
return nil
},
},
Expand All @@ -90,15 +101,19 @@ func createHook(waitGroup *sync.WaitGroup) []testcontainers.ContainerLifecycleHo
// The returned DepContainers struct can be used to gracefully
// terminate the containers using the Terminate method
func Run(ctx context.Context, depsConfig DepsConfig) (*DepsContainers, error) {

debugLogger := debugLogging{}
var waitGroup sync.WaitGroup
var finishedWaitGroup sync.WaitGroup
var startedWaitGroup sync.WaitGroup

containers := []testcontainers.Container{}
if depsConfig.Postgres != nil {
// wait strategy copied from testcontainers docs
postgresWaitStrategy := wait.ForLog("database system is ready to accept connections").
WithOccurrence(numPostgresCheckReadyAttempts).
WithPollInterval(pollInterval)

startedWaitGroup.Add(1)
postgresReq := testcontainers.ContainerRequest{
Image: depsConfig.Postgres.DockerImage,
ExposedPorts: []string{strings.Join([]string{
Expand All @@ -108,7 +123,8 @@ func Run(ctx context.Context, depsConfig DepsConfig) (*DepsContainers, error) {
Env: map[string]string{
"POSTGRES_PASSWORD": depsConfig.Postgres.Password,
},
LifecycleHooks: createHook(&waitGroup),
LifecycleHooks: createHook("rollups-node-dep-postgres",
&finishedWaitGroup, &startedWaitGroup),
}
postgres, err := testcontainers.GenericContainer(
ctx,
Expand All @@ -121,20 +137,20 @@ func Run(ctx context.Context, depsConfig DepsConfig) (*DepsContainers, error) {
if err != nil {
return nil, err
}
waitGroup.Add(1)
finishedWaitGroup.Add(1)
containers = append(containers, postgres)
}

if depsConfig.Devnet != nil {
startedWaitGroup.Add(1)
devNetReq := testcontainers.ContainerRequest{
Image: depsConfig.Devnet.DockerImage,
ExposedPorts: []string{strings.Join([]string{depsConfig.Devnet.Port, ":8545/tcp"}, "")},
WaitingFor: wait.ForLog("Listening on 0.0.0.0:8545"),
WaitingFor: wait.ForLog("Block Number: 21"),
Name: "rollups-node-dep-devnet",
Env: map[string]string{
"ANVIL_IP_ADDR": "0.0.0.0",
},
LifecycleHooks: createHook(&waitGroup),
Cmd: []string{"anvil", "--block-time", depsConfig.Devnet.BlockTime, "--load-state", "/usr/share/devnet/anvil_state.json"},
LifecycleHooks: createHook("rollups-node-dep-devnet",
&finishedWaitGroup, &startedWaitGroup),
}
devnet, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
ContainerRequest: devNetReq,
Expand All @@ -144,13 +160,16 @@ func Run(ctx context.Context, depsConfig DepsConfig) (*DepsContainers, error) {
if err != nil {
return nil, err
}
waitGroup.Add(1)
finishedWaitGroup.Add(1)
containers = append(containers, devnet)
}

if len(containers) < 1 {
return nil, fmt.Errorf("configuration is empty")
}
return &DepsContainers{containers, &waitGroup}, nil
startedWaitGroup.Wait()

return &DepsContainers{containers, &finishedWaitGroup}, nil
}

// Terminate terminates all dependencies containers. This method waits for all the containers
Expand Down
4 changes: 4 additions & 0 deletions pkg/addresses/addresses.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ type Book struct {
EtherPortal common.Address
InputBox common.Address
CartesiDApp common.Address
HistoryAddress common.Address
AuthorityAddress common.Address
}

// Get the addresses for the test environment.
Expand All @@ -45,6 +47,8 @@ func GetTestBook() *Book {
EtherPortal: common.HexToAddress("0xFfdbe43d4c855BF7e0f105c400A50857f53AB044"),
InputBox: common.HexToAddress("0x59b22D57D4f067708AB0c00552767405926dc768"),
CartesiDApp: common.HexToAddress("0x7FFdf694A877067DE99462A7243b29972D19cf72"),
HistoryAddress: common.HexToAddress("0x325272217ae6815b494bF38cED004c5Eb8a7CdA7"),
AuthorityAddress: common.HexToAddress("0x58c93F83fb3304730C95aad2E360cdb88b782010"),
}
}

Expand Down
50 changes: 50 additions & 0 deletions pkg/ethutil/ethutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ import (
"github.com/cartesi/rollups-node/pkg/contracts"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/rpc"
)

// Gas limit when sending transactions.
Expand Down Expand Up @@ -59,6 +61,31 @@ func AddInput(
return getInputIndex(ctx, client, book, inputBox, receipt)
}

// Convenience function to add an input using Foundry Mneumonic
// This function waits until the transaction is added to a block and return the input index.
func AddInputUsingFoundryMneumonic(ctx context.Context,
blockchainHttpEnpoint string, payload string) (int, error) {

// Send Input
client, err := ethclient.DialContext(ctx, blockchainHttpEnpoint)
if err != nil {
return 0, err
}
defer client.Close()

signer, err := NewMnemonicSigner(ctx, client, FoundryMnemonic, 0)
if err != nil {
return 0, err
}
book := addresses.GetTestBook()

payloadBytes, err := hexutil.Decode(payload)
if err != nil {
panic(err)
}
return AddInput(ctx, client, book, signer, payloadBytes)
}

// Get input index in the transaction by looking at the event logs.
func getInputIndex(
ctx context.Context,
Expand Down Expand Up @@ -159,3 +186,26 @@ func ExecuteVoucher(

return &receipt.TxHash, nil
}

// Advances the Devnet timestamp
func AdvanceDevnetTime(ctx context.Context, blockchainHttpEnpoint string, timeInSeconds int) error {
client, err := rpc.DialContext(ctx, blockchainHttpEnpoint)
if err != nil {
return err
}
defer client.Close()
return client.CallContext(ctx, nil, "evm_increaseTime", timeInSeconds)

}

// Sets the timestamp for the next block at Devnet
func SetNextDevnetBlockTimestamp(ctx context.Context,
blockchainHttpEnpoint string, timestamp int64) error {

client, err := rpc.DialContext(ctx, blockchainHttpEnpoint)
if err != nil {
return err
}
defer client.Close()
return client.CallContext(ctx, nil, "evm_setNextBlockTimestamp", timestamp)
}
Loading

0 comments on commit 3c71fb5

Please sign in to comment.