Skip to content

Commit

Permalink
feat: updated staking pool values (forbole#455)
Browse files Browse the repository at this point in the history
## Description

Closes: [BDU-484](https://forbole.atlassian.net/browse/BDU-484)



---

### Author Checklist

*All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.*

I have...

- [x] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] added `!` to the type prefix if API or client breaking change
- [x] targeted the correct branch
- [x] provided a link to the relevant issue or specification
- [x] added a changelog entry to `CHANGELOG.md`
- [x] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [x] updated the relevant documentation or specification
- [x] reviewed "Files changed" and left comments if necessary
- [x] confirmed all CI checks have passed

### Reviewers Checklist

*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*

I have...

- [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] confirmed `!` in the type prefix if API or client breaking change
- [ ] confirmed all author checklist items have been addressed
- [ ] reviewed API design and naming
- [ ] reviewed documentation is accurate
- [ ] reviewed tests and test coverage
- [ ] manually tested (if applicable)
  • Loading branch information
MonikaCat authored and ankurdotb committed Sep 8, 2022
1 parent b777817 commit 6ecbb0a
Show file tree
Hide file tree
Showing 12 changed files with 162 additions and 58 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
### Changes
#### Staking Module
- ([\#443](https://github.com/forbole/bdjuno/pull/443)) Remove tombstone status from staking module(already stored in slashing module)
- ([\#455](https://github.com/forbole/bdjuno/pull/455)) Added `unbonding_tokens` and `staked_not_bonded_tokens` values to staking pool table


## Version v3.2.0
### Changes
Expand Down
8 changes: 8 additions & 0 deletions database/gov_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,8 @@ func (suite *DbTestSuite) TestBigDipperDb_SaveProposalStakingPoolSnapshot() {
snapshot := types.NewProposalStakingPoolSnapshot(1, types.NewPool(
sdk.NewInt(100),
sdk.NewInt(200),
sdk.NewInt(20),
sdk.NewInt(30),
10,
))
err := suite.database.SaveProposalStakingPoolSnapshot(snapshot)
Expand All @@ -530,6 +532,8 @@ func (suite *DbTestSuite) TestBigDipperDb_SaveProposalStakingPoolSnapshot() {
err = suite.database.SaveProposalStakingPoolSnapshot(types.NewProposalStakingPoolSnapshot(1, types.NewPool(
sdk.NewInt(200),
sdk.NewInt(500),
sdk.NewInt(14),
sdk.NewInt(10),
9,
)))
suite.Require().NoError(err)
Expand All @@ -551,6 +555,8 @@ func (suite *DbTestSuite) TestBigDipperDb_SaveProposalStakingPoolSnapshot() {
err = suite.database.SaveProposalStakingPoolSnapshot(types.NewProposalStakingPoolSnapshot(1, types.NewPool(
sdk.NewInt(500),
sdk.NewInt(1000),
sdk.NewInt(20),
sdk.NewInt(30),
10,
)))
suite.Require().NoError(err)
Expand All @@ -572,6 +578,8 @@ func (suite *DbTestSuite) TestBigDipperDb_SaveProposalStakingPoolSnapshot() {
err = suite.database.SaveProposalStakingPoolSnapshot(types.NewProposalStakingPoolSnapshot(1, types.NewPool(
sdk.NewInt(1000),
sdk.NewInt(2000),
sdk.NewInt(80),
sdk.NewInt(40),
11,
)))
suite.Require().NoError(err)
Expand Down
10 changes: 6 additions & 4 deletions database/schema/03-staking.sql
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ CREATE INDEX staking_params_height_index ON staking_params (height);

CREATE TABLE staking_pool
(
one_row_id BOOLEAN NOT NULL DEFAULT TRUE PRIMARY KEY,
bonded_tokens TEXT NOT NULL,
not_bonded_tokens TEXT NOT NULL,
height BIGINT NOT NULL,
one_row_id BOOLEAN NOT NULL DEFAULT TRUE PRIMARY KEY,
bonded_tokens TEXT NOT NULL,
not_bonded_tokens TEXT NOT NULL,
unbonding_tokens TEXT NOT NULL,
staked_not_bonded_tokens TEXT NOT NULL,
height BIGINT NOT NULL,
CHECK (one_row_id)
);
CREATE INDEX staking_pool_height_index ON staking_pool (height);
Expand Down
13 changes: 10 additions & 3 deletions database/staking_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,22 @@ import (
// SaveStakingPool allows to save for the given height the given stakingtypes pool
func (db *Db) SaveStakingPool(pool *types.Pool) error {
stmt := `
INSERT INTO staking_pool (bonded_tokens, not_bonded_tokens, height)
VALUES ($1, $2, $3)
INSERT INTO staking_pool (bonded_tokens, not_bonded_tokens, unbonding_tokens, staked_not_bonded_tokens, height)
VALUES ($1, $2, $3, $4, $5)
ON CONFLICT (one_row_id) DO UPDATE
SET bonded_tokens = excluded.bonded_tokens,
not_bonded_tokens = excluded.not_bonded_tokens,
unbonding_tokens = excluded.unbonding_tokens,
staked_not_bonded_tokens = excluded.staked_not_bonded_tokens,
height = excluded.height
WHERE staking_pool.height <= excluded.height`

_, err := db.Sql.Exec(stmt, pool.BondedTokens.String(), pool.NotBondedTokens.String(), pool.Height)
_, err := db.Sql.Exec(stmt,
pool.BondedTokens.String(),
pool.NotBondedTokens.String(),
pool.UnbondingTokens.String(),
pool.StakedNotBondedTokens.String(),
pool.Height)
if err != nil {
return fmt.Errorf("error while storing staking pool: %s", err)
}
Expand Down
14 changes: 7 additions & 7 deletions database/staking_pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ import (

func (suite *DbTestSuite) TestBigDipperDb_SaveStakingPool() {
// Save the data
original := types.NewPool(sdk.NewInt(50), sdk.NewInt(100), 10)
original := types.NewPool(sdk.NewInt(50), sdk.NewInt(100), sdk.NewInt(5), sdk.NewInt(1), 10)
err := suite.database.SaveStakingPool(original)
suite.Require().NoError(err)

// Verify the data
expected := dbtypes.NewStakingPoolRow(50, 100, 10)
expected := dbtypes.NewStakingPoolRow(50, 100, 5, 1, 10)

var rows []dbtypes.StakingPoolRow
err = suite.database.Sqlx.Select(&rows, `SELECT * FROM staking_pool`)
Expand All @@ -25,7 +25,7 @@ func (suite *DbTestSuite) TestBigDipperDb_SaveStakingPool() {
// ----------------------------------------------------------------------------------------------------------------

// Try updating using a lower height
pool := types.NewPool(sdk.NewInt(1), sdk.NewInt(1), 8)
pool := types.NewPool(sdk.NewInt(1), sdk.NewInt(1), sdk.NewInt(1), sdk.NewInt(1), 8)
err = suite.database.SaveStakingPool(pool)
suite.Require().NoError(err)

Expand All @@ -39,12 +39,12 @@ func (suite *DbTestSuite) TestBigDipperDb_SaveStakingPool() {
// ----------------------------------------------------------------------------------------------------------------

// Try updating with the same height
pool = types.NewPool(sdk.NewInt(1), sdk.NewInt(1), 10)
pool = types.NewPool(sdk.NewInt(1), sdk.NewInt(1), sdk.NewInt(1), sdk.NewInt(1), 10)
err = suite.database.SaveStakingPool(pool)
suite.Require().NoError(err)

// Verify the data
expected = dbtypes.NewStakingPoolRow(1, 1, 10)
expected = dbtypes.NewStakingPoolRow(1, 1, 1, 1, 10)

rows = []dbtypes.StakingPoolRow{}
err = suite.database.Sqlx.Select(&rows, `SELECT * FROM staking_pool`)
Expand All @@ -55,12 +55,12 @@ func (suite *DbTestSuite) TestBigDipperDb_SaveStakingPool() {
// ----------------------------------------------------------------------------------------------------------------

// Try updating with a higher height
pool = types.NewPool(sdk.NewInt(1000000), sdk.NewInt(1000000), 20)
pool = types.NewPool(sdk.NewInt(1000000), sdk.NewInt(1000000), sdk.NewInt(20), sdk.NewInt(15), 20)
err = suite.database.SaveStakingPool(pool)
suite.Require().NoError(err)

// Verify the data
expected = dbtypes.NewStakingPoolRow(1000000, 1000000, 20)
expected = dbtypes.NewStakingPoolRow(1000000, 1000000, 20, 15, 20)

rows = []dbtypes.StakingPoolRow{}
err = suite.database.Sqlx.Select(&rows, `SELECT * FROM staking_pool`)
Expand Down
24 changes: 15 additions & 9 deletions database/types/staking_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,31 @@ package types

// StakingPoolRow represents a single row inside the staking_pool table
type StakingPoolRow struct {
OneRowID bool `db:"one_row_id"`
BondedTokens int64 `db:"bonded_tokens"`
NotBondedTokens int64 `db:"not_bonded_tokens"`
Height int64 `db:"height"`
OneRowID bool `db:"one_row_id"`
BondedTokens int64 `db:"bonded_tokens"`
NotBondedTokens int64 `db:"not_bonded_tokens"`
UnbondingTokens int64 `db:"unbonding_tokens"`
StakedNotBondedTokens int64 `db:"staked_not_bonded_tokens"`
Height int64 `db:"height"`
}

// NewStakingPoolRow allows to easily create a new StakingPoolRow
func NewStakingPoolRow(bondedTokens, notBondedTokens int64, height int64) StakingPoolRow {
func NewStakingPoolRow(bondedTokens, notBondedTokens, unbondingTokens, stakedNotBondedTokens int64, height int64) StakingPoolRow {
return StakingPoolRow{
OneRowID: true,
BondedTokens: bondedTokens,
NotBondedTokens: notBondedTokens,
Height: height,
OneRowID: true,
BondedTokens: bondedTokens,
NotBondedTokens: notBondedTokens,
UnbondingTokens: unbondingTokens,
StakedNotBondedTokens: stakedNotBondedTokens,
Height: height,
}
}

// Equal allows to tells whether r and as represent the same rows
func (r StakingPoolRow) Equal(s StakingPoolRow) bool {
return r.BondedTokens == s.BondedTokens &&
r.NotBondedTokens == s.NotBondedTokens &&
r.UnbondingTokens == s.UnbondingTokens &&
r.StakedNotBondedTokens == s.StakedNotBondedTokens &&
r.Height == s.Height
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,7 @@ select_permissions:
- height
- bonded_tokens
- not_bonded_tokens
- unbonding_tokens
- staked_not_bonded_tokens
filter: {}
role: anonymous
23 changes: 0 additions & 23 deletions modules/staking/handle_block.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@ func (m *Module) HandleBlock(
// Updated the double sign evidences
go m.updateDoubleSignEvidence(block.Block.Height, block.Block.Evidence.Evidence)

// Update the staking pool
go m.updateStakingPool(block.Block.Height)

return nil
}

Expand Down Expand Up @@ -123,23 +120,3 @@ func (m *Module) updateDoubleSignEvidence(height int64, evidenceList tmtypes.Evi

}
}

// updateStakingPool reads from the LCD the current staking pool and stores its value inside the database
func (m *Module) updateStakingPool(height int64) {
log.Debug().Str("module", "staking").Int64("height", height).
Msg("updating staking pool")

pool, err := m.GetStakingPool(height)
if err != nil {
log.Error().Str("module", "staking").Err(err).Int64("height", height).
Msg("error while getting staking pool")
return
}

err = m.db.SaveStakingPool(pool)
if err != nil {
log.Error().Str("module", "staking").Err(err).Int64("height", height).
Msg("error while saving staking pool")
return
}
}
48 changes: 48 additions & 0 deletions modules/staking/handle_periodic_operations.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package staking

import (
"fmt"

"github.com/go-co-op/gocron"
"github.com/rs/zerolog/log"

"github.com/forbole/bdjuno/v3/modules/utils"
)

// RegisterPeriodicOperations implements modules.PeriodicOperationsModule
func (m *Module) RegisterPeriodicOperations(scheduler *gocron.Scheduler) error {
log.Debug().Str("module", "staking").Msg("setting up periodic tasks")

// Update the staking pool every 5 mins
if _, err := scheduler.Every(5).Minutes().Do(func() {
utils.WatchMethod(m.updateStakingPool)
}); err != nil {
return fmt.Errorf("error while scheduling staking pool periodic operation: %s", err)
}

return nil
}

// updateStakingPool reads from the LCD the current staking pool and stores its value inside the database
func (m *Module) updateStakingPool() error {
height, err := m.db.GetLastBlockHeight()
if err != nil {
return fmt.Errorf("error while getting latest block height: %s", err)
}
log.Debug().Str("module", "staking").Int64("height", height).
Msg("updating staking pool")

pool, err := m.GetStakingPool(height)
if err != nil {
return fmt.Errorf("error while getting staking pool: %s", err)

}

err = m.db.SaveStakingPool(pool)
if err != nil {
return fmt.Errorf("error while saving staking pool: %s", err)

}

return nil
}
9 changes: 5 additions & 4 deletions modules/staking/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ import (
)

var (
_ modules.Module = &Module{}
_ modules.GenesisModule = &Module{}
_ modules.BlockModule = &Module{}
_ modules.MessageModule = &Module{}
_ modules.Module = &Module{}
_ modules.GenesisModule = &Module{}
_ modules.BlockModule = &Module{}
_ modules.MessageModule = &Module{}
_ modules.PeriodicOperationsModule = &Module{}
)

// Module represents the x/staking module
Expand Down
49 changes: 48 additions & 1 deletion modules/staking/utils_staking_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ package staking
import (
"fmt"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/query"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/forbole/bdjuno/v3/types"
)

Expand All @@ -12,5 +15,49 @@ func (m *Module) GetStakingPool(height int64) (*types.Pool, error) {
return nil, fmt.Errorf("error while getting staking pool: %s", err)
}

return types.NewPool(pool.BondedTokens, pool.NotBondedTokens, height), nil
validatorsList, err := m.db.GetValidators()
if err != nil {
return nil, fmt.Errorf("error while getting validators list: %s", err)
}

var unbondingTokens = sdk.NewInt(0)

for _, validator := range validatorsList {
// get list of all unbonding delegations for each validator
unbondingDelegations := m.getTotalUnbondingDelegationsFromValidator(height, validator.GetOperator())
if len(unbondingDelegations) > 0 {
// calculate total value of unbonding tokens
for _, unbonding := range unbondingDelegations {
for _, entry := range unbonding.Entries {
unbondingTokens = unbondingTokens.Add(entry.Balance)
}
}
}

}

// calculate total value of staked tokens that are not bonded
stakedNotBondedTokens := pool.NotBondedTokens.Sub(unbondingTokens)

return types.NewPool(pool.BondedTokens, pool.NotBondedTokens, unbondingTokens, stakedNotBondedTokens, height), nil
}

func (m *Module) getTotalUnbondingDelegationsFromValidator(height int64, valOperatorAddress string) []stakingtypes.UnbondingDelegation {
var unbondingDelegations []stakingtypes.UnbondingDelegation
var nextKey []byte
var stop = false
for !stop {
res, err := m.source.GetUnbondingDelegationsFromValidator(height,
valOperatorAddress,
&query.PageRequest{Key: nextKey},
)
if err != nil {
return []stakingtypes.UnbondingDelegation{}
}

nextKey = res.Pagination.NextKey
stop = len(res.Pagination.NextKey) == 0
unbondingDelegations = append(unbondingDelegations, res.UnbondingResponses...)
}
return unbondingDelegations
}
18 changes: 11 additions & 7 deletions types/staking_pool_params.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,21 @@ import (

// Pool contains the data of the staking pool at the given height
type Pool struct {
BondedTokens sdk.Int
NotBondedTokens sdk.Int
Height int64
BondedTokens sdk.Int
NotBondedTokens sdk.Int
UnbondingTokens sdk.Int
StakedNotBondedTokens sdk.Int
Height int64
}

// NewPool allows to build a new Pool instance
func NewPool(bondedTokens, notBondedTokens sdk.Int, height int64) *Pool {
func NewPool(bondedTokens, notBondedTokens, unbondingTokens, stakedNotBondedTokens sdk.Int, height int64) *Pool {
return &Pool{
BondedTokens: bondedTokens,
NotBondedTokens: notBondedTokens,
Height: height,
BondedTokens: bondedTokens,
NotBondedTokens: notBondedTokens,
UnbondingTokens: unbondingTokens,
StakedNotBondedTokens: stakedNotBondedTokens,
Height: height,
}
}

Expand Down

0 comments on commit 6ecbb0a

Please sign in to comment.