Skip to content

Commit

Permalink
Merge pull request #42 from symbioticfi/fix-vote-ext
Browse files Browse the repository at this point in the history
Fix vote ext
  • Loading branch information
alrxy authored Sep 25, 2024
2 parents e96d08c + 0da4c1a commit ad6cd81
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 66 deletions.
6 changes: 2 additions & 4 deletions x/symGenutil/gentx.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,7 @@ func DeliverGenTxs(
}
}

if err := stakingKeeper.SymbioticUpdateValidatorsPower(ctx, initBlockHash); err != nil {
return nil, fmt.Errorf("failed to update symbiotic validators power: %w", err)
}
stakingKeeper.CacheBlockHash(initBlockHash, 0)

return stakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx)
return stakingKeeper.BlockValidatorUpdates(ctx)
}
9 changes: 4 additions & 5 deletions x/symGenutil/types/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,18 @@ package types

import (
"context"
"encoding/json"
"github.com/cosmos/cosmos-sdk/types/module"

"cosmossdk.io/core/appmodule"
bankexported "cosmossdk.io/x/bank/exported"
"encoding/json"

"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
)

// StakingKeeper defines the expected staking keeper (noalias)
type StakingKeeper interface {
SymbioticUpdateValidatorsPower(ctx context.Context, blockHash string) error
ApplyAndReturnValidatorSetUpdates(context.Context) (updates []module.ValidatorUpdate, err error)
CacheBlockHash(blockHash string, height int64)
BlockValidatorUpdates(ctx context.Context) ([]appmodule.ValidatorUpdate, error)
}

// AccountKeeper defines the expected account keeper (noalias)
Expand Down
45 changes: 8 additions & 37 deletions x/symStaking/abci/proposal.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,8 @@ import (
"cosmossdk.io/x/symStaking/types"
"encoding/json"
"errors"
"fmt"
abci "github.com/cometbft/cometbft/abci/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"time"
)

const (
SYMBIOTIC_SYNC_PERIOD = 10
SLEEP_ON_RETRY = 200
RETRIES = 5
)

type ProposalHandler struct {
Expand All @@ -33,17 +25,7 @@ func NewProposalHandler(logger log.Logger, keeper *keeper2.Keeper) *ProposalHand

func (h *ProposalHandler) PrepareProposal() sdk.PrepareProposalHandler {
return func(ctx sdk.Context, req *abci.PrepareProposalRequest) (*abci.PrepareProposalResponse, error) {
var err error
var resp *abci.PrepareProposalResponse

for i := 0; i < RETRIES; i++ {
resp, err = h.internalPrepareProposal(ctx, req)
if err == nil {
break
}
time.Sleep(time.Millisecond * SLEEP_ON_RETRY)
}

resp, err := h.internalPrepareProposal(ctx, req)
if err != nil {
panic(errors.Join(types.ErrSymbioticValUpdate, err))
}
Expand All @@ -53,18 +35,8 @@ func (h *ProposalHandler) PrepareProposal() sdk.PrepareProposalHandler {
}

func (h *ProposalHandler) PreBlocker() sdk.PreBlocker {
return func(context sdk.Context, req *abci.FinalizeBlockRequest) error {
var err error

for i := 0; i < RETRIES; i++ {
err = h.internalPreBlocker(context, req)
if err == nil {
break
}
time.Sleep(time.Millisecond * SLEEP_ON_RETRY)
}

if err != nil {
return func(ctx sdk.Context, req *abci.FinalizeBlockRequest) error {
if err := h.internalPreBlocker(ctx, req); err != nil {
panic(errors.Join(types.ErrSymbioticValUpdate, err))
}

Expand All @@ -75,7 +47,7 @@ func (h *ProposalHandler) PreBlocker() sdk.PreBlocker {
func (h *ProposalHandler) internalPrepareProposal(ctx sdk.Context, req *abci.PrepareProposalRequest) (*abci.PrepareProposalResponse, error) {
proposalTxs := req.Txs

if req.Height%SYMBIOTIC_SYNC_PERIOD != 0 {
if req.Height%keeper2.SYMBIOTIC_SYNC_PERIOD != 0 {
return &abci.PrepareProposalResponse{
Txs: proposalTxs,
}, nil
Expand Down Expand Up @@ -103,7 +75,7 @@ func (h *ProposalHandler) internalPrepareProposal(ctx sdk.Context, req *abci.Pre
}

func (h *ProposalHandler) internalPreBlocker(context sdk.Context, req *abci.FinalizeBlockRequest) error {
if req.Height%SYMBIOTIC_SYNC_PERIOD != 0 || len(req.Txs) == 0 {
if req.Height%keeper2.SYMBIOTIC_SYNC_PERIOD != 0 || len(req.Txs) == 0 {
return nil
}

Expand All @@ -118,12 +90,11 @@ func (h *ProposalHandler) internalPreBlocker(context sdk.Context, req *abci.Fina
}

if block.Time() < h.prevBlockTime || int64(block.Time()) >= context.HeaderInfo().Time.Unix() || block.Time() < h.keeper.GetMinBlockTimestamp(context) {
return fmt.Errorf("symbiotic invalid proposed block")
h.keeper.CacheBlockHash(keeper2.INVALID_BLOCKHASH, req.Height)
return nil
}

if err := h.keeper.SymbioticUpdateValidatorsPower(context, blockHash); err != nil {
return err
}
h.keeper.CacheBlockHash(blockHash, req.Height)

h.prevBlockTime = block.Time()

Expand Down
4 changes: 3 additions & 1 deletion x/symStaking/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,9 @@ type Keeper struct {
validatorAddressCodec addresscodec.Codec
consensusAddressCodec addresscodec.Codec
cometInfoService comet.Service
apiUrls *types.ApiUrls
apiUrls types.ApiUrls
networkMiddlewareAddress string
cachedBlockHash CachedBlockHash

Schema collections.Schema

Expand Down Expand Up @@ -110,6 +111,7 @@ func NewKeeper(
consensusAddressCodec: consensusAddressCodec,
cometInfoService: cometInfoService,
apiUrls: types.NewApiUrls(),
cachedBlockHash: CachedBlockHash{},
networkMiddlewareAddress: networkMiddlewareAddress,
LastTotalPower: collections.NewItem(sb, types.LastTotalPowerKey, "last_total_power", sdk.IntValue),
HistoricalInfo: collections.NewMap(sb, types.HistoricalInfoKey, "historical_info", collections.Uint64Key, HistoricalInfoCodec(cdc)),
Expand Down
99 changes: 82 additions & 17 deletions x/symStaking/keeper/symbiotic_state_change.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"net/http"
"strconv"
"strings"
"time"
)

// Struct to unmarshal the response from the Beacon Chain API
Expand Down Expand Up @@ -56,10 +57,19 @@ type Validator struct {
ConsAddr [32]byte
}

type CachedBlockHash struct {
BlockHash string
Height int64
}

const (
SYMBIOTIC_SYNC_PERIOD = 10
SLEEP_ON_RETRY = 200
RETRIES = 5
BEACON_GENESIS_TIMESTAMP = 1695902400
SLOTS_IN_EPOCH = 32
SLOT_DURATION = 12
INVALID_BLOCKHASH = "invalid"
BLOCK_PATH = "/eth/v2/beacon/blocks/"
GET_VALIDATOR_SET_FUNCTION_NAME = "getValidatorSet"
GET_CURRENT_EPOCH_FUNCTION_NAME = "getCurrentEpoch"
Expand Down Expand Up @@ -110,15 +120,41 @@ const (
]`
)

func (k Keeper) SymbioticUpdateValidatorsPower(ctx context.Context, blockHash string) error {
func (k *Keeper) CacheBlockHash(blockHash string, height int64) {
k.cachedBlockHash.BlockHash = blockHash
k.cachedBlockHash.Height = height
}

func (k *Keeper) SymbioticUpdateValidatorsPower(ctx context.Context) error {
if k.networkMiddlewareAddress == "" {
panic("middleware address is not set")
}

validators, err := k.getSymbioticValidatorSet(ctx, blockHash)
if err != nil {
height := k.HeaderService.HeaderInfo(ctx).Height

if height%SYMBIOTIC_SYNC_PERIOD != 0 {
return nil
}

if k.cachedBlockHash.Height != height {
return fmt.Errorf("symbiotic no blockhash cache, actual cached height %v, expected %v", k.cachedBlockHash.Height, height)
}

if k.cachedBlockHash.BlockHash == INVALID_BLOCKHASH {
return nil
}

var validators []Validator
var err error

for i := 0; i < RETRIES; i++ {
validators, err = k.getSymbioticValidatorSet(ctx, k.cachedBlockHash.BlockHash)
if err == nil {
break
}

k.apiUrls.RotateEthUrl()
return err
time.Sleep(time.Millisecond * SLEEP_ON_RETRY)
}

for _, v := range validators {
Expand All @@ -136,35 +172,64 @@ func (k Keeper) SymbioticUpdateValidatorsPower(ctx context.Context, blockHash st
return nil
}

func (k Keeper) GetFinalizedBlockHash(ctx context.Context) (string, error) {
slot := k.getSlot(ctx)
block, err := k.parseBlock(slot)
for errors.Is(err, stakingtypes.ErrSymbioticNotFound) { // some slots on api may be omitted
for i := 1; i < SLOTS_IN_EPOCH; i++ {
block, err = k.parseBlock(slot + i)
if err == nil {
break
}
if !errors.Is(err, stakingtypes.ErrSymbioticNotFound) {
return "", err
func (k *Keeper) GetFinalizedBlockHash(ctx context.Context) (string, error) {
var err error
var block Block

for i := 0; i < RETRIES; i++ {
slot := k.getSlot(ctx)
block, err = k.parseBlock(slot)

for errors.Is(err, stakingtypes.ErrSymbioticNotFound) { // some slots on api may be omitted
for i := 1; i < SLOTS_IN_EPOCH; i++ {
block, err = k.parseBlock(slot + i)
if err == nil {
break
}
if !errors.Is(err, stakingtypes.ErrSymbioticNotFound) {
return "", err
}
}
}

if err == nil {
break
}

k.apiUrls.RotateBeaconUrl()
time.Sleep(time.Millisecond * SLEEP_ON_RETRY)
}

if err != nil {
return "", err
}

return block.Data.Message.Body.ExecutionPayload.BlockHash, nil
}

func (k Keeper) GetBlockByHash(ctx context.Context, blockHash string) (*types.Block, error) {
func (k *Keeper) GetBlockByHash(ctx context.Context, blockHash string) (*types.Block, error) {
var block *types.Block
client, err := ethclient.Dial(k.apiUrls.GetEthApiUrl())
if err != nil {
return nil, err
}
defer client.Close()

return client.BlockByHash(ctx, common.HexToHash(blockHash))
for i := 0; i < RETRIES; i++ {
block, err = client.BlockByHash(ctx, common.HexToHash(blockHash))
if err == nil {
break
}

k.apiUrls.RotateEthUrl()
time.Sleep(time.Millisecond * SLEEP_ON_RETRY)
}

if err != nil {
return nil, err
}

return block, nil
}

func (k Keeper) GetMinBlockTimestamp(ctx context.Context) uint64 {
Expand Down
3 changes: 3 additions & 0 deletions x/symStaking/keeper/val_state_change.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ import (
func (k Keeper) BlockValidatorUpdates(ctx context.Context) ([]appmodule.ValidatorUpdate, error) {
// Calculate validator set changes.
//
if err := k.SymbioticUpdateValidatorsPower(ctx); err != nil {
panic(errors.Join(types.ErrSymbioticValUpdate, err))
}
// NOTE: ApplyAndReturnValidatorSetUpdates has to come before
// UnbondAllMatureValidatorQueue.
// This fixes a bug when the unbonding period is instant (is the case in
Expand Down
4 changes: 2 additions & 2 deletions x/symStaking/types/api_urls.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type ApiUrls struct {
currentEthId int
}

func NewApiUrls() *ApiUrls {
func NewApiUrls() ApiUrls {
// USE ONLY YOUR LOCAL BEACON CLIENT FOR SAFETY!!!
beaconApiUrls := strings.Split(os.Getenv("BEACON_API_URLS"), ",")
if len(beaconApiUrls) == 1 && beaconApiUrls[0] == "" {
Expand All @@ -31,7 +31,7 @@ func NewApiUrls() *ApiUrls {
ethApiUrls = append(ethApiUrls, "https://holesky.gateway.tenderly.co")
}

return &ApiUrls{beaconApiUrls: beaconApiUrls, ethApiUrls: ethApiUrls}
return ApiUrls{beaconApiUrls: beaconApiUrls, ethApiUrls: ethApiUrls}
}

func (au ApiUrls) GetEthApiUrl() string {
Expand Down

0 comments on commit ad6cd81

Please sign in to comment.