diff --git a/config/protocol.mainnet.yml b/config/protocol.mainnet.yml index 45d1f8056..4de51b60c 100644 --- a/config/protocol.mainnet.yml +++ b/config/protocol.mainnet.yml @@ -7,6 +7,7 @@ ProtocolConfiguration: KeepOnlyLatestState: false LowPriorityThreshold: 0.001 MemPoolSize: 50000 + NoBonusHeight: 8000000 StandbyValidators: - 03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c - 02df48f60e8f3e01c48ff40b9b7f1310d7a8b2a193188befe1c2e3df740e895093 diff --git a/config/protocol.testnet.yml b/config/protocol.testnet.yml index 75311c918..374fc67e1 100644 --- a/config/protocol.testnet.yml +++ b/config/protocol.testnet.yml @@ -7,6 +7,7 @@ ProtocolConfiguration: KeepOnlyLatestState: false LowPriorityThreshold: 0.000 MemPoolSize: 50000 + NoBonusHeight: 8000000 StandbyValidators: - 0327da12b5c40200e9f65569476bbff2218da4f32548ff43b6387ec1416a231ee8 - 026ce35b29147ad09e4afe4ec4a7319095f08198fa8babbe3c56e970b143528d22 diff --git a/pkg/config/protocol_config.go b/pkg/config/protocol_config.go index b094a1958..854ece299 100644 --- a/pkg/config/protocol_config.go +++ b/pkg/config/protocol_config.go @@ -44,6 +44,8 @@ type ( // MinimumNetworkFee sets the minimum required network fee for transaction to pass validation. MinimumNetworkFee util.Fixed8 `yaml:"MinimumNetworkFee"` MemPoolSize int `yaml:"MemPoolSize"` + // NoBonusHeight is the height where GAS generation stops. + NoBonusHeight uint32 `yaml:"NoBonusHeight"` // SaveStorageBatch enables storage batch saving before every persist. SaveStorageBatch bool `yaml:"SaveStorageBatch"` SecondsPerBlock int `yaml:"SecondsPerBlock"` diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 07af0b03f..e0781f153 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -103,6 +103,7 @@ type Blockchain struct { generationAmount []int decrementInterval int + noBonusHeight uint32 // All operations on headerList must be called from an // headersOp to be routine safe. @@ -184,6 +185,7 @@ func NewBlockchain(s storage.Store, cfg config.ProtocolConfiguration, log *zap.L generationAmount: genAmount, decrementInterval: decrementInterval, + noBonusHeight: cfg.NoBonusHeight, } if err := bc.init(); err != nil { @@ -1488,9 +1490,14 @@ func (bc *Blockchain) CalculateClaimable(value util.Fixed8, startHeight, endHeig di := uint32(bc.decrementInterval) ustart := startHeight / di - if genSize := uint32(len(bc.generationAmount)); ustart < genSize { - uend := endHeight / di - iend := endHeight % di + genSize := uint32(len(bc.generationAmount)) + if ustart < genSize && (bc.noBonusHeight == 0 || startHeight < bc.noBonusHeight) { + endHeightMin := endHeight + if bc.noBonusHeight != 0 && endHeightMin > bc.noBonusHeight { + endHeightMin = bc.noBonusHeight + } + uend := endHeightMin / di + iend := endHeightMin % di if uend >= genSize { uend = genSize - 1 iend = di diff --git a/pkg/core/blockchain_test.go b/pkg/core/blockchain_test.go index 5f06ab4d8..aa5a5d918 100644 --- a/pkg/core/blockchain_test.go +++ b/pkg/core/blockchain_test.go @@ -187,6 +187,7 @@ func TestGetClaimable(t *testing.T) { bc.generationAmount = []int{4, 3, 2, 1} bc.decrementInterval = 2 _, err := bc.genBlocks(10) + bc.noBonusHeight = 6 // stop right before `1` require.NoError(t, err) t.Run("first generation period", func(t *testing.T) { @@ -206,16 +207,40 @@ func TestGetClaimable(t *testing.T) { t.Run("start from the 2-nd block", func(t *testing.T) { amount, sysfee, err := bc.CalculateClaimable(util.Fixed8FromInt64(1), 1, 7) require.NoError(t, err) - require.EqualValues(t, 4+3+3+2+2+1, amount) + require.EqualValues(t, 4+3+3+2+2, amount) require.EqualValues(t, 0, sysfee) }) t.Run("end height after generation has ended", func(t *testing.T) { + amount, sysfee, err := bc.CalculateClaimable(util.Fixed8FromInt64(1), 1, 10) + require.NoError(t, err) + require.EqualValues(t, 4+3+3+2+2, amount) + require.EqualValues(t, 0, sysfee) + }) + + t.Run("end height after generation has ended, noBonusHeight is very big", func(t *testing.T) { + bc.noBonusHeight = 20 amount, sysfee, err := bc.CalculateClaimable(util.Fixed8FromInt64(1), 1, 10) require.NoError(t, err) require.EqualValues(t, 4+3+3+2+2+1+1, amount) require.EqualValues(t, 0, sysfee) }) + + t.Run("end height after generation has ended, noBonusHeight is 0", func(t *testing.T) { + bc.noBonusHeight = 0 + amount, sysfee, err := bc.CalculateClaimable(util.Fixed8FromInt64(1), 1, 10) + require.NoError(t, err) + require.EqualValues(t, 4+3+3+2+2+1+1, amount) + require.EqualValues(t, 0, sysfee) + }) + + t.Run("noBonusHeight is not divisible by decrement interval", func(t *testing.T) { + bc.noBonusHeight = 5 + amount, sysfee, err := bc.CalculateClaimable(util.Fixed8FromInt64(1), 1, 10) + require.NoError(t, err) + require.EqualValues(t, 4+3+3+2, amount) + require.EqualValues(t, 0, sysfee) + }) } func TestClose(t *testing.T) {