code.vegaprotocol.io/vega@v0.79.0/core/pow/multiple_config_test.go (about)

     1  // Copyright (C) 2023 Gobalsky Labs Limited
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  package pow
    17  
    18  import (
    19  	"context"
    20  	"testing"
    21  
    22  	"code.vegaprotocol.io/vega/core/blockchain/abci"
    23  	"code.vegaprotocol.io/vega/libs/crypto"
    24  	"code.vegaprotocol.io/vega/libs/num"
    25  	"code.vegaprotocol.io/vega/logging"
    26  
    27  	"github.com/stretchr/testify/require"
    28  )
    29  
    30  func TestConfigurationHistory(t *testing.T) {
    31  	e := New(logging.NewTestLogger(), NewDefaultConfig())
    32  
    33  	e.BeginBlock(1, crypto.RandomHash(), []abci.Tx{})
    34  	require.Equal(t, 0, len(e.activeParams))
    35  	require.Equal(t, 0, len(e.activeStates))
    36  	e.UpdateSpamPoWDifficulty(context.Background(), num.NewUint(1))
    37  	require.Equal(t, 1, len(e.activeParams))
    38  	require.Equal(t, 1, len(e.activeStates))
    39  	require.Equal(t, uint64(1), e.activeParams[0].fromBlock)
    40  	require.Nil(t, e.activeParams[0].untilBlock)
    41  
    42  	e.BeginBlock(2, crypto.RandomHash(), []abci.Tx{})
    43  	e.UpdateSpamPoWDifficulty(context.Background(), num.NewUint(5))
    44  	require.Equal(t, 2, len(e.activeParams))
    45  	require.Equal(t, 2, len(e.activeStates))
    46  	require.Equal(t, uint64(1), e.activeParams[0].fromBlock)
    47  	require.Equal(t, uint64(2), *e.activeParams[0].untilBlock)
    48  	require.Equal(t, uint64(3), e.activeParams[1].fromBlock)
    49  	require.Nil(t, e.activeParams[1].untilBlock)
    50  
    51  	// we're in block 2, we expect difficulty to change in block 3
    52  	require.Equal(t, uint32(1), e.SpamPoWDifficulty())
    53  	e.BeginBlock(3, crypto.RandomHash(), []abci.Tx{})
    54  	require.Equal(t, uint32(5), e.SpamPoWDifficulty())
    55  }
    56  
    57  func TestSpamPoWNumberOfPastBlocksChange(t *testing.T) {
    58  	e := New(logging.NewTestLogger(), NewDefaultConfig())
    59  	e.BeginBlock(1, crypto.RandomHash(), []abci.Tx{})
    60  	e.UpdateSpamPoWNumberOfPastBlocks(context.Background(), num.NewUint(10))
    61  
    62  	// it's the first configuration so it's starting from this block rather than next
    63  	require.Equal(t, uint32(10), e.SpamPoWNumberOfPastBlocks())
    64  	e.BeginBlock(2, crypto.RandomHash(), []abci.Tx{})
    65  	e.UpdateSpamPoWNumberOfPastBlocks(context.Background(), num.NewUint(100))
    66  	require.Equal(t, uint32(10), e.SpamPoWNumberOfPastBlocks())
    67  	e.UpdateSpamPoWNumberOfPastBlocks(context.Background(), num.NewUint(110))
    68  	require.Equal(t, uint32(10), e.SpamPoWNumberOfPastBlocks())
    69  	e.BeginBlock(3, crypto.RandomHash(), []abci.Tx{})
    70  	require.Equal(t, uint32(110), e.SpamPoWNumberOfPastBlocks())
    71  }
    72  
    73  func TestSpamPoWDifficultyChange(t *testing.T) {
    74  	e := New(logging.NewTestLogger(), NewDefaultConfig())
    75  	e.BeginBlock(1, crypto.RandomHash(), []abci.Tx{})
    76  	e.UpdateSpamPoWDifficulty(context.Background(), num.NewUint(10))
    77  
    78  	// it's the first configuration so it's starting from this block rather than next
    79  	require.Equal(t, uint32(10), e.SpamPoWDifficulty())
    80  	e.BeginBlock(2, crypto.RandomHash(), []abci.Tx{})
    81  	e.UpdateSpamPoWDifficulty(context.Background(), num.NewUint(100))
    82  	require.Equal(t, uint32(10), e.SpamPoWDifficulty())
    83  	e.UpdateSpamPoWDifficulty(context.Background(), num.NewUint(110))
    84  	require.Equal(t, uint32(10), e.SpamPoWDifficulty())
    85  	e.BeginBlock(3, crypto.RandomHash(), []abci.Tx{})
    86  	require.Equal(t, uint32(110), e.SpamPoWDifficulty())
    87  }
    88  
    89  func TestSpamPoWHashChange(t *testing.T) {
    90  	e := New(logging.NewTestLogger(), NewDefaultConfig())
    91  	e.BeginBlock(1, crypto.RandomHash(), []abci.Tx{})
    92  	e.UpdateSpamPoWHashFunction(context.Background(), "f1")
    93  
    94  	// it's the first configuration so it's starting from this block rather than next
    95  	require.Equal(t, "f1", e.SpamPoWHashFunction())
    96  	e.BeginBlock(2, crypto.RandomHash(), []abci.Tx{})
    97  	e.UpdateSpamPoWHashFunction(context.Background(), "f2")
    98  	require.Equal(t, "f1", e.SpamPoWHashFunction())
    99  	e.UpdateSpamPoWHashFunction(context.Background(), "f3")
   100  	require.Equal(t, "f1", e.SpamPoWHashFunction())
   101  	e.BeginBlock(3, crypto.RandomHash(), []abci.Tx{})
   102  	require.Equal(t, "f3", e.SpamPoWHashFunction())
   103  }
   104  
   105  func TestSpamPoWNumberOfTxPerBlockChange(t *testing.T) {
   106  	e := New(logging.NewTestLogger(), NewDefaultConfig())
   107  	e.BeginBlock(1, crypto.RandomHash(), []abci.Tx{})
   108  	e.UpdateSpamPoWNumberOfTxPerBlock(context.Background(), num.NewUint(10))
   109  
   110  	// it's the first configuration so it's starting from this block rather than next
   111  	require.Equal(t, uint32(10), e.SpamPoWNumberOfTxPerBlock())
   112  	e.BeginBlock(2, crypto.RandomHash(), []abci.Tx{})
   113  	e.UpdateSpamPoWNumberOfTxPerBlock(context.Background(), num.NewUint(100))
   114  	require.Equal(t, uint32(10), e.SpamPoWNumberOfTxPerBlock())
   115  	e.UpdateSpamPoWNumberOfTxPerBlock(context.Background(), num.NewUint(110))
   116  	require.Equal(t, uint32(10), e.SpamPoWNumberOfTxPerBlock())
   117  	e.BeginBlock(3, crypto.RandomHash(), []abci.Tx{})
   118  	require.Equal(t, uint32(110), e.SpamPoWNumberOfTxPerBlock())
   119  }
   120  
   121  func TestSpamPoWIncreasingDifficultyChange(t *testing.T) {
   122  	e := New(logging.NewTestLogger(), NewDefaultConfig())
   123  	e.BeginBlock(1, crypto.RandomHash(), []abci.Tx{})
   124  	e.UpdateSpamPoWIncreasingDifficulty(context.Background(), num.NewUint(1))
   125  
   126  	// it's the first configuration so it's starting from this block rather than next
   127  	require.Equal(t, true, e.SpamPoWIncreasingDifficulty())
   128  	e.BeginBlock(2, crypto.RandomHash(), []abci.Tx{})
   129  	e.UpdateSpamPoWIncreasingDifficulty(context.Background(), num.NewUint(1))
   130  	require.Equal(t, true, e.SpamPoWIncreasingDifficulty())
   131  	e.UpdateSpamPoWIncreasingDifficulty(context.Background(), num.NewUint(0))
   132  	require.Equal(t, true, e.SpamPoWIncreasingDifficulty())
   133  	e.BeginBlock(3, crypto.RandomHash(), []abci.Tx{})
   134  	require.Equal(t, false, e.SpamPoWIncreasingDifficulty())
   135  }
   136  
   137  func TestBlockData(t *testing.T) {
   138  	e := New(logging.NewTestLogger(), NewDefaultConfig())
   139  	blockHash := crypto.RandomHash()
   140  	e.UpdateSpamPoWDifficulty(context.Background(), num.NewUint(5))
   141  	e.BeginBlock(1, blockHash, []abci.Tx{})
   142  
   143  	height, hash := e.BlockData()
   144  	require.Equal(t, uint64(1), height)
   145  	require.Equal(t, blockHash, hash)
   146  
   147  	blockHash = crypto.RandomHash()
   148  	e.BeginBlock(2, blockHash, []abci.Tx{})
   149  	height, hash = e.BlockData()
   150  	require.Equal(t, uint64(2), height)
   151  	require.Equal(t, blockHash, hash)
   152  }
   153  
   154  func TestFindParamsForBlockHeight(t *testing.T) {
   155  	e := New(logging.NewTestLogger(), NewDefaultConfig())
   156  	e.UpdateSpamPoWNumberOfPastBlocks(context.Background(), num.NewUint(100))
   157  	e.UpdateSpamPoWDifficulty(context.Background(), num.NewUint(20))
   158  	e.UpdateSpamPoWHashFunction(context.Background(), "sha3")
   159  	e.UpdateSpamPoWNumberOfTxPerBlock(context.Background(), num.NewUint(1))
   160  	e.UpdateSpamPoWIncreasingDifficulty(context.Background(), num.NewUint(1))
   161  
   162  	e.BeginBlock(9, crypto.RandomHash(), []abci.Tx{})
   163  	e.UpdateSpamPoWDifficulty(context.Background(), num.NewUint(21))
   164  	e.BeginBlock(19, crypto.RandomHash(), []abci.Tx{})
   165  	e.UpdateSpamPoWDifficulty(context.Background(), num.NewUint(22))
   166  	e.BeginBlock(29, crypto.RandomHash(), []abci.Tx{})
   167  	e.UpdateSpamPoWDifficulty(context.Background(), num.NewUint(23))
   168  
   169  	require.Equal(t, uint(20), e.activeParams[e.findParamsForBlockHeight(1)].spamPoWDifficulty)
   170  	require.Equal(t, uint(20), e.activeParams[e.findParamsForBlockHeight(9)].spamPoWDifficulty)
   171  	require.Equal(t, uint(21), e.activeParams[e.findParamsForBlockHeight(10)].spamPoWDifficulty)
   172  	require.Equal(t, uint(21), e.activeParams[e.findParamsForBlockHeight(19)].spamPoWDifficulty)
   173  	require.Equal(t, uint(22), e.activeParams[e.findParamsForBlockHeight(20)].spamPoWDifficulty)
   174  	require.Equal(t, uint(22), e.activeParams[e.findParamsForBlockHeight(29)].spamPoWDifficulty)
   175  	require.Equal(t, uint(23), e.activeParams[e.findParamsForBlockHeight(30)].spamPoWDifficulty)
   176  	require.Equal(t, uint(23), e.activeParams[e.findParamsForBlockHeight(100)].spamPoWDifficulty)
   177  }
   178  
   179  // func TestVerifyWithMultipleConfigs(t *testing.T) {
   180  // 	e := New(logging.NewTestLogger(), NewDefaultConfig())
   181  // 	e.UpdateSpamPoWNumberOfPastBlocks(context.Background(), num.NewUint(100))
   182  // 	e.UpdateSpamPoWDifficulty(context.Background(), num.NewUint(20))
   183  // 	e.UpdateSpamPoWHashFunction(context.Background(), "sha3_24_rounds")
   184  // 	e.UpdateSpamPoWNumberOfTxPerBlock(context.Background(), num.NewUint(1))
   185  // 	e.UpdateSpamPoWIncreasingDifficulty(context.Background(), num.NewUint(0))
   186  
   187  // 	block9Hash := "2E7A16D9EF690F0D2BEED115FBA13BA2AAA16C8F971910AD88C72B9DB010C7D4"
   188  // 	e.BeginBlock(9, block9Hash)
   189  // 	e.UpdateSpamPoWDifficulty(context.Background(), num.NewUint(21))
   190  // 	e.UpdateSpamPoWNumberOfPastBlocks(context.Background(), num.NewUint(50))
   191  // 	e.UpdateSpamPoWNumberOfTxPerBlock(context.Background(), num.NewUint(5))
   192  // 	e.UpdateSpamPoWIncreasingDifficulty(context.Background(), num.NewUint(1))
   193  
   194  // 	e.EndOfBlock()
   195  // 	e.BeginBlock(19, crypto.RandomHash())
   196  // 	e.UpdateSpamPoWDifficulty(context.Background(), num.NewUint(22))
   197  // 	e.UpdateSpamPoWNumberOfPastBlocks(context.Background(), num.NewUint(80))
   198  // 	e.UpdateSpamPoWNumberOfTxPerBlock(context.Background(), num.NewUint(1))
   199  // 	e.UpdateSpamPoWIncreasingDifficulty(context.Background(), num.NewUint(1))
   200  
   201  // 	e.EndOfBlock()
   202  // 	block29Hash := "8890702af457ddcda01fba579a126adcecae954781500acb546fef9c8087a239"
   203  // 	e.BeginBlock(29, block29Hash)
   204  // 	e.UpdateSpamPoWDifficulty(context.Background(), num.NewUint(1))
   205  // 	e.UpdateSpamPoWNumberOfPastBlocks(context.Background(), num.NewUint(70))
   206  // 	e.UpdateSpamPoWNumberOfTxPerBlock(context.Background(), num.NewUint(2))
   207  // 	e.UpdateSpamPoWIncreasingDifficulty(context.Background(), num.NewUint(0))
   208  // 	e.EndOfBlock()
   209  
   210  // 	block30Hash := "377EEAC9847D751A4FAFD3F2896E99C1A03363EBDA3036C33940CFE578E196D1"
   211  // 	e.BeginBlock(30, block30Hash)
   212  
   213  // 	// now we're in block 90
   214  // 	e.BeginBlock(90, "792ca202b84226c739f9923046a0f4e7b5ff9e6f1b5636d8e26a8e2c5dec70ac")
   215  
   216  // 	// transactions sent from block height < 10 have past blocks of 100, difficulty of 20 and allow 1 transaction per block with no increased difficulty
   217  // 	tx9_1 := &testTx{txID: "1", blockHeight: 9, party: "party", powTxID: "DFE522E234D67E6AE3F017859F898E576B3928EA57310B765398615A0D3FDE2F", powNonce: 424517}
   218  // 	err := e.DeliverTx(tx9_1)
   219  // 	require.NoError(t, err)
   220  
   221  // 	// doesn't really matter what the pow data is because in block 19 the parameters allowed only 50 blocks behind meaning in block 90 the transaction should be rejected as too old
   222  // 	tx19 := &testTx{txID: "2", blockHeight: 19, party: "party", powTxID: "5B87F9DFA41DABE84A11CA78D9FE11DA8FC2AA926004CA66454A7AF0A206480D", powNonce: 4095356}
   223  // 	err = e.DeliverTx(tx19)
   224  // 	require.Equal(t, "unknown block height for tx:32, command:Amend Order, party:party", err.Error())
   225  
   226  // 	// in block 29 we're allowed to submit 1 transactions with difficulty starting at 22 and increased difficulty
   227  // 	tx29_1 := &testTx{txID: "3", blockHeight: 29, party: "party", powTxID: "74030ee7dc931be9d9cc5f2c9d44ac174b4144b377ef07a7bb1781856921dd43", powNonce: 1903233}
   228  // 	tx29_2 := &testTx{txID: "4", blockHeight: 29, party: "party", powTxID: "94A9CB1532011081B013CCD8E6AAA832CAB1CBA603F0C5A093B14C4961E5E7F0", powNonce: 7914217}
   229  // 	err = e.DeliverTx(tx29_1)
   230  // 	require.NoError(t, err)
   231  // 	err = e.DeliverTx(tx29_2)
   232  // 	require.NoError(t, err)
   233  
   234  // 	// finally we have a transaction sent in block 30 which allows for 2 transactions with no increased difficulty
   235  // 	tx30_1 := &testTx{txID: "5", blockHeight: 30, party: "party", powTxID: "2A1319636230740888C968E4E7610D6DE820E644EEC3C08AA5322A0A022014BD", powNonce: 380742}
   236  // 	err = e.DeliverTx(tx30_1)
   237  // 	require.NoError(t, err)
   238  
   239  // 	tx30_2 := &testTx{txID: "6", blockHeight: 30, party: "party", powTxID: "2E7A16D9EF690F0D2BEED115FBA13BA2AAA16C8F971910AD88C72B9DB010C7D4", powNonce: 1296835}
   240  // 	err = e.DeliverTx(tx30_2)
   241  // 	require.NoError(t, err)
   242  // 	tx30_3 := &testTx{txID: "7", blockHeight: 30, party: "party", powTxID: "5B0E1EB96CCAC120E6D824A5F4C4007EABC59573B861BD84B1EF09DFB376DC84", powNonce: 388948}
   243  // 	err = e.DeliverTx(tx30_3)
   244  // 	// the third transaction would be rejected and ban the party
   245  // 	require.Equal(t, "too many transactions per block", err.Error())
   246  
   247  // 	// now move on to the next block and the party should be banned
   248  // 	e.BeginBlock(91, crypto.RandomHash())
   249  // 	tx90 := &testTx{txID: "7", blockHeight: 90, party: "party", powTxID: "3b8399cdffee2686d75d1a96d22cd49cd11f62c93da20e72239895bfdaf4b772", powNonce: 0}
   250  // 	err = e.DeliverTx(tx90)
   251  // 	require.Equal(t, "party is banned from sending transactions", err.Error())
   252  // }
   253  
   254  func TestEndOfBlockCleanup(t *testing.T) {
   255  	e := New(logging.NewTestLogger(), NewDefaultConfig())
   256  	e.UpdateSpamPoWNumberOfPastBlocks(context.Background(), num.NewUint(100))
   257  	e.UpdateSpamPoWDifficulty(context.Background(), num.NewUint(20))
   258  	e.UpdateSpamPoWHashFunction(context.Background(), "sha3_24_rounds")
   259  	e.UpdateSpamPoWNumberOfTxPerBlock(context.Background(), num.NewUint(1))
   260  	e.UpdateSpamPoWIncreasingDifficulty(context.Background(), num.NewUint(0))
   261  
   262  	// the setting above is good for transactions from blocks 0 - 9+100
   263  	// that means at the end of block 109 it can be removed
   264  
   265  	e.BeginBlock(9, crypto.RandomHash(), []abci.Tx{})
   266  	e.UpdateSpamPoWDifficulty(context.Background(), num.NewUint(21))
   267  	e.UpdateSpamPoWNumberOfPastBlocks(context.Background(), num.NewUint(50))
   268  	e.UpdateSpamPoWNumberOfTxPerBlock(context.Background(), num.NewUint(5))
   269  	e.UpdateSpamPoWIncreasingDifficulty(context.Background(), num.NewUint(1))
   270  
   271  	// the setting above is good for transactions from blocks 10 - 19+50
   272  	// that means at the end of block 69 it can be removed
   273  
   274  	e.BeginBlock(19, crypto.RandomHash(), []abci.Tx{})
   275  	e.UpdateSpamPoWDifficulty(context.Background(), num.NewUint(22))
   276  	e.UpdateSpamPoWNumberOfPastBlocks(context.Background(), num.NewUint(80))
   277  	e.UpdateSpamPoWNumberOfTxPerBlock(context.Background(), num.NewUint(1))
   278  	e.UpdateSpamPoWIncreasingDifficulty(context.Background(), num.NewUint(1))
   279  
   280  	// the setting above is good for transactions from blocks 20 - 29+80
   281  	// that means at the end of block 109 it can be removed
   282  
   283  	e.BeginBlock(29, crypto.RandomHash(), []abci.Tx{})
   284  	e.UpdateSpamPoWDifficulty(context.Background(), num.NewUint(1))
   285  	e.UpdateSpamPoWNumberOfPastBlocks(context.Background(), num.NewUint(70))
   286  	e.UpdateSpamPoWNumberOfTxPerBlock(context.Background(), num.NewUint(2))
   287  	e.UpdateSpamPoWIncreasingDifficulty(context.Background(), num.NewUint(0))
   288  
   289  	// the setting above is good for transactions from blocks 30 -
   290  
   291  	e.BeginBlock(30, crypto.RandomHash(), []abci.Tx{})
   292  
   293  	require.Equal(t, 4, len(e.activeParams))
   294  	require.Equal(t, 4, len(e.activeStates))
   295  
   296  	e.BeginBlock(69, crypto.RandomHash(), []abci.Tx{})
   297  
   298  	require.Equal(t, 3, len(e.activeParams))
   299  	require.Equal(t, 3, len(e.activeStates))
   300  
   301  	e.BeginBlock(109, crypto.RandomHash(), []abci.Tx{})
   302  
   303  	require.Equal(t, 1, len(e.activeParams))
   304  	require.Equal(t, 1, len(e.activeStates))
   305  	require.Equal(t, uint32(70), e.SpamPoWNumberOfPastBlocks())
   306  	require.Equal(t, uint32(1), e.SpamPoWDifficulty())
   307  	require.Equal(t, false, e.SpamPoWIncreasingDifficulty())
   308  	require.Equal(t, uint32(2), e.SpamPoWNumberOfTxPerBlock())
   309  }