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(&params.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