diff --git a/src/avalanche/peermanager.cpp b/src/avalanche/peermanager.cpp --- a/src/avalanche/peermanager.cpp +++ b/src/avalanche/peermanager.cpp @@ -229,9 +229,7 @@ // Check the proof's validity. ProofValidationState validationState; - if (!WITH_LOCK(cs_main, return proof->verify( - validationState, - chainman.ActiveChainstate().CoinsTip()))) { + if (!WITH_LOCK(cs_main, return proof->verify(validationState, chainman))) { if (isOrphanState(validationState)) { orphanProofPool.addProofIfPreferred(proof); if (orphanProofPool.countProofs() > AVALANCHE_MAX_ORPHAN_PROOFS) { @@ -464,10 +462,9 @@ { LOCK(cs_main); - const CCoinsViewCache &coins = chainman.ActiveChainstate().CoinsTip(); for (const auto &p : peers) { ProofValidationState state; - if (!p.proof->verify(state, coins)) { + if (!p.proof->verify(state, chainman)) { if (isOrphanState(state)) { newOrphans.push_back(p.proof); } diff --git a/src/avalanche/proof.h b/src/avalanche/proof.h --- a/src/avalanche/proof.h +++ b/src/avalanche/proof.h @@ -12,6 +12,7 @@ #include #include #include +#include // For ChainstateManager and cs_main #include #include @@ -19,7 +20,6 @@ #include class ArgsManager; -class CCoinsView; struct bilingual_str; /** @@ -189,7 +189,9 @@ Amount getStakedAmount() const; bool verify(ProofValidationState &state) const; - bool verify(ProofValidationState &state, const CCoinsView &view) const; + bool verify(ProofValidationState &state, + const ChainstateManager &chainman) const + EXCLUSIVE_LOCKS_REQUIRED(cs_main); }; using ProofRef = RCUPtr; diff --git a/src/avalanche/proof.cpp b/src/avalanche/proof.cpp --- a/src/avalanche/proof.cpp +++ b/src/avalanche/proof.cpp @@ -13,7 +13,6 @@ #include #include #include -#include // For g_chainman #include @@ -180,14 +179,15 @@ return true; } -bool Proof::verify(ProofValidationState &state, const CCoinsView &view) const { +bool Proof::verify(ProofValidationState &state, + const ChainstateManager &chainman) const { + AssertLockHeld(cs_main); if (!verify(state)) { // state is set by verify. return false; } - const int64_t activeHeight = - WITH_LOCK(cs_main, return g_chainman.ActiveHeight()); + const int64_t activeHeight = chainman.ActiveHeight(); const int64_t stakeUtxoMinConfirmations = gArgs.GetArg("-avaproofstakeutxoconfirmations", AVALANCHE_DEFAULT_STAKE_UTXO_CONFIRMATIONS); @@ -197,7 +197,7 @@ const COutPoint &utxo = s.getUTXO(); Coin coin; - if (!view.GetCoin(utxo, coin)) { + if (!chainman.ActiveChainstate().CoinsTip().GetCoin(utxo, coin)) { // The coins are not in the UTXO set. return state.Invalid(ProofValidationResult::MISSING_UTXO, "utxo-missing-or-spent"); diff --git a/src/avalanche/test/proof_tests.cpp b/src/avalanche/test/proof_tests.cpp --- a/src/avalanche/test/proof_tests.cpp +++ b/src/avalanche/test/proof_tests.cpp @@ -889,8 +889,6 @@ BOOST_AUTO_TEST_CASE(verify) { gArgs.ForceSetArg("-avaproofstakeutxoconfirmations", "1"); - CCoinsView coinsDummy; - CCoinsViewCache coins(&coinsDummy); auto key = CKey::MakeCompressedKey(); const CPubKey pubkey = key.GetPubKey(); @@ -899,6 +897,8 @@ const uint32_t height = 10; ChainstateManager &chainman = *Assert(m_node.chainman); + LOCK(cs_main); + CCoinsViewCache &coins = chainman.ActiveChainstate().CoinsTip(); COutPoint pkh_outpoint(TxId(InsecureRand256()), InsecureRand32()); CTxOut pkh_output(value, GetScriptForRawPubKey(pubkey)); @@ -924,7 +924,8 @@ ProofValidationState state; BOOST_CHECK(p->verify(state)); - BOOST_CHECK(p->verify(state, coins) == + LOCK(cs_main); + BOOST_CHECK(p->verify(state, chainman) == (result == ProofValidationResult::NONE)); BOOST_CHECK(state.GetResult() == result); }; @@ -972,7 +973,7 @@ ProofRef p = ProofBuilder(0, 0, key).build(); ProofValidationState state; - BOOST_CHECK(!p->verify(state, coins)); + BOOST_CHECK(!p->verify(state, chainman)); BOOST_CHECK(state.GetResult() == ProofValidationResult::NO_STAKE); } @@ -984,7 +985,7 @@ ProofRef p = pb.build(); ProofValidationState state; - BOOST_CHECK(!p->verify(state, coins)); + BOOST_CHECK(!p->verify(state, chainman)); BOOST_CHECK(state.GetResult() == ProofValidationResult::DUST_THRESHOLD); } @@ -995,7 +996,7 @@ ProofRef p = pb.build(); ProofValidationState state; - BOOST_CHECK(!p->verify(state, coins)); + BOOST_CHECK(!p->verify(state, chainman)); BOOST_CHECK(state.GetResult() == ProofValidationResult::DUST_THRESHOLD); } @@ -1006,7 +1007,7 @@ ProofRef p = TestProofBuilder::buildDuplicatedStakes(pb); ProofValidationState state; - BOOST_CHECK(!p->verify(state, coins)); + BOOST_CHECK(!p->verify(state, chainman)); BOOST_CHECK(state.GetResult() == ProofValidationResult::DUPLICATE_STAKE); } @@ -1024,7 +1025,7 @@ ProofRef p = TestProofBuilder::buildWithReversedOrderStakes(pb); ProofValidationState state; - BOOST_CHECK(!p->verify(state, coins)); + BOOST_CHECK(!p->verify(state, chainman)); BOOST_CHECK(state.GetResult() == ProofValidationResult::WRONG_STAKE_ORDERING); } @@ -1080,9 +1081,6 @@ } BOOST_AUTO_TEST_CASE(deterministic_proofid) { - CCoinsView coinsDummy; - CCoinsViewCache coins(&coinsDummy); - auto key = CKey::MakeCompressedKey(); const Amount value = 12345 * COIN; diff --git a/src/rpc/avalanche.cpp b/src/rpc/avalanche.cpp --- a/src/rpc/avalanche.cpp +++ b/src/rpc/avalanche.cpp @@ -85,8 +85,7 @@ avalanche::ProofValidationState state; { LOCK(cs_main); - if (!proof.verify(state, - node.chainman->ActiveChainstate().CoinsTip())) { + if (!proof.verify(state, *Assert(node.chainman))) { throw JSONRPCError(RPC_INVALID_PARAMETER, "The proof is invalid: " + state.ToString()); }