-
Notifications
You must be signed in to change notification settings - Fork 63
/
Copy pathmulticoin.cpp
137 lines (115 loc) · 5.77 KB
/
multicoin.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include "multicoin.h"
#include "consensus/PoW.h"
CryptoKernel::MulticoinLoader::MulticoinLoader(const std::string& configFile,
Log* log,
bool* running) {
this->log = log;
std::ifstream t(configFile);
if(!t.is_open()) {
throw std::runtime_error("Could not open multicoin config file");
}
const std::string buffer((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
const Json::Value config = CryptoKernel::Storage::toJson(buffer);
t.close();
for(const auto& coin : config["coins"]) {
Coin* newCoin = new Coin;
newCoin->name = coin["name"].asString();
auto subsidyFunc = getSubsidyFunc(coin["subsidy"].asString());
auto coinbaseOwnerFunc = [](const std::string& publicKey) {
return publicKey;
};
newCoin->blockchain.reset(new DynamicBlockchain(log,
coin["blockdb"].asString(),
coinbaseOwnerFunc,
subsidyFunc));
newCoin->consensusAlgo = getConsensusAlgo(coin["consensus"]["type"].asString(),
coin["consensus"]["params"],
config,
newCoin->blockchain.get());
newCoin->blockchain->loadChain(newCoin->consensusAlgo.get(),
coin["genesisblock"].asString());
newCoin->consensusAlgo->start();
newCoin->network.reset(new Network(log, newCoin->blockchain.get(),
coin["port"].asUInt(),
coin["peerdb"].asString()));
if(!coin["walletdb"].empty()) {
newCoin->wallet.reset(new Wallet(newCoin->blockchain.get(),
newCoin->network.get(),
log,
coin["walletdb"].asString()));
}
newCoin->httpserver.reset(new jsonrpc::HttpServerLocal(coin["rpcport"].asUInt(),
config["rpcuser"].asString(),
config["rpcpassword"].asString(),
config["sslcert"].asString(),
config["sslkey"].asString()));
newCoin->rpcserver.reset(new CryptoServer(*newCoin->httpserver));
newCoin->rpcserver->setWallet(newCoin->wallet.get(), newCoin->blockchain.get(),
newCoin->network.get(), running);
newCoin->rpcserver->StartListening();
coins.push_back(std::unique_ptr<Coin>(newCoin));
}
}
CryptoKernel::MulticoinLoader::~MulticoinLoader() {
for(auto& coin : coins) {
coin->rpcserver->StopListening();
coin->wallet.reset();
coin->network.reset();
coin->consensusAlgo.reset();
}
}
std::function<uint64_t(const uint64_t)> CryptoKernel::MulticoinLoader::getSubsidyFunc(
const std::string& name) const {
if(name == "k320") {
return [](const uint64_t height) {
const uint64_t COIN = 100000000;
const uint64_t G = 100 * COIN;
const uint64_t blocksPerYear = 210240;
const long double k = 1 + (std::log(1 + 0.032) / blocksPerYear);
const long double r = 1 + (std::log(1 - 0.24) / blocksPerYear);
const uint64_t supplyAtSwitchover = 68720300 * COIN;
const uint64_t switchoverBlock = 1741620;
if(height > switchoverBlock) {
const uint64_t supply = supplyAtSwitchover * std::pow(k, height - switchoverBlock);
return supply * (k - 1);
} else {
return G * std::pow(r, height);
}
};
} else {
throw std::runtime_error("Unknown subsidy function " + name);
}
}
std::unique_ptr<CryptoKernel::Consensus> CryptoKernel::MulticoinLoader::getConsensusAlgo(
const std::string& name,
const Json::Value& params,
const Json::Value& config,
Blockchain* blockchain) {
if(name == "kgw_lyra2rev2") {
return std::unique_ptr<CryptoKernel::Consensus>(
new Consensus::PoW::KGW_LYRA2REV2(params["blocktime"].asUInt64(),
blockchain,
config["miner"].asBool(),
config["pubKey"].asString(),
log));
} else {
throw std::runtime_error("Unknown consensus algorithm " + name);
}
}
CryptoKernel::MulticoinLoader::
DynamicBlockchain::DynamicBlockchain(Log* GlobalLog,
const std::string& dbDir,
std::function<std::string(const std::string&)> getCoinbaseOwnerFunc,
std::function<uint64_t(const uint64_t)> getBlockRewardFunc) :
CryptoKernel::Blockchain(GlobalLog, dbDir) {
this->getCoinbaseOwnerFunc = getCoinbaseOwnerFunc;
this->getBlockRewardFunc = getBlockRewardFunc;
}
std::string CryptoKernel::MulticoinLoader::
DynamicBlockchain::getCoinbaseOwner(const std::string& publicKey) {
return getCoinbaseOwnerFunc(publicKey);
}
uint64_t CryptoKernel::MulticoinLoader::
DynamicBlockchain::getBlockReward(const uint64_t height) {
return getBlockRewardFunc(height);
}