You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

addrdb.cpp 3.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. // Copyright (c) 2009-2010 Satoshi Nakamoto
  2. // Copyright (c) 2009-2016 The Starwels developers
  3. // Distributed under the MIT software license, see the accompanying
  4. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  5. #include "addrdb.h"
  6. #include "addrman.h"
  7. #include "chainparams.h"
  8. #include "clientversion.h"
  9. #include "fs.h"
  10. #include "hash.h"
  11. #include "random.h"
  12. #include "streams.h"
  13. #include "tinyformat.h"
  14. #include "util.h"
  15. namespace {
  16. template <typename Stream, typename Data>
  17. bool SerializeDB(Stream& stream, const Data& data)
  18. {
  19. // Write and commit header, data
  20. try {
  21. CHashWriter hasher(SER_DISK, CLIENT_VERSION);
  22. stream << FLATDATA(Params().MessageStart()) << data;
  23. hasher << FLATDATA(Params().MessageStart()) << data;
  24. stream << hasher.GetHash();
  25. } catch (const std::exception& e) {
  26. return error("%s: Serialize or I/O error - %s", __func__, e.what());
  27. }
  28. return true;
  29. }
  30. template <typename Data>
  31. bool SerializeFileDB(const std::string& prefix, const fs::path& path, const Data& data)
  32. {
  33. // Generate random temporary filename
  34. unsigned short randv = 0;
  35. GetRandBytes((unsigned char*)&randv, sizeof(randv));
  36. std::string tmpfn = strprintf("%s.%04x", prefix, randv);
  37. // open temp output file, and associate with CAutoFile
  38. fs::path pathTmp = GetDataDir() / tmpfn;
  39. FILE *file = fsbridge::fopen(pathTmp, "wb");
  40. CAutoFile fileout(file, SER_DISK, CLIENT_VERSION);
  41. if (fileout.IsNull())
  42. return error("%s: Failed to open file %s", __func__, pathTmp.string());
  43. // Serialize
  44. if (!SerializeDB(fileout, data)) return false;
  45. FileCommit(fileout.Get());
  46. fileout.fclose();
  47. // replace existing file, if any, with new file
  48. if (!RenameOver(pathTmp, path))
  49. return error("%s: Rename-into-place failed", __func__);
  50. return true;
  51. }
  52. template <typename Stream, typename Data>
  53. bool DeserializeDB(Stream& stream, Data& data, bool fCheckSum = true)
  54. {
  55. try {
  56. CHashVerifier<Stream> verifier(&stream);
  57. // de-serialize file header (network specific magic number) and ..
  58. unsigned char pchMsgTmp[4];
  59. verifier >> FLATDATA(pchMsgTmp);
  60. // ... verify the network matches ours
  61. if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)))
  62. return error("%s: Invalid network magic number", __func__);
  63. // de-serialize data
  64. verifier >> data;
  65. // verify checksum
  66. if (fCheckSum) {
  67. uint256 hashTmp;
  68. stream >> hashTmp;
  69. if (hashTmp != verifier.GetHash()) {
  70. return error("%s: Checksum mismatch, data corrupted", __func__);
  71. }
  72. }
  73. }
  74. catch (const std::exception& e) {
  75. return error("%s: Deserialize or I/O error - %s", __func__, e.what());
  76. }
  77. return true;
  78. }
  79. template <typename Data>
  80. bool DeserializeFileDB(const fs::path& path, Data& data)
  81. {
  82. // open input file, and associate with CAutoFile
  83. FILE *file = fsbridge::fopen(path, "rb");
  84. CAutoFile filein(file, SER_DISK, CLIENT_VERSION);
  85. if (filein.IsNull())
  86. return error("%s: Failed to open file %s", __func__, path.string());
  87. return DeserializeDB(filein, data);
  88. }
  89. }
  90. CBanDB::CBanDB()
  91. {
  92. pathBanlist = GetDataDir() / "banlist.dat";
  93. }
  94. bool CBanDB::Write(const banmap_t& banSet)
  95. {
  96. return SerializeFileDB("banlist", pathBanlist, banSet);
  97. }
  98. bool CBanDB::Read(banmap_t& banSet)
  99. {
  100. return DeserializeFileDB(pathBanlist, banSet);
  101. }
  102. CAddrDB::CAddrDB()
  103. {
  104. pathAddr = GetDataDir() / "peers.dat";
  105. }
  106. bool CAddrDB::Write(const CAddrMan& addr)
  107. {
  108. return SerializeFileDB("peers", pathAddr, addr);
  109. }
  110. bool CAddrDB::Read(CAddrMan& addr)
  111. {
  112. return DeserializeFileDB(pathAddr, addr);
  113. }
  114. bool CAddrDB::Read(CAddrMan& addr, CDataStream& ssPeers)
  115. {
  116. bool ret = DeserializeDB(ssPeers, addr, false);
  117. if (!ret) {
  118. // Ensure addrman is left in a clean state
  119. addr.Clear();
  120. }
  121. return ret;
  122. }