diff --git a/src/avalanche/proofbuilder.cpp b/src/avalanche/proofbuilder.cpp index 1144496bc..d7e9ac370 100644 --- a/src/avalanche/proofbuilder.cpp +++ b/src/avalanche/proofbuilder.cpp @@ -1,83 +1,72 @@ // Copyright (c) 2020 The Bitcoin developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <avalanche/proofbuilder.h> #include <random.h> #include <util/system.h> namespace avalanche { -SignedStake ProofBuilder::StakeSigner::sign(const StakeCommitment &commitment) { - const uint256 h = stake.getHash(commitment); - - SchnorrSig sig; - if (!key.SignSchnorr(h, sig)) { - sig.fill(0); - } - - return SignedStake(std::move(stake), std::move(sig)); -} - bool ProofBuilder::addUTXO(COutPoint utxo, Amount amount, uint32_t height, bool is_coinbase, CKey key) { if (!key.IsValid()) { return false; } - return stakes - .emplace(Stake(std::move(utxo), amount, height, is_coinbase, - key.GetPubKey()), - std::move(key)) - .second; + const StakeCommitment commitment(getProofId(), expirationTime, + masterKey.GetPubKey()); + auto stake = + Stake(std::move(utxo), amount, height, is_coinbase, key.GetPubKey()); + const uint256 h = stake.getHash(commitment); + SchnorrSig sig; + if (!key.SignSchnorr(h, sig)) { + sig.fill(0); + } + + return stakes.emplace(std::move(stake), std::move(sig)).second; } ProofRef ProofBuilder::build() { SchnorrSig proofSignature; const LimitedProofId limitedProofId = getLimitedProofId(); if (!masterKey.SignSchnorr(limitedProofId, proofSignature)) { proofSignature.fill(0); } - - const ProofId proofid = getProofId(); - - const StakeCommitment commitment(proofid, expirationTime, - masterKey.GetPubKey()); - std::vector<SignedStake> signedStakes; signedStakes.reserve(stakes.size()); while (!stakes.empty()) { auto handle = stakes.extract(stakes.begin()); - signedStakes.push_back(handle.value().sign(commitment)); + signedStakes.push_back(handle.value()); } return ProofRef::make(sequence, expirationTime, masterKey.GetPubKey(), std::move(signedStakes), payoutScriptPubKey, std::move(proofSignature)); } LimitedProofId ProofBuilder::getLimitedProofId() const { CHashWriter ss(SER_GETHASH, 0); ss << sequence; ss << expirationTime; ss << payoutScriptPubKey; WriteCompactSize(ss, stakes.size()); for (const auto &s : stakes) { - ss << s.stake; + ss << s.getStake(); } return LimitedProofId(ss.GetHash()); } ProofId ProofBuilder::getProofId() const { CHashWriter ss(SER_GETHASH, 0); ss << getLimitedProofId(); ss << masterKey.GetPubKey(); return ProofId(ss.GetHash()); } } // namespace avalanche diff --git a/src/avalanche/proofbuilder.h b/src/avalanche/proofbuilder.h index a023dd862..b9afc7157 100644 --- a/src/avalanche/proofbuilder.h +++ b/src/avalanche/proofbuilder.h @@ -1,61 +1,51 @@ // Copyright (c) 2020 The Bitcoin developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_AVALANCHE_PROOFBUILDER_H #define BITCOIN_AVALANCHE_PROOFBUILDER_H #include <avalanche/proof.h> #include <key.h> #include <cstdio> namespace avalanche { struct TestProofBuilder; class ProofBuilder { uint64_t sequence; int64_t expirationTime; CKey masterKey; CScript payoutScriptPubKey; - struct StakeSigner { - Stake stake; - CKey key; - - StakeSigner(Stake stake_, CKey key_) - : stake(std::move(stake_)), key(std::move(key_)) {} - - SignedStake sign(const StakeCommitment &commitment); - }; - - struct StakeSignerComparator { - bool operator()(const StakeSigner &lhs, const StakeSigner &rhs) const { - return lhs.stake.getId() < rhs.stake.getId(); + struct SignedStakeComparator { + bool operator()(const SignedStake &lhs, const SignedStake &rhs) const { + return lhs.getStake().getId() < rhs.getStake().getId(); } }; - std::set<StakeSigner, StakeSignerComparator> stakes; + std::set<SignedStake, SignedStakeComparator> stakes; public: ProofBuilder(uint64_t sequence_, int64_t expirationTime_, CKey masterKey_, const CScript &payoutScriptPubKey_) : sequence(sequence_), expirationTime(expirationTime_), masterKey(std::move(masterKey_)), payoutScriptPubKey(payoutScriptPubKey_) {} [[nodiscard]] bool addUTXO(COutPoint utxo, Amount amount, uint32_t height, bool is_coinbase, CKey key); ProofRef build(); private: LimitedProofId getLimitedProofId() const; ProofId getProofId() const; friend struct TestProofBuilder; }; } // namespace avalanche #endif // BITCOIN_AVALANCHE_PROOFBUILDER_H diff --git a/src/avalanche/test/util.cpp b/src/avalanche/test/util.cpp index a5e119b53..a5bef5cf4 100644 --- a/src/avalanche/test/util.cpp +++ b/src/avalanche/test/util.cpp @@ -1,134 +1,134 @@ // Copyright (c) 2020 The Bitcoin developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <amount.h> #include <avalanche/proofbuilder.h> #include <avalanche/test/util.h> #include <key.h> #include <primitives/transaction.h> #include <random.h> #include <script/standard.h> #include <validation.h> #include <boost/test/unit_test.hpp> #include <limits> namespace avalanche { ProofRef buildRandomProof(CChainState &active_chainstate, uint32_t score, int height, const CKey &masterKey) { auto key = CKey::MakeCompressedKey(); const COutPoint o(TxId(GetRandHash()), 0); const Amount v = (int64_t(score) * COIN) / 100; const bool is_coinbase = false; { CScript script = GetScriptForDestination(PKHash(key.GetPubKey())); LOCK(cs_main); CCoinsViewCache &coins = active_chainstate.CoinsTip(); coins.AddCoin(o, Coin(CTxOut(v, script), height, is_coinbase), false); } ProofBuilder pb(0, std::numeric_limits<uint32_t>::max(), masterKey, UNSPENDABLE_ECREG_PAYOUT_SCRIPT); BOOST_CHECK(pb.addUTXO(o, v, height, is_coinbase, std::move(key))); return pb.build(); } bool hasDustStake(const ProofRef &proof) { for (const SignedStake &s : proof->getStakes()) { if (s.getStake().getAmount() < PROOF_DUST_THRESHOLD) { return true; } } return false; } LimitedProofId TestProofBuilder::getReverseOrderLimitedProofId(ProofBuilder &pb) { CHashWriter ss(SER_GETHASH, 0); ss << pb.sequence; ss << pb.expirationTime; ss << pb.payoutScriptPubKey; WriteCompactSize(ss, pb.stakes.size()); for (auto it = pb.stakes.rbegin(); it != pb.stakes.rend(); it++) { - ss << it->stake; + ss << it->getStake(); } return LimitedProofId(ss.GetHash()); } ProofRef TestProofBuilder::buildWithReversedOrderStakes(ProofBuilder &pb) { const LimitedProofId limitedProofid = TestProofBuilder::getReverseOrderLimitedProofId(pb); const CPubKey masterPubKey = pb.masterKey.GetPubKey(); const StakeCommitment commitment( limitedProofid.computeProofId(masterPubKey), pb.expirationTime, pb.masterKey.GetPubKey()); std::vector<SignedStake> signedStakes; signedStakes.reserve(pb.stakes.size()); while (!pb.stakes.empty()) { // We need a forward iterator, so pb.stakes.rbegin() is not an // option. auto handle = pb.stakes.extract(std::prev(pb.stakes.end())); - signedStakes.push_back(handle.value().sign(commitment)); + signedStakes.push_back(handle.value()); } SchnorrSig proofSignature; BOOST_CHECK(pb.masterKey.SignSchnorr(limitedProofid, proofSignature)); return ProofRef::make(pb.sequence, pb.expirationTime, masterPubKey, std::move(signedStakes), pb.payoutScriptPubKey, proofSignature); } LimitedProofId TestProofBuilder::getDuplicatedStakeLimitedProofId(ProofBuilder &pb) { CHashWriter ss(SER_GETHASH, 0); ss << pb.sequence; ss << pb.expirationTime; ss << pb.payoutScriptPubKey; WriteCompactSize(ss, 2 * pb.stakes.size()); for (auto &s : pb.stakes) { - ss << s.stake; - ss << s.stake; + ss << s.getStake(); + ss << s.getStake(); } return LimitedProofId(ss.GetHash()); } ProofRef TestProofBuilder::buildDuplicatedStakes(ProofBuilder &pb) { const LimitedProofId limitedProofid = TestProofBuilder::getDuplicatedStakeLimitedProofId(pb); const CPubKey masterPubKey = pb.masterKey.GetPubKey(); const StakeCommitment commitment( limitedProofid.computeProofId(masterPubKey), pb.expirationTime, pb.masterKey.GetPubKey()); std::vector<SignedStake> signedStakes; signedStakes.reserve(2 * pb.stakes.size()); while (!pb.stakes.empty()) { auto handle = pb.stakes.extract(pb.stakes.begin()); - SignedStake signedStake = handle.value().sign(commitment); + SignedStake signedStake = handle.value(); signedStakes.push_back(signedStake); signedStakes.push_back(signedStake); } SchnorrSig proofSignature; BOOST_CHECK(pb.masterKey.SignSchnorr(limitedProofid, proofSignature)); return ProofRef::make(pb.sequence, pb.expirationTime, masterPubKey, std::move(signedStakes), pb.payoutScriptPubKey, proofSignature); } } // namespace avalanche