Fabcoin Core  0.16.2
P2P Digital Currency
WhisperDB.cpp
Go to the documentation of this file.
1 /*
2  This file is part of cpp-ethereum.
3 
4  cpp-ethereum is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  cpp-ethereum is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
16 */
22 #include "WhisperDB.h"
23 #include <boost/filesystem.hpp>
24 #include <libdevcore/FileSystem.h>
25 #include "WhisperHost.h"
26 
27 using namespace std;
28 using namespace dev;
29 using namespace dev::shh;
30 namespace fs = boost::filesystem;
31 
32 WhisperDB::WhisperDB(string const& _type)
33 {
34  m_readOptions.verify_checksums = true;
35  string path = dev::getDataDir("shh");
36  fs::create_directories(path);
37  DEV_IGNORE_EXCEPTIONS(fs::permissions(path, fs::owner_all));
38  path += "/" + _type;
39  leveldb::Options op;
40  op.create_if_missing = true;
41  op.max_open_files = 256;
42  leveldb::DB* p = nullptr;
43  leveldb::Status status = leveldb::DB::Open(op, path, &p);
44  m_db.reset(p);
45  if (!status.ok())
46  BOOST_THROW_EXCEPTION(FailedToOpenLevelDB(status.ToString()));
47 }
48 
49 string WhisperDB::lookup(dev::h256 const& _key) const
50 {
51  string ret;
52  leveldb::Slice slice((char const*)_key.data(), _key.size);
53  leveldb::Status status = m_db->Get(m_readOptions, slice, &ret);
54  if (!status.ok() && !status.IsNotFound())
55  BOOST_THROW_EXCEPTION(FailedLookupInLevelDB(status.ToString()));
56 
57  return ret;
58 }
59 
60 void WhisperDB::insert(dev::h256 const& _key, string const& _value)
61 {
62  leveldb::Slice slice((char const*)_key.data(), _key.size);
63  leveldb::Status status = m_db->Put(m_writeOptions, slice, _value);
64  if (!status.ok())
65  BOOST_THROW_EXCEPTION(FailedInsertInLevelDB(status.ToString()));
66 }
67 
68 void WhisperDB::insert(dev::h256 const& _key, bytes const& _value)
69 {
70  leveldb::Slice k((char const*)_key.data(), _key.size);
71  leveldb::Slice v((char const*)_value.data(), _value.size());
72  leveldb::Status status = m_db->Put(m_writeOptions, k, v);
73  if (!status.ok())
74  BOOST_THROW_EXCEPTION(FailedInsertInLevelDB(status.ToString()));
75 }
76 
77 void WhisperDB::kill(dev::h256 const& _key)
78 {
79  leveldb::Slice slice((char const*)_key.data(), _key.size);
80  leveldb::Status status = m_db->Delete(m_writeOptions, slice);
81  if (!status.ok())
82  BOOST_THROW_EXCEPTION(FailedDeleteInLevelDB(status.ToString()));
83 }
84 
85 void WhisperMessagesDB::loadAllMessages(std::map<h256, Envelope>& o_dst)
86 {
87  leveldb::ReadOptions op;
88  op.fill_cache = false;
89  op.verify_checksums = true;
90  vector<string> wasted;
91  unique_ptr<leveldb::Iterator> it(m_db->NewIterator(op));
92  unsigned const now = utcTime();
93 
94  for (it->SeekToFirst(); it->Valid(); it->Next())
95  {
96  leveldb::Slice const k = it->key();
97  leveldb::Slice const v = it->value();
98  bool useless = true;
99 
100  try
101  {
102  RLP rlp((byte const*)v.data(), v.size());
103  Envelope e(rlp);
104  h256 h2 = e.sha3();
105  h256 h1;
106 
107  if (k.size() == h256::size)
108  h1 = h256((byte const*)k.data(), h256::ConstructFromPointer);
109 
110  if (h1 != h2)
111  cwarn << "Corrupted data in Level DB:" << h1.hex() << "versus" << h2.hex();
112  else if (e.expiry() > now)
113  {
114  o_dst[h1] = e;
115  useless = false;
116  }
117  }
118  catch(RLPException const& ex)
119  {
120  cwarn << "RLPException in WhisperDB::loadAll():" << ex.what();
121  }
122  catch(Exception const& ex)
123  {
124  cwarn << "Exception in WhisperDB::loadAll():" << ex.what();
125  }
126 
127  if (useless)
128  wasted.push_back(k.ToString());
129  }
130 
131  cdebug << "WhisperDB::loadAll(): loaded " << o_dst.size() << ", deleted " << wasted.size() << "messages";
132 
133  for (auto const& k: wasted)
134  {
135  leveldb::Status status = m_db->Delete(m_writeOptions, k);
136  if (!status.ok())
137  cwarn << "Failed to delete an entry from Level DB:" << k;
138  }
139 }
140 
141 void WhisperMessagesDB::saveSingleMessage(h256 const& _key, Envelope const& _e)
142 {
143  try
144  {
145  RLPStream rlp;
146  _e.streamRLP(rlp);
147  bytes b;
148  rlp.swapOut(b);
149  insert(_key, b);
150  }
151  catch(RLPException const& ex)
152  {
153  cwarn << boost::diagnostic_information(ex);
154  }
155  catch(FailedInsertInLevelDB const& ex)
156  {
157  cwarn << boost::diagnostic_information(ex);
158  }
159 }
Adapted from code found on http://stackoverflow.com/questions/180947/base64-decode-snippet-in-c Origi...
Definition: Arith256.cpp:15
uint8_t byte
Definition: Common.h:57
byte * data()
Definition: FixedHash.h:139
bytes rlp(_T _t)
Export a single item in RLP format, returning a byte array.
Definition: RLP.h:467
Definition: util.h:95
void streamRLP(RLPStream &_s, IncludeNonce _withNonce=WithNonce) const
Definition: Message.h:67
uint64_t utcTime()
Get the current time in seconds since the epoch in UTC.
Definition: Common.cpp:64
const char * what() const noexceptoverride
Definition: Exceptions.h:42
std::hash for asio::adress
Definition: Common.h:323
Definition: Eth.h:45
std::string getDataDir(std::string _prefix="ethereum")
#define cdebug
Definition: Log.h:302
Base class for all exceptions.
Definition: Exceptions.h:39
std::vector< byte > bytes
Definition: Common.h:75
#define h1(tab, w)
Definition: skipjack.cpp:73
FixedHash< 32 > h256
Definition: FixedHash.h:340
#define cwarn
Definition: Log.h:304
#define b(i, j)
uint8_t const size_t const size
Definition: sha3.h:20
Base class for all RLP exceptions.
Definition: Exceptions.h:51
#define e(i)
Definition: sha.cpp:733
void swapOut(bytes &_dest)
Swap the contents of the output stream out for some other byte array.
Definition: RLP.h:439
#define h2(tab, w)
Definition: skipjack.cpp:74
Class for writing to an RLP bytestream.
Definition: RLP.h:383
Class for interpreting Recursive Linear-Prefix Data.
Definition: RLP.h:64
#define DEV_IGNORE_EXCEPTIONS(X)
Definition: Common.h:63
std::string hex() const
Definition: FixedHash.h:130