github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/eth/handler_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:38</date>
    10  //</624342636093771776>
    11  
    12  
    13  package eth
    14  
    15  import (
    16  	"math"
    17  	"math/big"
    18  	"math/rand"
    19  	"testing"
    20  	"time"
    21  
    22  	"github.com/ethereum/go-ethereum/common"
    23  	"github.com/ethereum/go-ethereum/consensus/ethash"
    24  	"github.com/ethereum/go-ethereum/core"
    25  	"github.com/ethereum/go-ethereum/core/state"
    26  	"github.com/ethereum/go-ethereum/core/types"
    27  	"github.com/ethereum/go-ethereum/core/vm"
    28  	"github.com/ethereum/go-ethereum/crypto"
    29  	"github.com/ethereum/go-ethereum/eth/downloader"
    30  	"github.com/ethereum/go-ethereum/ethdb"
    31  	"github.com/ethereum/go-ethereum/event"
    32  	"github.com/ethereum/go-ethereum/p2p"
    33  	"github.com/ethereum/go-ethereum/params"
    34  )
    35  
    36  //测试协议版本和操作模式是否正确匹配。
    37  func TestProtocolCompatibility(t *testing.T) {
    38  //定义兼容性图表
    39  	tests := []struct {
    40  		version    uint
    41  		mode       downloader.SyncMode
    42  		compatible bool
    43  	}{
    44  		{61, downloader.FullSync, true}, {62, downloader.FullSync, true}, {63, downloader.FullSync, true},
    45  		{61, downloader.FastSync, false}, {62, downloader.FastSync, false}, {63, downloader.FastSync, true},
    46  	}
    47  //确保我们搞砸的东西都恢复了
    48  	backup := ProtocolVersions
    49  	defer func() { ProtocolVersions = backup }()
    50  
    51  //尝试所有可用的兼容性配置并检查错误
    52  	for i, tt := range tests {
    53  		ProtocolVersions = []uint{tt.version}
    54  
    55  		pm, _, err := newTestProtocolManager(tt.mode, 0, nil, nil)
    56  		if pm != nil {
    57  			defer pm.Stop()
    58  		}
    59  		if (err == nil && !tt.compatible) || (err != nil && tt.compatible) {
    60  			t.Errorf("test %d: compatibility mismatch: have error %v, want compatibility %v", i, err, tt.compatible)
    61  		}
    62  	}
    63  }
    64  
    65  //可以根据用户查询从远程链中检索阻止头的测试。
    66  func TestGetBlockHeaders62(t *testing.T) { testGetBlockHeaders(t, 62) }
    67  func TestGetBlockHeaders63(t *testing.T) { testGetBlockHeaders(t, 63) }
    68  
    69  func testGetBlockHeaders(t *testing.T, protocol int) {
    70  	pm, _ := newTestProtocolManagerMust(t, downloader.FullSync, downloader.MaxHashFetch+15, nil, nil)
    71  	peer, _ := newTestPeer("peer", protocol, pm, true)
    72  	defer peer.close()
    73  
    74  //为测试创建一个“随机”的未知哈希
    75  	var unknown common.Hash
    76  	for i := range unknown {
    77  		unknown[i] = byte(i)
    78  	}
    79  //为各种方案创建一批测试
    80  	limit := uint64(downloader.MaxHeaderFetch)
    81  	tests := []struct {
    82  query  *getBlockHeadersData //要为头检索执行的查询
    83  expect []common.Hash        //应为其头的块的哈希
    84  	}{
    85  //单个随机块也应该可以通过哈希和数字检索。
    86  		{
    87  			&getBlockHeadersData{Origin: hashOrNumber{Hash: pm.blockchain.GetBlockByNumber(limit / 2).Hash()}, Amount: 1},
    88  			[]common.Hash{pm.blockchain.GetBlockByNumber(limit / 2).Hash()},
    89  		}, {
    90  			&getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Amount: 1},
    91  			[]common.Hash{pm.blockchain.GetBlockByNumber(limit / 2).Hash()},
    92  		},
    93  //应可从两个方向检索多个邮件头
    94  		{
    95  			&getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Amount: 3},
    96  			[]common.Hash{
    97  				pm.blockchain.GetBlockByNumber(limit / 2).Hash(),
    98  				pm.blockchain.GetBlockByNumber(limit/2 + 1).Hash(),
    99  				pm.blockchain.GetBlockByNumber(limit/2 + 2).Hash(),
   100  			},
   101  		}, {
   102  			&getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Amount: 3, Reverse: true},
   103  			[]common.Hash{
   104  				pm.blockchain.GetBlockByNumber(limit / 2).Hash(),
   105  				pm.blockchain.GetBlockByNumber(limit/2 - 1).Hash(),
   106  				pm.blockchain.GetBlockByNumber(limit/2 - 2).Hash(),
   107  			},
   108  		},
   109  //应检索具有跳过列表的多个邮件头
   110  		{
   111  			&getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Skip: 3, Amount: 3},
   112  			[]common.Hash{
   113  				pm.blockchain.GetBlockByNumber(limit / 2).Hash(),
   114  				pm.blockchain.GetBlockByNumber(limit/2 + 4).Hash(),
   115  				pm.blockchain.GetBlockByNumber(limit/2 + 8).Hash(),
   116  			},
   117  		}, {
   118  			&getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Skip: 3, Amount: 3, Reverse: true},
   119  			[]common.Hash{
   120  				pm.blockchain.GetBlockByNumber(limit / 2).Hash(),
   121  				pm.blockchain.GetBlockByNumber(limit/2 - 4).Hash(),
   122  				pm.blockchain.GetBlockByNumber(limit/2 - 8).Hash(),
   123  			},
   124  		},
   125  //链端点应该是可检索的
   126  		{
   127  			&getBlockHeadersData{Origin: hashOrNumber{Number: 0}, Amount: 1},
   128  			[]common.Hash{pm.blockchain.GetBlockByNumber(0).Hash()},
   129  		}, {
   130  			&getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().NumberU64()}, Amount: 1},
   131  			[]common.Hash{pm.blockchain.CurrentBlock().Hash()},
   132  		},
   133  //确保遵守协议限制
   134  		{
   135  			&getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().NumberU64() - 1}, Amount: limit + 10, Reverse: true},
   136  			pm.blockchain.GetBlockHashesFromHash(pm.blockchain.CurrentBlock().Hash(), limit),
   137  		},
   138  //检查请求是否处理得当
   139  		{
   140  			&getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().NumberU64() - 4}, Skip: 3, Amount: 3},
   141  			[]common.Hash{
   142  				pm.blockchain.GetBlockByNumber(pm.blockchain.CurrentBlock().NumberU64() - 4).Hash(),
   143  				pm.blockchain.GetBlockByNumber(pm.blockchain.CurrentBlock().NumberU64()).Hash(),
   144  			},
   145  		}, {
   146  			&getBlockHeadersData{Origin: hashOrNumber{Number: 4}, Skip: 3, Amount: 3, Reverse: true},
   147  			[]common.Hash{
   148  				pm.blockchain.GetBlockByNumber(4).Hash(),
   149  				pm.blockchain.GetBlockByNumber(0).Hash(),
   150  			},
   151  		},
   152  //检查请求是否处理得当,即使中间跳过
   153  		{
   154  			&getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().NumberU64() - 4}, Skip: 2, Amount: 3},
   155  			[]common.Hash{
   156  				pm.blockchain.GetBlockByNumber(pm.blockchain.CurrentBlock().NumberU64() - 4).Hash(),
   157  				pm.blockchain.GetBlockByNumber(pm.blockchain.CurrentBlock().NumberU64() - 1).Hash(),
   158  			},
   159  		}, {
   160  			&getBlockHeadersData{Origin: hashOrNumber{Number: 4}, Skip: 2, Amount: 3, Reverse: true},
   161  			[]common.Hash{
   162  				pm.blockchain.GetBlockByNumber(4).Hash(),
   163  				pm.blockchain.GetBlockByNumber(1).Hash(),
   164  			},
   165  		},
   166  //检查一个角情况,在这种情况下,请求更多可以迭代通过端点
   167  		{
   168  			&getBlockHeadersData{Origin: hashOrNumber{Number: 2}, Amount: 5, Reverse: true},
   169  			[]common.Hash{
   170  				pm.blockchain.GetBlockByNumber(2).Hash(),
   171  				pm.blockchain.GetBlockByNumber(1).Hash(),
   172  				pm.blockchain.GetBlockByNumber(0).Hash(),
   173  			},
   174  		},
   175  //检查将溢出循环跳回到链起始处的角情况
   176  		{
   177  			&getBlockHeadersData{Origin: hashOrNumber{Hash: pm.blockchain.GetBlockByNumber(3).Hash()}, Amount: 2, Reverse: false, Skip: math.MaxUint64 - 1},
   178  			[]common.Hash{
   179  				pm.blockchain.GetBlockByNumber(3).Hash(),
   180  			},
   181  		},
   182  //检查跳过溢出循环返回同一头的角情况
   183  		{
   184  			&getBlockHeadersData{Origin: hashOrNumber{Hash: pm.blockchain.GetBlockByNumber(1).Hash()}, Amount: 2, Reverse: false, Skip: math.MaxUint64},
   185  			[]common.Hash{
   186  				pm.blockchain.GetBlockByNumber(1).Hash(),
   187  			},
   188  		},
   189  //检查是否未返回不存在的邮件头
   190  		{
   191  			&getBlockHeadersData{Origin: hashOrNumber{Hash: unknown}, Amount: 1},
   192  			[]common.Hash{},
   193  		}, {
   194  			&getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().NumberU64() + 1}, Amount: 1},
   195  			[]common.Hash{},
   196  		},
   197  	}
   198  //运行每个测试并对照链验证结果
   199  	for i, tt := range tests {
   200  //收集响应中预期的头
   201  		headers := []*types.Header{}
   202  		for _, hash := range tt.expect {
   203  			headers = append(headers, pm.blockchain.GetBlockByHash(hash).Header())
   204  		}
   205  //发送哈希请求并验证响应
   206  		p2p.Send(peer.app, 0x03, tt.query)
   207  		if err := p2p.ExpectMsg(peer.app, 0x04, headers); err != nil {
   208  			t.Errorf("test %d: headers mismatch: %v", i, err)
   209  		}
   210  //如果测试使用的是数字源,也可以使用哈希进行重复。
   211  		if tt.query.Origin.Hash == (common.Hash{}) {
   212  			if origin := pm.blockchain.GetBlockByNumber(tt.query.Origin.Number); origin != nil {
   213  				tt.query.Origin.Hash, tt.query.Origin.Number = origin.Hash(), 0
   214  
   215  				p2p.Send(peer.app, 0x03, tt.query)
   216  				if err := p2p.ExpectMsg(peer.app, 0x04, headers); err != nil {
   217  					t.Errorf("test %d: headers mismatch: %v", i, err)
   218  				}
   219  			}
   220  		}
   221  	}
   222  }
   223  
   224  //可以基于哈希从远程链中检索阻止内容的测试。
   225  func TestGetBlockBodies62(t *testing.T) { testGetBlockBodies(t, 62) }
   226  func TestGetBlockBodies63(t *testing.T) { testGetBlockBodies(t, 63) }
   227  
   228  func testGetBlockBodies(t *testing.T, protocol int) {
   229  	pm, _ := newTestProtocolManagerMust(t, downloader.FullSync, downloader.MaxBlockFetch+15, nil, nil)
   230  	peer, _ := newTestPeer("peer", protocol, pm, true)
   231  	defer peer.close()
   232  
   233  //为各种方案创建一批测试
   234  	limit := downloader.MaxBlockFetch
   235  	tests := []struct {
   236  random    int           //从链中随机提取的块数
   237  explicit  []common.Hash //显式请求的块
   238  available []bool        //显式请求块的可用性
   239  expected  int           //期望的现有块总数
   240  	}{
   241  {1, nil, nil, 1},                                                         //单个随机块应该是可检索的
   242  {10, nil, nil, 10},                                                       //应可检索多个随机块
   243  {limit, nil, nil, limit},                                                 //最大可能的块应该是可检索的
   244  {limit + 1, nil, nil, limit},                                             //不应返回超过可能的块计数
   245  {0, []common.Hash{pm.blockchain.Genesis().Hash()}, []bool{true}, 1},      //Genesis区块应该是可回收的。
   246  {0, []common.Hash{pm.blockchain.CurrentBlock().Hash()}, []bool{true}, 1}, //链头滑轮应可回收。
   247  {0, []common.Hash{{}}, []bool{false}, 0},                                 //不应返回不存在的块
   248  
   249  //现有和不存在的块交错不应导致问题
   250  		{0, []common.Hash{
   251  			{},
   252  			pm.blockchain.GetBlockByNumber(1).Hash(),
   253  			{},
   254  			pm.blockchain.GetBlockByNumber(10).Hash(),
   255  			{},
   256  			pm.blockchain.GetBlockByNumber(100).Hash(),
   257  			{},
   258  		}, []bool{false, true, false, true, false, true, false}, 3},
   259  	}
   260  //运行每个测试并对照链验证结果
   261  	for i, tt := range tests {
   262  //收集要请求的哈希值和预期的响应
   263  		hashes, seen := []common.Hash{}, make(map[int64]bool)
   264  		bodies := []*blockBody{}
   265  
   266  		for j := 0; j < tt.random; j++ {
   267  			for {
   268  				num := rand.Int63n(int64(pm.blockchain.CurrentBlock().NumberU64()))
   269  				if !seen[num] {
   270  					seen[num] = true
   271  
   272  					block := pm.blockchain.GetBlockByNumber(uint64(num))
   273  					hashes = append(hashes, block.Hash())
   274  					if len(bodies) < tt.expected {
   275  						bodies = append(bodies, &blockBody{Transactions: block.Transactions(), Uncles: block.Uncles()})
   276  					}
   277  					break
   278  				}
   279  			}
   280  		}
   281  		for j, hash := range tt.explicit {
   282  			hashes = append(hashes, hash)
   283  			if tt.available[j] && len(bodies) < tt.expected {
   284  				block := pm.blockchain.GetBlockByHash(hash)
   285  				bodies = append(bodies, &blockBody{Transactions: block.Transactions(), Uncles: block.Uncles()})
   286  			}
   287  		}
   288  //发送哈希请求并验证响应
   289  		p2p.Send(peer.app, 0x05, hashes)
   290  		if err := p2p.ExpectMsg(peer.app, 0x06, bodies); err != nil {
   291  			t.Errorf("test %d: bodies mismatch: %v", i, err)
   292  		}
   293  	}
   294  }
   295  
   296  //测试可以基于哈希检索节点状态数据库。
   297  func TestGetNodeData63(t *testing.T) { testGetNodeData(t, 63) }
   298  
   299  func testGetNodeData(t *testing.T, protocol int) {
   300  //定义三个科目以模拟交易
   301  	acc1Key, _ := crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
   302  	acc2Key, _ := crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
   303  	acc1Addr := crypto.PubkeyToAddress(acc1Key.PublicKey)
   304  	acc2Addr := crypto.PubkeyToAddress(acc2Key.PublicKey)
   305  
   306  	signer := types.HomesteadSigner{}
   307  //用一些简单的事务创建一个链生成器(公然从@fjl/chain_markets_test中被盗)
   308  	generator := func(i int, block *core.BlockGen) {
   309  		switch i {
   310  		case 0:
   311  //在块1中,测试银行发送帐户1一些乙醚。
   312  			tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil), signer, testBankKey)
   313  			block.AddTx(tx)
   314  		case 1:
   315  //在区块2中,测试银行向账户1发送更多乙醚。
   316  //acc1addr将其传递到account_2。
   317  			tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, testBankKey)
   318  			tx2, _ := types.SignTx(types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, acc1Key)
   319  			block.AddTx(tx1)
   320  			block.AddTx(tx2)
   321  		case 2:
   322  //区块3为空,但由账户2开采。
   323  			block.SetCoinbase(acc2Addr)
   324  			block.SetExtra([]byte("yeehaw"))
   325  		case 3:
   326  //块4包括块2和3作为叔叔头(带有修改的额外数据)。
   327  			b2 := block.PrevBlock(1).Header()
   328  			b2.Extra = []byte("foo")
   329  			block.AddUncle(b2)
   330  			b3 := block.PrevBlock(2).Header()
   331  			b3.Extra = []byte("foo")
   332  			block.AddUncle(b3)
   333  		}
   334  	}
   335  //组装测试环境
   336  	pm, db := newTestProtocolManagerMust(t, downloader.FullSync, 4, generator, nil)
   337  	peer, _ := newTestPeer("peer", protocol, pm, true)
   338  	defer peer.close()
   339  
   340  //现在获取整个链数据库
   341  	hashes := []common.Hash{}
   342  	for _, key := range db.Keys() {
   343  		if len(key) == len(common.Hash{}) {
   344  			hashes = append(hashes, common.BytesToHash(key))
   345  		}
   346  	}
   347  	p2p.Send(peer.app, 0x0d, hashes)
   348  	msg, err := peer.app.ReadMsg()
   349  	if err != nil {
   350  		t.Fatalf("failed to read node data response: %v", err)
   351  	}
   352  	if msg.Code != 0x0e {
   353  		t.Fatalf("response packet code mismatch: have %x, want %x", msg.Code, 0x0c)
   354  	}
   355  	var data [][]byte
   356  	if err := msg.Decode(&data); err != nil {
   357  		t.Fatalf("failed to decode response node data: %v", err)
   358  	}
   359  //验证所有哈希是否与请求的数据对应,并重建状态树
   360  	for i, want := range hashes {
   361  		if hash := crypto.Keccak256Hash(data[i]); hash != want {
   362  			t.Errorf("data hash mismatch: have %x, want %x", hash, want)
   363  		}
   364  	}
   365  	statedb := ethdb.NewMemDatabase()
   366  	for i := 0; i < len(data); i++ {
   367  		statedb.Put(hashes[i].Bytes(), data[i])
   368  	}
   369  	accounts := []common.Address{testBank, acc1Addr, acc2Addr}
   370  	for i := uint64(0); i <= pm.blockchain.CurrentBlock().NumberU64(); i++ {
   371  		trie, _ := state.New(pm.blockchain.GetBlockByNumber(i).Root(), state.NewDatabase(statedb))
   372  
   373  		for j, acc := range accounts {
   374  			state, _ := pm.blockchain.State()
   375  			bw := state.GetBalance(acc)
   376  			bh := trie.GetBalance(acc)
   377  
   378  			if (bw != nil && bh == nil) || (bw == nil && bh != nil) {
   379  				t.Errorf("test %d, account %d: balance mismatch: have %v, want %v", i, j, bh, bw)
   380  			}
   381  			if bw != nil && bh != nil && bw.Cmp(bw) != 0 {
   382  				t.Errorf("test %d, account %d: balance mismatch: have %v, want %v", i, j, bh, bw)
   383  			}
   384  		}
   385  	}
   386  }
   387  
   388  //测试是否可以基于哈希值检索事务回执。
   389  func TestGetReceipt63(t *testing.T) { testGetReceipt(t, 63) }
   390  
   391  func testGetReceipt(t *testing.T, protocol int) {
   392  //定义三个科目以模拟交易
   393  	acc1Key, _ := crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
   394  	acc2Key, _ := crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
   395  	acc1Addr := crypto.PubkeyToAddress(acc1Key.PublicKey)
   396  	acc2Addr := crypto.PubkeyToAddress(acc2Key.PublicKey)
   397  
   398  	signer := types.HomesteadSigner{}
   399  //用一些简单的事务创建一个链生成器(公然从@fjl/chain_markets_test中被盗)
   400  	generator := func(i int, block *core.BlockGen) {
   401  		switch i {
   402  		case 0:
   403  //在块1中,测试银行发送帐户1一些乙醚。
   404  			tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil), signer, testBankKey)
   405  			block.AddTx(tx)
   406  		case 1:
   407  //在区块2中,测试银行向账户1发送更多乙醚。
   408  //acc1addr将其传递到account_2。
   409  			tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, testBankKey)
   410  			tx2, _ := types.SignTx(types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, acc1Key)
   411  			block.AddTx(tx1)
   412  			block.AddTx(tx2)
   413  		case 2:
   414  //区块3为空,但由账户2开采。
   415  			block.SetCoinbase(acc2Addr)
   416  			block.SetExtra([]byte("yeehaw"))
   417  		case 3:
   418  //块4包括块2和3作为叔叔头(带有修改的额外数据)。
   419  			b2 := block.PrevBlock(1).Header()
   420  			b2.Extra = []byte("foo")
   421  			block.AddUncle(b2)
   422  			b3 := block.PrevBlock(2).Header()
   423  			b3.Extra = []byte("foo")
   424  			block.AddUncle(b3)
   425  		}
   426  	}
   427  //组装测试环境
   428  	pm, _ := newTestProtocolManagerMust(t, downloader.FullSync, 4, generator, nil)
   429  	peer, _ := newTestPeer("peer", protocol, pm, true)
   430  	defer peer.close()
   431  
   432  //收集要请求的哈希值和预期的响应
   433  	hashes, receipts := []common.Hash{}, []types.Receipts{}
   434  	for i := uint64(0); i <= pm.blockchain.CurrentBlock().NumberU64(); i++ {
   435  		block := pm.blockchain.GetBlockByNumber(i)
   436  
   437  		hashes = append(hashes, block.Hash())
   438  		receipts = append(receipts, pm.blockchain.GetReceiptsByHash(block.Hash()))
   439  	}
   440  //发送哈希请求并验证响应
   441  	p2p.Send(peer.app, 0x0f, hashes)
   442  	if err := p2p.ExpectMsg(peer.app, 0x10, receipts); err != nil {
   443  		t.Errorf("receipts mismatch: %v", err)
   444  	}
   445  }
   446  
   447  //发布ETH协议握手的测试,启用DAO分叉的客户端也会执行
   448  //一个DAO“挑战”验证彼此的DAO分叉头,以确保它们处于打开状态
   449  //兼容的链条。
   450  func TestDAOChallengeNoVsNo(t *testing.T)       { testDAOChallenge(t, false, false, false) }
   451  func TestDAOChallengeNoVsPro(t *testing.T)      { testDAOChallenge(t, false, true, false) }
   452  func TestDAOChallengeProVsNo(t *testing.T)      { testDAOChallenge(t, true, false, false) }
   453  func TestDAOChallengeProVsPro(t *testing.T)     { testDAOChallenge(t, true, true, false) }
   454  func TestDAOChallengeNoVsTimeout(t *testing.T)  { testDAOChallenge(t, false, false, true) }
   455  func TestDAOChallengeProVsTimeout(t *testing.T) { testDAOChallenge(t, true, true, true) }
   456  
   457  func testDAOChallenge(t *testing.T, localForked, remoteForked bool, timeout bool) {
   458  //减少DAO握手挑战超时
   459  	if timeout {
   460  		defer func(old time.Duration) { daoChallengeTimeout = old }(daoChallengeTimeout)
   461  		daoChallengeTimeout = 500 * time.Millisecond
   462  	}
   463  //创建DAO感知协议管理器
   464  	var (
   465  		evmux         = new(event.TypeMux)
   466  		pow           = ethash.NewFaker()
   467  		db            = ethdb.NewMemDatabase()
   468  		config        = &params.ChainConfig{DAOForkBlock: big.NewInt(1), DAOForkSupport: localForked}
   469  		gspec         = &core.Genesis{Config: config}
   470  		genesis       = gspec.MustCommit(db)
   471  		blockchain, _ = core.NewBlockChain(db, nil, config, pow, vm.Config{})
   472  	)
   473  	pm, err := NewProtocolManager(config, downloader.FullSync, DefaultConfig.NetworkId, evmux, new(testTxPool), pow, blockchain, db)
   474  	if err != nil {
   475  		t.Fatalf("failed to start test protocol manager: %v", err)
   476  	}
   477  	pm.Start(1000)
   478  	defer pm.Stop()
   479  
   480  //连接新的对等点并检查我们是否收到DAO挑战
   481  	peer, _ := newTestPeer("peer", eth63, pm, true)
   482  	defer peer.close()
   483  
   484  	challenge := &getBlockHeadersData{
   485  		Origin:  hashOrNumber{Number: config.DAOForkBlock.Uint64()},
   486  		Amount:  1,
   487  		Skip:    0,
   488  		Reverse: false,
   489  	}
   490  	if err := p2p.ExpectMsg(peer.app, GetBlockHeadersMsg, challenge); err != nil {
   491  		t.Fatalf("challenge mismatch: %v", err)
   492  	}
   493  //如果没有模拟超时,则创建一个块以答复质询
   494  	if !timeout {
   495  		blocks, _ := core.GenerateChain(&params.ChainConfig{}, genesis, ethash.NewFaker(), db, 1, func(i int, block *core.BlockGen) {
   496  			if remoteForked {
   497  				block.SetExtra(params.DAOForkBlockExtra)
   498  			}
   499  		})
   500  		if err := p2p.Send(peer.app, BlockHeadersMsg, []*types.Header{blocks[0].Header()}); err != nil {
   501  			t.Fatalf("failed to answer challenge: %v", err)
   502  		}
   503  time.Sleep(100 * time.Millisecond) //睡眠以避免验证与水滴赛跑
   504  	} else {
   505  //否则,等待测试超时通过
   506  		time.Sleep(daoChallengeTimeout + 500*time.Millisecond)
   507  	}
   508  //验证是否根据分叉端维护或删除远程对等机
   509  	if localForked == remoteForked && !timeout {
   510  		if peers := pm.peers.Len(); peers != 1 {
   511  			t.Fatalf("peer count mismatch: have %d, want %d", peers, 1)
   512  		}
   513  	} else {
   514  		if peers := pm.peers.Len(); peers != 0 {
   515  			t.Fatalf("peer count mismatch: have %d, want %d", peers, 0)
   516  		}
   517  	}
   518  }
   519