boost::optional<SaplingNotePlaintext> SaplingNotePlaintext::decrypt(
    const SaplingEncCiphertext &ciphertext,
    const uint256 &ivk,
    const uint256 &epk,
    const uint256 &cmu
)
{
    auto pt = AttemptSaplingEncDecryption(ciphertext, ivk, epk);
    if (!pt) {
        return boost::none;
    }

    // Deserialize from the plaintext
    SaplingNotePlaintext ret;
    try {
        CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
        ss << pt.get();
        ss >> ret;
        assert(ss.size() == 0);
    } catch (const boost::thread_interrupted&) {
        throw;
    } catch (...) {
        return boost::none;
    }

    uint256 pk_d;
    if (!librustzcash_ivk_to_pkd(ivk.begin(), ret.d.data(), pk_d.begin())) {
        return boost::none;
    }

    uint256 cmu_expected;
    if (!librustzcash_sapling_compute_cm(
        ret.d.data(),
        pk_d.begin(),
        ret.value(),
        ret.rcm.begin(),
        cmu_expected.begin()
    ))
    {
        return boost::none;
    }

    if (cmu_expected != cmu) {
        return boost::none;
    }

    return ret;
}
boost::optional<SaplingNotePlaintext> SaplingNotePlaintext::decrypt(
    const SaplingEncCiphertext &ciphertext,
    const uint256 &ivk,
    const uint256 &epk,
    const uint256 &cmu
)
{
    auto pt = AttemptSaplingEncDecryption(ciphertext, ivk, epk);
    if (!pt) {
        return boost::none;
    }

     
    SaplingNotePlaintext ret;
    try {
        CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
        ss << pt.get();
        ss >> ret;
        assert(ss.size() == 0);
    } catch (const boost::thread_interrupted&) {
        throw;
    } catch (...) {
        return boost::none;
    }

    uint256 pk_d;
    if (!librustzcash_ivk_to_pkd(ivk.begin(), ret.d.data(), pk_d.begin())) {
        return boost::none;
    }

    uint256 cmu_expected;
    if (!librustzcash_sapling_compute_cm(
        ret.d.data(),
        pk_d.begin(),
        ret.value(),
        ret.rcm.begin(),
        cmu_expected.begin()
    ))
    {
        return boost::none;
    }

    if (cmu_expected != cmu) {
        return boost::none;
    }

    return ret;
}