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.

dbwrapper.cpp 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. // Copyright (c) 2012-2015 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. #include "dbwrapper.h"
  5. #include "util.h"
  6. #include "random.h"
  7. #include <boost/filesystem.hpp>
  8. #include <leveldb/cache.h>
  9. #include <leveldb/env.h>
  10. #include <leveldb/filter_policy.h>
  11. #include <memenv.h>
  12. #include <stdint.h>
  13. void HandleError(const leveldb::Status& status) throw(dbwrapper_error)
  14. {
  15. if (status.ok())
  16. return;
  17. LogPrintf("%s\n", status.ToString());
  18. if (status.IsCorruption())
  19. throw dbwrapper_error("Database corrupted");
  20. if (status.IsIOError())
  21. throw dbwrapper_error("Database I/O error");
  22. if (status.IsNotFound())
  23. throw dbwrapper_error("Database entry missing");
  24. throw dbwrapper_error("Unknown database error");
  25. }
  26. static leveldb::Options GetOptions(size_t nCacheSize)
  27. {
  28. leveldb::Options options;
  29. options.block_cache = leveldb::NewLRUCache(nCacheSize / 2);
  30. options.write_buffer_size = nCacheSize / 4; // up to two write buffers may be held in memory simultaneously
  31. options.filter_policy = leveldb::NewBloomFilterPolicy(10);
  32. options.compression = leveldb::kNoCompression;
  33. options.max_open_files = 64;
  34. if (leveldb::kMajorVersion > 1 || (leveldb::kMajorVersion == 1 && leveldb::kMinorVersion >= 16)) {
  35. // LevelDB versions before 1.16 consider short writes to be corruption. Only trigger error
  36. // on corruption in later versions.
  37. options.paranoid_checks = true;
  38. }
  39. return options;
  40. }
  41. CDBWrapper::CDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, bool fMemory, bool fWipe, bool obfuscate)
  42. {
  43. penv = NULL;
  44. readoptions.verify_checksums = true;
  45. iteroptions.verify_checksums = true;
  46. iteroptions.fill_cache = false;
  47. syncoptions.sync = true;
  48. options = GetOptions(nCacheSize);
  49. options.create_if_missing = true;
  50. if (fMemory) {
  51. penv = leveldb::NewMemEnv(leveldb::Env::Default());
  52. options.env = penv;
  53. } else {
  54. if (fWipe) {
  55. LogPrintf("Wiping LevelDB in %s\n", path.string());
  56. leveldb::Status result = leveldb::DestroyDB(path.string(), options);
  57. HandleError(result);
  58. }
  59. TryCreateDirectory(path);
  60. LogPrintf("Opening LevelDB in %s\n", path.string());
  61. }
  62. leveldb::Status status = leveldb::DB::Open(options, path.string(), &pdb);
  63. HandleError(status);
  64. LogPrintf("Opened LevelDB successfully\n");
  65. // The base-case obfuscation key, which is a noop.
  66. obfuscate_key = std::vector<unsigned char>(OBFUSCATE_KEY_NUM_BYTES, '\000');
  67. bool key_exists = Read(OBFUSCATE_KEY_KEY, obfuscate_key);
  68. if (!key_exists && obfuscate && IsEmpty()) {
  69. // Initialize non-degenerate obfuscation if it won't upset
  70. // existing, non-obfuscated data.
  71. std::vector<unsigned char> new_key = CreateObfuscateKey();
  72. // Write `new_key` so we don't obfuscate the key with itself
  73. Write(OBFUSCATE_KEY_KEY, new_key);
  74. obfuscate_key = new_key;
  75. LogPrintf("Wrote new obfuscate key for %s: %s\n", path.string(), GetObfuscateKeyHex());
  76. }
  77. LogPrintf("Using obfuscation key for %s: %s\n", path.string(), GetObfuscateKeyHex());
  78. }
  79. CDBWrapper::~CDBWrapper()
  80. {
  81. delete pdb;
  82. pdb = NULL;
  83. delete options.filter_policy;
  84. options.filter_policy = NULL;
  85. delete options.block_cache;
  86. options.block_cache = NULL;
  87. delete penv;
  88. options.env = NULL;
  89. }
  90. bool CDBWrapper::WriteBatch(CDBBatch& batch, bool fSync) throw(dbwrapper_error)
  91. {
  92. leveldb::Status status = pdb->Write(fSync ? syncoptions : writeoptions, &batch.batch);
  93. HandleError(status);
  94. return true;
  95. }
  96. // Prefixed with null character to avoid collisions with other keys
  97. //
  98. // We must use a string constructor which specifies length so that we copy
  99. // past the null-terminator.
  100. const std::string CDBWrapper::OBFUSCATE_KEY_KEY("\000obfuscate_key", 14);
  101. const unsigned int CDBWrapper::OBFUSCATE_KEY_NUM_BYTES = 8;
  102. /**
  103. * Returns a string (consisting of 8 random bytes) suitable for use as an
  104. * obfuscating XOR key.
  105. */
  106. std::vector<unsigned char> CDBWrapper::CreateObfuscateKey() const
  107. {
  108. unsigned char buff[OBFUSCATE_KEY_NUM_BYTES];
  109. GetRandBytes(buff, OBFUSCATE_KEY_NUM_BYTES);
  110. return std::vector<unsigned char>(&buff[0], &buff[OBFUSCATE_KEY_NUM_BYTES]);
  111. }
  112. bool CDBWrapper::IsEmpty()
  113. {
  114. boost::scoped_ptr<CDBIterator> it(NewIterator());
  115. it->SeekToFirst();
  116. return !(it->Valid());
  117. }
  118. const std::vector<unsigned char>& CDBWrapper::GetObfuscateKey() const
  119. {
  120. return obfuscate_key;
  121. }
  122. std::string CDBWrapper::GetObfuscateKeyHex() const
  123. {
  124. return HexStr(obfuscate_key);
  125. }
  126. CDBIterator::~CDBIterator() { delete piter; }
  127. bool CDBIterator::Valid() { return piter->Valid(); }
  128. void CDBIterator::SeekToFirst() { piter->SeekToFirst(); }
  129. void CDBIterator::Next() { piter->Next(); }