github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/consensus/clique/snapshot_test.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 19:16:34</date> 10 //</624450074604212224> 11 12 13 package clique 14 15 import ( 16 "bytes" 17 "crypto/ecdsa" 18 "sort" 19 "testing" 20 21 "github.com/ethereum/go-ethereum/common" 22 "github.com/ethereum/go-ethereum/core" 23 "github.com/ethereum/go-ethereum/core/types" 24 "github.com/ethereum/go-ethereum/core/vm" 25 "github.com/ethereum/go-ethereum/crypto" 26 "github.com/ethereum/go-ethereum/ethdb" 27 "github.com/ethereum/go-ethereum/params" 28 ) 29 30 //TestAccountPool是一个用于维护当前活动的测试人员帐户的池, 31 //从下面测试中使用的文本名称映射到实际的以太坊私有 32 //能够签署事务的密钥。 33 type testerAccountPool struct { 34 accounts map[string]*ecdsa.PrivateKey 35 } 36 37 func newTesterAccountPool() *testerAccountPool { 38 return &testerAccountPool{ 39 accounts: make(map[string]*ecdsa.PrivateKey), 40 } 41 } 42 43 // 44 // 45 func (ap *testerAccountPool) checkpoint(header *types.Header, signers []string) { 46 auths := make([]common.Address, len(signers)) 47 for i, signer := range signers { 48 auths[i] = ap.address(signer) 49 } 50 sort.Sort(signersAscending(auths)) 51 for i, auth := range auths { 52 copy(header.Extra[extraVanity+i*common.AddressLength:], auth.Bytes()) 53 } 54 } 55 56 //地址通过标签检索测试人员帐户的以太坊地址,创建 57 //如果以前的帐户还不存在,则为新帐户。 58 func (ap *testerAccountPool) address(account string) common.Address { 59 //返回非地址的零帐户 60 if account == "" { 61 return common.Address{} 62 } 63 //确保我们有帐户的持久密钥 64 if ap.accounts[account] == nil { 65 ap.accounts[account], _ = crypto.GenerateKey() 66 } 67 //解析并返回以太坊地址 68 return crypto.PubkeyToAddress(ap.accounts[account].PublicKey) 69 } 70 71 //符号为给定的块计算一组数字签名并将其嵌入 72 //回到标题。 73 func (ap *testerAccountPool) sign(header *types.Header, signer string) { 74 //确保我们有签名者的持久密钥 75 if ap.accounts[signer] == nil { 76 ap.accounts[signer], _ = crypto.GenerateKey() 77 } 78 //在头上签名并将签名嵌入额外的数据中 79 sig, _ := crypto.Sign(sigHash(header).Bytes(), ap.accounts[signer]) 80 copy(header.Extra[len(header.Extra)-extraSeal:], sig) 81 } 82 83 //testervote表示一个由parcitular帐户签名的单个块,其中 84 //该账户可能会或可能不会投集团票。 85 type testerVote struct { 86 signer string 87 voted string 88 auth bool 89 checkpoint []string 90 newbatch bool 91 } 92 93 //测试团体签名者投票是否正确地评估各种简单和 94 //复杂的场景,以及一些特殊的角落案例会正确失败。 95 func TestClique(t *testing.T) { 96 //定义要测试的各种投票方案 97 tests := []struct { 98 epoch uint64 99 signers []string 100 votes []testerVote 101 results []string 102 failure error 103 }{ 104 { 105 //单签名人,无投票权 106 signers: []string{"A"}, 107 votes: []testerVote{{signer: "A"}}, 108 results: []string{"A"}, 109 }, { 110 //单个签名人,投票添加两个其他人(只接受第一个,第二个需要2票) 111 signers: []string{"A"}, 112 votes: []testerVote{ 113 {signer: "A", voted: "B", auth: true}, 114 {signer: "B"}, 115 {signer: "A", voted: "C", auth: true}, 116 }, 117 results: []string{"A", "B"}, 118 }, { 119 //两个签名者,投票加三个(只接受前两个,第三个已经需要3票) 120 signers: []string{"A", "B"}, 121 votes: []testerVote{ 122 {signer: "A", voted: "C", auth: true}, 123 {signer: "B", voted: "C", auth: true}, 124 {signer: "A", voted: "D", auth: true}, 125 {signer: "B", voted: "D", auth: true}, 126 {signer: "C"}, 127 {signer: "A", voted: "E", auth: true}, 128 {signer: "B", voted: "E", auth: true}, 129 }, 130 results: []string{"A", "B", "C", "D"}, 131 }, { 132 //单个签名者,放弃自己(很奇怪,但明确允许这样做的话就少了一个死角) 133 signers: []string{"A"}, 134 votes: []testerVote{ 135 {signer: "A", voted: "A", auth: false}, 136 }, 137 results: []string{}, 138 }, { 139 //两个签名者,实际上需要双方同意放弃其中一个(未履行) 140 signers: []string{"A", "B"}, 141 votes: []testerVote{ 142 {signer: "A", voted: "B", auth: false}, 143 }, 144 results: []string{"A", "B"}, 145 }, { 146 //两个签名者,实际上需要双方同意放弃其中一个(满足) 147 signers: []string{"A", "B"}, 148 votes: []testerVote{ 149 {signer: "A", voted: "B", auth: false}, 150 {signer: "B", voted: "B", auth: false}, 151 }, 152 results: []string{"A"}, 153 }, { 154 //三个签名者,其中两个决定放弃第三个 155 signers: []string{"A", "B", "C"}, 156 votes: []testerVote{ 157 {signer: "A", voted: "C", auth: false}, 158 {signer: "B", voted: "C", auth: false}, 159 }, 160 results: []string{"A", "B"}, 161 }, { 162 //四个签名者,两个的共识不足以让任何人放弃 163 signers: []string{"A", "B", "C", "D"}, 164 votes: []testerVote{ 165 {signer: "A", voted: "C", auth: false}, 166 {signer: "B", voted: "C", auth: false}, 167 }, 168 results: []string{"A", "B", "C", "D"}, 169 }, { 170 //四个签名者,三个人的共识已经足够让某人离开 171 signers: []string{"A", "B", "C", "D"}, 172 votes: []testerVote{ 173 {signer: "A", voted: "D", auth: false}, 174 {signer: "B", voted: "D", auth: false}, 175 {signer: "C", voted: "D", auth: false}, 176 }, 177 results: []string{"A", "B", "C"}, 178 }, { 179 //每个签名者对每个目标的授权计数一次 180 signers: []string{"A", "B"}, 181 votes: []testerVote{ 182 {signer: "A", voted: "C", auth: true}, 183 {signer: "B"}, 184 {signer: "A", voted: "C", auth: true}, 185 {signer: "B"}, 186 {signer: "A", voted: "C", auth: true}, 187 }, 188 results: []string{"A", "B"}, 189 }, { 190 //允许同时授权多个帐户 191 signers: []string{"A", "B"}, 192 votes: []testerVote{ 193 {signer: "A", voted: "C", auth: true}, 194 {signer: "B"}, 195 {signer: "A", voted: "D", auth: true}, 196 {signer: "B"}, 197 {signer: "A"}, 198 {signer: "B", voted: "D", auth: true}, 199 {signer: "A"}, 200 {signer: "B", voted: "C", auth: true}, 201 }, 202 results: []string{"A", "B", "C", "D"}, 203 }, { 204 //每个目标的每个签名者对取消授权计数一次 205 signers: []string{"A", "B"}, 206 votes: []testerVote{ 207 {signer: "A", voted: "B", auth: false}, 208 {signer: "B"}, 209 {signer: "A", voted: "B", auth: false}, 210 {signer: "B"}, 211 {signer: "A", voted: "B", auth: false}, 212 }, 213 results: []string{"A", "B"}, 214 }, { 215 //允许同时解除多个帐户的授权 216 signers: []string{"A", "B", "C", "D"}, 217 votes: []testerVote{ 218 {signer: "A", voted: "C", auth: false}, 219 {signer: "B"}, 220 {signer: "C"}, 221 {signer: "A", voted: "D", auth: false}, 222 {signer: "B"}, 223 {signer: "C"}, 224 {signer: "A"}, 225 {signer: "B", voted: "D", auth: false}, 226 {signer: "C", voted: "D", auth: false}, 227 {signer: "A"}, 228 {signer: "B", voted: "C", auth: false}, 229 }, 230 results: []string{"A", "B"}, 231 }, { 232 //取消授权签名者的投票将立即被丢弃(取消授权投票) 233 signers: []string{"A", "B", "C"}, 234 votes: []testerVote{ 235 {signer: "C", voted: "B", auth: false}, 236 {signer: "A", voted: "C", auth: false}, 237 {signer: "B", voted: "C", auth: false}, 238 {signer: "A", voted: "B", auth: false}, 239 }, 240 results: []string{"A", "B"}, 241 }, { 242 //来自未授权签名者的投票将立即丢弃(授权投票) 243 signers: []string{"A", "B", "C"}, 244 votes: []testerVote{ 245 {signer: "C", voted: "B", auth: false}, 246 {signer: "A", voted: "C", auth: false}, 247 {signer: "B", voted: "C", auth: false}, 248 {signer: "A", voted: "B", auth: false}, 249 }, 250 results: []string{"A", "B"}, 251 }, { 252 //不允许级联更改,只有被投票的帐户才可以更改 253 signers: []string{"A", "B", "C", "D"}, 254 votes: []testerVote{ 255 {signer: "A", voted: "C", auth: false}, 256 {signer: "B"}, 257 {signer: "C"}, 258 {signer: "A", voted: "D", auth: false}, 259 {signer: "B", voted: "C", auth: false}, 260 {signer: "C"}, 261 {signer: "A"}, 262 {signer: "B", voted: "D", auth: false}, 263 {signer: "C", voted: "D", auth: false}, 264 }, 265 results: []string{"A", "B", "C"}, 266 }, { 267 //达成共识的变化超出范围(通过deauth)触摸执行 268 signers: []string{"A", "B", "C", "D"}, 269 votes: []testerVote{ 270 {signer: "A", voted: "C", auth: false}, 271 {signer: "B"}, 272 {signer: "C"}, 273 {signer: "A", voted: "D", auth: false}, 274 {signer: "B", voted: "C", auth: false}, 275 {signer: "C"}, 276 {signer: "A"}, 277 {signer: "B", voted: "D", auth: false}, 278 {signer: "C", voted: "D", auth: false}, 279 {signer: "A"}, 280 {signer: "C", voted: "C", auth: true}, 281 }, 282 results: []string{"A", "B"}, 283 }, { 284 //达成共识的变化(通过deauth)可能会在第一次接触时失去共识。 285 signers: []string{"A", "B", "C", "D"}, 286 votes: []testerVote{ 287 {signer: "A", voted: "C", auth: false}, 288 {signer: "B"}, 289 {signer: "C"}, 290 {signer: "A", voted: "D", auth: false}, 291 {signer: "B", voted: "C", auth: false}, 292 {signer: "C"}, 293 {signer: "A"}, 294 {signer: "B", voted: "D", auth: false}, 295 {signer: "C", voted: "D", auth: false}, 296 {signer: "A"}, 297 {signer: "B", voted: "C", auth: true}, 298 }, 299 results: []string{"A", "B", "C"}, 300 }, { 301 //确保挂起的投票不会在授权状态更改后继续有效。这个 302 //只有快速添加、删除签名者,然后 303 //阅读(或相反),而其中一个最初的选民投了。如果A 304 //过去的投票被保存在系统中的某个位置,这将干扰 305 //最终签名者结果。 306 signers: []string{"A", "B", "C", "D", "E"}, 307 votes: []testerVote{ 308 {signer: "A", voted: "F", auth: true}, //授权F,需要3票 309 {signer: "B", voted: "F", auth: true}, 310 {signer: "C", voted: "F", auth: true}, 311 {signer: "D", voted: "F", auth: false}, //取消F的授权,需要4票(保持A以前的投票“不变”)。 312 {signer: "E", voted: "F", auth: false}, 313 {signer: "B", voted: "F", auth: false}, 314 {signer: "C", voted: "F", auth: false}, 315 {signer: "D", voted: "F", auth: true}, //几乎授权F,需要2/3票 316 {signer: "E", voted: "F", auth: true}, 317 {signer: "B", voted: "A", auth: false}, //取消授权A,需要3票 318 {signer: "C", voted: "A", auth: false}, 319 {signer: "D", voted: "A", auth: false}, 320 {signer: "B", voted: "F", auth: true}, //完成授权F,需要3/3票 321 }, 322 results: []string{"B", "C", "D", "E", "F"}, 323 }, { 324 //epoch转换重置所有投票以允许链检查点 325 epoch: 3, 326 signers: []string{"A", "B"}, 327 votes: []testerVote{ 328 {signer: "A", voted: "C", auth: true}, 329 {signer: "B"}, 330 {signer: "A", checkpoint: []string{"A", "B"}}, 331 {signer: "B", voted: "C", auth: true}, 332 }, 333 results: []string{"A", "B"}, 334 }, { 335 // 336 signers: []string{"A"}, 337 votes: []testerVote{ 338 {signer: "B"}, 339 }, 340 failure: errUnauthorizedSigner, 341 }, { 342 //签署了recenty的授权签署者不应再次签署 343 signers: []string{"A", "B"}, 344 votes: []testerVote{ 345 {signer: "A"}, 346 {signer: "A"}, 347 }, 348 failure: errRecentlySigned, 349 }, { 350 // 351 epoch: 3, 352 signers: []string{"A", "B", "C"}, 353 votes: []testerVote{ 354 {signer: "A"}, 355 {signer: "B"}, 356 {signer: "A", checkpoint: []string{"A", "B", "C"}}, 357 {signer: "A"}, 358 }, 359 failure: errRecentlySigned, 360 }, { 361 //最近的签名不应在新的 362 //批处理(https://github.com/ethereum/go-ethereum/issues/17593)。虽然这 363 //似乎过于具体和奇怪,这是一个由双方意见分歧。 364 epoch: 3, 365 signers: []string{"A", "B", "C"}, 366 votes: []testerVote{ 367 {signer: "A"}, 368 {signer: "B"}, 369 {signer: "A", checkpoint: []string{"A", "B", "C"}}, 370 {signer: "A", newbatch: true}, 371 }, 372 failure: errRecentlySigned, 373 }, 374 } 375 //运行场景并测试它们 376 for i, tt := range tests { 377 //创建帐户池并生成初始签名者集 378 accounts := newTesterAccountPool() 379 380 signers := make([]common.Address, len(tt.signers)) 381 for j, signer := range tt.signers { 382 signers[j] = accounts.address(signer) 383 } 384 for j := 0; j < len(signers); j++ { 385 for k := j + 1; k < len(signers); k++ { 386 if bytes.Compare(signers[j][:], signers[k][:]) > 0 { 387 signers[j], signers[k] = signers[k], signers[j] 388 } 389 } 390 } 391 //使用初始签名者集创建Genesis块 392 genesis := &core.Genesis{ 393 ExtraData: make([]byte, extraVanity+common.AddressLength*len(signers)+extraSeal), 394 } 395 for j, signer := range signers { 396 copy(genesis.ExtraData[extraVanity+j*common.AddressLength:], signer[:]) 397 } 398 //创建一个原始的区块链,注入Genesis 399 db := ethdb.NewMemDatabase() 400 genesis.Commit(db) 401 402 // 403 config := *params.TestChainConfig 404 config.Clique = ¶ms.CliqueConfig{ 405 Period: 1, 406 Epoch: tt.epoch, 407 } 408 engine := New(config.Clique, db) 409 engine.fakeDiff = true 410 411 blocks, _ := core.GenerateChain(&config, genesis.ToBlock(db), engine, db, len(tt.votes), func(j int, gen *core.BlockGen) { 412 // 413 gen.SetCoinbase(accounts.address(tt.votes[j].voted)) 414 if tt.votes[j].auth { 415 var nonce types.BlockNonce 416 copy(nonce[:], nonceAuthVote) 417 gen.SetNonce(nonce) 418 } 419 }) 420 //遍历块并分别密封它们 421 for j, block := range blocks { 422 //获取标题并准备签名 423 header := block.Header() 424 if j > 0 { 425 header.ParentHash = blocks[j-1].Hash() 426 } 427 header.Extra = make([]byte, extraVanity+extraSeal) 428 if auths := tt.votes[j].checkpoint; auths != nil { 429 header.Extra = make([]byte, extraVanity+len(auths)*common.AddressLength+extraSeal) 430 accounts.checkpoint(header, auths) 431 } 432 header.Difficulty = diffInTurn //忽略,我们只需要一个有效的数字 433 434 //生成签名,将其嵌入头和块中 435 accounts.sign(header, tt.votes[j].signer) 436 blocks[j] = block.WithSeal(header) 437 } 438 //将块拆分为单独的导入批次(Cornercase测试) 439 batches := [][]*types.Block{nil} 440 for j, block := range blocks { 441 if tt.votes[j].newbatch { 442 batches = append(batches, nil) 443 } 444 batches[len(batches)-1] = append(batches[len(batches)-1], block) 445 } 446 //把所有的头条都传给小集团,确保理货成功。 447 chain, err := core.NewBlockChain(db, nil, &config, engine, vm.Config{}, nil) 448 if err != nil { 449 t.Errorf("test %d: failed to create test chain: %v", i, err) 450 continue 451 } 452 failed := false 453 for j := 0; j < len(batches)-1; j++ { 454 if k, err := chain.InsertChain(batches[j]); err != nil { 455 t.Errorf("test %d: failed to import batch %d, block %d: %v", i, j, k, err) 456 failed = true 457 break 458 } 459 } 460 if failed { 461 continue 462 } 463 if _, err = chain.InsertChain(batches[len(batches)-1]); err != tt.failure { 464 t.Errorf("test %d: failure mismatch: have %v, want %v", i, err, tt.failure) 465 } 466 if tt.failure != nil { 467 continue 468 } 469 //未生成或请求失败,生成最终投票快照 470 head := blocks[len(blocks)-1] 471 472 snap, err := engine.snapshot(chain, head.NumberU64(), head.Hash(), nil) 473 if err != nil { 474 t.Errorf("test %d: failed to retrieve voting snapshot: %v", i, err) 475 continue 476 } 477 //验证签名者的最终列表与预期列表 478 signers = make([]common.Address, len(tt.results)) 479 for j, signer := range tt.results { 480 signers[j] = accounts.address(signer) 481 } 482 for j := 0; j < len(signers); j++ { 483 for k := j + 1; k < len(signers); k++ { 484 if bytes.Compare(signers[j][:], signers[k][:]) > 0 { 485 signers[j], signers[k] = signers[k], signers[j] 486 } 487 } 488 } 489 result := snap.signers() 490 if len(result) != len(signers) { 491 t.Errorf("test %d: signers mismatch: have %x, want %x", i, result, signers) 492 continue 493 } 494 for j := 0; j < len(result); j++ { 495 if !bytes.Equal(result[j][:], signers[j][:]) { 496 t.Errorf("test %d, signer %d: signer mismatch: have %x, want %x", i, j, result[j], signers[j]) 497 } 498 } 499 } 500 } 501