Changeset View
Changeset View
Standalone View
Standalone View
src/avalanche/test/proof_tests.cpp
// Copyright (c) 2020 The Bitcoin developers | // Copyright (c) 2020 The Bitcoin developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#include <avalanche/proof.h> | #include <avalanche/proof.h> | ||||
#include <avalanche/proofbuilder.h> | #include <avalanche/proofbuilder.h> | ||||
#include <avalanche/test/util.h> | #include <avalanche/test/util.h> | ||||
#include <avalanche/validation.h> | #include <avalanche/validation.h> | ||||
#include <blockindex.h> | |||||
#include <coins.h> | #include <coins.h> | ||||
#include <script/standard.h> | #include <script/standard.h> | ||||
#include <streams.h> | #include <streams.h> | ||||
#include <util/strencodings.h> | #include <util/strencodings.h> | ||||
#include <test/util/block_utils.h> | |||||
#include <test/util/setup_common.h> | #include <test/util/setup_common.h> | ||||
#include <boost/test/unit_test.hpp> | #include <boost/test/unit_test.hpp> | ||||
using namespace avalanche; | using namespace avalanche; | ||||
BOOST_FIXTURE_TEST_SUITE(proof_tests, TestingSetup) | BOOST_FIXTURE_TEST_SUITE(proof_tests, TestingSetup) | ||||
▲ Show 20 Lines • Show All 300 Lines • ▼ Show 20 Lines | for (auto &c : testcases) { | ||||
BOOST_TEST_MESSAGE(c.proofid); | BOOST_TEST_MESSAGE(c.proofid); | ||||
} | } | ||||
} | } | ||||
BOOST_AUTO_TEST_CASE(verify) { | BOOST_AUTO_TEST_CASE(verify) { | ||||
CCoinsView coinsDummy; | CCoinsView coinsDummy; | ||||
CCoinsViewCache coins(&coinsDummy); | CCoinsViewCache coins(&coinsDummy); | ||||
std::array<CBlockIndex, 12> blocks; | |||||
for (size_t i = 1; i < blocks.size(); ++i) { | |||||
blocks[i].pprev = &blocks[i - 1]; | |||||
} | |||||
CBlockIndex *pindex = &blocks.back(); | |||||
const int64_t MOCK_MTP{200000}; | |||||
SetMTP(blocks, MOCK_MTP); | |||||
CKey key; | CKey key; | ||||
key.MakeNewKey(true); | key.MakeNewKey(true); | ||||
const CPubKey pubkey = key.GetPubKey(); | const CPubKey pubkey = key.GetPubKey(); | ||||
const Amount value = 12345 * COIN; | const Amount value = 12345 * COIN; | ||||
const uint32_t height = 10; | const uint32_t height = 10; | ||||
COutPoint pkh_outpoint(TxId(InsecureRand256()), InsecureRand32()); | COutPoint pkh_outpoint(TxId(InsecureRand256()), InsecureRand32()); | ||||
CTxOut pkh_output(value, GetScriptForRawPubKey(pubkey)); | CTxOut pkh_output(value, GetScriptForRawPubKey(pubkey)); | ||||
coins.AddCoin(pkh_outpoint, Coin(pkh_output, height, false), false); | coins.AddCoin(pkh_outpoint, Coin(pkh_output, height, false), false); | ||||
COutPoint nonstd_outpoint(TxId(InsecureRand256()), InsecureRand32()); | COutPoint nonstd_outpoint(TxId(InsecureRand256()), InsecureRand32()); | ||||
CTxOut nonstd_output(value, CScript() << OP_TRUE); | CTxOut nonstd_output(value, CScript() << OP_TRUE); | ||||
coins.AddCoin(nonstd_outpoint, Coin(nonstd_output, height, false), false); | coins.AddCoin(nonstd_outpoint, Coin(nonstd_output, height, false), false); | ||||
COutPoint p2sh_outpoint(TxId(InsecureRand256()), InsecureRand32()); | COutPoint p2sh_outpoint(TxId(InsecureRand256()), InsecureRand32()); | ||||
CTxOut p2sh_output(value, | CTxOut p2sh_output(value, | ||||
GetScriptForDestination(ScriptHash(InsecureRand160()))); | GetScriptForDestination(ScriptHash(InsecureRand160()))); | ||||
coins.AddCoin(p2sh_outpoint, Coin(p2sh_output, height, false), false); | coins.AddCoin(p2sh_outpoint, Coin(p2sh_output, height, false), false); | ||||
const auto runCheck = [&](const ProofValidationResult result, | const auto runCheck = [&](const ProofValidationResult result, | ||||
const COutPoint &o, const Amount v, | const COutPoint &o, const Amount v, | ||||
const uint32_t h, const bool is_coinbase, | const uint32_t h, const bool is_coinbase, | ||||
const CKey &k) { | const CKey &k, int64_t expirationTime) { | ||||
// Generate a proof that match the UTXO. | // Generate a proof that match the UTXO. | ||||
ProofBuilder pb(0, 0, pubkey); | ProofBuilder pb(0, expirationTime, pubkey); | ||||
pb.addUTXO(o, v, h, is_coinbase, k); | pb.addUTXO(o, v, h, is_coinbase, k); | ||||
Proof p = pb.build(); | Proof p = pb.build(); | ||||
ProofValidationState state; | ProofValidationState state; | ||||
BOOST_CHECK(p.verify(state)); | BOOST_CHECK(p.verify(state)); | ||||
BOOST_CHECK(p.verify(state, coins) == | BOOST_CHECK(p.verify(state, coins, pindex) == | ||||
(result == ProofValidationResult::NONE)); | (result == ProofValidationResult::NONE)); | ||||
BOOST_CHECK(state.GetResult() == result); | BOOST_CHECK(state.GetResult() == result); | ||||
}; | }; | ||||
// Valid proof | // Valid proof | ||||
runCheck(ProofValidationResult::NONE, pkh_outpoint, value, height, false, | runCheck(ProofValidationResult::NONE, pkh_outpoint, value, height, false, | ||||
key); | key, MOCK_MTP + 1); | ||||
// Coinbase mismatch | // Coinbase mismatch | ||||
runCheck(ProofValidationResult::COINBASE_MISMATCH, pkh_outpoint, value, | runCheck(ProofValidationResult::COINBASE_MISMATCH, pkh_outpoint, value, | ||||
height, true, key); | height, true, key, MOCK_MTP + 1); | ||||
// Height mismatch | // Height mismatch | ||||
runCheck(ProofValidationResult::HEIGHT_MISMATCH, pkh_outpoint, value, | runCheck(ProofValidationResult::HEIGHT_MISMATCH, pkh_outpoint, value, | ||||
height + 1, false, key); | height + 1, false, key, MOCK_MTP + 1); | ||||
// Amount mismatch | // Amount mismatch | ||||
runCheck(ProofValidationResult::AMOUNT_MISMATCH, pkh_outpoint, | runCheck(ProofValidationResult::AMOUNT_MISMATCH, pkh_outpoint, | ||||
value + 1 * SATOSHI, height, false, key); | value + 1 * SATOSHI, height, false, key, MOCK_MTP + 1); | ||||
// Invalid outpoints | // Invalid outpoints | ||||
runCheck(ProofValidationResult::MISSING_UTXO, | runCheck(ProofValidationResult::MISSING_UTXO, | ||||
COutPoint(pkh_outpoint.GetTxId(), pkh_outpoint.GetN() + 1), value, | COutPoint(pkh_outpoint.GetTxId(), pkh_outpoint.GetN() + 1), value, | ||||
height, false, key); | height, false, key, MOCK_MTP + 1); | ||||
runCheck(ProofValidationResult::MISSING_UTXO, | runCheck(ProofValidationResult::MISSING_UTXO, | ||||
COutPoint(TxId(InsecureRand256()), pkh_outpoint.GetN()), value, | COutPoint(TxId(InsecureRand256()), pkh_outpoint.GetN()), value, | ||||
height, false, key); | height, false, key, MOCK_MTP + 1); | ||||
// Non standard script | // Non standard script | ||||
runCheck(ProofValidationResult::NON_STANDARD_DESTINATION, nonstd_outpoint, | runCheck(ProofValidationResult::NON_STANDARD_DESTINATION, nonstd_outpoint, | ||||
value, height, false, key); | value, height, false, key, MOCK_MTP + 1); | ||||
// Non PKHhash destination | // Non PKHhash destination | ||||
runCheck(ProofValidationResult::DESTINATION_NOT_SUPPORTED, p2sh_outpoint, | runCheck(ProofValidationResult::DESTINATION_NOT_SUPPORTED, p2sh_outpoint, | ||||
value, height, false, key); | value, height, false, key, MOCK_MTP + 1); | ||||
// Mismatching key | // Mismatching key | ||||
{ | { | ||||
CKey altkey; | CKey altkey; | ||||
altkey.MakeNewKey(true); | altkey.MakeNewKey(true); | ||||
runCheck(ProofValidationResult::DESTINATION_MISMATCH, pkh_outpoint, | runCheck(ProofValidationResult::DESTINATION_MISMATCH, pkh_outpoint, | ||||
value, height, false, altkey); | value, height, false, altkey, MOCK_MTP + 1); | ||||
} | } | ||||
// No stake | // No stake | ||||
{ | { | ||||
Proof p = ProofBuilder(0, 0, pubkey).build(); | Proof p = ProofBuilder(0, MOCK_MTP + 1, pubkey).build(); | ||||
ProofValidationState state; | ProofValidationState state; | ||||
BOOST_CHECK(!p.verify(state, coins)); | BOOST_CHECK(!p.verify(state, coins, pindex)); | ||||
BOOST_CHECK(state.GetResult() == ProofValidationResult::NO_STAKE); | BOOST_CHECK(state.GetResult() == ProofValidationResult::NO_STAKE); | ||||
} | } | ||||
// Dust thresold | // Dust thresold | ||||
{ | { | ||||
ProofBuilder pb(0, 0, pubkey); | ProofBuilder pb(0, 0, pubkey); | ||||
pb.addUTXO(pkh_outpoint, Amount::zero(), height, false, key); | pb.addUTXO(pkh_outpoint, Amount::zero(), height, false, key); | ||||
Proof p = pb.build(); | Proof p = pb.build(); | ||||
ProofValidationState state; | ProofValidationState state; | ||||
BOOST_CHECK(!p.verify(state, coins)); | BOOST_CHECK(!p.verify(state, coins, pindex)); | ||||
BOOST_CHECK(state.GetResult() == ProofValidationResult::DUST_THRESOLD); | BOOST_CHECK(state.GetResult() == ProofValidationResult::DUST_THRESOLD); | ||||
} | } | ||||
{ | { | ||||
ProofBuilder pb(0, 0, pubkey); | ProofBuilder pb(0, 0, pubkey); | ||||
pb.addUTXO(pkh_outpoint, PROOF_DUST_THRESHOLD - 1 * SATOSHI, height, | pb.addUTXO(pkh_outpoint, PROOF_DUST_THRESHOLD - 1 * SATOSHI, height, | ||||
false, key); | false, key); | ||||
Proof p = pb.build(); | Proof p = pb.build(); | ||||
ProofValidationState state; | ProofValidationState state; | ||||
BOOST_CHECK(!p.verify(state, coins)); | BOOST_CHECK(!p.verify(state, coins, pindex)); | ||||
BOOST_CHECK(state.GetResult() == ProofValidationResult::DUST_THRESOLD); | BOOST_CHECK(state.GetResult() == ProofValidationResult::DUST_THRESOLD); | ||||
} | } | ||||
// Duplicated input | // Duplicated input | ||||
{ | { | ||||
ProofBuilder pb(0, 0, pubkey); | ProofBuilder pb(0, 0, pubkey); | ||||
pb.addUTXO(pkh_outpoint, value, height, false, key); | pb.addUTXO(pkh_outpoint, value, height, false, key); | ||||
pb.addUTXO(pkh_outpoint, value, height, false, key); | pb.addUTXO(pkh_outpoint, value, height, false, key); | ||||
Proof p = pb.build(); | Proof p = pb.build(); | ||||
ProofValidationState state; | ProofValidationState state; | ||||
BOOST_CHECK(!p.verify(state, coins)); | BOOST_CHECK(!p.verify(state, coins, pindex)); | ||||
BOOST_CHECK(state.GetResult() == | BOOST_CHECK(state.GetResult() == | ||||
ProofValidationResult::DUPLICATE_STAKE); | ProofValidationResult::DUPLICATE_STAKE); | ||||
} | } | ||||
} | } | ||||
Fabien: Where is the expiration test ? | |||||
PiRKAuthorUnsubmitted Done Inline ActionsI will add one. I haven't finished fixed all the existing test, yet PiRK: I will add one. I haven't finished fixed all the existing test, yet | |||||
BOOST_AUTO_TEST_SUITE_END() | BOOST_AUTO_TEST_SUITE_END() |
Where is the expiration test ?