github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/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 12:09:32</date> 10 //</624342610944724992> 11 12 13 package clique 14 15 import ( 16 "bytes" 17 "crypto/ecdsa" 18 "math/big" 19 "testing" 20 21 "github.com/ethereum/go-ethereum/common" 22 "github.com/ethereum/go-ethereum/core" 23 "github.com/ethereum/go-ethereum/core/rawdb" 24 "github.com/ethereum/go-ethereum/core/types" 25 "github.com/ethereum/go-ethereum/crypto" 26 "github.com/ethereum/go-ethereum/ethdb" 27 "github.com/ethereum/go-ethereum/params" 28 ) 29 30 type testerVote struct { 31 signer string 32 voted string 33 auth bool 34 } 35 36 //TestAccountPool是一个用于维护当前活动的测试人员帐户的池, 37 //从下面测试中使用的文本名称映射到实际的以太坊私有 38 //能够签署事务的密钥。 39 type testerAccountPool struct { 40 accounts map[string]*ecdsa.PrivateKey 41 } 42 43 func newTesterAccountPool() *testerAccountPool { 44 return &testerAccountPool{ 45 accounts: make(map[string]*ecdsa.PrivateKey), 46 } 47 } 48 49 func (ap *testerAccountPool) sign(header *types.Header, signer string) { 50 //确保我们有签名者的持久密钥 51 if ap.accounts[signer] == nil { 52 ap.accounts[signer], _ = crypto.GenerateKey() 53 } 54 //在头上签名并将签名嵌入额外的数据中 55 sig, _ := crypto.Sign(sigHash(header).Bytes(), ap.accounts[signer]) 56 copy(header.Extra[len(header.Extra)-65:], sig) 57 } 58 59 func (ap *testerAccountPool) address(account string) common.Address { 60 //确保我们有帐户的持久密钥 61 if ap.accounts[account] == nil { 62 ap.accounts[account], _ = crypto.GenerateKey() 63 } 64 //解析并返回以太坊地址 65 return crypto.PubkeyToAddress(ap.accounts[account].PublicKey) 66 } 67 68 //TestChainReader实现consension.chainReader以访问Genesis 69 //块。所有其他方法和请求都会恐慌。 70 type testerChainReader struct { 71 db ethdb.Database 72 } 73 74 func (r *testerChainReader) Config() *params.ChainConfig { return params.AllCliqueProtocolChanges } 75 func (r *testerChainReader) CurrentHeader() *types.Header { panic("not supported") } 76 func (r *testerChainReader) GetHeader(common.Hash, uint64) *types.Header { panic("not supported") } 77 func (r *testerChainReader) GetBlock(common.Hash, uint64) *types.Block { panic("not supported") } 78 func (r *testerChainReader) GetHeaderByHash(common.Hash) *types.Header { panic("not supported") } 79 func (r *testerChainReader) GetHeaderByNumber(number uint64) *types.Header { 80 if number == 0 { 81 return rawdb.ReadHeader(r.db, rawdb.ReadCanonicalHash(r.db, 0), 0) 82 } 83 return nil 84 } 85 86 //测试在各种简单和复杂的情况下是否正确评估投票。 87 func TestVoting(t *testing.T) { 88 // 89 tests := []struct { 90 epoch uint64 91 signers []string 92 votes []testerVote 93 results []string 94 }{ 95 { 96 //单签名人,无投票权 97 signers: []string{"A"}, 98 votes: []testerVote{{signer: "A"}}, 99 results: []string{"A"}, 100 }, { 101 //单个签名人,投票添加两个其他人(只接受第一个,第二个需要2票) 102 signers: []string{"A"}, 103 votes: []testerVote{ 104 {signer: "A", voted: "B", auth: true}, 105 {signer: "B"}, 106 {signer: "A", voted: "C", auth: true}, 107 }, 108 results: []string{"A", "B"}, 109 }, { 110 //两个签名者,投票加三个(只接受前两个,第三个已经需要3票) 111 signers: []string{"A", "B"}, 112 votes: []testerVote{ 113 {signer: "A", voted: "C", auth: true}, 114 {signer: "B", voted: "C", auth: true}, 115 {signer: "A", voted: "D", auth: true}, 116 {signer: "B", voted: "D", auth: true}, 117 {signer: "C"}, 118 {signer: "A", voted: "E", auth: true}, 119 {signer: "B", voted: "E", auth: true}, 120 }, 121 results: []string{"A", "B", "C", "D"}, 122 }, { 123 //单个签名者,放弃自己(很奇怪,但明确允许这样做的话就少了一个死角) 124 signers: []string{"A"}, 125 votes: []testerVote{ 126 {signer: "A", voted: "A", auth: false}, 127 }, 128 results: []string{}, 129 }, { 130 // 131 signers: []string{"A", "B"}, 132 votes: []testerVote{ 133 {signer: "A", voted: "B", auth: false}, 134 }, 135 results: []string{"A", "B"}, 136 }, { 137 //两个签名者,实际上需要双方同意放弃其中一个(满足) 138 signers: []string{"A", "B"}, 139 votes: []testerVote{ 140 {signer: "A", voted: "B", auth: false}, 141 {signer: "B", voted: "B", auth: false}, 142 }, 143 results: []string{"A"}, 144 }, { 145 //三个签名者,其中两个决定放弃第三个 146 signers: []string{"A", "B", "C"}, 147 votes: []testerVote{ 148 {signer: "A", voted: "C", auth: false}, 149 {signer: "B", voted: "C", auth: false}, 150 }, 151 results: []string{"A", "B"}, 152 }, { 153 //四个签名者,两个的共识不足以让任何人放弃 154 signers: []string{"A", "B", "C", "D"}, 155 votes: []testerVote{ 156 {signer: "A", voted: "C", auth: false}, 157 {signer: "B", voted: "C", auth: false}, 158 }, 159 results: []string{"A", "B", "C", "D"}, 160 }, { 161 //四个签名者,三个人的共识已经足够让某人离开 162 signers: []string{"A", "B", "C", "D"}, 163 votes: []testerVote{ 164 {signer: "A", voted: "D", auth: false}, 165 {signer: "B", voted: "D", auth: false}, 166 {signer: "C", voted: "D", auth: false}, 167 }, 168 results: []string{"A", "B", "C"}, 169 }, { 170 //每个签名者对每个目标的授权计数一次 171 signers: []string{"A", "B"}, 172 votes: []testerVote{ 173 {signer: "A", voted: "C", auth: true}, 174 {signer: "B"}, 175 {signer: "A", voted: "C", auth: true}, 176 {signer: "B"}, 177 {signer: "A", voted: "C", auth: true}, 178 }, 179 results: []string{"A", "B"}, 180 }, { 181 //允许同时授权多个帐户 182 signers: []string{"A", "B"}, 183 votes: []testerVote{ 184 {signer: "A", voted: "C", auth: true}, 185 {signer: "B"}, 186 {signer: "A", voted: "D", auth: true}, 187 {signer: "B"}, 188 {signer: "A"}, 189 {signer: "B", voted: "D", auth: true}, 190 {signer: "A"}, 191 {signer: "B", voted: "C", auth: true}, 192 }, 193 results: []string{"A", "B", "C", "D"}, 194 }, { 195 //每个目标的每个签名者对取消授权计数一次 196 signers: []string{"A", "B"}, 197 votes: []testerVote{ 198 {signer: "A", voted: "B", auth: false}, 199 {signer: "B"}, 200 {signer: "A", voted: "B", auth: false}, 201 {signer: "B"}, 202 {signer: "A", voted: "B", auth: false}, 203 }, 204 results: []string{"A", "B"}, 205 }, { 206 //允许同时解除多个帐户的授权 207 signers: []string{"A", "B", "C", "D"}, 208 votes: []testerVote{ 209 {signer: "A", voted: "C", auth: false}, 210 {signer: "B"}, 211 {signer: "C"}, 212 {signer: "A", voted: "D", auth: false}, 213 {signer: "B"}, 214 {signer: "C"}, 215 {signer: "A"}, 216 {signer: "B", voted: "D", auth: false}, 217 {signer: "C", voted: "D", auth: false}, 218 {signer: "A"}, 219 {signer: "B", voted: "C", auth: false}, 220 }, 221 results: []string{"A", "B"}, 222 }, { 223 //取消授权签名者的投票将立即被丢弃(取消授权投票) 224 signers: []string{"A", "B", "C"}, 225 votes: []testerVote{ 226 {signer: "C", voted: "B", auth: false}, 227 {signer: "A", voted: "C", auth: false}, 228 {signer: "B", voted: "C", auth: false}, 229 {signer: "A", voted: "B", auth: false}, 230 }, 231 results: []string{"A", "B"}, 232 }, { 233 //来自未授权签名者的投票将立即丢弃(授权投票) 234 signers: []string{"A", "B", "C"}, 235 votes: []testerVote{ 236 {signer: "C", voted: "B", auth: false}, 237 {signer: "A", voted: "C", auth: false}, 238 {signer: "B", voted: "C", auth: false}, 239 {signer: "A", voted: "B", auth: false}, 240 }, 241 results: []string{"A", "B"}, 242 }, { 243 //不允许级联更改,只有被投票的帐户才可以更改 244 signers: []string{"A", "B", "C", "D"}, 245 votes: []testerVote{ 246 {signer: "A", voted: "C", auth: false}, 247 {signer: "B"}, 248 {signer: "C"}, 249 {signer: "A", voted: "D", auth: false}, 250 {signer: "B", voted: "C", auth: false}, 251 {signer: "C"}, 252 {signer: "A"}, 253 {signer: "B", voted: "D", auth: false}, 254 {signer: "C", voted: "D", auth: false}, 255 }, 256 results: []string{"A", "B", "C"}, 257 }, { 258 //达成共识的变化超出范围(通过deauth)触摸执行 259 signers: []string{"A", "B", "C", "D"}, 260 votes: []testerVote{ 261 {signer: "A", voted: "C", auth: false}, 262 {signer: "B"}, 263 {signer: "C"}, 264 {signer: "A", voted: "D", auth: false}, 265 {signer: "B", voted: "C", auth: false}, 266 {signer: "C"}, 267 {signer: "A"}, 268 {signer: "B", voted: "D", auth: false}, 269 {signer: "C", voted: "D", auth: false}, 270 {signer: "A"}, 271 {signer: "C", voted: "C", auth: true}, 272 }, 273 results: []string{"A", "B"}, 274 }, { 275 //达成共识的变化(通过deauth)可能会在第一次接触时失去共识。 276 signers: []string{"A", "B", "C", "D"}, 277 votes: []testerVote{ 278 {signer: "A", voted: "C", auth: false}, 279 {signer: "B"}, 280 {signer: "C"}, 281 {signer: "A", voted: "D", auth: false}, 282 {signer: "B", voted: "C", auth: false}, 283 {signer: "C"}, 284 {signer: "A"}, 285 {signer: "B", voted: "D", auth: false}, 286 {signer: "C", voted: "D", auth: false}, 287 {signer: "A"}, 288 {signer: "B", voted: "C", auth: true}, 289 }, 290 results: []string{"A", "B", "C"}, 291 }, { 292 //确保挂起的投票不会在授权状态更改后继续有效。这个 293 //只有快速添加、删除签名者,然后 294 //阅读(或相反),而其中一个最初的选民投了。如果A 295 //过去的投票被保存在系统中的某个位置,这将干扰 296 //最终签名者结果。 297 signers: []string{"A", "B", "C", "D", "E"}, 298 votes: []testerVote{ 299 {signer: "A", voted: "F", auth: true}, //授权F,需要3票 300 {signer: "B", voted: "F", auth: true}, 301 {signer: "C", voted: "F", auth: true}, 302 {signer: "D", voted: "F", auth: false}, //取消F的授权,需要4票(保持A以前的投票“不变”)。 303 {signer: "E", voted: "F", auth: false}, 304 {signer: "B", voted: "F", auth: false}, 305 {signer: "C", voted: "F", auth: false}, 306 {signer: "D", voted: "F", auth: true}, //几乎授权F,需要2/3票 307 {signer: "E", voted: "F", auth: true}, 308 {signer: "B", voted: "A", auth: false}, //取消授权A,需要3票 309 {signer: "C", voted: "A", auth: false}, 310 {signer: "D", voted: "A", auth: false}, 311 {signer: "B", voted: "F", auth: true}, //完成授权F,需要3/3票 312 }, 313 results: []string{"B", "C", "D", "E", "F"}, 314 }, { 315 //epoch转换重置所有投票以允许链检查点 316 epoch: 3, 317 signers: []string{"A", "B"}, 318 votes: []testerVote{ 319 {signer: "A", voted: "C", auth: true}, 320 {signer: "B"}, 321 {signer: "A"}, //检查点块(不要在这里投票,它是在快照之外验证的) 322 {signer: "B", voted: "C", auth: true}, 323 }, 324 results: []string{"A", "B"}, 325 }, 326 } 327 //运行场景并测试它们 328 for i, tt := range tests { 329 //创建帐户池并生成初始签名者集 330 accounts := newTesterAccountPool() 331 332 signers := make([]common.Address, len(tt.signers)) 333 for j, signer := range tt.signers { 334 signers[j] = accounts.address(signer) 335 } 336 for j := 0; j < len(signers); j++ { 337 for k := j + 1; k < len(signers); k++ { 338 if bytes.Compare(signers[j][:], signers[k][:]) > 0 { 339 signers[j], signers[k] = signers[k], signers[j] 340 } 341 } 342 } 343 //使用初始签名者集创建Genesis块 344 genesis := &core.Genesis{ 345 ExtraData: make([]byte, extraVanity+common.AddressLength*len(signers)+extraSeal), 346 } 347 for j, signer := range signers { 348 copy(genesis.ExtraData[extraVanity+j*common.AddressLength:], signer[:]) 349 } 350 //创建一个原始的区块链,注入Genesis 351 db := ethdb.NewMemDatabase() 352 genesis.Commit(db) 353 354 // 355 headers := make([]*types.Header, len(tt.votes)) 356 for j, vote := range tt.votes { 357 headers[j] = &types.Header{ 358 Number: big.NewInt(int64(j) + 1), 359 Time: big.NewInt(int64(j) * 15), 360 Coinbase: accounts.address(vote.voted), 361 Extra: make([]byte, extraVanity+extraSeal), 362 } 363 if j > 0 { 364 headers[j].ParentHash = headers[j-1].Hash() 365 } 366 if vote.auth { 367 copy(headers[j].Nonce[:], nonceAuthVote) 368 } 369 accounts.sign(headers[j], vote.signer) 370 } 371 //把所有的头条都传给小集团,确保理货成功。 372 head := headers[len(headers)-1] 373 374 snap, err := New(¶ms.CliqueConfig{Epoch: tt.epoch}, db).snapshot(&testerChainReader{db: db}, head.Number.Uint64(), head.Hash(), headers) 375 if err != nil { 376 t.Errorf("test %d: failed to create voting snapshot: %v", i, err) 377 continue 378 } 379 //验证签名者的最终列表与预期列表 380 signers = make([]common.Address, len(tt.results)) 381 for j, signer := range tt.results { 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 result := snap.signers() 392 if len(result) != len(signers) { 393 t.Errorf("test %d: signers mismatch: have %x, want %x", i, result, signers) 394 continue 395 } 396 for j := 0; j < len(result); j++ { 397 if !bytes.Equal(result[j][:], signers[j][:]) { 398 t.Errorf("test %d, signer %d: signer mismatch: have %x, want %x", i, j, result[j], signers[j]) 399 } 400 } 401 } 402 } 403