github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/eth/handler_test.go (about)

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