diff --git a/src/avalanche/proofbuilder.cpp b/src/avalanche/proofbuilder.cpp index 6e618e579..ceacc385f 100644 --- a/src/avalanche/proofbuilder.cpp +++ b/src/avalanche/proofbuilder.cpp @@ -1,67 +1,67 @@ // 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 #include namespace avalanche { SignedStake ProofBuilder::StakeSigner::sign(const ProofId &proofid) { const uint256 h = stake.getHash(proofid); 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; } Proof ProofBuilder::build() { const ProofId proofid = getProofId(); std::vector signedStakes; signedStakes.reserve(stakes.size()); while (!stakes.empty()) { auto handle = stakes.extract(stakes.begin()); signedStakes.push_back(handle.value().sign(proofid)); } - return Proof(sequence, expirationTime, std::move(master), + return Proof(sequence, expirationTime, masterKey.GetPubKey(), std::move(signedStakes)); } ProofId ProofBuilder::getProofId() const { CHashWriter ss(SER_GETHASH, 0); ss << sequence; ss << expirationTime; WriteCompactSize(ss, stakes.size()); for (const auto &s : stakes) { ss << s.stake; } CHashWriter ss2(SER_GETHASH, 0); ss2 << ss.GetHash(); - ss2 << master; + ss2 << masterKey.GetPubKey(); return ProofId(ss2.GetHash()); } } // namespace avalanche diff --git a/src/avalanche/proofbuilder.h b/src/avalanche/proofbuilder.h index 720c683ef..2de323346 100644 --- a/src/avalanche/proofbuilder.h +++ b/src/avalanche/proofbuilder.h @@ -1,57 +1,57 @@ // 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 #include #include namespace avalanche { struct TestProofBuilder; class ProofBuilder { uint64_t sequence; int64_t expirationTime; - CPubKey master; + CKey masterKey; struct StakeSigner { Stake stake; CKey key; StakeSigner(Stake stake_, CKey key_) : stake(std::move(stake_)), key(std::move(key_)) {} SignedStake sign(const ProofId &proofid); }; struct StakeSignerComparator { bool operator()(const StakeSigner &lhs, const StakeSigner &rhs) const { return lhs.stake.getId() < rhs.stake.getId(); } }; std::set stakes; public: - ProofBuilder(uint64_t sequence_, int64_t expirationTime_, CPubKey master_) + ProofBuilder(uint64_t sequence_, int64_t expirationTime_, CKey masterKey_) : sequence(sequence_), expirationTime(expirationTime_), - master(std::move(master_)) {} + masterKey(std::move(masterKey_)) {} [[nodiscard]] bool addUTXO(COutPoint utxo, Amount amount, uint32_t height, bool is_coinbase, CKey key); Proof build(); private: ProofId getProofId() const; friend struct TestProofBuilder; }; } // namespace avalanche #endif // BITCOIN_AVALANCHE_PROOFBUILDER_H diff --git a/src/avalanche/test/delegation_tests.cpp b/src/avalanche/test/delegation_tests.cpp index 54c497564..be613f542 100644 --- a/src/avalanche/test/delegation_tests.cpp +++ b/src/avalanche/test/delegation_tests.cpp @@ -1,198 +1,198 @@ // 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 #include #include #include #include #include #include #include #include using namespace avalanche; BOOST_FIXTURE_TEST_SUITE(delegation_tests, TestingSetup) static void CheckDelegation(const Delegation &dg, const Proof &p, const CPubKey &expected_pubkey) { DelegationState state; CPubKey pubkey; BOOST_CHECK(dg.verify(state, pubkey)); BOOST_CHECK(state.GetResult() == DelegationResult::NONE); BOOST_CHECK(pubkey == expected_pubkey); BOOST_CHECK(dg.getProofId() == p.getId()); } BOOST_AUTO_TEST_CASE(verify_random) { auto key = CKey::MakeCompressedKey(); - const Proof p = buildRandomProof(123456, key.GetPubKey()); + const Proof p = buildRandomProof(123456, key); DelegationBuilder dgb(p); { Delegation dg = dgb.build(); BOOST_CHECK_EQUAL(dg.getId(), p.getId()); CheckDelegation(dg, p, p.getMaster()); } auto l1key = CKey::MakeCompressedKey(); BOOST_CHECK(!dgb.addLevel(l1key, key.GetPubKey())); dgb.addLevel(key, l1key.GetPubKey()); CheckDelegation(dgb.build(), p, l1key.GetPubKey()); auto l2key = CKey::MakeCompressedKey(); BOOST_CHECK(!dgb.addLevel(key, l2key.GetPubKey())); BOOST_CHECK(!dgb.addLevel(l2key, l2key.GetPubKey())); dgb.addLevel(l1key, l2key.GetPubKey()); CheckDelegation(dgb.build(), p, l2key.GetPubKey()); } // Proof master priv: // L4J6gEE4wL9ji2EQbzS5dPMTTsw8LRvcMst1Utij4e3X5ccUSdqW // Proof master pub: // 023beefdde700a6bc02036335b4df141c8bc67bb05a971f5ac2745fd683797dde3 // Stake priv: // KydYrKDNsVnY5uhpLyC4UmazuJvUjNoKJhEEv9f1mdK1D5zcnMSM // Stake pub: // 02449fb5237efe8f647d32e8b64f06c22d1d40368eaca2a71ffc6a13ecc8bce680 // Level 1 priv: // KzzLLtiYiyFcTXPWUzywt2yEKk5FxkGbMfKhWgBd4oZdt8t8kk77 // Level 1 pub: // 03e49f9df52de2dea81cf7838b82521b69f2ea360f1c4eed9e6c89b7d0f9e645ef // Level 2 priv: // KwM6hV6hxZt3Kt4NHMtWQGH5T2SwhpyswodUQC2zmSjg6KWFWkQU // Level 2 pub: // 03aac52f4cfca700e7e9824298e0184755112e32f359c832f5f6ad2ef62a2c024a static Proof getProof() { Proof p; CDataStream stream( ParseHex( "0000000000000000ffffffff0000000021023beefdde700a6bc02036335b4df141" "c8bc67bb05a971f5ac2745fd683797dde301bee72758084395310b5a7ccc98a836" "11dff786f0a469d1d66626ba286b0423870000000000108dbe1c000000a4090000" "2102449fb5237efe8f647d32e8b64f06c22d1d40368eaca2a71ffc6a13ecc8bce6" "8069c539018ac799848811fb44a4b987faa71a634970d35976c5e766fb98502432" "aaec53034bd7df23767e7e695203599cf4a6a71569bdf03e90f0f91c8760faae"), SER_NETWORK, 0); stream >> p; BOOST_CHECK_EQUAL(p.getId(), ProofId::fromHex("afc74900c1f28b69e466461fb1e0663352da615" "3be0fcd59280e27f2446391d5")); BOOST_CHECK_EQUAL( p.getLimitedId(), LimitedProofId::fromHex("0d45ca55662c483107b45f5c5699e0d8c7778b2" "45c116cb988abba1afa6a1146")); return p; } struct TestVector { std::string name; std::string hex; std::string dgid; std::string pubkey; DelegationResult result; }; BOOST_AUTO_TEST_CASE(deserialization) { Proof p = getProof(); std::vector testcases{ {"Empty delegation", "46116afa1abaab88b96c115c248b77c7d8e099565c5fb40731482c6655ca450d21" "023beefdde700a6bc02036335b4df141c8bc67bb05a971f5ac2745fd683797dde3" "00", "afc74900c1f28b69e466461fb1e0663352da6153be0fcd59280e27f2446391d5", "023beefdde700a6bc02036335b4df141c8bc67bb05a971f5ac2745fd683797dde3", DelegationResult::NONE}, {"One delegation", "46116afa1abaab88b96c115c248b77c7d8e099565c5fb40731482c6655ca450d21" "023beefdde700a6bc02036335b4df141c8bc67bb05a971f5ac2745fd683797dde3" "012103e49f9df52de2dea81cf7838b82521b69f2ea360f1c4eed9e6c89b7d0f9e645e" "f7d51" "2ddbea7c88dcf38412b58374856a466e165797a69321c0928a89c64521f7e2e767c93" "de645ef5125ec901dcd51347787ca29771e7786bbe402d2d5ead0dc", "ffcd49dc98ebdbc90e731a7b0c89939bfe082f15f3aa82aca657176b83669185", "03e49f9df52de2dea81cf7838b82521b69f2ea360f1c4eed9e6c89b7d0f9e645ef", DelegationResult::NONE}, {"Two delegation", "46116afa1abaab88b96c115c248b77c7d8e099565c5fb40731482c6655ca450d21" "023beefdde700a6bc02036335b4df141c8bc67bb05a971f5ac2745fd683797dde3" "022103e49f9df52de2dea81cf7838b82521b69f2ea360f1c4eed9e6c89b7d0f9e645e" "f7d512ddbea7c88dcf38412b58374856a466e165797a69321c0928a89c64521f7e2e7" "67c93de645ef5125ec901dcd51347787ca29771e7786bbe402d2d5ead0dc2103aac52" "f4cfca700e7e9824298e0184755112e32f359c832f5f6ad2ef62a2c024a5cddd0ffe8" "4e12e4bf49e4c0af7c8548e618a24e12495d659f5ba75e114e1526a618aa305b1e69b" "f6ae20b2557999f2e3fec25d5f2271f8b9de0d06ba7344550", "a3f98e6b5ec330219493d109e5c11ed8e302315df4604b5462e9fb80cb0fde89", "03aac52f4cfca700e7e9824298e0184755112e32f359c832f5f6ad2ef62a2c024a", DelegationResult::NONE}, {"Invalid pubkey", "46116afa1abaab88b96c115c248b77c7d8e099565c5fb40731482c6655ca450d21" "023beefdde700a6bc02036335b4df141c8bc67bb05a971f5ac2745fd683797dde3012" "103e49f9df53de2dea81cf7838b82521b69f2ea360f1c4eed9e6c89b7d0f9e645ef7d" "512ddbea7c88dcf38412b58374856a466e165797a69321c0928a89c64521f7e2e767c" "93de645ef5125ec901dcd51347787ca29771e7786bbe402d2d5ead0dc", "af7e82716489c3cf3f361d449ed815112ff619f7fc34a4803bd958c68d1e2684", "023beefdde700a6bc02036335b4df141c8bc67bb05a971f5ac2745fd683797dde3", DelegationResult::INVALID_SIGNATURE}, {"Invalid signature", "46116afa1abaab88b96c115c248b77c7d8e099565c5fb40731482c6655ca450d21" "023beefdde700a6bc02036335b4df141c8bc67bb05a971f5ac2745fd683797dde3" "012103e49f9df52de2dea81cf7838b82521b69f2ea360f1c4eed9e6c89b7d0f9e645e" "f7d512ddbea7c88dcf38412c58374856a466e165797a69321c0928a89c64521f7e2e7" "67c93de645ef5125ec901dcd51347787ca29771e7786bbe402d2d5ead0dc", "ffcd49dc98ebdbc90e731a7b0c89939bfe082f15f3aa82aca657176b83669185", "023beefdde700a6bc02036335b4df141c8bc67bb05a971f5ac2745fd683797dde3", DelegationResult::INVALID_SIGNATURE}, {"Second invalid key", "46116afa1abaab88b96c115c248b77c7d8e099565c5fb40731482c6655ca450d21" "023beefdde700a6bc02036335b4df141c8bc67bb05a971f5ac2745fd683797dde3" "022103e49f9df52de2dea81cf7838b82521b69f2ea360f1c4eed9e6c89b7d0f9e645e" "f7d512ddbea7c88dcf38412b58374856a466e165797a69321c0928a89c64521f7e2e7" "67c93de645ef5125ec901dcd51347787ca29771e7786bbe402d2d5ead0dc2103aac52" "f4dfca700e7e9824298e0184755112e32f359c832f5f6ad2ef62a2c024a5cddd0ffe8" "4e12e4bf49e4c0af7c8548e618a24e12495d659f5ba75e114e1526a618aa305b1e69b" "f6ae20b2557999f2e3fec25d5f2271f8b9de0d06ba7344550", "b474512f71a3f5a6e94cc3b958fd658ece0d0632ace58c8c8f9f65c2b9ad5fad", "03e49f9df52de2dea81cf7838b82521b69f2ea360f1c4eed9e6c89b7d0f9e645ef", DelegationResult::INVALID_SIGNATURE}, {"Second invalid signature", "46116afa1abaab88b96c115c248b77c7d8e099565c5fb40731482c6655ca450d21" "023beefdde700a6bc02036335b4df141c8bc67bb05a971f5ac2745fd683797dde3" "022103e49f9df52de2dea81cf7838b82521b69f2ea360f1c4eed9e6c89b7d0f9e645e" "f7d512ddbea7c88dcf38412b58374856a466e165797a69321c0928a89c64521f7e2e7" "67c93de645ef5125ec901dcd51347787ca29771e7786bbe402d2d5ead0dc2103aac52" "f4cfca700e7e9824298e0184755112e32f359c832f5f6ad2ef62a2c024a5cddd0ffe8" "4e12e4bf49e4c0af7c8548e618a24e12495d659f5ba75e114e1526a618aa305b1e69b" "f6ae20b2557999f2e3fec25d5f2271f8b9de0d06ba7344551", "a3f98e6b5ec330219493d109e5c11ed8e302315df4604b5462e9fb80cb0fde89", "03e49f9df52de2dea81cf7838b82521b69f2ea360f1c4eed9e6c89b7d0f9e645ef", DelegationResult::INVALID_SIGNATURE}, }; for (auto &c : testcases) { CDataStream stream(ParseHex(c.hex), SER_NETWORK, 0); Delegation dg; stream >> dg; BOOST_CHECK_EQUAL(dg.getId(), DelegationId::fromHex(c.dgid)); DelegationState state; CPubKey pubkey; BOOST_CHECK_EQUAL(dg.verify(state, pubkey), c.result == DelegationResult::NONE); BOOST_CHECK(state.GetResult() == c.result); BOOST_CHECK(pubkey == CPubKey(ParseHex(c.pubkey))); } } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/avalanche/test/orphanproofpool_tests.cpp b/src/avalanche/test/orphanproofpool_tests.cpp index 47f639342..04db1577d 100644 --- a/src/avalanche/test/orphanproofpool_tests.cpp +++ b/src/avalanche/test/orphanproofpool_tests.cpp @@ -1,163 +1,163 @@ // Copyright (c) 2021 The Bitcoin developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include #include #include #include #include #include #include using namespace avalanche; BOOST_FIXTURE_TEST_SUITE(orphanproofpool_tests, TestingSetup) /** Make a proof with stakes using random txids */ static std::shared_ptr makeProof(const size_t nStakes) { const Amount v = 5 * COIN; const int height = 1234; - ProofBuilder pb(0, 0, CPubKey()); + ProofBuilder pb(0, 0, CKey::MakeCompressedKey()); for (size_t i = 0; i < nStakes; i++) { TxId txid(GetRandHash()); BOOST_CHECK(pb.addUTXO(COutPoint(txid, 0), v, height, false, CKey::MakeCompressedKey())); } return std::make_shared(pb.build()); } BOOST_AUTO_TEST_CASE(pool_starts_empty) { OrphanProofPool pool{10}; BOOST_CHECK_EQUAL(pool.getNProofs(), 0); BOOST_CHECK_EQUAL(pool.getNStakes(), 0); } BOOST_AUTO_TEST_CASE(fail_to_add_same_proof_twice) { OrphanProofPool pool{10}; auto p = makeProof(1); BOOST_CHECK(!pool.getProof(p->getId())); BOOST_CHECK(pool.addProof(p)); BOOST_CHECK_EQUAL(pool.getNStakes(), 1); BOOST_CHECK_EQUAL(pool.getNProofs(), 1); BOOST_CHECK(pool.getProof(p->getId())); BOOST_CHECK(!pool.addProof(p)); BOOST_CHECK_EQUAL(pool.getNStakes(), 1); BOOST_CHECK_EQUAL(pool.getNProofs(), 1); BOOST_CHECK(pool.getProof(p->getId())); } BOOST_AUTO_TEST_CASE(check_eviction_behavior) { { // Fill the pool OrphanProofPool pool{7}; auto first = makeProof(4); pool.addProof(first); pool.addProof(makeProof(2)); pool.addProof(makeProof(1)); BOOST_CHECK_EQUAL(pool.getNStakes(), 7); BOOST_CHECK_EQUAL(pool.getNProofs(), 3); BOOST_CHECK(pool.getProof(first->getId())); } { OrphanProofPool pool{6}; auto first = makeProof(4); pool.addProof(first); pool.addProof(makeProof(2)); BOOST_CHECK_EQUAL(pool.getNStakes(), 6); BOOST_CHECK_EQUAL(pool.getNProofs(), 2); // The oldest proof has to be dropped pool.addProof(makeProof(1)); BOOST_CHECK_EQUAL(pool.getNStakes(), 3); BOOST_CHECK_EQUAL(pool.getNProofs(), 2); BOOST_CHECK(!pool.getProof(first->getId())); } { OrphanProofPool pool{15}; auto first = makeProof(1); pool.addProof(first); auto second = makeProof(2); pool.addProof(second); pool.addProof(makeProof(4)); pool.addProof(makeProof(8)); BOOST_CHECK_EQUAL(pool.getNStakes(), 15); BOOST_CHECK_EQUAL(pool.getNProofs(), 4); // Multiple proofs are dropped if needed pool.addProof(makeProof(2)); BOOST_CHECK_EQUAL(pool.getNStakes(), 14); BOOST_CHECK_EQUAL(pool.getNProofs(), 3); BOOST_CHECK(!pool.getProof(first->getId())); BOOST_CHECK(!pool.getProof(second->getId())); } } BOOST_AUTO_TEST_CASE(remove_proofs) { OrphanProofPool pool{1337}; std::array aProofIds; // Add 10 proofs for (size_t i = 0; i < 10; i++) { auto p = makeProof(i + 1); aProofIds[i] = p->getId(); BOOST_CHECK(pool.addProof(p)); } BOOST_CHECK_EQUAL(pool.getNProofs(), 10); BOOST_CHECK_EQUAL(pool.getNStakes(), 55); // Remove a proof in the middle BOOST_CHECK(pool.removeProof(aProofIds[5])); BOOST_CHECK_EQUAL(pool.getNProofs(), 9); BOOST_CHECK_EQUAL(pool.getNStakes(), 49); // Remove a proof at the front BOOST_CHECK(pool.removeProof(aProofIds[0])); BOOST_CHECK_EQUAL(pool.getNProofs(), 8); BOOST_CHECK_EQUAL(pool.getNStakes(), 48); // Remove a proof at the back BOOST_CHECK(pool.removeProof(aProofIds[9])); BOOST_CHECK_EQUAL(pool.getNProofs(), 7); BOOST_CHECK_EQUAL(pool.getNStakes(), 38); // Fail to remove a proof that is longer in the pool BOOST_CHECK(!pool.removeProof(aProofIds[5])); BOOST_CHECK_EQUAL(pool.getNProofs(), 7); BOOST_CHECK_EQUAL(pool.getNStakes(), 38); // Fail to remove a proof that was never in the pool auto p = makeProof(11); BOOST_CHECK(!pool.getProof(p->getId())); BOOST_CHECK(!pool.removeProof(p->getId())); BOOST_CHECK_EQUAL(pool.getNProofs(), 7); BOOST_CHECK_EQUAL(pool.getNStakes(), 38); } BOOST_AUTO_TEST_CASE(add_proof_larger_than_pool) { OrphanProofPool pool{AVALANCHE_MAX_PROOF_STAKES - 1}; // Add a couple of small proofs BOOST_CHECK(pool.addProof(makeProof(1))); BOOST_CHECK_EQUAL(pool.getNStakes(), 1); BOOST_CHECK_EQUAL(pool.getNProofs(), 1); BOOST_CHECK(pool.addProof(makeProof(2))); BOOST_CHECK_EQUAL(pool.getNStakes(), 3); BOOST_CHECK_EQUAL(pool.getNProofs(), 2); // Adding a proof larger than the pool causes the pool to be emptied BOOST_CHECK(pool.addProof(makeProof(AVALANCHE_MAX_PROOF_STAKES))); BOOST_CHECK_EQUAL(pool.getNStakes(), 0); BOOST_CHECK_EQUAL(pool.getNProofs(), 0); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/avalanche/test/peermanager_tests.cpp b/src/avalanche/test/peermanager_tests.cpp index 8b041ddd6..2f6d679f7 100644 --- a/src/avalanche/test/peermanager_tests.cpp +++ b/src/avalanche/test/peermanager_tests.cpp @@ -1,797 +1,798 @@ // 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 #include #include #include #include