Skip to content

Commit

Permalink
feat: bc fusion hardfork implementation (#358)
Browse files Browse the repository at this point in the history
  • Loading branch information
j75689 authored Nov 29, 2023
1 parent 5a7b238 commit 065b547
Show file tree
Hide file tree
Showing 16 changed files with 242 additions and 14 deletions.
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 {
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)
case types.MsgSideChainUndelegate:
return handleMsgSideChainUndelegate(ctx, msg, k)
Expand Down
Loading

0 comments on commit 065b547

Please sign in to comment.