code: def initialize_symmetric(cls, noise_protocol: 'NoiseProtocol') -> 'SymmetricState':
          
          # Create SymmetricState
          instance = cls()
          instance.noise_protocol = noise_protocol
  
          # If protocol_name is less than or equal to HASHLEN bytes in length, sets h equal to protocol_name with zero
          # bytes appended to make HASHLEN bytes. Otherwise sets h = HASH(protocol_name).
          if len(noise_protocol.name) <= noise_protocol.hash_fn.hashlen:
              instance.h = noise_protocol.name.ljust(noise_protocol.hash_fn.hashlen, b'\0')
          else:
              instance.h = noise_protocol.hash_fn.hash(noise_protocol.name)
  
          # Sets ck = h.
          instance.ck = instance.h
  
          # Calls InitializeKey(empty).
          instance.cipher_state = CipherState(noise_protocol)
          instance.cipher_state.initialize_key(Empty())
          noise_protocol.cipher_state_handshake = instance.cipher_state
  
          return instance
docs: Instead of taking protocol_name as an argument, we take full NoiseProtocol object, that way we have access to
          protocol name and crypto functions
  
          Comments below are mostly copied from specification.
  
          :param noise_protocol: a valid NoiseProtocol instance
          :return: initialised SymmetricState instance