LevelDB.cpp 5.96 KB
Newer Older
kladkogex's avatar
kladkogex committed
1
/*
2
    Copyright (C) 2019-Present SKALE Labs
kladkogex's avatar
kladkogex committed
3

4
    This file is part of sgxwallet.
kladkogex's avatar
kladkogex committed
5

6
    sgxwallet is free software: you can redistribute it and/or modify
kladkogex's avatar
kladkogex committed
7 8 9 10
    it under the terms of the GNU Affero General Public License as published
    by the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

11
    sgxwallet is distributed in the hope that it will be useful,
kladkogex's avatar
kladkogex committed
12 13 14 15 16
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
17
    along with sgxwallet.  If not, see <https://www.gnu.org/licenses/>.
kladkogex's avatar
kladkogex committed
18 19 20 21 22 23 24 25 26

    @file LevelDB.cpp
    @author Stan Kladko
    @date 2019
*/

#include <stdexcept>
#include <memory>
#include <string>
27
#include <iostream>
kladkogex's avatar
kladkogex committed
28 29 30

#include "leveldb/db.h"

kladkogex's avatar
kladkogex committed
31
#include "sgxwallet_common.h"
32
#include "SGXException.h"
kladkogex's avatar
kladkogex committed
33 34
#include "LevelDB.h"

35 36
#include "ServerInit.h"

Oleh Nikolaiev's avatar
Oleh Nikolaiev committed
37
#include "third_party/spdlog/spdlog.h"
38 39
#include "common.h"

kladkogex's avatar
kladkogex committed
40 41 42 43 44
using namespace leveldb;

static WriteOptions writeOptions;
static ReadOptions readOptions;

45
std::shared_ptr<string> LevelDB::readString(const string &_key) {
kladkogex's avatar
kladkogex committed
46

47
    auto result = std::make_shared<string>();
kladkogex's avatar
kladkogex committed
48

kladko's avatar
kladko committed
49
    CHECK_STATE(db)
kladkogex's avatar
kladkogex committed
50

Oleh Nikolaiev's avatar
Oleh Nikolaiev committed
51
    auto status = db->Get(readOptions, _key, result.get());
52

kladkogex's avatar
kladkogex committed
53 54
    throwExceptionOnError(status);

55
    if (status.IsNotFound()) {
kladkogex's avatar
kladkogex committed
56
        return nullptr;
57
    }
kladkogex's avatar
kladkogex committed
58 59 60 61

    return result;
}

62
void LevelDB::writeString(const string &_key, const string &_value) {
kladkogex's avatar
kladkogex committed
63

kladkogex's avatar
kladkogex committed
64 65 66 67 68
    auto status = db->Put(writeOptions, Slice(_key), Slice(_value));

    throwExceptionOnError(status);
}

69

Oleh Nikolaiev's avatar
Oleh Nikolaiev committed
70
void LevelDB::deleteDHDKGKey(const string &_key) {
71

72
    string full_key = "DKG_DH_KEY_" + _key;
73

74
    auto status = db->Delete(writeOptions, Slice(full_key));
75 76 77 78 79

    throwExceptionOnError(status);

}

80
void LevelDB::deleteTempNEK(const string &_key) {
81

kladko's avatar
kladko committed
82
    CHECK_STATE(_key.rfind("tmp_NEK", 0) == 0);
83 84 85 86 87 88

    auto status = db->Delete(writeOptions, Slice(_key));

    throwExceptionOnError(status);
}

89
void LevelDB::deleteKey(const string &_key) {
90 91 92 93 94 95 96

    auto status = db->Delete(writeOptions, Slice(_key));

    throwExceptionOnError(status);

}

97

kladkogex's avatar
kladkogex committed
98

99
void LevelDB::writeByteArray(string &_key, const char *value,
kladkogex's avatar
kladkogex committed
100
                             size_t _valueLen) {
kladko's avatar
kladko committed
101 102

    CHECK_STATE(value);
kladkogex's avatar
kladkogex committed
103

kladkogex's avatar
kladkogex committed
104 105 106 107 108 109 110 111
    auto status = db->Put(writeOptions, Slice(_key), Slice(value, _valueLen));

    throwExceptionOnError(status);
}

void LevelDB::throwExceptionOnError(Status _status) {
    if (_status.IsNotFound())
        return;
kladkogex's avatar
kladkogex committed
112

kladkogex's avatar
kladkogex committed
113
    if (!_status.ok()) {
114
        throw SGXException(COULD_NOT_ACCESS_DATABASE, ("Could not access database database:" + _status.ToString()).c_str());
kladkogex's avatar
kladkogex committed
115 116 117 118
    }
}

uint64_t LevelDB::visitKeys(LevelDB::KeyVisitor *_visitor, uint64_t _maxKeysToVisit) {
kladko's avatar
kladko committed
119 120 121

    CHECK_STATE(_visitor);

kladkogex's avatar
kladkogex committed
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
    uint64_t readCounter = 0;

    leveldb::Iterator *it = db->NewIterator(readOptions);
    for (it->SeekToFirst(); it->Valid(); it->Next()) {
        _visitor->visitDBKey(it->key().data());
        readCounter++;
        if (readCounter >= _maxKeysToVisit) {
            break;
        }
    }

    delete it;

    return readCounter;
}

138
std::vector<string> LevelDB::writeKeysToVector1(uint64_t _maxKeysToVisit){
139
  uint64_t readCounter = 0;
140
  std::vector<string> keys;
141 142 143

  leveldb::Iterator *it = db->NewIterator(readOptions);
  for (it->SeekToFirst(); it->Valid(); it->Next()) {
144
    string cur_key(it->key().data(), it->key().size());
145 146 147 148 149 150 151 152 153 154 155 156
    keys.push_back(cur_key);
    readCounter++;
    if (readCounter >= _maxKeysToVisit) {
      break;
    }
  }

  delete it;

  return keys;
}

kladko's avatar
kladko committed
157
void LevelDB::writeDataUnique(const string & name, const string &value) {
kladko's avatar
kladko committed
158
  auto key = name;
159

kladko's avatar
kladko committed
160
  if (readString(name)) {
kladko's avatar
kladko committed
161
    spdlog::debug("Name {} already exists", name);
162
    throw SGXException(KEY_SHARE_ALREADY_EXISTS, "Data with this name already exists");
163 164 165
  }

  writeString(key, value);
kladko's avatar
kladko committed
166

167 168 169
}


170
LevelDB::LevelDB(string &filename) {
kladkogex's avatar
kladkogex committed
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
    leveldb::Options options;
    options.create_if_missing = true;

    if (!leveldb::DB::Open(options, filename, (leveldb::DB **) &db).ok()) {
        throw std::runtime_error("Unable to open levelDB database");
    }

    if (db == nullptr) {
        throw std::runtime_error("Null levelDB object");
    }
}

LevelDB::~LevelDB() {
}

186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
const std::shared_ptr<LevelDB> &LevelDB::getLevelDb() {
    CHECK_STATE(levelDb)
    return levelDb;
}

const std::shared_ptr<LevelDB> &LevelDB::getCsrDb() {
    CHECK_STATE(csrDb)
    return csrDb;
}

const std::shared_ptr<LevelDB> &LevelDB::getCsrStatusDb() {
    CHECK_STATE(csrStatusDb)
    return csrStatusDb;
}


std::shared_ptr<LevelDB> LevelDB::levelDb = nullptr;

std::shared_ptr<LevelDB> LevelDB::csrDb = nullptr;
kladkogex's avatar
kladkogex committed
205

206
std::shared_ptr<LevelDB> LevelDB::csrStatusDb = nullptr;
kladkogex's avatar
kladkogex committed
207

kladko's avatar
kladko committed
208
string LevelDB::sgx_data_folder;
209 210 211

bool LevelDB::isInited = false;

kladko's avatar
kladko committed
212
void LevelDB::initDataFolderAndDBs() {
213 214 215 216 217
    CHECK_STATE(!isInited)
    isInited = true;

    spdlog::info("Initing wallet database ... ");

kladko's avatar
kladko committed
218
    char cwd[PATH_MAX];
219

kladko's avatar
kladko committed
220
    if (getcwd(cwd, sizeof(cwd)) == NULL) {
221
        spdlog::error("could not get current workin directory");
kladko's avatar
kladko committed
222 223 224 225 226 227 228
        exit(-1);
    }

    sgx_data_folder = string(cwd) + "/" + SGXDATA_FOLDER;

    struct stat info;
    if (stat(sgx_data_folder.c_str(), &info) !=0 ){
229 230 231 232
        spdlog::info("sgx_data folder does not exist. Creating ...");

        if (system(("mkdir " + sgx_data_folder).c_str()) == 0){
            spdlog::info("Successfully created sgx_data folder");
kladko's avatar
kladko committed
233 234
        }
        else{
235
            spdlog::error("Couldnt create creating sgx_data folder");
kladko's avatar
kladko committed
236 237 238 239
            exit(-1);
        }
    }

240 241
    spdlog::info("Opening wallet databases");

kladko's avatar
kladko committed
242
    auto dbName = sgx_data_folder +  WALLETDB_NAME;
243 244
    levelDb = make_shared<LevelDB>(dbName);

kladko's avatar
kladko committed
245
    auto csr_dbname = sgx_data_folder + "CSR_DB";
246 247
    csrDb = make_shared<LevelDB>(csr_dbname);

kladko's avatar
kladko committed
248
    auto csr_status_dbname = sgx_data_folder + "CSR_STATUS_DB";
249 250
    csrStatusDb = make_shared<LevelDB>(csr_status_dbname);

251
    spdlog::info("Successfully opened databases");
252
}
kladko's avatar
kladko committed
253 254 255 256

const string &LevelDB::getSgxDataFolder() {
    return sgx_data_folder;
}