From 5b050815251c0e01afd20581b83759e4a29b8b97 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Tue, 8 Sep 2020 10:24:08 +0300 Subject: [PATCH] config: allow configuring free gas depending on height And update default mainnet/testnet settings. Follow neo-project/neo#1888 and neo-project/neo-node#656. --- config/protocol.mainnet.yml | 2 +- config/protocol.testnet.yml | 2 +- pkg/config/protocol_config.go | 24 ++++++++++++++++++++---- pkg/config/protocol_config_test.go | 25 +++++++++++++++++++++++++ pkg/core/blockchain.go | 5 +++-- pkg/core/interop_neo.go | 3 ++- 6 files changed, 52 insertions(+), 9 deletions(-) create mode 100644 pkg/config/protocol_config_test.go diff --git a/config/protocol.mainnet.yml b/config/protocol.mainnet.yml index 7284cd7ce..14f163821 100644 --- a/config/protocol.mainnet.yml +++ b/config/protocol.mainnet.yml @@ -32,7 +32,7 @@ ProtocolConfiguration: RegisterTransaction: 10000 VerifyBlocks: true VerifyTransactions: false - FreeGasLimit: 10.0 + FreeGasLimit: {0: 10.0, 6200000: 50.0} MaxTransactionsPerBlock: 500 MaxFreeTransactionsPerBlock: 20 MaxFreeTransactionSize: 1024 diff --git a/config/protocol.testnet.yml b/config/protocol.testnet.yml index 8ccb17005..ccfe6a689 100644 --- a/config/protocol.testnet.yml +++ b/config/protocol.testnet.yml @@ -32,7 +32,7 @@ ProtocolConfiguration: RegisterTransaction: 100 VerifyBlocks: true VerifyTransactions: false - FreeGasLimit: 10.0 + FreeGasLimit: {0: 10.0, 4818000: 50.0} MaxTransactionsPerBlock: 500 MaxFreeTransactionsPerBlock: 20 MaxFreeTransactionSize: 1024 diff --git a/pkg/config/protocol_config.go b/pkg/config/protocol_config.go index dff592038..acd2bb203 100644 --- a/pkg/config/protocol_config.go +++ b/pkg/config/protocol_config.go @@ -26,10 +26,12 @@ type ( // transactions exceeding the MaxFreeTransactionSize. FeePerExtraByte float64 `yaml:"FeePerExtraByte"` // FreeGasLimit is an amount of GAS which can be spent for free. - FreeGasLimit util.Fixed8 `yaml:"FreeGasLimit"` - LowPriorityThreshold float64 `yaml:"LowPriorityThreshold"` - Magic NetMode `yaml:"Magic"` - MaxTransactionsPerBlock int `yaml:"MaxTransactionsPerBlock"` + // It can change over time, thus it's a map of block height to the + // respective GAS limit. + FreeGasLimit map[uint32]util.Fixed8 `yaml:"FreeGasLimit"` + LowPriorityThreshold float64 `yaml:"LowPriorityThreshold"` + Magic NetMode `yaml:"Magic"` + MaxTransactionsPerBlock int `yaml:"MaxTransactionsPerBlock"` // Maximum size of low priority transaction in bytes. MaxFreeTransactionSize int `yaml:"MaxFreeTransactionSize"` // Maximum number of low priority transactions accepted into block. @@ -61,6 +63,20 @@ type ( NetMode uint32 ) +// GetFreeGas returns FreeGasLimit value for given block height. +func (p *ProtocolConfiguration) GetFreeGas(block uint32) util.Fixed8 { + var gas util.Fixed8 + var height uint32 + for h, g := range p.FreeGasLimit { + if h > block || h < height { + continue + } + gas = g + height = h + } + return gas +} + // String implements the stringer interface. func (n NetMode) String() string { switch n { diff --git a/pkg/config/protocol_config_test.go b/pkg/config/protocol_config_test.go new file mode 100644 index 000000000..2a5cd8a38 --- /dev/null +++ b/pkg/config/protocol_config_test.go @@ -0,0 +1,25 @@ +package config + +import ( + "testing" + + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/stretchr/testify/require" +) + +func TestGetFreeGas(t *testing.T) { + fixed10 := util.Fixed8FromInt64(10) + fixed50 := util.Fixed8FromInt64(50) + p := ProtocolConfiguration{ + FreeGasLimit: map[uint32]util.Fixed8{ + 0: fixed10, + 6200000: fixed50, + }, + } + require.Equal(t, fixed10, p.GetFreeGas(0)) + require.Equal(t, fixed10, p.GetFreeGas(1000)) + require.Equal(t, fixed10, p.GetFreeGas(1000000)) + require.Equal(t, fixed10, p.GetFreeGas(6100000)) + require.Equal(t, fixed50, p.GetFreeGas(6200000)) + require.Equal(t, fixed50, p.GetFreeGas(7000000)) +} diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 2119f22a3..440efabff 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -792,8 +792,9 @@ func (bc *Blockchain) storeBlock(block *block.Block) error { v.SetCheckedHash(tx.VerificationHash().BytesBE()) v.LoadScript(t.Script) v.SetPriceGetter(getPrice) - if bc.config.FreeGasLimit > 0 { - v.SetGasLimit(bc.config.FreeGasLimit + t.Gas) + gasLimit := bc.config.GetFreeGas(block.Index) + if gasLimit > 0 { + v.SetGasLimit(gasLimit + t.Gas) } err := v.Run() diff --git a/pkg/core/interop_neo.go b/pkg/core/interop_neo.go index 12d653d0c..742c2dcbf 100644 --- a/pkg/core/interop_neo.go +++ b/pkg/core/interop_neo.go @@ -605,7 +605,8 @@ func (ic *interopContext) contractMigrate(v *vm.VM) error { v := ic.bc.GetTestVM(nil) w := io.NewBufBinWriter() emit.AppCallWithOperationAndArgs(w.BinWriter, hash, "decimals") - v.SetGasLimit(ic.bc.GetConfig().FreeGasLimit) + conf := ic.bc.GetConfig() + v.SetGasLimit(conf.GetFreeGas(ic.bc.BlockHeight() + 1)) // BlockHeight() is already persisted, so it's either a new block or test invocation. v.Load(w.Bytes()) if err := v.Run(); err == nil && v.Estack().Len() == 1 { res := v.Estack().Pop().Item().ToContractParameter(map[vm.StackItem]bool{})