code: func (s *Simulation) Run(ctx context.Context, step *Step) (result *StepResult) {
  	result = newStepResult()
  
  	result.StartedAt = time.Now()
  	defer func() { result.FinishedAt = time.Now() }()
  
  	// watch network events for the duration of the step
  	stop := s.watchNetwork(result)
  	defer stop()
  
  	// perform the action
  	if err := step.Action(ctx); err != nil {
  		result.Error = err
  		return
  	}
  
  	// wait for all node expectations to either pass, error or timeout
  	nodes := make(map[enode.ID]struct{}, len(step.Expect.Nodes))
  	for _, id := range step.Expect.Nodes {
  		nodes[id] = struct{}{}
  	}
  	for len(result.Passes) < len(nodes) {
  		select {
  		case id := <-step.Trigger:
  			// skip if we aren't checking the node
  			if _, ok := nodes[id]; !ok {
  				continue
  			}
  
  			// skip if the node has already passed
  			if _, ok := result.Passes[id]; ok {
  				continue
  			}
  
  			// run the node expectation check
  			pass, err := step.Expect.Check(ctx, id)
  			if err != nil {
  				result.Error = err
  				return
  			}
  			if pass {
  				result.Passes[id] = time.Now()
  			}
  		case <-ctx.Done():
  			result.Error = ctx.Err()
  			return
  		}
  	}
  
  	return
  }
docs: // Run performs a step of the simulation by performing the step's action and
  // then waiting for the step's expectation to be met