Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: bc fusion hardfork implementation #358

Merged
merged 22 commits into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions types/stake.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ type ValidatorSet interface {
ValidatorByConsAddr(Context, ConsAddress) Validator // get a particular validator by consensus address
ValidatorByVoteAddr(Context, []byte) Validator // get a particular validator by vote address
TotalPower(Context) Dec // total power of the validator set
GetAllStatusVotingPower(ctx Context) Dec // total voting power of the validator set

// slash the validator and delegators of the validator, specifying offence height, offence power, and slash fraction
Slash(Context, ConsAddress, int64, int64, Dec)
Expand Down
8 changes: 8 additions & 0 deletions types/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ const (
FixDoubleSignChainId = "FixDoubleSignChainId"
BEP126 = "BEP126" //https://github.com/binance-chain/BEPs/pull/126
BEP255 = "BEP255" // https://github.com/bnb-chain/BEPs/pull/255

FirstSunsetFork = "FirstSunsetFork"
SecondSunsetFork = "SecondSunsetFork"
FinalSunsetFork = "FinalSunsetFork"
)

var (
BCFusionStopGovThreshold int64 = 5_000_000
)

var MainNetConfig = UpgradeConfig{
Expand Down
3 changes: 3 additions & 0 deletions x/gov/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ func NewHandler(keeper Keeper) sdk.Handler {
case MsgSideChainDeposit:
return handleMsgSideChainDeposit(ctx, keeper, msg)
case MsgSideChainSubmitProposal:
if sdk.IsUpgrade(sdk.SecondSunsetFork) {
return sdk.ErrMsgNotSupported("").Result()
}
return handleMsgSideChainSubmitProposal(ctx, keeper, msg)
case MsgSideChainVote:
return handleMsgSideChainVote(ctx, keeper, msg)
Expand Down
14 changes: 10 additions & 4 deletions x/gov/handler_sidechain.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,20 @@ import (
)

func handleMsgSideChainSubmitProposal(ctx sdk.Context, keeper Keeper, msg MsgSideChainSubmitProposal) sdk.Result {
if msg.ProposalType == ProposalTypeText && !sdk.IsUpgrade(sdk.BEP173) {
return ErrInvalidProposalType(keeper.codespace, msg.ProposalType).Result()
}

ctx, err := keeper.ScKeeper.PrepareCtxForSideChain(ctx, msg.SideChainId)
if err != nil {
return ErrInvalidSideChainId(keeper.codespace, msg.SideChainId).Result()
}
if sdk.IsUpgrade(sdk.FirstSunsetFork) {
vp := keeper.vs.GetAllStatusVotingPower(ctx)
if vp.LTE(sdk.NewDecFromInt(sdk.BCFusionStopGovThreshold)) {
return sdk.ErrMsgNotSupported("").Result()
}
}

if msg.ProposalType == ProposalTypeText && !sdk.IsUpgrade(sdk.BEP173) {
return ErrInvalidProposalType(keeper.codespace, msg.ProposalType).Result()
}

result := handleMsgSubmitProposal(ctx, keeper,
NewMsgSubmitProposal(msg.Title, msg.Description, msg.ProposalType, msg.Proposer, msg.InitialDeposit,
Expand Down
65 changes: 63 additions & 2 deletions x/ibc/endblock.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,81 @@
package ibc

import (
"fmt"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/gov"
)

func EndBlocker(ctx sdk.Context, keeper Keeper) {
if len(keeper.packageCollector.collectedPackages) == 0 {
return
}
var attributes []sdk.Attribute
var (
attributes []sdk.Attribute
events sdk.Events
)
for _, ibcPackageRecord := range keeper.packageCollector.collectedPackages {
attributes = append(attributes,
sdk.NewAttribute(ibcPackageInfoAttributeKey,
buildIBCPackageAttributeValue(ibcPackageRecord.destChainID, ibcPackageRecord.channelID, ibcPackageRecord.sequence)))
}

keeper.packageCollector.collectedPackages = keeper.packageCollector.collectedPackages[:0]
event := sdk.NewEvent(ibcEventType, attributes...)
ctx.EventManager().EmitEvent(event)
events.AppendEvent(event)
if sdk.IsUpgrade(sdk.FinalSunsetFork) && !keeper.sideKeeper.IsBSCAllChannelClosed(ctx) {
events = events.AppendEvents(closeSideChainChannels(ctx, keeper))
}
ctx.EventManager().EmitEvents(events)
}

func closeSideChainChannels(ctx sdk.Context, k Keeper) sdk.Events {
var events sdk.Events
sideChainId := k.sideKeeper.BscSideChainId(ctx)
// disable side chain channels
id := k.sideKeeper.Config().DestChainNameToID(sideChainId)
govChannelId := sdk.ChannelID(gov.ProposalTypeManageChanPermission)
permissions := k.sideKeeper.GetChannelSendPermissions(ctx, id)
for _, channelId := range k.sideKeeper.Config().ChannelIDs() {
if channelId == govChannelId {
// skip gov channel
continue
}
if permissions[channelId] == sdk.ChannelForbidden {
// skip forbidden channel
continue
}

events = events.AppendEvents(closeChannelOnSideChanAndKeeper(ctx, k, id, channelId))
}

// disable side chain gov channel
if permissions[govChannelId] == sdk.ChannelAllow {
events = events.AppendEvents(closeChannelOnSideChanAndKeeper(ctx, k, id, govChannelId))
}
k.sideKeeper.SetBSCAllChannelClosed(ctx)
return events
}

func closeChannelOnSideChanAndKeeper(ctx sdk.Context, k Keeper,
destChainID sdk.ChainID, channelID sdk.ChannelID) sdk.Events {
var events sdk.Events
_, err := k.sideKeeper.SaveChannelSettingChangeToIbc(ctx, destChainID, channelID, sdk.ChannelForbidden)
if err != nil {
ctx.Logger().Error("failed to save ibc channel change", "err", err.Error())
events.AppendEvent(sdk.NewEvent(EventTypeSaveIBCChannelSettingFailed,
sdk.NewAttribute(AttributeKeySideChainId, fmt.Sprint(destChainID)),
sdk.NewAttribute(AttributeKeyChannelId, fmt.Sprint(channelID)),
sdk.NewAttribute(AttributeKeyError, err.Error()),
))
return events
}
events.AppendEvent(sdk.NewEvent(EventTypeSaveIBCChannelSettingSucceed,
sdk.NewAttribute(AttributeKeySideChainId, fmt.Sprint(destChainID)),
sdk.NewAttribute(AttributeKeyChannelId, fmt.Sprint(channelID)),
))
// close bc side chain channel
k.sideKeeper.SetChannelSendPermission(ctx, destChainID, channelID, sdk.ChannelForbidden)
return events
}
9 changes: 9 additions & 0 deletions x/ibc/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
)

var (
EventTypeSaveIBCChannelSettingFailed = "save_ibc_channel_setting_failed"
EventTypeSaveIBCChannelSettingSucceed = "save_ibc_channel_setting_succeed"

AttributeKeySideChainId = "side_chain_id"
AttributeKeyChannelId = "channel_id"
AttributeKeyError = "error"
)

const (
separator = "::"
ibcEventType = "IBCPackage"
Expand Down
10 changes: 10 additions & 0 deletions x/sidechain/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import sdk "github.com/cosmos/cosmos-sdk/types"
type crossChainConfig struct {
srcChainID sdk.ChainID

channelIDs []sdk.ChannelID
nameToChannelID map[string]sdk.ChannelID
channelIDToName map[sdk.ChannelID]string
channelIDToApp map[sdk.ChannelID]sdk.CrossChainApplication
Expand All @@ -16,6 +17,7 @@ type crossChainConfig struct {
func newCrossChainCfg() *crossChainConfig {
config := &crossChainConfig{
srcChainID: 0,
channelIDs: make([]sdk.ChannelID, 0),
nameToChannelID: make(map[string]sdk.ChannelID),
channelIDToName: make(map[sdk.ChannelID]string),
destChainNameToID: make(map[string]sdk.ChainID),
Expand All @@ -24,3 +26,11 @@ func newCrossChainCfg() *crossChainConfig {
}
return config
}

func (c *crossChainConfig) DestChainNameToID(name string) sdk.ChainID {
return c.destChainNameToID[name]
}

func (c *crossChainConfig) ChannelIDs() []sdk.ChannelID {
unclezoro marked this conversation as resolved.
Show resolved Hide resolved
return c.channelIDs
}
15 changes: 15 additions & 0 deletions x/sidechain/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ func (k *Keeper) RegisterChannel(name string, id sdk.ChannelID, app sdk.CrossCha
if ok {
return fmt.Errorf("duplicated channel id")
}
k.cfg.channelIDs = append(k.cfg.channelIDs, id)
k.cfg.nameToChannelID[name] = id
k.cfg.channelIDToName[id] = name
k.cfg.channelIDToApp[id] = app
Expand Down Expand Up @@ -224,6 +225,16 @@ func (k *Keeper) incrSequence(ctx sdk.Context, destChainID sdk.ChainID, channelI
kvStore.Set(buildChannelSequenceKey(destChainID, channelID, prefix), sequenceBytes)
}

func (k *Keeper) IsBSCAllChannelClosed(ctx sdk.Context) bool {
kvStore := ctx.KVStore(k.storeKey)
return kvStore.Has(buildBSCAllChannelStatusPrefixKey(k.BscSideChainId(ctx)))
}

func (k *Keeper) SetBSCAllChannelClosed(ctx sdk.Context) {
kvStore := ctx.KVStore(k.storeKey)
kvStore.Set(buildBSCAllChannelStatusPrefixKey(k.BscSideChainId(ctx)), []byte{1})
}

func EndBlock(ctx sdk.Context, k Keeper) {
if sdk.IsUpgrade(sdk.LaunchBscUpgrade) && k.govKeeper != nil {
chanPermissions := k.getLastChanPermissionChanges(ctx)
Expand All @@ -242,3 +253,7 @@ func EndBlock(ctx sdk.Context, k Keeper) {
}
return
}

func (k *Keeper) Config() *crossChainConfig {
return k.cfg
}
6 changes: 6 additions & 0 deletions x/sidechain/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ var (
PrefixForReceiveSequenceKey = []byte{0xf1}

PrefixForChannelPermissionKey = []byte{0xc0}

PrefixForBSCAllChannelStatus = []byte{0xc1}
)

func GetSideChainStorePrefixKey(sideChainId string) []byte {
Expand Down Expand Up @@ -51,3 +53,7 @@ func buildChannelPermissionsPrefixKey(destChainID sdk.ChainID) []byte {
binary.BigEndian.PutUint16(key[prefixLength:prefixLength+destChainIDLength], uint16(destChainID))
return key
}

func buildBSCAllChannelStatusPrefixKey(sideChainId string) []byte {
return append(PrefixForBSCAllChannelStatus, []byte(sideChainId)...)
}
56 changes: 53 additions & 3 deletions x/stake/endblock.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,24 @@ import (

func EndBlocker(ctx sdk.Context, k keeper.Keeper) (validatorUpdates []abci.ValidatorUpdate, completedUbds []types.UnbondingDelegation) {
// only change validator set in breath block after BEP159
var events sdk.Events
var csEvents sdk.Events
var (
events sdk.Events
csEvents sdk.Events
)

if !sdk.IsUpgrade(sdk.BEP159) {
_, validatorUpdates, completedUbds, _, events = handleValidatorAndDelegations(ctx, k)
} else {
k.DistributeInBlock(ctx, types.ChainIDForBeaconChain)
validatorUpdates = k.PopPendingABCIValidatorUpdate(ctx)
}

var (
sideChainIds []string
storePrefixes [][]byte
)
if sdk.IsUpgrade(sdk.BEP128) {
sideChainIds, storePrefixes := k.ScKeeper.GetAllSideChainPrefixes(ctx)
sideChainIds, storePrefixes = k.ScKeeper.GetAllSideChainPrefixes(ctx)
if len(sideChainIds) == len(storePrefixes) {
for i := range storePrefixes {
sideChainCtx := ctx.WithSideChainKeyPrefix(storePrefixes[i])
Expand All @@ -31,9 +39,18 @@ func EndBlocker(ctx sdk.Context, k keeper.Keeper) (validatorUpdates []abci.Valid
panic("sideChainIds does not equal to sideChainStores")
}
}

if len(storePrefixes) > 0 && sdk.IsUpgrade(sdk.SecondSunsetFork) {
for i := range storePrefixes {
sideChainCtx := ctx.WithSideChainKeyPrefix(storePrefixes[i])
events.AppendEvents(handleRefundStake(sideChainCtx, k))
}
}

if sdk.IsUpgrade(sdk.BEP153) {
events = events.AppendEvents(csEvents)
}

ctx.EventManager().EmitEvents(events)
return
}
Expand Down Expand Up @@ -252,3 +269,36 @@ func handleMatureUnbondingDelegations(k keeper.Keeper, ctx sdk.Context) ([]types

return completed, events
}

const (
maxProcessedRefundCount = 10
)

func handleRefundStake(ctx sdk.Context, k keeper.Keeper) sdk.Events {
iterator := k.IteratorAllDelegations(ctx)
defer iterator.Close()
var refundEvents sdk.Events
count := 0
boundDenom := k.BondDenom(ctx)

for ; iterator.Valid(); iterator.Next() {
delegation := types.MustUnmarshalDelegation(k.CDC(), iterator.Key(), iterator.Value())
if delegation.CrossStake {
ctx = ctx.WithCrossStake(true)
}
result := handleMsgSideChainUndelegate(ctx, types.MsgSideChainUndelegate{
DelegatorAddr: delegation.DelegatorAddr,
ValidatorAddr: delegation.ValidatorAddr,
Amount: sdk.NewCoin(boundDenom, delegation.GetShares().RawInt()),
SideChainId: k.ScKeeper.BscSideChainId(ctx),
}, k)
refundEvents = refundEvents.AppendEvents(result.Events)

count++
if count >= maxProcessedRefundCount {
break
}
}

return refundEvents
}
18 changes: 18 additions & 0 deletions x/stake/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ func NewHandler(k keeper.Keeper, govKeeper gov.Keeper) sdk.Handler {
return handleMsgRemoveValidatorAfterProposal(ctx, msg, k, govKeeper)
// Beacon Chain New Staking in BEP-159
case types.MsgCreateValidatorOpen:
if sdk.IsUpgrade(sdk.FirstSunsetFork) {
return sdk.ErrMsgNotSupported("").Result()
}
if !sdk.IsUpgrade(sdk.BEP159Phase2) {
return sdk.ErrMsgNotSupported("BEP-159 Phase 2 not activated yet").Result()
}
Expand All @@ -40,16 +43,31 @@ func NewHandler(k keeper.Keeper, govKeeper gov.Keeper) sdk.Handler {
return handleMsgUndelegate(ctx, msg, k)
// case MsgSideChain
case types.MsgCreateSideChainValidator:
if sdk.IsUpgrade(sdk.FirstSunsetFork) {
return sdk.ErrMsgNotSupported("").Result()
}
return handleMsgCreateSideChainValidator(ctx, msg, k)
case types.MsgEditSideChainValidator:
return handleMsgEditSideChainValidator(ctx, msg, k)
case types.MsgCreateSideChainValidatorWithVoteAddr:
if sdk.IsUpgrade(sdk.FirstSunsetFork) {
return sdk.ErrMsgNotSupported("").Result()
}
return handleMsgCreateSideChainValidatorWithVoteAddr(ctx, msg, k)
case types.MsgEditSideChainValidatorWithVoteAddr:
if sdk.IsUpgrade(sdk.FirstSunsetFork) {
return sdk.ErrMsgNotSupported("").Result()
}
return handleMsgEditSideChainValidatorWithVoteAddr(ctx, msg, k)
case types.MsgSideChainDelegate:
if sdk.IsUpgrade(sdk.SecondSunsetFork) {
return sdk.ErrMsgNotSupported("").Result()
}
return handleMsgSideChainDelegate(ctx, msg, k)
case types.MsgSideChainRedelegate:
if sdk.IsUpgrade(sdk.SecondSunsetFork) {
return sdk.ErrMsgNotSupported("").Result()
}
return handleMsgSideChainRedelegate(ctx, msg, k)
unclezoro marked this conversation as resolved.
Show resolved Hide resolved
case types.MsgSideChainUndelegate:
return handleMsgSideChainUndelegate(ctx, msg, k)
Expand Down
Loading
Loading