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 }