/ src / net_types.cpp
net_types.cpp
 1  // Copyright (c) 2021-2022 The Bitcoin Core developers
 2  // Distributed under the MIT software license, see the accompanying
 3  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 4  
 5  #include <net_types.h>
 6  
 7  #include <logging.h>
 8  #include <netaddress.h>
 9  #include <netbase.h>
10  #include <univalue.h>
11  
12  static const char* BANMAN_JSON_VERSION_KEY{"version"};
13  
14  CBanEntry::CBanEntry(const UniValue& json)
15      : nVersion(json[BANMAN_JSON_VERSION_KEY].getInt<int>()),
16        nCreateTime(json["ban_created"].getInt<int64_t>()),
17        nBanUntil(json["banned_until"].getInt<int64_t>())
18  {
19  }
20  
21  UniValue CBanEntry::ToJson() const
22  {
23      UniValue json(UniValue::VOBJ);
24      json.pushKV(BANMAN_JSON_VERSION_KEY, nVersion);
25      json.pushKV("ban_created", nCreateTime);
26      json.pushKV("banned_until", nBanUntil);
27      return json;
28  }
29  
30  static const char* BANMAN_JSON_ADDR_KEY = "address";
31  
32  /**
33   * Convert a `banmap_t` object to a JSON array.
34   * @param[in] bans Bans list to convert.
35   * @return a JSON array, similar to the one returned by the `listbanned` RPC. Suitable for
36   * passing to `BanMapFromJson()`.
37   */
38  UniValue BanMapToJson(const banmap_t& bans)
39  {
40      UniValue bans_json(UniValue::VARR);
41      for (const auto& it : bans) {
42          const auto& address = it.first;
43          const auto& ban_entry = it.second;
44          UniValue j = ban_entry.ToJson();
45          j.pushKV(BANMAN_JSON_ADDR_KEY, address.ToString());
46          bans_json.push_back(j);
47      }
48      return bans_json;
49  }
50  
51  /**
52   * Convert a JSON array to a `banmap_t` object.
53   * @param[in] bans_json JSON to convert, must be as returned by `BanMapToJson()`.
54   * @param[out] bans Bans list to create from the JSON.
55   * @throws std::runtime_error if the JSON does not have the expected fields or they contain
56   * unparsable values.
57   */
58  void BanMapFromJson(const UniValue& bans_json, banmap_t& bans)
59  {
60      for (const auto& ban_entry_json : bans_json.getValues()) {
61          const int version{ban_entry_json[BANMAN_JSON_VERSION_KEY].getInt<int>()};
62          if (version != CBanEntry::CURRENT_VERSION) {
63              LogPrintf("Dropping entry with unknown version (%s) from ban list\n", version);
64              continue;
65          }
66          const auto& subnet_str = ban_entry_json[BANMAN_JSON_ADDR_KEY].get_str();
67          const CSubNet subnet{LookupSubNet(subnet_str)};
68          if (!subnet.IsValid()) {
69              LogPrintf("Dropping entry with unparseable address or subnet (%s) from ban list\n", subnet_str);
70              continue;
71          }
72          bans.insert_or_assign(subnet, CBanEntry{ban_entry_json});
73      }
74  }