github.com/igggame/nebulas-go@v2.1.0+incompatible/core/block_pool_test.go (about)

     1  // Copyright (C) 2017 go-nebulas authors
     2  //
     3  // This file is part of the go-nebulas library.
     4  //
     5  // the go-nebulas library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // the go-nebulas library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  // GNU General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU General Public License
    16  // along with the go-nebulas library.  If not, see <http://www.gnu.org/licenses/>.
    17  //
    18  
    19  package core
    20  
    21  import (
    22  	"testing"
    23  
    24  	"github.com/nebulasio/go-nebulas/core/pb"
    25  
    26  	"time"
    27  
    28  	"github.com/gogo/protobuf/proto"
    29  	"github.com/nebulasio/go-nebulas/crypto"
    30  	"github.com/nebulasio/go-nebulas/crypto/keystore"
    31  	"github.com/nebulasio/go-nebulas/crypto/keystore/secp256k1"
    32  	"github.com/nebulasio/go-nebulas/net"
    33  	"github.com/nebulasio/go-nebulas/util"
    34  	"github.com/stretchr/testify/assert"
    35  )
    36  
    37  func TestBlockPool(t *testing.T) {
    38  	received = []byte{}
    39  
    40  	ks := keystore.DefaultKS
    41  	priv := secp256k1.GeneratePrivateKey()
    42  	pubdata, _ := priv.PublicKey().Encoded()
    43  	from, _ := NewAddressFromPublicKey(pubdata)
    44  	ks.SetKey(from.String(), priv, []byte("passphrase"))
    45  	ks.Unlock(from.String(), []byte("passphrase"), time.Second*60*60*24*365)
    46  	key, _ := ks.GetUnlocked(from.String())
    47  	signature, _ := crypto.NewSignature(keystore.SECP256K1)
    48  	signature.InitSign(key.(keystore.PrivateKey))
    49  
    50  	// generate block
    51  	neb := testNeb(t)
    52  	bc := neb.chain
    53  	pool := bc.bkPool
    54  	assert.Equal(t, pool.cache.Len(), 0)
    55  
    56  	bc.tailBlock.Begin()
    57  	baseGas, _ := util.NewUint128FromInt(2000000)
    58  	balance, err := TransactionGasPrice.Mul(baseGas)
    59  	assert.Nil(t, err)
    60  	acc, err := bc.tailBlock.worldState.GetOrCreateUserAccount(from.Bytes())
    61  	assert.Nil(t, err)
    62  	acc.AddBalance(balance)
    63  	assert.Nil(t, err)
    64  	bc.tailBlock.Commit()
    65  	bc.tailBlock.header.stateRoot = bc.tailBlock.worldState.AccountsRoot()
    66  	bc.StoreBlockToStorage(bc.tailBlock)
    67  
    68  	addr, err := AddressParse(MockDynasty[1])
    69  	assert.Nil(t, err)
    70  	block0, err := NewBlock(bc.ChainID(), addr, bc.tailBlock)
    71  	assert.Nil(t, err)
    72  	block0.header.timestamp = bc.tailBlock.header.timestamp + BlockInterval
    73  	block0.Seal()
    74  	signBlock(block0)
    75  	assert.Nil(t, pool.Push(block0))
    76  
    77  	addr, err = AddressParse(MockDynasty[2])
    78  	assert.Nil(t, err)
    79  	block1, err := NewBlock(bc.ChainID(), addr, bc.tailBlock)
    80  	assert.Nil(t, err)
    81  	block1.header.timestamp = block0.header.timestamp + BlockInterval
    82  	block1.Seal()
    83  	signBlock(block1)
    84  	assert.Nil(t, pool.Push(block1))
    85  
    86  	addr, err = AddressParse(MockDynasty[3])
    87  	assert.Nil(t, err)
    88  	block2, err := NewBlock(bc.ChainID(), addr, bc.tailBlock)
    89  	assert.Nil(t, err)
    90  	block2.header.timestamp = block1.header.timestamp + BlockInterval
    91  	block2.Seal()
    92  	signBlock(block2)
    93  	assert.Nil(t, pool.Push(block2))
    94  
    95  	addr, err = AddressParse(MockDynasty[4])
    96  	assert.Nil(t, err)
    97  	block3, err := NewBlock(bc.ChainID(), addr, bc.tailBlock)
    98  	assert.Nil(t, err)
    99  	block3.header.timestamp = block2.header.timestamp + BlockInterval
   100  	block3.Seal()
   101  	signBlock(block3)
   102  	assert.Nil(t, pool.Push(block3))
   103  
   104  	addr, err = AddressParse(MockDynasty[5])
   105  	assert.Nil(t, err)
   106  	block4, err := NewBlock(bc.ChainID(), addr, bc.tailBlock)
   107  	assert.Nil(t, err)
   108  	block4.header.timestamp = block3.header.timestamp + BlockInterval
   109  	block4.Seal()
   110  	signBlock(block4)
   111  	assert.Nil(t, pool.Push(block4))
   112  
   113  	// push blocks into pool in random order
   114  	neb = testNeb(t)
   115  	bc = neb.chain
   116  	pool = bc.bkPool
   117  
   118  	bc.tailBlock.Begin()
   119  	baseGas, _ = util.NewUint128FromInt(2000000)
   120  	balance, err = TransactionGasPrice.Mul(baseGas)
   121  	assert.Nil(t, err)
   122  	acc, err = bc.tailBlock.worldState.GetOrCreateUserAccount(from.Bytes())
   123  	assert.Nil(t, err)
   124  	acc.AddBalance(balance)
   125  	assert.Nil(t, err)
   126  	bc.tailBlock.Commit()
   127  	bc.tailBlock.header.stateRoot = bc.tailBlock.worldState.AccountsRoot()
   128  	bc.StoreBlockToStorage(bc.tailBlock)
   129  
   130  	err = pool.Push(block0)
   131  	assert.Nil(t, err)
   132  	assert.Equal(t, pool.cache.Len(), 0)
   133  	err = pool.PushAndBroadcast(block0)
   134  	assert.Equal(t, err, ErrDuplicatedBlock)
   135  
   136  	err = pool.Push(block3)
   137  	assert.Equal(t, pool.cache.Len(), 1)
   138  	assert.Error(t, err, ErrMissingParentBlock)
   139  	err = pool.Push(block4)
   140  	assert.Equal(t, pool.cache.Len(), 2)
   141  	assert.Error(t, err, ErrMissingParentBlock)
   142  	err = pool.Push(block2)
   143  	assert.Equal(t, pool.cache.Len(), 3)
   144  	assert.Error(t, err, ErrMissingParentBlock)
   145  
   146  	err = pool.Push(block1)
   147  	assert.NoError(t, err)
   148  	assert.Equal(t, pool.cache.Len(), 0)
   149  
   150  	bc.SetTailBlock(block4)
   151  	assert.Equal(t, bc.tailBlock.Hash(), block4.Hash())
   152  
   153  	addr, err = AddressParse(MockDynasty[0])
   154  	assert.Nil(t, err)
   155  	block5, err := NewBlock(bc.ChainID(), addr, block4)
   156  	assert.Nil(t, err)
   157  	block5.header.timestamp = block4.header.timestamp + BlockInterval
   158  	block5.Seal()
   159  	signBlock(block5)
   160  	block5.header.hash[0]++
   161  	assert.Equal(t, pool.Push(block5), ErrInvalidBlockHash)
   162  }
   163  
   164  func TestHandleBlock(t *testing.T) {
   165  	neb := testNeb(t)
   166  	bc := neb.chain
   167  	from := mockAddress()
   168  	ks := keystore.DefaultKS
   169  	key, err := ks.GetUnlocked(from.String())
   170  	signature, err := crypto.NewSignature(keystore.SECP256K1)
   171  	assert.Nil(t, err)
   172  	signature.InitSign(key.(keystore.PrivateKey))
   173  
   174  	// wrong msg type
   175  	block, err := bc.NewBlock(from)
   176  	assert.Nil(t, err)
   177  	assert.Nil(t, block.Seal())
   178  	assert.Nil(t, block.Sign(signature))
   179  	pbMsg, err := block.ToProto()
   180  	assert.Nil(t, err)
   181  	data, err := proto.Marshal(pbMsg)
   182  	assert.Nil(t, err)
   183  	msg := net.NewBaseMessage(MessageTypeNewTx, "from", data)
   184  	bc.bkPool.handleReceivedBlock(msg)
   185  	assert.Nil(t, bc.GetBlock(block.Hash()))
   186  
   187  	// expired block
   188  	block, err = bc.NewBlock(from)
   189  	assert.Nil(t, err)
   190  	block.header.timestamp = time.Now().Unix() - AcceptedNetWorkDelay - 1
   191  	assert.Nil(t, block.Seal())
   192  	assert.Nil(t, block.Sign(signature))
   193  	pbMsg, err = block.ToProto()
   194  	assert.Nil(t, err)
   195  	data, err = proto.Marshal(pbMsg)
   196  	msg = net.NewBaseMessage(MessageTypeNewBlock, "from", data)
   197  	bc.bkPool.handleReceivedBlock(msg)
   198  	assert.Nil(t, bc.GetBlock(block.Hash()))
   199  
   200  	// success
   201  	block, err = bc.NewBlock(from)
   202  	assert.Nil(t, err)
   203  	block.Seal()
   204  	block.Sign(signature)
   205  	pbMsg, err = block.ToProto()
   206  	assert.Nil(t, err)
   207  	data, err = proto.Marshal(pbMsg)
   208  	msg = net.NewBaseMessage(MessageTypeBlockDownloadResponse, "from", data)
   209  	bc.bkPool.handleReceivedBlock(msg)
   210  	assert.NotNil(t, bc.GetBlock(block.Hash()))
   211  }
   212  
   213  func TestHandleDownloadedBlock(t *testing.T) {
   214  	received = []byte{}
   215  
   216  	neb := testNeb(t)
   217  	bc := neb.chain
   218  	from := mockAddress()
   219  	ks := keystore.DefaultKS
   220  	key, err := ks.GetUnlocked(from.String())
   221  	signature, err := crypto.NewSignature(keystore.SECP256K1)
   222  	assert.Nil(t, err)
   223  	signature.InitSign(key.(keystore.PrivateKey))
   224  
   225  	block1, err := bc.NewBlock(from)
   226  	assert.Nil(t, err)
   227  	block1.SetTimestamp(BlockInterval)
   228  	block1.Seal()
   229  	block1.Sign(signature)
   230  
   231  	// wrong message type
   232  	downloadBlock := new(corepb.DownloadBlock)
   233  	downloadBlock.Hash = block1.Hash()
   234  	downloadBlock.Sign = block1.Signature()
   235  	data, err := proto.Marshal(downloadBlock)
   236  	assert.Nil(t, err)
   237  	msg := net.NewBaseMessage(MessageTypeNewBlock, "from", data)
   238  	bc.bkPool.handleParentDownloadRequest(msg)
   239  	assert.Equal(t, received, []byte{})
   240  
   241  	// no need to download genesis
   242  	downloadBlock = new(corepb.DownloadBlock)
   243  	downloadBlock.Hash = bc.genesisBlock.Hash()
   244  	downloadBlock.Sign = bc.genesisBlock.Signature()
   245  	data, err = proto.Marshal(downloadBlock)
   246  	assert.Nil(t, err)
   247  	msg = net.NewBaseMessage(MessageTypeParentBlockDownloadRequest, "from", data)
   248  	bc.bkPool.handleParentDownloadRequest(msg)
   249  	assert.Equal(t, received, []byte{})
   250  
   251  	// cannot find downloaded block
   252  	downloadBlock = new(corepb.DownloadBlock)
   253  	downloadBlock.Hash = block1.Hash()
   254  	downloadBlock.Sign = block1.Signature()
   255  	data, err = proto.Marshal(downloadBlock)
   256  	assert.Nil(t, err)
   257  	msg = net.NewBaseMessage(MessageTypeParentBlockDownloadRequest, "from", data)
   258  	bc.bkPool.handleParentDownloadRequest(msg)
   259  	assert.Equal(t, received, []byte{})
   260  
   261  	// set new tail
   262  	assert.Nil(t, bc.BlockPool().Push(block1))
   263  	block2, err := bc.NewBlock(from)
   264  	assert.Nil(t, err)
   265  	block2.SetTimestamp(BlockInterval * 2)
   266  	block2.Seal()
   267  	block2.Sign(signature)
   268  	assert.Nil(t, bc.BlockPool().Push(block2))
   269  
   270  	// wrong signature
   271  	downloadBlock = new(corepb.DownloadBlock)
   272  	downloadBlock.Hash = block1.Hash()
   273  	downloadBlock.Sign = block2.Signature()
   274  	data, err = proto.Marshal(downloadBlock)
   275  	assert.Nil(t, err)
   276  	msg = net.NewBaseMessage(MessageTypeParentBlockDownloadRequest, "from", data)
   277  	bc.bkPool.handleParentDownloadRequest(msg)
   278  	assert.Equal(t, received, []byte{})
   279  
   280  	// right
   281  	downloadBlock = new(corepb.DownloadBlock)
   282  	downloadBlock.Hash = block1.Hash()
   283  	downloadBlock.Sign = block1.Signature()
   284  	data, err = proto.Marshal(downloadBlock)
   285  	assert.Nil(t, err)
   286  	msg = net.NewBaseMessage(MessageTypeParentBlockDownloadRequest, "from", data)
   287  	bc.bkPool.handleParentDownloadRequest(msg)
   288  	pbGenesis, err := bc.genesisBlock.ToProto()
   289  	assert.Nil(t, err)
   290  	data, err = proto.Marshal(pbGenesis)
   291  	assert.Nil(t, err)
   292  	assert.Equal(t, received, data)
   293  }