code: def add_block(self, nodes, data):
          
  
          # We can eliminate this source node
          if len(nodes) == 1:
              to_eliminate = list(self.eliminate(next(iter(nodes)), data))
  
              # Recursively eliminate all nodes that can now be resolved
              while len(to_eliminate):
                  other, check = to_eliminate.pop()
                  to_eliminate.extend(self.eliminate(other, check))
          else:
  
              # Pass messages from already-resolved source nodes
              for node in list(nodes):
                  if node in self.eliminated:
                      nodes.remove(node)
                      data ^= self.eliminated[node]
  
              # Resolve if we are left with a single non-resolved source node
              if len(nodes) == 1:
                  return self.add_block(nodes, data)
              else:
  
                  # Add edges for all remaining nodes to this check
                  check = CheckNode(nodes, data)
                  for node in nodes:
                      self.checks[node].append(check)
  
          # Are we done yet?
          return len(self.eliminated) >= self.num_blocks
docs: Adds a new check node and edges between that node and all
          source nodes it connects, resolving all message passes that
          become possible as a result.