diff --git a/app/app.go b/app/app.go index 7f4dbc63..9d466e7a 100644 --- a/app/app.go +++ b/app/app.go @@ -22,13 +22,11 @@ import ( cbdbank "github.com/cybercongress/cyberd/x/bank" "github.com/cybercongress/cyberd/x/link" "github.com/cybercongress/cyberd/x/link/keeper" - lnk "github.com/cybercongress/cyberd/x/link/types" "github.com/cybercongress/cyberd/x/rank" abci "github.com/tendermint/tendermint/abci/types" cmn "github.com/tendermint/tendermint/libs/common" dbm "github.com/tendermint/tendermint/libs/db" "github.com/tendermint/tendermint/libs/log" - "math" "os" "sort" "time" @@ -57,11 +55,8 @@ type CyberdApp struct { txDecoder sdk.TxDecoder // bandwidth - bandwidthMeter bw.BandwidthMeter - //todo 3 fields below should be in bw meter - curBlockSpentBandwidth uint64 //resets every block - lastTotalSpentBandwidth uint64 //resets every bandwidth price adjustment interval - currentCreditPrice float64 + bandwidthMeter bw.BandwidthMeter + blockBandwidthKeeper bw.BlockSpentBandwidthKeeper // keys to access the multistore dbKeys CyberdAppDbKeys @@ -85,8 +80,6 @@ type CyberdApp struct { rankState *rank.RankState latestBlockHeight int64 - - // TODO: move to RankState??? } // NewBasecoinApp returns a reference to a new CyberdApp given a @@ -120,6 +113,7 @@ func NewCyberdApp( app.feeCollectionKeeper = NoopFeeCollectionKeeper{} app.paramsKeeper = params.NewKeeper(app.cdc, dbKeys.params, dbKeys.tParams) app.accBandwidthKeeper = bandwidth.NewAccBandwidthKeeper(dbKeys.accBandwidth) + app.blockBandwidthKeeper = bandwidth.NewBlockSpentBandwidthKeeper(dbKeys.blockBandwidth) app.accountKeeper = auth.NewAccountKeeper( app.cdc, dbKeys.acc, @@ -169,7 +163,8 @@ func NewCyberdApp( ) app.bandwidthMeter = bandwidth.NewBaseMeter( - app.accountKeeper, app.bankKeeper, app.accBandwidthKeeper, bandwidth.MsgBandwidthCosts, + app.mainKeeper, app.accountKeeper, app.bankKeeper, app.accBandwidthKeeper, bandwidth.MsgBandwidthCosts, + app.blockBandwidthKeeper, ) // register message routes @@ -202,6 +197,7 @@ func NewCyberdApp( ctx := app.BaseApp.NewContext(true, abci.Header{}) app.latestBlockHeight = int64(ms.GetLatestBlockNumber(ctx)) + ctx = ctx.WithBlockHeight(app.latestBlockHeight) // build context for current rank calculation round rankRoundBlockNumber := (app.latestBlockHeight / rank.CalculationPeriod) * rank.CalculationPeriod @@ -214,10 +210,8 @@ func NewCyberdApp( app.stakeIndex.Load(rankCtx, ctx) app.BaseApp.Logger.Info("App loaded", "time", time.Since(start)) - // BANDWIDTH PARAMS - app.lastTotalSpentBandwidth = ms.GetSpentBandwidth(ctx) - app.currentCreditPrice = math.Float64frombits(ms.GetBandwidthPrice(ctx, bandwidth.BaseCreditPrice)) - app.curBlockSpentBandwidth = 0 + // BANDWIDTH LOAD + app.bandwidthMeter.Load(ctx) // RANK PARAMS app.rankState.Load(ctx, app.latestBlockHeight, app.Logger) @@ -315,7 +309,7 @@ func (app *CyberdApp) CheckTx(txBytes []byte) (res abci.ResponseCheckTx) { if err == nil { - txCost := app.bandwidthMeter.GetTxCost(ctx, app.currentCreditPrice, tx) + txCost := app.bandwidthMeter.GetTxCost(ctx, tx) accBw := app.bandwidthMeter.GetCurrentAccBandwidth(ctx, acc) if !accBw.HasEnoughRemained(txCost) { @@ -348,7 +342,7 @@ func (app *CyberdApp) DeliverTx(txBytes []byte) (res abci.ResponseDeliverTx) { if err == nil { - txCost := app.bandwidthMeter.GetTxCost(ctx, app.currentCreditPrice, tx) + txCost := app.bandwidthMeter.GetTxCost(ctx, tx) accBw := app.bandwidthMeter.GetCurrentAccBandwidth(ctx, acc) if !accBw.HasEnoughRemained(txCost) { @@ -357,7 +351,7 @@ func (app *CyberdApp) DeliverTx(txBytes []byte) (res abci.ResponseDeliverTx) { resp := app.BaseApp.DeliverTx(txBytes) app.bandwidthMeter.ConsumeAccBandwidth(ctx, accBw, txCost) - app.curBlockSpentBandwidth = app.curBlockSpentBandwidth + uint64(txCost) + app.bandwidthMeter.AddToBlockBandwidth(uint64(txCost)) return abci.ResponseDeliverTx{ Code: uint32(resp.Code), @@ -453,13 +447,7 @@ func (app *CyberdApp) EndBlocker(ctx sdk.Context, _ abci.RequestEndBlock) abci.R validatorUpdates, tags := staking.EndBlocker(ctx, app.stakingKeeper) app.stakeIndex.EndBlocker(ctx) - newPrice, totalSpentBandwidth := bandwidth.EndBlocker( - ctx, app.lastTotalSpentBandwidth+app.curBlockSpentBandwidth, app.currentCreditPrice, - app.mainKeeper, app.bandwidthMeter, - ) - app.lastTotalSpentBandwidth = totalSpentBandwidth - app.currentCreditPrice = newPrice - app.curBlockSpentBandwidth = 0 + bandwidth.EndBlocker(ctx, app.bandwidthMeter) // RANK CALCULATION app.rankState.EndBlocker(ctx, app.Logger) diff --git a/app/fee.go b/app/fee.go index 4abf71e5..5d2e576a 100644 --- a/app/fee.go +++ b/app/fee.go @@ -2,17 +2,13 @@ package app import ( sdk "github.com/cosmos/cosmos-sdk/types" - "log" ) var noCoins = sdk.Coins{} -//__________________________________________________________________________________ -// fee collection keeper used only for testing type NoopFeeCollectionKeeper struct{} func (fck NoopFeeCollectionKeeper) AddCollectedFees(_ sdk.Context, c sdk.Coins) sdk.Coins { - log.Println(c.String()) return noCoins } diff --git a/app/keys.go b/app/keys.go index 5d2c6167..2c490c45 100644 --- a/app/keys.go +++ b/app/keys.go @@ -12,51 +12,52 @@ import ( ) type CyberdAppDbKeys struct { - main *sdk.KVStoreKey - acc *sdk.KVStoreKey - accIndex *sdk.KVStoreKey - cidNum *sdk.KVStoreKey - cidNumReverse *sdk.KVStoreKey - links *sdk.KVStoreKey - rank *sdk.KVStoreKey - stake *sdk.KVStoreKey - tStake *sdk.TransientStoreKey - distr *sdk.KVStoreKey - tDistr *sdk.TransientStoreKey - slashing *sdk.KVStoreKey + main *sdk.KVStoreKey + acc *sdk.KVStoreKey + accIndex *sdk.KVStoreKey + cidNum *sdk.KVStoreKey + cidNumReverse *sdk.KVStoreKey + links *sdk.KVStoreKey + rank *sdk.KVStoreKey + stake *sdk.KVStoreKey + tStake *sdk.TransientStoreKey + distr *sdk.KVStoreKey + tDistr *sdk.TransientStoreKey + slashing *sdk.KVStoreKey mint *sdk.KVStoreKey - params *sdk.KVStoreKey - tParams *sdk.TransientStoreKey - accBandwidth *sdk.KVStoreKey + params *sdk.KVStoreKey + tParams *sdk.TransientStoreKey + accBandwidth *sdk.KVStoreKey + blockBandwidth *sdk.KVStoreKey } func NewCyberdAppDbKeys() CyberdAppDbKeys { return CyberdAppDbKeys{ - - main: sdk.NewKVStoreKey(bam.MainStoreKey), - acc: sdk.NewKVStoreKey(auth.StoreKey), - stake: sdk.NewKVStoreKey(staking.StoreKey), - tStake: sdk.NewTransientStoreKey(staking.TStoreKey), - mint: sdk.NewKVStoreKey(mint.StoreKey), - distr: sdk.NewKVStoreKey(distr.StoreKey), + main: sdk.NewKVStoreKey(bam.MainStoreKey), + acc: sdk.NewKVStoreKey(auth.StoreKey), + stake: sdk.NewKVStoreKey(staking.StoreKey), + tStake: sdk.NewTransientStoreKey(staking.TStoreKey), + mint: sdk.NewKVStoreKey(mint.StoreKey), + distr: sdk.NewKVStoreKey(distr.StoreKey), tDistr: sdk.NewTransientStoreKey(distr.TStoreKey), - slashing: sdk.NewKVStoreKey(slashing.StoreKey), - params: sdk.NewKVStoreKey(params.StoreKey), - tParams: sdk.NewTransientStoreKey(params.TStoreKey), + slashing: sdk.NewKVStoreKey(slashing.StoreKey), + params: sdk.NewKVStoreKey(params.StoreKey), + tParams: sdk.NewTransientStoreKey(params.TStoreKey), - cidNum: sdk.NewKVStoreKey("cid_index"), - cidNumReverse: sdk.NewKVStoreKey("cid_index_reverse"), + cidNum: sdk.NewKVStoreKey("cid_index"), + cidNumReverse: sdk.NewKVStoreKey("cid_index_reverse"), links: sdk.NewKVStoreKey("links"), - rank: sdk.NewKVStoreKey("rank"), - accBandwidth: sdk.NewKVStoreKey("acc_bandwidth"), + rank: sdk.NewKVStoreKey("rank"), + accBandwidth: sdk.NewKVStoreKey("acc_bandwidth"), + blockBandwidth: sdk.NewKVStoreKey("block_spent_bandwidth"), } } func (k CyberdAppDbKeys) GetStoreKeys() []*sdk.KVStoreKey { return []*sdk.KVStoreKey{ k.main, k.acc, k.cidNum, k.cidNumReverse, k.links, k.rank, k.stake, - k.slashing, k.params, k.distr, k.mint, k.accBandwidth, + k.slashing, k.params, k.distr, k.mint, k.accBandwidth, k.blockBandwidth, } } diff --git a/app/rpc.go b/app/rpc.go index dea92a1b..8b2c9677 100644 --- a/app/rpc.go +++ b/app/rpc.go @@ -67,7 +67,7 @@ func (app *CyberdApp) IsLinkExist(from cbdlink.Cid, to cbdlink.Cid, address sdk. } func (app *CyberdApp) CurrentBandwidthPrice() float64 { - return app.currentCreditPrice + return app.bandwidthMeter.GetCurrentCreditPrice() } func (app *CyberdApp) CidsCount() uint64 { diff --git a/wiki/cid.go b/wiki/cid.go deleted file mode 100644 index e736d7b6..00000000 --- a/wiki/cid.go +++ /dev/null @@ -1,19 +0,0 @@ -package main - -import ( - links "github.com/cybercongress/cyberd/x/link/types" - "github.com/ipfs/go-cid" - "github.com/multiformats/go-multihash" -) - -var pref = cid.Prefix{ - Version: 0, - Codec: cid.Raw, - MhType: multihash.SHA2_256, - MhLength: -1, // default length -} - -func Cid(data string) links.Cid { - result, _ := pref.Sum([]byte(data)) - return links.Cid(result.String()) -} diff --git a/wiki/index.go b/wiki/index.go deleted file mode 100644 index 3b209fa6..00000000 --- a/wiki/index.go +++ /dev/null @@ -1,83 +0,0 @@ -package main - -import ( - "bufio" - "fmt" - "github.com/cybercongress/cyberd/client" - "os" - "regexp" - "strings" - "unicode" -) - -func ContinueIndex(cbdClient client.CyberdClient) { - - startArticleId := int64(1) - - f, err := os.OpenFile("enwiki-latest-all-titles", 0, 0) - if err != nil { - panic(err) - } - br := bufio.NewReader(f) - defer f.Close() - - reg, err := regexp.Compile("[^a-zA-Z0-9]+") - - counter := int64(0) - links := make([]client.Link, 0, 1000) - for { - - line, err := br.ReadString('\n') - - if err != nil { - break - } - - if counter < startArticleId { - counter++ - continue - } - - split := strings.Split(strings.TrimSuffix(line, "\n"), "\t") - ids := strings.Split(split[1], "_") - - idsSet := make(map[string]struct{}) - for _, id := range ids { - idsSet[id] = struct{}{} - } - - for id := range idsSet { - - id = reg.ReplaceAllString(id, "") - id = strings.ToLower(id) - - if len(id) == 0 || id == "" { - continue - } - - if len(id) == 1 && unicode.IsSymbol(rune(id[0])) { - continue - } - - page := split[1] + ".wiki" - links = append(links, client.Link{From: Cid(id), To: Cid(page)}) - counter++ - - if len(links) == 1000 { - fmt.Printf("%d %s\n", counter, split[1]) - - accBw, err := cbdClient.GetAccountBandwidth() - if err == nil { - per := int64(100 * float64(accBw.RemainedValue) / float64(accBw.MaxValue)) - fmt.Printf("Remaining acc bw: %d %v%%\n", accBw.RemainedValue, per) - } - - err = cbdClient.SubmitLinksSync(links) - if err != nil { - panic(err.Error()) - } - links = make([]client.Link, 0, 1000) - } - } - } -} diff --git a/wiki/wiki.go b/wiki/wiki.go deleted file mode 100644 index 4b598d74..00000000 --- a/wiki/wiki.go +++ /dev/null @@ -1,53 +0,0 @@ -package main - -import ( - "fmt" - "github.com/cybercongress/cyberd/client" - "github.com/mitchellh/go-homedir" - "github.com/spf13/cobra" - "github.com/spf13/viper" - "os" -) - -/* -./wiki start ---node=127.0.0.1:34657 --passphrase=1q2w3e4r \ ---address=cosmos1g7e74lxpwlcsza8v0nca2hwahluqcv4r4d3p8p \ -*/ - -func main() { - - homeDir, err := homedir.Dir() - if err != nil { - fmt.Println(err) - os.Exit(1) - } - - cmd := &cobra.Command{ - Use: "start", - Short: "Start wiki indexing", - RunE: func(cmd *cobra.Command, args []string) error { - address := viper.GetString(client.FlagAddress) - nodeUrl := viper.GetString(client.FlagNode) - pasphrase := viper.GetString(client.FlagPassphrase) - cyberdClient := client.NewHttpCyberdClient(nodeUrl, pasphrase, address) - ContinueIndex(cyberdClient) - return nil - }, - } - - cmd.Flags().String(client.FlagAddress, "", "Account to sign transactions") - cmd.Flags().String(client.FlagPassphrase, "", "Passphrase of account") - cmd.Flags().String(client.FlagNode, "127.0.0.1:26657", "Url of node communicate with") - cmd.Flags().String(client.FlagHome, homeDir+"/.cyberdcli", "Cyberd CLI home folder") - - _ = viper.BindPFlag(client.FlagPassphrase, cmd.Flags().Lookup(client.FlagPassphrase)) - _ = viper.BindPFlag(client.FlagAddress, cmd.Flags().Lookup(client.FlagAddress)) - _ = viper.BindPFlag(client.FlagNode, cmd.Flags().Lookup(client.FlagNode)) - _ = viper.BindPFlag(client.FlagHome, cmd.Flags().Lookup(client.FlagHome)) - - if err := cmd.Execute(); err != nil { - fmt.Println(err) - os.Exit(1) - } -} diff --git a/x/bandwidth/abci.go b/x/bandwidth/abci.go index 41042ced..c8865aa2 100644 --- a/x/bandwidth/abci.go +++ b/x/bandwidth/abci.go @@ -2,9 +2,7 @@ package bandwidth import ( sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cybercongress/cyberd/store" "github.com/cybercongress/cyberd/x/bandwidth/types" - "math" ) var accsToUpdate = make([]sdk.AccAddress, 0) @@ -37,25 +35,11 @@ func CollectAddressesWithStakeChange() func(ctx sdk.Context, from sdk.AccAddress // 2. For accs with updated on current block stake adjust max bandwidth. Why not update on `onCoinsTransfer`? // Cuz for some bound related operations, coins already added/reduced from acc, but not added to // validator\delegator pool. -func EndBlocker( - ctx sdk.Context, totalSpentForPeriod uint64, curPrice float64, ms store.MainKeeper, meter types.BandwidthMeter, -) (newPrice float64, totalSpent uint64) { +func EndBlocker(ctx sdk.Context, meter types.BandwidthMeter) { - newPrice = curPrice if ctx.BlockHeight() != 0 && ctx.BlockHeight()%AdjustPricePeriod == 0 { - averageSpentValue := DesirableNetworkBandwidthForRecoveryPeriod / (RecoveryPeriod / AdjustPricePeriod) - newPrice = float64(totalSpentForPeriod) / float64(averageSpentValue) - - if newPrice < 0.01*BaseCreditPrice { - newPrice = 0.01 * BaseCreditPrice - } - - ms.StoreBandwidthPrice(ctx, math.Float64bits(newPrice)) - ms.StoreSpentBandwidth(ctx, 0) - totalSpentForPeriod = 0 + meter.AdjustPrice(ctx) } - - ms.StoreSpentBandwidth(ctx, totalSpentForPeriod) + meter.CommitBlockBandwidth(ctx) updateAccMaxBandwidth(ctx, meter) - return newPrice, totalSpentForPeriod } diff --git a/x/bandwidth/keeper.go b/x/bandwidth/keeper.go index 8db26b47..5670b614 100644 --- a/x/bandwidth/keeper.go +++ b/x/bandwidth/keeper.go @@ -1,6 +1,7 @@ package bandwidth import ( + "encoding/binary" "encoding/json" sdk "github.com/cosmos/cosmos-sdk/types" . "github.com/cybercongress/cyberd/x/bandwidth/types" @@ -38,3 +39,41 @@ func (bk BaseAccBandwidthKeeper) GetAccBandwidth(ctx sdk.Context, addr sdk.AccAd } return } + +type BaseBlockSpentBandwidthKeeper struct { + key *sdk.KVStoreKey +} + +func NewBlockSpentBandwidthKeeper(key *sdk.KVStoreKey) BaseBlockSpentBandwidthKeeper { + return BaseBlockSpentBandwidthKeeper{key: key} +} + +func (bk BaseBlockSpentBandwidthKeeper) SetBlockSpentBandwidth(ctx sdk.Context, blockNumber uint64, value uint64) { + keyAsBytes := make([]byte, 8) + binary.LittleEndian.PutUint64(keyAsBytes, blockNumber) + valueAsBytes := make([]byte, 8) + binary.LittleEndian.PutUint64(valueAsBytes, value) + ctx.KVStore(bk.key).Set(keyAsBytes, valueAsBytes) +} + +func (bk BaseBlockSpentBandwidthKeeper) GetValuesForPeriod(ctx sdk.Context, period int64) map[uint64]uint64 { + + startKey := make([]byte, 8) + binary.LittleEndian.PutUint64(startKey, uint64(ctx.BlockHeight()-period+1)) + + endKey := make([]byte, 8) + binary.LittleEndian.PutUint64(endKey, uint64(ctx.BlockHeight())) + + iterator := ctx.KVStore(bk.key).Iterator(startKey, sdk.PrefixEndBytes(endKey)) + defer iterator.Close() + + result := make(map[uint64]uint64) + for iterator.Valid() { + blockNumber := binary.LittleEndian.Uint64(iterator.Key()) + value := binary.LittleEndian.Uint64(iterator.Value()) + result[blockNumber] = value + iterator.Next() + } + + return result +} diff --git a/x/bandwidth/meter.go b/x/bandwidth/meter.go index d1625478..73009864 100644 --- a/x/bandwidth/meter.go +++ b/x/bandwidth/meter.go @@ -3,56 +3,120 @@ package bandwidth import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cybercongress/cyberd/store" "github.com/cybercongress/cyberd/x/bandwidth/types" + "math" ) var _ types.BandwidthMeter = BaseBandwidthMeter{} type BaseBandwidthMeter struct { // data providers - accKeeper auth.AccountKeeper - stakeProvider types.AccStakeProvider - bwKeeper types.Keeper + accKeeper auth.AccountKeeper + stakeProvider types.AccStakeProvider + bwKeeper types.Keeper + mainKeeper store.MainKeeper + blockBandwidthKeeper types.BlockSpentBandwidthKeeper // bw configuration msgCost types.MsgBandwidthCost + + // price adjustment fields + curBlockSpentBandwidth *uint64 //resets every block + currentCreditPrice *float64 + bandwidthSpent map[uint64]uint64 // bandwidth spent by blocks + totalSpentForSlidingWindow *uint64 } func NewBaseMeter( - ak auth.AccountKeeper, sp types.AccStakeProvider, bwKeeper types.Keeper, msgCost types.MsgBandwidthCost, + mainKeeper store.MainKeeper, ak auth.AccountKeeper, sp types.AccStakeProvider, bwKeeper types.Keeper, + msgCost types.MsgBandwidthCost, blockBandwidthKeeper types.BlockSpentBandwidthKeeper, ) BaseBandwidthMeter { return BaseBandwidthMeter{ - accKeeper: ak, - stakeProvider: sp, - bwKeeper: bwKeeper, - msgCost: msgCost, + mainKeeper: mainKeeper, + blockBandwidthKeeper: blockBandwidthKeeper, + accKeeper: ak, + stakeProvider: sp, + bwKeeper: bwKeeper, + msgCost: msgCost, + curBlockSpentBandwidth: new(uint64), + currentCreditPrice: new(float64), + totalSpentForSlidingWindow: new(uint64), + bandwidthSpent: make(map[uint64]uint64), } } -func (h BaseBandwidthMeter) GetTxCost(ctx sdk.Context, price float64, tx sdk.Tx) int64 { +func (m BaseBandwidthMeter) Load(ctx sdk.Context) { + *m.totalSpentForSlidingWindow = 0 + for blockNum, spentBandwidth := range m.blockBandwidthKeeper.GetValuesForPeriod(ctx, SlidingWindowSize) { + m.bandwidthSpent[blockNum] = spentBandwidth + *m.totalSpentForSlidingWindow += spentBandwidth + } + *m.currentCreditPrice = math.Float64frombits(m.mainKeeper.GetBandwidthPrice(ctx, BaseCreditPrice)) + *m.curBlockSpentBandwidth = 0 +} + +func (m BaseBandwidthMeter) AddToBlockBandwidth(value uint64) { + // we have to divide by price here to get base price value + *m.curBlockSpentBandwidth += uint64(float64(value) / *m.currentCreditPrice) +} + +// Here we move bandwidth window: +// Remove first block of window and add new block to window end +func (m BaseBandwidthMeter) CommitBlockBandwidth(ctx sdk.Context) { + *m.totalSpentForSlidingWindow += *m.curBlockSpentBandwidth + + newWindowEnd := ctx.BlockHeight() + windowStart := newWindowEnd - SlidingWindowSize + if windowStart < 0 { // check needed cause it will be casted to uint and can cause overflow + windowStart = 0 + } + windowStartValue, exists := m.bandwidthSpent[uint64(windowStart)] + if exists { + *m.totalSpentForSlidingWindow -= windowStartValue + delete(m.bandwidthSpent, uint64(windowStart)) + } + m.blockBandwidthKeeper.SetBlockSpentBandwidth(ctx, uint64(ctx.BlockHeight()), *m.curBlockSpentBandwidth) + m.bandwidthSpent[uint64(newWindowEnd)] = *m.curBlockSpentBandwidth + *m.curBlockSpentBandwidth = 0 +} + +func (m BaseBandwidthMeter) AdjustPrice(ctx sdk.Context) { + + newPrice := float64(*m.totalSpentForSlidingWindow) / float64(ShouldBeSpentPerSlidingWindow) + + if newPrice < 0.01*BaseCreditPrice { + newPrice = 0.01 * BaseCreditPrice + } + + *m.currentCreditPrice = newPrice + m.mainKeeper.StoreBandwidthPrice(ctx, math.Float64bits(newPrice)) +} + +func (m BaseBandwidthMeter) GetTxCost(ctx sdk.Context, tx sdk.Tx) int64 { bandwidthForTx := TxCost for _, msg := range tx.GetMsgs() { - bandwidthForTx = bandwidthForTx + h.msgCost(msg) + bandwidthForTx = bandwidthForTx + m.msgCost(msg) } - return int64(float64(bandwidthForTx) * price) + return int64(float64(bandwidthForTx) * *m.currentCreditPrice) } -func (h BaseBandwidthMeter) GetAccMaxBandwidth(ctx sdk.Context, addr sdk.AccAddress) int64 { - accStakePercentage := h.stakeProvider.GetAccStakePercentage(ctx, addr) +func (m BaseBandwidthMeter) GetAccMaxBandwidth(ctx sdk.Context, addr sdk.AccAddress) int64 { + accStakePercentage := m.stakeProvider.GetAccStakePercentage(ctx, addr) return int64(accStakePercentage * float64(DesirableNetworkBandwidthForRecoveryPeriod)) } -func (h BaseBandwidthMeter) GetCurrentAccBandwidth(ctx sdk.Context, address sdk.AccAddress) types.AcсBandwidth { - accBw := h.bwKeeper.GetAccBandwidth(ctx, address) - accMaxBw := h.GetAccMaxBandwidth(ctx, address) +func (m BaseBandwidthMeter) GetCurrentAccBandwidth(ctx sdk.Context, address sdk.AccAddress) types.AcсBandwidth { + accBw := m.bwKeeper.GetAccBandwidth(ctx, address) + accMaxBw := m.GetAccMaxBandwidth(ctx, address) accBw.UpdateMax(accMaxBw, ctx.BlockHeight(), RecoveryPeriod) return accBw } -func (h BaseBandwidthMeter) UpdateAccMaxBandwidth(ctx sdk.Context, address sdk.AccAddress) { - bw := h.GetCurrentAccBandwidth(ctx, address) - h.bwKeeper.SetAccBandwidth(ctx, bw) +func (m BaseBandwidthMeter) UpdateAccMaxBandwidth(ctx sdk.Context, address sdk.AccAddress) { + bw := m.GetCurrentAccBandwidth(ctx, address) + m.bwKeeper.SetAccBandwidth(ctx, bw) } // @@ -63,9 +127,13 @@ func (h BaseBandwidthMeter) UpdateAccMaxBandwidth(ctx sdk.Context, address sdk.A // bw := getCurrentBw(addr) // bwCost := deliverTx(tx) // consumeBw(bw, bwCost) -func (h BaseBandwidthMeter) ConsumeAccBandwidth(ctx sdk.Context, bw types.AcсBandwidth, amt int64) { +func (m BaseBandwidthMeter) ConsumeAccBandwidth(ctx sdk.Context, bw types.AcсBandwidth, amt int64) { bw.Consume(amt) - h.bwKeeper.SetAccBandwidth(ctx, bw) - bw = h.GetCurrentAccBandwidth(ctx, bw.Address) - h.bwKeeper.SetAccBandwidth(ctx, bw) + m.bwKeeper.SetAccBandwidth(ctx, bw) + bw = m.GetCurrentAccBandwidth(ctx, bw.Address) + m.bwKeeper.SetAccBandwidth(ctx, bw) +} + +func (m BaseBandwidthMeter) GetCurrentCreditPrice() float64 { + return *m.currentCreditPrice } diff --git a/x/bandwidth/params.go b/x/bandwidth/params.go index 84a9921e..04227e5a 100644 --- a/x/bandwidth/params.go +++ b/x/bandwidth/params.go @@ -12,6 +12,8 @@ const ( // Number of blocks to recover full bandwidth RecoveryPeriod = 60 * 60 * 24 // Number of blocks before next adjust price - AdjustPricePeriod = 60 * 10 - BaseCreditPrice float64 = 1.0 + AdjustPricePeriod = 60 * 10 + BaseCreditPrice float64 = 1.0 + SlidingWindowSize = RecoveryPeriod / 2 + ShouldBeSpentPerSlidingWindow = float64(DesirableNetworkBandwidthForRecoveryPeriod) / (float64(RecoveryPeriod) / float64(SlidingWindowSize)) ) diff --git a/x/bandwidth/types/keeper.go b/x/bandwidth/types/keeper.go index 90bc076a..fa596996 100644 --- a/x/bandwidth/types/keeper.go +++ b/x/bandwidth/types/keeper.go @@ -8,3 +8,8 @@ type Keeper interface { SetAccBandwidth(ctx sdk.Context, bandwidth AcсBandwidth) GetAccBandwidth(ctx sdk.Context, address sdk.AccAddress) (bw AcсBandwidth) } + +type BlockSpentBandwidthKeeper interface { + SetBlockSpentBandwidth(ctx sdk.Context, blockNumber uint64, value uint64) + GetValuesForPeriod(ctx sdk.Context, period int64) map[uint64]uint64 +} \ No newline at end of file diff --git a/x/bandwidth/types/meter.go b/x/bandwidth/types/meter.go index 638fc9fe..ed979c01 100644 --- a/x/bandwidth/types/meter.go +++ b/x/bandwidth/types/meter.go @@ -15,6 +15,16 @@ type AccStakeProvider interface { // 4. Consume bw and save with old max bw value // 5. Load bw with new max value and save it type BandwidthMeter interface { + // load current bandwidth state after restart + Load(ctx sdk.Context) + // add value to consumed bandwidth for current block + AddToBlockBandwidth(value uint64) + // adjust price based on 24h loading + AdjustPrice(ctx sdk.Context) + // get current bandwidth price + GetCurrentCreditPrice() float64 + // commit bandwidth value spent for current block + CommitBlockBandwidth(ctx sdk.Context) // Update acc max bandwidth for current stake. Also, performs recover. UpdateAccMaxBandwidth(ctx sdk.Context, address sdk.AccAddress) // Returns recovered to current block height acc bandwidth @@ -22,7 +32,7 @@ type BandwidthMeter interface { // Returns acc max bandwidth GetAccMaxBandwidth(ctx sdk.Context, address sdk.AccAddress) int64 // Returns tx bandwidth cost - GetTxCost(ctx sdk.Context, price float64, tx sdk.Tx) int64 + GetTxCost(ctx sdk.Context, tx sdk.Tx) int64 // // Performs bw consumption for given acc // To get right number, should be called after tx delivery with bw state obtained prior delivery