From 7499b881e8cb0388905b11ed7d49f91d575fffba Mon Sep 17 00:00:00 2001 From: ptrus Date: Thu, 19 Oct 2023 11:35:33 +0200 Subject: [PATCH 1/4] tests/e2e: add early-query with runtimes scenario --- .../scenario/e2e/byzantine_beacon_vrf.go | 2 +- .../scenario/e2e/change_reward_schedule.go | 2 +- .../e2e/consensus_parameter_upgrade.go | 2 +- .../scenario/e2e/consensus_state_sync.go | 2 +- go/oasis-test-runner/scenario/e2e/debond.go | 2 +- .../scenario/e2e/early_query.go | 109 ------------- .../scenario/e2e/gas_fees_staking.go | 2 +- .../scenario/e2e/genesis_file.go | 2 +- .../scenario/e2e/identity_cli.go | 2 +- .../scenario/e2e/min_transact_balance.go | 2 +- .../scenario/e2e/multiple_seeds.go | 2 +- .../scenario/e2e/runtime/early_query.go | 152 ++++++++++++++++++ .../scenario/e2e/runtime/scenario.go | 6 +- go/oasis-test-runner/scenario/e2e/scenario.go | 19 ++- go/oasis-test-runner/scenario/e2e/seed_api.go | 2 +- go/oasis-test-runner/scenario/e2e/upgrade.go | 2 +- .../scenario/e2e/upgrade_cancel.go | 2 +- .../scenario/e2e/validator_equivocation.go | 2 +- .../scenario/pluginsigner/pluginsigner.go | 4 + .../scenario/remotesigner/remotesigner.go | 4 + go/oasis-test-runner/scenario/scenario.go | 3 + 21 files changed, 196 insertions(+), 129 deletions(-) delete mode 100644 go/oasis-test-runner/scenario/e2e/early_query.go create mode 100644 go/oasis-test-runner/scenario/e2e/runtime/early_query.go diff --git a/go/oasis-test-runner/scenario/e2e/byzantine_beacon_vrf.go b/go/oasis-test-runner/scenario/e2e/byzantine_beacon_vrf.go index d610dad5c19..cd10a5f4d69 100644 --- a/go/oasis-test-runner/scenario/e2e/byzantine_beacon_vrf.go +++ b/go/oasis-test-runner/scenario/e2e/byzantine_beacon_vrf.go @@ -51,7 +51,7 @@ type byzantineVRFBeaconImpl struct { func (sc *byzantineVRFBeaconImpl) Clone() scenario.Scenario { return &byzantineVRFBeaconImpl{ - Scenario: sc.Scenario.Clone(), + Scenario: *sc.Scenario.Clone().(*Scenario), extraArgs: sc.extraArgs, identitySeed: sc.identitySeed, } diff --git a/go/oasis-test-runner/scenario/e2e/change_reward_schedule.go b/go/oasis-test-runner/scenario/e2e/change_reward_schedule.go index a350e3cef84..6952bc1fb77 100644 --- a/go/oasis-test-runner/scenario/e2e/change_reward_schedule.go +++ b/go/oasis-test-runner/scenario/e2e/change_reward_schedule.go @@ -57,7 +57,7 @@ func newChangeRewardScheduleImpl(name string, parameters *api.ChangeParametersPr func (sc *changeRewardScheduleImpl) Clone() scenario.Scenario { return &changeRewardScheduleImpl{ - Scenario: sc.Scenario.Clone(), + Scenario: *sc.Scenario.Clone().(*Scenario), parameters: sc.parameters, currentEpoch: sc.currentEpoch, entityNonce: sc.entityNonce, diff --git a/go/oasis-test-runner/scenario/e2e/consensus_parameter_upgrade.go b/go/oasis-test-runner/scenario/e2e/consensus_parameter_upgrade.go index acb97b7cb71..2e03eebcfab 100644 --- a/go/oasis-test-runner/scenario/e2e/consensus_parameter_upgrade.go +++ b/go/oasis-test-runner/scenario/e2e/consensus_parameter_upgrade.go @@ -235,7 +235,7 @@ func newConsensusParameterUpgradeImpl(name string, parameters *api.ChangeParamet func (sc *consensusParameterUpgradeImpl) Clone() scenario.Scenario { return &consensusParameterUpgradeImpl{ - Scenario: sc.Scenario.Clone(), + Scenario: *sc.Scenario.Clone().(*Scenario), parameters: sc.parameters, upgradeChecker: sc.upgradeChecker, currentEpoch: sc.currentEpoch, diff --git a/go/oasis-test-runner/scenario/e2e/consensus_state_sync.go b/go/oasis-test-runner/scenario/e2e/consensus_state_sync.go index 1f4b8d71ebb..e9a007309cf 100644 --- a/go/oasis-test-runner/scenario/e2e/consensus_state_sync.go +++ b/go/oasis-test-runner/scenario/e2e/consensus_state_sync.go @@ -23,7 +23,7 @@ type consensusStateSyncImpl struct { func (sc *consensusStateSyncImpl) Clone() scenario.Scenario { return &consensusStateSyncImpl{ - Scenario: sc.Scenario.Clone(), + Scenario: *sc.Scenario.Clone().(*Scenario), } } diff --git a/go/oasis-test-runner/scenario/e2e/debond.go b/go/oasis-test-runner/scenario/e2e/debond.go index 4184632b8e1..7a0a74e80fc 100644 --- a/go/oasis-test-runner/scenario/e2e/debond.go +++ b/go/oasis-test-runner/scenario/e2e/debond.go @@ -23,7 +23,7 @@ type debondImpl struct { func (s *debondImpl) Clone() scenario.Scenario { return &debondImpl{ - Scenario: s.Scenario.Clone(), + Scenario: *s.Scenario.Clone().(*Scenario), } } diff --git a/go/oasis-test-runner/scenario/e2e/early_query.go b/go/oasis-test-runner/scenario/e2e/early_query.go deleted file mode 100644 index fa78020aa71..00000000000 --- a/go/oasis-test-runner/scenario/e2e/early_query.go +++ /dev/null @@ -1,109 +0,0 @@ -package e2e - -import ( - "context" - "errors" - "fmt" - "time" - - consensus "github.com/oasisprotocol/oasis-core/go/consensus/api" - "github.com/oasisprotocol/oasis-core/go/oasis-test-runner/env" - "github.com/oasisprotocol/oasis-core/go/oasis-test-runner/oasis" - "github.com/oasisprotocol/oasis-core/go/oasis-test-runner/scenario" -) - -var ( - // EarlyQuery is the early query scenario where we query a validator node before the network - // has started and there are no committed blocks. - EarlyQuery scenario.Scenario = &earlyQueryImpl{ - Scenario: *NewScenario("early-query"), - } - - // EarlyQueryInitHeight is the same as EarlyQuery scenario but with an initial height set. - EarlyQueryInitHeight scenario.Scenario = &earlyQueryImpl{ - Scenario: *NewScenario("early-query/init-height"), - initialHeight: 42, - } -) - -type earlyQueryImpl struct { - Scenario - - initialHeight int64 -} - -func (sc *earlyQueryImpl) Clone() scenario.Scenario { - return &earlyQueryImpl{ - Scenario: sc.Scenario.Clone(), - initialHeight: sc.initialHeight, - } -} - -func (sc *earlyQueryImpl) Fixture() (*oasis.NetworkFixture, error) { - f, err := sc.Scenario.Fixture() - if err != nil { - return nil, err - } - - f.Network.SetInsecureBeacon() - - // Set initial height. - f.Network.InitialHeight = sc.initialHeight - - // Only one validator should actually start to prevent the network from committing any blocks. - f.Validators[1].NoAutoStart = true - f.Validators[2].NoAutoStart = true - - return f, nil -} - -func (sc *earlyQueryImpl) Run(ctx context.Context, _ *env.Env) error { - // Start the network. - var err error - if err = sc.Net.Start(); err != nil { - return err - } - - // Perform some queries. - cs := sc.Net.Controller().Consensus - ctx, cancel := context.WithTimeout(ctx, 1*time.Second) - defer cancel() - - // StateToGenesis. - _, err = cs.StateToGenesis(ctx, consensus.HeightLatest) - if !errors.Is(err, consensus.ErrNoCommittedBlocks) { - return fmt.Errorf("StateToGenesis query should fail with ErrNoCommittedBlocks (got: %s)", err) - } - // GetBlock. - _, err = cs.GetBlock(ctx, consensus.HeightLatest) - if !errors.Is(err, consensus.ErrNoCommittedBlocks) { - return fmt.Errorf("GetBlock query should fail with ErrNoCommittedBlocks (got: %s)", err) - } - // GetTransactions. - _, err = cs.GetTransactions(ctx, consensus.HeightLatest) - if !errors.Is(err, consensus.ErrNoCommittedBlocks) { - return fmt.Errorf("GetTransactions query should fail with ErrNoCommittedBlocks (got: %s)", err) - } - // GetTransactionsWithResults. - _, err = cs.GetTransactionsWithResults(ctx, consensus.HeightLatest) - if !errors.Is(err, consensus.ErrNoCommittedBlocks) { - return fmt.Errorf("GetTransactionsWithResults query should fail with ErrNoCommittedBlocks (got: %s)", err) - } - - // GetStatus. - status, err := sc.Net.Controller().GetStatus(ctx) - if err != nil { - return fmt.Errorf("failed to get status for node: %w", err) - } - if status.Consensus.Status != consensus.StatusStateSyncing { - return fmt.Errorf("node reports as ready before chain is initialized") - } - if status.Consensus.LatestHeight != 0 { - return fmt.Errorf("node reports non-zero latest height before chain is initialized") - } - if !status.Consensus.IsValidator { - return fmt.Errorf("node does not report itself to be a validator at genesis") - } - - return nil -} diff --git a/go/oasis-test-runner/scenario/e2e/gas_fees_staking.go b/go/oasis-test-runner/scenario/e2e/gas_fees_staking.go index 2ebdee812c8..b5a90cf50e2 100644 --- a/go/oasis-test-runner/scenario/e2e/gas_fees_staking.go +++ b/go/oasis-test-runner/scenario/e2e/gas_fees_staking.go @@ -51,7 +51,7 @@ type gasFeesImpl struct { func (sc *gasFeesImpl) Clone() scenario.Scenario { return &gasFeesImpl{ - Scenario: sc.Scenario.Clone(), + Scenario: *sc.Scenario.Clone().(*Scenario), dumpRestore: sc.dumpRestore, } } diff --git a/go/oasis-test-runner/scenario/e2e/genesis_file.go b/go/oasis-test-runner/scenario/e2e/genesis_file.go index 12147127974..a6ed7e97164 100644 --- a/go/oasis-test-runner/scenario/e2e/genesis_file.go +++ b/go/oasis-test-runner/scenario/e2e/genesis_file.go @@ -42,7 +42,7 @@ type genesisFileImpl struct { func (s *genesisFileImpl) Clone() scenario.Scenario { return &genesisFileImpl{ - Scenario: s.Scenario.Clone(), + Scenario: *s.Scenario.Clone().(*Scenario), } } diff --git a/go/oasis-test-runner/scenario/e2e/identity_cli.go b/go/oasis-test-runner/scenario/e2e/identity_cli.go index b108c7f2811..90082dcd828 100644 --- a/go/oasis-test-runner/scenario/e2e/identity_cli.go +++ b/go/oasis-test-runner/scenario/e2e/identity_cli.go @@ -26,7 +26,7 @@ type identityCLIImpl struct { func (sc *identityCLIImpl) Clone() scenario.Scenario { return &identityCLIImpl{ - Scenario: sc.Scenario.Clone(), + Scenario: *sc.Scenario.Clone().(*Scenario), dataDir: sc.dataDir, } } diff --git a/go/oasis-test-runner/scenario/e2e/min_transact_balance.go b/go/oasis-test-runner/scenario/e2e/min_transact_balance.go index 7f41361d6f7..0a753b05904 100644 --- a/go/oasis-test-runner/scenario/e2e/min_transact_balance.go +++ b/go/oasis-test-runner/scenario/e2e/min_transact_balance.go @@ -82,7 +82,7 @@ func (mtb *minTransactBalanceImpl) getAccountAndCheckNonce(ctx context.Context, func (mtb *minTransactBalanceImpl) Clone() scenario.Scenario { return &minTransactBalanceImpl{ - Scenario: mtb.Scenario.Clone(), + Scenario: *mtb.Scenario.Clone().(*Scenario), } } diff --git a/go/oasis-test-runner/scenario/e2e/multiple_seeds.go b/go/oasis-test-runner/scenario/e2e/multiple_seeds.go index ab826c73904..4bec95c52a4 100644 --- a/go/oasis-test-runner/scenario/e2e/multiple_seeds.go +++ b/go/oasis-test-runner/scenario/e2e/multiple_seeds.go @@ -39,7 +39,7 @@ func (sc *multipleSeeds) Fixture() (*oasis.NetworkFixture, error) { func (sc *multipleSeeds) Clone() scenario.Scenario { return &multipleSeeds{ - Scenario: sc.Scenario.Clone(), + Scenario: *sc.Scenario.Clone().(*Scenario), } } diff --git a/go/oasis-test-runner/scenario/e2e/runtime/early_query.go b/go/oasis-test-runner/scenario/e2e/runtime/early_query.go new file mode 100644 index 00000000000..975b6753672 --- /dev/null +++ b/go/oasis-test-runner/scenario/e2e/runtime/early_query.go @@ -0,0 +1,152 @@ +package runtime + +import ( + "context" + "errors" + "fmt" + "time" + + consensus "github.com/oasisprotocol/oasis-core/go/consensus/api" + "github.com/oasisprotocol/oasis-core/go/oasis-test-runner/env" + "github.com/oasisprotocol/oasis-core/go/oasis-test-runner/oasis" + "github.com/oasisprotocol/oasis-core/go/oasis-test-runner/scenario" + "github.com/oasisprotocol/oasis-core/go/oasis-test-runner/scenario/e2e" +) + +var ( + // EarlyQuery is the early query scenario where we query a validator node before the network + // has started and there are no committed blocks. + EarlyQuery scenario.Scenario = &earlyQueryImpl{ + Scenario: e2e.NewScenario("early-query"), + } + + // EarlyQueryInitHeight is the same as EarlyQuery scenario but with an initial height set. + EarlyQueryInitHeight scenario.Scenario = &earlyQueryImpl{ + Scenario: e2e.NewScenario("early-query/init-height"), + initialHeight: 42, + } + + // EarlyQueryRuntime is the early query scenario where we query a runtime node. + EarlyQueryRuntime scenario.Scenario = &earlyQueryImpl{ + Scenario: NewScenario("early-query", nil), + runtime: true, + } +) + +type earlyQueryImpl struct { + scenario.Scenario + + runtime bool + initialHeight int64 +} + +func (sc *earlyQueryImpl) Clone() scenario.Scenario { + return &earlyQueryImpl{ + Scenario: sc.Scenario.Clone(), + runtime: sc.runtime, + initialHeight: sc.initialHeight, + } +} + +func (sc *earlyQueryImpl) Fixture() (*oasis.NetworkFixture, error) { + f, err := sc.Scenario.Fixture() + if err != nil { + return nil, err + } + + f.Network.SetInsecureBeacon() + + // Set initial height. + f.Network.InitialHeight = sc.initialHeight + + // Only one validator should actually start to prevent the network from committing any blocks. + f.Validators[1].NoAutoStart = true + f.Validators[2].NoAutoStart = true + + return f, nil +} + +func (sc *earlyQueryImpl) Run(ctx context.Context, _ *env.Env) error { + // Start the network. + var err error + if err = sc.Network().Start(); err != nil { + return err + } + + var ctrl *oasis.Controller + switch sc.runtime { + case false: + ctrl = sc.Network().Controller() + case true: + // Use the compute worker node in the runtime scenario. + ctrl, err = oasis.NewController(sc.Network().ComputeWorkers()[0].SocketPath()) + if err != nil { + return fmt.Errorf("failed to create controller for compute node: %w", err) + } + + } + + // Perform consensus queries. + ctx, cancel := context.WithTimeout(ctx, 10*time.Second) + defer cancel() + + // StateToGenesis. + _, err = ctrl.Consensus.StateToGenesis(ctx, consensus.HeightLatest) + if !errors.Is(err, consensus.ErrNoCommittedBlocks) { + return fmt.Errorf("StateToGenesis query should fail with ErrNoCommittedBlocks (got: %s)", err) + } + // GetBlock. + _, err = ctrl.Consensus.GetBlock(ctx, consensus.HeightLatest) + if !errors.Is(err, consensus.ErrNoCommittedBlocks) { + return fmt.Errorf("GetBlock query should fail with ErrNoCommittedBlocks (got: %s)", err) + } + // GetTransactions. + _, err = ctrl.Consensus.GetTransactions(ctx, consensus.HeightLatest) + if !errors.Is(err, consensus.ErrNoCommittedBlocks) { + return fmt.Errorf("GetTransactions query should fail with ErrNoCommittedBlocks (got: %s)", err) + } + // GetTransactionsWithResults. + _, err = ctrl.Consensus.GetTransactionsWithResults(ctx, consensus.HeightLatest) + if !errors.Is(err, consensus.ErrNoCommittedBlocks) { + return fmt.Errorf("GetTransactionsWithResults query should fail with ErrNoCommittedBlocks (got: %s)", err) + } + + switch sc.runtime { + case false: + // GetStatus on validator. + status, err := ctrl.GetStatus(ctx) + if err != nil { + return fmt.Errorf("failed to get status for node: %w", err) + } + if status.Consensus.Status != consensus.StatusStateSyncing { + return fmt.Errorf("node reports as ready before chain is initialized") + } + if status.Consensus.LatestHeight != 0 { + return fmt.Errorf("node reports non-zero latest height before chain is initialized") + } + if !status.Consensus.IsValidator { + return fmt.Errorf("node does not report itself to be a validator at genesis") + } + case true: + // GetStatus on a compute node. + status, err := ctrl.GetStatus(ctx) + if err != nil { + return fmt.Errorf("failed to get status for compute node: %w", err) + } + fmt.Println(status) + if status.Consensus.Status != consensus.StatusStateSyncing { + return fmt.Errorf("node reports as ready before chain is initialized") + } + if status.Consensus.LatestHeight != 0 { + return fmt.Errorf("node reports non-zero latest height before chain is initialized") + } + if status.Consensus.IsValidator { + return fmt.Errorf("compute node does report itself to be a validator at genesis") + } + if len(status.Runtimes) < 1 { + return fmt.Errorf("compute node status does not contain any runtimes") + } + } + + return nil +} diff --git a/go/oasis-test-runner/scenario/e2e/runtime/scenario.go b/go/oasis-test-runner/scenario/e2e/runtime/scenario.go index 8daf6034beb..34870718627 100644 --- a/go/oasis-test-runner/scenario/e2e/runtime/scenario.go +++ b/go/oasis-test-runner/scenario/e2e/runtime/scenario.go @@ -110,7 +110,7 @@ func (sc *Scenario) Clone() scenario.Scenario { testClient = sc.TestClient.Clone() } return &Scenario{ - Scenario: sc.Scenario.Clone(), + Scenario: *sc.Scenario.Clone().(*e2e.Scenario), TestClient: testClient, debugNoRandomInitialEpoch: sc.debugNoRandomInitialEpoch, debugWeakAlphaOk: sc.debugWeakAlphaOk, @@ -362,6 +362,10 @@ func RegisterScenarios() error { TrustRootChangeFailsTest, // Archive node API test. ArchiveAPI, + // Early query tests. + EarlyQuery, + EarlyQueryInitHeight, + EarlyQueryRuntime, } { if err := cmd.Register(s); err != nil { return err diff --git a/go/oasis-test-runner/scenario/e2e/scenario.go b/go/oasis-test-runner/scenario/e2e/scenario.go index 516ba8cd6a5..d68cdc75249 100644 --- a/go/oasis-test-runner/scenario/e2e/scenario.go +++ b/go/oasis-test-runner/scenario/e2e/scenario.go @@ -2,6 +2,8 @@ package e2e import ( + "context" + flag "github.com/spf13/pflag" "github.com/oasisprotocol/oasis-core/go/common/logging" @@ -49,8 +51,8 @@ func NewScenario(name string) *Scenario { } // Clone implements scenario.Scenario. -func (sc *Scenario) Clone() Scenario { - return Scenario{ +func (sc *Scenario) Clone() scenario.Scenario { + return &Scenario{ Net: sc.Net, Flags: sc.Flags.Clone(), Logger: sc.Logger, @@ -63,6 +65,11 @@ func (sc *Scenario) Name() string { return sc.name } +// Network implements scenario.Scenario. +func (sc *Scenario) Network() *oasis.Network { + return sc.Net +} + // Parameters implements scenario.Scenario. func (sc *Scenario) Parameters() *env.ParameterFlagSet { return sc.Flags @@ -73,6 +80,11 @@ func (sc *Scenario) PreInit() error { return nil } +// Run implements scenario.Scenario. +func (sc *Scenario) Run(context.Context, *env.Env) error { + return nil +} + // Fixture implements scenario.Scenario. func (sc *Scenario) Fixture() (*oasis.NetworkFixture, error) { nodeBinary, _ := sc.Flags.GetString(cfgNodeBinary) @@ -129,9 +141,6 @@ func RegisterScenarios() error { NodeUpgradeCancel, // Debonding entries from genesis test. Debond, - // Early query test. - EarlyQuery, - EarlyQueryInitHeight, // Consensus state sync. ConsensusStateSync, // Multiple seeds test. diff --git a/go/oasis-test-runner/scenario/e2e/seed_api.go b/go/oasis-test-runner/scenario/e2e/seed_api.go index 77f848f8030..8343735e2f0 100644 --- a/go/oasis-test-runner/scenario/e2e/seed_api.go +++ b/go/oasis-test-runner/scenario/e2e/seed_api.go @@ -37,7 +37,7 @@ func (sc *seedAPI) Fixture() (*oasis.NetworkFixture, error) { func (sc *seedAPI) Clone() scenario.Scenario { return &seedAPI{ - Scenario: sc.Scenario.Clone(), + Scenario: *sc.Scenario.Clone().(*Scenario), } } diff --git a/go/oasis-test-runner/scenario/e2e/upgrade.go b/go/oasis-test-runner/scenario/e2e/upgrade.go index 6195f3602a1..287b43d88fa 100644 --- a/go/oasis-test-runner/scenario/e2e/upgrade.go +++ b/go/oasis-test-runner/scenario/e2e/upgrade.go @@ -225,7 +225,7 @@ func newNodeUpgradeImpl(handlerName upgrade.HandlerName, upgradeChecker upgradeC func (sc *nodeUpgradeImpl) Clone() scenario.Scenario { return &nodeUpgradeImpl{ - Scenario: sc.Scenario.Clone(), + Scenario: *sc.Scenario.Clone().(*Scenario), handlerName: sc.handlerName, upgradeChecker: sc.upgradeChecker, } diff --git a/go/oasis-test-runner/scenario/e2e/upgrade_cancel.go b/go/oasis-test-runner/scenario/e2e/upgrade_cancel.go index c64b8a4b23d..e33ad1267eb 100644 --- a/go/oasis-test-runner/scenario/e2e/upgrade_cancel.go +++ b/go/oasis-test-runner/scenario/e2e/upgrade_cancel.go @@ -42,7 +42,7 @@ func newNodeUpgradeCancelImpl() scenario.Scenario { func (sc *nodeUpgradeCancelImpl) Clone() scenario.Scenario { return &nodeUpgradeCancelImpl{ - Scenario: sc.Scenario.Clone(), + Scenario: *sc.Scenario.Clone().(*Scenario), } } diff --git a/go/oasis-test-runner/scenario/e2e/validator_equivocation.go b/go/oasis-test-runner/scenario/e2e/validator_equivocation.go index 2e0e052e810..1267496cd56 100644 --- a/go/oasis-test-runner/scenario/e2e/validator_equivocation.go +++ b/go/oasis-test-runner/scenario/e2e/validator_equivocation.go @@ -36,7 +36,7 @@ type validatorEquivocationImpl struct { func (sc *validatorEquivocationImpl) Clone() scenario.Scenario { return &validatorEquivocationImpl{ - Scenario: sc.Scenario.Clone(), + Scenario: *sc.Scenario.Clone().(*Scenario), } } diff --git a/go/oasis-test-runner/scenario/pluginsigner/pluginsigner.go b/go/oasis-test-runner/scenario/pluginsigner/pluginsigner.go index 49d2b7b9212..f2c5ca841e1 100644 --- a/go/oasis-test-runner/scenario/pluginsigner/pluginsigner.go +++ b/go/oasis-test-runner/scenario/pluginsigner/pluginsigner.go @@ -68,6 +68,10 @@ func (sc *pluginSignerImpl) Fixture() (*oasis.NetworkFixture, error) { return nil, nil } +func (sc *pluginSignerImpl) Network() *oasis.Network { + return nil +} + func (sc *pluginSignerImpl) Init(*env.Env, *oasis.Network) error { return nil } diff --git a/go/oasis-test-runner/scenario/remotesigner/remotesigner.go b/go/oasis-test-runner/scenario/remotesigner/remotesigner.go index e71db55ba1e..fcaf6b0ad45 100644 --- a/go/oasis-test-runner/scenario/remotesigner/remotesigner.go +++ b/go/oasis-test-runner/scenario/remotesigner/remotesigner.go @@ -67,6 +67,10 @@ func (sc *remoteSignerImpl) Fixture() (*oasis.NetworkFixture, error) { return nil, nil } +func (sc *remoteSignerImpl) Network() *oasis.Network { + return nil +} + func (sc *remoteSignerImpl) Init(*env.Env, *oasis.Network) error { return nil } diff --git a/go/oasis-test-runner/scenario/scenario.go b/go/oasis-test-runner/scenario/scenario.go index 42cb5d92829..541c463df86 100644 --- a/go/oasis-test-runner/scenario/scenario.go +++ b/go/oasis-test-runner/scenario/scenario.go @@ -38,6 +38,9 @@ type Scenario interface { // otherwise it will be nil. Init(childEnv *env.Env, net *oasis.Network) error + // Network returns the network used by this scenario. + Network() *oasis.Network + // Run runs the scenario. Run(ctx context.Context, childEnv *env.Env) error } From 8feb391f6ebed008e4c8d78a088fc65d52070f72 Mon Sep 17 00:00:00 2001 From: ptrus Date: Thu, 19 Oct 2023 12:01:19 +0200 Subject: [PATCH 2/4] fix: control status blocking before chain init with runtimes --- .changelog/5407.bugfix.md | 1 + go/oasis-node/cmd/node/node_control.go | 3 ++- go/runtime/registry/host.go | 8 +++++++- go/runtime/registry/registry.go | 18 +++++++++++------- 4 files changed, 21 insertions(+), 9 deletions(-) create mode 100644 .changelog/5407.bugfix.md diff --git a/.changelog/5407.bugfix.md b/.changelog/5407.bugfix.md new file mode 100644 index 00000000000..655ad300a42 --- /dev/null +++ b/.changelog/5407.bugfix.md @@ -0,0 +1 @@ +Fix stuck `control status` on runtime nodes before initialization diff --git a/go/oasis-node/cmd/node/node_control.go b/go/oasis-node/cmd/node/node_control.go index 44385e0a521..ce655bec45b 100644 --- a/go/oasis-node/cmd/node/node_control.go +++ b/go/oasis-node/cmd/node/node_control.go @@ -332,12 +332,13 @@ func (n *Node) getRuntimeStatus(ctx context.Context) (map[common.Namespace]contr } // Fetch provisioner type. - _, provisioner, err := rt.Host(ctx) + _, provisioner, err := rt.Host() switch { case err != nil: n.logger.Error("failed to fetch host configuration", "err", err, ) + status.Provisioner = "pending" case provisioner != nil: status.Provisioner = provisioner.Name() default: diff --git a/go/runtime/registry/host.go b/go/runtime/registry/host.go index e05cbda2689..5346c225076 100644 --- a/go/runtime/registry/host.go +++ b/go/runtime/registry/host.go @@ -61,7 +61,13 @@ type RuntimeHostNode struct { // started automatically, you must call Start explicitly. func (n *RuntimeHostNode) ProvisionHostedRuntime(ctx context.Context) (host.RichRuntime, protocol.Notifier, error) { runtime := n.factory.GetRuntime() - cfgs, provisioner, err := runtime.Host(ctx) + + // Ensure registry descriptor is ready as it is required for obtaining Host configuration. + _, err := runtime.RegistryDescriptor(ctx) + if err != nil { + return nil, nil, fmt.Errorf("failed to wait for registry descriptor: %w", err) + } + cfgs, provisioner, err := runtime.Host() if err != nil { return nil, nil, fmt.Errorf("failed to get runtime host: %w", err) } diff --git a/go/runtime/registry/registry.go b/go/runtime/registry/registry.go index 3476bbd9f17..91b7115aa9c 100644 --- a/go/runtime/registry/registry.go +++ b/go/runtime/registry/registry.go @@ -107,7 +107,10 @@ type Runtime interface { HasHost() bool // Host returns the runtime host configuration and provisioner if configured. - Host(ctx context.Context) (map[version.Version]*runtimeHost.Config, runtimeHost.Provisioner, error) + // + // If the runtime is not yet registered an error is returned. Use `RegistryDescriptor` to + // wait for the runtime to be registered. + Host() (map[version.Version]*runtimeHost.Config, runtimeHost.Provisioner, error) // HostVersions returns a list of supported runtime versions. HostVersions() []version.Version @@ -240,19 +243,20 @@ func (r *runtime) HasHost() bool { return r.hostProvisioners != nil && r.hostConfig != nil } -func (r *runtime) Host(ctx context.Context) (map[version.Version]*runtimeHost.Config, runtimeHost.Provisioner, error) { +func (r *runtime) Host() (map[version.Version]*runtimeHost.Config, runtimeHost.Provisioner, error) { if r.hostProvisioners == nil || r.hostConfig == nil { return nil, nil, ErrRuntimeHostNotConfigured } - rt, err := r.RegistryDescriptor(ctx) - if err != nil { - return nil, nil, fmt.Errorf("failed to get runtime registry descriptor: %w", err) + r.RLock() + defer r.RUnlock() + if r.registryDescriptor == nil { + return nil, nil, fmt.Errorf("runtime not yet registered") } - provisioner, ok := r.hostProvisioners[rt.TEEHardware] + provisioner, ok := r.hostProvisioners[r.registryDescriptor.TEEHardware] if !ok { - return nil, nil, fmt.Errorf("no provisioner suitable for TEE hardware '%s'", rt.TEEHardware) + return nil, nil, fmt.Errorf("no provisioner suitable for TEE hardware '%s'", r.registryDescriptor.TEEHardware) } return r.hostConfig, provisioner, nil From 9dc8799705116d35302fa5402b918abc3377b712 Mon Sep 17 00:00:00 2001 From: ptrus Date: Thu, 19 Oct 2023 15:28:22 +0200 Subject: [PATCH 3/4] fix consensus light client status shows empty peer IDs --- .changelog/5408.bugfix.md | 1 + go/consensus/cometbft/light/p2p/p2p.go | 2 ++ go/consensus/cometbft/light/service.go | 4 +++- 3 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changelog/5408.bugfix.md diff --git a/.changelog/5408.bugfix.md b/.changelog/5408.bugfix.md new file mode 100644 index 00000000000..27161f2144f --- /dev/null +++ b/.changelog/5408.bugfix.md @@ -0,0 +1 @@ +Fix showing empty peer IDs in the Consensus light client status output diff --git a/go/consensus/cometbft/light/p2p/p2p.go b/go/consensus/cometbft/light/p2p/p2p.go index d4c25b64803..de3ad54d1e4 100644 --- a/go/consensus/cometbft/light/p2p/p2p.go +++ b/go/consensus/cometbft/light/p2p/p2p.go @@ -189,6 +189,8 @@ func (lp *lightClientProvider) Initialized() <-chan struct{} { func (lp *lightClientProvider) PeerID() string { peer := lp.getPeer() if peer == nil { + // This happens if a provider is not yet initialized, or + // (less likely) if a peer was just dropped and no new peer is available. return "" } return peer.String() diff --git a/go/consensus/cometbft/light/service.go b/go/consensus/cometbft/light/service.go index f1d076600ca..9b1455407c5 100644 --- a/go/consensus/cometbft/light/service.go +++ b/go/consensus/cometbft/light/service.go @@ -106,7 +106,9 @@ func (c *client) GetStatus() (*consensus.LightClientStatus, error) { } for _, p := range c.providers { - status.PeerIDs = append(status.PeerIDs, p.PeerID()) + if id := p.PeerID(); id != "" { + status.PeerIDs = append(status.PeerIDs, id) + } } return status, nil From ddd4fd238af8bdd7a8fb650942f424b3f1925b8a Mon Sep 17 00:00:00 2001 From: ptrus Date: Thu, 19 Oct 2023 17:09:35 +0200 Subject: [PATCH 4/4] config/migrate: Automatically configure external P2P addresses --- .changelog/5410.bugfix.md | 1 + go/oasis-node/cmd/config/migrate/migrate.go | 34 ++++++++++- .../cmd/config/migrate/migrate_test.go | 56 ++++++++++++++++++- 3 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 .changelog/5410.bugfix.md diff --git a/.changelog/5410.bugfix.md b/.changelog/5410.bugfix.md new file mode 100644 index 00000000000..9f75de96fe5 --- /dev/null +++ b/.changelog/5410.bugfix.md @@ -0,0 +1 @@ +config/migrate: Automatically configure external P2P addresses for validators diff --git a/go/oasis-node/cmd/config/migrate/migrate.go b/go/oasis-node/cmd/config/migrate/migrate.go index 8c7a2aaeef4..018a0b87cda 100644 --- a/go/oasis-node/cmd/config/migrate/migrate.go +++ b/go/oasis-node/cmd/config/migrate/migrate.go @@ -6,6 +6,7 @@ import ( "bytes" "fmt" "io" + "net/url" "os" "runtime" "strings" @@ -724,13 +725,44 @@ func doMigrateConfig(cmd *cobra.Command, args []string) { // If a node has `consensus.validator` set to true and it does not have any runtimes configured, // the new `mode` should be set to `validator`. + var isValidator bool if newValidator, ok := m(newCfg["consensus"])["validator"]; ok { - isValidator, _ := newValidator.(bool) + isValidator, _ = newValidator.(bool) if _, hasRuntimes := m(newCfg["runtime"])["paths"]; !hasRuntimes && isValidator { nodeMode = "validator" delete(m(newCfg["consensus"]), "validator") } } + // If node is a validator, it now requires external P2P addresses to have set. + if isValidator { + // Set P2P port if not set. + if _, ok := m(newCfg["p2p"])["port"]; !ok { + m(newCfg["p2p"])["port"] = 9200 + } + // Set P2P registration addresses if not set. + if _, ok := m(m(newCfg["p2p"])["registration"])["addresses"]; !ok { + mkSubMap(m(newCfg["p2p"]), "registration") + + // Parse host from consensus.external_address. + ea := m(newCfg["consensus"])["external_address"] + if eaStr, ok := ea.(string); ok { + url, err := url.Parse(eaStr) + if err != nil { + logger.Error("failed to parse URI from consensus.external_address", "err", err) + os.Exit(1) + } + m(m(newCfg["p2p"])["registration"])["addresses"] = []string{url.Hostname() + ":" + fmt.Sprintf("%d", m(newCfg["p2p"])["port"])} + } else { + logger.Warn("consensus.external_address missing, not configuring p2p.registration.addresses parameter", "address", ea) + } + } else { + logger.Warn("p2p.registration.addresses is already set, make sure the address port matches p2p.port") + } + + } + if isValidator && (m(newCfg["p2p"])["port"] == nil || m(m(newCfg["p2p"])["registration"])["addresses"] == nil) { + logger.Warn("node is a validator but p2p.port or p2p.registration.addresses are not set") + } // Check for options that are only available on the command-line. if _, ok = oldCfg["debug"]; ok { diff --git a/go/oasis-node/cmd/config/migrate/migrate_test.go b/go/oasis-node/cmd/config/migrate/migrate_test.go index a55bdcc581e..102386e3f09 100644 --- a/go/oasis-node/cmd/config/migrate/migrate_test.go +++ b/go/oasis-node/cmd/config/migrate/migrate_test.go @@ -67,7 +67,7 @@ genesis: file: /storage/node/genesis.json # Worker configuration. -worker: +worker: p2p: port: 9002 peer_outbound_queue_size: 42 @@ -261,6 +261,39 @@ worker: entity: /node/entity/entity.json ` +// Validator node with external address set and no P2P address. +const testValidatorConfig2Raw = ` +datadir: /node/data + +log: + level: + default: info + tendermint: info + tendermint/context: error + format: JSON + +genesis: + file: /node/etc/genesis.json + +consensus: + validator: true + + tendermint: + p2p: + # List of seed nodes to connect to. + # NOTE: You can add additional seed nodes to this list if you want. + seed: + - "E27F6B7A350B4CC2B48A6CBE94B0A02B0DCB0BF3@35.199.49.168:26656" + core: + external_address: tcp://4.3.2.1:26656 + +worker: + registration: + # In order for the node to register itself, the entity.json of the entity + # used to provision the node must be available on the node. + entity: /node/entity/entity.json +` + // Non-validator node from docs test configuration file. const testDocsNonValidatorConfigRaw = ` datadir: /node/data @@ -612,6 +645,27 @@ func TestConfigMigrationValidator(t *testing.T) { require.Equal(newConfig.Consensus.Validator, false) } +func TestConfigMigrationValidator2(t *testing.T) { + require := require.New(t) + newConfig := prepareTest(require, testValidatorConfig2Raw) + + // Now check if the config struct fields actually match the original state. + require.Equal(newConfig.Mode, config.ModeValidator) + require.Equal(newConfig.Common.DataDir, "/node/data") + require.Equal(newConfig.Common.Log.Format, "JSON") + require.Equal(newConfig.Common.Log.Level["default"], "info") + require.Equal(newConfig.Common.Log.Level["cometbft"], "info") + require.Equal(newConfig.Common.Log.Level["cometbft/context"], "error") + require.Equal(newConfig.Genesis.File, "/node/etc/genesis.json") + require.Equal(newConfig.P2P.Seeds[0], "H6u9MtuoWRKn5DKSgarj/dzr2Z9BsjuRHgRAoXITOcU=@35.199.49.168:26656") + require.Equal(newConfig.P2P.Seeds[1], "H6u9MtuoWRKn5DKSgarj/dzr2Z9BsjuRHgRAoXITOcU=@35.199.49.168:9200") + require.Equal(newConfig.Consensus.Validator, false) + require.Equal(newConfig.Consensus.ExternalAddress, "tcp://4.3.2.1:26656") + require.Equal(newConfig.P2P.Port, uint16(9200)) + require.Equal(len(newConfig.P2P.Registration.Addresses), 1) + require.Equal(newConfig.P2P.Registration.Addresses[0], "4.3.2.1:9200") +} + func TestConfigMigrationDocsNonValidator(t *testing.T) { require := require.New(t) newConfig := prepareTest(require, testDocsNonValidatorConfigRaw)