danicoin/src/CryptoNoteCore/BlockchainIndices.cpp
2016-01-18 15:33:29 +00:00

250 lines
6.8 KiB
C++
Executable file

// Copyright (c) 2011-2016 The Cryptonote developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "BlockchainIndices.h"
#include "Common/StringTools.h"
#include "CryptoNoteCore/CryptoNoteTools.h"
#include "CryptoNoteCore/CryptoNoteFormatUtils.h"
#include "BlockchainExplorer/BlockchainExplorerDataBuilder.h"
#include "CryptoNoteBasicImpl.h"
namespace CryptoNote {
bool PaymentIdIndex::add(const Transaction& transaction) {
Crypto::Hash paymentId;
Crypto::Hash transactionHash = getObjectHash(transaction);
if (!BlockchainExplorerDataBuilder::getPaymentId(transaction, paymentId)) {
return false;
}
index.emplace(paymentId, transactionHash);
return true;
}
bool PaymentIdIndex::remove(const Transaction& transaction) {
Crypto::Hash paymentId;
Crypto::Hash transactionHash = getObjectHash(transaction);
if (!BlockchainExplorerDataBuilder::getPaymentId(transaction, paymentId)) {
return false;
}
auto range = index.equal_range(paymentId);
for (auto iter = range.first; iter != range.second; ++iter){
if (iter->second == transactionHash) {
index.erase(iter);
return true;
}
}
return false;
}
bool PaymentIdIndex::find(const Crypto::Hash& paymentId, std::vector<Crypto::Hash>& transactionHashes) {
bool found = false;
auto range = index.equal_range(paymentId);
for (auto iter = range.first; iter != range.second; ++iter){
found = true;
transactionHashes.emplace_back(iter->second);
}
return found;
}
void PaymentIdIndex::clear() {
index.clear();
}
void PaymentIdIndex::serialize(ISerializer& s) {
s(index, "index");
}
bool TimestampBlocksIndex::add(uint64_t timestamp, const Crypto::Hash& hash) {
index.emplace(timestamp, hash);
return true;
}
bool TimestampBlocksIndex::remove(uint64_t timestamp, const Crypto::Hash& hash) {
auto range = index.equal_range(timestamp);
for (auto iter = range.first; iter != range.second; ++iter) {
if (iter->second == hash) {
index.erase(iter);
return true;
}
}
return false;
}
bool TimestampBlocksIndex::find(uint64_t timestampBegin, uint64_t timestampEnd, uint32_t hashesNumberLimit, std::vector<Crypto::Hash>& hashes, uint32_t& hashesNumberWithinTimestamps) {
uint32_t hashesNumber = 0;
if (timestampBegin > timestampEnd) {
//std::swap(timestampBegin, timestampEnd);
return false;
}
auto begin = index.lower_bound(timestampBegin);
auto end = index.upper_bound(timestampEnd);
hashesNumberWithinTimestamps = static_cast<uint32_t>(std::distance(begin, end));
for (auto iter = begin; iter != end && hashesNumber < hashesNumberLimit; ++iter){
++hashesNumber;
hashes.emplace_back(iter->second);
}
return hashesNumber > 0;
}
void TimestampBlocksIndex::clear() {
index.clear();
}
void TimestampBlocksIndex::serialize(ISerializer& s) {
s(index, "index");
}
bool TimestampTransactionsIndex::add(uint64_t timestamp, const Crypto::Hash& hash) {
index.emplace(timestamp, hash);
return true;
}
bool TimestampTransactionsIndex::remove(uint64_t timestamp, const Crypto::Hash& hash) {
auto range = index.equal_range(timestamp);
for (auto iter = range.first; iter != range.second; ++iter) {
if (iter->second == hash) {
index.erase(iter);
return true;
}
}
return false;
}
bool TimestampTransactionsIndex::find(uint64_t timestampBegin, uint64_t timestampEnd, uint64_t hashesNumberLimit, std::vector<Crypto::Hash>& hashes, uint64_t& hashesNumberWithinTimestamps) {
uint32_t hashesNumber = 0;
if (timestampBegin > timestampEnd) {
//std::swap(timestampBegin, timestampEnd);
return false;
}
auto begin = index.lower_bound(timestampBegin);
auto end = index.upper_bound(timestampEnd);
hashesNumberWithinTimestamps = static_cast<uint32_t>(std::distance(begin, end));
for (auto iter = begin; iter != end && hashesNumber < hashesNumberLimit; ++iter) {
++hashesNumber;
hashes.emplace_back(iter->second);
}
return hashesNumber > 0;
}
void TimestampTransactionsIndex::clear() {
index.clear();
}
void TimestampTransactionsIndex::serialize(ISerializer& s) {
s(index, "index");
}
GeneratedTransactionsIndex::GeneratedTransactionsIndex() : lastGeneratedTxNumber(0) {
}
bool GeneratedTransactionsIndex::add(const Block& block) {
uint32_t blockHeight = boost::get<BaseInput>(block.baseTransaction.inputs.front()).blockIndex;
if (index.size() != blockHeight) {
return false;
}
bool status = index.emplace(blockHeight, lastGeneratedTxNumber + block.transactionHashes.size() + 1).second; //Plus miner tx
if (status) {
lastGeneratedTxNumber += block.transactionHashes.size() + 1;
}
return status;
}
bool GeneratedTransactionsIndex::remove(const Block& block) {
uint32_t blockHeight = boost::get<BaseInput>(block.baseTransaction.inputs.front()).blockIndex;
if (blockHeight != index.size() - 1) {
return false;
}
auto iter = index.find(blockHeight);
assert(iter != index.end());
index.erase(iter);
if (blockHeight != 0) {
iter = index.find(blockHeight - 1);
assert(iter != index.end());
lastGeneratedTxNumber = iter->second;
} else {
lastGeneratedTxNumber = 0;
}
return true;
}
bool GeneratedTransactionsIndex::find(uint32_t height, uint64_t& generatedTransactions) {
if (height > std::numeric_limits<uint32_t>::max()) {
return false;
}
auto iter = index.find(height);
if (iter == index.end()) {
return false;
}
generatedTransactions = iter->second;
return true;
}
void GeneratedTransactionsIndex::clear() {
index.clear();
}
void GeneratedTransactionsIndex::serialize(ISerializer& s) {
s(index, "index");
s(lastGeneratedTxNumber, "lastGeneratedTxNumber");
}
bool OrphanBlocksIndex::add(const Block& block) {
Crypto::Hash blockHash = get_block_hash(block);
uint32_t blockHeight = boost::get<BaseInput>(block.baseTransaction.inputs.front()).blockIndex;
index.emplace(blockHeight, blockHash);
return true;
}
bool OrphanBlocksIndex::remove(const Block& block) {
Crypto::Hash blockHash = get_block_hash(block);
uint32_t blockHeight = boost::get<BaseInput>(block.baseTransaction.inputs.front()).blockIndex;
auto range = index.equal_range(blockHeight);
for (auto iter = range.first; iter != range.second; ++iter) {
if (iter->second == blockHash) {
index.erase(iter);
return true;
}
}
return false;
}
bool OrphanBlocksIndex::find(uint32_t height, std::vector<Crypto::Hash>& blockHashes) {
if (height > std::numeric_limits<uint32_t>::max()) {
return false;
}
bool found = false;
auto range = index.equal_range(height);
for (auto iter = range.first; iter != range.second; ++iter) {
found = true;
blockHashes.emplace_back(iter->second);
}
return found;
}
void OrphanBlocksIndex::clear() {
index.clear();
}
}