-
Notifications
You must be signed in to change notification settings - Fork 64
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
533 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
// (c) Cartesi and individual authors (see AUTHORS) | ||
// SPDX-License-Identifier: Apache-2.0 (see LICENSE) | ||
|
||
package endtoendtests | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/cartesi/rollups-node/pkg/addresses" | ||
"github.com/cartesi/rollups-node/pkg/ethutil" | ||
"github.com/ethereum/go-ethereum/common/hexutil" | ||
"github.com/ethereum/go-ethereum/ethclient" | ||
"github.com/ethereum/go-ethereum/rpc" | ||
) | ||
|
||
func AddInput(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 := ethutil.NewMnemonicSigner(ctx, client, ethutil.FoundryMnemonic, 0) | ||
if err != nil { | ||
return 0, err | ||
} | ||
book := addresses.GetTestBook() | ||
|
||
payloadBytes, _ := hexutil.Decode(payload) | ||
inputIndex, err := ethutil.AddInput(ctx, client, book, signer, payloadBytes) | ||
if err != nil { | ||
return 0, err | ||
} | ||
return inputIndex, nil | ||
|
||
} | ||
|
||
func AdvanceTime(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) | ||
|
||
} | ||
|
||
func SetNextBlockTimestamp(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) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
// (c) Cartesi and individual authors (see AUTHORS) | ||
// SPDX-License-Identifier: Apache-2.0 (see LICENSE) | ||
|
||
// Package endtoendtests | ||
package endtoendtests | ||
|
||
import ( | ||
"fmt" | ||
"log/slog" | ||
"time" | ||
|
||
"github.com/cartesi/rollups-node/internal/node/config" | ||
"github.com/cartesi/rollups-node/pkg/addresses" | ||
"github.com/cartesi/rollups-node/pkg/ethutil" | ||
) | ||
|
||
const ( | ||
LocalPostgresEndpoint = "postgres://postgres:password@localhost:5432/postgres" | ||
LocalBlockchainID = 31337 | ||
LocalBlockchainHttpEndpoint = "http://localhost:8545" | ||
LocalBlockchainWsEnpoint = "ws://localhost:8545" | ||
LocalApplicationDeploymentBlockNumber = 20 | ||
LocalInputBoxDeploymentBlockNumber = 20 | ||
LocalHttpAddress = "0.0.0.0" | ||
LocalHttpPort = 10000 | ||
LocalBlockTimeout = 60 | ||
LocalFinalityOffset = 1 | ||
LocalEpochDurationInSeconds = 120 | ||
) | ||
|
||
func NewLocalNodeConfig() config.NodeConfig { | ||
var nodeConfig config.NodeConfig | ||
|
||
book := addresses.GetTestBook() | ||
|
||
//Log | ||
nodeConfig.LogLevel = slog.LevelInfo | ||
nodeConfig.LogPretty = false | ||
|
||
//Postgres | ||
nodeConfig.PostgresEndpoint = | ||
config.Redacted[string]{Value: LocalPostgresEndpoint} | ||
|
||
//Epoch | ||
nodeConfig.RollupsEpochDuration, _ = | ||
time.ParseDuration(fmt.Sprintf("%ds", LocalEpochDurationInSeconds)) | ||
|
||
//Blochain | ||
nodeConfig.BlockchainID = LocalBlockchainID | ||
nodeConfig.BlockchainHttpEndpoint = | ||
config.Redacted[string]{Value: LocalBlockchainHttpEndpoint} | ||
nodeConfig.BlockchainWsEndpoint = | ||
config.Redacted[string]{Value: LocalBlockchainWsEnpoint} | ||
nodeConfig.BlockchainIsLegacy = false | ||
nodeConfig.BlockchainFinalityOffset = LocalFinalityOffset | ||
nodeConfig.BlockchainBlockTimeout = LocalBlockTimeout | ||
|
||
//Contracts | ||
nodeConfig.ContractsHistoryAddress = book.HistoryAddress.Hex() | ||
nodeConfig.ContractsAuthorityAddress = book.AuthorityAddress.Hex() | ||
nodeConfig.ContractsApplicationAddress = book.CartesiDApp.Hex() | ||
nodeConfig.ContractsApplicationDeploymentBlockNumber = LocalApplicationDeploymentBlockNumber | ||
nodeConfig.ContractsInputBoxAddress = book.InputBox.Hex() | ||
nodeConfig.ContractsInputBoxDeploymentBlockNumber = LocalInputBoxDeploymentBlockNumber | ||
|
||
//HTTP endpoint | ||
nodeConfig.HttpAddress = LocalHttpAddress | ||
nodeConfig.HttpPort = LocalHttpPort | ||
|
||
//Features | ||
nodeConfig.FeatureHostMode = false | ||
nodeConfig.FeatureDisableClaimer = false | ||
nodeConfig.FeatureDisableMachineHashCheck = true | ||
|
||
//Experimental | ||
nodeConfig.ExperimentalSunodoValidatorEnabled = false | ||
|
||
//Auth | ||
nodeConfig.Auth = config.AuthMnemonic{ | ||
Mnemonic: config.Redacted[string]{Value: ethutil.FoundryMnemonic}, | ||
AccountIndex: config.Redacted[int]{Value: 0}, | ||
} | ||
|
||
return nodeConfig | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,205 @@ | ||
// (c) Cartesi and individual authors (see AUTHORS) | ||
// SPDX-License-Identifier: Apache-2.0 (see LICENSE) | ||
|
||
//go:build endtoendtests | ||
// +build endtoendtests | ||
|
||
package endtoendtests | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"io/ioutil" | ||
"os" | ||
"path/filepath" | ||
"testing" | ||
"time" | ||
|
||
"github.com/Khan/genqlient/graphql" | ||
"github.com/cartesi/rollups-node/internal/deps" | ||
"github.com/cartesi/rollups-node/internal/machine" | ||
"github.com/cartesi/rollups-node/internal/node" | ||
"github.com/cartesi/rollups-node/pkg/readerclient" | ||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
"github.com/stretchr/testify/suite" | ||
) | ||
|
||
const ( | ||
payload = "0xdeadbeef" | ||
maxReadInputAttempts = 10 | ||
defaulTxDatabaseFile = "default_tx_database" | ||
) | ||
|
||
type EchoInputTestSuite struct { | ||
suite.Suite | ||
containers *deps.DepsContainers | ||
cancel context.CancelFunc | ||
tempDir string | ||
supervisorErr chan error | ||
} | ||
|
||
func (s *EchoInputTestSuite) SetupSuite() { | ||
|
||
// Clear default_tx_database | ||
cwd, err := os.Getwd() | ||
require.NoError(s.T(), err) | ||
|
||
_ = os.Remove(filepath.Join(cwd, defaulTxDatabaseFile)) | ||
|
||
// Create machine snapshot | ||
tempDir, err := ioutil.TempDir("", "machine-snapshot") | ||
assert.NoError(s.T(), err) | ||
machine.Save("cartesi/rollups-node-snapshot:devel", tempDir, "test-echo-app") | ||
|
||
// Run deps | ||
ctx := context.Background() | ||
var depsConfig = deps.NewDefaultDepsConfig() | ||
depsContainers, err := deps.Run(ctx, *depsConfig) | ||
require.NoError(s.T(), err) | ||
|
||
// Wait a little for Dependencies to be actually ready | ||
time.Sleep(2 * time.Second) | ||
|
||
// Fix the Blochain timestamp. Must be "in the future" | ||
err = SetNextBlockTimestamp(ctx, LocalBlockchainHttpEndpoint, 7000000000) | ||
require.NoError(s.T(), err) | ||
|
||
// Run Node Service | ||
nodeConfig := NewLocalNodeConfig() | ||
|
||
nodeConfig.SnapshotDir = tempDir | ||
|
||
ctx, cancel := context.WithCancel(ctx) | ||
supervisor, err := node.Setup(ctx, nodeConfig) | ||
require.NoError(s.T(), err) | ||
|
||
ready := make(chan struct{}, 1) | ||
supervisorErr := make(chan error, 1) | ||
go func() { | ||
err := supervisor.Start(ctx, ready) | ||
if err != nil { | ||
supervisorErr <- err | ||
} | ||
}() | ||
|
||
select { | ||
case err := <-supervisorErr: | ||
require.NoError(s.T(), err) | ||
case <-ready: | ||
break | ||
} | ||
|
||
// Configure Suite for tear down | ||
s.containers = depsContainers | ||
s.tempDir = tempDir | ||
s.cancel = cancel | ||
s.supervisorErr = supervisorErr | ||
|
||
} | ||
|
||
func (s *EchoInputTestSuite) TearDownSuite() { | ||
|
||
// Stop Node services | ||
s.cancel() | ||
|
||
// Remove machine snpshot | ||
os.RemoveAll(s.tempDir) | ||
|
||
// Terminate deps | ||
ctx := context.Background() | ||
err := deps.Terminate(ctx, s.containers) | ||
require.NoError(s.T(), err) | ||
|
||
// Clear default_tx_database | ||
cwd, err := os.Getwd() | ||
require.NoError(s.T(), err) | ||
|
||
_ = os.Remove(filepath.Join(cwd, defaulTxDatabaseFile)) | ||
|
||
} | ||
|
||
func (s *EchoInputTestSuite) SetupTest() { | ||
|
||
} | ||
|
||
func (s *EchoInputTestSuite) TestSendInput() { | ||
|
||
ctx := context.Background() | ||
|
||
inputIndex, err := AddInput(ctx, LocalBlockchainHttpEndpoint, payload) | ||
require.NoError(s.T(), err) | ||
|
||
// Check input was correctly added to the blockchain | ||
require.EqualValues(s.T(), 0, inputIndex) | ||
|
||
require.NoError(s.T(), AdvanceTime(ctx, LocalBlockchainHttpEndpoint, 120)) | ||
|
||
// Get Input with vouchers and proofs | ||
graphQlClient := graphql.NewClient("http://localhost:10000/graphql", nil) | ||
getInputChan := make(chan *readerclient.Input, 1) | ||
getInputErr := make(chan struct{}, 1) | ||
|
||
go func() { | ||
var resp *readerclient.Input | ||
attempts := 0 | ||
for ; attempts < maxReadInputAttempts; attempts++ { | ||
time.Sleep(2 * time.Second) | ||
resp, err = readerclient.GetInput(ctx, graphQlClient, inputIndex) | ||
if err == nil && resp.Status == "ACCEPTED" && | ||
resp.Vouchers != nil && resp.Vouchers[0].Proof != nil && | ||
resp.Notices != nil && resp.Notices[0].Proof != nil { | ||
break | ||
} | ||
} | ||
if attempts == maxReadInputAttempts { | ||
getInputErr <- struct{}{} | ||
return | ||
} | ||
getInputChan <- resp | ||
}() | ||
|
||
select { | ||
case input := <-getInputChan: | ||
|
||
//Check Input | ||
expectedInput, err := readExpectedInputWithProof("expected_input_with_proofs.json") | ||
require.NoError(s.T(), err) | ||
|
||
require.EqualValues(s.T(), expectedInput, input) | ||
|
||
break | ||
case err = <-s.supervisorErr: | ||
require.NoError(s.T(), err) | ||
break | ||
case <-getInputErr: | ||
require.FailNow(s.T(), "Could not retrieve Voucher with Proof 0") | ||
} | ||
|
||
} | ||
|
||
func readExpectedInputWithProof(filename string) (*readerclient.Input, error) { | ||
cwd, err := os.Getwd() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
expectedInputJsonBytes, err := ioutil.ReadFile(filepath.Join(cwd, "resources", "echo_input", filename)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
var input readerclient.Input | ||
err = json.Unmarshal(expectedInputJsonBytes, &input) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &input, nil | ||
|
||
} | ||
|
||
func TestEchoInput(t *testing.T) { | ||
|
||
suite.Run(t, new(EchoInputTestSuite)) | ||
} |
Oops, something went wrong.