docs: def padding_oracle_decrypt(oracle, ciphertext, known_prefix=b'', known_suffix=b'', block_size=128,
                             alphabet=None, pool=None, block_pool=None, progress=None):
      """
      Decrypt ciphertext using an oracle function that returns ``True`` if the
      provided ciphertext is correctly PKCS#7 padded after decryption. The
      cipher needs to operate in CBC mode.
  
      Args:
          oracle(callable): The oracle function. Will be called repeatedly with
              a chunk of ciphertext.
          ciphertext(bytes): The data to decrypt. Should include the IV at the
              start.
          known_prefix(bytes): If the start of the plaintext is known, it can be
              provided to skip decrypting the known prefix.
          known_suffix(bytes): If the end of the plaintext is known, it can be
              provided to skip decrypting the known suffix. Should include
              padding.
          block_size(int): The cipher's block size in bits.
          alphabet(bytes): Optimize decryption if you know which characters the
              plaintext will consist of.
          pool(multiprocessing.Pool): A multiprocessing pool to use to
              parallelize the decryption. This pool is used to call the oracle
              function. Fairly heavy due to the required inter-process state
              synchronization. If ``None`` (the default), no multiprocessing
              will be used.
          block_pool(multiprocessing.Pool): A multiprocessing pool to use to
              parallelize the decryption. This pool is used to decrypt entire
              blocks in parallel. When decrypting ciphertext consisting of
              multiple blocks, it is usually more efficient than using the
              ``pool`` argument. If ``None`` (the default), no multiprocessing
              will be used.
          progress(callable): A callable that will be called each time a new
              byte is decrypted. Is called with the positition of the character
              in the plaintext result and the character itself.
  
      Returns:
          bytes: The decrypted data with its PKCS#7 padding stripped.
  
      Raises:
          RuntimeError: Raised if the oracle behaves unpredictable.
  
      Example:
          >>> from pwny import *
          >>> with multiprocessing.Pool(5) as pool:
          >>>     print(padding_oracle_decrypt(oracle_function, encrypted_data, pool=pool))
          b'decrypted data'
      """
  
      block_len = block_size // 8
      assert len(ciphertext) % block_len == 0 and len(ciphertext) >= 2 * block_len
  
      known_prefix = bytearray(known_prefix)
      known_suffix = bytearray(known_suffix)
  
      if alphabet is None:
          alphabet = bytearray(range(256))
  
      if block_pool is not None:
          map_func = block_pool.imap
      else:
          map_func = map
  
      plaintext = bytearray()
  
      decrypt_func = functools.partial(decrypt_block, oracle, block_len, alphabet, pool, progress)
      for plain in map_func(decrypt_func, block_pairs(block_len, bytearray(ciphertext), known_prefix, known_suffix)):
          plaintext[0:0] = plain
  
      return bytes(plaintext[:-plaintext[-1]])