git / moonbite-core / src/libmw/test/tests/consensus/Test_KernelSumValidator.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/consensus/KernelSumValidator.h>#include <mw/consensus/Aggregation.h>#include <mw/crypto/Pedersen.h>#include <mw/node/CoinsView.h>#include <test_framework/TestMWEB.h>#include <test_framework/models/Tx.h>#include <test_framework/Miner.h>#include <test_framework/TxBuilder.h>// FUTURE: Create official test vectors for the consensus rules being testedBOOST_FIXTURE_TEST_SUITE(TestKernelSumValidator, MWEBTestingSetup)BOOST_AUTO_TEST_CASE(ValidateState){    // Pegin transaction    test::Tx pegin_tx = test::TxBuilder()        .AddOutput(4'000'000)        .AddOutput(5'000'000)        .AddPeginKernel(9'000'000)        .Build();    // Standard transaction    test::Tx standard_tx = test::TxBuilder()        .AddInput(pegin_tx.GetOutputs()[0])        .AddOutput(2'950'000).AddOutput(1'000'000)        .AddPlainKernel(50'000)        .Build();    // Pegout Transaction    test::Tx pegout_tx = test::TxBuilder()        .AddInput(standard_tx.GetOutputs()[1])        .AddOutput(200'000)        .AddPegoutKernel(750'000, 50'000)        .Build();    std::vector<Commitment> utxo_commitments{        pegin_tx.GetOutputs()[1].GetCommitment(),        standard_tx.GetOutputs()[0].GetCommitment(),        pegout_tx.GetOutputs()[0].GetCommitment()    };    std::vector<Kernel> kernels{        pegin_tx.GetKernels().front(),        standard_tx.GetKernels().front(),        pegout_tx.GetKernels().front()    };    BlindingFactor total_offset = Blinds()        .Add(pegin_tx.GetKernelOffset())        .Add(standard_tx.GetKernelOffset())        .Add(pegout_tx.GetKernelOffset())        .Total();    // State is valid    KernelSumValidator::ValidateState(utxo_commitments, kernels, total_offset);    // Move pegout kernel before pegin kernel in list to make supply negative in the past    kernels = std::vector<Kernel>{        pegout_tx.GetKernels().front(),        pegin_tx.GetKernels().front(),        standard_tx.GetKernels().front()    };    // Consensus error should be thrown    BOOST_REQUIRE_THROW(KernelSumValidator::ValidateState(utxo_commitments, kernels, total_offset), ValidationException);}BOOST_AUTO_TEST_CASE(ValidateForBlock){    // Standard transaction - 2 inputs, 2 outputs, 1 kernel    mw::Transaction::CPtr tx1 = test::TxBuilder()        .AddInput(5'000'000).AddInput(6'000'000)        .AddOutput(4'000'000).AddOutput(6'500'000)        .AddPlainKernel(500'000)        .Build().GetTransaction();    KernelSumValidator::ValidateForTx(*tx1); // Sanity check    // Pegin transaction - 1 output, 1 kernel    mw::Transaction::CPtr tx2 = test::TxBuilder()        .AddOutput(8'000'000)        .AddPeginKernel(8'000'000)        .Build().GetTransaction();    KernelSumValidator::ValidateForTx(*tx2); // Sanity check    mw::Transaction::CPtr tx3 = test::TxBuilder()        .AddInput(1'234'567).AddInput(4'000'000)        .AddOutput(234'567)        .AddPegoutKernel(4'500'000, 500'000)        .Build().GetTransaction();    KernelSumValidator::ValidateForTx(*tx3); // Sanity check    BlindingFactor prev_total_offset = BlindingFactor::Random();    mw::Transaction::CPtr pAggregated = Aggregation::Aggregate({ tx1, tx2, tx3 });    KernelSumValidator::ValidateForTx(*pAggregated); // Sanity check    BlindingFactor total_offset = Pedersen::AddBlindingFactors({ prev_total_offset, pAggregated->GetKernelOffset() });    KernelSumValidator::ValidateForBlock(pAggregated->GetBody(), total_offset, prev_total_offset);}//// This tests ValidateForBlock without using the TxBuilder utility, since in theory it could contain bugs.// In the future, it would be even better to replace this with official test vectors, and avoid relying on Random entirely.//BOOST_AUTO_TEST_CASE(ValidateForBlockWithoutBuilder){    std::vector<Input> inputs;    std::vector<Output> outputs;    std::vector<Kernel> kernels;    // Add inputs    BlindingFactor input1_bf = BlindingFactor::Random();    SecretKey input1_key = SecretKey::Random();    SecretKey input1_output_key = SecretKey::Random();    inputs.push_back(test::TxInput::Create(input1_bf, input1_key, input1_output_key, 5'000'000).GetInput());    BlindingFactor input2_bf = BlindingFactor::Random();    SecretKey input2_key = SecretKey::Random();    SecretKey input2_output_key = SecretKey::Random();    inputs.push_back(test::TxInput::Create(input2_bf, input2_key, input2_output_key, 6'000'000).GetInput());    // Add outputs    SecretKey output1_sender_key = SecretKey::Random();    test::TxOutput output1 = test::TxOutput::Create(        output1_sender_key,        StealthAddress::Random(),        4'000'000    );    BlindingFactor output1_bf = output1.GetBlind();    outputs.push_back(output1.GetOutput());    SecretKey output2_sender_key = SecretKey::Random();    test::TxOutput output2 = test::TxOutput::Create(        output2_sender_key,        StealthAddress::Random(),        6'500'000    );    BlindingFactor output2_bf = output2.GetBlind();    outputs.push_back(output2.GetOutput());    // Kernel offset    mw::Hash prev_total_offset = mw::Hash::FromHex("0123456789abcdef0123456789abcdef00000000000000000000000000000000");    BlindingFactor tx_offset = BlindingFactor::Random();    BlindingFactor total_offset = Blinds().Add(prev_total_offset).Add(tx_offset).Total();    // Calculate kernel excess    BlindingFactor excess = Blinds()        .Add(output1_bf)        .Add(output2_bf)        .Sub(input1_bf)        .Sub(input2_bf)        .Sub(tx_offset)        .Total();    // Add kernel    const CAmount fee = 500'000;    kernels.push_back(Kernel::Create(excess, boost::none, fee, boost::none, std::vector<PegOutCoin>{}, boost::none));    // Create Transaction    auto pTransaction = mw::Transaction::Create(        tx_offset,        BlindingFactor::Random(),        inputs,        outputs,        kernels    );    KernelSumValidator::ValidateForBlock(pTransaction->GetBody(), total_offset, prev_total_offset);}BOOST_AUTO_TEST_CASE(ValidateForTx){    // Standard transaction - 2 inputs, 2 outputs, 1 kernel    mw::Transaction::CPtr tx1 = test::TxBuilder()        .AddInput(5'000'000).AddInput(6'000'000)        .AddOutput(4'000'000).AddOutput(6'500'000)        .AddPlainKernel(500'000)        .Build().GetTransaction();    KernelSumValidator::ValidateForTx(*tx1);    // Pegin transaction - 1 output, 1 kernel    mw::Transaction::CPtr tx2 = test::TxBuilder()        .AddOutput(8'000'000)        .AddPeginKernel(8'000'000)        .Build().GetTransaction();    KernelSumValidator::ValidateForTx(*tx2);    // Pegout transaction - 2 inputs, 1 output, 1 kernel    mw::Transaction::CPtr tx3 = test::TxBuilder()        .AddInput(1'234'567).AddInput(4'000'000)        .AddOutput(234'567)        .AddPegoutKernel(4'500'000, 500'000)        .Build().GetTransaction();    KernelSumValidator::ValidateForTx(*tx3);    // Aggregate all 3    mw::Transaction::CPtr pAggregated = Aggregation::Aggregate({ tx1, tx2, tx3 });    KernelSumValidator::ValidateForTx(*pAggregated);}BOOST_AUTO_TEST_SUITE_END()