Skip to content

Commit

Permalink
#179 Change Bandwidth Price to Average for 24h Sliding Window. Notes …
Browse files Browse the repository at this point in the history
…fixes
  • Loading branch information
arturalbov authored and hleb-albau committed Jan 31, 2019
1 parent 5b46eae commit 649bd7b
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 42 deletions.
6 changes: 3 additions & 3 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ func (app *CyberdApp) CheckTx(txBytes []byte) (res abci.ResponseCheckTx) {

if err == nil {

txCost := app.bandwidthMeter.GetTxCost(ctx, tx)
txCost := app.bandwidthMeter.GetPricedTxCost(tx)
accBw := app.bandwidthMeter.GetCurrentAccBandwidth(ctx, acc)

if !accBw.HasEnoughRemained(txCost) {
Expand Down Expand Up @@ -342,7 +342,7 @@ func (app *CyberdApp) DeliverTx(txBytes []byte) (res abci.ResponseDeliverTx) {

if err == nil {

txCost := app.bandwidthMeter.GetTxCost(ctx, tx)
txCost := app.bandwidthMeter.GetPricedTxCost(tx)
accBw := app.bandwidthMeter.GetCurrentAccBandwidth(ctx, acc)

if !accBw.HasEnoughRemained(txCost) {
Expand All @@ -351,7 +351,7 @@ func (app *CyberdApp) DeliverTx(txBytes []byte) (res abci.ResponseDeliverTx) {

resp := app.BaseApp.DeliverTx(txBytes)
app.bandwidthMeter.ConsumeAccBandwidth(ctx, accBw, txCost)
app.bandwidthMeter.AddToBlockBandwidth(uint64(txCost))
app.bandwidthMeter.AddToBlockBandwidth(app.bandwidthMeter.GetTxCost(tx))

return abci.ResponseDeliverTx{
Code: uint32(resp.Code),
Expand Down
6 changes: 5 additions & 1 deletion x/bandwidth/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,11 @@ func (bk BaseBlockSpentBandwidthKeeper) SetBlockSpentBandwidth(ctx sdk.Context,
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))
windowStart := ctx.BlockHeight() - period + 1
if windowStart < 0 { // check needed cause it will be casted to uint and can cause overflow
windowStart = 0
}
binary.LittleEndian.PutUint64(startKey, uint64(windowStart))

endKey := make([]byte, 8)
binary.LittleEndian.PutUint64(endKey, uint64(ctx.BlockHeight()))
Expand Down
72 changes: 36 additions & 36 deletions x/bandwidth/meter.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"math"
)

var _ types.BandwidthMeter = BaseBandwidthMeter{}
var _ types.BandwidthMeter = &BaseBandwidthMeter{}

type BaseBandwidthMeter struct {
// data providers
Expand All @@ -22,50 +22,46 @@ type BaseBandwidthMeter struct {
msgCost types.MsgBandwidthCost

// price adjustment fields
curBlockSpentBandwidth *uint64 //resets every block
currentCreditPrice *float64
curBlockSpentBandwidth uint64 //resets every block
currentCreditPrice float64
bandwidthSpent map[uint64]uint64 // bandwidth spent by blocks
totalSpentForSlidingWindow *uint64
totalSpentForSlidingWindow uint64
}

func NewBaseMeter(
mainKeeper store.MainKeeper, ak auth.AccountKeeper, sp types.AccStakeProvider, bwKeeper types.Keeper,
msgCost types.MsgBandwidthCost, blockBandwidthKeeper types.BlockSpentBandwidthKeeper,
) BaseBandwidthMeter {
) *BaseBandwidthMeter {

return BaseBandwidthMeter{
return &BaseBandwidthMeter{
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 (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
func (m *BaseBandwidthMeter) Load(ctx sdk.Context) {
m.totalSpentForSlidingWindow = 0
m.bandwidthSpent = m.blockBandwidthKeeper.GetValuesForPeriod(ctx, SlidingWindowSize)
for _, spentBandwidth := range m.bandwidthSpent {
m.totalSpentForSlidingWindow += spentBandwidth
}
*m.currentCreditPrice = math.Float64frombits(m.mainKeeper.GetBandwidthPrice(ctx, BaseCreditPrice))
*m.curBlockSpentBandwidth = 0
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)
func (m *BaseBandwidthMeter) AddToBlockBandwidth(value int64) {
m.curBlockSpentBandwidth += uint64(value)
}

// 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
func (m *BaseBandwidthMeter) CommitBlockBandwidth(ctx sdk.Context) {
m.totalSpentForSlidingWindow += m.curBlockSpentBandwidth

newWindowEnd := ctx.BlockHeight()
windowStart := newWindowEnd - SlidingWindowSize
Expand All @@ -74,47 +70,51 @@ func (m BaseBandwidthMeter) CommitBlockBandwidth(ctx sdk.Context) {
}
windowStartValue, exists := m.bandwidthSpent[uint64(windowStart)]
if exists {
*m.totalSpentForSlidingWindow -= windowStartValue
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
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) {
func (m *BaseBandwidthMeter) AdjustPrice(ctx sdk.Context) {

newPrice := float64(*m.totalSpentForSlidingWindow) / float64(ShouldBeSpentPerSlidingWindow)
newPrice := float64(m.totalSpentForSlidingWindow) / float64(ShouldBeSpentPerSlidingWindow)

if newPrice < 0.01*BaseCreditPrice {
newPrice = 0.01 * BaseCreditPrice
}

*m.currentCreditPrice = newPrice
m.currentCreditPrice = newPrice
m.mainKeeper.StoreBandwidthPrice(ctx, math.Float64bits(newPrice))
}

func (m BaseBandwidthMeter) GetTxCost(ctx sdk.Context, tx sdk.Tx) int64 {
func (m *BaseBandwidthMeter) GetTxCost(tx sdk.Tx) int64 {
bandwidthForTx := TxCost
for _, msg := range tx.GetMsgs() {
bandwidthForTx = bandwidthForTx + m.msgCost(msg)
}
return int64(float64(bandwidthForTx) * *m.currentCreditPrice)
return bandwidthForTx
}

func (m BaseBandwidthMeter) GetAccMaxBandwidth(ctx sdk.Context, addr sdk.AccAddress) int64 {
func (m *BaseBandwidthMeter) GetPricedTxCost(tx sdk.Tx) int64 {
return int64(float64(m.GetTxCost(tx)) * m.currentCreditPrice)
}

func (m *BaseBandwidthMeter) GetAccMaxBandwidth(ctx sdk.Context, addr sdk.AccAddress) int64 {
accStakePercentage := m.stakeProvider.GetAccStakePercentage(ctx, addr)
return int64(accStakePercentage * float64(DesirableNetworkBandwidthForRecoveryPeriod))
}

func (m BaseBandwidthMeter) GetCurrentAccBandwidth(ctx sdk.Context, address sdk.AccAddress) types.AcсBandwidth {
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 (m BaseBandwidthMeter) UpdateAccMaxBandwidth(ctx sdk.Context, address sdk.AccAddress) {
func (m *BaseBandwidthMeter) UpdateAccMaxBandwidth(ctx sdk.Context, address sdk.AccAddress) {
bw := m.GetCurrentAccBandwidth(ctx, address)
m.bwKeeper.SetAccBandwidth(ctx, bw)
}
Expand All @@ -127,13 +127,13 @@ func (m BaseBandwidthMeter) UpdateAccMaxBandwidth(ctx sdk.Context, address sdk.A
// bw := getCurrentBw(addr)
// bwCost := deliverTx(tx)
// consumeBw(bw, bwCost)
func (m 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)
m.bwKeeper.SetAccBandwidth(ctx, bw)
bw = m.GetCurrentAccBandwidth(ctx, bw.Address)
m.bwKeeper.SetAccBandwidth(ctx, bw)
}

func (m BaseBandwidthMeter) GetCurrentCreditPrice() float64 {
return *m.currentCreditPrice
func (m *BaseBandwidthMeter) GetCurrentCreditPrice() float64 {
return m.currentCreditPrice
}
6 changes: 4 additions & 2 deletions x/bandwidth/types/meter.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type BandwidthMeter interface {
// load current bandwidth state after restart
Load(ctx sdk.Context)
// add value to consumed bandwidth for current block
AddToBlockBandwidth(value uint64)
AddToBlockBandwidth(value int64)
// adjust price based on 24h loading
AdjustPrice(ctx sdk.Context)
// get current bandwidth price
Expand All @@ -32,7 +32,9 @@ type BandwidthMeter interface {
// Returns acc max bandwidth
GetAccMaxBandwidth(ctx sdk.Context, address sdk.AccAddress) int64
// Returns tx bandwidth cost
GetTxCost(ctx sdk.Context, tx sdk.Tx) int64
GetTxCost(tx sdk.Tx) int64
// Return tx bandwidth cost considering the price
GetPricedTxCost(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
Expand Down

0 comments on commit 649bd7b

Please sign in to comment.