github.com/Finschia/finschia-sdk@v0.49.1/x/fbridge/keeper/keeper.go (about)

     1  package keeper
     2  
     3  import (
     4  	"encoding/binary"
     5  	"errors"
     6  	"fmt"
     7  
     8  	"github.com/Finschia/ostracon/libs/log"
     9  
    10  	"github.com/Finschia/finschia-sdk/codec"
    11  	sdk "github.com/Finschia/finschia-sdk/types"
    12  	"github.com/Finschia/finschia-sdk/x/fbridge/types"
    13  )
    14  
    15  type Keeper struct {
    16  	storeKey   sdk.StoreKey
    17  	memKey     sdk.StoreKey
    18  	cdc        codec.BinaryCodec
    19  	authKeeper types.AccountKeeper
    20  	bankKeeper types.BankKeeper
    21  
    22  	// authority can give a role to a specific address like guardian
    23  	authority string
    24  }
    25  
    26  func NewKeeper(
    27  	cdc codec.BinaryCodec,
    28  	key, memKey sdk.StoreKey,
    29  	authKeeper types.AccountKeeper,
    30  	bankKeeper types.BankKeeper,
    31  	authority string,
    32  ) Keeper {
    33  	if addr := authKeeper.GetModuleAddress(types.ModuleName); addr == nil {
    34  		panic(errors.New("fbridge module account has not been set"))
    35  	}
    36  
    37  	found := false
    38  	for _, addr := range types.AuthorityCandiates() {
    39  		if authority == addr.String() {
    40  			found = true
    41  			break
    42  		}
    43  	}
    44  
    45  	if !found {
    46  		panic("x/bridge authority must be the gov or foundation module account")
    47  	}
    48  
    49  	return Keeper{
    50  		storeKey:   key,
    51  		memKey:     memKey,
    52  		cdc:        cdc,
    53  		authKeeper: authKeeper,
    54  		bankKeeper: bankKeeper,
    55  		authority:  authority,
    56  	}
    57  }
    58  
    59  func (k Keeper) Logger(ctx sdk.Context) log.Logger {
    60  	return ctx.Logger().With("module", "x/"+types.ModuleName)
    61  }
    62  
    63  func (k Keeper) InitMemStore(ctx sdk.Context) {
    64  	memStore := ctx.KVStore(k.memKey)
    65  	memStoreType := memStore.GetStoreType()
    66  	if memStoreType != sdk.StoreTypeMemory {
    67  		panic(fmt.Sprintf("invalid memory store type; got %s, expected: %s", memStoreType, sdk.StoreTypeMemory))
    68  	}
    69  
    70  	// create context with no block gas meter to ensure we do not consume gas during local initialization logic.
    71  	noGasCtx := ctx.WithBlockGasMeter(sdk.NewInfiniteGasMeter())
    72  
    73  	roleMetadata := types.RoleMetadata{}
    74  	if !k.IsInitialized(noGasCtx) {
    75  		for _, pair := range k.GetRolePairs(noGasCtx) {
    76  			switch pair.Role {
    77  			case types.RoleGuardian:
    78  				roleMetadata.Guardian++
    79  			case types.RoleOperator:
    80  				roleMetadata.Operator++
    81  			case types.RoleJudge:
    82  				roleMetadata.Judge++
    83  			}
    84  		}
    85  		k.setRoleMetadata(noGasCtx, roleMetadata)
    86  
    87  		nInactive := uint64(0)
    88  		for _, bs := range k.GetBridgeSwitches(ctx) {
    89  			if bs.Status == types.StatusInactive {
    90  				nInactive++
    91  			}
    92  		}
    93  		k.setBridgeInactiveCounter(noGasCtx, nInactive)
    94  
    95  		memStore := noGasCtx.KVStore(k.memKey)
    96  		memStore.Set(types.KeyMemInitialized, []byte{1})
    97  	}
    98  }
    99  
   100  // IsInitialized returns true if the keeper is properly initialized, and false otherwise.
   101  func (k Keeper) IsInitialized(ctx sdk.Context) bool {
   102  	memStore := ctx.KVStore(k.memKey)
   103  	return memStore.Get(types.KeyMemInitialized) != nil
   104  }
   105  
   106  func (k Keeper) GetAuthority() string {
   107  	return k.authority
   108  }
   109  
   110  func (k Keeper) IsBridgeHalted(ctx sdk.Context) bool {
   111  	return k.GetBridgeStatus(ctx) == types.StatusInactive
   112  }
   113  
   114  func (k Keeper) setRoleMetadata(ctx sdk.Context, data types.RoleMetadata) {
   115  	memStore := ctx.KVStore(k.memKey)
   116  	bz := k.cdc.MustMarshal(&data)
   117  	memStore.Set(types.KeyMemRoleMetadata, bz)
   118  }
   119  
   120  func (k Keeper) GetRoleMetadata(ctx sdk.Context) types.RoleMetadata {
   121  	memStore := ctx.KVStore(k.memKey)
   122  	data := types.RoleMetadata{}
   123  	bz := memStore.Get(types.KeyMemRoleMetadata)
   124  	if bz == nil {
   125  		return types.RoleMetadata{}
   126  	}
   127  	k.cdc.MustUnmarshal(bz, &data)
   128  	return data
   129  }
   130  
   131  func (k Keeper) GetBridgeStatus(ctx sdk.Context) types.BridgeStatus {
   132  	roleMeta := k.GetRoleMetadata(ctx)
   133  	if roleMeta.Guardian != 0 {
   134  		bsMeta := k.GetBridgeStatusMetadata(ctx)
   135  		if types.CheckTrustLevelThreshold(roleMeta.Guardian, bsMeta.Inactive, k.GetParams(ctx).GuardianTrustLevel) {
   136  			return types.StatusInactive
   137  		}
   138  
   139  		return types.StatusActive
   140  	}
   141  
   142  	return types.StatusInactive
   143  }
   144  
   145  func (k Keeper) setBridgeInactiveCounter(ctx sdk.Context, nInactive uint64) {
   146  	memStore := ctx.KVStore(k.memKey)
   147  	bz := make([]byte, 8)
   148  	binary.BigEndian.PutUint64(bz, nInactive)
   149  	memStore.Set(types.KeyMemBridgeInactiveCounter, bz)
   150  }
   151  
   152  func (k Keeper) GetBridgeInactiveCounter(ctx sdk.Context) uint64 {
   153  	memStore := ctx.KVStore(k.memKey)
   154  	bz := memStore.Get(types.KeyMemBridgeInactiveCounter)
   155  	if bz == nil {
   156  		panic("bridge inactive counter must be set at initialization")
   157  	}
   158  
   159  	return binary.BigEndian.Uint64(bz)
   160  }
   161  
   162  func (k Keeper) GetBridgeStatusMetadata(ctx sdk.Context) types.BridgeStatusMetadata {
   163  	bsMeta := types.BridgeStatusMetadata{}
   164  	bsMeta.Inactive = k.GetBridgeInactiveCounter(ctx)
   165  	bsMeta.Active = k.GetRoleMetadata(ctx).Guardian - bsMeta.Inactive
   166  	return bsMeta
   167  }