github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/core/state/sync_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 state
    26  
    27  import (
    28  	"bytes"
    29  	"math/big"
    30  	"testing"
    31  
    32  	"github.com/ethereum/go-ethereum/common"
    33  	"github.com/ethereum/go-ethereum/crypto"
    34  	"github.com/ethereum/go-ethereum/ethdb"
    35  	"github.com/ethereum/go-ethereum/trie"
    36  )
    37  
    38  //TestAccount是与状态测试使用的帐户关联的数据。
    39  type testAccount struct {
    40  	address common.Address
    41  	balance *big.Int
    42  	nonce   uint64
    43  	code    []byte
    44  }
    45  
    46  //maketeststate创建一个样本测试状态来测试节点重构。
    47  func makeTestState() (Database, common.Hash, []*testAccount) {
    48  //创建空状态
    49  	db := NewDatabase(ethdb.NewMemDatabase())
    50  	state, _ := New(common.Hash{}, db)
    51  
    52  //用任意数据填充它
    53  	accounts := []*testAccount{}
    54  	for i := byte(0); i < 96; i++ {
    55  		obj := state.GetOrNewStateObject(common.BytesToAddress([]byte{i}))
    56  		acc := &testAccount{address: common.BytesToAddress([]byte{i})}
    57  
    58  		obj.AddBalance(big.NewInt(int64(11 * i)))
    59  		acc.balance = big.NewInt(int64(11 * i))
    60  
    61  		obj.SetNonce(uint64(42 * i))
    62  		acc.nonce = uint64(42 * i)
    63  
    64  		if i%3 == 0 {
    65  			obj.SetCode(crypto.Keccak256Hash([]byte{i, i, i, i, i}), []byte{i, i, i, i, i})
    66  			acc.code = []byte{i, i, i, i, i}
    67  		}
    68  		state.updateStateObject(obj)
    69  		accounts = append(accounts, acc)
    70  	}
    71  	root, _ := state.Commit(false)
    72  
    73  //返回生成的状态
    74  	return db, root, accounts
    75  }
    76  
    77  //checkStateAccounts交叉引用一个重构的状态,该状态应为
    78  //帐户数组。
    79  func checkStateAccounts(t *testing.T, db ethdb.Database, root common.Hash, accounts []*testAccount) {
    80  //检查根可用性和状态内容
    81  	state, err := New(root, NewDatabase(db))
    82  	if err != nil {
    83  		t.Fatalf("failed to create state trie at %x: %v", root, err)
    84  	}
    85  	if err := checkStateConsistency(db, root); err != nil {
    86  		t.Fatalf("inconsistent state trie at %x: %v", root, err)
    87  	}
    88  	for i, acc := range accounts {
    89  		if balance := state.GetBalance(acc.address); balance.Cmp(acc.balance) != 0 {
    90  			t.Errorf("account %d: balance mismatch: have %v, want %v", i, balance, acc.balance)
    91  		}
    92  		if nonce := state.GetNonce(acc.address); nonce != acc.nonce {
    93  			t.Errorf("account %d: nonce mismatch: have %v, want %v", i, nonce, acc.nonce)
    94  		}
    95  		if code := state.GetCode(acc.address); !bytes.Equal(code, acc.code) {
    96  			t.Errorf("account %d: code mismatch: have %x, want %x", i, code, acc.code)
    97  		}
    98  	}
    99  }
   100  
   101  //checktrie一致性检查(sub-)trie中的所有节点是否确实存在。
   102  func checkTrieConsistency(db ethdb.Database, root common.Hash) error {
   103  	if v, _ := db.Get(root[:]); v == nil {
   104  return nil //认为不存在的状态是一致的。
   105  	}
   106  	trie, err := trie.New(root, trie.NewDatabase(db))
   107  	if err != nil {
   108  		return err
   109  	}
   110  	it := trie.NodeIterator(nil)
   111  	for it.Next(true) {
   112  	}
   113  	return it.Error()
   114  }
   115  
   116  //checkstateconsistency检查状态根的所有数据是否存在。
   117  func checkStateConsistency(db ethdb.Database, root common.Hash) error {
   118  //创建并迭代子节点中的状态trie
   119  	if _, err := db.Get(root.Bytes()); err != nil {
   120  return nil //认为不存在的状态是一致的。
   121  	}
   122  	state, err := New(root, NewDatabase(db))
   123  	if err != nil {
   124  		return err
   125  	}
   126  	it := NewNodeIterator(state)
   127  	for it.Next() {
   128  	}
   129  	return it.Error
   130  }
   131  
   132  //测试是否未计划空状态进行同步。
   133  func TestEmptyStateSync(t *testing.T) {
   134  	empty := common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
   135  	if req := NewStateSync(empty, ethdb.NewMemDatabase()).Missing(1); len(req) != 0 {
   136  		t.Errorf("content requested for empty state: %v", req)
   137  	}
   138  }
   139  
   140  //测试给定根哈希,状态可以在单个线程上迭代同步,
   141  //请求检索任务并一次性返回所有任务。
   142  func TestIterativeStateSyncIndividual(t *testing.T) { testIterativeStateSync(t, 1) }
   143  func TestIterativeStateSyncBatched(t *testing.T)    { testIterativeStateSync(t, 100) }
   144  
   145  func testIterativeStateSync(t *testing.T, batch int) {
   146  //创建要复制的随机状态
   147  	srcDb, srcRoot, srcAccounts := makeTestState()
   148  
   149  //创建目标状态并与调度程序同步
   150  	dstDb := ethdb.NewMemDatabase()
   151  	sched := NewStateSync(srcRoot, dstDb)
   152  
   153  	queue := append([]common.Hash{}, sched.Missing(batch)...)
   154  	for len(queue) > 0 {
   155  		results := make([]trie.SyncResult, len(queue))
   156  		for i, hash := range queue {
   157  			data, err := srcDb.TrieDB().Node(hash)
   158  			if err != nil {
   159  				t.Fatalf("failed to retrieve node data for %x", hash)
   160  			}
   161  			results[i] = trie.SyncResult{Hash: hash, Data: data}
   162  		}
   163  		if _, index, err := sched.Process(results); err != nil {
   164  			t.Fatalf("failed to process result #%d: %v", index, err)
   165  		}
   166  		if index, err := sched.Commit(dstDb); err != nil {
   167  			t.Fatalf("failed to commit data #%d: %v", index, err)
   168  		}
   169  		queue = append(queue[:0], sched.Missing(batch)...)
   170  	}
   171  //交叉检查两个状态是否同步
   172  	checkStateAccounts(t, dstDb, srcRoot, srcAccounts)
   173  }
   174  
   175  //测试trie调度程序是否可以正确地重建状态,即使只有
   176  //返回部分结果,其他结果只在稍后发送。
   177  func TestIterativeDelayedStateSync(t *testing.T) {
   178  //创建要复制的随机状态
   179  	srcDb, srcRoot, srcAccounts := makeTestState()
   180  
   181  //创建目标状态并与调度程序同步
   182  	dstDb := ethdb.NewMemDatabase()
   183  	sched := NewStateSync(srcRoot, dstDb)
   184  
   185  	queue := append([]common.Hash{}, sched.Missing(0)...)
   186  	for len(queue) > 0 {
   187  //只同步一半的计划节点
   188  		results := make([]trie.SyncResult, len(queue)/2+1)
   189  		for i, hash := range queue[:len(results)] {
   190  			data, err := srcDb.TrieDB().Node(hash)
   191  			if err != nil {
   192  				t.Fatalf("failed to retrieve node data for %x", hash)
   193  			}
   194  			results[i] = trie.SyncResult{Hash: hash, Data: data}
   195  		}
   196  		if _, index, err := sched.Process(results); err != nil {
   197  			t.Fatalf("failed to process result #%d: %v", index, err)
   198  		}
   199  		if index, err := sched.Commit(dstDb); err != nil {
   200  			t.Fatalf("failed to commit data #%d: %v", index, err)
   201  		}
   202  		queue = append(queue[len(results):], sched.Missing(0)...)
   203  	}
   204  //交叉检查两个状态是否同步
   205  	checkStateAccounts(t, dstDb, srcRoot, srcAccounts)
   206  }
   207  
   208  //测试给定根哈希,trie可以在单个线程上迭代同步,
   209  //请求检索任务并一次性返回所有任务,但是在
   210  //随机顺序。
   211  func TestIterativeRandomStateSyncIndividual(t *testing.T) { testIterativeRandomStateSync(t, 1) }
   212  func TestIterativeRandomStateSyncBatched(t *testing.T)    { testIterativeRandomStateSync(t, 100) }
   213  
   214  func testIterativeRandomStateSync(t *testing.T, batch int) {
   215  //创建要复制的随机状态
   216  	srcDb, srcRoot, srcAccounts := makeTestState()
   217  
   218  //创建目标状态并与调度程序同步
   219  	dstDb := ethdb.NewMemDatabase()
   220  	sched := NewStateSync(srcRoot, dstDb)
   221  
   222  	queue := make(map[common.Hash]struct{})
   223  	for _, hash := range sched.Missing(batch) {
   224  		queue[hash] = struct{}{}
   225  	}
   226  	for len(queue) > 0 {
   227  //以随机顺序获取所有排队的节点
   228  		results := make([]trie.SyncResult, 0, len(queue))
   229  		for hash := range queue {
   230  			data, err := srcDb.TrieDB().Node(hash)
   231  			if err != nil {
   232  				t.Fatalf("failed to retrieve node data for %x", hash)
   233  			}
   234  			results = append(results, trie.SyncResult{Hash: hash, Data: data})
   235  		}
   236  //将检索到的结果反馈并将新任务排队
   237  		if _, index, err := sched.Process(results); err != nil {
   238  			t.Fatalf("failed to process result #%d: %v", index, err)
   239  		}
   240  		if index, err := sched.Commit(dstDb); err != nil {
   241  			t.Fatalf("failed to commit data #%d: %v", index, err)
   242  		}
   243  		queue = make(map[common.Hash]struct{})
   244  		for _, hash := range sched.Missing(batch) {
   245  			queue[hash] = struct{}{}
   246  		}
   247  	}
   248  //交叉检查两个状态是否同步
   249  	checkStateAccounts(t, dstDb, srcRoot, srcAccounts)
   250  }
   251  
   252  //测试trie调度程序是否可以正确地重建状态,即使只有
   253  //部分结果会被返回(甚至是随机返回的结果),其他结果只会在稍后发送。
   254  func TestIterativeRandomDelayedStateSync(t *testing.T) {
   255  //创建要复制的随机状态
   256  	srcDb, srcRoot, srcAccounts := makeTestState()
   257  
   258  //创建目标状态并与调度程序同步
   259  	dstDb := ethdb.NewMemDatabase()
   260  	sched := NewStateSync(srcRoot, dstDb)
   261  
   262  	queue := make(map[common.Hash]struct{})
   263  	for _, hash := range sched.Missing(0) {
   264  		queue[hash] = struct{}{}
   265  	}
   266  	for len(queue) > 0 {
   267  //只同步一半的计划节点,甚至是随机顺序的节点
   268  		results := make([]trie.SyncResult, 0, len(queue)/2+1)
   269  		for hash := range queue {
   270  			delete(queue, hash)
   271  
   272  			data, err := srcDb.TrieDB().Node(hash)
   273  			if err != nil {
   274  				t.Fatalf("failed to retrieve node data for %x", hash)
   275  			}
   276  			results = append(results, trie.SyncResult{Hash: hash, Data: data})
   277  
   278  			if len(results) >= cap(results) {
   279  				break
   280  			}
   281  		}
   282  //将检索到的结果反馈并将新任务排队
   283  		if _, index, err := sched.Process(results); err != nil {
   284  			t.Fatalf("failed to process result #%d: %v", index, err)
   285  		}
   286  		if index, err := sched.Commit(dstDb); err != nil {
   287  			t.Fatalf("failed to commit data #%d: %v", index, err)
   288  		}
   289  		for _, hash := range sched.Missing(0) {
   290  			queue[hash] = struct{}{}
   291  		}
   292  	}
   293  //交叉检查两个状态是否同步
   294  	checkStateAccounts(t, dstDb, srcRoot, srcAccounts)
   295  }
   296  
   297  //测试在同步过程中的任何时间点,只有完整的子尝试处于
   298  //数据库。
   299  func TestIncompleteStateSync(t *testing.T) {
   300  //创建要复制的随机状态
   301  	srcDb, srcRoot, srcAccounts := makeTestState()
   302  
   303  	checkTrieConsistency(srcDb.TrieDB().DiskDB().(ethdb.Database), srcRoot)
   304  
   305  //创建目标状态并与调度程序同步
   306  	dstDb := ethdb.NewMemDatabase()
   307  	sched := NewStateSync(srcRoot, dstDb)
   308  
   309  	added := []common.Hash{}
   310  	queue := append([]common.Hash{}, sched.Missing(1)...)
   311  	for len(queue) > 0 {
   312  //获取一批状态节点
   313  		results := make([]trie.SyncResult, len(queue))
   314  		for i, hash := range queue {
   315  			data, err := srcDb.TrieDB().Node(hash)
   316  			if err != nil {
   317  				t.Fatalf("failed to retrieve node data for %x", hash)
   318  			}
   319  			results[i] = trie.SyncResult{Hash: hash, Data: data}
   320  		}
   321  //处理每个状态节点
   322  		if _, index, err := sched.Process(results); err != nil {
   323  			t.Fatalf("failed to process result #%d: %v", index, err)
   324  		}
   325  		if index, err := sched.Commit(dstDb); err != nil {
   326  			t.Fatalf("failed to commit data #%d: %v", index, err)
   327  		}
   328  		for _, result := range results {
   329  			added = append(added, result.Hash)
   330  		}
   331  //检查到目前为止添加的所有已知子尝试是否完全完成或丢失。
   332  	checkSubtries:
   333  		for _, hash := range added {
   334  			for _, acc := range srcAccounts {
   335  				if hash == crypto.Keccak256Hash(acc.code) {
   336  continue checkSubtries //跳过代码节点的三检。
   337  				}
   338  			}
   339  //无法在此处使用CheckStateConsistency,因为子RIE键可能具有奇数
   340  //长度和撞击力。
   341  			if err := checkTrieConsistency(dstDb, hash); err != nil {
   342  				t.Fatalf("state inconsistent: %v", err)
   343  			}
   344  		}
   345  //获取要检索的下一批
   346  		queue = append(queue[:0], sched.Missing(1)...)
   347  	}
   348  //健全性检查是否检测到从数据库中删除任何节点
   349  	for _, node := range added[1:] {
   350  		key := node.Bytes()
   351  		value, _ := dstDb.Get(key)
   352  
   353  		dstDb.Delete(key)
   354  		if err := checkStateConsistency(dstDb, added[0]); err == nil {
   355  			t.Fatalf("trie inconsistency not caught, missing: %x", key)
   356  		}
   357  		dstDb.Put(key, value)
   358  	}
   359  }