nameservice: implement processing record and authority expiry
This commit is contained in:
parent
8477b3d9cb
commit
7f70108a4a
9
init.sh
9
init.sh
@ -34,10 +34,19 @@ cat $HOME/.chibaclonkd/config/genesis.json | jq '.app_state["gov"]["deposit_para
|
||||
cat $HOME/.chibaclonkd/config/genesis.json | jq '.app_state["mint"]["params"]["mint_denom"]="aphoton"' > $HOME/.chibaclonkd/config/tmp_genesis.json && mv $HOME/.chibaclonkd/config/tmp_genesis.json $HOME/.chibaclonkd/config/genesis.json
|
||||
# Custom modules
|
||||
cat $HOME/.chibaclonkd/config/genesis.json | jq '.app_state["nameservice"]["params"]["record_rent"]["denom"]="aphoton"' > $HOME/.chibaclonkd/config/tmp_genesis.json && mv $HOME/.chibaclonkd/config/tmp_genesis.json $HOME/.chibaclonkd/config/genesis.json
|
||||
cat $HOME/.chibaclonkd/config/genesis.json | jq '.app_state["nameservice"]["params"]["authority_rent"]["denom"]="aphoton"' > $HOME/.chibaclonkd/config/tmp_genesis.json && mv $HOME/.chibaclonkd/config/tmp_genesis.json $HOME/.chibaclonkd/config/genesis.json
|
||||
cat $HOME/.chibaclonkd/config/genesis.json | jq '.app_state["nameservice"]["params"]["authority_auction_commit_fee"]["denom"]="aphoton"' > $HOME/.chibaclonkd/config/tmp_genesis.json && mv $HOME/.chibaclonkd/config/tmp_genesis.json $HOME/.chibaclonkd/config/genesis.json
|
||||
cat $HOME/.chibaclonkd/config/genesis.json | jq '.app_state["nameservice"]["params"]["authority_auction_reveal_fee"]["denom"]="aphoton"' > $HOME/.chibaclonkd/config/tmp_genesis.json && mv $HOME/.chibaclonkd/config/tmp_genesis.json $HOME/.chibaclonkd/config/genesis.json
|
||||
cat $HOME/.chibaclonkd/config/genesis.json | jq '.app_state["nameservice"]["params"]["authority_auction_minimum_bid"]["denom"]="aphoton"' > $HOME/.chibaclonkd/config/tmp_genesis.json && mv $HOME/.chibaclonkd/config/tmp_genesis.json $HOME/.chibaclonkd/config/genesis.json
|
||||
|
||||
if [[ "$TEST_EXPIRY" == "true" ]]; then
|
||||
echo "Setting timers for expiry tests."
|
||||
|
||||
cat $HOME/.chibaclonkd/config/genesis.json | jq '.app_state["nameservice"]["params"]["record_rent_duration"]="60s"' > $HOME/.chibaclonkd/config/tmp_genesis.json && mv $HOME/.chibaclonkd/config/tmp_genesis.json $HOME/.chibaclonkd/config/genesis.json
|
||||
cat $HOME/.chibaclonkd/config/genesis.json | jq '.app_state["nameservice"]["params"]["authority_grace_period"]="60s"' > $HOME/.chibaclonkd/config/tmp_genesis.json && mv $HOME/.chibaclonkd/config/tmp_genesis.json $HOME/.chibaclonkd/config/genesis.json
|
||||
cat $HOME/.chibaclonkd/config/genesis.json | jq '.app_state["nameservice"]["params"]["authority_rent_duration"]="60s"' > $HOME/.chibaclonkd/config/tmp_genesis.json && mv $HOME/.chibaclonkd/config/tmp_genesis.json $HOME/.chibaclonkd/config/genesis.json
|
||||
fi
|
||||
|
||||
if [[ "$TEST_AUCTION_ENABLED" == "true" ]]; then
|
||||
echo "Enabling auction and setting timers."
|
||||
|
||||
|
@ -13,5 +13,8 @@ func BeginBlocker(ctx sdk.Context, k keeper.Keeper) {
|
||||
|
||||
// EndBlocker Called every block, update validator set
|
||||
func EndBlocker(ctx sdk.Context, k keeper.Keeper) []abci.ValidatorUpdate {
|
||||
k.ProcessRecordExpiryQueue(ctx)
|
||||
k.ProcessAuthorityExpiryQueue(ctx)
|
||||
|
||||
return []abci.ValidatorUpdate{}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package keeper
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"sort"
|
||||
"time"
|
||||
@ -302,6 +303,102 @@ func (k Keeper) InsertRecordExpiryQueue(ctx sdk.Context, val types.Record) {
|
||||
k.SetRecordExpiryQueueTimeSlice(ctx, expiryTime, timeSlice)
|
||||
}
|
||||
|
||||
// DeleteRecordExpiryQueue deletes a record CID from the record expiry queue.
|
||||
func (k Keeper) DeleteRecordExpiryQueue(ctx sdk.Context, record types.Record) {
|
||||
expiryTime, err := time.Parse(time.RFC3339, record.ExpiryTime)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
timeSlice := k.GetRecordExpiryQueueTimeSlice(ctx, expiryTime)
|
||||
var newTimeSlice []string
|
||||
|
||||
for _, cid := range timeSlice {
|
||||
if !bytes.Equal([]byte(cid), []byte(record.Id)) {
|
||||
newTimeSlice = append(newTimeSlice, cid)
|
||||
}
|
||||
}
|
||||
|
||||
if len(newTimeSlice) == 0 {
|
||||
k.DeleteRecordExpiryQueueTimeSlice(ctx, expiryTime)
|
||||
} else {
|
||||
k.SetRecordExpiryQueueTimeSlice(ctx, expiryTime, newTimeSlice)
|
||||
}
|
||||
}
|
||||
|
||||
// RecordExpiryQueueIterator returns all the record expiry queue timeslices from time 0 until endTime.
|
||||
func (k Keeper) RecordExpiryQueueIterator(ctx sdk.Context, endTime time.Time) sdk.Iterator {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
rangeEndBytes := sdk.InclusiveEndBytes(getRecordExpiryQueueTimeKey(endTime))
|
||||
return store.Iterator(PrefixExpiryTimeToRecordsIndex, rangeEndBytes)
|
||||
}
|
||||
|
||||
// GetAllExpiredRecords returns a concatenated list of all the timeslices before currTime.
|
||||
func (k Keeper) GetAllExpiredRecords(ctx sdk.Context, currTime time.Time) (expiredRecordCIDs []string) {
|
||||
// Gets an iterator for all timeslices from time 0 until the current block header time.
|
||||
itr := k.RecordExpiryQueueIterator(ctx, ctx.BlockHeader().Time)
|
||||
defer itr.Close()
|
||||
|
||||
for ; itr.Valid(); itr.Next() {
|
||||
timeslice, err := helpers.BytesArrToStringArr(itr.Value())
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
expiredRecordCIDs = append(expiredRecordCIDs, timeslice...)
|
||||
}
|
||||
|
||||
return expiredRecordCIDs
|
||||
}
|
||||
|
||||
// ProcessRecordExpiryQueue tries to renew expiring records (by collecting rent) else marks them as deleted.
|
||||
func (k Keeper) ProcessRecordExpiryQueue(ctx sdk.Context) {
|
||||
cids := k.GetAllExpiredRecords(ctx, ctx.BlockHeader().Time)
|
||||
for _, cid := range cids {
|
||||
record := k.GetRecord(ctx, cid)
|
||||
|
||||
// If record doesn't have an associated bond or if bond no longer exists, mark it deleted.
|
||||
if record.BondId == "" || !k.bondKeeper.HasBond(ctx, record.BondId) {
|
||||
record.Deleted = true
|
||||
k.PutRecord(ctx, record)
|
||||
k.DeleteRecordExpiryQueue(ctx, record)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Try to renew the record by taking rent.
|
||||
k.TryTakeRecordRent(ctx, record)
|
||||
}
|
||||
}
|
||||
|
||||
// TryTakeRecordRent tries to take rent from the record bond.
|
||||
func (k Keeper) TryTakeRecordRent(ctx sdk.Context, record types.Record) {
|
||||
params := k.GetParams(ctx)
|
||||
rent := params.RecordRent
|
||||
sdkErr := k.bondKeeper.TransferCoinsToModuleAccount(ctx, record.BondId, types.RecordRentModuleAccountName, sdk.NewCoins(rent))
|
||||
|
||||
if sdkErr != nil {
|
||||
// Insufficient funds, mark record as deleted.
|
||||
record.Deleted = true
|
||||
k.PutRecord(ctx, record)
|
||||
k.DeleteRecordExpiryQueue(ctx, record)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Delete old expiry queue entry, create new one.
|
||||
k.DeleteRecordExpiryQueue(ctx, record)
|
||||
record.ExpiryTime = ctx.BlockHeader().Time.Add(params.RecordRentDuration).Format(time.RFC3339)
|
||||
k.InsertRecordExpiryQueue(ctx, record)
|
||||
|
||||
// Save record.
|
||||
record.Deleted = false
|
||||
k.PutRecord(ctx, record)
|
||||
k.AddBondToRecordIndexEntry(ctx, record.BondId, record.Id)
|
||||
}
|
||||
|
||||
// GetModuleBalances gets the nameservice module account(s) balances.
|
||||
func (k Keeper) GetModuleBalances(ctx sdk.Context) []*types.AccountBalance {
|
||||
var balances []*types.AccountBalance
|
||||
|
@ -1,7 +1,12 @@
|
||||
package keeper
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
@ -9,9 +14,6 @@ import (
|
||||
auctiontypes "github.com/tharsis/ethermint/x/auction/types"
|
||||
"github.com/tharsis/ethermint/x/nameservice/helpers"
|
||||
"github.com/tharsis/ethermint/x/nameservice/types"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func getAuthorityPubKey(pubKey cryptotypes.PubKey) string {
|
||||
@ -596,6 +598,111 @@ func (k Keeper) SetAuthorityExpiryQueueTimeSlice(ctx sdk.Context, timestamp time
|
||||
store.Set(getAuthorityExpiryQueueTimeKey(timestamp), bz)
|
||||
}
|
||||
|
||||
// ProcessAuthorityExpiryQueue tries to renew expiring authorities (by collecting rent) else marks them as expired.
|
||||
func (k Keeper) ProcessAuthorityExpiryQueue(ctx sdk.Context) {
|
||||
names := k.GetAllExpiredAuthorities(ctx, ctx.BlockHeader().Time)
|
||||
for _, name := range names {
|
||||
authority := k.GetNameAuthority(ctx, name)
|
||||
|
||||
// If authority doesn't have an associated bond or if bond no longer exists, mark it expired.
|
||||
if authority.BondId == "" || !k.bondKeeper.HasBond(ctx, authority.BondId) {
|
||||
authority.Status = types.AuthorityExpired
|
||||
k.SetNameAuthority(ctx, name, &authority)
|
||||
k.DeleteAuthorityExpiryQueue(ctx, name, authority)
|
||||
|
||||
ctx.Logger().Info(fmt.Sprintf("Marking authority expired as no bond present: %s", name))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Try to renew the authority by taking rent.
|
||||
k.TryTakeAuthorityRent(ctx, name, authority)
|
||||
}
|
||||
}
|
||||
|
||||
// DeleteAuthorityExpiryQueueTimeSlice deletes a specific authority expiry queue timeslice.
|
||||
func (k Keeper) DeleteAuthorityExpiryQueueTimeSlice(ctx sdk.Context, timestamp time.Time) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
store.Delete(getAuthorityExpiryQueueTimeKey(timestamp))
|
||||
}
|
||||
|
||||
// DeleteAuthorityExpiryQueue deletes an authority name from the authority expiry queue.
|
||||
func (k Keeper) DeleteAuthorityExpiryQueue(ctx sdk.Context, name string, authority types.NameAuthority) {
|
||||
timeSlice := k.GetAuthorityExpiryQueueTimeSlice(ctx, authority.ExpiryTime)
|
||||
newTimeSlice := []string{}
|
||||
|
||||
for _, existingName := range timeSlice {
|
||||
if !bytes.Equal([]byte(existingName), []byte(name)) {
|
||||
newTimeSlice = append(newTimeSlice, existingName)
|
||||
}
|
||||
}
|
||||
|
||||
if len(newTimeSlice) == 0 {
|
||||
k.DeleteAuthorityExpiryQueueTimeSlice(ctx, authority.ExpiryTime)
|
||||
} else {
|
||||
k.SetAuthorityExpiryQueueTimeSlice(ctx, authority.ExpiryTime, newTimeSlice)
|
||||
}
|
||||
}
|
||||
|
||||
// GetAllExpiredAuthorities returns a concatenated list of all the timeslices before currTime.
|
||||
func (k Keeper) GetAllExpiredAuthorities(ctx sdk.Context, currTime time.Time) (expiredAuthorityNames []string) {
|
||||
// Gets an iterator for all timeslices from time 0 until the current block header time.
|
||||
itr := k.AuthorityExpiryQueueIterator(ctx, ctx.BlockHeader().Time)
|
||||
defer itr.Close()
|
||||
|
||||
for ; itr.Valid(); itr.Next() {
|
||||
timeslice := []string{}
|
||||
timeslice, err := helpers.BytesArrToStringArr(itr.Value())
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
expiredAuthorityNames = append(expiredAuthorityNames, timeslice...)
|
||||
}
|
||||
|
||||
return expiredAuthorityNames
|
||||
}
|
||||
|
||||
// AuthorityExpiryQueueIterator returns all the authority expiry queue timeslices from time 0 until endTime.
|
||||
func (k Keeper) AuthorityExpiryQueueIterator(ctx sdk.Context, endTime time.Time) sdk.Iterator {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
rangeEndBytes := sdk.InclusiveEndBytes(getAuthorityExpiryQueueTimeKey(endTime))
|
||||
return store.Iterator(PrefixExpiryTimeToAuthoritiesIndex, rangeEndBytes)
|
||||
}
|
||||
|
||||
// TryTakeAuthorityRent tries to take rent from the authority bond.
|
||||
func (k Keeper) TryTakeAuthorityRent(ctx sdk.Context, name string, authority types.NameAuthority) {
|
||||
ctx.Logger().Info(fmt.Sprintf("Trying to take rent for authority: %s", name))
|
||||
|
||||
params := k.GetParams(ctx)
|
||||
rent := params.AuthorityRent
|
||||
sdkErr := k.bondKeeper.TransferCoinsToModuleAccount(ctx, authority.BondId, types.AuthorityRentModuleAccountName, sdk.NewCoins(rent))
|
||||
|
||||
if sdkErr != nil {
|
||||
// Insufficient funds, mark authority as expired.
|
||||
authority.Status = types.AuthorityExpired
|
||||
k.SetNameAuthority(ctx, name, &authority)
|
||||
k.DeleteAuthorityExpiryQueue(ctx, name, authority)
|
||||
|
||||
ctx.Logger().Info(fmt.Sprintf("Insufficient funds in owner account to pay authority rent, marking as expired: %s", name))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Delete old expiry queue entry, create new one.
|
||||
k.DeleteAuthorityExpiryQueue(ctx, name, authority)
|
||||
authority.ExpiryTime = ctx.BlockTime().Add(params.AuthorityRentDuration)
|
||||
k.InsertAuthorityExpiryQueue(ctx, name, authority.ExpiryTime)
|
||||
|
||||
// Save authority.
|
||||
authority.Status = types.AuthorityActive
|
||||
k.SetNameAuthority(ctx, name, &authority)
|
||||
k.AddBondToAuthorityIndexEntry(ctx, authority.BondId, name)
|
||||
|
||||
ctx.Logger().Info(fmt.Sprintf("Authority rent paid successfully: %s", name))
|
||||
}
|
||||
|
||||
// ListNameAuthorityRecords - get all name authority records.
|
||||
func (k Keeper) ListNameAuthorityRecords(ctx sdk.Context) map[string]types.NameAuthority {
|
||||
nameAuthorityRecords := make(map[string]types.NameAuthority)
|
||||
|
Loading…
Reference in New Issue
Block a user