text: #!/usr/bin/env python3
  # Copyright (c) 2014-2017 The Bitcoin Core developers
  # Distributed under the MIT software license, see the accompanying
  # file COPYING or http://www.opensource.org/licenses/mit-license.php.
  
  from .messages import msg_getheaders, msg_headers, CBlockHeader
  from .mininode import P2PInterface, mininode_lock
  from .util import wait_until
  
  ## Altecoin Test Node
  class AltecoinTestNode(P2PInterface):
      def __init__(self):
          super().__init__()
          self.last_sendcmpct = []
          self.block_announced = False
          # Store the hashes of blocks we've seen announced.
          # This is for synchronizing the p2p message traffic,
          # so we can eg wait until a particular block is announced.
          self.announced_blockhashes = set()
  
      def on_sendcmpct(self, message):
          self.last_sendcmpct.append(message)
  
      def on_cmpctblock(self, message):
          self.block_announced = True
          self.last_message["cmpctblock"].header_and_shortids.header.calc_sha256()
          self.announced_blockhashes.add(self.last_message["cmpctblock"].header_and_shortids.header.sha256)
  
      def on_headers(self, message):
          self.block_announced = True
          for x in self.last_message["headers"].headers:
              x.calc_sha256()
              self.announced_blockhashes.add(x.sha256)
  
      def on_inv(self, message):
          for x in self.last_message["inv"].inv:
              if x.type == 2:
                  self.block_announced = True
                  self.announced_blockhashes.add(x.hash)
  
      # Requires caller to hold mininode_lock
      def received_block_announcement(self):
          return self.block_announced
  
      def clear_block_announcement(self):
          with mininode_lock:
              self.block_announced = False
              self.last_message.pop("inv", None)
              self.last_message.pop("headers", None)
              self.last_message.pop("cmpctblock", None)
  
      def get_headers(self, locator, hashstop):
          msg = msg_getheaders()
          msg.locator.vHave = locator
          msg.hashstop = hashstop
          self.connection.send_message(msg)
  
      def send_header_for_blocks(self, new_blocks):
          headers_message = msg_headers()
          headers_message.headers = [CBlockHeader(b) for b in new_blocks]
          self.send_message(headers_message)
  
      def request_headers_and_sync(self, locator, hashstop=0):
          self.clear_block_announcement()
          self.get_headers(locator, hashstop)
          wait_until(self.received_block_announcement, timeout=30, lock=mininode_lock)
          self.clear_block_announcement()
  
      # Block until a block announcement for a particular block hash is received.
      def wait_for_block_announcement(self, block_hash, timeout=30):
          def received_hash():
              return (block_hash in self.announced_blockhashes)
          wait_until(received_hash, timeout=timeout, lock=mininode_lock)
  
      def send_await_disconnect(self, message, timeout=30):
          """Sends a message to the node and wait for disconnect.
  
          This is used when we want to send a message into the node that we expect
          will get us disconnected, eg an invalid block."""
          self.send_message(message)
          wait_until(lambda: not self.connected, timeout=timeout, lock=mininode_lock)
  
  