mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-18 13:17:55 +02:00
175 lines
6.6 KiB
C++
175 lines
6.6 KiB
C++
// Copyright (c) 2011-2014 The Bitcoin Core developers
|
|
// Distributed under the MIT/X11 software license, see the accompanying
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
#include "arith_uint256.h"
|
|
#include "blind.h"
|
|
#include "coins.h"
|
|
#include "uint256.h"
|
|
|
|
#include "test/test_bitcoin.h"
|
|
|
|
#include <boost/test/unit_test.hpp>
|
|
|
|
BOOST_FIXTURE_TEST_SUITE(blind_tests, BasicTestingSetup)
|
|
|
|
BOOST_AUTO_TEST_CASE(naive_blinding_test)
|
|
{
|
|
CCoinsView viewBase;
|
|
CCoinsViewCache cache(&viewBase);
|
|
|
|
CKey key1;
|
|
CKey key2;
|
|
CKey keyDummy;
|
|
|
|
unsigned char k1[32] = {1,2,3};
|
|
unsigned char k2[32] = {22,33,44};
|
|
unsigned char kDummy[32] = {133,144,155};
|
|
key1.Set(&k1[0], &k1[32], true);
|
|
key2.Set(&k2[0], &k2[32], true);
|
|
keyDummy.Set(&kDummy[0], &kDummy[32], true);
|
|
CPubKey pubkey1 = key1.GetPubKey();
|
|
CPubKey pubkey2 = key2.GetPubKey();
|
|
CPubKey pubkeyDummy = keyDummy.GetPubKey();
|
|
|
|
uint256 blind3, blind4, blindDummy;
|
|
|
|
{
|
|
CCoinsModifier tx1 = cache.ModifyCoins(ArithToUint256(1));
|
|
tx1->vout.resize(1);
|
|
tx1->vout[0].nValue = 11;
|
|
}
|
|
|
|
{
|
|
CCoinsModifier tx2 = cache.ModifyCoins(ArithToUint256(2));
|
|
tx2->vout.resize(2);
|
|
tx2->vout[0].nValue = 111;
|
|
}
|
|
|
|
{
|
|
// Build a transaction that spends 2 unblinded coins (11, 111), and produces a single blinded one (100) and fee (22).
|
|
CMutableTransaction tx3;
|
|
tx3.vin.resize(2);
|
|
tx3.vin[0].prevout.hash = ArithToUint256(1);
|
|
|
|
tx3.vin[0].prevout.n = 0;
|
|
tx3.vin[1].prevout.hash = ArithToUint256(2);
|
|
tx3.vin[1].prevout.n = 0;
|
|
tx3.vout.resize(1);
|
|
tx3.vout[0].nValue = 100;
|
|
tx3.nTxFee = 22;
|
|
BOOST_CHECK(cache.VerifyAmounts(tx3, tx3.nTxFee));
|
|
|
|
// Try to blind with a single output, which fails as its blinding factor ends up being zero.
|
|
std::vector<uint256> input_blinds;
|
|
std::vector<uint256> output_blinds;
|
|
std::vector<CPubKey> output_pubkeys;
|
|
input_blinds.push_back(uint256());
|
|
input_blinds.push_back(uint256());
|
|
output_blinds.push_back(uint256());
|
|
output_pubkeys.push_back(pubkey1);
|
|
BOOST_CHECK(!BlindOutputs(input_blinds, output_blinds, output_pubkeys, tx3));
|
|
|
|
// Add a dummy output.
|
|
tx3.vout.resize(2);
|
|
tx3.vout[1].nValue = 0;
|
|
output_blinds.push_back(uint256());
|
|
output_pubkeys.push_back(pubkeyDummy);
|
|
BOOST_CHECK(BlindOutputs(input_blinds, output_blinds, output_pubkeys, tx3));
|
|
BOOST_CHECK(!tx3.vout[0].nValue.IsAmount());
|
|
BOOST_CHECK(!tx3.vout[1].nValue.IsAmount());
|
|
BOOST_CHECK(cache.VerifyAmounts(tx3, tx3.nTxFee));
|
|
|
|
CAmount unblinded_amount;
|
|
BOOST_CHECK(UnblindOutput(key2, tx3.vout[0], unblinded_amount, blind3) == 0);
|
|
BOOST_CHECK(UnblindOutput(key1, tx3.vout[0], unblinded_amount, blind3) == 1);
|
|
BOOST_CHECK(unblinded_amount == 100);
|
|
BOOST_CHECK(UnblindOutput(keyDummy, tx3.vout[1], unblinded_amount, blindDummy) == 1);
|
|
BOOST_CHECK(unblinded_amount == 0);
|
|
|
|
CCoinsModifier in3 = cache.ModifyCoins(ArithToUint256(3));
|
|
in3->vout.resize(2);
|
|
in3->vout[0] = tx3.vout[0];
|
|
in3->vout[1] = tx3.vout[1];
|
|
|
|
tx3.nTxFee--;
|
|
BOOST_CHECK(!cache.VerifyAmounts(tx3, tx3.nTxFee));
|
|
}
|
|
|
|
{
|
|
// Build a transactions that spends an unblinded (111) and blinded (100) coin, and produces only unblinded coins (impossible)
|
|
CMutableTransaction tx4;
|
|
tx4.vin.resize(2);
|
|
tx4.vin[0].prevout.hash = ArithToUint256(2);
|
|
tx4.vin[0].prevout.n = 0;
|
|
tx4.vin[1].prevout.hash = ArithToUint256(3);
|
|
tx4.vin[1].prevout.n = 0;
|
|
tx4.vout.resize(2);
|
|
tx4.vout[0].nValue = 30;
|
|
tx4.vout[1].nValue = 40;
|
|
tx4.nTxFee = 100 + 111 - 30 - 40;
|
|
BOOST_CHECK(!cache.VerifyAmounts(tx4, tx4.nTxFee)); // Spends a blinded coin with no blinded outputs to compensate.
|
|
|
|
std::vector<uint256> input_blinds;
|
|
std::vector<uint256> output_blinds;
|
|
std::vector<CPubKey> output_pubkeys;
|
|
input_blinds.push_back(uint256());
|
|
input_blinds.push_back(blind3);
|
|
output_blinds.push_back(uint256());
|
|
output_blinds.push_back(uint256());
|
|
output_pubkeys.push_back(CPubKey());
|
|
output_pubkeys.push_back(CPubKey());
|
|
BOOST_CHECK(!BlindOutputs(input_blinds, output_blinds, output_pubkeys, tx4)); // fails as there is no place to put the blinding factor
|
|
}
|
|
|
|
{
|
|
// Build a transactions that spends an unblinded (111) and blinded (100) coin, and produces a blinded (30), unblinded (40), and blinded (50) coin and fee (91)
|
|
CMutableTransaction tx4;
|
|
tx4.vin.resize(2);
|
|
tx4.vin[0].prevout.hash = ArithToUint256(2);
|
|
tx4.vin[0].prevout.n = 0;
|
|
tx4.vin[1].prevout.hash = ArithToUint256(3);
|
|
tx4.vin[1].prevout.n = 0;
|
|
tx4.vout.resize(3);
|
|
tx4.vout[0].nValue = 30;
|
|
tx4.vout[1].nValue = 40;
|
|
tx4.vout[2].nValue = 50;
|
|
tx4.nTxFee = 100 + 111 - 30 - 40 - 50;
|
|
BOOST_CHECK(!cache.VerifyAmounts(tx4, tx4.nTxFee)); // Spends a blinded coin with no blinded outputs to compensate.
|
|
|
|
std::vector<uint256> input_blinds;
|
|
std::vector<uint256> output_blinds;
|
|
std::vector<CPubKey> output_pubkeys;
|
|
input_blinds.push_back(uint256());
|
|
input_blinds.push_back(blind3);
|
|
output_blinds.push_back(uint256());
|
|
output_blinds.push_back(uint256());
|
|
output_blinds.push_back(uint256());
|
|
output_pubkeys.push_back(pubkey2);
|
|
output_pubkeys.push_back(CPubKey());
|
|
output_pubkeys.push_back(pubkey2);
|
|
BOOST_CHECK(BlindOutputs(input_blinds, output_blinds, output_pubkeys, tx4));
|
|
BOOST_CHECK(!tx4.vout[0].nValue.IsAmount());
|
|
BOOST_CHECK(tx4.vout[1].nValue.IsAmount());
|
|
BOOST_CHECK(!tx4.vout[2].nValue.IsAmount());
|
|
BOOST_CHECK(cache.VerifyAmounts(tx4, tx4.nTxFee));
|
|
|
|
CAmount unblinded_amount;
|
|
BOOST_CHECK(UnblindOutput(key1, tx4.vout[0], unblinded_amount, blind4) == 0);
|
|
BOOST_CHECK(UnblindOutput(key2, tx4.vout[0], unblinded_amount, blind4) == 1);
|
|
BOOST_CHECK(unblinded_amount == 30);
|
|
BOOST_CHECK(UnblindOutput(key2, tx4.vout[2], unblinded_amount, blind4) == 1);
|
|
BOOST_CHECK(unblinded_amount == 50);
|
|
|
|
CCoinsModifier in4 = cache.ModifyCoins(ArithToUint256(4));
|
|
in4->vout.resize(3);
|
|
in4->vout[0] = tx4.vout[0];
|
|
in4->vout[1] = tx4.vout[1];
|
|
in4->vout[2] = tx4.vout[2];
|
|
|
|
tx4.nTxFee--;
|
|
BOOST_CHECK(!cache.VerifyAmounts(tx4, tx4.nTxFee));
|
|
}
|
|
}
|
|
|
|
BOOST_AUTO_TEST_SUITE_END()
|