diff --git a/orchestrator/orchestrator.go b/orchestrator/orchestrator.go index ec05dc0f..9a4c0f30 100644 --- a/orchestrator/orchestrator.go +++ b/orchestrator/orchestrator.go @@ -300,29 +300,17 @@ func (orch Orchestrator) Process(ctx context.Context, nonce uint64) error { if att == nil { return celestiatypes.ErrAttestationNotFound } - // check if the validator is part of the needed valset - var previousValset *celestiatypes.Valset - if att.GetNonce() == 1 { - // if nonce == 1, then, the current valset should sign the confirm. - // In fact, the first nonce should never be signed. Because, the first attestation, in the case - // where the `earliest` flag is specified when deploying the contract, will be relayed as part of - // the deployment of the QGB contract. - // It will be signed temporarily for now. - previousValset, err = orch.AppQuerier.QueryValsetByNonce(ctx, att.GetNonce()) - if err != nil { - return err - } - } else { - previousValset, err = orch.AppQuerier.QueryLastValsetBeforeNonce(ctx, att.GetNonce()) - if err != nil { - return err - } - } - if !ValidatorPartOfValset(previousValset.Members, orch.EvmAccount.Address.Hex()) { + + // check if we need to sign or not + previousValset, err := orch.AppQuerier.QueryLastValsetBeforeNonce(ctx, att.GetNonce()) + if err != nil { + orch.Logger.Debug("failed to query last valset before nonce (most likely pruned). signing anyway", "err", err.Error()) + } else if !ValidatorPartOfValset(previousValset.Members, orch.EvmAccount.Address.Hex()) { // no need to sign if the orchestrator is not part of the validator set that needs to sign the attestation orch.Logger.Debug("validator not part of valset. won't sign", "nonce", nonce) return nil } + switch castedAtt := att.(type) { case *celestiatypes.Valset: signBytes, err := castedAtt.SignBytes() diff --git a/orchestrator/orchestrator_test.go b/orchestrator/orchestrator_test.go index e8566d73..e60a2ed1 100644 --- a/orchestrator/orchestrator_test.go +++ b/orchestrator/orchestrator_test.go @@ -6,6 +6,9 @@ import ( "testing" "time" + "github.com/celestiaorg/celestia-app/test/util/testnode" + qgbtesting "github.com/celestiaorg/orchestrator-relayer/testing" + "github.com/celestiaorg/celestia-app/app" "github.com/celestiaorg/celestia-app/app/encoding" "github.com/celestiaorg/orchestrator-relayer/rpc" @@ -163,3 +166,29 @@ func (s *OrchestratorTestSuite) TestEnqueuingAttestationNonces() { close(noncesQueue) assert.GreaterOrEqual(t, len(noncesQueue), int(latestNonce)) } + +func TestProcessWithoutValsetInStore(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + codec := encoding.MakeConfig(app.ModuleEncodingRegisters...).Codec + node := qgbtesting.NewTestNode( + ctx, + t, + qgbtesting.CelestiaNetworkParams{ + GenesisOpts: []testnode.GenesisOption{ + testnode.ImmediateProposals(codec), + qgbtesting.SetDataCommitmentWindowParams(codec, celestiatypes.Params{DataCommitmentWindow: 101}), + }, + TimeIotaMs: 6048000, // to have enough time to sign attestations after they're pruned + }, + ) + _, err := node.CelestiaNetwork.WaitForHeight(400) + require.NoError(t, err) + + orch := qgbtesting.NewOrchestrator(t, node) + + latestNonce, err := orch.AppQuerier.QueryLatestAttestationNonce(ctx) + require.NoError(t, err) + assert.NoError(t, orch.Process(ctx, latestNonce)) +} diff --git a/orchestrator/suite_test.go b/orchestrator/suite_test.go index 95c0c1c7..2d6155b7 100644 --- a/orchestrator/suite_test.go +++ b/orchestrator/suite_test.go @@ -26,9 +26,13 @@ func (s *OrchestratorTestSuite) SetupSuite() { s.Node = qgbtesting.NewTestNode( ctx, t, - testnode.ImmediateProposals(codec), - qgbtesting.SetDataCommitmentWindowParams(codec, types.Params{DataCommitmentWindow: 101}), - // qgbtesting.SetVotingParams(codec, v1beta1.VotingParams{VotingPeriod: 100 * time.Hour}), + qgbtesting.CelestiaNetworkParams{ + GenesisOpts: []testnode.GenesisOption{ + testnode.ImmediateProposals(codec), + qgbtesting.SetDataCommitmentWindowParams(codec, types.Params{DataCommitmentWindow: 101}), + }, + TimeIotaMs: 1, + }, ) s.Orchestrator = qgbtesting.NewOrchestrator(t, s.Node) } diff --git a/relayer/suite_test.go b/relayer/suite_test.go index 95e3f41d..2b1fe630 100644 --- a/relayer/suite_test.go +++ b/relayer/suite_test.go @@ -26,7 +26,7 @@ func (s *RelayerTestSuite) SetupSuite() { t.Skip("skipping relayer tests in short mode.") } ctx := context.Background() - s.Node = qgbtesting.NewTestNode(ctx, t) + s.Node = qgbtesting.NewTestNode(ctx, t, qgbtesting.DefaultCelestiaNetworkParams()) _, err := s.Node.CelestiaNetwork.WaitForHeight(2) require.NoError(t, err) s.Orchestrator = qgbtesting.NewOrchestrator(t, s.Node) diff --git a/rpc/suite_test.go b/rpc/suite_test.go index e0846514..380c4715 100644 --- a/rpc/suite_test.go +++ b/rpc/suite_test.go @@ -25,7 +25,7 @@ type QuerierTestSuite struct { func (s *QuerierTestSuite) SetupSuite() { t := s.T() ctx := context.Background() - s.Network = qgbtesting.NewCelestiaNetwork(ctx, t) + s.Network = qgbtesting.NewCelestiaNetwork(ctx, t, qgbtesting.DefaultCelestiaNetworkParams()) _, err := s.Network.WaitForHeightWithTimeout(400, 30*time.Second) s.EncConf = encoding.MakeConfig(app.ModuleEncodingRegisters...) s.Logger = tmlog.NewNopLogger() diff --git a/testing/celestia_network.go b/testing/celestia_network.go index 4c7e185a..74c73ba6 100644 --- a/testing/celestia_network.go +++ b/testing/celestia_network.go @@ -41,10 +41,22 @@ type CelestiaNetwork struct { GRPCAddr string } +type CelestiaNetworkParams struct { + GenesisOpts []celestiatestnode.GenesisOption + TimeIotaMs int64 +} + +func DefaultCelestiaNetworkParams() CelestiaNetworkParams { + return CelestiaNetworkParams{ + GenesisOpts: nil, + TimeIotaMs: 1, + } +} + // NewCelestiaNetwork creates a new CelestiaNetwork. // Uses `testing.T` to fail if an error happens. // Only supports the creation of a single validator currently. -func NewCelestiaNetwork(ctx context.Context, t *testing.T, genesisOpts ...celestiatestnode.GenesisOption) *CelestiaNetwork { +func NewCelestiaNetwork(ctx context.Context, t *testing.T, params CelestiaNetworkParams) *CelestiaNetwork { if testing.Short() { // The main reason for skipping these tests in short mode is to avoid detecting unrelated // race conditions. @@ -63,14 +75,17 @@ func NewCelestiaNetwork(ctx context.Context, t *testing.T, genesisOpts ...celest tmCfg := celestiatestnode.DefaultTendermintConfig() tmCfg.Consensus.TimeoutCommit = time.Millisecond * 5 appConf := celestiatestnode.DefaultAppConfig() + consensusParams := celestiatestnode.DefaultParams() + consensusParams.Block.TimeIotaMs = params.TimeIotaMs clientContext, _, _ := celestiatestnode.NewNetwork( t, celestiatestnode.DefaultConfig(). WithAppConfig(appConf). + WithConsensusParams(consensusParams). WithTendermintConfig(tmCfg). WithAccounts(accounts). - WithGenesisOptions(genesisOpts...). + WithGenesisOptions(params.GenesisOpts...). WithChainID("qgb-test"), ) diff --git a/testing/testnode.go b/testing/testnode.go index ddc956da..89a4cd9e 100644 --- a/testing/testnode.go +++ b/testing/testnode.go @@ -3,8 +3,6 @@ package testing import ( "context" "testing" - - celestiatestnode "github.com/celestiaorg/celestia-app/test/util/testnode" ) // TestNode contains a DHTNetwork along with a test Celestia network and a simulated EVM chain. @@ -15,8 +13,8 @@ type TestNode struct { EVMChain *EVMChain } -func NewTestNode(ctx context.Context, t *testing.T, genesisOpts ...celestiatestnode.GenesisOption) *TestNode { - celestiaNetwork := NewCelestiaNetwork(ctx, t, genesisOpts...) +func NewTestNode(ctx context.Context, t *testing.T, celestiaParams CelestiaNetworkParams) *TestNode { + celestiaNetwork := NewCelestiaNetwork(ctx, t, celestiaParams) dhtNetwork := NewDHTNetwork(ctx, 2) evmChain := NewEVMChain(NodeEVMPrivateKey)