github.com/codingfuture/orig-energi3@v0.8.4/core/energi_preblacklist_test.go (about)

     1  // Copyright 2019 The Energi Core Authors
     2  // This file is part of the Energi Core library.
     3  //
     4  // The Energi Core library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The Energi Core library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the Energi Core library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package core
    18  
    19  import (
    20  	"io/ioutil"
    21  	"os"
    22  	"strings"
    23  	"testing"
    24  	"time"
    25  
    26  	"github.com/ethereum/go-ethereum/accounts/abi"
    27  	"github.com/ethereum/go-ethereum/common"
    28  	"github.com/ethereum/go-ethereum/consensus/ethash"
    29  	"github.com/ethereum/go-ethereum/core/state"
    30  	"github.com/ethereum/go-ethereum/core/types"
    31  	"github.com/ethereum/go-ethereum/core/vm"
    32  	"github.com/ethereum/go-ethereum/ethdb"
    33  	"github.com/ethereum/go-ethereum/event"
    34  	"github.com/ethereum/go-ethereum/log"
    35  	"github.com/ethereum/go-ethereum/params"
    36  
    37  	"github.com/stretchr/testify/assert"
    38  
    39  	energi_abi "energi.world/core/gen3/energi/abi"
    40  	energi_params "energi.world/core/gen3/energi/params"
    41  )
    42  
    43  /*
    44  type fakeSigner struct {
    45  	sender common.Address
    46  }
    47  
    48  func (s *fakeSigner) Sender(tx *types.Transaction) (common.Address, error) {
    49  	return s.sender, nil
    50  }
    51  func (sg *fakeSigner) SignatureValues(tx *types.Transaction, sig []byte) (r, s, v *big.Int, err error) {
    52  	return common.Big0, common.Big0, common.Big0, nil
    53  }
    54  func (s *fakeSigner) Hash(tx *types.Transaction) common.Hash {
    55  	return tx.Hash()
    56  }
    57  func (s *fakeSigner) Equal(types.Signer) bool {
    58  	return false
    59  }
    60  */
    61  
    62  func TestPreBlacklist(t *testing.T) {
    63  	t.Parallel()
    64  	log.Root().SetHandler(log.StdoutHandler)
    65  
    66  	now := time.Now() // It can be fixed
    67  	adjust_time := time.Duration(0)
    68  
    69  	testdb := ethdb.NewMemDatabase()
    70  	gspec := &Genesis{
    71  		Config: params.TestnetChainConfig,
    72  	}
    73  	gspec.MustCommit(testdb)
    74  	engine := ethash.NewFaker()
    75  
    76  	chain, err := NewBlockChain(
    77  		testdb, nil, gspec.Config,
    78  		engine, vm.Config{}, nil)
    79  	assert.Empty(t, err)
    80  
    81  	dir, err := ioutil.TempDir(os.TempDir(), "test-*")
    82  	if err != nil {
    83  		panic(err)
    84  	}
    85  
    86  	pool := NewTxPool(TxPoolConfig{Protection: dir}, gspec.Config, chain)
    87  	prebl := pool.preBlacklist
    88  	prebl.timeNow = func() time.Time {
    89  		return now.Add(adjust_time)
    90  	}
    91  
    92  	bladdr1 := common.HexToAddress("0x1111")
    93  	bladdr2 := common.HexToAddress("0x2222")
    94  	sender := common.HexToAddress("0x3333")
    95  	wladdr1 := common.HexToAddress("0x4444")
    96  
    97  	gspec.Config.Energi = &params.EnergiConfig{
    98  		EBISigner: sender,
    99  	}
   100  
   101  	signer := &fakeSigner{}
   102  	pool.signer = signer
   103  	signer.sender = sender
   104  
   105  	defer chain.Stop()
   106  	defer pool.Stop()
   107  	pool.chain = chain
   108  	pool.currentState, _ = chain.State()
   109  
   110  	blreg_abi, err := abi.JSON(strings.NewReader(energi_abi.IBlacklistRegistryABI))
   111  	assert.Empty(t, err)
   112  	propose1Call, err := blreg_abi.Pack("propose", bladdr1)
   113  	assert.Empty(t, err)
   114  	propose2Call, err := blreg_abi.Pack("propose", bladdr2)
   115  	assert.Empty(t, err)
   116  	proposeWLCall, err := blreg_abi.Pack("propose", wladdr1)
   117  	assert.Empty(t, err)
   118  	revokeCall, err := blreg_abi.Pack("proposeRevoke", bladdr1)
   119  	assert.Empty(t, err)
   120  
   121  	propose1 := types.NewTransaction(
   122  		1, energi_params.Energi_BlacklistRegistry, common.Big0, 1000000, common.Big0, propose1Call)
   123  	propose2 := types.NewTransaction(
   124  		2, energi_params.Energi_BlacklistRegistry, common.Big0, 1000000, common.Big0, propose2Call)
   125  	proposeWL := types.NewTransaction(
   126  		3, energi_params.Energi_BlacklistRegistry, common.Big0, 1000000, common.Big0, proposeWLCall)
   127  	revoke := types.NewTransaction(
   128  		4, energi_params.Energi_BlacklistRegistry, common.Big0, 1000000, common.Big0, revokeCall)
   129  	proposePaid := types.NewTransaction(
   130  		1, energi_params.Energi_BlacklistRegistry, common.Big0, 1000000, common.Big1, propose1Call)
   131  
   132  	pool.currentState.SetCode(
   133  		energi_params.Energi_BlacklistRegistry,
   134  		// PUSH1 1 PUSH1 0 MSTORE PUSH1 1 PUSH1 0 RETURN
   135  		[]byte{0x60, 0x01, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0xF3},
   136  	)
   137  	pool.currentState.SetState(
   138  		energi_params.Energi_Whitelist,
   139  		wladdr1.Hash(),
   140  		common.BytesToHash([]byte{0x01}),
   141  	)
   142  	assert.True(t, IsWhitelisted(pool.currentState, wladdr1))
   143  
   144  	log.Trace("Make sure removed in pool")
   145  	signer.sender = bladdr1
   146  	err = pool.AddLocal(revoke)
   147  	assert.Equal(t, nil, err)
   148  	assert.Equal(t, 1, len(pool.queue[bladdr1].Flatten()))
   149  	signer.sender = sender
   150  
   151  	log.Trace("Initial")
   152  	err = prebl.processTx(pool, revoke)
   153  	assert.Equal(t, nil, err)
   154  	assert.Equal(t, 0, len(prebl.proposed))
   155  	assert.Equal(t, 1, len(pool.queue[bladdr1].Flatten()))
   156  
   157  	err = prebl.processTx(pool, propose1)
   158  	assert.Equal(t, nil, err)
   159  	assert.Equal(t, 1, len(prebl.proposed))
   160  	if qb, ok := pool.queue[bladdr1]; ok {
   161  		assert.Equal(t, 1, len(qb.Flatten()))
   162  	}
   163  
   164  	adjust_time = time.Duration(10) * time.Minute
   165  
   166  	err = prebl.processTx(pool, propose2)
   167  	assert.Equal(t, nil, err)
   168  	assert.Equal(t, 2, len(prebl.proposed))
   169  
   170  	err = prebl.processTx(pool, proposeWL)
   171  	assert.Equal(t, nil, err)
   172  	assert.Equal(t, 2, len(prebl.proposed))
   173  	assert.True(t, IsWhitelisted(pool.currentState, wladdr1))
   174  
   175  	// Non-EBI
   176  	err = prebl.processTx(pool, proposePaid)
   177  	assert.Equal(t, nil, err)
   178  	assert.Equal(t, 2, len(prebl.proposed))
   179  
   180  	log.Trace("Check if filtered properly")
   181  	signer.sender = bladdr1
   182  	err = prebl.processTx(pool, revoke)
   183  	assert.Equal(t, ErrPreBlacklist, err)
   184  
   185  	signer.sender = sender
   186  	err = prebl.processTx(pool, revoke)
   187  	assert.Equal(t, nil, err)
   188  
   189  	signer.sender = bladdr2
   190  	err = prebl.processTx(pool, revoke)
   191  	assert.Equal(t, ErrPreBlacklist, err)
   192  
   193  	signer.sender = sender
   194  
   195  	log.Trace("Check block filter hook")
   196  	blocks := make(types.Blocks, 0, 3)
   197  	blocks = append(blocks, types.NewBlockWithHeader(&types.Header{Coinbase: sender}))
   198  	blocks = append(blocks, types.NewBlockWithHeader(&types.Header{Coinbase: bladdr1}))
   199  	blocks = append(blocks, types.NewBlockWithHeader(&types.Header{Coinbase: sender}))
   200  	blocks = pool.PreBlacklistHook(blocks)
   201  	assert.Equal(t, 1, len(blocks))
   202  	assert.Equal(t, sender, blocks[0].Coinbase())
   203  
   204  	log.Trace("After timeout")
   205  	adjust_time = pbPeriod + time.Minute
   206  
   207  	err = prebl.processTx(pool, revoke)
   208  	assert.Equal(t, nil, err)
   209  	assert.Equal(t, 1, len(prebl.proposed))
   210  
   211  	err = prebl.processTx(pool, propose1)
   212  	assert.Equal(t, nil, err)
   213  	assert.Equal(t, 2, len(prebl.proposed))
   214  
   215  	err = prebl.processTx(pool, propose2)
   216  	assert.Equal(t, nil, err)
   217  	assert.Equal(t, 2, len(prebl.proposed))
   218  
   219  	adjust_time *= time.Duration(2)
   220  	err = prebl.processTx(pool, revoke)
   221  	assert.Equal(t, nil, err)
   222  	assert.Equal(t, 0, len(prebl.proposed))
   223  
   224  	log.Trace("Ignore not valid proposals")
   225  
   226  	pool.currentState.SetCode(
   227  		energi_params.Energi_BlacklistRegistry,
   228  		// PUSH1 1 PUSH1 0 MSTORE PUSH1 1 PUSH1 0 REVERT
   229  		[]byte{0x60, 0x01, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0xFD},
   230  	)
   231  
   232  	err = prebl.processTx(pool, propose1)
   233  	assert.Equal(t, nil, err)
   234  	assert.Equal(t, 0, len(prebl.proposed))
   235  }
   236  
   237  func TestPersistence(t *testing.T) {
   238  	dir, err := ioutil.TempDir(os.TempDir(), "test-*")
   239  	if err != nil {
   240  		panic(err)
   241  	}
   242  
   243  	statedb, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
   244  	blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
   245  	pool := NewTxPool(TxPoolConfig{Protection: dir}, params.TestChainConfig, blockchain)
   246  
   247  	preblacklistNewData := map[common.Address]time.Time{
   248  		common.HexToAddress("12"): time.Unix(123456, 0),
   249  		common.HexToAddress("13"): time.Unix(56789, 0),
   250  	}
   251  
   252  	mnHeartbeatsNewData := map[common.Address]time.Time{
   253  		common.HexToAddress("14"): time.Unix(674782, 0),
   254  		common.HexToAddress("15"): time.Unix(1232142, 0),
   255  	}
   256  
   257  	mnInvalidationsNewData := map[common.Address]time.Time{
   258  		common.HexToAddress("24"): time.Unix(13132, 0),
   259  		common.HexToAddress("35"): time.Unix(113231, 0),
   260  	}
   261  
   262  	mnCheckpointsNewData := map[common.Address]time.Time{
   263  		common.HexToAddress("124"): time.Unix(1231124, 0),
   264  		common.HexToAddress("152"): time.Unix(123123, 0),
   265  	}
   266  
   267  	coinClaimsNewData := map[uint32]time.Time{
   268  		3124: time.Unix(12313, 0),
   269  		3152: time.Unix(123121, 0),
   270  	}
   271  
   272  	// Assign the new data.
   273  	pool.preBlacklist.proposed = preblacklistNewData
   274  	pool.zfProtector.mnHeartbeats = mnHeartbeatsNewData
   275  	pool.zfProtector.mnInvalidations = mnInvalidationsNewData
   276  	pool.zfProtector.mnCheckpoints = mnCheckpointsNewData
   277  	pool.zfProtector.coinClaims = coinClaimsNewData
   278  
   279  	// Persist in the persist path.
   280  	err = pool.persistenceWriter()
   281  	assert.Equal(t, nil, err)
   282  
   283  	// Drop the previous set data to simulate a shutdown.
   284  	pool.preBlacklist.proposed = nil
   285  	pool.zfProtector.mnHeartbeats = nil
   286  	pool.zfProtector.mnInvalidations = nil
   287  	pool.zfProtector.mnCheckpoints = nil
   288  	pool.zfProtector.coinClaims = nil
   289  
   290  	// Assert that the data was actually dropped.
   291  	assert.NotEqual(t, preblacklistNewData, pool.preBlacklist.proposed)
   292  	assert.NotEqual(t, mnHeartbeatsNewData, pool.zfProtector.mnHeartbeats)
   293  	assert.NotEqual(t, mnInvalidationsNewData, pool.zfProtector.mnInvalidations)
   294  	assert.NotEqual(t, mnCheckpointsNewData, pool.zfProtector.mnCheckpoints)
   295  	assert.NotEqual(t, coinClaimsNewData, pool.zfProtector.coinClaims)
   296  
   297  	// Read the persisted data.
   298  	err = pool.persistenceReader()
   299  	assert.Equal(t, nil, err)
   300  
   301  	// Assert that the persisted data was successfully read.
   302  	assert.Equal(t, preblacklistNewData, pool.preBlacklist.proposed)
   303  	assert.Equal(t, mnHeartbeatsNewData, pool.zfProtector.mnHeartbeats)
   304  	assert.Equal(t, mnInvalidationsNewData, pool.zfProtector.mnInvalidations)
   305  	assert.Equal(t, mnCheckpointsNewData, pool.zfProtector.mnCheckpoints)
   306  	assert.Equal(t, coinClaimsNewData, pool.zfProtector.coinClaims)
   307  
   308  	// Cleanup
   309  	os.Remove(dir)
   310  }