git / moonbite-core / src/libmw/test/tests/models/tx/Test_Output.cpp · raw

// Copyright (c) 2021 The Litecoin Core developers// Distributed under the MIT software license, see the accompanying// file COPYING or http://www.opensource.org/licenses/mit-license.php.#include <mw/crypto/Blinds.h>#include <mw/crypto/Bulletproofs.h>#include <mw/crypto/Hasher.h>#include <mw/crypto/Schnorr.h>#include <mw/crypto/SecretKeys.h>#include <mw/models/tx/Output.h>#include <mw/models/wallet/StealthAddress.h>#include <test_framework/Deserializer.h>#include <test_framework/TestMWEB.h>BOOST_FIXTURE_TEST_SUITE(TestOutput, MWEBTestingSetup)BOOST_AUTO_TEST_CASE(Create){    // Generate receiver master keys    SecretKey a = SecretKey::Random();    SecretKey b = SecretKey::Random();    PublicKey A = PublicKey::From(a);    // Generate receiver sub-address (i = 10)    SecretKey b_i = SecretKeys::From(b)        .Add(SecretKey::FromHash(Hasher().Append(A).Append(10).Append(a).hash()))        .Total();    StealthAddress receiver_subaddr(        PublicKey::From(b_i).Mul(a),        PublicKey::From(b_i)    );    // Build output    uint64_t amount = 1'234'567;    BlindingFactor blind;    SecretKey sender_key = SecretKey::Random();    Output output = Output::Create(        &blind,        sender_key,        receiver_subaddr,        amount    );    Commitment expected_commit = Commitment::Switch(blind, amount);    // Verify bulletproof    ProofData proof_data = output.BuildProofData();    BOOST_REQUIRE(proof_data.commitment == expected_commit);    BOOST_REQUIRE(proof_data.pRangeProof == output.GetRangeProof());    BOOST_REQUIRE(Bulletproofs::BatchVerify({ output.BuildProofData() }));    // Verify sender signature    SignedMessage signed_msg = output.BuildSignedMsg();    BOOST_REQUIRE(signed_msg.GetPublicKey() == PublicKey::From(sender_key));    BOOST_REQUIRE(Schnorr::BatchVerify({ signed_msg }));    // Verify Output ID    mw::Hash expected_id = Hasher()        .Append(output.GetCommitment())        .Append(output.GetSenderPubKey())        .Append(output.GetReceiverPubKey())        .Append(output.GetOutputMessage().GetHash())        .Append(output.GetRangeProof()->GetHash())        .Append(output.GetSignature())        .hash();    BOOST_REQUIRE(output.GetOutputID() == expected_id);    // Getters    BOOST_REQUIRE(output.GetCommitment() == expected_commit);    //    // Test Restoring Output    //    {        // Check view tag        BOOST_REQUIRE(Hashed(EHashTag::TAG, output.Ke().Mul(a))[0] == output.GetViewTag());        // Make sure B belongs to wallet        SecretKey t = SecretKey::FromHash(Hashed(EHashTag::DERIVE, output.Ke().Mul(a)));        BOOST_REQUIRE(receiver_subaddr.B() == output.Ko().Div(SecretKey::FromHash(Hashed(EHashTag::OUT_KEY, t))));        BlindingFactor r(SecretKey::FromHash(Hashed(EHashTag::BLIND, t)));        uint64_t value = output.GetMaskedValue() ^ *((uint64_t*)Hashed(EHashTag::VALUE_MASK, t).data());        BigInt<16> n = output.GetMaskedNonce() ^ BigInt<16>(Hashed(EHashTag::NONCE_MASK, t).data());        BOOST_REQUIRE(Commitment::Switch(r, value) == output.GetCommitment());        // Calculate Carol's sending key 's' and check that s*B ?= Ke        SecretKey s = SecretKey::FromHash(Hasher(EHashTag::SEND_KEY)            .Append(receiver_subaddr.A())            .Append(receiver_subaddr.B())            .Append(value)            .Append(n)            .hash());        BOOST_REQUIRE(output.Ke() == receiver_subaddr.B().Mul(s));        // Make sure receiver can generate the spend key        SecretKey spend_key = SecretKeys::From(b_i)            .Mul(SecretKey::FromHash(Hashed(EHashTag::OUT_KEY, t)))            .Total();        BOOST_REQUIRE(output.GetReceiverPubKey() == PublicKey::From(spend_key));    }}BOOST_AUTO_TEST_SUITE_END()