github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/p2p/simulations/simulation.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 //版权所有2017 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 simulations 26 27 import ( 28 "context" 29 "time" 30 31 "github.com/ethereum/go-ethereum/p2p/discover" 32 ) 33 34 //模拟为在模拟网络中运行操作提供了一个框架 35 //然后等待期望得到满足 36 type Simulation struct { 37 network *Network 38 } 39 40 //新模拟返回在给定网络中运行的新模拟 41 func NewSimulation(network *Network) *Simulation { 42 return &Simulation{ 43 network: network, 44 } 45 } 46 47 //运行通过执行步骤的操作执行模拟步骤,并 48 //然后等待步骤的期望得到满足 49 func (s *Simulation) Run(ctx context.Context, step *Step) (result *StepResult) { 50 result = newStepResult() 51 52 result.StartedAt = time.Now() 53 defer func() { result.FinishedAt = time.Now() }() 54 55 //在步骤期间监视网络事件 56 stop := s.watchNetwork(result) 57 defer stop() 58 59 //执行操作 60 if err := step.Action(ctx); err != nil { 61 result.Error = err 62 return 63 } 64 65 //等待所有节点期望通过、错误或超时 66 nodes := make(map[discover.NodeID]struct{}, len(step.Expect.Nodes)) 67 for _, id := range step.Expect.Nodes { 68 nodes[id] = struct{}{} 69 } 70 for len(result.Passes) < len(nodes) { 71 select { 72 case id := <-step.Trigger: 73 //如果不检查节点,则跳过 74 if _, ok := nodes[id]; !ok { 75 continue 76 } 77 78 //如果节点已通过,则跳过 79 if _, ok := result.Passes[id]; ok { 80 continue 81 } 82 83 //运行节点期望检查 84 pass, err := step.Expect.Check(ctx, id) 85 if err != nil { 86 result.Error = err 87 return 88 } 89 if pass { 90 result.Passes[id] = time.Now() 91 } 92 case <-ctx.Done(): 93 result.Error = ctx.Err() 94 return 95 } 96 } 97 98 return 99 } 100 101 func (s *Simulation) watchNetwork(result *StepResult) func() { 102 stop := make(chan struct{}) 103 done := make(chan struct{}) 104 events := make(chan *Event) 105 sub := s.network.Events().Subscribe(events) 106 go func() { 107 defer close(done) 108 defer sub.Unsubscribe() 109 for { 110 select { 111 case event := <-events: 112 result.NetworkEvents = append(result.NetworkEvents, event) 113 case <-stop: 114 return 115 } 116 } 117 }() 118 return func() { 119 close(stop) 120 <-done 121 } 122 } 123 124 type Step struct { 125 //操作是为此步骤执行的操作 126 Action func(context.Context) error 127 128 //触发器是一个接收节点ID并触发 129 //该节点的预期检查 130 Trigger chan discover.NodeID 131 132 //Expect是执行此步骤时等待的期望 133 Expect *Expectation 134 } 135 136 type Expectation struct { 137 //节点是要检查的节点列表 138 Nodes []discover.NodeID 139 140 //检查给定节点是否满足预期 141 Check func(context.Context, discover.NodeID) (bool, error) 142 } 143 144 func newStepResult() *StepResult { 145 return &StepResult{ 146 Passes: make(map[discover.NodeID]time.Time), 147 } 148 } 149 150 type StepResult struct { 151 //错误是运行步骤时遇到的错误 152 Error error 153 154 //Startedat是步骤开始的时间 155 StartedAt time.Time 156 157 //FinishedAt是步骤完成的时间。 158 FinishedAt time.Time 159 160 //传递是成功节点期望的时间戳 161 Passes map[discover.NodeID]time.Time 162 163 //NetworkEvents是在步骤中发生的网络事件。 164 NetworkEvents []*Event 165 }