diff --git a/.changelog/2747.feature.md b/.changelog/2747.feature.md new file mode 100644 index 00000000000..af93f72f511 --- /dev/null +++ b/.changelog/2747.feature.md @@ -0,0 +1,4 @@ +e2e tests: Test debonding entries from genesis + +Here's an e2e test scenario that exercises debonding delegation records +from the genesis document. diff --git a/go/oasis-test-runner/scenario/e2e/debond.go b/go/oasis-test-runner/scenario/e2e/debond.go new file mode 100644 index 00000000000..1dc2582379c --- /dev/null +++ b/go/oasis-test-runner/scenario/e2e/debond.go @@ -0,0 +1,106 @@ +package e2e + +import ( + "context" + "fmt" + + "github.com/oasislabs/oasis-core/go/common/quantity" + consensus "github.com/oasislabs/oasis-core/go/consensus/api" + "github.com/oasislabs/oasis-core/go/oasis-test-runner/env" + "github.com/oasislabs/oasis-core/go/oasis-test-runner/oasis" + "github.com/oasislabs/oasis-core/go/oasis-test-runner/scenario" + staking "github.com/oasislabs/oasis-core/go/staking/api" +) + +// Debond tests debonding records created in the genesis document. +var Debond scenario.Scenario = &debondImpl{ + basicImpl: *newBasicImpl("debond", "", nil), +} + +type debondImpl struct { + basicImpl +} + +func (s *debondImpl) Fixture() (*oasis.NetworkFixture, error) { + f, err := s.basicImpl.Fixture() + if err != nil { + return nil, err + } + + // We will mock epochs for reclaiming the escrow. + f.Network.EpochtimeMock = true + + // Enable some features in the staking system that we'll test. + f.Network.StakingGenesis = "tests/fixture-data/debond/staking-genesis.json" + + return f, nil +} + +func (s *debondImpl) Run(*env.Env) error { + if err := s.net.Start(); err != nil { + return fmt.Errorf("net Start: %w", err) + } + + ctx := context.Background() + + s.logger.Info("waiting for network to come up") + if err := s.net.Controller().WaitNodesRegistered(ctx, 3); err != nil { + return fmt.Errorf("WaitNodesRegistered: %w", err) + } + + // Beginning: lockup account has no funds. + lockupQuery := staking.OwnerQuery{ + Height: consensus.HeightLatest, + } + if err := lockupQuery.Owner.UnmarshalHex("5555555555555555555555555555555555555555555555555555555555555555"); err != nil { + return fmt.Errorf("import lockup account ID: %w", err) + } + s.logger.Info("checking balance at beginning") + acct, err := s.net.Controller().Staking.AccountInfo(ctx, &lockupQuery) + if err != nil { + return fmt.Errorf("beginning AccountInfo: %w", err) + } + if !acct.General.Balance.IsZero() { + return fmt.Errorf("beginning balance %v should be zero", acct.General.Balance) + } + s.logger.Info("balance ok") + + // First debonding: 500 tokens at epoch 1. + s.logger.Info("advancing to first debonding") + if err = s.net.Controller().SetEpoch(ctx, 1); err != nil { + return fmt.Errorf("first SetEpoch: %w", err) + } + var expected quantity.Quantity + if err = expected.FromInt64(500); err != nil { + return fmt.Errorf("import first debonding expected balance: %w", err) + } + s.logger.Info("checking balance at first debonding") + acct, err = s.net.Controller().Staking.AccountInfo(ctx, &lockupQuery) + if err != nil { + return fmt.Errorf("first debonding AccountInfo: %w", err) + } + if acct.General.Balance.Cmp(&expected) != 0 { + return fmt.Errorf("first debonding balance %v should be %v", acct.General.Balance, expected) + } + s.logger.Info("balance ok") + + // Second debonding: 500 more tokens at epoch 2. + s.logger.Info("advancing to second debonding") + if err = s.net.Controller().SetEpoch(ctx, 2); err != nil { + return fmt.Errorf("second SetEpoch: %w", err) + } + if err = expected.FromInt64(1000); err != nil { + return fmt.Errorf("import second debonding expected balance: %w", err) + } + s.logger.Info("checking balance at second debonding") + acct, err = s.net.Controller().Staking.AccountInfo(ctx, &lockupQuery) + if err != nil { + return fmt.Errorf("second debonding AccountInfo: %w", err) + } + if acct.General.Balance.Cmp(&expected) != 0 { + return fmt.Errorf("second debonding balance %v should be %v", acct.General.Balance, expected) + } + s.logger.Info("balance ok") + + return nil +} diff --git a/go/oasis-test-runner/test-runner.go b/go/oasis-test-runner/test-runner.go index 132648d3385..0929f0548ee 100644 --- a/go/oasis-test-runner/test-runner.go +++ b/go/oasis-test-runner/test-runner.go @@ -64,6 +64,8 @@ func main() { // Node upgrade tests. _ = cmd.Register(e2e.NodeUpgrade) _ = cmd.Register(e2e.NodeUpgradeCancel) + // Debonding entries from genesis test. + _ = cmd.Register(e2e.Debond) // Register the remote signer test cases. rootCmd.Flags().AddFlagSet(remotesigner.Flags) diff --git a/tests/fixture-data/debond/staking-genesis.json b/tests/fixture-data/debond/staking-genesis.json new file mode 100644 index 00000000000..680b6a9f006 --- /dev/null +++ b/tests/fixture-data/debond/staking-genesis.json @@ -0,0 +1,44 @@ +{ + "params": { + "commission_schedule_rules": { + "rate_change_interval": 10, + "rate_bound_lead": 30, + "max_rate_steps": 4, + "max_bound_steps": 12 + }, + "thresholds": { + "0": "0", + "1": "0", + "2": "0", + "3": "0", + "4": "0", + "5": "0", + "6": "0" + } + }, + "total_supply": "1000", + "ledger": { + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=": { + "escrow": { + "debonding": { + "balance": "1000", + "total_shares": "1000" + } + } + } + }, + "debonding_delegations": { + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=": { + "VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVU=": [ + { + "shares": "500", + "debond_end": 1 + }, + { + "shares": "500", + "debond_end": 2 + } + ] + } + } +}