Changeset View
Changeset View
Standalone View
Standalone View
src/avalanche/test/proof_tests.cpp
Show All 18 Lines | |||||
using namespace avalanche; | using namespace avalanche; | ||||
BOOST_FIXTURE_TEST_SUITE(proof_tests, TestChain100Setup) | BOOST_FIXTURE_TEST_SUITE(proof_tests, TestChain100Setup) | ||||
BOOST_AUTO_TEST_CASE(proof_random) { | BOOST_AUTO_TEST_CASE(proof_random) { | ||||
CChainState &active_chainstate = | CChainState &active_chainstate = | ||||
Assert(m_node.chainman)->ActiveChainstate(); | Assert(m_node.chainman)->ActiveChainstate(); | ||||
ProofParams proofParams; | |||||
for (int i = 0; i < 1000; i++) { | for (int i = 0; i < 1000; i++) { | ||||
const uint32_t score = InsecureRand32(); | const uint32_t score = InsecureRand32(); | ||||
auto p = buildRandomProof(active_chainstate, score); | auto p = buildRandomProof(active_chainstate, score); | ||||
BOOST_CHECK_EQUAL(p->getScore(), score); | BOOST_CHECK_EQUAL(p->getScore(), score); | ||||
ProofValidationResult expected_state = | ProofValidationResult expected_state = | ||||
hasDustStake(p) ? ProofValidationResult::DUST_THRESHOLD | hasDustStake(p) ? ProofValidationResult::DUST_THRESHOLD | ||||
: ProofValidationResult::NONE; | : ProofValidationResult::NONE; | ||||
ProofValidationState state; | ProofValidationState state; | ||||
BOOST_CHECK_EQUAL(p->verify(state), | BOOST_CHECK_EQUAL(p->verify(proofParams, state), | ||||
state.GetResult() == ProofValidationResult::NONE); | state.GetResult() == ProofValidationResult::NONE); | ||||
BOOST_CHECK(state.GetResult() == expected_state); | BOOST_CHECK(state.GetResult() == expected_state); | ||||
} | } | ||||
} | } | ||||
BOOST_AUTO_TEST_CASE(proofbuilder) { | BOOST_AUTO_TEST_CASE(proofbuilder) { | ||||
// Master key. | ProofParams proofParams; | ||||
auto key = CKey::MakeCompressedKey(); | auto key = CKey::MakeCompressedKey(); | ||||
const CPubKey master = key.GetPubKey(); | const CPubKey master = key.GetPubKey(); | ||||
const uint64_t sequence = InsecureRandBits(64); | const uint64_t sequence = InsecureRandBits(64); | ||||
const int64_t expiration = InsecureRandBits(64); | const int64_t expiration = InsecureRandBits(64); | ||||
ProofBuilder pb(sequence, expiration, key); | ProofBuilder pb(sequence, expiration, key); | ||||
for (int i = 0; i < 3; i++) { | for (int i = 0; i < 3; i++) { | ||||
key.MakeNewKey(true); | key.MakeNewKey(true); | ||||
BOOST_CHECK(pb.addUTXO(COutPoint(TxId(GetRandHash()), InsecureRand32()), | BOOST_CHECK(pb.addUTXO(COutPoint(TxId(GetRandHash()), InsecureRand32()), | ||||
int64_t(InsecureRand32()) * COIN / 100, | int64_t(InsecureRand32()) * COIN / 100, | ||||
InsecureRand32(), InsecureRandBool(), key)); | InsecureRand32(), InsecureRandBool(), key)); | ||||
} | } | ||||
ProofRef p = pb.build(); | ProofRef p = pb.build(); | ||||
ProofValidationState state; | ProofValidationState state; | ||||
BOOST_CHECK(p->verify(state)); | BOOST_CHECK(p->verify(proofParams, state)); | ||||
BOOST_CHECK_EQUAL(p->getSequence(), sequence); | BOOST_CHECK_EQUAL(p->getSequence(), sequence); | ||||
BOOST_CHECK_EQUAL(p->getExpirationTime(), expiration); | BOOST_CHECK_EQUAL(p->getExpirationTime(), expiration); | ||||
BOOST_CHECK(p->getMaster() == master); | BOOST_CHECK(p->getMaster() == master); | ||||
BOOST_CHECK(state.GetResult() == ProofValidationResult::NONE); | BOOST_CHECK(state.GetResult() == ProofValidationResult::NONE); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 784 Lines • ▼ Show 20 Lines | std::vector<TestVector> regularFormatTestCases{ | ||||
"023beefdde700a6bc02036335b4df141c8bc67bb05a971f5ac2745fd683797dde3ac9" | "023beefdde700a6bc02036335b4df141c8bc67bb05a971f5ac2745fd683797dde3ac9" | ||||
"32ce54c4d405de52399cf48b4b10038d1bbbd65206f0934b2bdfc7b6a4a2e1cff1803" | "32ce54c4d405de52399cf48b4b10038d1bbbd65206f0934b2bdfc7b6a4a2e1cff1803" | ||||
"a69bd03dd3897d4cfde46c2ee2cf17895880770c8b49089a26b6b5ff1e", | "a69bd03dd3897d4cfde46c2ee2cf17895880770c8b49089a26b6b5ff1e", | ||||
ProofId::fromHex("96bd9fee759d81f9bc30e26015d979df3f6046c7a8764582d1a2" | ProofId::fromHex("96bd9fee759d81f9bc30e26015d979df3f6046c7a8764582d1a2" | ||||
"c5c3d61c2f44"), | "c5c3d61c2f44"), | ||||
2 * 444638638, ProofValidationResult::NONE}, | 2 * 444638638, ProofValidationResult::NONE}, | ||||
}; | }; | ||||
ProofParams proofParams; | |||||
auto checkCases = [&](const std::vector<TestVector> &testcases) { | auto checkCases = [&](const std::vector<TestVector> &testcases) { | ||||
for (auto &c : testcases) { | for (auto &c : testcases) { | ||||
Proof p; | Proof p; | ||||
bilingual_str error; | bilingual_str error; | ||||
BOOST_CHECK(Proof::FromHex(p, c.hex, error)); | BOOST_CHECK(Proof::FromHex(p, c.hex, error)); | ||||
BOOST_CHECK_EQUAL(p.getId(), c.proofid); | BOOST_CHECK_EQUAL(p.getId(), c.proofid); | ||||
BOOST_CHECK_EQUAL(p.getScore(), c.score); | BOOST_CHECK_EQUAL(p.getScore(), c.score); | ||||
ProofValidationState state; | ProofValidationState state; | ||||
BOOST_CHECK_EQUAL(p.verify(state), | BOOST_CHECK_EQUAL(p.verify(proofParams, state), | ||||
c.result == ProofValidationResult::NONE); | c.result == ProofValidationResult::NONE); | ||||
BOOST_CHECK(state.GetResult() == c.result); | BOOST_CHECK(state.GetResult() == c.result); | ||||
BOOST_TEST_MESSAGE(c.proofid); | BOOST_TEST_MESSAGE(c.proofid); | ||||
} | } | ||||
}; | }; | ||||
gArgs.ForceSetArg("-legacyavaproof", "1"); | gArgs.ForceSetArg("-legacyavaproof", "1"); | ||||
BOOST_CHECK(Proof::useLegacy(gArgs)); | BOOST_CHECK(Proof::useLegacy(gArgs)); | ||||
checkCases(legacyFormatTestCases); | checkCases(legacyFormatTestCases); | ||||
gArgs.ForceSetArg("-legacyavaproof", "0"); | gArgs.ForceSetArg("-legacyavaproof", "0"); | ||||
BOOST_CHECK(!Proof::useLegacy(gArgs)); | BOOST_CHECK(!Proof::useLegacy(gArgs)); | ||||
checkCases(regularFormatTestCases); | checkCases(regularFormatTestCases); | ||||
gArgs.ClearForcedArg("-legacyavaproof"); | gArgs.ClearForcedArg("-legacyavaproof"); | ||||
} | } | ||||
BOOST_AUTO_TEST_CASE(verify) { | BOOST_AUTO_TEST_CASE(verify) { | ||||
gArgs.ForceSetArg("-avaproofstakeutxoconfirmations", "1"); | gArgs.ForceSetArg("-avaproofstakeutxoconfirmations", "1"); | ||||
ProofParams proofParams; | |||||
auto key = CKey::MakeCompressedKey(); | auto key = CKey::MakeCompressedKey(); | ||||
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; | ||||
ChainstateManager &chainman = *Assert(m_node.chainman); | ChainstateManager &chainman = *Assert(m_node.chainman); | ||||
Show All 18 Lines | const auto runCheck = [&](const ProofValidationResult result, | ||||
const uint32_t h, const bool is_coinbase, | const uint32_t h, const bool is_coinbase, | ||||
const CKey &k) { | const CKey &k) { | ||||
// Generate a proof that match the UTXO. | // Generate a proof that match the UTXO. | ||||
ProofBuilder pb(0, 0, key); | ProofBuilder pb(0, 0, key); | ||||
BOOST_CHECK(pb.addUTXO(o, v, h, is_coinbase, k)); | BOOST_CHECK(pb.addUTXO(o, v, h, is_coinbase, k)); | ||||
ProofRef p = pb.build(); | ProofRef p = pb.build(); | ||||
ProofValidationState state; | ProofValidationState state; | ||||
BOOST_CHECK(p->verify(state)); | BOOST_CHECK(p->verify(proofParams, state)); | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
BOOST_CHECK(p->verify(state, chainman) == | BOOST_CHECK(p->verify(proofParams, state, chainman) == | ||||
(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); | ||||
Show All 31 Lines | // Mismatching key | ||||
value, height, false, CKey::MakeCompressedKey()); | value, height, false, CKey::MakeCompressedKey()); | ||||
} | } | ||||
// No stake | // No stake | ||||
{ | { | ||||
ProofRef p = ProofBuilder(0, 0, key).build(); | ProofRef p = ProofBuilder(0, 0, key).build(); | ||||
ProofValidationState state; | ProofValidationState state; | ||||
BOOST_CHECK(!p->verify(state, chainman)); | BOOST_CHECK(!p->verify(proofParams, state, chainman)); | ||||
BOOST_CHECK(state.GetResult() == ProofValidationResult::NO_STAKE); | BOOST_CHECK(state.GetResult() == ProofValidationResult::NO_STAKE); | ||||
} | } | ||||
// Dust thresold | // Dust thresold | ||||
{ | { | ||||
ProofBuilder pb(0, 0, key); | ProofBuilder pb(0, 0, key); | ||||
BOOST_CHECK( | BOOST_CHECK( | ||||
pb.addUTXO(pkh_outpoint, Amount::zero(), height, false, key)); | pb.addUTXO(pkh_outpoint, Amount::zero(), height, false, key)); | ||||
ProofRef p = pb.build(); | ProofRef p = pb.build(); | ||||
ProofValidationState state; | ProofValidationState state; | ||||
BOOST_CHECK(!p->verify(state, chainman)); | BOOST_CHECK(!p->verify(proofParams, state, chainman)); | ||||
BOOST_CHECK(state.GetResult() == ProofValidationResult::DUST_THRESHOLD); | BOOST_CHECK(state.GetResult() == ProofValidationResult::DUST_THRESHOLD); | ||||
} | } | ||||
{ | { | ||||
ProofBuilder pb(0, 0, key); | ProofBuilder pb(0, 0, key); | ||||
BOOST_CHECK(pb.addUTXO(pkh_outpoint, PROOF_DUST_THRESHOLD - 1 * SATOSHI, | BOOST_CHECK(pb.addUTXO(pkh_outpoint, PROOF_DUST_THRESHOLD - 1 * SATOSHI, | ||||
height, false, key)); | height, false, key)); | ||||
ProofRef p = pb.build(); | ProofRef p = pb.build(); | ||||
ProofValidationState state; | ProofValidationState state; | ||||
BOOST_CHECK(!p->verify(state, chainman)); | BOOST_CHECK(!p->verify(proofParams, state, chainman)); | ||||
BOOST_CHECK(state.GetResult() == ProofValidationResult::DUST_THRESHOLD); | BOOST_CHECK(state.GetResult() == ProofValidationResult::DUST_THRESHOLD); | ||||
} | } | ||||
// Duplicated input | // Duplicated input | ||||
{ | { | ||||
ProofBuilder pb(0, 0, key); | ProofBuilder pb(0, 0, key); | ||||
BOOST_CHECK(pb.addUTXO(pkh_outpoint, value, height, false, key)); | BOOST_CHECK(pb.addUTXO(pkh_outpoint, value, height, false, key)); | ||||
ProofRef p = TestProofBuilder::buildDuplicatedStakes(pb); | ProofRef p = TestProofBuilder::buildDuplicatedStakes(pb); | ||||
ProofValidationState state; | ProofValidationState state; | ||||
BOOST_CHECK(!p->verify(state, chainman)); | BOOST_CHECK(!p->verify(proofParams, state, chainman)); | ||||
BOOST_CHECK(state.GetResult() == | BOOST_CHECK(state.GetResult() == | ||||
ProofValidationResult::DUPLICATE_STAKE); | ProofValidationResult::DUPLICATE_STAKE); | ||||
} | } | ||||
// Wrong stake ordering | // Wrong stake ordering | ||||
{ | { | ||||
COutPoint other_pkh_outpoint(TxId(InsecureRand256()), InsecureRand32()); | COutPoint other_pkh_outpoint(TxId(InsecureRand256()), InsecureRand32()); | ||||
CTxOut other_pkh_output(value, GetScriptForRawPubKey(pubkey)); | CTxOut other_pkh_output(value, GetScriptForRawPubKey(pubkey)); | ||||
coins.AddCoin(other_pkh_outpoint, Coin(other_pkh_output, height, false), | coins.AddCoin(other_pkh_outpoint, Coin(other_pkh_output, height, false), | ||||
false); | false); | ||||
ProofBuilder pb(0, 0, key); | ProofBuilder pb(0, 0, key); | ||||
BOOST_CHECK(pb.addUTXO(pkh_outpoint, value, height, false, key)); | BOOST_CHECK(pb.addUTXO(pkh_outpoint, value, height, false, key)); | ||||
BOOST_CHECK(pb.addUTXO(other_pkh_outpoint, value, height, false, key)); | BOOST_CHECK(pb.addUTXO(other_pkh_outpoint, value, height, false, key)); | ||||
ProofRef p = TestProofBuilder::buildWithReversedOrderStakes(pb); | ProofRef p = TestProofBuilder::buildWithReversedOrderStakes(pb); | ||||
ProofValidationState state; | ProofValidationState state; | ||||
BOOST_CHECK(!p->verify(state, chainman)); | BOOST_CHECK(!p->verify(proofParams, state, chainman)); | ||||
BOOST_CHECK(state.GetResult() == | BOOST_CHECK(state.GetResult() == | ||||
ProofValidationResult::WRONG_STAKE_ORDERING); | ProofValidationResult::WRONG_STAKE_ORDERING); | ||||
} | } | ||||
// Immature stake | // Immature stake | ||||
{ | { | ||||
uint32_t chaintipHeight = chainman.ActiveHeight(); | uint32_t chaintipHeight = chainman.ActiveHeight(); | ||||
▲ Show 20 Lines • Show All 93 Lines • Show Last 20 Lines |