github.com/cheng762/platon-go@v1.8.17-0.20190529111256-7deff2d7be26/consensus/cbft/cbft_test.go (about) 1 package cbft 2 3 import ( 4 "container/list" 5 "crypto/md5" 6 "encoding/json" 7 "flag" 8 "fmt" 9 "github.com/PlatONnetwork/PlatON-Go/common" 10 "github.com/PlatONnetwork/PlatON-Go/core/types" 11 "github.com/PlatONnetwork/PlatON-Go/crypto" 12 "github.com/PlatONnetwork/PlatON-Go/log" 13 "github.com/PlatONnetwork/PlatON-Go/p2p/discover" 14 "github.com/PlatONnetwork/PlatON-Go/params" 15 "math/big" 16 "os" 17 "strconv" 18 "testing" 19 ) 20 21 func TestMain(m *testing.M) { 22 fmt.Println("test begin ...") 23 initTest() 24 25 flag.Parse() 26 exitCode := m.Run() 27 28 destroyTest() 29 fmt.Println("test end ...") 30 // Exit 31 os.Exit(exitCode) 32 } 33 34 //var cbftConfig *params.CbftConfig 35 var forkRootHash common.Hash 36 var rootBlock *types.Block 37 var rootNumber uint64 38 var hash23 common.Hash 39 var lastMainBlockHash common.Hash 40 41 var discreteBlock *types.Block 42 var lastMainBlock *types.Block 43 var lastButOneMainBlock *types.Block 44 45 func TestMarshalJson(t *testing.T){ 46 obj := NewBlockExt(lastButOneMainBlock, 0) 47 obj.inTree = true 48 obj.isExecuted = true 49 obj.isSigned = true 50 obj.isConfirmed = true 51 obj.parent = nil 52 53 t.Log("cbft.highestConfirmed is null", "hash:", obj.Hash) 54 fmt.Println("cbft.highestConfirmed:" + obj.Hash) 55 56 jsons, errs := json.Marshal(obj) //byte[] for json 57 if errs != nil { 58 fmt.Println(errs.Error()) 59 } 60 fmt.Println("obj:" + string(jsons)) //byte[] to string 61 } 62 63 func TestBlockSynced_discreteBlock(t *testing.T) { 64 doBlockSynced(discreteBlock, t) 65 } 66 67 func TestBlockSynced_lastMainBlock(t *testing.T) { 68 doBlockSynced(lastMainBlock, t) 69 } 70 71 func TestBlockSynced_lastButOneMainBlock(t *testing.T) { 72 doBlockSynced(lastButOneMainBlock, t) 73 } 74 75 /*func TestBlockSynced_hash23(t *testing.T) { 76 doBlockSynced(cbft.findBlockExt(hash23).block, t) 77 } 78 */ 79 80 func doBlockSynced(currentBlock *types.Block, t *testing.T){ 81 if currentBlock.NumberU64() > cbft.getRootIrreversible().Number { 82 log.Debug("chain has a higher irreversible block", "hash", currentBlock.Hash(), "number", currentBlock.NumberU64()) 83 newRoot := cbft.findBlockExt(currentBlock.Hash()) 84 if newRoot == nil || newRoot.block == nil { 85 log.Debug("higher irreversible block is not existing in memory", "newTree", newRoot.toJson()) 86 //the block synced from other peer is a new block in local peer 87 //remove all blocks referenced in old tree after being cut off 88 cbft.cleanByTailoredTree(cbft.getRootIrreversible()) 89 90 newRoot = NewBlockExt(currentBlock, currentBlock.NumberU64()) 91 newRoot.inTree = true 92 newRoot.isExecuted = true 93 newRoot.isSigned = true 94 newRoot.isConfirmed = true 95 newRoot.Number = currentBlock.NumberU64() 96 newRoot.parent = nil 97 cbft.saveBlockExt(newRoot.block.Hash(), newRoot) 98 99 cbft.buildChildNode(newRoot) 100 101 if len(newRoot.Children) > 0{ 102 //the new root's children should re-execute base on new state 103 for _, child := range newRoot.Children { 104 if err := cbft.executeBlockAndDescendantMock(child, newRoot); err != nil { 105 log.Error("execute the block error", "err", err) 106 break 107 } 108 } 109 //there are some redundancy code for newRoot, but these codes are necessary for other logical blocks 110 cbft.signLogicalAndDescendantMock(newRoot) 111 } 112 113 } else if newRoot.block != nil { 114 log.Debug("higher irreversible block is existing in memory","newTree", newRoot.toJson()) 115 116 //the block synced from other peer exists in local peer 117 newRoot.isExecuted = true 118 newRoot.isSigned = true 119 newRoot.isConfirmed = true 120 newRoot.Number = currentBlock.NumberU64() 121 122 if newRoot.inTree == false { 123 newRoot.inTree = true 124 125 cbft.setDescendantInTree(newRoot) 126 127 if len(newRoot.Children) > 0{ 128 //the new root's children should re-execute base on new state 129 for _, child := range newRoot.Children { 130 if err := cbft.executeBlockAndDescendantMock(child, newRoot); err != nil { 131 log.Error("execute the block error", "err", err) 132 break 133 } 134 } 135 //there are some redundancy code for newRoot, but these codes are necessary for other logical blocks 136 cbft.signLogicalAndDescendantMock(newRoot) 137 } 138 }else{ 139 //cut off old tree from new root, 140 tailorTree(newRoot) 141 } 142 143 //remove all blocks referenced in old tree after being cut off 144 cbft.cleanByTailoredTree(cbft.getRootIrreversible()) 145 } 146 147 //remove all other blocks those their numbers are too low 148 cbft.cleanByNumber(newRoot.Number) 149 150 log.Debug("the cleared new tree in memory", "json", newRoot.toJson()) 151 152 //reset the new root irreversible 153 cbft.rootIrreversible.Store(newRoot) 154 155 log.Debug("reset the new root irreversible by synced", "hash", newRoot.block.Hash(), "number", newRoot.block.NumberU64()) 156 157 158 //reset logical path 159 highestLogical := cbft.findHighestLogical(newRoot) 160 //cbft.setHighestLogical(highestLogical) 161 cbft.highestLogical.Store(highestLogical) 162 163 t.Log("reset the highestLogical by synced", "number", highestLogical.block.NumberU64(), "newRoot.number", newRoot.block.NumberU64() ) 164 165 //reset highest confirmed block 166 highestConfirmed :=cbft.findLastClosestConfirmedIncludingSelf(newRoot) 167 cbft.highestConfirmed.Store(highestConfirmed) 168 if highestConfirmed != nil { 169 t.Log("cbft.highestConfirmed", "number", highestConfirmed.block.NumberU64(),"rcvTime", highestConfirmed.rcvTime) 170 } else { 171 172 t.Log("reset the highestConfirmed by synced failure because findLastClosestConfirmedIncludingSelf() returned nil", "newRoot.number", newRoot.block.NumberU64()) 173 174 } 175 } 176 } 177 178 179 180 func TestFindLastClosestConfirmedIncludingSelf(t *testing.T) { 181 182 newRoot := NewBlockExt(rootBlock, 0) 183 newRoot.inTree = true 184 newRoot.isExecuted = true 185 newRoot.isSigned = true 186 newRoot.isConfirmed = true 187 newRoot.Number = rootBlock.NumberU64() 188 189 //reorg the block tree 190 children := cbft.findChildren(newRoot) 191 for _, child := range children { 192 child.parent = newRoot 193 child.inTree = true 194 } 195 newRoot.Children = children 196 197 //save the root in BlockExtMap 198 cbft.saveBlockExt(newRoot.block.Hash(), newRoot) 199 200 //reset the new root irreversible 201 cbft.rootIrreversible.Store(newRoot) 202 //the new root's children should re-execute base on new state 203 for _, child := range newRoot.Children { 204 if err := cbft.executeBlockAndDescendant(child, newRoot); err != nil { 205 //remove bad block from tree and map 206 cbft.removeBadBlock(child) 207 break 208 } 209 } 210 211 //there are some redundancy code for newRoot, but these codes are necessary for other logical blocks 212 cbft.signLogicalAndDescendant(newRoot) 213 214 //reset logical path 215 //highestLogical := cbft.findHighestLogical(newRoot) 216 //cbft.setHighestLogical(highestLogical) 217 //reset highest confirmed block 218 cbft.highestConfirmed.Store(cbft.findLastClosestConfirmedIncludingSelf(newRoot)) 219 220 if cbft.getHighestLogical() != nil { 221 t.Log("ok") 222 } else { 223 t.Log("cbft.highestConfirmed is null") 224 } 225 } 226 func TestFindClosestConfirmedExcludingSelf(t *testing.T) { 227 newRoot := NewBlockExt(rootBlock, 0) 228 newRoot.inTree = true 229 newRoot.isExecuted = true 230 newRoot.isSigned = true 231 newRoot.isConfirmed = true 232 newRoot.Number = rootBlock.NumberU64() 233 234 closest := cbft.findClosestConfirmedExcludingSelf(newRoot) 235 fmt.Println(closest) 236 } 237 238 func TestExecuteBlockAndDescendant(t *testing.T) { 239 newRoot := NewBlockExt(rootBlock, 0) 240 newRoot.inTree = true 241 newRoot.isExecuted = true 242 newRoot.isSigned = true 243 newRoot.isConfirmed = true 244 newRoot.Number = rootBlock.NumberU64() 245 246 //save the root in BlockExtMap 247 cbft.saveBlockExt(newRoot.block.Hash(), newRoot) 248 249 //reset the new root irreversible 250 cbft.rootIrreversible.Store(newRoot) 251 //reorg the block tree 252 cbft.buildChildNode(newRoot) 253 254 //the new root's children should re-execute base on new state 255 for _, child := range newRoot.Children { 256 if err := cbft.executeBlockAndDescendant(child, newRoot); err != nil { 257 //remove bad block from tree and map 258 cbft.removeBadBlock(child) 259 break 260 } 261 } 262 263 //there are some redundancy code for newRoot, but these codes are necessary for other logical blocks 264 cbft.signLogicalAndDescendant(newRoot) 265 } 266 267 func TestBackTrackBlocksIncludingEnd(t *testing.T) { 268 testBackTrackBlocks(t, true) 269 } 270 271 func TestBackTrackBlocksExcludingEnd(t *testing.T) { 272 testBackTrackBlocks(t, false) 273 } 274 275 func testBackTrackBlocks(t *testing.T, includeEnd bool) { 276 end, _ := cbft.blockExtMap.Load(rootBlock.Hash()) 277 exts := cbft.backTrackBlocks(cbft.getHighestLogical(), end.(*BlockExt), includeEnd) 278 279 t.Log("len(exts)", len(exts)) 280 } 281 282 func initTest() { 283 nodes := initNodes() 284 priKey, _ := crypto.HexToECDSA("0x8b54398b67e656dcab213c1b5886845963a9ab0671786eefaf6e241ee9c8074f") 285 286 cbftConfig := ¶ms.CbftConfig{ 287 Period: 1, 288 Epoch: 250000, 289 MaxLatency: 600, 290 Duration: 10, 291 InitialNodes: nodes, 292 NodeID: nodes[0].ID, 293 PrivateKey: priKey, 294 } 295 296 cbft = &Cbft{ 297 config: cbftConfig, 298 //blockExtMap: make(map[common.Hash]*BlockExt), 299 //signedSet: make(map[uint64]struct{}), 300 netLatencyMap: make(map[discover.NodeID]*list.List), 301 } 302 buildMain(cbft) 303 304 buildFork(cbft) 305 } 306 307 func destroyTest() { 308 cbft.Close() 309 } 310 311 func buildFork(cbft *Cbft) { 312 313 //sealhash := cbft.SealHash(header) 314 315 parentHash := forkRootHash 316 for i := uint64(3); i <= 5; i++ { 317 header := &types.Header{ 318 ParentHash: parentHash, 319 Number: big.NewInt(int64(i)), 320 TxHash: hash(2, i), 321 } 322 block := types.NewBlockWithHeader(header) 323 324 ext := &BlockExt{ 325 block: block, 326 inTree: true, 327 isExecuted: true, 328 isConfirmed: false, 329 rcvTime: int64(20+i), 330 Number: block.NumberU64(), 331 signs: make([]*common.BlockConfirmSign, 0), 332 } 333 cbft.blockExtMap.Store(block.Hash(), ext) 334 335 parentHash = block.Hash() 336 337 if i == 3 { 338 ext.isSigned=false 339 ext.isConfirmed=false 340 hash23 = block.Hash() 341 } else if i == 4 { 342 ext.isSigned=true 343 ext.isConfirmed=false 344 } else if i == 5 { 345 ext.isSigned=false 346 ext.isConfirmed=false 347 } 348 cbft.buildIntoTree(ext) 349 } 350 } 351 352 func hash(branch uint64, number uint64) (hash common.Hash) { 353 s := "branch" + strconv.FormatUint(branch, 10) + "number" + strconv.FormatUint(number, 10) 354 signByte := []byte(s) 355 hasher := md5.New() 356 hasher.Write(signByte) 357 return common.BytesToHash(hasher.Sum(nil)) 358 } 359 360 361 362 363 func buildMain(cbft *Cbft) { 364 365 //sealhash := cbft.SealHash(header) 366 367 rootHeader := &types.Header{Number: big.NewInt(0), TxHash: hash(1, 0)} 368 rootBlock = types.NewBlockWithHeader(rootHeader) 369 rootNumber = 0 370 371 rootExt := &BlockExt{ 372 block: rootBlock, 373 inTree: true, 374 isExecuted: true, 375 isSigned: true, 376 isConfirmed: true, 377 rcvTime: 0, 378 Number: rootBlock.NumberU64(), 379 signs: make([]*common.BlockConfirmSign, 0), 380 } 381 382 //hashSet[uint64(0)] = rootBlock.Hash() 383 cbft.blockExtMap.Store(rootBlock.Hash(), rootExt) 384 cbft.highestConfirmed.Store(rootExt) 385 cbft.rootIrreversible.Store(rootExt) 386 387 parentHash := rootBlock.Hash() 388 for i := uint64(1); i <= 5; i++ { 389 header := &types.Header{ 390 ParentHash: parentHash, 391 Number: big.NewInt(int64(i)), 392 TxHash: hash(1, i), 393 } 394 block := types.NewBlockWithHeader(header) 395 396 ext := &BlockExt{ 397 block: block, 398 inTree: true, 399 isExecuted: true, 400 isSigned: true, 401 isConfirmed: false, 402 rcvTime: int64(i), 403 Number: block.NumberU64(), 404 signs: make([]*common.BlockConfirmSign, 0), 405 } 406 //hashSet[i] = rootBlock.Hash() 407 cbft.blockExtMap.Store(block.Hash(), ext) 408 409 cbft.highestLogical.Store(ext) 410 411 parentHash = block.Hash() 412 413 if i == 2 { 414 forkRootHash = block.Hash() 415 ext.isSigned=false 416 ext.isConfirmed=true 417 } else if i == 3 { 418 ext.isSigned=true 419 ext.isConfirmed=false 420 } else if i == 4 { 421 lastButOneMainBlock = block 422 423 ext.isSigned=false 424 ext.isConfirmed=false 425 } else if i == 5 { 426 lastMainBlock = block 427 ext.isSigned=false 428 ext.isConfirmed=false 429 430 } 431 cbft.buildIntoTree(ext) 432 } 433 434 notExistHeader := &types.Header{ 435 ParentHash: parentHash, 436 Number: big.NewInt(int64(20)), 437 TxHash: hash(1, 20), 438 } 439 notExistBlock := types.NewBlockWithHeader(notExistHeader) 440 441 442 discreteHeader := &types.Header{ 443 ParentHash: notExistBlock.Hash(), 444 Number: big.NewInt(int64(6)), 445 TxHash: hash(1, 6), 446 } 447 discreteBlock = types.NewBlockWithHeader(discreteHeader) 448 449 discreteExt := &BlockExt{ 450 block: discreteBlock, 451 inTree: false, 452 isExecuted: false, 453 isSigned: false, 454 isConfirmed: false, 455 rcvTime: int64(220), 456 Number: discreteBlock.NumberU64(), 457 signs: make([]*common.BlockConfirmSign, 0), 458 } 459 //hashSet[i] = rootBlock.Hash() 460 cbft.blockExtMap.Store(discreteBlock.Hash(), discreteExt) 461 462 parentHash = discreteBlock.Hash() 463 for i := 7; i <= 7; i++ { 464 header := &types.Header{ 465 ParentHash: parentHash, 466 Number: big.NewInt(int64(i)), 467 TxHash: hash(1, uint64(i)), 468 } 469 block := types.NewBlockWithHeader(header) 470 471 ext := &BlockExt{ 472 block: block, 473 inTree: false, 474 isExecuted: false, 475 isSigned: false, 476 isConfirmed: false, 477 rcvTime: int64(i), 478 Number: block.NumberU64(), 479 signs: make([]*common.BlockConfirmSign, 0), 480 } 481 //hashSet[i] = rootBlock.Hash() 482 cbft.blockExtMap.Store(block.Hash(), ext) 483 parentHash = block.Hash() 484 } 485 486 } 487 488 func initNodes() []discover.Node { 489 var nodes [3]discover.Node 490 491 initialNodes := [3]string{ 492 "1f3a8672348ff6b789e416762ad53e69063138b8eb4d8780101658f24b2369f1a8e09499226b467d8bc0c4e03e1dc903df857eeb3c67733d21b6aaee2840e429", 493 "751f4f62fccee84fc290d0c68d673e4b0cc6975a5747d2baccb20f954d59ba3315d7bfb6d831523624d003c8c2d33451129e67c3eef3098f711ef3b3e268fd3c", 494 "b6c8c9f99bfebfa4fb174df720b9385dbd398de699ec36750af3f38f8e310d4f0b90447acbef64bdf924c4b59280f3d42bb256e6123b53e9a7e99e4c432549d6", 495 } 496 nodeIDs := convert(initialNodes[:]) 497 498 for i, node := range nodes { 499 node.ID = nodeIDs[i] 500 } 501 502 return nodes[:] 503 } 504 func convert(initialNodes []string) []discover.NodeID { 505 NodeIDList := make([]discover.NodeID, 0, len(initialNodes)) 506 for _, value := range initialNodes { 507 if nodeID, error := discover.HexID(value); error == nil { 508 NodeIDList = append(NodeIDList, nodeID) 509 } 510 } 511 return NodeIDList 512 }