banman: save the banlist in a JSON format on disk

Save the banlist in `banlist.json` instead of `banlist.dat`.

This makes it possible to store Tor v3 entries in the banlist on disk
(and any other addresses that cannot be serialized in addrv1 format).

Only read `banlist.dat` if it exists and `banlist.json` does not
exist (first start after an upgrade).

Supersedes https://github.com/bitcoin/bitcoin/pull/20904
Resolves https://github.com/bitcoin/bitcoin/issues/19748
This commit is contained in:
Vasil Dimov
2021-01-14 09:33:04 +01:00
parent 6a67366fdc
commit d197977ae2
9 changed files with 170 additions and 39 deletions

View File

@@ -191,7 +191,7 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
BOOST_AUTO_TEST_CASE(peer_discouragement)
{
const CChainParams& chainparams = Params();
auto banman = std::make_unique<BanMan>(m_args.GetDataDirBase() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
auto banman = std::make_unique<BanMan>(m_args.GetDataDirBase() / "banlist", nullptr, DEFAULT_MISBEHAVING_BANTIME);
auto connman = std::make_unique<ConnmanTestMsg>(0x1337, 0x1337, *m_node.addrman);
auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, banman.get(),
*m_node.scheduler, *m_node.chainman, *m_node.mempool, false);
@@ -285,7 +285,7 @@ BOOST_AUTO_TEST_CASE(peer_discouragement)
BOOST_AUTO_TEST_CASE(DoS_bantime)
{
const CChainParams& chainparams = Params();
auto banman = std::make_unique<BanMan>(m_args.GetDataDirBase() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
auto banman = std::make_unique<BanMan>(m_args.GetDataDirBase() / "banlist", nullptr, DEFAULT_MISBEHAVING_BANTIME);
auto connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman);
auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, banman.get(),
*m_node.scheduler, *m_node.chainman, *m_node.mempool, false);

View File

@@ -9,8 +9,10 @@
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
#include <test/util/setup_common.h>
#include <util/readwritefile.h>
#include <util/system.h>
#include <cassert>
#include <cstdint>
#include <limits>
#include <string>
@@ -38,8 +40,20 @@ FUZZ_TARGET_INIT(banman, initialize_banman)
int limit_max_ops{300};
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
SetMockTime(ConsumeTime(fuzzed_data_provider));
const fs::path banlist_file = gArgs.GetDataDirNet() / "fuzzed_banlist.dat";
fs::remove(banlist_file);
fs::path banlist_file = gArgs.GetDataDirNet() / "fuzzed_banlist";
const bool start_with_corrupted_banlist{fuzzed_data_provider.ConsumeBool()};
if (start_with_corrupted_banlist) {
const std::string sfx{fuzzed_data_provider.ConsumeBool() ? ".dat" : ".json"};
assert(WriteBinaryFile(banlist_file.string() + sfx,
fuzzed_data_provider.ConsumeRandomLengthString()));
} else {
const bool force_read_and_write_to_err{fuzzed_data_provider.ConsumeBool()};
if (force_read_and_write_to_err) {
banlist_file = fs::path{"path"} / "to" / "inaccessible" / "fuzzed_banlist";
}
}
{
BanMan ban_man{banlist_file, nullptr, ConsumeBanTimeOffset(fuzzed_data_provider)};
while (--limit_max_ops >= 0 && fuzzed_data_provider.ConsumeBool()) {
@@ -80,5 +94,6 @@ FUZZ_TARGET_INIT(banman, initialize_banman)
});
}
}
fs::remove(banlist_file);
fs::remove(banlist_file.string() + ".dat");
fs::remove(banlist_file.string() + ".json");
}

View File

@@ -196,7 +196,7 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector<const
}
m_node.addrman = std::make_unique<CAddrMan>();
m_node.banman = std::make_unique<BanMan>(m_args.GetDataDirBase() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
m_node.banman = std::make_unique<BanMan>(m_args.GetDataDirBase() / "banlist", nullptr, DEFAULT_MISBEHAVING_BANTIME);
m_node.connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman); // Deterministic randomness for tests.
m_node.peerman = PeerManager::make(chainparams, *m_node.connman, *m_node.addrman,
m_node.banman.get(), *m_node.scheduler, *m_node.chainman,