Bytecoin v.1.0.6 release
This commit is contained in:
parent
b3a91f67d7
commit
50cdbfa424
|
@ -8,7 +8,7 @@ set(CMAKE_CONFIGURATION_TYPES Debug RelWithDebInfo Release CACHE TYPE INTERNAL)
|
|||
set(CMAKE_SKIP_INSTALL_RULES ON)
|
||||
set(CMAKE_SKIP_PACKAGE_ALL_DEPENDENCY ON)
|
||||
set(CMAKE_SUPPRESS_REGENERATION ON)
|
||||
#enable_testing()
|
||||
enable_testing()
|
||||
|
||||
project(Bytecoin)
|
||||
|
||||
|
@ -62,11 +62,14 @@ else()
|
|||
else()
|
||||
set(MINGW_FLAG "")
|
||||
endif()
|
||||
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND NOT (CMAKE_C_COMPILER_VERSION VERSION_LESS 5.1))
|
||||
set(WARNINGS "${WARNINGS} -Wno-error=odr")
|
||||
endif()
|
||||
set(C_WARNINGS "-Waggregate-return -Wnested-externs -Wold-style-definition -Wstrict-prototypes")
|
||||
set(CXX_WARNINGS "-Wno-reorder -Wno-missing-field-initializers")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 ${MINGW_FLAG} ${WARNINGS} ${C_WARNINGS} ${ARCH_FLAG} -maes")
|
||||
if(NOT APPLE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ${MINGW_FLAG} ${WARNINGS} ${CXX_WARNINGS} ${ARCH_FLAG} -maes")
|
||||
if(APPLE)
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
Release notes 1.0.6
|
||||
|
||||
- High-level API update
|
||||
- Aggregate multi-addresses for Bytecoin RPC Wallet
|
||||
- Wallet synchronization speed increase
|
||||
|
||||
Release notes 1.0.5
|
||||
|
||||
- High-level API for blockchain explorer
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "CryptoTypes.h"
|
||||
|
||||
#include <boost/variant.hpp>
|
||||
|
||||
namespace CryptoNote {
|
||||
|
@ -32,17 +34,17 @@ enum class TransactionRemoveReason : uint8_t
|
|||
};
|
||||
|
||||
struct TransactionOutputToKeyDetails {
|
||||
std::array<uint8_t, 16> txOutKey;
|
||||
Crypto::PublicKey txOutKey;
|
||||
};
|
||||
|
||||
struct TransactionOutputMultisignatureDetails {
|
||||
std::vector<std::array<uint8_t, 16>> keys;
|
||||
std::vector<Crypto::PublicKey> keys;
|
||||
uint32_t requiredSignatures;
|
||||
};
|
||||
|
||||
struct TransactionOutputDetails {
|
||||
uint64_t amount;
|
||||
uint64_t globalIndex;
|
||||
uint32_t globalIndex;
|
||||
|
||||
boost::variant<
|
||||
TransactionOutputToKeyDetails,
|
||||
|
@ -50,17 +52,17 @@ struct TransactionOutputDetails {
|
|||
};
|
||||
|
||||
struct TransactionOutputReferenceDetails {
|
||||
std::array<uint8_t, 32> transactionHash;
|
||||
Crypto::Hash transactionHash;
|
||||
size_t number;
|
||||
};
|
||||
|
||||
struct TransactionInputGenerateDetails {
|
||||
uint64_t height;
|
||||
uint32_t height;
|
||||
};
|
||||
|
||||
struct TransactionInputToKeyDetails {
|
||||
std::vector<uint64_t> keyOffsets;
|
||||
std::array<uint8_t, 16> keyImage;
|
||||
std::vector<uint32_t> outputIndexes;
|
||||
Crypto::KeyImage keyImage;
|
||||
uint64_t mixin;
|
||||
TransactionOutputReferenceDetails output;
|
||||
};
|
||||
|
@ -81,13 +83,13 @@ struct TransactionInputDetails {
|
|||
|
||||
struct TransactionExtraDetails {
|
||||
std::vector<size_t> padding;
|
||||
std::vector<std::array<uint8_t, 16>> publicKey;
|
||||
std::vector<Crypto::PublicKey> publicKey;
|
||||
std::vector<std::string> nonce;
|
||||
std::vector<uint8_t> raw;
|
||||
};
|
||||
|
||||
struct TransactionDetails {
|
||||
std::array<uint8_t, 32> hash;
|
||||
Crypto::Hash hash;
|
||||
uint64_t size;
|
||||
uint64_t fee;
|
||||
uint64_t totalInputsAmount;
|
||||
|
@ -95,12 +97,12 @@ struct TransactionDetails {
|
|||
uint64_t mixin;
|
||||
uint64_t unlockTime;
|
||||
uint64_t timestamp;
|
||||
std::array<uint8_t, 32> paymentId;
|
||||
Crypto::Hash paymentId;
|
||||
bool inBlockchain;
|
||||
std::array<uint8_t, 32> blockHash;
|
||||
uint64_t blockHeight;
|
||||
Crypto::Hash blockHash;
|
||||
uint32_t blockHeight;
|
||||
TransactionExtraDetails extra;
|
||||
std::vector<std::vector<std::array<uint8_t, 32>>> signatures;
|
||||
std::vector<std::vector<Crypto::Signature>> signatures;
|
||||
std::vector<TransactionInputDetails> inputs;
|
||||
std::vector<TransactionOutputDetails> outputs;
|
||||
};
|
||||
|
@ -109,11 +111,11 @@ struct BlockDetails {
|
|||
uint8_t majorVersion;
|
||||
uint8_t minorVersion;
|
||||
uint64_t timestamp;
|
||||
std::array<uint8_t, 32> prevBlockHash;
|
||||
Crypto::Hash prevBlockHash;
|
||||
uint32_t nonce;
|
||||
bool isOrphaned;
|
||||
uint64_t height;
|
||||
std::array<uint8_t, 32> hash;
|
||||
uint32_t height;
|
||||
Crypto::Hash hash;
|
||||
uint64_t difficulty;
|
||||
uint64_t reward;
|
||||
uint64_t baseReward;
|
||||
|
|
114
include/CryptoNote.h
Normal file
114
include/CryptoNote.h
Normal file
|
@ -0,0 +1,114 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <boost/variant.hpp>
|
||||
#include "CryptoTypes.h"
|
||||
|
||||
namespace CryptoNote {
|
||||
|
||||
struct BaseInput {
|
||||
uint32_t blockIndex;
|
||||
};
|
||||
|
||||
struct KeyInput {
|
||||
uint64_t amount;
|
||||
std::vector<uint32_t> outputIndexes;
|
||||
Crypto::KeyImage keyImage;
|
||||
};
|
||||
|
||||
struct MultisignatureInput {
|
||||
uint64_t amount;
|
||||
uint8_t signatureCount;
|
||||
uint32_t outputIndex;
|
||||
};
|
||||
|
||||
struct KeyOutput {
|
||||
Crypto::PublicKey key;
|
||||
};
|
||||
|
||||
struct MultisignatureOutput {
|
||||
std::vector<Crypto::PublicKey> keys;
|
||||
uint8_t requiredSignatureCount;
|
||||
};
|
||||
|
||||
typedef boost::variant<BaseInput, KeyInput, MultisignatureInput> TransactionInput;
|
||||
|
||||
typedef boost::variant<KeyOutput, MultisignatureOutput> TransactionOutputTarget;
|
||||
|
||||
struct TransactionOutput {
|
||||
uint64_t amount;
|
||||
TransactionOutputTarget target;
|
||||
};
|
||||
|
||||
struct TransactionPrefix {
|
||||
uint8_t version;
|
||||
uint64_t unlockTime;
|
||||
std::vector<TransactionInput> inputs;
|
||||
std::vector<TransactionOutput> outputs;
|
||||
std::vector<uint8_t> extra;
|
||||
};
|
||||
|
||||
struct Transaction : public TransactionPrefix {
|
||||
std::vector<std::vector<Crypto::Signature>> signatures;
|
||||
};
|
||||
|
||||
struct ParentBlock {
|
||||
uint8_t majorVersion;
|
||||
uint8_t minorVersion;
|
||||
Crypto::Hash previousBlockHash;
|
||||
uint16_t transactionCount;
|
||||
std::vector<Crypto::Hash> baseTransactionBranch;
|
||||
Transaction baseTransaction;
|
||||
std::vector<Crypto::Hash> blockchainBranch;
|
||||
};
|
||||
|
||||
struct BlockHeader {
|
||||
uint8_t majorVersion;
|
||||
uint8_t minorVersion;
|
||||
uint32_t nonce;
|
||||
uint64_t timestamp;
|
||||
Crypto::Hash previousBlockHash;
|
||||
};
|
||||
|
||||
struct Block : public BlockHeader {
|
||||
ParentBlock parentBlock;
|
||||
Transaction baseTransaction;
|
||||
std::vector<Crypto::Hash> transactionHashes;
|
||||
};
|
||||
|
||||
struct AccountPublicAddress {
|
||||
Crypto::PublicKey spendPublicKey;
|
||||
Crypto::PublicKey viewPublicKey;
|
||||
};
|
||||
|
||||
struct AccountKeys {
|
||||
AccountPublicAddress address;
|
||||
Crypto::SecretKey spendSecretKey;
|
||||
Crypto::SecretKey viewSecretKey;
|
||||
};
|
||||
|
||||
struct KeyPair {
|
||||
Crypto::PublicKey publicKey;
|
||||
Crypto::SecretKey secretKey;
|
||||
};
|
||||
|
||||
using BinaryArray = std::vector<uint8_t>;
|
||||
|
||||
}
|
|
@ -17,18 +17,32 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <sstream>
|
||||
#include "json_archive.h"
|
||||
#include <cstdint>
|
||||
|
||||
namespace serialization {
|
||||
namespace Crypto {
|
||||
|
||||
template<class T>
|
||||
std::string dump_json(T &v)
|
||||
{
|
||||
std::stringstream ostr;
|
||||
json_archive<true> oar(ostr);
|
||||
assert(serialization::serialize(oar, v));
|
||||
return ostr.str();
|
||||
struct Hash {
|
||||
uint8_t data[32];
|
||||
};
|
||||
|
||||
} // namespace serialization
|
||||
struct PublicKey {
|
||||
uint8_t data[32];
|
||||
};
|
||||
|
||||
struct SecretKey {
|
||||
uint8_t data[32];
|
||||
};
|
||||
|
||||
struct KeyDerivation {
|
||||
uint8_t data[32];
|
||||
};
|
||||
|
||||
struct KeyImage {
|
||||
uint8_t data[32];
|
||||
};
|
||||
|
||||
struct Signature {
|
||||
uint8_t data[64];
|
||||
};
|
||||
|
||||
}
|
|
@ -29,7 +29,7 @@ public:
|
|||
virtual ~IBlockchainObserver() {}
|
||||
|
||||
virtual void blockchainUpdated(const std::vector<BlockDetails>& newBlocks, const std::vector<BlockDetails>& orphanedBlocks) {}
|
||||
virtual void poolUpdated(const std::vector<TransactionDetails>& newTransactions, const std::vector<std::pair<std::array<uint8_t, 32>, TransactionRemoveReason>>& removedTransactions) {}
|
||||
virtual void poolUpdated(const std::vector<TransactionDetails>& newTransactions, const std::vector<std::pair<Crypto::Hash, TransactionRemoveReason>>& removedTransactions) {}
|
||||
|
||||
virtual void blockchainSynchronized(const BlockDetails& topBlock) {}
|
||||
};
|
||||
|
@ -44,13 +44,16 @@ public:
|
|||
virtual void init() = 0;
|
||||
virtual void shutdown() = 0;
|
||||
|
||||
virtual bool getBlocks(const std::vector<uint64_t>& blockHeights, std::vector<std::vector<BlockDetails>>& blocks) = 0;
|
||||
virtual bool getBlocks(const std::vector<std::array<uint8_t, 32>>& blockHashes, std::vector<BlockDetails>& blocks) = 0;
|
||||
virtual bool getBlocks(const std::vector<uint32_t>& blockHeights, std::vector<std::vector<BlockDetails>>& blocks) = 0;
|
||||
virtual bool getBlocks(const std::vector<Crypto::Hash>& blockHashes, std::vector<BlockDetails>& blocks) = 0;
|
||||
virtual bool getBlocks(uint64_t timestampBegin, uint64_t timestampEnd, uint32_t blocksNumberLimit, std::vector<BlockDetails>& blocks, uint32_t& blocksNumberWithinTimestamps) = 0;
|
||||
|
||||
virtual bool getBlockchainTop(BlockDetails& topBlock) = 0;
|
||||
|
||||
virtual bool getTransactions(const std::vector<std::array<uint8_t, 32>>& transactionHashes, std::vector<TransactionDetails>& transactions) = 0;
|
||||
virtual bool getPoolState(const std::vector<std::array<uint8_t, 32>>& knownPoolTransactionHashes, std::array<uint8_t, 32> knownBlockchainTop, bool& isBlockchainActual, std::vector<TransactionDetails>& newTransactions, std::vector<std::array<uint8_t, 32>>& removedTransactions) = 0;
|
||||
virtual bool getTransactions(const std::vector<Crypto::Hash>& transactionHashes, std::vector<TransactionDetails>& transactions) = 0;
|
||||
virtual bool getTransactionsByPaymentId(const Crypto::Hash& paymentId, std::vector<TransactionDetails>& transactions) = 0;
|
||||
virtual bool getPoolTransactions(uint64_t timestampBegin, uint64_t timestampEnd, uint32_t transactionsNumberLimit, std::vector<TransactionDetails>& transactions, uint64_t& transactionsNumberWithinTimestamps) = 0;
|
||||
virtual bool getPoolState(const std::vector<Crypto::Hash>& knownPoolTransactionHashes, Crypto::Hash knownBlockchainTop, bool& isBlockchainActual, std::vector<TransactionDetails>& newTransactions, std::vector<Crypto::Hash>& removedTransactions) = 0;
|
||||
|
||||
virtual uint64_t getRewardBlocksWindow() = 0;
|
||||
virtual uint64_t getFullRewardMaxBlockSize(uint8_t majorVersion) = 0;
|
||||
|
|
|
@ -1,84 +0,0 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
|
||||
namespace CryptoNote {
|
||||
|
||||
enum class MultiWalletTransactionState : uint8_t {
|
||||
FAILED
|
||||
};
|
||||
|
||||
struct MultiWalletTransaction {
|
||||
MultiWalletTransactionState state;
|
||||
uint64_t timestamp;
|
||||
uint64_t blockHeight;
|
||||
std::array<uint8_t, 32> hash;
|
||||
bool isBase;
|
||||
int64_t totalAmount;
|
||||
uint64_t fee;
|
||||
uint64_t creationTime;
|
||||
uint64_t unlockTime;
|
||||
std::string extra;
|
||||
};
|
||||
|
||||
struct MultiWalletTransfer {
|
||||
std::string address;
|
||||
uint64_t amount;
|
||||
};
|
||||
|
||||
class IMultiWallet {
|
||||
public:
|
||||
virtual ~IMultiWallet() {}
|
||||
|
||||
virtual void initialize(const std::string& password) = 0;
|
||||
virtual void load(std::istream& source, const std::string& password) = 0;
|
||||
virtual void shutdown() = 0;
|
||||
|
||||
virtual void changePassword(const std::string& oldPassword, const std::string& newPassword) = 0;
|
||||
virtual void save(std::ostream& destination, bool saveDetails = true, bool saveCache = true) = 0;
|
||||
|
||||
virtual std::size_t getAddressCount() const = 0;
|
||||
virtual std::string getAddress(std::size_t index) const = 0;
|
||||
virtual std::string createAddress() = 0;
|
||||
virtual std::string createAddress(const std::array<uint8_t, 32>& spendPublicKey, const std::array<uint8_t, 32>& spendSecretKey) = 0;
|
||||
virtual void deleteAddress(const std::string& address) = 0;
|
||||
|
||||
virtual uint64_t getActualBalance() const = 0;
|
||||
virtual uint64_t getActualBalance(const std::string& address) const = 0;
|
||||
virtual uint64_t getPendingBalance() const = 0;
|
||||
virtual uint64_t getPendingBalance(const std::string& address) const = 0;
|
||||
|
||||
virtual std::size_t getTransactionCount() const = 0;
|
||||
virtual MultiWalletTransaction getTransaction(std::size_t transactionIndex) const = 0;
|
||||
virtual std::size_t getTransactionTransferCount(std::size_t transactionIndex) const = 0;
|
||||
virtual MultiWalletTransfer getTransactionTransfer(std::size_t transactionIndex, std::size_t transferIndex) const = 0;
|
||||
|
||||
virtual std::size_t transfer(const MultiWalletTransfer& destination, uint64_t fee, uint64_t mixIn = 0, const std::string& extra = "", uint64_t unlockTimestamp = 0) = 0;
|
||||
virtual std::size_t transfer(const std::vector<MultiWalletTransfer>& destinations, uint64_t fee, uint64_t mixIn = 0, const std::string& extra = "", uint64_t unlockTimestamp = 0) = 0;
|
||||
virtual std::size_t transfer(const std::string& sourceAddress, const MultiWalletTransfer& destination, uint64_t fee, uint64_t mixIn = 0, const std::string& extra = "", uint64_t unlockTimestamp = 0) = 0;
|
||||
virtual std::size_t transfer(const std::string& sourceAddress, const std::vector<MultiWalletTransfer>& destinations, uint64_t fee, uint64_t mixIn = 0, const std::string& extra = "", uint64_t unlockTimestamp = 0) = 0;
|
||||
|
||||
virtual void start() = 0;
|
||||
virtual void stop() = 0;
|
||||
virtual void refresh() = 0;
|
||||
};
|
||||
|
||||
}
|
57
include/INode.h
Normal file → Executable file
57
include/INode.h
Normal file → Executable file
|
@ -23,11 +23,12 @@
|
|||
#include <vector>
|
||||
|
||||
#include "crypto/crypto.h"
|
||||
#include "cryptonote_core/cryptonote_basic.h"
|
||||
#include "cryptonote_protocol/cryptonote_protocol_defs.h"
|
||||
#include "rpc/core_rpc_server_commands_defs.h"
|
||||
#include "CryptoNoteCore/CryptoNoteBasic.h"
|
||||
#include "CryptoNoteProtocol/CryptoNoteProtocolDefinitions.h"
|
||||
#include "Rpc/CoreRpcServerCommandsDefinitions.h"
|
||||
|
||||
#include "BlockchainExplorerData.h"
|
||||
#include "ITransaction.h"
|
||||
|
||||
namespace CryptoNote {
|
||||
|
||||
|
@ -35,15 +36,15 @@ class INodeObserver {
|
|||
public:
|
||||
virtual ~INodeObserver() {}
|
||||
virtual void peerCountUpdated(size_t count) {}
|
||||
virtual void localBlockchainUpdated(uint64_t height) {}
|
||||
virtual void lastKnownBlockHeightUpdated(uint64_t height) {}
|
||||
virtual void localBlockchainUpdated(uint32_t height) {}
|
||||
virtual void lastKnownBlockHeightUpdated(uint32_t height) {}
|
||||
virtual void poolChanged() {}
|
||||
virtual void blockchainSynchronized(uint64_t topHeight) {}
|
||||
virtual void blockchainSynchronized(uint32_t topHeight) {}
|
||||
};
|
||||
|
||||
struct OutEntry {
|
||||
uint64_t outGlobalIndex;
|
||||
crypto::public_key outKey;
|
||||
uint32_t outGlobalIndex;
|
||||
Crypto::PublicKey outKey;
|
||||
};
|
||||
|
||||
struct OutsForAmount {
|
||||
|
@ -51,10 +52,16 @@ struct OutsForAmount {
|
|||
std::vector<OutEntry> outs;
|
||||
};
|
||||
|
||||
struct BlockCompleteEntry {
|
||||
crypto::hash blockHash;
|
||||
CryptoNote::blobdata block;
|
||||
std::list<CryptoNote::blobdata> txs;
|
||||
struct TransactionShortInfo {
|
||||
Crypto::Hash txId;
|
||||
TransactionPrefix txPrefix;
|
||||
};
|
||||
|
||||
struct BlockShortEntry {
|
||||
Crypto::Hash blockHash;
|
||||
bool hasBlock;
|
||||
CryptoNote::Block block;
|
||||
std::vector<TransactionShortInfo> txsShortInfo;
|
||||
};
|
||||
|
||||
class INode {
|
||||
|
@ -69,22 +76,26 @@ public:
|
|||
virtual bool shutdown() = 0;
|
||||
|
||||
virtual size_t getPeerCount() const = 0;
|
||||
virtual uint64_t getLastLocalBlockHeight() const = 0;
|
||||
virtual uint64_t getLastKnownBlockHeight() const = 0;
|
||||
virtual uint64_t getLocalBlockCount() const = 0;
|
||||
virtual uint64_t getKnownBlockCount() const = 0;
|
||||
virtual uint32_t getLastLocalBlockHeight() const = 0;
|
||||
virtual uint32_t getLastKnownBlockHeight() const = 0;
|
||||
virtual uint32_t getLocalBlockCount() const = 0;
|
||||
virtual uint32_t getKnownBlockCount() const = 0;
|
||||
virtual uint64_t getLastLocalBlockTimestamp() const = 0;
|
||||
|
||||
virtual void relayTransaction(const Transaction& transaction, const Callback& callback) = 0;
|
||||
virtual void getRandomOutsByAmounts(std::vector<uint64_t>&& amounts, uint64_t outsCount, std::vector<CryptoNote::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount>& result, const Callback& callback) = 0;
|
||||
virtual void getNewBlocks(std::list<crypto::hash>&& knownBlockIds, std::list<CryptoNote::block_complete_entry>& newBlocks, uint64_t& startHeight, const Callback& callback) = 0;
|
||||
virtual void getTransactionOutsGlobalIndices(const crypto::hash& transactionHash, std::vector<uint64_t>& outsGlobalIndices, const Callback& callback) = 0;
|
||||
virtual void queryBlocks(std::list<crypto::hash>&& knownBlockIds, uint64_t timestamp, std::list<BlockCompleteEntry>& newBlocks, uint64_t& startHeight, const Callback& callback) = 0;
|
||||
virtual void getPoolSymmetricDifference(std::vector<crypto::hash>&& known_pool_tx_ids, crypto::hash known_block_id, bool& is_bc_actual, std::vector<Transaction>& new_txs, std::vector<crypto::hash>& deleted_tx_ids, const Callback& callback) = 0;
|
||||
virtual void getNewBlocks(std::vector<Crypto::Hash>&& knownBlockIds, std::vector<CryptoNote::block_complete_entry>& newBlocks, uint32_t& startHeight, const Callback& callback) = 0;
|
||||
virtual void getTransactionOutsGlobalIndices(const Crypto::Hash& transactionHash, std::vector<uint32_t>& outsGlobalIndices, const Callback& callback) = 0;
|
||||
virtual void queryBlocks(std::vector<Crypto::Hash>&& knownBlockIds, uint64_t timestamp, std::vector<BlockShortEntry>& newBlocks, uint32_t& startHeight, const Callback& callback) = 0;
|
||||
virtual void getPoolSymmetricDifference(std::vector<Crypto::Hash>&& knownPoolTxIds, Crypto::Hash knownBlockId, bool& isBcActual, std::vector<std::unique_ptr<ITransactionReader>>& newTxs, std::vector<Crypto::Hash>& deletedTxIds, const Callback& callback) = 0;
|
||||
virtual void getMultisignatureOutputByGlobalIndex(uint64_t amount, uint32_t gindex, MultisignatureOutput& out, const Callback& callback) = 0;
|
||||
|
||||
virtual void getBlocks(const std::vector<uint64_t>& blockHeights, std::vector<std::vector<BlockDetails>>& blocks, const Callback& callback) = 0;
|
||||
virtual void getBlocks(const std::vector<crypto::hash>& blockHashes, std::vector<BlockDetails>& blocks, const Callback& callback) = 0;
|
||||
virtual void getTransactions(const std::vector<crypto::hash>& transactionHashes, std::vector<TransactionDetails>& transactions, const Callback& callback) = 0;
|
||||
virtual void getBlocks(const std::vector<uint32_t>& blockHeights, std::vector<std::vector<BlockDetails>>& blocks, const Callback& callback) = 0;
|
||||
virtual void getBlocks(const std::vector<Crypto::Hash>& blockHashes, std::vector<BlockDetails>& blocks, const Callback& callback) = 0;
|
||||
virtual void getBlocks(uint64_t timestampBegin, uint64_t timestampEnd, uint32_t blocksNumberLimit, std::vector<BlockDetails>& blocks, uint32_t& blocksNumberWithinTimestamps, const Callback& callback) = 0;
|
||||
virtual void getTransactions(const std::vector<Crypto::Hash>& transactionHashes, std::vector<TransactionDetails>& transactions, const Callback& callback) = 0;
|
||||
virtual void getTransactionsByPaymentId(const Crypto::Hash& paymentId, std::vector<TransactionDetails>& transactions, const Callback& callback) = 0;
|
||||
virtual void getPoolTransactions(uint64_t timestampBegin, uint64_t timestampEnd, uint32_t transactionsNumberLimit, std::vector<TransactionDetails>& transactions, uint64_t& transactionsNumberWithinTimestamps, const Callback& callback) = 0;
|
||||
virtual void isSynchronized(bool& syncStatus, const Callback& callback) = 0;
|
||||
};
|
||||
|
||||
|
|
106
include/ITransaction.h
Normal file → Executable file
106
include/ITransaction.h
Normal file → Executable file
|
@ -19,64 +19,27 @@
|
|||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "CryptoNote.h"
|
||||
|
||||
namespace CryptoNote {
|
||||
|
||||
typedef std::array<uint8_t, 32> PublicKey;
|
||||
typedef std::array<uint8_t, 32> SecretKey;
|
||||
typedef std::array<uint8_t, 32> KeyImage;
|
||||
typedef std::array<uint8_t, 32> Hash;
|
||||
typedef std::vector<uint8_t> Blob;
|
||||
|
||||
struct AccountAddress {
|
||||
PublicKey spendPublicKey;
|
||||
PublicKey viewPublicKey;
|
||||
};
|
||||
|
||||
struct AccountKeys {
|
||||
AccountAddress address;
|
||||
SecretKey spendSecretKey;
|
||||
SecretKey viewSecretKey;
|
||||
};
|
||||
|
||||
namespace TransactionTypes {
|
||||
|
||||
enum class InputType : uint8_t { Invalid, Key, Multisignature, Generating };
|
||||
enum class OutputType : uint8_t { Invalid, Key, Multisignature };
|
||||
|
||||
struct InputKey {
|
||||
uint64_t amount;
|
||||
std::vector<uint64_t> keyOffsets;
|
||||
KeyImage keyImage; // double spending protection
|
||||
};
|
||||
|
||||
struct InputMultisignature {
|
||||
uint64_t amount;
|
||||
uint32_t signatures;
|
||||
uint64_t outputIndex;
|
||||
};
|
||||
|
||||
struct OutputKey {
|
||||
uint64_t amount;
|
||||
PublicKey key;
|
||||
};
|
||||
|
||||
struct OutputMultisignature {
|
||||
uint64_t amount;
|
||||
std::vector<PublicKey> keys;
|
||||
uint32_t requiredSignatures;
|
||||
};
|
||||
|
||||
struct GlobalOutput {
|
||||
PublicKey targetKey;
|
||||
uint64_t outputIndex;
|
||||
Crypto::PublicKey targetKey;
|
||||
uint32_t outputIndex;
|
||||
};
|
||||
|
||||
typedef std::vector<GlobalOutput> GlobalOutputsContainer;
|
||||
|
||||
struct OutputKeyInfo {
|
||||
PublicKey transactionPublicKey;
|
||||
Crypto::PublicKey transactionPublicKey;
|
||||
size_t transactionIndex;
|
||||
size_t outputInTransaction;
|
||||
};
|
||||
|
@ -86,12 +49,6 @@ namespace TransactionTypes {
|
|||
GlobalOutputsContainer outputs;
|
||||
OutputKeyInfo realOutput;
|
||||
};
|
||||
|
||||
struct KeyPair {
|
||||
PublicKey publicKey;
|
||||
SecretKey secretKey;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -101,33 +58,34 @@ class ITransactionReader {
|
|||
public:
|
||||
virtual ~ITransactionReader() { }
|
||||
|
||||
virtual Hash getTransactionHash() const = 0;
|
||||
virtual Hash getTransactionPrefixHash() const = 0;
|
||||
virtual PublicKey getTransactionPublicKey() const = 0;
|
||||
virtual Crypto::Hash getTransactionHash() const = 0;
|
||||
virtual Crypto::Hash getTransactionPrefixHash() const = 0;
|
||||
virtual Crypto::PublicKey getTransactionPublicKey() const = 0;
|
||||
virtual bool getTransactionSecretKey(Crypto::SecretKey& key) const = 0;
|
||||
virtual uint64_t getUnlockTime() const = 0;
|
||||
|
||||
// extra
|
||||
virtual bool getPaymentId(Hash& paymentId) const = 0;
|
||||
virtual bool getExtraNonce(std::string& nonce) const = 0;
|
||||
virtual Blob getExtra() const = 0;
|
||||
virtual bool getPaymentId(Crypto::Hash& paymentId) const = 0;
|
||||
virtual bool getExtraNonce(BinaryArray& nonce) const = 0;
|
||||
virtual BinaryArray getExtra() const = 0;
|
||||
|
||||
// inputs
|
||||
virtual size_t getInputCount() const = 0;
|
||||
virtual uint64_t getInputTotalAmount() const = 0;
|
||||
virtual TransactionTypes::InputType getInputType(size_t index) const = 0;
|
||||
virtual void getInput(size_t index, TransactionTypes::InputKey& input) const = 0;
|
||||
virtual void getInput(size_t index, TransactionTypes::InputMultisignature& input) const = 0;
|
||||
virtual void getInput(size_t index, KeyInput& input) const = 0;
|
||||
virtual void getInput(size_t index, MultisignatureInput& input) const = 0;
|
||||
|
||||
// outputs
|
||||
virtual size_t getOutputCount() const = 0;
|
||||
virtual uint64_t getOutputTotalAmount() const = 0;
|
||||
virtual TransactionTypes::OutputType getOutputType(size_t index) const = 0;
|
||||
virtual void getOutput(size_t index, TransactionTypes::OutputKey& output) const = 0;
|
||||
virtual void getOutput(size_t index, TransactionTypes::OutputMultisignature& output) const = 0;
|
||||
virtual void getOutput(size_t index, KeyOutput& output, uint64_t& amount) const = 0;
|
||||
virtual void getOutput(size_t index, MultisignatureOutput& output, uint64_t& amount) const = 0;
|
||||
|
||||
// signatures
|
||||
virtual size_t getRequiredSignaturesCount(size_t inputIndex) const = 0;
|
||||
virtual bool findOutputsToAccount(const AccountAddress& addr, const SecretKey& viewSecretKey, std::vector<uint32_t>& outs, uint64_t& outputAmount) const = 0;
|
||||
virtual bool findOutputsToAccount(const AccountPublicAddress& addr, const Crypto::SecretKey& viewSecretKey, std::vector<uint32_t>& outs, uint64_t& outputAmount) const = 0;
|
||||
|
||||
// various checks
|
||||
virtual bool validateInputs() const = 0;
|
||||
|
@ -135,7 +93,7 @@ public:
|
|||
virtual bool validateSignatures() const = 0;
|
||||
|
||||
// serialized transaction
|
||||
virtual Blob getTransactionData() const = 0;
|
||||
virtual BinaryArray getTransactionData() const = 0;
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -150,25 +108,27 @@ public:
|
|||
virtual void setUnlockTime(uint64_t unlockTime) = 0;
|
||||
|
||||
// extra
|
||||
virtual void setPaymentId(const Hash& paymentId) = 0;
|
||||
virtual void setExtraNonce(const std::string& nonce) = 0;
|
||||
virtual void appendExtra(const Blob& extraData) = 0;
|
||||
virtual void setPaymentId(const Crypto::Hash& paymentId) = 0;
|
||||
virtual void setExtraNonce(const BinaryArray& nonce) = 0;
|
||||
virtual void appendExtra(const BinaryArray& extraData) = 0;
|
||||
|
||||
// Inputs/Outputs
|
||||
virtual size_t addInput(const TransactionTypes::InputKey& input) = 0;
|
||||
virtual size_t addInput(const AccountKeys& senderKeys, const TransactionTypes::InputKeyInfo& info, TransactionTypes::KeyPair& ephKeys) = 0;
|
||||
virtual size_t addInput(const TransactionTypes::InputMultisignature& input) = 0;
|
||||
virtual size_t addInput(const KeyInput& input) = 0;
|
||||
virtual size_t addInput(const MultisignatureInput& input) = 0;
|
||||
virtual size_t addInput(const AccountKeys& senderKeys, const TransactionTypes::InputKeyInfo& info, KeyPair& ephKeys) = 0;
|
||||
|
||||
virtual size_t addOutput(uint64_t amount, const AccountAddress& to) = 0;
|
||||
virtual size_t addOutput(uint64_t amount, const std::vector<AccountAddress>& to, uint32_t requiredSignatures) = 0;
|
||||
virtual size_t addOutput(uint64_t amount, const AccountPublicAddress& to) = 0;
|
||||
virtual size_t addOutput(uint64_t amount, const std::vector<AccountPublicAddress>& to, uint32_t requiredSignatures) = 0;
|
||||
virtual size_t addOutput(uint64_t amount, const KeyOutput& out) = 0;
|
||||
virtual size_t addOutput(uint64_t amount, const MultisignatureOutput& out) = 0;
|
||||
|
||||
// transaction info
|
||||
virtual bool getTransactionSecretKey(SecretKey& key) const = 0;
|
||||
virtual void setTransactionSecretKey(const SecretKey& key) = 0;
|
||||
virtual void setTransactionSecretKey(const Crypto::SecretKey& key) = 0;
|
||||
|
||||
// signing
|
||||
virtual void signInputKey(size_t input, const TransactionTypes::InputKeyInfo& info, const TransactionTypes::KeyPair& ephKeys) = 0;
|
||||
virtual void signInputMultisignature(size_t input, const PublicKey& sourceTransactionKey, size_t outputIndex, const AccountKeys& accountKeys) = 0;
|
||||
virtual void signInputKey(size_t input, const TransactionTypes::InputKeyInfo& info, const KeyPair& ephKeys) = 0;
|
||||
virtual void signInputMultisignature(size_t input, const Crypto::PublicKey& sourceTransactionKey, size_t outputIndex, const AccountKeys& accountKeys) = 0;
|
||||
virtual void signInputMultisignature(size_t input, const KeyPair& ephemeralKeys) = 0;
|
||||
};
|
||||
|
||||
class ITransaction :
|
||||
|
|
|
@ -27,19 +27,19 @@
|
|||
|
||||
namespace CryptoNote {
|
||||
|
||||
const uint64_t UNCONFIRMED_TRANSACTION_GLOBAL_OUTPUT_INDEX = std::numeric_limits<uint64_t>::max();
|
||||
const uint32_t UNCONFIRMED_TRANSACTION_GLOBAL_OUTPUT_INDEX = std::numeric_limits<uint32_t>::max();
|
||||
|
||||
struct TransactionInformation {
|
||||
// transaction info
|
||||
Hash transactionHash;
|
||||
PublicKey publicKey;
|
||||
uint64_t blockHeight;
|
||||
Crypto::Hash transactionHash;
|
||||
Crypto::PublicKey publicKey;
|
||||
uint32_t blockHeight;
|
||||
uint64_t timestamp;
|
||||
uint64_t unlockTime;
|
||||
uint64_t totalAmountIn;
|
||||
uint64_t totalAmountOut;
|
||||
std::vector<uint8_t> extra;
|
||||
Hash paymentId;
|
||||
Crypto::Hash paymentId;
|
||||
};
|
||||
|
||||
|
||||
|
@ -47,24 +47,24 @@ struct TransactionOutputInformation {
|
|||
// output info
|
||||
TransactionTypes::OutputType type;
|
||||
uint64_t amount;
|
||||
uint64_t globalOutputIndex;
|
||||
uint32_t globalOutputIndex;
|
||||
uint32_t outputInTransaction;
|
||||
|
||||
// transaction info
|
||||
Hash transactionHash;
|
||||
PublicKey transactionPublicKey;
|
||||
Crypto::Hash transactionHash;
|
||||
Crypto::PublicKey transactionPublicKey;
|
||||
|
||||
union {
|
||||
PublicKey outputKey; // Type: Key
|
||||
Crypto::PublicKey outputKey; // Type: Key
|
||||
uint32_t requiredSignatures; // Type: Multisignature
|
||||
};
|
||||
};
|
||||
|
||||
struct TransactionSpentOutputInformation: public TransactionOutputInformation {
|
||||
uint64_t spendingBlockHeight;
|
||||
uint32_t spendingBlockHeight;
|
||||
uint64_t timestamp;
|
||||
Hash spendingTransactionHash;
|
||||
KeyImage keyImage; //!< \attention Used only for TransactionTypes::OutputType::Key
|
||||
Crypto::Hash spendingTransactionHash;
|
||||
Crypto::KeyImage keyImage; //!< \attention Used only for TransactionTypes::OutputType::Key
|
||||
uint32_t inputInTransaction;
|
||||
};
|
||||
|
||||
|
@ -96,9 +96,9 @@ public:
|
|||
virtual size_t transactionsCount() = 0;
|
||||
virtual uint64_t balance(uint32_t flags = IncludeDefault) = 0;
|
||||
virtual void getOutputs(std::vector<TransactionOutputInformation>& transfers, uint32_t flags = IncludeDefault) = 0;
|
||||
virtual bool getTransactionInformation(const Hash& transactionHash, TransactionInformation& info, int64_t& txBalance) = 0;
|
||||
virtual std::vector<TransactionOutputInformation> getTransactionOutputs(const Hash& transactionHash, uint32_t flags = IncludeDefault) = 0;
|
||||
virtual void getUnconfirmedTransactions(std::vector<crypto::hash>& transactions) = 0;
|
||||
virtual bool getTransactionInformation(const Crypto::Hash& transactionHash, TransactionInformation& info, int64_t& txBalance) = 0;
|
||||
virtual std::vector<TransactionOutputInformation> getTransactionOutputs(const Crypto::Hash& transactionHash, uint32_t flags = IncludeDefault) = 0;
|
||||
virtual void getUnconfirmedTransactions(std::vector<Crypto::Hash>& transactions) = 0;
|
||||
virtual std::vector<TransactionSpentOutputInformation> getSpentOutputs() = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -42,22 +42,23 @@ class ITransfersSubscription;
|
|||
class ITransfersObserver {
|
||||
public:
|
||||
virtual void onError(ITransfersSubscription* object,
|
||||
uint64_t height, std::error_code ec) {}
|
||||
uint32_t height, std::error_code ec) {
|
||||
}
|
||||
|
||||
virtual void onTransactionUpdated(ITransfersSubscription* object, const Hash& transactionHash) {}
|
||||
virtual void onTransactionUpdated(ITransfersSubscription* object, const Crypto::Hash& transactionHash) {}
|
||||
|
||||
/**
|
||||
* \note The sender must guarantee that onTransactionDeleted() is called only after onTransactionUpdated() is called
|
||||
* for the same \a transactionHash.
|
||||
*/
|
||||
virtual void onTransactionDeleted(ITransfersSubscription* object, const Hash& transactionHash) { }
|
||||
virtual void onTransactionDeleted(ITransfersSubscription* object, const Crypto::Hash& transactionHash) {}
|
||||
};
|
||||
|
||||
class ITransfersSubscription : public IObservable < ITransfersObserver > {
|
||||
public:
|
||||
virtual ~ITransfersSubscription() {}
|
||||
|
||||
virtual AccountAddress getAddress() = 0;
|
||||
virtual AccountPublicAddress getAddress() = 0;
|
||||
virtual ITransfersContainer& getContainer() = 0;
|
||||
};
|
||||
|
||||
|
@ -66,10 +67,10 @@ public:
|
|||
virtual ~ITransfersSynchronizer() {}
|
||||
|
||||
virtual ITransfersSubscription& addSubscription(const AccountSubscription& acc) = 0;
|
||||
virtual bool removeSubscription(const AccountAddress& acc) = 0;
|
||||
virtual void getSubscriptions(std::vector<AccountAddress>& subscriptions) = 0;
|
||||
virtual bool removeSubscription(const AccountPublicAddress& acc) = 0;
|
||||
virtual void getSubscriptions(std::vector<AccountPublicAddress>& subscriptions) = 0;
|
||||
// returns nullptr if address is not found
|
||||
virtual ITransfersSubscription* getSubscription(const AccountAddress& acc) = 0;
|
||||
virtual ITransfersSubscription* getSubscription(const AccountPublicAddress& acc) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
156
include/IWallet.h
Normal file → Executable file
156
include/IWallet.h
Normal file → Executable file
|
@ -17,113 +17,99 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <istream>
|
||||
#include <limits>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
#include <vector>
|
||||
#include "CryptoNote.h"
|
||||
|
||||
namespace CryptoNote {
|
||||
|
||||
typedef size_t TransactionId;
|
||||
typedef size_t TransferId;
|
||||
typedef std::array<uint8_t, 32> TransactionHash;
|
||||
const size_t WALLET_INVALID_TRANSACTION_ID = std::numeric_limits<size_t>::max();
|
||||
const size_t WALLET_INVALID_TRANSFER_ID = std::numeric_limits<size_t>::max();
|
||||
const uint32_t WALLET_UNCONFIRMED_TRANSACTION_HEIGHT = std::numeric_limits<uint32_t>::max();
|
||||
|
||||
struct Transfer {
|
||||
enum class WalletTransactionState : uint8_t {
|
||||
SUCCEEDED = 0,
|
||||
FAILED,
|
||||
CANCELLED
|
||||
};
|
||||
|
||||
enum WalletEventType {
|
||||
TRANSACTION_CREATED,
|
||||
TRANSACTION_UPDATED,
|
||||
BALANCE_UNLOCKED
|
||||
};
|
||||
|
||||
struct WalletTransactionCreatedData {
|
||||
size_t transactionIndex;
|
||||
};
|
||||
|
||||
struct WalletTransactionUpdatedData {
|
||||
size_t transactionIndex;
|
||||
};
|
||||
|
||||
struct WalletEvent {
|
||||
WalletEventType type;
|
||||
union {
|
||||
WalletTransactionCreatedData transactionCreated;
|
||||
WalletTransactionUpdatedData transactionUpdated;
|
||||
};
|
||||
};
|
||||
|
||||
struct WalletTransaction {
|
||||
WalletTransactionState state;
|
||||
uint64_t timestamp;
|
||||
uint32_t blockHeight;
|
||||
Crypto::Hash hash;
|
||||
int64_t totalAmount;
|
||||
uint64_t fee;
|
||||
uint64_t creationTime;
|
||||
uint64_t unlockTime;
|
||||
std::string extra;
|
||||
};
|
||||
|
||||
struct WalletTransfer {
|
||||
std::string address;
|
||||
int64_t amount;
|
||||
};
|
||||
|
||||
const TransactionId INVALID_TRANSACTION_ID = std::numeric_limits<TransactionId>::max();
|
||||
const TransferId INVALID_TRANSFER_ID = std::numeric_limits<TransferId>::max();
|
||||
const uint64_t UNCONFIRMED_TRANSACTION_HEIGHT = std::numeric_limits<uint64_t>::max();
|
||||
|
||||
enum class TransactionState : uint8_t {
|
||||
Active, // --> {Deleted}
|
||||
Deleted, // --> {Active}
|
||||
|
||||
Sending, // --> {Active, Cancelled, Failed}
|
||||
Cancelled, // --> {}
|
||||
Failed // --> {}
|
||||
};
|
||||
|
||||
struct TransactionInfo {
|
||||
TransferId firstTransferId;
|
||||
size_t transferCount;
|
||||
int64_t totalAmount;
|
||||
uint64_t fee;
|
||||
uint64_t sentTime;
|
||||
uint64_t unlockTime;
|
||||
TransactionHash hash;
|
||||
bool isCoinbase;
|
||||
uint64_t blockHeight;
|
||||
uint64_t timestamp;
|
||||
std::string extra;
|
||||
TransactionState state;
|
||||
};
|
||||
|
||||
typedef std::array<uint8_t, 32> WalletPublicKey;
|
||||
typedef std::array<uint8_t, 32> WalletSecretKey;
|
||||
|
||||
struct WalletAccountKeys {
|
||||
WalletPublicKey viewPublicKey;
|
||||
WalletSecretKey viewSecretKey;
|
||||
WalletPublicKey spendPublicKey;
|
||||
WalletSecretKey spendSecretKey;
|
||||
};
|
||||
|
||||
class IWalletObserver {
|
||||
public:
|
||||
virtual ~IWalletObserver() {}
|
||||
|
||||
virtual void initCompleted(std::error_code result) {}
|
||||
virtual void saveCompleted(std::error_code result) {}
|
||||
virtual void synchronizationProgressUpdated(uint64_t current, uint64_t total) {}
|
||||
virtual void synchronizationCompleted(std::error_code result) {}
|
||||
virtual void actualBalanceUpdated(uint64_t actualBalance) {}
|
||||
virtual void pendingBalanceUpdated(uint64_t pendingBalance) {}
|
||||
virtual void externalTransactionCreated(TransactionId transactionId) {}
|
||||
virtual void sendTransactionCompleted(TransactionId transactionId, std::error_code result) {}
|
||||
virtual void transactionUpdated(TransactionId transactionId) {}
|
||||
};
|
||||
|
||||
class IWallet {
|
||||
public:
|
||||
virtual ~IWallet() {} ;
|
||||
virtual void addObserver(IWalletObserver* observer) = 0;
|
||||
virtual void removeObserver(IWalletObserver* observer) = 0;
|
||||
virtual ~IWallet() {}
|
||||
|
||||
virtual void initAndGenerate(const std::string& password) = 0;
|
||||
virtual void initAndLoad(std::istream& source, const std::string& password) = 0;
|
||||
virtual void initWithKeys(const WalletAccountKeys& accountKeys, const std::string& password) = 0;
|
||||
virtual void initialize(const std::string& password) = 0;
|
||||
virtual void load(std::istream& source, const std::string& password) = 0;
|
||||
virtual void shutdown() = 0;
|
||||
virtual void reset() = 0;
|
||||
|
||||
virtual void save(std::ostream& destination, bool saveDetailed = true, bool saveCache = true) = 0;
|
||||
virtual void changePassword(const std::string& oldPassword, const std::string& newPassword) = 0;
|
||||
virtual void save(std::ostream& destination, bool saveDetails = true, bool saveCache = true) = 0;
|
||||
|
||||
virtual std::error_code changePassword(const std::string& oldPassword, const std::string& newPassword) = 0;
|
||||
virtual size_t getAddressCount() const = 0;
|
||||
virtual std::string getAddress(size_t index) const = 0;
|
||||
virtual std::string createAddress() = 0;
|
||||
virtual std::string createAddress(const KeyPair& spendKey) = 0;
|
||||
virtual void deleteAddress(const std::string& address) = 0;
|
||||
|
||||
virtual std::string getAddress() = 0;
|
||||
virtual uint64_t getActualBalance() const = 0;
|
||||
virtual uint64_t getActualBalance(const std::string& address) const = 0;
|
||||
virtual uint64_t getPendingBalance() const = 0;
|
||||
virtual uint64_t getPendingBalance(const std::string& address) const = 0;
|
||||
|
||||
virtual uint64_t actualBalance() = 0;
|
||||
virtual uint64_t pendingBalance() = 0;
|
||||
virtual size_t getTransactionCount() const = 0;
|
||||
virtual WalletTransaction getTransaction(size_t transactionIndex) const = 0;
|
||||
virtual size_t getTransactionTransferCount(size_t transactionIndex) const = 0;
|
||||
virtual WalletTransfer getTransactionTransfer(size_t transactionIndex, size_t transferIndex) const = 0;
|
||||
|
||||
virtual size_t getTransactionCount() = 0;
|
||||
virtual size_t getTransferCount() = 0;
|
||||
virtual size_t transfer(const WalletTransfer& destination, uint64_t fee, uint64_t mixIn = 0, const std::string& extra = "", uint64_t unlockTimestamp = 0) = 0;
|
||||
virtual size_t transfer(const std::vector<WalletTransfer>& destinations, uint64_t fee, uint64_t mixIn = 0, const std::string& extra = "", uint64_t unlockTimestamp = 0) = 0;
|
||||
virtual size_t transfer(const std::string& sourceAddress, const WalletTransfer& destination, uint64_t fee, uint64_t mixIn = 0, const std::string& extra = "", uint64_t unlockTimestamp = 0) = 0;
|
||||
virtual size_t transfer(const std::string& sourceAddress, const std::vector<WalletTransfer>& destinations, uint64_t fee, uint64_t mixIn = 0, const std::string& extra = "", uint64_t unlockTimestamp = 0) = 0;
|
||||
|
||||
virtual TransactionId findTransactionByTransferId(TransferId transferId) = 0;
|
||||
|
||||
virtual bool getTransaction(TransactionId transactionId, TransactionInfo& transaction) = 0;
|
||||
virtual bool getTransfer(TransferId transferId, Transfer& transfer) = 0;
|
||||
virtual void start() = 0;
|
||||
virtual void stop() = 0;
|
||||
|
||||
virtual TransactionId sendTransaction(const Transfer& transfer, uint64_t fee, const std::string& extra = "", uint64_t mixIn = 0, uint64_t unlockTimestamp = 0) = 0;
|
||||
virtual TransactionId sendTransaction(const std::vector<Transfer>& transfers, uint64_t fee, const std::string& extra = "", uint64_t mixIn = 0, uint64_t unlockTimestamp = 0) = 0;
|
||||
virtual std::error_code cancelTransaction(size_t transferId) = 0;
|
||||
|
||||
virtual void getAccountKeys(WalletAccountKeys& keys) = 0;
|
||||
//blocks until an event occured
|
||||
virtual WalletEvent getEvent() = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
116
include/IWalletLegacy.h
Normal file
116
include/IWalletLegacy.h
Normal file
|
@ -0,0 +1,116 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <istream>
|
||||
#include <limits>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
#include "CryptoNote.h"
|
||||
|
||||
namespace CryptoNote {
|
||||
|
||||
typedef size_t TransactionId;
|
||||
typedef size_t TransferId;
|
||||
|
||||
struct WalletLegacyTransfer {
|
||||
std::string address;
|
||||
int64_t amount;
|
||||
};
|
||||
|
||||
const TransactionId WALLET_LEGACY_INVALID_TRANSACTION_ID = std::numeric_limits<TransactionId>::max();
|
||||
const TransferId WALLET_LEGACY_INVALID_TRANSFER_ID = std::numeric_limits<TransferId>::max();
|
||||
const uint32_t WALLET_LEGACY_UNCONFIRMED_TRANSACTION_HEIGHT = std::numeric_limits<uint32_t>::max();
|
||||
|
||||
enum class WalletLegacyTransactionState : uint8_t {
|
||||
Active, // --> {Deleted}
|
||||
Deleted, // --> {Active}
|
||||
|
||||
Sending, // --> {Active, Cancelled, Failed}
|
||||
Cancelled, // --> {}
|
||||
Failed // --> {}
|
||||
};
|
||||
|
||||
struct WalletLegacyTransaction {
|
||||
TransferId firstTransferId;
|
||||
size_t transferCount;
|
||||
int64_t totalAmount;
|
||||
uint64_t fee;
|
||||
uint64_t sentTime;
|
||||
uint64_t unlockTime;
|
||||
Crypto::Hash hash;
|
||||
bool isCoinbase;
|
||||
uint32_t blockHeight;
|
||||
uint64_t timestamp;
|
||||
std::string extra;
|
||||
WalletLegacyTransactionState state;
|
||||
};
|
||||
|
||||
class IWalletLegacyObserver {
|
||||
public:
|
||||
virtual ~IWalletLegacyObserver() {}
|
||||
|
||||
virtual void initCompleted(std::error_code result) {}
|
||||
virtual void saveCompleted(std::error_code result) {}
|
||||
virtual void synchronizationProgressUpdated(uint32_t current, uint32_t total) {}
|
||||
virtual void synchronizationCompleted(std::error_code result) {}
|
||||
virtual void actualBalanceUpdated(uint64_t actualBalance) {}
|
||||
virtual void pendingBalanceUpdated(uint64_t pendingBalance) {}
|
||||
virtual void externalTransactionCreated(TransactionId transactionId) {}
|
||||
virtual void sendTransactionCompleted(TransactionId transactionId, std::error_code result) {}
|
||||
virtual void transactionUpdated(TransactionId transactionId) {}
|
||||
};
|
||||
|
||||
class IWalletLegacy {
|
||||
public:
|
||||
virtual ~IWalletLegacy() {} ;
|
||||
virtual void addObserver(IWalletLegacyObserver* observer) = 0;
|
||||
virtual void removeObserver(IWalletLegacyObserver* observer) = 0;
|
||||
|
||||
virtual void initAndGenerate(const std::string& password) = 0;
|
||||
virtual void initAndLoad(std::istream& source, const std::string& password) = 0;
|
||||
virtual void initWithKeys(const AccountKeys& accountKeys, const std::string& password) = 0;
|
||||
virtual void shutdown() = 0;
|
||||
virtual void reset() = 0;
|
||||
|
||||
virtual void save(std::ostream& destination, bool saveDetailed = true, bool saveCache = true) = 0;
|
||||
|
||||
virtual std::error_code changePassword(const std::string& oldPassword, const std::string& newPassword) = 0;
|
||||
|
||||
virtual std::string getAddress() = 0;
|
||||
|
||||
virtual uint64_t actualBalance() = 0;
|
||||
virtual uint64_t pendingBalance() = 0;
|
||||
|
||||
virtual size_t getTransactionCount() = 0;
|
||||
virtual size_t getTransferCount() = 0;
|
||||
|
||||
virtual TransactionId findTransactionByTransferId(TransferId transferId) = 0;
|
||||
|
||||
virtual bool getTransaction(TransactionId transactionId, WalletLegacyTransaction& transaction) = 0;
|
||||
virtual bool getTransfer(TransferId transferId, WalletLegacyTransfer& transfer) = 0;
|
||||
|
||||
virtual TransactionId sendTransaction(const WalletLegacyTransfer& transfer, uint64_t fee, const std::string& extra = "", uint64_t mixIn = 0, uint64_t unlockTimestamp = 0) = 0;
|
||||
virtual TransactionId sendTransaction(const std::vector<WalletLegacyTransfer>& transfers, uint64_t fee, const std::string& extra = "", uint64_t mixIn = 0, uint64_t unlockTimestamp = 0) = 0;
|
||||
virtual std::error_code cancelTransaction(size_t transferId) = 0;
|
||||
|
||||
virtual void getAccountKeys(AccountKeys& keys) = 0;
|
||||
};
|
||||
|
||||
}
|
261
src/BlockchainExplorer/BlockchainExplorer.cpp
Normal file → Executable file
261
src/BlockchainExplorer/BlockchainExplorer.cpp
Normal file → Executable file
|
@ -21,37 +21,69 @@
|
|||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#include "cryptonote_core/cryptonote_format_utils.h"
|
||||
#include "CryptoNoteCore/CryptoNoteFormatUtils.h"
|
||||
#include "CryptoNoteConfig.h"
|
||||
|
||||
#include "BlockchainExplorerErrors.h"
|
||||
#include "ITransaction.h"
|
||||
|
||||
using namespace Logging;
|
||||
using namespace Crypto;
|
||||
|
||||
namespace CryptoNote {
|
||||
|
||||
class ContextCounterHolder
|
||||
{
|
||||
public:
|
||||
ContextCounterHolder(BlockchainExplorer::AsyncContextCounter& counter) : counter(counter) {}
|
||||
~ContextCounterHolder() { counter.delAsyncContext(); }
|
||||
|
||||
private:
|
||||
BlockchainExplorer::AsyncContextCounter& counter;
|
||||
};
|
||||
|
||||
class NodeRequest {
|
||||
public:
|
||||
|
||||
NodeRequest(const std::function<void(const INode::Callback&)>& request) : requestFunc(request) {}
|
||||
|
||||
std::error_code performBlocking() {
|
||||
requestFunc(std::bind(&NodeRequest::completeionCallback, this, std::placeholders::_1));
|
||||
return promise.get_future().get();
|
||||
std::promise<std::error_code> promise;
|
||||
std::future<std::error_code> future = promise.get_future();
|
||||
requestFunc([&](std::error_code c){
|
||||
blockingCompleteionCallback(std::move(promise), c);
|
||||
});
|
||||
return future.get();
|
||||
}
|
||||
|
||||
void performAsync(const INode::Callback& callback) {
|
||||
requestFunc(callback);
|
||||
void performAsync(BlockchainExplorer::AsyncContextCounter& asyncContextCounter, const INode::Callback& callback) {
|
||||
asyncContextCounter.addAsyncContext();
|
||||
requestFunc(std::bind(&NodeRequest::asyncCompleteionCallback, callback, std::ref(asyncContextCounter), std::placeholders::_1));
|
||||
}
|
||||
|
||||
private:
|
||||
void completeionCallback(std::error_code ec) {
|
||||
void blockingCompleteionCallback(std::promise<std::error_code> promise, std::error_code ec) {
|
||||
promise.set_value(ec);
|
||||
}
|
||||
|
||||
std::promise<std::error_code> promise;
|
||||
static void asyncCompleteionCallback(const INode::Callback& callback, BlockchainExplorer::AsyncContextCounter& asyncContextCounter, std::error_code ec) {
|
||||
ContextCounterHolder counterHolder(asyncContextCounter);
|
||||
try {
|
||||
callback(ec);
|
||||
} catch (...) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const std::function<void(const INode::Callback&)> requestFunc;
|
||||
};
|
||||
|
||||
BlockchainExplorer::BlockchainExplorer(INode& node, Logging::ILogger& logger) : node(node), logger(logger, "BlockchainExplorer"), state(NOT_INITIALIZED) {}
|
||||
BlockchainExplorer::BlockchainExplorer(INode& node, Logging::ILogger& logger) :
|
||||
node(node),
|
||||
logger(logger, "BlockchainExplorer"),
|
||||
state(NOT_INITIALIZED),
|
||||
synchronized(false),
|
||||
observersCounter(0) {}
|
||||
|
||||
BlockchainExplorer::~BlockchainExplorer() {}
|
||||
|
||||
|
@ -59,7 +91,7 @@ bool BlockchainExplorer::addObserver(IBlockchainObserver* observer) {
|
|||
if (state.load() != INITIALIZED) {
|
||||
throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED));
|
||||
}
|
||||
|
||||
observersCounter.fetch_add(1);
|
||||
return observerManager.add(observer);
|
||||
}
|
||||
|
||||
|
@ -67,7 +99,9 @@ bool BlockchainExplorer::removeObserver(IBlockchainObserver* observer) {
|
|||
if (state.load() != INITIALIZED) {
|
||||
throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED));
|
||||
}
|
||||
|
||||
if (observersCounter.load() != 0) {
|
||||
observersCounter.fetch_sub(1);
|
||||
}
|
||||
return observerManager.remove(observer);
|
||||
}
|
||||
|
||||
|
@ -98,10 +132,11 @@ void BlockchainExplorer::shutdown() {
|
|||
throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED));
|
||||
}
|
||||
node.removeObserver(this);
|
||||
asyncContextCounter.waitAsyncContextsFinish();
|
||||
state.store(NOT_INITIALIZED);
|
||||
}
|
||||
|
||||
bool BlockchainExplorer::getBlocks(const std::vector<uint64_t>& blockHeights, std::vector<std::vector<BlockDetails>>& blocks) {
|
||||
bool BlockchainExplorer::getBlocks(const std::vector<uint32_t>& blockHeights, std::vector<std::vector<BlockDetails>>& blocks) {
|
||||
if (state.load() != INITIALIZED) {
|
||||
throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED));
|
||||
}
|
||||
|
@ -111,7 +146,7 @@ bool BlockchainExplorer::getBlocks(const std::vector<uint64_t>& blockHeights, st
|
|||
std::bind(
|
||||
static_cast<
|
||||
void(INode::*)(
|
||||
const std::vector<uint64_t>&,
|
||||
const std::vector<uint32_t>&,
|
||||
std::vector<std::vector<BlockDetails>>&,
|
||||
const INode::Callback&
|
||||
)
|
||||
|
@ -131,7 +166,7 @@ bool BlockchainExplorer::getBlocks(const std::vector<uint64_t>& blockHeights, st
|
|||
return true;
|
||||
}
|
||||
|
||||
bool BlockchainExplorer::getBlocks(const std::vector<std::array<uint8_t, 32>>& blockHashes, std::vector<BlockDetails>& blocks) {
|
||||
bool BlockchainExplorer::getBlocks(const std::vector<Hash>& blockHashes, std::vector<BlockDetails>& blocks) {
|
||||
if (state.load() != INITIALIZED) {
|
||||
throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED));
|
||||
}
|
||||
|
@ -141,13 +176,13 @@ bool BlockchainExplorer::getBlocks(const std::vector<std::array<uint8_t, 32>>& b
|
|||
std::bind(
|
||||
static_cast<
|
||||
void(INode::*)(
|
||||
const std::vector<crypto::hash>&,
|
||||
const std::vector<Hash>&,
|
||||
std::vector<BlockDetails>&,
|
||||
const INode::Callback&
|
||||
)
|
||||
>(&INode::getBlocks),
|
||||
std::ref(node),
|
||||
std::cref(reinterpret_cast<const std::vector<crypto::hash>&>(blockHashes)),
|
||||
std::cref(reinterpret_cast<const std::vector<Hash>&>(blockHashes)),
|
||||
std::ref(blocks),
|
||||
std::placeholders::_1
|
||||
)
|
||||
|
@ -161,15 +196,50 @@ bool BlockchainExplorer::getBlocks(const std::vector<std::array<uint8_t, 32>>& b
|
|||
return true;
|
||||
}
|
||||
|
||||
bool BlockchainExplorer::getBlocks(uint64_t timestampBegin, uint64_t timestampEnd, uint32_t blocksNumberLimit, std::vector<BlockDetails>& blocks, uint32_t& blocksNumberWithinTimestamps) {
|
||||
if (state.load() != INITIALIZED) {
|
||||
throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED));
|
||||
}
|
||||
|
||||
logger(DEBUGGING) << "Get blocks by timestamp request came.";
|
||||
NodeRequest request(
|
||||
std::bind(
|
||||
static_cast<
|
||||
void(INode::*)(
|
||||
uint64_t,
|
||||
uint64_t,
|
||||
uint32_t,
|
||||
std::vector<BlockDetails>&,
|
||||
uint32_t&,
|
||||
const INode::Callback&
|
||||
)
|
||||
>(&INode::getBlocks),
|
||||
std::ref(node),
|
||||
timestampBegin,
|
||||
timestampEnd,
|
||||
blocksNumberLimit,
|
||||
std::ref(blocks),
|
||||
std::ref(blocksNumberWithinTimestamps),
|
||||
std::placeholders::_1
|
||||
)
|
||||
);
|
||||
std::error_code ec = request.performBlocking();
|
||||
if (ec) {
|
||||
logger(ERROR) << "Can't get blocks by timestamp: " << ec.message();
|
||||
throw std::system_error(ec);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BlockchainExplorer::getBlockchainTop(BlockDetails& topBlock) {
|
||||
if (state.load() != INITIALIZED) {
|
||||
throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED));
|
||||
}
|
||||
|
||||
logger(DEBUGGING) << "Get blockchain top request came.";
|
||||
uint64_t lastHeight = node.getLastLocalBlockHeight();
|
||||
uint32_t lastHeight = node.getLastLocalBlockHeight();
|
||||
|
||||
std::vector<uint64_t> heights;
|
||||
std::vector<uint32_t> heights;
|
||||
heights.push_back(std::move(lastHeight));
|
||||
|
||||
std::vector<std::vector<BlockDetails>> blocks;
|
||||
|
@ -195,49 +265,105 @@ bool BlockchainExplorer::getBlockchainTop(BlockDetails& topBlock) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool BlockchainExplorer::getTransactions(const std::vector<std::array<uint8_t, 32>>& transactionHashes, std::vector<TransactionDetails>& transactions) {
|
||||
bool BlockchainExplorer::getTransactions(const std::vector<Hash>& transactionHashes, std::vector<TransactionDetails>& transactions) {
|
||||
if (state.load() != INITIALIZED) {
|
||||
throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED));
|
||||
}
|
||||
|
||||
logger(DEBUGGING) << "Get transactions request came.";
|
||||
logger(DEBUGGING) << "Get transactions by hash request came.";
|
||||
NodeRequest request(
|
||||
std::bind(
|
||||
&INode::getTransactions,
|
||||
static_cast<
|
||||
void(INode::*)(
|
||||
const std::vector<Hash>&,
|
||||
std::vector<TransactionDetails>&,
|
||||
const INode::Callback&
|
||||
)
|
||||
>(&INode::getTransactions),
|
||||
std::ref(node),
|
||||
std::cref(reinterpret_cast<const std::vector<crypto::hash>&>(transactionHashes)),
|
||||
std::cref(reinterpret_cast<const std::vector<Hash>&>(transactionHashes)),
|
||||
std::ref(transactions),
|
||||
std::placeholders::_1
|
||||
)
|
||||
);
|
||||
std::error_code ec = request.performBlocking();
|
||||
if (ec) {
|
||||
logger(ERROR) << "Can't get transactions: " << ec.message();
|
||||
logger(ERROR) << "Can't get transactions by hash: " << ec.message();
|
||||
throw std::system_error(ec);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BlockchainExplorer::getPoolState(const std::vector<std::array<uint8_t, 32>>& knownPoolTransactionHashes, std::array<uint8_t, 32> knownBlockchainTopHash, bool& isBlockchainActual, std::vector<TransactionDetails>& newTransactions, std::vector<std::array<uint8_t, 32>>& removedTransactions) {
|
||||
bool BlockchainExplorer::getPoolTransactions(uint64_t timestampBegin, uint64_t timestampEnd, uint32_t transactionsNumberLimit, std::vector<TransactionDetails>& transactions, uint64_t& transactionsNumberWithinTimestamps) {
|
||||
if (state.load() != INITIALIZED) {
|
||||
throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED));
|
||||
}
|
||||
|
||||
logger(DEBUGGING) << "Get transactions by timestamp request came.";
|
||||
NodeRequest request(
|
||||
std::bind(
|
||||
&INode::getPoolTransactions,
|
||||
std::ref(node),
|
||||
timestampBegin,
|
||||
timestampEnd,
|
||||
transactionsNumberLimit,
|
||||
std::ref(transactions),
|
||||
std::ref(transactionsNumberWithinTimestamps),
|
||||
std::placeholders::_1
|
||||
)
|
||||
);
|
||||
std::error_code ec = request.performBlocking();
|
||||
if (ec) {
|
||||
logger(ERROR) << "Can't get transactions by timestamp: " << ec.message();
|
||||
throw std::system_error(ec);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BlockchainExplorer::getTransactionsByPaymentId(const Hash& paymentId, std::vector<TransactionDetails>& transactions) {
|
||||
if (state.load() != INITIALIZED) {
|
||||
throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED));
|
||||
}
|
||||
|
||||
logger(DEBUGGING) << "Get transactions by payment id request came.";
|
||||
NodeRequest request(
|
||||
std::bind(
|
||||
&INode::getTransactionsByPaymentId,
|
||||
std::ref(node),
|
||||
std::cref(reinterpret_cast<const Hash&>(paymentId)),
|
||||
std::ref(transactions),
|
||||
std::placeholders::_1
|
||||
)
|
||||
);
|
||||
std::error_code ec = request.performBlocking();
|
||||
if (ec) {
|
||||
logger(ERROR) << "Can't get transactions by payment id: " << ec.message();
|
||||
throw std::system_error(ec);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BlockchainExplorer::getPoolState(const std::vector<Hash>& knownPoolTransactionHashes, Hash knownBlockchainTopHash, bool& isBlockchainActual, std::vector<TransactionDetails>& newTransactions, std::vector<Hash>& removedTransactions) {
|
||||
if (state.load() != INITIALIZED) {
|
||||
throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED));
|
||||
}
|
||||
|
||||
logger(DEBUGGING) << "Get pool state request came.";
|
||||
std::vector<Transaction> rawNewTransactions;
|
||||
std::vector<std::unique_ptr<ITransactionReader>> rawNewTransactions;
|
||||
|
||||
NodeRequest request(
|
||||
[&](const INode::Callback& callback) {
|
||||
std::vector<crypto::hash> hashes;
|
||||
for (const std::array<uint8_t, 32>& hash : knownPoolTransactionHashes) {
|
||||
hashes.push_back(std::move(reinterpret_cast<const crypto::hash&>(hash)));
|
||||
std::vector<Hash> hashes;
|
||||
for (Hash hash : knownPoolTransactionHashes) {
|
||||
hashes.push_back(std::move(hash));
|
||||
}
|
||||
|
||||
node.getPoolSymmetricDifference(
|
||||
std::move(hashes),
|
||||
reinterpret_cast<crypto::hash&>(knownBlockchainTopHash),
|
||||
reinterpret_cast<Hash&>(knownBlockchainTopHash),
|
||||
isBlockchainActual,
|
||||
rawNewTransactions,
|
||||
reinterpret_cast<std::vector<crypto::hash>&>(removedTransactions),
|
||||
removedTransactions,
|
||||
callback
|
||||
);
|
||||
}
|
||||
|
@ -248,10 +374,10 @@ bool BlockchainExplorer::getPoolState(const std::vector<std::array<uint8_t, 32>>
|
|||
throw std::system_error(ec);
|
||||
}
|
||||
|
||||
std::vector<std::array<uint8_t, 32>> newTransactionsHashes;
|
||||
for (const Transaction& rawTransaction : rawNewTransactions) {
|
||||
crypto::hash transactionHash = get_transaction_hash(rawTransaction);
|
||||
newTransactionsHashes.push_back(std::move(reinterpret_cast<const std::array<uint8_t, 32>&>(transactionHash)));
|
||||
std::vector<Hash> newTransactionsHashes;
|
||||
for (const auto& rawTransaction : rawNewTransactions) {
|
||||
Hash transactionHash = rawTransaction->getTransactionHash();
|
||||
newTransactionsHashes.push_back(std::move(transactionHash));
|
||||
}
|
||||
|
||||
return getTransactions(newTransactionsHashes, newTransactions);
|
||||
|
@ -295,27 +421,32 @@ bool BlockchainExplorer::isSynchronized() {
|
|||
logger(ERROR) << "Can't get synchronization status: " << ec.message();
|
||||
throw std::system_error(ec);
|
||||
}
|
||||
synchronized.store(syncStatus);
|
||||
return syncStatus;
|
||||
}
|
||||
|
||||
void BlockchainExplorer::poolChanged() {
|
||||
logger(DEBUGGING) << "Got poolChanged notification.";
|
||||
|
||||
if (!synchronized.load() || observersCounter.load() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
|
||||
std::shared_ptr<std::vector<Transaction>> rawNewTransactionsPtr = std::make_shared<std::vector<Transaction>>();
|
||||
std::shared_ptr<std::vector<crypto::hash>> removedTransactionsPtr = std::make_shared<std::vector<crypto::hash>>();
|
||||
std::shared_ptr<std::vector<std::unique_ptr<ITransactionReader>>> rawNewTransactionsPtr = std::make_shared<std::vector<std::unique_ptr<ITransactionReader>>>();
|
||||
std::shared_ptr<std::vector<Hash>> removedTransactionsPtr = std::make_shared<std::vector<Hash>>();
|
||||
std::shared_ptr<bool> isBlockchainActualPtr = std::make_shared<bool>(false);
|
||||
|
||||
NodeRequest request(
|
||||
[this, rawNewTransactionsPtr, removedTransactionsPtr, isBlockchainActualPtr](const INode::Callback& callback) {
|
||||
std::vector<crypto::hash> hashes;
|
||||
for (const crypto::hash& hash : knownPoolState) {
|
||||
std::vector<Hash> hashes;
|
||||
for (const Hash& hash : knownPoolState) {
|
||||
hashes.push_back(std::move(hash));
|
||||
}
|
||||
node.getPoolSymmetricDifference(
|
||||
std::move(hashes),
|
||||
reinterpret_cast<crypto::hash&>(knownBlockchainTop.hash),
|
||||
reinterpret_cast<Hash&>(knownBlockchainTop.hash),
|
||||
*isBlockchainActualPtr,
|
||||
*rawNewTransactionsPtr,
|
||||
*removedTransactionsPtr,
|
||||
|
@ -323,7 +454,7 @@ void BlockchainExplorer::poolChanged() {
|
|||
);
|
||||
}
|
||||
);
|
||||
request.performAsync(
|
||||
request.performAsync(asyncContextCounter,
|
||||
[this, rawNewTransactionsPtr, removedTransactionsPtr, isBlockchainActualPtr](std::error_code ec) {
|
||||
if (ec) {
|
||||
logger(ERROR) << "Can't send poolChanged notification because can't get pool symmetric difference: " << ec.message();
|
||||
|
@ -336,22 +467,23 @@ void BlockchainExplorer::poolChanged() {
|
|||
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
|
||||
std::shared_ptr<std::vector<crypto::hash>> newTransactionsHashesPtr = std::make_shared<std::vector<crypto::hash>>();
|
||||
for (const Transaction& rawTransaction : *rawNewTransactionsPtr) {
|
||||
crypto::hash transactionHash = get_transaction_hash(rawTransaction);
|
||||
std::shared_ptr<std::vector<Hash>> newTransactionsHashesPtr = std::make_shared<std::vector<Hash>>();
|
||||
for (const auto& rawTransaction : *rawNewTransactionsPtr) {
|
||||
auto hash = rawTransaction->getTransactionHash();
|
||||
Hash transactionHash = reinterpret_cast<const Hash&>(hash);
|
||||
bool inserted = knownPoolState.emplace(transactionHash).second;
|
||||
if (inserted) {
|
||||
newTransactionsHashesPtr->push_back(std::move(transactionHash));
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<std::vector<std::pair<std::array<uint8_t, 32>, TransactionRemoveReason>>> removedTransactionsHashesPtr = std::make_shared<std::vector<std::pair<std::array<uint8_t, 32>, TransactionRemoveReason>>>();
|
||||
for (const crypto::hash hash : *removedTransactionsPtr) {
|
||||
std::shared_ptr<std::vector<std::pair<Hash, TransactionRemoveReason>>> removedTransactionsHashesPtr = std::make_shared<std::vector<std::pair<Hash, TransactionRemoveReason>>>();
|
||||
for (const Hash hash : *removedTransactionsPtr) {
|
||||
auto iter = knownPoolState.find(hash);
|
||||
if (iter != knownPoolState.end()) {
|
||||
removedTransactionsHashesPtr->push_back(
|
||||
std::move(std::make_pair(
|
||||
reinterpret_cast<const std::array<uint8_t, 32>&>(hash),
|
||||
hash,
|
||||
TransactionRemoveReason::INCLUDED_IN_BLOCK //Can't have real reason here.
|
||||
))
|
||||
);
|
||||
|
@ -362,14 +494,20 @@ void BlockchainExplorer::poolChanged() {
|
|||
std::shared_ptr<std::vector<TransactionDetails>> newTransactionsPtr = std::make_shared<std::vector<TransactionDetails>>();
|
||||
NodeRequest request(
|
||||
std::bind(
|
||||
&INode::getTransactions,
|
||||
static_cast<
|
||||
void(INode::*)(
|
||||
const std::vector<Hash>&,
|
||||
std::vector<TransactionDetails>&,
|
||||
const INode::Callback&
|
||||
)
|
||||
>(&INode::getTransactions),
|
||||
std::ref(node),
|
||||
std::cref(*newTransactionsHashesPtr),
|
||||
std::ref(*newTransactionsPtr),
|
||||
std::placeholders::_1
|
||||
)
|
||||
);
|
||||
request.performAsync(
|
||||
request.performAsync(asyncContextCounter,
|
||||
[this, newTransactionsHashesPtr, newTransactionsPtr, removedTransactionsHashesPtr](std::error_code ec) {
|
||||
if (ec) {
|
||||
logger(ERROR) << "Can't send poolChanged notification because can't get transactions: " << ec.message();
|
||||
|
@ -386,10 +524,16 @@ void BlockchainExplorer::poolChanged() {
|
|||
|
||||
}
|
||||
|
||||
void BlockchainExplorer::blockchainSynchronized(uint64_t topHeight) {
|
||||
void BlockchainExplorer::blockchainSynchronized(uint32_t topHeight) {
|
||||
logger(DEBUGGING) << "Got blockchainSynchronized notification.";
|
||||
|
||||
std::shared_ptr<std::vector<uint64_t>> blockHeightsPtr = std::make_shared<std::vector<uint64_t>>();
|
||||
synchronized.store(true);
|
||||
|
||||
if (observersCounter.load() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::shared_ptr<std::vector<uint32_t>> blockHeightsPtr = std::make_shared<std::vector<uint32_t>>();
|
||||
std::shared_ptr<std::vector<std::vector<BlockDetails>>> blocksPtr = std::make_shared<std::vector<std::vector<BlockDetails>>>();
|
||||
|
||||
blockHeightsPtr->push_back(topHeight);
|
||||
|
@ -398,7 +542,7 @@ void BlockchainExplorer::blockchainSynchronized(uint64_t topHeight) {
|
|||
std::bind(
|
||||
static_cast<
|
||||
void(INode::*)(
|
||||
const std::vector<uint64_t>&,
|
||||
const std::vector<uint32_t>&,
|
||||
std::vector<std::vector<BlockDetails>>&,
|
||||
const INode::Callback&
|
||||
)
|
||||
|
@ -410,7 +554,7 @@ void BlockchainExplorer::blockchainSynchronized(uint64_t topHeight) {
|
|||
)
|
||||
);
|
||||
|
||||
request.performAsync(
|
||||
request.performAsync(asyncContextCounter,
|
||||
[this, blockHeightsPtr, blocksPtr, topHeight](std::error_code ec) {
|
||||
if (ec) {
|
||||
logger(ERROR) << "Can't send blockchainSynchronized notification because can't get blocks by height: " << ec.message();
|
||||
|
@ -439,17 +583,22 @@ void BlockchainExplorer::blockchainSynchronized(uint64_t topHeight) {
|
|||
);
|
||||
}
|
||||
|
||||
void BlockchainExplorer::localBlockchainUpdated(uint64_t height) {
|
||||
void BlockchainExplorer::localBlockchainUpdated(uint32_t height) {
|
||||
logger(DEBUGGING) << "Got localBlockchainUpdated notification.";
|
||||
|
||||
if (observersCounter.load() == 0) {
|
||||
knownBlockchainTopHeight = height;
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
|
||||
assert(height >= knownBlockchainTopHeight);
|
||||
|
||||
std::shared_ptr<std::vector<uint64_t>> blockHeightsPtr = std::make_shared<std::vector<uint64_t>>();
|
||||
std::shared_ptr<std::vector<uint32_t>> blockHeightsPtr = std::make_shared<std::vector<uint32_t>>();
|
||||
std::shared_ptr<std::vector<std::vector<BlockDetails>>> blocksPtr = std::make_shared<std::vector<std::vector<BlockDetails>>>();
|
||||
|
||||
for (size_t i = knownBlockchainTopHeight; i <= height; ++i) {
|
||||
for (uint32_t i = knownBlockchainTopHeight; i <= height; ++i) {
|
||||
blockHeightsPtr->push_back(i);
|
||||
}
|
||||
|
||||
|
@ -459,7 +608,7 @@ void BlockchainExplorer::localBlockchainUpdated(uint64_t height) {
|
|||
std::bind(
|
||||
static_cast<
|
||||
void(INode::*)(
|
||||
const std::vector<uint64_t>&,
|
||||
const std::vector<uint32_t>&,
|
||||
std::vector<std::vector<BlockDetails>>&,
|
||||
const INode::Callback&
|
||||
)
|
||||
|
@ -471,7 +620,7 @@ void BlockchainExplorer::localBlockchainUpdated(uint64_t height) {
|
|||
)
|
||||
);
|
||||
|
||||
request.performAsync(
|
||||
request.performAsync(asyncContextCounter,
|
||||
[this, blockHeightsPtr, blocksPtr](std::error_code ec) {
|
||||
if (ec) {
|
||||
logger(ERROR) << "Can't send blockchainUpdated notification because can't get blocks by height: " << ec.message();
|
||||
|
|
29
src/BlockchainExplorer/BlockchainExplorer.h
Normal file → Executable file
29
src/BlockchainExplorer/BlockchainExplorer.h
Normal file → Executable file
|
@ -27,6 +27,8 @@
|
|||
#include "Common/ObserverManager.h"
|
||||
#include "BlockchainExplorerErrors.h"
|
||||
|
||||
#include "Wallet/WalletAsyncContextCounter.h"
|
||||
|
||||
#include "Logging/LoggerRef.h"
|
||||
|
||||
namespace CryptoNote {
|
||||
|
@ -46,13 +48,16 @@ public:
|
|||
virtual bool addObserver(IBlockchainObserver* observer) override;
|
||||
virtual bool removeObserver(IBlockchainObserver* observer) override;
|
||||
|
||||
virtual bool getBlocks(const std::vector<uint64_t>& blockHeights, std::vector<std::vector<BlockDetails>>& blocks) override;
|
||||
virtual bool getBlocks(const std::vector<std::array<uint8_t, 32>>& blockHashes, std::vector<BlockDetails>& blocks) override;
|
||||
virtual bool getBlocks(const std::vector<uint32_t>& blockHeights, std::vector<std::vector<BlockDetails>>& blocks) override;
|
||||
virtual bool getBlocks(const std::vector<Crypto::Hash>& blockHashes, std::vector<BlockDetails>& blocks) override;
|
||||
virtual bool getBlocks(uint64_t timestampBegin, uint64_t timestampEnd, uint32_t blocksNumberLimit, std::vector<BlockDetails>& blocks, uint32_t& blocksNumberWithinTimestamps) override;
|
||||
|
||||
virtual bool getBlockchainTop(BlockDetails& topBlock) override;
|
||||
|
||||
virtual bool getTransactions(const std::vector<std::array<uint8_t, 32>>& transactionHashes, std::vector<TransactionDetails>& transactions) override;
|
||||
virtual bool getPoolState(const std::vector<std::array<uint8_t, 32>>& knownPoolTransactionHashes, std::array<uint8_t, 32> knownBlockchainTop, bool& isBlockchainActual, std::vector<TransactionDetails>& newTransactions, std::vector<std::array<uint8_t, 32>>& removedTransactions) override;
|
||||
virtual bool getTransactions(const std::vector<Crypto::Hash>& transactionHashes, std::vector<TransactionDetails>& transactions) override;
|
||||
virtual bool getTransactionsByPaymentId(const Crypto::Hash& paymentId, std::vector<TransactionDetails>& transactions) override;
|
||||
virtual bool getPoolTransactions(uint64_t timestampBegin, uint64_t timestampEnd, uint32_t transactionsNumberLimit, std::vector<TransactionDetails>& transactions, uint64_t& transactionsNumberWithinTimestamps) override;
|
||||
virtual bool getPoolState(const std::vector<Crypto::Hash>& knownPoolTransactionHashes, Crypto::Hash knownBlockchainTop, bool& isBlockchainActual, std::vector<TransactionDetails>& newTransactions, std::vector<Crypto::Hash>& removedTransactions) override;
|
||||
|
||||
virtual uint64_t getRewardBlocksWindow() override;
|
||||
virtual uint64_t getFullRewardMaxBlockSize(uint8_t majorVersion) override;
|
||||
|
@ -63,8 +68,10 @@ public:
|
|||
virtual void shutdown() override;
|
||||
|
||||
virtual void poolChanged() override;
|
||||
virtual void blockchainSynchronized(uint64_t topHeight) override;
|
||||
virtual void localBlockchainUpdated(uint64_t height) override;
|
||||
virtual void blockchainSynchronized(uint32_t topHeight) override;
|
||||
virtual void localBlockchainUpdated(uint32_t height) override;
|
||||
|
||||
typedef WalletAsyncContextCounter AsyncContextCounter;
|
||||
|
||||
private:
|
||||
enum State {
|
||||
|
@ -73,16 +80,20 @@ private:
|
|||
};
|
||||
|
||||
BlockDetails knownBlockchainTop;
|
||||
uint64_t knownBlockchainTopHeight;
|
||||
std::unordered_set<crypto::hash> knownPoolState;
|
||||
uint32_t knownBlockchainTopHeight;
|
||||
std::unordered_set<Crypto::Hash> knownPoolState;
|
||||
|
||||
std::atomic<State> state;
|
||||
tools::ObserverManager<IBlockchainObserver> observerManager;
|
||||
std::atomic<bool> synchronized;
|
||||
std::atomic<uint32_t> observersCounter;
|
||||
Tools::ObserverManager<IBlockchainObserver> observerManager;
|
||||
|
||||
std::mutex mutex;
|
||||
|
||||
INode& node;
|
||||
Logging::LoggerRef logger;
|
||||
|
||||
AsyncContextCounter asyncContextCounter;
|
||||
|
||||
};
|
||||
}
|
||||
|
|
245
src/BlockchainExplorer/BlockchainExplorerDataBuilder.cpp
Normal file → Executable file
245
src/BlockchainExplorer/BlockchainExplorerDataBuilder.cpp
Normal file → Executable file
|
@ -21,23 +21,25 @@
|
|||
#include <boost/range/combine.hpp>
|
||||
|
||||
#include "Common/StringTools.h"
|
||||
#include "cryptonote_core/cryptonote_format_utils.h"
|
||||
#include "CryptoNoteCore/CryptoNoteFormatUtils.h"
|
||||
#include "CryptoNoteCore/CryptoNoteTools.h"
|
||||
#include "CryptoNoteCore/TransactionExtra.h"
|
||||
#include "CryptoNoteConfig.h"
|
||||
|
||||
namespace CryptoNote {
|
||||
|
||||
BlockchainExplorerDataBuilder::BlockchainExplorerDataBuilder(CryptoNote::ICore& core, CryptoNote::ICryptonoteProtocolQuery& protocol) :
|
||||
core(core),
|
||||
protocol(protocol)
|
||||
{
|
||||
BlockchainExplorerDataBuilder::BlockchainExplorerDataBuilder(CryptoNote::ICore& core, CryptoNote::ICryptoNoteProtocolQuery& protocol) :
|
||||
core(core),
|
||||
protocol(protocol) {
|
||||
}
|
||||
|
||||
bool BlockchainExplorerDataBuilder::getMixin(const Transaction& transaction, uint64_t& mixin) {
|
||||
mixin = 0;
|
||||
for (const TransactionInput& txin : transaction.vin) {
|
||||
if (txin.type() != typeid(TransactionInputToKey)) {
|
||||
for (const TransactionInput& txin : transaction.inputs) {
|
||||
if (txin.type() != typeid(KeyInput)) {
|
||||
continue;
|
||||
}
|
||||
uint64_t currentMixin = boost::get<TransactionInputToKey>(txin).keyOffsets.size();
|
||||
uint64_t currentMixin = boost::get<KeyInput>(txin).outputIndexes.size();
|
||||
if (currentMixin > mixin) {
|
||||
mixin = currentMixin;
|
||||
}
|
||||
|
@ -45,75 +47,71 @@ bool BlockchainExplorerDataBuilder::getMixin(const Transaction& transaction, uin
|
|||
return true;
|
||||
}
|
||||
|
||||
bool BlockchainExplorerDataBuilder::getPaymentId(const Transaction& transaction, crypto::hash& paymentId) {
|
||||
std::vector<tx_extra_field> txExtraFields;
|
||||
parse_tx_extra(transaction.extra, txExtraFields);
|
||||
tx_extra_nonce extraNonce;
|
||||
if (!find_tx_extra_field_by_type(txExtraFields, extraNonce)) {
|
||||
bool BlockchainExplorerDataBuilder::getPaymentId(const Transaction& transaction, Crypto::Hash& paymentId) {
|
||||
std::vector<TransactionExtraField> txExtraFields;
|
||||
parseTransactionExtra(transaction.extra, txExtraFields);
|
||||
TransactionExtraNonce extraNonce;
|
||||
if (!findTransactionExtraFieldByType(txExtraFields, extraNonce)) {
|
||||
return false;
|
||||
}
|
||||
return get_payment_id_from_tx_extra_nonce(extraNonce.nonce, paymentId);
|
||||
return getPaymentIdFromTransactionExtraNonce(extraNonce.nonce, paymentId);
|
||||
}
|
||||
|
||||
bool BlockchainExplorerDataBuilder::fillTxExtra(const std::vector<uint8_t>& rawExtra, TransactionExtraDetails& extraDetails) {
|
||||
extraDetails.raw = rawExtra;
|
||||
std::vector<tx_extra_field> txExtraFields;
|
||||
parse_tx_extra(rawExtra, txExtraFields);
|
||||
for (const tx_extra_field& field : txExtraFields) {
|
||||
if (typeid(tx_extra_padding) == field.type()) {
|
||||
extraDetails.padding.push_back(std::move(boost::get<tx_extra_padding>(field).size));
|
||||
}
|
||||
else if (typeid(tx_extra_pub_key) == field.type()) {
|
||||
extraDetails.publicKey.push_back(std::move(reinterpret_cast<const std::array<uint8_t, 16>&>(boost::get<tx_extra_pub_key>(field).pub_key)));
|
||||
}
|
||||
else if (typeid(tx_extra_nonce) == field.type()) {
|
||||
extraDetails.nonce.push_back(std::move(Common::toHex(boost::get<tx_extra_nonce>(field).nonce.data(), boost::get<tx_extra_nonce>(field).nonce.size())));
|
||||
std::vector<TransactionExtraField> txExtraFields;
|
||||
parseTransactionExtra(rawExtra, txExtraFields);
|
||||
for (const TransactionExtraField& field : txExtraFields) {
|
||||
if (typeid(TransactionExtraPadding) == field.type()) {
|
||||
extraDetails.padding.push_back(std::move(boost::get<TransactionExtraPadding>(field).size));
|
||||
} else if (typeid(TransactionExtraPublicKey) == field.type()) {
|
||||
extraDetails.publicKey.push_back(std::move(boost::get<TransactionExtraPublicKey>(field).publicKey));
|
||||
} else if (typeid(TransactionExtraNonce) == field.type()) {
|
||||
extraDetails.nonce.push_back(std::move(Common::toHex(boost::get<TransactionExtraNonce>(field).nonce.data(), boost::get<TransactionExtraNonce>(field).nonce.size())));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t BlockchainExplorerDataBuilder::median(std::vector<size_t>& v) {
|
||||
if(v.empty())
|
||||
if (v.empty())
|
||||
return boost::value_initialized<size_t>();
|
||||
if(v.size() == 1)
|
||||
if (v.size() == 1)
|
||||
return v[0];
|
||||
|
||||
size_t n = (v.size()) / 2;
|
||||
std::sort(v.begin(), v.end());
|
||||
//nth_element(v.begin(), v.begin()+n-1, v.end());
|
||||
if(v.size()%2)
|
||||
{//1, 3, 5...
|
||||
if (v.size() % 2) {//1, 3, 5...
|
||||
return v[n];
|
||||
}else
|
||||
{//2, 4, 6...
|
||||
return (v[n-1] + v[n])/2;
|
||||
} else {//2, 4, 6...
|
||||
return (v[n - 1] + v[n]) / 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool BlockchainExplorerDataBuilder::fillBlockDetails(const Block &block, BlockDetails& blockDetails) {
|
||||
crypto::hash hash = get_block_hash(block);
|
||||
|
||||
Crypto::Hash hash = get_block_hash(block);
|
||||
|
||||
blockDetails.majorVersion = block.majorVersion;
|
||||
blockDetails.minorVersion = block.minorVersion;
|
||||
blockDetails.timestamp = block.timestamp;
|
||||
blockDetails.prevBlockHash = reinterpret_cast<const std::array<uint8_t, 32>&>(block.prevId);
|
||||
blockDetails.prevBlockHash = block.previousBlockHash;
|
||||
blockDetails.nonce = block.nonce;
|
||||
blockDetails.hash = reinterpret_cast<const std::array<uint8_t, 32>&>(hash);
|
||||
blockDetails.hash = hash;
|
||||
|
||||
blockDetails.reward = 0;
|
||||
for (const TransactionOutput& out : block.minerTx.vout) {
|
||||
for (const TransactionOutput& out : block.baseTransaction.outputs) {
|
||||
blockDetails.reward += out.amount;
|
||||
}
|
||||
|
||||
if (block.minerTx.vin.front().type() != typeid(TransactionInputGenerate))
|
||||
if (block.baseTransaction.inputs.front().type() != typeid(BaseInput))
|
||||
return false;
|
||||
blockDetails.height = boost::get<TransactionInputGenerate>(block.minerTx.vin.front()).height;
|
||||
|
||||
crypto::hash tmpHash = core.getBlockIdByHeight(blockDetails.height);
|
||||
blockDetails.height = boost::get<BaseInput>(block.baseTransaction.inputs.front()).blockIndex;
|
||||
|
||||
Crypto::Hash tmpHash = core.getBlockIdByHeight(blockDetails.height);
|
||||
blockDetails.isOrphaned = hash != tmpHash;
|
||||
|
||||
|
||||
if (!core.getBlockDifficulty(blockDetails.height, blockDetails.difficulty)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -130,20 +128,21 @@ bool BlockchainExplorerDataBuilder::fillBlockDetails(const Block &block, BlockDe
|
|||
}
|
||||
blockDetails.transactionsCumulativeSize = blockSize;
|
||||
|
||||
size_t blokBlobSize = get_object_blobsize(block);
|
||||
size_t minerTxBlobSize = get_object_blobsize(block.minerTx);
|
||||
size_t blokBlobSize = getObjectBinarySize(block);
|
||||
size_t minerTxBlobSize = getObjectBinarySize(block.baseTransaction);
|
||||
blockDetails.blockSize = blokBlobSize + blockDetails.transactionsCumulativeSize - minerTxBlobSize;
|
||||
|
||||
|
||||
if (!core.getAlreadyGeneratedCoins(hash, blockDetails.alreadyGeneratedCoins)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
blockDetails.alreadyGeneratedTransactions = 0; //TODO
|
||||
|
||||
if (!core.getGeneratedTransactionsNumber(blockDetails.height, blockDetails.alreadyGeneratedTransactions)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t prevBlockGeneratedCoins = 0;
|
||||
if (blockDetails.height > 0)
|
||||
{
|
||||
if (!core.getAlreadyGeneratedCoins(block.prevId, prevBlockGeneratedCoins)) {
|
||||
if (blockDetails.height > 0) {
|
||||
if (!core.getAlreadyGeneratedCoins(block.previousBlockHash, prevBlockGeneratedCoins)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -151,45 +150,40 @@ bool BlockchainExplorerDataBuilder::fillBlockDetails(const Block &block, BlockDe
|
|||
uint64_t currentReward = 0;
|
||||
int64_t emissionChange = 0;
|
||||
bool penalizeFee = block.majorVersion >= 2;
|
||||
if(!core.getBlockReward(blockDetails.sizeMedian, 0, prevBlockGeneratedCoins, 0, penalizeFee, maxReward, emissionChange))
|
||||
{
|
||||
if (!core.getBlockReward(blockDetails.sizeMedian, 0, prevBlockGeneratedCoins, 0, penalizeFee, maxReward, emissionChange)) {
|
||||
return false;
|
||||
}
|
||||
if(!core.getBlockReward(blockDetails.sizeMedian, blockDetails.transactionsCumulativeSize, prevBlockGeneratedCoins, 0, penalizeFee, currentReward, emissionChange))
|
||||
{
|
||||
if (!core.getBlockReward(blockDetails.sizeMedian, blockDetails.transactionsCumulativeSize, prevBlockGeneratedCoins, 0, penalizeFee, currentReward, emissionChange)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
blockDetails.baseReward = maxReward;
|
||||
if (maxReward == 0 && currentReward == 0)
|
||||
{
|
||||
if (maxReward == 0 && currentReward == 0) {
|
||||
blockDetails.penalty = static_cast<double>(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
if (maxReward < currentReward) {
|
||||
return false;
|
||||
}
|
||||
blockDetails.penalty = static_cast<double>(maxReward - currentReward) / static_cast<double>(maxReward);
|
||||
}
|
||||
|
||||
|
||||
blockDetails.transactions.reserve(block.txHashes.size() + 1);
|
||||
|
||||
blockDetails.transactions.reserve(block.transactionHashes.size() + 1);
|
||||
TransactionDetails transactionDetails;
|
||||
if (!fillTransactionDetails(block.minerTx, transactionDetails, block.timestamp)) {
|
||||
if (!fillTransactionDetails(block.baseTransaction, transactionDetails, block.timestamp)) {
|
||||
return false;
|
||||
}
|
||||
blockDetails.transactions.push_back(std::move(transactionDetails));
|
||||
|
||||
|
||||
std::list<Transaction> found;
|
||||
std::list<crypto::hash> missed;
|
||||
core.getTransactions(block.txHashes, found, missed);
|
||||
if (found.size() != block.txHashes.size()) {
|
||||
std::list<Crypto::Hash> missed;
|
||||
core.getTransactions(block.transactionHashes, found, missed, blockDetails.isOrphaned);
|
||||
if (found.size() != block.transactionHashes.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
blockDetails.totalFeeAmount = 0;
|
||||
|
||||
|
||||
for (const Transaction& tx : found) {
|
||||
TransactionDetails transactionDetails;
|
||||
if (!fillTransactionDetails(tx, transactionDetails, block.timestamp)) {
|
||||
|
@ -202,21 +196,21 @@ bool BlockchainExplorerDataBuilder::fillBlockDetails(const Block &block, BlockDe
|
|||
}
|
||||
|
||||
bool BlockchainExplorerDataBuilder::fillTransactionDetails(const Transaction& transaction, TransactionDetails& transactionDetails, uint64_t timestamp) {
|
||||
crypto::hash hash = get_transaction_hash(transaction);
|
||||
transactionDetails.hash = reinterpret_cast<const std::array<uint8_t, 32>&>(hash);
|
||||
|
||||
Crypto::Hash hash = getObjectHash(transaction);
|
||||
transactionDetails.hash = hash;
|
||||
|
||||
transactionDetails.timestamp = timestamp;
|
||||
|
||||
crypto::hash blockHash;
|
||||
uint64_t blockHeight;
|
||||
|
||||
Crypto::Hash blockHash;
|
||||
uint32_t blockHeight;
|
||||
if (!core.getBlockContainingTx(hash, blockHash, blockHeight)) {
|
||||
transactionDetails.inBlockchain = false;
|
||||
transactionDetails.blockHeight = boost::value_initialized<uint64_t>();
|
||||
transactionDetails.blockHash = boost::value_initialized<std::array<uint8_t, 32>>();
|
||||
transactionDetails.blockHeight = boost::value_initialized<uint32_t>();
|
||||
transactionDetails.blockHash = boost::value_initialized<Crypto::Hash>();
|
||||
} else {
|
||||
transactionDetails.inBlockchain = true;
|
||||
transactionDetails.blockHeight = blockHeight;
|
||||
transactionDetails.blockHash = reinterpret_cast<const std::array<uint8_t, 32>&>(blockHash);
|
||||
transactionDetails.blockHash = blockHash;
|
||||
if (timestamp == 0) {
|
||||
Block block;
|
||||
if (!core.getBlockByHash(blockHash, block)) {
|
||||
|
@ -225,8 +219,8 @@ bool BlockchainExplorerDataBuilder::fillTransactionDetails(const Transaction& tr
|
|||
transactionDetails.timestamp = block.timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
transactionDetails.size = get_object_blobsize(transaction);
|
||||
|
||||
transactionDetails.size = getObjectBinarySize(transaction);
|
||||
transactionDetails.unlockTime = transaction.unlockTime;
|
||||
transactionDetails.totalOutputsAmount = get_outs_money_amount(transaction);
|
||||
|
||||
|
@ -236,7 +230,7 @@ bool BlockchainExplorerDataBuilder::fillTransactionDetails(const Transaction& tr
|
|||
}
|
||||
transactionDetails.totalInputsAmount = inputsAmount;
|
||||
|
||||
if (transaction.vin.size() > 0 && transaction.vin.front().type() == typeid(TransactionInputGenerate)) {
|
||||
if (transaction.inputs.size() > 0 && transaction.inputs.front().type() == typeid(BaseInput)) {
|
||||
//It's gen transaction
|
||||
transactionDetails.fee = 0;
|
||||
transactionDetails.mixin = 0;
|
||||
|
@ -252,106 +246,105 @@ bool BlockchainExplorerDataBuilder::fillTransactionDetails(const Transaction& tr
|
|||
}
|
||||
transactionDetails.mixin = mixin;
|
||||
}
|
||||
|
||||
crypto::hash paymentId;
|
||||
|
||||
Crypto::Hash paymentId;
|
||||
if (getPaymentId(transaction, paymentId)) {
|
||||
transactionDetails.paymentId = reinterpret_cast<const std::array<uint8_t, 32>&>(paymentId);
|
||||
transactionDetails.paymentId = paymentId;
|
||||
} else {
|
||||
transactionDetails.paymentId = boost::value_initialized<Crypto::Hash>();
|
||||
}
|
||||
else {
|
||||
transactionDetails.paymentId = boost::value_initialized<std::array<uint8_t, 32>>();
|
||||
}
|
||||
|
||||
|
||||
fillTxExtra(transaction.extra, transactionDetails.extra);
|
||||
|
||||
|
||||
transactionDetails.signatures.reserve(transaction.signatures.size());
|
||||
for (const std::vector<crypto::signature>& signatures : transaction.signatures) {
|
||||
std::vector<std::array<uint8_t, 32>> signaturesDetails;
|
||||
for (const std::vector<Crypto::Signature>& signatures : transaction.signatures) {
|
||||
std::vector<Crypto::Signature> signaturesDetails;
|
||||
signaturesDetails.reserve(signatures.size());
|
||||
for (const crypto::signature& signature : signatures) {
|
||||
signaturesDetails.push_back(std::move(reinterpret_cast<const std::array<uint8_t, 32>&>(signature)));
|
||||
for (const Crypto::Signature& signature : signatures) {
|
||||
signaturesDetails.push_back(std::move(signature));
|
||||
}
|
||||
transactionDetails.signatures.push_back(std::move(signaturesDetails));
|
||||
}
|
||||
|
||||
transactionDetails.inputs.reserve(transaction.vin.size());
|
||||
for (const TransactionInput& txIn : transaction.vin) {
|
||||
|
||||
transactionDetails.inputs.reserve(transaction.inputs.size());
|
||||
for (const TransactionInput& txIn : transaction.inputs) {
|
||||
TransactionInputDetails txInDetails;
|
||||
|
||||
if (txIn.type() == typeid(TransactionInputGenerate)) {
|
||||
if (txIn.type() == typeid(BaseInput)) {
|
||||
TransactionInputGenerateDetails txInGenDetails;
|
||||
txInGenDetails.height = boost::get<TransactionInputGenerate>(txIn).height;
|
||||
txInGenDetails.height = boost::get<BaseInput>(txIn).blockIndex;
|
||||
txInDetails.amount = 0;
|
||||
for (const TransactionOutput& out : transaction.vout) {
|
||||
for (const TransactionOutput& out : transaction.outputs) {
|
||||
txInDetails.amount += out.amount;
|
||||
}
|
||||
txInDetails.input = txInGenDetails;
|
||||
} else if (txIn.type() == typeid(TransactionInputToKey)) {
|
||||
} else if (txIn.type() == typeid(KeyInput)) {
|
||||
TransactionInputToKeyDetails txInToKeyDetails;
|
||||
const TransactionInputToKey& txInToKey = boost::get<TransactionInputToKey>(txIn);
|
||||
std::list<std::pair<crypto::hash, size_t>> outputReferences;
|
||||
const KeyInput& txInToKey = boost::get<KeyInput>(txIn);
|
||||
std::list<std::pair<Crypto::Hash, size_t>> outputReferences;
|
||||
if (!core.scanOutputkeysForIndices(txInToKey, outputReferences)) {
|
||||
return false;
|
||||
}
|
||||
txInDetails.amount = txInToKey.amount;
|
||||
txInToKeyDetails.keyOffsets = txInToKey.keyOffsets;
|
||||
txInToKeyDetails.keyImage = reinterpret_cast<const std::array<uint8_t, 16>&>(txInToKey.keyImage);
|
||||
txInToKeyDetails.mixin = txInToKey.keyOffsets.size();
|
||||
txInToKeyDetails.outputIndexes = txInToKey.outputIndexes;
|
||||
txInToKeyDetails.keyImage = txInToKey.keyImage;
|
||||
txInToKeyDetails.mixin = txInToKey.outputIndexes.size();
|
||||
txInToKeyDetails.output.number = outputReferences.back().second;
|
||||
txInToKeyDetails.output.transactionHash = reinterpret_cast<const std::array<uint8_t, 32>&>(outputReferences.back().first);
|
||||
txInToKeyDetails.output.transactionHash = outputReferences.back().first;
|
||||
txInDetails.input = txInToKeyDetails;
|
||||
} else if (txIn.type() == typeid(TransactionInputMultisignature)) {
|
||||
} else if (txIn.type() == typeid(MultisignatureInput)) {
|
||||
TransactionInputMultisignatureDetails txInMultisigDetails;
|
||||
const TransactionInputMultisignature& txInMultisig = boost::get<TransactionInputMultisignature>(txIn);
|
||||
const MultisignatureInput& txInMultisig = boost::get<MultisignatureInput>(txIn);
|
||||
txInDetails.amount = txInMultisig.amount;
|
||||
txInMultisigDetails.signatures = txInMultisig.signatures;
|
||||
std::pair<crypto::hash, size_t> outputReference;
|
||||
txInMultisigDetails.signatures = txInMultisig.signatureCount;
|
||||
std::pair<Crypto::Hash, size_t> outputReference;
|
||||
if (!core.getMultisigOutputReference(txInMultisig, outputReference)) {
|
||||
return false;
|
||||
}
|
||||
txInMultisigDetails.output.number = outputReference.second;
|
||||
txInMultisigDetails.output.transactionHash = reinterpret_cast<const std::array<uint8_t, 32>&>(outputReference.first);
|
||||
txInMultisigDetails.output.transactionHash = outputReference.first;
|
||||
txInDetails.input = txInMultisigDetails;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
transactionDetails.inputs.push_back(std::move(txInDetails));
|
||||
}
|
||||
|
||||
transactionDetails.outputs.reserve(transaction.vout.size());
|
||||
std::vector<uint64_t> globalIndices;
|
||||
globalIndices.reserve(transaction.vout.size());
|
||||
if (!core.get_tx_outputs_gindexs(hash, globalIndices)) {
|
||||
for (size_t i = 0; i < transaction.vout.size(); ++i) {
|
||||
|
||||
transactionDetails.outputs.reserve(transaction.outputs.size());
|
||||
std::vector<uint32_t> globalIndices;
|
||||
globalIndices.reserve(transaction.outputs.size());
|
||||
if (!transactionDetails.inBlockchain || !core.get_tx_outputs_gindexs(hash, globalIndices)) {
|
||||
for (size_t i = 0; i < transaction.outputs.size(); ++i) {
|
||||
globalIndices.push_back(0);
|
||||
}
|
||||
}
|
||||
|
||||
typedef boost::tuple<TransactionOutput, uint64_t> outputWithIndex;
|
||||
auto range = boost::combine(transaction.vout, globalIndices);
|
||||
typedef boost::tuple<TransactionOutput, uint32_t> outputWithIndex;
|
||||
auto range = boost::combine(transaction.outputs, globalIndices);
|
||||
for (const outputWithIndex& txOutput : range) {
|
||||
TransactionOutputDetails txOutDetails;
|
||||
txOutDetails.amount = txOutput.get<0>().amount;
|
||||
txOutDetails.globalIndex = txOutput.get<1>();
|
||||
|
||||
if (txOutput.get<0>().target.type() == typeid(TransactionOutputToKey)) {
|
||||
if (txOutput.get<0>().target.type() == typeid(KeyOutput)) {
|
||||
TransactionOutputToKeyDetails txOutToKeyDetails;
|
||||
txOutToKeyDetails.txOutKey = reinterpret_cast<const std::array<uint8_t, 16>&>(boost::get<TransactionOutputToKey>(txOutput.get<0>().target).key);
|
||||
txOutToKeyDetails.txOutKey = boost::get<KeyOutput>(txOutput.get<0>().target).key;
|
||||
txOutDetails.output = txOutToKeyDetails;
|
||||
} else if (txOutput.get<0>().target.type() == typeid(TransactionOutputMultisignature)) {
|
||||
} else if (txOutput.get<0>().target.type() == typeid(MultisignatureOutput)) {
|
||||
TransactionOutputMultisignatureDetails txOutMultisigDetails;
|
||||
TransactionOutputMultisignature txOutMultisig = boost::get<TransactionOutputMultisignature>(txOutput.get<0>().target);
|
||||
MultisignatureOutput txOutMultisig = boost::get<MultisignatureOutput>(txOutput.get<0>().target);
|
||||
txOutMultisigDetails.keys.reserve(txOutMultisig.keys.size());
|
||||
for (const crypto::public_key& key : txOutMultisig.keys) {
|
||||
txOutMultisigDetails.keys.push_back(std::move(reinterpret_cast<const std::array<uint8_t, 16>&>(key)));
|
||||
for (const Crypto::PublicKey& key : txOutMultisig.keys) {
|
||||
txOutMultisigDetails.keys.push_back(std::move(key));
|
||||
}
|
||||
txOutMultisigDetails.requiredSignatures = txOutMultisig.requiredSignatures;
|
||||
txOutMultisigDetails.requiredSignatures = txOutMultisig.requiredSignatureCount;
|
||||
txOutDetails.output = txOutMultisigDetails;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
transactionDetails.outputs.push_back(std::move(txOutDetails));
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
11
src/BlockchainExplorer/BlockchainExplorerDataBuilder.h
Normal file → Executable file
11
src/BlockchainExplorer/BlockchainExplorerDataBuilder.h
Normal file → Executable file
|
@ -20,8 +20,8 @@
|
|||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
#include "cryptonote_protocol/ICryptonoteProtocolQuery.h"
|
||||
#include "cryptonote_core/ICore.h"
|
||||
#include "CryptoNoteProtocol/ICryptoNoteProtocolQuery.h"
|
||||
#include "CryptoNoteCore/ICore.h"
|
||||
#include "BlockchainExplorerData.h"
|
||||
|
||||
namespace CryptoNote {
|
||||
|
@ -29,7 +29,7 @@ namespace CryptoNote {
|
|||
class BlockchainExplorerDataBuilder
|
||||
{
|
||||
public:
|
||||
BlockchainExplorerDataBuilder(CryptoNote::ICore& core, CryptoNote::ICryptonoteProtocolQuery& protocol);
|
||||
BlockchainExplorerDataBuilder(CryptoNote::ICore& core, CryptoNote::ICryptoNoteProtocolQuery& protocol);
|
||||
|
||||
BlockchainExplorerDataBuilder(const BlockchainExplorerDataBuilder&) = delete;
|
||||
BlockchainExplorerDataBuilder(BlockchainExplorerDataBuilder&&) = delete;
|
||||
|
@ -40,13 +40,14 @@ public:
|
|||
bool fillBlockDetails(const Block& block, BlockDetails& blockDetails);
|
||||
bool fillTransactionDetails(const Transaction &tx, TransactionDetails& txRpcInfo, uint64_t timestamp = 0);
|
||||
|
||||
static bool getPaymentId(const Transaction& transaction, Crypto::Hash& paymentId);
|
||||
|
||||
private:
|
||||
bool getMixin(const Transaction& transaction, uint64_t& mixin);
|
||||
bool getPaymentId(const Transaction& transaction, crypto::hash& paymentId);
|
||||
bool fillTxExtra(const std::vector<uint8_t>& rawExtra, TransactionExtraDetails& extraDetails);
|
||||
size_t median(std::vector<size_t>& v);
|
||||
|
||||
CryptoNote::ICore& core;
|
||||
CryptoNote::ICryptonoteProtocolQuery& protocol;
|
||||
CryptoNote::ICryptoNoteProtocolQuery& protocol;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -2,20 +2,19 @@ add_definitions(-DSTATICLIB)
|
|||
|
||||
file(GLOB_RECURSE BlockchainExplorer BlockchainExplorer/*)
|
||||
file(GLOB_RECURSE Common Common/*)
|
||||
file(GLOB_RECURSE ConnectivityTool connectivity_tool/*)
|
||||
file(GLOB_RECURSE ConnectivityTool ConnectivityTool/*)
|
||||
file(GLOB_RECURSE Crypto crypto/*)
|
||||
file(GLOB_RECURSE CryptoNote CryptoNote/*)
|
||||
file(GLOB_RECURSE CryptoNoteCore cryptonote_core/* cryptonote_config.h)
|
||||
file(GLOB_RECURSE CryptoNoteProtocol cryptonote_protocol/*)
|
||||
file(GLOB_RECURSE Daemon daemon/*)
|
||||
file(GLOB_RECURSE CryptoNoteCore CryptoNoteCore/* CryptoNoteConfig.h)
|
||||
file(GLOB_RECURSE CryptoNoteProtocol CryptoNoteProtocol/*)
|
||||
file(GLOB_RECURSE Daemon Daemon/*)
|
||||
file(GLOB_RECURSE Http HTTP/*)
|
||||
file(GLOB_RECURSE InProcessNode InProcessNode/*)
|
||||
file(GLOB_RECURSE Logging Logging/*)
|
||||
file(GLOB_RECURSE NodeRpcProxy node_rpc_proxy/*)
|
||||
file(GLOB_RECURSE P2p p2p/*)
|
||||
file(GLOB_RECURSE Rpc rpc/*)
|
||||
file(GLOB_RECURSE Serialization serialization/*)
|
||||
file(GLOB_RECURSE SimpleWallet simplewallet/*)
|
||||
file(GLOB_RECURSE NodeRpcProxy NodeRpcProxy/*)
|
||||
file(GLOB_RECURSE P2p P2p/*)
|
||||
file(GLOB_RECURSE Rpc Rpc/*)
|
||||
file(GLOB_RECURSE Serialization Serialization/*)
|
||||
file(GLOB_RECURSE SimpleWallet SimpleWallet/*)
|
||||
if(MSVC)
|
||||
file(GLOB_RECURSE System System/* Platform/Windows/System/*)
|
||||
elseif(APPLE)
|
||||
|
@ -23,17 +22,20 @@ file(GLOB_RECURSE System System/* Platform/OSX/System/*)
|
|||
else()
|
||||
file(GLOB_RECURSE System System/* Platform/Linux/System/*)
|
||||
endif()
|
||||
file(GLOB_RECURSE Transfers transfers/*)
|
||||
file(GLOB_RECURSE Wallet wallet/*)
|
||||
file(GLOB_RECURSE PaymentService payment_service/*)
|
||||
file(GLOB_RECURSE Transfers Transfers/*)
|
||||
file(GLOB_RECURSE Wallet Wallet/*)
|
||||
file(GLOB_RECURSE WalletLegacy WalletLegacy/*)
|
||||
|
||||
file(GLOB_RECURSE JsonRpcServer JsonRpcServer/*)
|
||||
|
||||
source_group("" FILES ${Common} ${ConnectivityTool} ${Crypto} ${CryptoNote} ${CryptoNoteCore} ${CryptoNoteProtocol} ${Daemon} ${Http} ${Logging} ${NodeRpcProxy} ${P2p} ${Rpc} ${Serialization} ${SimpleWallet} ${System} ${Transfers} ${Wallet})
|
||||
file(GLOB_RECURSE PaymentGate PaymentGate/*)
|
||||
file(GLOB_RECURSE PaymentGateService PaymentGateService/*)
|
||||
|
||||
source_group("" FILES $${Common} ${ConnectivityTool} ${Crypto} ${CryptoNoteCore} ${CryptoNoteProtocol} ${Daemon} ${JsonRpcServer} ${Http} ${Logging} ${NodeRpcProxy} ${P2p} ${Rpc} ${Serialization} ${SimpleWallet} ${System} ${Transfers} ${Wallet} ${WalletLegacy})
|
||||
|
||||
add_library(BlockchainExplorer ${BlockchainExplorer})
|
||||
add_library(Common ${Common})
|
||||
add_library(Crypto ${Crypto})
|
||||
add_library(CryptoNote ${CryptoNote})
|
||||
add_library(CryptoNoteCore ${CryptoNoteCore})
|
||||
add_library(Http ${Http})
|
||||
add_library(InProcessNode ${InProcessNode})
|
||||
|
@ -44,27 +46,35 @@ add_library(P2P ${CryptoNoteProtocol} ${P2p})
|
|||
add_library(Serialization ${Serialization})
|
||||
add_library(System ${System})
|
||||
add_library(Transfers ${Transfers})
|
||||
add_library(Wallet ${Wallet})
|
||||
add_library(Wallet ${Wallet} ${WalletLegacy})
|
||||
add_library(PaymentGate ${PaymentGate})
|
||||
add_library(JsonRpcServer ${JsonRpcServer})
|
||||
|
||||
add_executable(ConnectivityTool ${ConnectivityTool})
|
||||
add_executable(Daemon ${Daemon})
|
||||
add_executable(SimpleWallet ${SimpleWallet})
|
||||
add_executable(PaymentGate ${PaymentService})
|
||||
add_executable(PaymentGateService ${PaymentGateService})
|
||||
|
||||
|
||||
target_link_libraries(ConnectivityTool CryptoNoteCore Common Logging Crypto P2P Rpc Http Serialization System ${Boost_LIBRARIES})
|
||||
target_link_libraries(Daemon CryptoNoteCore P2P Rpc Serialization System Http Logging Common Crypto upnpc-static ${Boost_LIBRARIES})
|
||||
target_link_libraries(Daemon CryptoNoteCore P2P Rpc Serialization System Http Logging Common Crypto upnpc-static BlockchainExplorer ${Boost_LIBRARIES})
|
||||
target_link_libraries(SimpleWallet Wallet NodeRpcProxy Transfers Rpc Http Serialization CryptoNoteCore System Logging Common Crypto ${Boost_LIBRARIES})
|
||||
target_link_libraries(PaymentGate Wallet NodeRpcProxy Transfers CryptoNoteCore Crypto P2P Rpc Http Serialization System Logging Common InProcessNode BlockchainExplorer upnpc-static ${Boost_LIBRARIES})
|
||||
target_link_libraries(PaymentGateService PaymentGate JsonRpcServer Wallet NodeRpcProxy Transfers CryptoNoteCore Crypto P2P Rpc Http Serialization System Logging Common InProcessNode upnpc-static BlockchainExplorer ${Boost_LIBRARIES})
|
||||
|
||||
if (MSVC)
|
||||
target_link_libraries(ConnectivityTool ws2_32)
|
||||
target_link_libraries(SimpleWallet ws2_32)
|
||||
endif ()
|
||||
|
||||
add_dependencies(Rpc version)
|
||||
|
||||
add_dependencies(ConnectivityTool version)
|
||||
add_dependencies(Daemon version)
|
||||
add_dependencies(SimpleWallet version)
|
||||
add_dependencies(PaymentGate version)
|
||||
add_dependencies(PaymentGateService version)
|
||||
add_dependencies(P2P version)
|
||||
|
||||
set_property(TARGET ConnectivityTool PROPERTY OUTPUT_NAME "connectivity_tool")
|
||||
set_property(TARGET Daemon PROPERTY OUTPUT_NAME "bytecoind")
|
||||
set_property(TARGET SimpleWallet PROPERTY OUTPUT_NAME "simplewallet")
|
||||
set_property(TARGET PaymentGate PROPERTY OUTPUT_NAME "walletd")
|
||||
set_property(TARGET PaymentGateService PROPERTY OUTPUT_NAME "walletd")
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace Common {
|
|||
// 'data' == 'nullptr' && 'size' > 0 - Undefined
|
||||
// 'data' != 'nullptr' && 'size' > 0 - NOTEMPTY NOTNIL
|
||||
// For signed integer 'Size', 'ArrayRef' with 'size' < 0 is undefined.
|
||||
template<class ObjectType = uint8_t, class SizeType = std::size_t> class ArrayRef {
|
||||
template<class ObjectType = uint8_t, class SizeType = size_t> class ArrayRef {
|
||||
public:
|
||||
typedef ObjectType Object;
|
||||
typedef SizeType Size;
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace Common {
|
|||
// 'data' == 'nullptr' && 'size' > 0 - Undefined
|
||||
// 'data' != 'nullptr' && 'size' > 0 - NOTEMPTY NOTNIL
|
||||
// For signed integer 'Size', 'ArrayView' with 'size' < 0 is undefined.
|
||||
template<class Object = uint8_t, class Size = std::size_t> class ArrayView {
|
||||
template<class Object = uint8_t, class Size = size_t> class ArrayView {
|
||||
public:
|
||||
typedef Object ObjectType;
|
||||
typedef Size SizeType;
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "base58.h"
|
||||
#include "Base58.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string>
|
||||
|
@ -23,11 +23,11 @@
|
|||
|
||||
#include "crypto/hash.h"
|
||||
#include "int-util.h"
|
||||
#include "varint.h"
|
||||
#include "Varint.h"
|
||||
|
||||
namespace tools
|
||||
namespace Tools
|
||||
{
|
||||
namespace base58
|
||||
namespace Base58
|
||||
{
|
||||
namespace
|
||||
{
|
||||
|
@ -227,7 +227,7 @@ namespace tools
|
|||
{
|
||||
std::string buf = get_varint_data(tag);
|
||||
buf += data;
|
||||
crypto::hash hash = crypto::cn_fast_hash(buf.data(), buf.size());
|
||||
Crypto::Hash hash = Crypto::cn_fast_hash(buf.data(), buf.size());
|
||||
const char* hash_data = reinterpret_cast<const char*>(&hash);
|
||||
buf.append(hash_data, addr_checksum_size);
|
||||
return encode(buf);
|
||||
|
@ -244,11 +244,11 @@ namespace tools
|
|||
checksum = addr_data.substr(addr_data.size() - addr_checksum_size);
|
||||
|
||||
addr_data.resize(addr_data.size() - addr_checksum_size);
|
||||
crypto::hash hash = crypto::cn_fast_hash(addr_data.data(), addr_data.size());
|
||||
Crypto::Hash hash = Crypto::cn_fast_hash(addr_data.data(), addr_data.size());
|
||||
std::string expected_checksum(reinterpret_cast<const char*>(&hash), addr_checksum_size);
|
||||
if (expected_checksum != checksum) return false;
|
||||
|
||||
int read = tools::read_varint(addr_data.begin(), addr_data.end(), tag);
|
||||
int read = Tools::read_varint(addr_data.begin(), addr_data.end(), tag);
|
||||
if (read <= 0) return false;
|
||||
|
||||
data = addr_data.substr(read);
|
4
src/Common/base58.h → src/Common/Base58.h
Normal file → Executable file
4
src/Common/base58.h → src/Common/Base58.h
Normal file → Executable file
|
@ -20,9 +20,9 @@
|
|||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace tools
|
||||
namespace Tools
|
||||
{
|
||||
namespace base58
|
||||
namespace Base58
|
||||
{
|
||||
std::string encode(const std::string& data);
|
||||
bool decode(const std::string& enc, std::string& data);
|
|
@ -16,3 +16,7 @@
|
|||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "BlockingQueue.h"
|
||||
|
||||
namespace {
|
||||
char suppressMSVCWarningLNK4221;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "command_line.h"
|
||||
#include "CommandLine.h"
|
||||
|
||||
namespace command_line
|
||||
{
|
0
src/Common/command_line.h → src/Common/CommandLine.h
Normal file → Executable file
0
src/Common/command_line.h → src/Common/CommandLine.h
Normal file → Executable file
|
@ -24,7 +24,7 @@ namespace Common {
|
|||
class IInputStream {
|
||||
public:
|
||||
virtual ~IInputStream() { }
|
||||
virtual std::size_t readSome(void* data, std::size_t size) = 0;
|
||||
virtual size_t readSome(void* data, size_t size) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace Common {
|
|||
class IOutputStream {
|
||||
public:
|
||||
virtual ~IOutputStream() { }
|
||||
virtual std::size_t writeSome(const void* data, std::size_t size) = 0;
|
||||
virtual size_t writeSome(const void* data, size_t size) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -492,7 +492,7 @@ const JsonValue::String& JsonValue::getString() const {
|
|||
return *reinterpret_cast<const String*>(valueString);
|
||||
}
|
||||
|
||||
std::size_t JsonValue::size() const {
|
||||
size_t JsonValue::size() const {
|
||||
switch (type) {
|
||||
case ARRAY:
|
||||
return reinterpret_cast<const Array*>(valueArray)->size();
|
||||
|
@ -503,7 +503,7 @@ std::size_t JsonValue::size() const {
|
|||
}
|
||||
}
|
||||
|
||||
JsonValue& JsonValue::operator[](std::size_t index) {
|
||||
JsonValue& JsonValue::operator[](size_t index) {
|
||||
if (type != ARRAY) {
|
||||
throw std::runtime_error("JsonValue type is not ARRAY");
|
||||
}
|
||||
|
@ -511,7 +511,7 @@ JsonValue& JsonValue::operator[](std::size_t index) {
|
|||
return reinterpret_cast<Array*>(valueArray)->at(index);
|
||||
}
|
||||
|
||||
const JsonValue& JsonValue::operator[](std::size_t index) const {
|
||||
const JsonValue& JsonValue::operator[](size_t index) const {
|
||||
if (type != ARRAY) {
|
||||
throw std::runtime_error("JsonValue type is not ARRAY");
|
||||
}
|
||||
|
@ -567,7 +567,7 @@ JsonValue& JsonValue::set(const Key& key, JsonValue&& value) {
|
|||
return *this;
|
||||
}
|
||||
|
||||
std::size_t JsonValue::erase(const Key& key) {
|
||||
size_t JsonValue::erase(const Key& key) {
|
||||
return getObject().erase(key);
|
||||
}
|
||||
|
||||
|
@ -595,7 +595,7 @@ std::ostream& operator<<(std::ostream& out, const JsonValue& jsonValue) {
|
|||
out << '[';
|
||||
if (array.size() > 0) {
|
||||
out << array[0];
|
||||
for (std::size_t i = 1; i < array.size(); ++i) {
|
||||
for (size_t i = 1; i < array.size(); ++i) {
|
||||
out << ',' << array[i];
|
||||
}
|
||||
}
|
||||
|
@ -811,7 +811,7 @@ void JsonValue::readNull(std::istream& in) {
|
|||
void JsonValue::readNumber(std::istream& in, char c) {
|
||||
std::string text;
|
||||
text += c;
|
||||
std::size_t dots = 0;
|
||||
size_t dots = 0;
|
||||
for (;;) {
|
||||
int i = in.peek();
|
||||
if (i >= '0' && i <= '9') {
|
||||
|
|
|
@ -61,7 +61,7 @@ public:
|
|||
JsonValue(Real value);
|
||||
JsonValue(const String& value);
|
||||
JsonValue(String&& value);
|
||||
template<std::size_t size> JsonValue(const char(&value)[size]) {
|
||||
template<size_t size> JsonValue(const char(&value)[size]) {
|
||||
new(valueString)String(value, size - 1);
|
||||
type = STRING;
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ public:
|
|||
JsonValue& operator=(Real value);
|
||||
JsonValue& operator=(const String& value);
|
||||
JsonValue& operator=(String&& value);
|
||||
template<std::size_t size> JsonValue& operator=(const char(&value)[size]) {
|
||||
template<size_t size> JsonValue& operator=(const char(&value)[size]) {
|
||||
if (type != STRING) {
|
||||
destructValue();
|
||||
type = NIL;
|
||||
|
@ -112,10 +112,10 @@ public:
|
|||
String& getString();
|
||||
const String& getString() const;
|
||||
|
||||
std::size_t size() const;
|
||||
size_t size() const;
|
||||
|
||||
JsonValue& operator[](std::size_t index);
|
||||
const JsonValue& operator[](std::size_t index) const;
|
||||
JsonValue& operator[](size_t index);
|
||||
const JsonValue& operator[](size_t index) const;
|
||||
JsonValue& pushBack(const JsonValue& value);
|
||||
JsonValue& pushBack(JsonValue&& value);
|
||||
|
||||
|
@ -129,7 +129,7 @@ public:
|
|||
JsonValue& set(const Key& key, const JsonValue& value);
|
||||
JsonValue& set(const Key& key, JsonValue&& value);
|
||||
|
||||
std::size_t erase(const Key& key);
|
||||
size_t erase(const Key& key);
|
||||
|
||||
static JsonValue fromString(const std::string& source);
|
||||
std::string toString() const;
|
||||
|
|
|
@ -16,3 +16,7 @@
|
|||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "Math.h"
|
||||
|
||||
namespace {
|
||||
char suppressMSVCWarningLNK4221;
|
||||
}
|
||||
|
|
35
src/CryptoNote/MultisignatureOutput.cpp → src/Common/MemoryInputStream.cpp
Executable file → Normal file
35
src/CryptoNote/MultisignatureOutput.cpp → src/Common/MemoryInputStream.cpp
Executable file → Normal file
|
@ -15,29 +15,34 @@
|
|||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "MultisignatureOutput.h"
|
||||
#include "MemoryInputStream.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstring> // memcpy
|
||||
|
||||
namespace CryptoNote {
|
||||
namespace Common {
|
||||
|
||||
MultisignatureOutput::MultisignatureOutput(uint64_t amount, std::vector<crypto::public_key>&& keys, uint32_t requiredSignatureCount) : amount(amount), keys(std::move(keys)), requiredSignatureCount(requiredSignatureCount) {
|
||||
assert(requiredSignatureCount <= keys.size());
|
||||
MemoryInputStream::MemoryInputStream(const void* buffer, size_t bufferSize) :
|
||||
buffer(static_cast<const char*>(buffer)), bufferSize(bufferSize), position(0) {}
|
||||
|
||||
size_t MemoryInputStream::getPosition() const {
|
||||
return position;
|
||||
}
|
||||
|
||||
uint64_t MultisignatureOutput::getAmount() const {
|
||||
return amount;
|
||||
bool MemoryInputStream::endOfStream() const {
|
||||
return position == bufferSize;
|
||||
}
|
||||
|
||||
uint32_t MultisignatureOutput::getKeyCount() const {
|
||||
return static_cast<uint32_t>(keys.size());
|
||||
}
|
||||
size_t MemoryInputStream::readSome(void* data, size_t size) {
|
||||
assert(position <= bufferSize);
|
||||
size_t readSize = std::min(size, bufferSize - position);
|
||||
|
||||
const crypto::public_key& MultisignatureOutput::getKey(uint32_t index) const {
|
||||
return keys[index];
|
||||
}
|
||||
|
||||
uint32_t MultisignatureOutput::getRequiredSignatureCount() const {
|
||||
return requiredSignatureCount;
|
||||
if (readSize > 0) {
|
||||
memcpy(data, buffer + position, readSize);
|
||||
position += readSize;
|
||||
}
|
||||
|
||||
return readSize;
|
||||
}
|
||||
|
||||
}
|
29
src/CryptoNote/KeyOutput.h → src/Common/MemoryInputStream.h
Executable file → Normal file
29
src/CryptoNote/KeyOutput.h → src/Common/MemoryInputStream.h
Executable file → Normal file
|
@ -17,21 +17,22 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "../crypto/crypto.h"
|
||||
#include "IInputStream.h"
|
||||
|
||||
namespace CryptoNote {
|
||||
namespace Common {
|
||||
|
||||
class KeyOutput {
|
||||
public:
|
||||
KeyOutput(uint64_t amount, const crypto::public_key& key);
|
||||
KeyOutput(const KeyOutput& other) = delete;
|
||||
KeyOutput& operator=(const KeyOutput& other) = delete;
|
||||
uint64_t getAmount() const;
|
||||
const crypto::public_key& getKey() const;
|
||||
|
||||
private:
|
||||
uint64_t amount;
|
||||
crypto::public_key key;
|
||||
};
|
||||
class MemoryInputStream : public IInputStream {
|
||||
public:
|
||||
MemoryInputStream(const void* buffer, size_t bufferSize);
|
||||
size_t getPosition() const;
|
||||
bool endOfStream() const;
|
||||
|
||||
// IInputStream
|
||||
virtual size_t readSome(void* data, size_t size) override;
|
||||
|
||||
private:
|
||||
const char* buffer;
|
||||
size_t bufferSize;
|
||||
size_t position;
|
||||
};
|
||||
}
|
3
src/Common/ObserverManager.h
Normal file → Executable file
3
src/Common/ObserverManager.h
Normal file → Executable file
|
@ -21,7 +21,7 @@
|
|||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
namespace tools {
|
||||
namespace Tools {
|
||||
|
||||
template<typename T>
|
||||
class ObserverManager {
|
||||
|
@ -39,6 +39,7 @@ public:
|
|||
|
||||
bool remove(T* observer) {
|
||||
std::unique_lock<std::mutex> lock(m_observersMutex);
|
||||
|
||||
auto it = std::find(m_observers.begin(), m_observers.end(), observer);
|
||||
if (m_observers.end() == it) {
|
||||
return false;
|
||||
|
|
23
src/Common/SignalHandler.cpp
Normal file → Executable file
23
src/Common/SignalHandler.cpp
Normal file → Executable file
|
@ -27,6 +27,7 @@
|
|||
#include <Windows.h>
|
||||
#else
|
||||
#include <signal.h>
|
||||
#include <cstring>
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
@ -65,7 +66,7 @@ void posixHandler(int /*type*/) {
|
|||
}
|
||||
|
||||
|
||||
namespace tools {
|
||||
namespace Tools {
|
||||
|
||||
bool SignalHandler::install(std::function<void(void)> t)
|
||||
{
|
||||
|
@ -76,9 +77,23 @@ namespace tools {
|
|||
}
|
||||
return r;
|
||||
#else
|
||||
signal(SIGINT, posixHandler);
|
||||
signal(SIGTERM, posixHandler);
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
struct sigaction newMask;
|
||||
std::memset(&newMask, 0, sizeof(struct sigaction));
|
||||
newMask.sa_handler = posixHandler;
|
||||
if (sigaction(SIGINT, &newMask, nullptr) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sigaction(SIGTERM, &newMask, nullptr) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::memset(&newMask, 0, sizeof(struct sigaction));
|
||||
newMask.sa_handler = SIG_IGN;
|
||||
if (sigaction(SIGPIPE, &newMask, nullptr) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_handler = t;
|
||||
return true;
|
||||
#endif
|
||||
|
|
2
src/Common/SignalHandler.h
Normal file → Executable file
2
src/Common/SignalHandler.h
Normal file → Executable file
|
@ -19,7 +19,7 @@
|
|||
|
||||
#include <functional>
|
||||
|
||||
namespace tools {
|
||||
namespace Tools {
|
||||
|
||||
class SignalHandler
|
||||
{
|
||||
|
|
30
src/Common/StdInputStream.cpp
Normal file
30
src/Common/StdInputStream.cpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "StdInputStream.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
StdInputStream::StdInputStream(std::istream& in) : in(in) {
|
||||
}
|
||||
|
||||
size_t StdInputStream::readSome(void* data, size_t size) {
|
||||
in.read(static_cast<char*>(data), size);
|
||||
return in.gcount();
|
||||
}
|
||||
|
||||
}
|
35
src/Common/StdInputStream.h
Normal file
35
src/Common/StdInputStream.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <istream>
|
||||
#include "IInputStream.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
class StdInputStream : public IInputStream {
|
||||
public:
|
||||
StdInputStream(std::istream& in);
|
||||
StdInputStream& operator=(const StdInputStream&) = delete;
|
||||
size_t readSome(void* data, size_t size) override;
|
||||
|
||||
private:
|
||||
std::istream& in;
|
||||
};
|
||||
|
||||
}
|
34
src/Common/StdOutputStream.cpp
Normal file
34
src/Common/StdOutputStream.cpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "StdOutputStream.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
StdOutputStream::StdOutputStream(std::ostream& out) : out(out) {
|
||||
}
|
||||
|
||||
size_t StdOutputStream::writeSome(const void* data, size_t size) {
|
||||
out.write(static_cast<const char*>(data), size);
|
||||
if (out.bad()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
}
|
35
src/Common/StdOutputStream.h
Normal file
35
src/Common/StdOutputStream.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ostream>
|
||||
#include "IOutputStream.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
class StdOutputStream : public IOutputStream {
|
||||
public:
|
||||
StdOutputStream(std::ostream& out);
|
||||
StdOutputStream& operator=(const StdOutputStream&) = delete;
|
||||
size_t writeSome(const void* data, size_t size) override;
|
||||
|
||||
private:
|
||||
std::ostream& out;
|
||||
};
|
||||
|
||||
}
|
|
@ -22,9 +22,9 @@
|
|||
|
||||
namespace Common {
|
||||
|
||||
void read(IInputStream& in, void* data, std::size_t size) {
|
||||
void read(IInputStream& in, void* data, size_t size) {
|
||||
while (size > 0) {
|
||||
std::size_t readSize = in.readSome(data, size);
|
||||
size_t readSize = in.readSome(data, size);
|
||||
if (readSize == 0) {
|
||||
throw std::runtime_error("Failed to read from IInputStream");
|
||||
}
|
||||
|
@ -72,12 +72,12 @@ void read(IInputStream& in, uint64_t& value) {
|
|||
read(in, &value, sizeof(value));
|
||||
}
|
||||
|
||||
void read(IInputStream& in, std::vector<uint8_t>& data, std::size_t size) {
|
||||
void read(IInputStream& in, std::vector<uint8_t>& data, size_t size) {
|
||||
data.resize(size);
|
||||
read(in, data.data(), size);
|
||||
}
|
||||
|
||||
void read(IInputStream& in, std::string& data, std::size_t size) {
|
||||
void read(IInputStream& in, std::string& data, size_t size) {
|
||||
std::vector<char> temp(size);
|
||||
read(in, temp.data(), size);
|
||||
data.assign(temp.data(), size);
|
||||
|
@ -92,7 +92,7 @@ void readVarint(IInputStream& in, uint8_t& value) {
|
|||
throw std::runtime_error("readVarint, value overflow");
|
||||
}
|
||||
|
||||
temp |= static_cast<std::size_t>(piece & 0x7f) << shift;
|
||||
temp |= static_cast<size_t>(piece & 0x7f) << shift;
|
||||
if ((piece & 0x80) == 0) {
|
||||
if (piece == 0 && shift != 0) {
|
||||
throw std::runtime_error("readVarint, invalid value representation");
|
||||
|
@ -114,7 +114,7 @@ void readVarint(IInputStream& in, uint16_t& value) {
|
|||
throw std::runtime_error("readVarint, value overflow");
|
||||
}
|
||||
|
||||
temp |= static_cast<std::size_t>(piece & 0x7f) << shift;
|
||||
temp |= static_cast<size_t>(piece & 0x7f) << shift;
|
||||
if ((piece & 0x80) == 0) {
|
||||
if (piece == 0 && shift != 0) {
|
||||
throw std::runtime_error("readVarint, invalid value representation");
|
||||
|
@ -136,7 +136,7 @@ void readVarint(IInputStream& in, uint32_t& value) {
|
|||
throw std::runtime_error("readVarint, value overflow");
|
||||
}
|
||||
|
||||
temp |= static_cast<std::size_t>(piece & 0x7f) << shift;
|
||||
temp |= static_cast<size_t>(piece & 0x7f) << shift;
|
||||
if ((piece & 0x80) == 0) {
|
||||
if (piece == 0 && shift != 0) {
|
||||
throw std::runtime_error("readVarint, invalid value representation");
|
||||
|
@ -158,7 +158,7 @@ void readVarint(IInputStream& in, uint64_t& value) {
|
|||
throw std::runtime_error("readVarint, value overflow");
|
||||
}
|
||||
|
||||
temp |= static_cast<std::size_t>(piece & 0x7f) << shift;
|
||||
temp |= static_cast<size_t>(piece & 0x7f) << shift;
|
||||
if ((piece & 0x80) == 0) {
|
||||
if (piece == 0 && shift != 0) {
|
||||
throw std::runtime_error("readVarint, invalid value representation");
|
||||
|
@ -171,9 +171,9 @@ void readVarint(IInputStream& in, uint64_t& value) {
|
|||
value = temp;
|
||||
}
|
||||
|
||||
void write(IOutputStream& out, const void* data, std::size_t size) {
|
||||
void write(IOutputStream& out, const void* data, size_t size) {
|
||||
while (size > 0) {
|
||||
std::size_t writtenSize = out.writeSome(data, size);
|
||||
size_t writtenSize = out.writeSome(data, size);
|
||||
if (writtenSize == 0) {
|
||||
throw std::runtime_error("Failed to write to IOutputStream");
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace Common {
|
|||
class IInputStream;
|
||||
class IOutputStream;
|
||||
|
||||
void read(IInputStream& in, void* data, std::size_t size);
|
||||
void read(IInputStream& in, void* data, size_t size);
|
||||
void read(IInputStream& in, int8_t& value);
|
||||
void read(IInputStream& in, int16_t& value);
|
||||
void read(IInputStream& in, int32_t& value);
|
||||
|
@ -35,14 +35,14 @@ void read(IInputStream& in, uint8_t& value);
|
|||
void read(IInputStream& in, uint16_t& value);
|
||||
void read(IInputStream& in, uint32_t& value);
|
||||
void read(IInputStream& in, uint64_t& value);
|
||||
void read(IInputStream& in, std::vector<uint8_t>& data, std::size_t size);
|
||||
void read(IInputStream& in, std::string& data, std::size_t size);
|
||||
void read(IInputStream& in, std::vector<uint8_t>& data, size_t size);
|
||||
void read(IInputStream& in, std::string& data, size_t size);
|
||||
void readVarint(IInputStream& in, uint8_t& value);
|
||||
void readVarint(IInputStream& in, uint16_t& value);
|
||||
void readVarint(IInputStream& in, uint32_t& value);
|
||||
void readVarint(IInputStream& in, uint64_t& value);
|
||||
|
||||
void write(IOutputStream& out, const void* data, std::size_t size);
|
||||
void write(IOutputStream& out, const void* data, size_t size);
|
||||
void write(IOutputStream& out, int8_t value);
|
||||
void write(IOutputStream& out, int16_t value);
|
||||
void write(IOutputStream& out, int32_t value);
|
||||
|
@ -61,7 +61,7 @@ template<typename T> T read(IInputStream& in) {
|
|||
return value;
|
||||
}
|
||||
|
||||
template<typename T> T read(IInputStream& in, std::size_t size) {
|
||||
template<typename T> T read(IInputStream& in, size_t size) {
|
||||
T value;
|
||||
read(in, value, size);
|
||||
return value;
|
||||
|
|
|
@ -24,10 +24,10 @@
|
|||
namespace Common {
|
||||
|
||||
// 'StringBuffer' is a string of fixed maximum size.
|
||||
template<std::size_t MAXIMUM_SIZE_VALUE> class StringBuffer {
|
||||
template<size_t MAXIMUM_SIZE_VALUE> class StringBuffer {
|
||||
public:
|
||||
typedef char Object;
|
||||
typedef std::size_t Size;
|
||||
typedef size_t Size;
|
||||
|
||||
const static Size MAXIMUM_SIZE = MAXIMUM_SIZE_VALUE;
|
||||
const static Size INVALID;
|
||||
|
@ -549,6 +549,6 @@ protected:
|
|||
Size size;
|
||||
};
|
||||
|
||||
template<std::size_t MAXIMUM_SIZE> const typename StringBuffer<MAXIMUM_SIZE>::Size StringBuffer<MAXIMUM_SIZE>::INVALID = std::numeric_limits<typename StringBuffer<MAXIMUM_SIZE>::Size>::max();
|
||||
template<size_t MAXIMUM_SIZE> const typename StringBuffer<MAXIMUM_SIZE>::Size StringBuffer<MAXIMUM_SIZE>::INVALID = std::numeric_limits<typename StringBuffer<MAXIMUM_SIZE>::Size>::max();
|
||||
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace Common {
|
|||
StringInputStream::StringInputStream(const std::string& in) : in(in), offset(0) {
|
||||
}
|
||||
|
||||
std::size_t StringInputStream::readSome(void* data, std::size_t size) {
|
||||
size_t StringInputStream::readSome(void* data, size_t size) {
|
||||
if (size > in.size() - offset) {
|
||||
size = in.size() - offset;
|
||||
}
|
||||
|
|
|
@ -25,11 +25,11 @@ namespace Common {
|
|||
class StringInputStream : public IInputStream {
|
||||
public:
|
||||
StringInputStream(const std::string& in);
|
||||
std::size_t readSome(void* data, std::size_t size) override;
|
||||
size_t readSome(void* data, size_t size) override;
|
||||
|
||||
private:
|
||||
const std::string& in;
|
||||
std::size_t offset;
|
||||
size_t offset;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace Common {
|
|||
StringOutputStream::StringOutputStream(std::string& out) : out(out) {
|
||||
}
|
||||
|
||||
std::size_t StringOutputStream::writeSome(const void* data, std::size_t size) {
|
||||
size_t StringOutputStream::writeSome(const void* data, size_t size) {
|
||||
out.append(static_cast<const char*>(data), size);
|
||||
return size;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace Common {
|
|||
class StringOutputStream : public IOutputStream {
|
||||
public:
|
||||
StringOutputStream(std::string& out);
|
||||
std::size_t writeSome(const void* data, std::size_t size) override;
|
||||
size_t writeSome(const void* data, size_t size) override;
|
||||
|
||||
private:
|
||||
std::string& out;
|
||||
|
|
|
@ -43,7 +43,7 @@ const uint8_t characterValues[256] = {
|
|||
|
||||
}
|
||||
|
||||
std::string asString(const void* data, std::size_t size) {
|
||||
std::string asString(const void* data, size_t size) {
|
||||
return std::string(static_cast<const char*>(data), size);
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,11 @@ std::string asString(const std::vector<uint8_t>& data) {
|
|||
return std::string(reinterpret_cast<const char*>(data.data()), data.size());
|
||||
}
|
||||
|
||||
std::vector<uint8_t> asBinaryArray(const std::string& data) {
|
||||
auto dataPtr = reinterpret_cast<const uint8_t*>(data.data());
|
||||
return std::vector<uint8_t>(dataPtr, dataPtr + data.size());
|
||||
}
|
||||
|
||||
uint8_t fromHex(char character) {
|
||||
uint8_t value = characterValues[static_cast<unsigned char>(character)];
|
||||
if (value > 0x0f) {
|
||||
|
@ -69,7 +74,7 @@ bool fromHex(char character, uint8_t& value) {
|
|||
return true;
|
||||
}
|
||||
|
||||
std::size_t fromHex(const std::string& text, void* data, std::size_t bufferSize) {
|
||||
size_t fromHex(const std::string& text, void* data, size_t bufferSize) {
|
||||
if ((text.size() & 1) != 0) {
|
||||
throw std::runtime_error("fromHex: invalid string size");
|
||||
}
|
||||
|
@ -78,14 +83,14 @@ std::size_t fromHex(const std::string& text, void* data, std::size_t bufferSize)
|
|||
throw std::runtime_error("fromHex: invalid buffer size");
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < text.size() >> 1; ++i) {
|
||||
for (size_t i = 0; i < text.size() >> 1; ++i) {
|
||||
static_cast<uint8_t*>(data)[i] = fromHex(text[i << 1]) << 4 | fromHex(text[(i << 1) + 1]);
|
||||
}
|
||||
|
||||
return text.size() >> 1;
|
||||
}
|
||||
|
||||
bool fromHex(const std::string& text, void* data, std::size_t bufferSize, std::size_t& size) {
|
||||
bool fromHex(const std::string& text, void* data, size_t bufferSize, size_t& size) {
|
||||
if ((text.size() & 1) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
@ -94,7 +99,7 @@ bool fromHex(const std::string& text, void* data, std::size_t bufferSize, std::s
|
|||
return false;
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < text.size() >> 1; ++i) {
|
||||
for (size_t i = 0; i < text.size() >> 1; ++i) {
|
||||
uint8_t value1;
|
||||
if (!fromHex(text[i << 1], value1)) {
|
||||
return false;
|
||||
|
@ -118,7 +123,7 @@ std::vector<uint8_t> fromHex(const std::string& text) {
|
|||
}
|
||||
|
||||
std::vector<uint8_t> data(text.size() >> 1);
|
||||
for (std::size_t i = 0; i < data.size(); ++i) {
|
||||
for (size_t i = 0; i < data.size(); ++i) {
|
||||
data[i] = fromHex(text[i << 1]) << 4 | fromHex(text[(i << 1) + 1]);
|
||||
}
|
||||
|
||||
|
@ -130,7 +135,7 @@ bool fromHex(const std::string& text, std::vector<uint8_t>& data) {
|
|||
return false;
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < text.size() >> 1; ++i) {
|
||||
for (size_t i = 0; i < text.size() >> 1; ++i) {
|
||||
uint8_t value1;
|
||||
if (!fromHex(text[i << 1], value1)) {
|
||||
return false;
|
||||
|
@ -147,9 +152,9 @@ bool fromHex(const std::string& text, std::vector<uint8_t>& data) {
|
|||
return true;
|
||||
}
|
||||
|
||||
std::string toHex(const void* data, std::size_t size) {
|
||||
std::string toHex(const void* data, size_t size) {
|
||||
std::string text;
|
||||
for (std::size_t i = 0; i < size; ++i) {
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
text += "0123456789abcdef"[static_cast<const uint8_t*>(data)[i] >> 4];
|
||||
text += "0123456789abcdef"[static_cast<const uint8_t*>(data)[i] & 15];
|
||||
}
|
||||
|
@ -157,8 +162,8 @@ std::string toHex(const void* data, std::size_t size) {
|
|||
return text;
|
||||
}
|
||||
|
||||
void toHex(const void* data, std::size_t size, std::string& text) {
|
||||
for (std::size_t i = 0; i < size; ++i) {
|
||||
void toHex(const void* data, size_t size, std::string& text) {
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
text += "0123456789abcdef"[static_cast<const uint8_t*>(data)[i] >> 4];
|
||||
text += "0123456789abcdef"[static_cast<const uint8_t*>(data)[i] & 15];
|
||||
}
|
||||
|
@ -166,7 +171,7 @@ void toHex(const void* data, std::size_t size, std::string& text) {
|
|||
|
||||
std::string toHex(const std::vector<uint8_t>& data) {
|
||||
std::string text;
|
||||
for (std::size_t i = 0; i < data.size(); ++i) {
|
||||
for (size_t i = 0; i < data.size(); ++i) {
|
||||
text += "0123456789abcdef"[data[i] >> 4];
|
||||
text += "0123456789abcdef"[data[i] & 15];
|
||||
}
|
||||
|
@ -175,14 +180,14 @@ std::string toHex(const std::vector<uint8_t>& data) {
|
|||
}
|
||||
|
||||
void toHex(const std::vector<uint8_t>& data, std::string& text) {
|
||||
for (std::size_t i = 0; i < data.size(); ++i) {
|
||||
for (size_t i = 0; i < data.size(); ++i) {
|
||||
text += "0123456789abcdef"[data[i] >> 4];
|
||||
text += "0123456789abcdef"[data[i] & 15];
|
||||
}
|
||||
}
|
||||
|
||||
std::string extract(std::string& text, char delimiter) {
|
||||
std::size_t delimiterPosition = text.find(delimiter);
|
||||
size_t delimiterPosition = text.find(delimiter);
|
||||
std::string subText;
|
||||
if (delimiterPosition != std::string::npos) {
|
||||
subText = text.substr(0, delimiterPosition);
|
||||
|
@ -194,8 +199,8 @@ std::string extract(std::string& text, char delimiter) {
|
|||
return subText;
|
||||
}
|
||||
|
||||
std::string extract(const std::string& text, char delimiter, std::size_t& offset) {
|
||||
std::size_t delimiterPosition = text.find(delimiter, offset);
|
||||
std::string extract(const std::string& text, char delimiter, size_t& offset) {
|
||||
size_t delimiterPosition = text.find(delimiter, offset);
|
||||
if (delimiterPosition != std::string::npos) {
|
||||
offset = delimiterPosition + 1;
|
||||
return text.substr(offset, delimiterPosition);
|
||||
|
|
|
@ -24,24 +24,25 @@
|
|||
|
||||
namespace Common {
|
||||
|
||||
std::string asString(const void* data, std::size_t size); // Does not throw
|
||||
std::string asString(const void* data, size_t size); // Does not throw
|
||||
std::string asString(const std::vector<uint8_t>& data); // Does not throw
|
||||
std::vector<uint8_t> asBinaryArray(const std::string& data);
|
||||
|
||||
uint8_t fromHex(char character); // Returns value of hex 'character', throws on error
|
||||
bool fromHex(char character, uint8_t& value); // Assigns value of hex 'character' to 'value', returns false on error, does not throw
|
||||
std::size_t fromHex(const std::string& text, void* data, std::size_t bufferSize); // Assigns values of hex 'text' to buffer 'data' up to 'bufferSize', returns actual data size, throws on error
|
||||
bool fromHex(const std::string& text, void* data, std::size_t bufferSize, std::size_t& size); // Assigns values of hex 'text' to buffer 'data' up to 'bufferSize', assigns actual data size to 'size', returns false on error, does not throw
|
||||
size_t fromHex(const std::string& text, void* data, size_t bufferSize); // Assigns values of hex 'text' to buffer 'data' up to 'bufferSize', returns actual data size, throws on error
|
||||
bool fromHex(const std::string& text, void* data, size_t bufferSize, size_t& size); // Assigns values of hex 'text' to buffer 'data' up to 'bufferSize', assigns actual data size to 'size', returns false on error, does not throw
|
||||
std::vector<uint8_t> fromHex(const std::string& text); // Returns values of hex 'text', throws on error
|
||||
bool fromHex(const std::string& text, std::vector<uint8_t>& data); // Appends values of hex 'text' to 'data', returns false on error, does not throw
|
||||
|
||||
template <typename T>
|
||||
bool podFromHex(const std::string& text, T& val) {
|
||||
std::size_t outSize;
|
||||
size_t outSize;
|
||||
return fromHex(text, &val, sizeof(val), outSize) && outSize == sizeof(val);
|
||||
}
|
||||
|
||||
std::string toHex(const void* data, std::size_t size); // Returns hex representation of ('data', 'size'), does not throw
|
||||
void toHex(const void* data, std::size_t size, std::string& text); // Appends hex representation of ('data', 'size') to 'text', does not throw
|
||||
std::string toHex(const void* data, size_t size); // Returns hex representation of ('data', 'size'), does not throw
|
||||
void toHex(const void* data, size_t size, std::string& text); // Appends hex representation of ('data', 'size') to 'text', does not throw
|
||||
std::string toHex(const std::vector<uint8_t>& data); // Returns hex representation of 'data', does not throw
|
||||
void toHex(const std::vector<uint8_t>& data, std::string& text); // Appends hex representation of 'data' to 'text', does not throw
|
||||
|
||||
|
@ -51,7 +52,7 @@ std::string podToHex(const T& s) {
|
|||
}
|
||||
|
||||
std::string extract(std::string& text, char delimiter); // Does not throw
|
||||
std::string extract(const std::string& text, char delimiter, std::size_t& offset); // Does not throw
|
||||
std::string extract(const std::string& text, char delimiter, size_t& offset); // Does not throw
|
||||
|
||||
template<typename T> T fromString(const std::string& text) { // Throws on error
|
||||
T value;
|
||||
|
@ -72,7 +73,7 @@ template<typename T> bool fromString(const std::string& text, T& value) { // Doe
|
|||
|
||||
template<typename T> std::vector<T> fromDelimitedString(const std::string& source, char delimiter) { // Throws on error
|
||||
std::vector<T> data;
|
||||
for (std::size_t offset = 0; offset != source.size();) {
|
||||
for (size_t offset = 0; offset != source.size();) {
|
||||
data.emplace_back(fromString<T>(extract(source, delimiter, offset)));
|
||||
}
|
||||
|
||||
|
@ -80,7 +81,7 @@ template<typename T> std::vector<T> fromDelimitedString(const std::string& sourc
|
|||
}
|
||||
|
||||
template<typename T> bool fromDelimitedString(const std::string& source, char delimiter, std::vector<T>& data) { // Does not throw
|
||||
for (std::size_t offset = 0; offset != source.size();) {
|
||||
for (size_t offset = 0; offset != source.size();) {
|
||||
T value;
|
||||
if (!fromString<T>(extract(source, delimiter, offset), value)) {
|
||||
return false;
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace Common {
|
|||
class StringView {
|
||||
public:
|
||||
typedef char Object;
|
||||
typedef std::size_t Size;
|
||||
typedef size_t Size;
|
||||
|
||||
const static Size INVALID;
|
||||
const static StringView EMPTY;
|
||||
|
|
|
@ -15,12 +15,12 @@
|
|||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "util.h"
|
||||
#include "Util.h"
|
||||
#include <cstdio>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include "cryptonote_config.h"
|
||||
#include "CryptoNoteConfig.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
|
@ -31,7 +31,7 @@
|
|||
#endif
|
||||
|
||||
|
||||
namespace tools
|
||||
namespace Tools
|
||||
{
|
||||
#ifdef WIN32
|
||||
std::string get_windows_version_display_string()
|
||||
|
@ -296,7 +296,7 @@ std::string get_nix_version_display_string()
|
|||
}
|
||||
#endif
|
||||
|
||||
std::string get_default_data_dir()
|
||||
std::string getDefaultDataDirectory()
|
||||
{
|
||||
//namespace fs = boost::filesystem;
|
||||
// Windows < Vista: C:\Documents and Settings\Username\Application Data\CRYPTONOTE_NAME
|
4
src/Common/util.h → src/Common/Util.h
Normal file → Executable file
4
src/Common/util.h → src/Common/Util.h
Normal file → Executable file
|
@ -20,9 +20,9 @@
|
|||
#include <string>
|
||||
#include <system_error>
|
||||
|
||||
namespace tools
|
||||
namespace Tools
|
||||
{
|
||||
std::string get_default_data_dir();
|
||||
std::string getDefaultDataDirectory();
|
||||
std::string get_os_version_string();
|
||||
bool create_directories_if_necessary(const std::string& path);
|
||||
std::error_code replace_file(const std::string& replacement_name, const std::string& replaced_name);
|
2
src/Common/varint.h → src/Common/Varint.h
Normal file → Executable file
2
src/Common/varint.h → src/Common/Varint.h
Normal file → Executable file
|
@ -23,7 +23,7 @@
|
|||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace tools {
|
||||
namespace Tools {
|
||||
|
||||
template<typename OutputIt, typename T>
|
||||
typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value, void>::type
|
30
src/Common/VectorOutputStream.cpp
Normal file
30
src/Common/VectorOutputStream.cpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "VectorOutputStream.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
VectorOutputStream::VectorOutputStream(std::vector<uint8_t>& out) : out(out) {
|
||||
}
|
||||
|
||||
size_t VectorOutputStream::writeSome(const void* data, size_t size) {
|
||||
out.insert(out.end(), static_cast<const uint8_t*>(data), static_cast<const uint8_t*>(data) + size);
|
||||
return size;
|
||||
}
|
||||
|
||||
}
|
36
src/Common/VectorOutputStream.h
Normal file
36
src/Common/VectorOutputStream.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include "IOutputStream.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
class VectorOutputStream : public IOutputStream {
|
||||
public:
|
||||
VectorOutputStream(std::vector<uint8_t>& out);
|
||||
VectorOutputStream& operator=(const VectorOutputStream&) = delete;
|
||||
size_t writeSome(const void* data, size_t size) override;
|
||||
|
||||
private:
|
||||
std::vector<uint8_t>& out;
|
||||
};
|
||||
|
||||
}
|
52
src/Common/static_assert.h
Executable file → Normal file
52
src/Common/static_assert.h
Executable file → Normal file
|
@ -1,26 +1,26 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __cplusplus
|
||||
#ifdef __clang__
|
||||
|
||||
#define static_assert _Static_assert
|
||||
|
||||
#endif
|
||||
#endif
|
||||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __cplusplus
|
||||
#ifdef __clang__
|
||||
|
||||
#define static_assert _Static_assert
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
85
src/connectivity_tool/conn_tool.cpp → src/ConnectivityTool/ConnectivityTool.cpp
Normal file → Executable file
85
src/connectivity_tool/conn_tool.cpp → src/ConnectivityTool/ConnectivityTool.cpp
Normal file → Executable file
|
@ -18,6 +18,8 @@
|
|||
#include <boost/optional.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
#include <System/ContextGroup.h>
|
||||
#include <System/ContextGroupTimeout.h>
|
||||
#include <System/Dispatcher.h>
|
||||
#include <System/Event.h>
|
||||
#include <System/InterruptedException.h>
|
||||
|
@ -27,14 +29,14 @@
|
|||
#include <System/TcpConnector.h>
|
||||
#include <System/Timer.h>
|
||||
|
||||
#include "Common/command_line.h"
|
||||
#include "Common/CommandLine.h"
|
||||
#include "Common/StringTools.h"
|
||||
#include "crypto/crypto.h"
|
||||
#include "p2p/p2p_protocol_defs.h"
|
||||
#include "p2p/LevinProtocol.h"
|
||||
#include "rpc/core_rpc_server_commands_defs.h"
|
||||
#include "rpc/HttpClient.h"
|
||||
#include "serialization/SerializationTools.h"
|
||||
#include "P2p/P2pProtocolDefinitions.h"
|
||||
#include "P2p/LevinProtocol.h"
|
||||
#include "Rpc/CoreRpcServerCommandsDefinitions.h"
|
||||
#include "Rpc/HttpClient.h"
|
||||
#include "Serialization/SerializationTools.h"
|
||||
#include "version.h"
|
||||
|
||||
namespace po = boost::program_options;
|
||||
|
@ -65,33 +67,26 @@ struct response_schema {
|
|||
boost::optional<COMMAND_REQUEST_NETWORK_STATE::response> ns_rsp;
|
||||
};
|
||||
|
||||
|
||||
template <typename SystemObj>
|
||||
void withTimeout(System::Dispatcher& dispatcher, SystemObj& obj, unsigned timeout, std::function<void()> f) {
|
||||
System::Event timeoutEvent(dispatcher);
|
||||
System::Timer timeoutTimer(dispatcher);
|
||||
|
||||
dispatcher.spawn([&](){
|
||||
void withTimeout(System::Dispatcher& dispatcher, unsigned timeout, std::function<void()> f) {
|
||||
std::string result;
|
||||
System::ContextGroup cg(dispatcher);
|
||||
System::ContextGroupTimeout cgTimeout(dispatcher, cg, std::chrono::milliseconds(timeout));
|
||||
|
||||
cg.spawn([&] {
|
||||
try {
|
||||
timeoutTimer.sleep(std::chrono::milliseconds(timeout));
|
||||
obj.stop();
|
||||
} catch (std::exception&) {}
|
||||
timeoutEvent.set();
|
||||
f();
|
||||
} catch (System::InterruptedException&) {
|
||||
result = "Operation timeout";
|
||||
} catch (std::exception& e) {
|
||||
result = e.what();
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
f();
|
||||
} catch (System::InterruptedException&) {
|
||||
timeoutEvent.wait();
|
||||
throw std::runtime_error("Operation timeout");
|
||||
} catch (std::exception&) {
|
||||
timeoutTimer.stop();
|
||||
timeoutEvent.wait();
|
||||
throw;
|
||||
}
|
||||
cg.wait();
|
||||
|
||||
timeoutTimer.stop();
|
||||
timeoutEvent.wait();
|
||||
if (!result.empty()) {
|
||||
throw std::runtime_error(result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -125,7 +120,7 @@ std::ostream& get_response_schema_as_json(std::ostream& ss, response_schema &rs)
|
|||
ss << " ]," << ENDL;
|
||||
ss << " \"local_peerlist_white\": [" << ENDL;
|
||||
i = 0;
|
||||
for (const peerlist_entry &pe : networkState.local_peerlist_white) {
|
||||
for (const PeerlistEntry &pe : networkState.local_peerlist_white) {
|
||||
ss << " {\"peer_id\": \"" << pe.id << "\", \"ip\": \"" << Common::ipAddressToString(pe.adr.ip) << "\", \"port\": " << pe.adr.port << ", \"last_seen\": " << networkState.local_time - pe.last_seen << "}";
|
||||
if (networkState.local_peerlist_white.size() - 1 != i)
|
||||
ss << ",";
|
||||
|
@ -136,7 +131,7 @@ std::ostream& get_response_schema_as_json(std::ostream& ss, response_schema &rs)
|
|||
|
||||
ss << " \"local_peerlist_gray\": [" << ENDL;
|
||||
i = 0;
|
||||
for (const peerlist_entry &pe : networkState.local_peerlist_gray) {
|
||||
for (const PeerlistEntry &pe : networkState.local_peerlist_gray) {
|
||||
ss << " {\"peer_id\": \"" << pe.id << "\", \"ip\": \"" << Common::ipAddressToString(pe.adr.ip) << "\", \"port\": " << pe.adr.port << ", \"last_seen\": " << networkState.local_time - pe.last_seen << "}";
|
||||
if (networkState.local_peerlist_gray.size() - 1 != i)
|
||||
ss << ",";
|
||||
|
@ -178,12 +173,12 @@ bool print_COMMAND_REQUEST_NETWORK_STATE(const COMMAND_REQUEST_NETWORK_STATE::re
|
|||
}
|
||||
|
||||
std::cout << "Peer list white:" << ns.my_id << ENDL;
|
||||
for (const peerlist_entry &pe : ns.local_peerlist_white) {
|
||||
for (const PeerlistEntry &pe : ns.local_peerlist_white) {
|
||||
std::cout << pe.id << "\t" << pe.adr << "\t" << Common::timeIntervalToString(ns.local_time - pe.last_seen) << ENDL;
|
||||
}
|
||||
|
||||
std::cout << "Peer list gray:" << ns.my_id << ENDL;
|
||||
for (const peerlist_entry &pe : ns.local_peerlist_gray) {
|
||||
for (const PeerlistEntry &pe : ns.local_peerlist_gray) {
|
||||
std::cout << pe.id << "\t" << pe.adr << "\t" << Common::timeIntervalToString(ns.local_time - pe.last_seen) << ENDL;
|
||||
}
|
||||
|
||||
|
@ -224,13 +219,13 @@ bool handle_get_daemon_info(po::variables_map& vm) {
|
|||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
bool handle_request_stat(po::variables_map& vm, peerid_type peer_id) {
|
||||
bool handle_request_stat(po::variables_map& vm, PeerIdType peer_id) {
|
||||
if(!command_line::has_arg(vm, arg_priv_key)) {
|
||||
std::cout << "{" << ENDL << " \"status\": \"ERROR: " << "secret key not set \"" << ENDL << "}";
|
||||
return false;
|
||||
}
|
||||
|
||||
crypto::secret_key prvk;
|
||||
Crypto::SecretKey prvk;
|
||||
if (!Common::podFromHex(command_line::get_arg(vm, arg_priv_key), prvk)) {
|
||||
std::cout << "{" << ENDL << " \"status\": \"ERROR: " << "wrong secret key set \"" << ENDL << "}";
|
||||
return false;
|
||||
|
@ -250,7 +245,7 @@ bool handle_request_stat(po::variables_map& vm, peerid_type peer_id) {
|
|||
|
||||
System::TcpConnection connection;
|
||||
|
||||
withTimeout(dispatcher, connector, timeout, [&] {
|
||||
withTimeout(dispatcher, timeout, [&] {
|
||||
connection = connector.connect(addr, command_line::get_arg(vm, arg_port));
|
||||
});
|
||||
|
||||
|
@ -261,7 +256,7 @@ bool handle_request_stat(po::variables_map& vm, peerid_type peer_id) {
|
|||
if (!peer_id) {
|
||||
COMMAND_REQUEST_PEER_ID::request req;
|
||||
COMMAND_REQUEST_PEER_ID::response rsp;
|
||||
withTimeout(dispatcher, connection, timeout, [&] {
|
||||
withTimeout(dispatcher, timeout, [&] {
|
||||
levin.invoke(COMMAND_REQUEST_PEER_ID::ID, req, rsp);
|
||||
});
|
||||
peer_id = rsp.my_id;
|
||||
|
@ -270,10 +265,10 @@ bool handle_request_stat(po::variables_map& vm, peerid_type peer_id) {
|
|||
proof_of_trust pot;
|
||||
pot.peer_id = peer_id;
|
||||
pot.time = time(NULL);
|
||||
crypto::public_key pubk;
|
||||
Crypto::PublicKey pubk;
|
||||
Common::podFromHex(P2P_STAT_TRUSTED_PUB_KEY, pubk);
|
||||
crypto::hash h = get_proof_of_trust_hash(pot);
|
||||
crypto::generate_signature(h, pubk, prvk, pot.sign);
|
||||
Crypto::Hash h = get_proof_of_trust_hash(pot);
|
||||
Crypto::generate_signature(h, pubk, prvk, pot.sign);
|
||||
|
||||
if (command_line::get_arg(vm, arg_request_stat_info)) {
|
||||
COMMAND_REQUEST_STAT_INFO::request req;
|
||||
|
@ -282,7 +277,7 @@ bool handle_request_stat(po::variables_map& vm, peerid_type peer_id) {
|
|||
req.tr = pot;
|
||||
|
||||
try {
|
||||
withTimeout(dispatcher, connection, timeout, [&] {
|
||||
withTimeout(dispatcher, timeout, [&] {
|
||||
levin.invoke(COMMAND_REQUEST_STAT_INFO::ID, req, res);
|
||||
});
|
||||
rs.si_rsp = std::move(res);
|
||||
|
@ -299,12 +294,12 @@ bool handle_request_stat(po::variables_map& vm, peerid_type peer_id) {
|
|||
if (command_line::get_arg(vm, arg_request_net_state)) {
|
||||
++pot.time;
|
||||
h = get_proof_of_trust_hash(pot);
|
||||
crypto::generate_signature(h, pubk, prvk, pot.sign);
|
||||
Crypto::generate_signature(h, pubk, prvk, pot.sign);
|
||||
COMMAND_REQUEST_NETWORK_STATE::request req{ pot };
|
||||
COMMAND_REQUEST_NETWORK_STATE::response res;
|
||||
|
||||
try {
|
||||
withTimeout(dispatcher, connection, timeout, [&] {
|
||||
withTimeout(dispatcher, timeout, [&] {
|
||||
levin.invoke(COMMAND_REQUEST_NETWORK_STATE::ID, req, res);
|
||||
});
|
||||
rs.ns_rsp = std::move(res);
|
||||
|
@ -328,8 +323,8 @@ bool handle_request_stat(po::variables_map& vm, peerid_type peer_id) {
|
|||
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
bool generate_and_print_keys() {
|
||||
crypto::public_key pk;
|
||||
crypto::secret_key sk;
|
||||
Crypto::PublicKey pk;
|
||||
Crypto::SecretKey sk;
|
||||
generate_keys(pk, sk);
|
||||
std::cout << "PUBLIC KEY: " << Common::podToHex(pk) << ENDL
|
||||
<< "PRIVATE KEY: " << Common::podToHex(sk);
|
|
@ -1,79 +0,0 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "BaseTransaction.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
namespace CryptoNote {
|
||||
|
||||
BaseTransaction::BaseTransaction(
|
||||
uint64_t blockIndex,
|
||||
uint64_t unlockTime,
|
||||
std::vector<KeyOutputEntry>&& keyOutputs,
|
||||
std::vector<MultisignatureOutputEntry>&& multisignatureOutputs,
|
||||
std::vector<uint8_t>&& extra) :
|
||||
blockIndex(blockIndex),
|
||||
unlockTime(unlockTime),
|
||||
keyOutputs(std::move(keyOutputs)),
|
||||
multisignatureOutputs(std::move(multisignatureOutputs)),
|
||||
extra(std::move(extra)) {
|
||||
}
|
||||
|
||||
BaseTransaction::BaseTransaction(BaseTransaction&& other) : blockIndex(other.blockIndex), unlockTime(other.unlockTime), keyOutputs(std::move(other.keyOutputs)), multisignatureOutputs(std::move(other.multisignatureOutputs)), extra(std::move(other.extra)) {
|
||||
}
|
||||
|
||||
uint64_t BaseTransaction::getBlockIndex() const {
|
||||
return blockIndex;
|
||||
}
|
||||
|
||||
uint64_t BaseTransaction::getUnlockTime() const {
|
||||
return unlockTime;
|
||||
}
|
||||
|
||||
uint32_t BaseTransaction::getOutputCount() const {
|
||||
return static_cast<uint32_t>(keyOutputs.size() + multisignatureOutputs.size());
|
||||
}
|
||||
|
||||
BaseTransaction::OutputType BaseTransaction::getOutputType(uint32_t index) const {
|
||||
auto iterator = std::lower_bound(keyOutputs.begin(), keyOutputs.end(), index, [](const KeyOutputEntry& keyOutputEntry, uint32_t index)->bool { return keyOutputEntry.index < index; });
|
||||
if (iterator != keyOutputs.end() && iterator->index == index) {
|
||||
return KEY_OUTPUT;
|
||||
}
|
||||
|
||||
return MULTISIGNATURE_OUTPUT;
|
||||
}
|
||||
|
||||
const KeyOutput& BaseTransaction::getKeyOutput(uint32_t index) const {
|
||||
auto iterator = std::lower_bound(keyOutputs.begin(), keyOutputs.end(), index, [](const KeyOutputEntry& keyOutputEntry, uint32_t index)->bool { return keyOutputEntry.index < index; });
|
||||
assert(iterator != keyOutputs.end());
|
||||
assert(iterator->index == index);
|
||||
return iterator->output;
|
||||
}
|
||||
|
||||
const MultisignatureOutput& BaseTransaction::getMultisignatureOutput(uint32_t index) const {
|
||||
auto iterator = std::lower_bound(multisignatureOutputs.begin(), multisignatureOutputs.end(), index, [](const MultisignatureOutputEntry& multisignatureOutputEntry, uint32_t index)->bool { return multisignatureOutputEntry.index < index; });
|
||||
assert(iterator != multisignatureOutputs.end());
|
||||
assert(iterator->index == index);
|
||||
return iterator->output;
|
||||
}
|
||||
|
||||
const std::vector<uint8_t>& BaseTransaction::getExtra() const {
|
||||
return extra;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "KeyOutput.h"
|
||||
#include "MultisignatureOutput.h"
|
||||
|
||||
namespace CryptoNote {
|
||||
|
||||
class BaseTransaction {
|
||||
public:
|
||||
enum OutputType {
|
||||
KEY_OUTPUT = 0,
|
||||
MULTISIGNATURE_OUTPUT = 1
|
||||
};
|
||||
|
||||
struct KeyOutputEntry {
|
||||
uint32_t index;
|
||||
KeyOutput output;
|
||||
};
|
||||
|
||||
struct MultisignatureOutputEntry {
|
||||
uint32_t index;
|
||||
MultisignatureOutput output;
|
||||
};
|
||||
|
||||
BaseTransaction(uint64_t blockIndex, uint64_t unlockTime, std::vector<KeyOutputEntry>&& keyOutputs, std::vector<MultisignatureOutputEntry>&& multisignatureOutputs, std::vector<uint8_t>&& extra);
|
||||
BaseTransaction(const BaseTransaction& other) = delete;
|
||||
BaseTransaction(BaseTransaction&& other);
|
||||
BaseTransaction& operator=(const BaseTransaction& other) = delete;
|
||||
uint64_t getBlockIndex() const;
|
||||
uint64_t getUnlockTime() const;
|
||||
uint32_t getOutputCount() const;
|
||||
OutputType getOutputType(uint32_t index) const;
|
||||
const KeyOutput& getKeyOutput(uint32_t index) const;
|
||||
const MultisignatureOutput& getMultisignatureOutput(uint32_t index) const;
|
||||
const std::vector<uint8_t>& getExtra() const;
|
||||
|
||||
private:
|
||||
uint64_t blockIndex;
|
||||
uint64_t unlockTime;
|
||||
std::vector<KeyOutputEntry> keyOutputs;
|
||||
std::vector<MultisignatureOutputEntry> multisignatureOutputs;
|
||||
std::vector<uint8_t> extra;
|
||||
};
|
||||
|
||||
}
|
|
@ -1,118 +0,0 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "Block.h"
|
||||
#include "KeyInput.h"
|
||||
#include "KeyOutput.h"
|
||||
#include "MultisignatureInput.h"
|
||||
#include "MultisignatureOutput.h"
|
||||
#include "Transaction.h"
|
||||
|
||||
namespace CryptoNote {
|
||||
|
||||
Block::Block(
|
||||
uint8_t majorVersion,
|
||||
uint8_t minorVersion,
|
||||
uint64_t timestamp,
|
||||
const crypto::hash& previousBlockHash,
|
||||
BaseTransaction&& baseTransaction,
|
||||
std::vector<Transaction>&& transactions,
|
||||
uint8_t parentMajorVersion,
|
||||
uint8_t parentMinorVersion,
|
||||
uint32_t nonce,
|
||||
const crypto::hash& parentPreviousBlockHash,
|
||||
BaseTransaction&& parentBaseTransaction,
|
||||
std::vector<crypto::hash>&& parentBaseTransactionBranch,
|
||||
uint32_t parentTransactionCount,
|
||||
std::vector<crypto::hash>&& branch) :
|
||||
majorVersion(majorVersion),
|
||||
minorVersion(minorVersion),
|
||||
timestamp(timestamp),
|
||||
previousBlockHash(previousBlockHash),
|
||||
baseTransaction(std::move(baseTransaction)),
|
||||
transactions(std::move(transactions)),
|
||||
parentMajorVersion(parentMajorVersion),
|
||||
parentMinorVersion(parentMinorVersion),
|
||||
nonce(nonce),
|
||||
parentPreviousBlockHash(parentPreviousBlockHash),
|
||||
parentBaseTransaction(std::move(parentBaseTransaction)),
|
||||
parentBaseTransactionBranch(std::move(parentBaseTransactionBranch)),
|
||||
parentTransactionCount(parentTransactionCount),
|
||||
branch(std::move(branch)) {
|
||||
}
|
||||
|
||||
uint8_t Block::getMajorVersion() const {
|
||||
return majorVersion;
|
||||
}
|
||||
|
||||
uint8_t Block::getMinorVersion() const {
|
||||
return minorVersion;
|
||||
}
|
||||
|
||||
uint64_t Block::getTimestamp() const {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
const crypto::hash& Block::getPreviousBlockHash() const {
|
||||
return previousBlockHash;
|
||||
}
|
||||
|
||||
const BaseTransaction& Block::getBaseTransaction() const {
|
||||
return baseTransaction;
|
||||
}
|
||||
|
||||
uint32_t Block::getTransactionCount() const {
|
||||
return static_cast<uint32_t>(transactions.size());
|
||||
}
|
||||
|
||||
const Transaction& Block::getTransaction(uint32_t index) const {
|
||||
return transactions[index];
|
||||
}
|
||||
|
||||
uint8_t Block::getParentMajorVersion() const {
|
||||
return parentMajorVersion;
|
||||
}
|
||||
|
||||
uint8_t Block::getParentMinorVersion() const {
|
||||
return parentMinorVersion;
|
||||
}
|
||||
|
||||
uint32_t Block::getNonce() const {
|
||||
return nonce;
|
||||
}
|
||||
|
||||
const crypto::hash& Block::getParentPreviousBlockHash() const {
|
||||
return parentPreviousBlockHash;
|
||||
}
|
||||
|
||||
const BaseTransaction& Block::getParentBaseTransaction() const {
|
||||
return parentBaseTransaction;
|
||||
}
|
||||
|
||||
const std::vector<crypto::hash>& Block::getParentBaseTransactionBranch() const {
|
||||
return parentBaseTransactionBranch;
|
||||
}
|
||||
|
||||
uint32_t Block::getParentTransactionCount() const {
|
||||
return parentTransactionCount;
|
||||
}
|
||||
|
||||
const std::vector<crypto::hash>& Block::getBranch() const {
|
||||
return branch;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BaseTransaction.h"
|
||||
|
||||
namespace CryptoNote {
|
||||
|
||||
class Transaction;
|
||||
|
||||
class Block {
|
||||
public:
|
||||
Block(
|
||||
uint8_t majorVersion,
|
||||
uint8_t minorVersion,
|
||||
uint64_t timestamp,
|
||||
const crypto::hash& previousBlockHash,
|
||||
BaseTransaction&& baseTransaction,
|
||||
std::vector<Transaction>&& transactions,
|
||||
uint8_t parentMajorVersion,
|
||||
uint8_t parentMinorVersion,
|
||||
uint32_t nonce,
|
||||
const crypto::hash& parentPreviousBlockHash,
|
||||
BaseTransaction&& parentBaseTransaction,
|
||||
std::vector<crypto::hash>&& parentBaseTransactionBranch,
|
||||
uint32_t parentTransactionCount,
|
||||
std::vector<crypto::hash>&& branch);
|
||||
Block(const Block& other) = delete;
|
||||
Block& operator=(const Block& other) = delete;
|
||||
uint8_t getMajorVersion() const;
|
||||
uint8_t getMinorVersion() const;
|
||||
uint64_t getTimestamp() const;
|
||||
const crypto::hash& getPreviousBlockHash() const;
|
||||
const BaseTransaction& getBaseTransaction() const;
|
||||
uint32_t getTransactionCount() const;
|
||||
const Transaction& getTransaction(uint32_t index) const;
|
||||
uint8_t getParentMajorVersion() const;
|
||||
uint8_t getParentMinorVersion() const;
|
||||
uint32_t getNonce() const;
|
||||
const crypto::hash& getParentPreviousBlockHash() const;
|
||||
const BaseTransaction& getParentBaseTransaction() const;
|
||||
const std::vector<crypto::hash>& getParentBaseTransactionBranch() const;
|
||||
uint32_t getParentTransactionCount() const;
|
||||
const std::vector<crypto::hash>& getBranch() const;
|
||||
|
||||
private:
|
||||
uint8_t majorVersion;
|
||||
uint8_t minorVersion;
|
||||
uint64_t timestamp;
|
||||
crypto::hash previousBlockHash;
|
||||
BaseTransaction baseTransaction;
|
||||
std::vector<Transaction> transactions;
|
||||
uint8_t parentMajorVersion;
|
||||
uint8_t parentMinorVersion;
|
||||
uint32_t nonce;
|
||||
crypto::hash parentPreviousBlockHash;
|
||||
BaseTransaction parentBaseTransaction;
|
||||
std::vector<crypto::hash> parentBaseTransactionBranch;
|
||||
uint32_t parentTransactionCount;
|
||||
std::vector<crypto::hash> branch;
|
||||
};
|
||||
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "KeyInput.h"
|
||||
|
||||
namespace CryptoNote {
|
||||
|
||||
KeyInput::KeyInput(uint64_t amount, std::vector<Output>&& outputs, const crypto::key_image& keyImage) : amount(amount), outputs(std::move(outputs)), keyImage(keyImage) {
|
||||
}
|
||||
|
||||
uint64_t KeyInput::getAmount() const {
|
||||
return amount;
|
||||
}
|
||||
|
||||
uint32_t KeyInput::getOutputCount() const {
|
||||
return static_cast<uint32_t>(outputs.size());
|
||||
}
|
||||
|
||||
uint32_t KeyInput::getOutputIndex(uint32_t index) const {
|
||||
return outputs[index].index;
|
||||
}
|
||||
|
||||
const crypto::signature& KeyInput::getOutputSignature(uint32_t index) const {
|
||||
return outputs[index].signature;
|
||||
}
|
||||
|
||||
const crypto::key_image& KeyInput::getKeyImage() const {
|
||||
return keyImage;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../crypto/crypto.h"
|
||||
|
||||
namespace CryptoNote {
|
||||
|
||||
class KeyInput {
|
||||
public:
|
||||
struct Output {
|
||||
uint32_t index;
|
||||
crypto::signature signature;
|
||||
};
|
||||
|
||||
KeyInput(uint64_t amount, std::vector<Output>&& outputs, const crypto::key_image& keyImage);
|
||||
KeyInput(const KeyInput& other) = delete;
|
||||
KeyInput& operator=(const KeyInput& other) = delete;
|
||||
uint64_t getAmount() const;
|
||||
uint32_t getOutputCount() const;
|
||||
uint32_t getOutputIndex(uint32_t index) const;
|
||||
const crypto::signature& getOutputSignature(uint32_t index) const;
|
||||
const crypto::key_image& getKeyImage() const;
|
||||
|
||||
private:
|
||||
uint64_t amount;
|
||||
std::vector<Output> outputs;
|
||||
crypto::key_image keyImage;
|
||||
};
|
||||
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "MultisignatureInput.h"
|
||||
|
||||
namespace CryptoNote {
|
||||
|
||||
MultisignatureInput::MultisignatureInput(uint64_t amount, uint32_t outputIndex, std::vector<crypto::signature>&& signatures) : amount(amount), outputIndex(outputIndex), signatures(std::move(signatures)) {
|
||||
}
|
||||
|
||||
uint64_t MultisignatureInput::getAmount() const {
|
||||
return amount;
|
||||
}
|
||||
|
||||
uint32_t MultisignatureInput::getOutputIndex() const {
|
||||
return outputIndex;
|
||||
}
|
||||
|
||||
uint32_t MultisignatureInput::getSignatureCount() const {
|
||||
return static_cast<uint32_t>(signatures.size());
|
||||
}
|
||||
|
||||
const crypto::signature& MultisignatureInput::getSignature(uint32_t index) const {
|
||||
return signatures[index];
|
||||
}
|
||||
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../crypto/crypto.h"
|
||||
|
||||
namespace CryptoNote {
|
||||
|
||||
class MultisignatureInput {
|
||||
public:
|
||||
MultisignatureInput(uint64_t amount, uint32_t outputIndex, std::vector<crypto::signature>&& signatures);
|
||||
MultisignatureInput(const MultisignatureInput& other) = delete;
|
||||
MultisignatureInput& operator=(const MultisignatureInput& other) = delete;
|
||||
uint64_t getAmount() const;
|
||||
uint32_t getOutputIndex() const;
|
||||
uint32_t getSignatureCount() const;
|
||||
const crypto::signature& getSignature(uint32_t index) const;
|
||||
|
||||
private:
|
||||
uint64_t amount;
|
||||
uint32_t outputIndex;
|
||||
std::vector<crypto::signature> signatures;
|
||||
};
|
||||
|
||||
}
|
|
@ -1,111 +0,0 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "Transaction.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
namespace CryptoNote {
|
||||
|
||||
Transaction::Transaction(
|
||||
uint64_t unlockTime,
|
||||
std::vector<KeyInputEntry>&& keyInputs,
|
||||
std::vector<MultisignatureInputEntry>&& multisignatureInputs,
|
||||
std::vector<KeyOutputEntry>&& keyOutputs,
|
||||
std::vector<MultisignatureOutputEntry>&& multisignatureOutputs,
|
||||
std::vector<uint8_t>&& extra) :
|
||||
unlockTime(unlockTime),
|
||||
keyInputs(std::move(keyInputs)),
|
||||
multisignatureInputs(std::move(multisignatureInputs)),
|
||||
keyOutputs(std::move(keyOutputs)),
|
||||
multisignatureOutputs(std::move(multisignatureOutputs)),
|
||||
extra(std::move(extra)) {
|
||||
}
|
||||
|
||||
Transaction::Transaction(
|
||||
Transaction&& other) :
|
||||
unlockTime(other.unlockTime),
|
||||
keyInputs(std::move(other.keyInputs)),
|
||||
multisignatureInputs(std::move(other.multisignatureInputs)),
|
||||
keyOutputs(std::move(other.keyOutputs)),
|
||||
multisignatureOutputs(std::move(other.multisignatureOutputs)),
|
||||
extra(std::move(other.extra)) {
|
||||
}
|
||||
|
||||
uint64_t Transaction::getUnlockTime() const {
|
||||
return unlockTime;
|
||||
}
|
||||
|
||||
uint32_t Transaction::getInputCount() const {
|
||||
return static_cast<uint32_t>(keyInputs.size() + multisignatureInputs.size());
|
||||
}
|
||||
|
||||
Transaction::InputType Transaction::getInputType(uint32_t index) const {
|
||||
auto iterator = std::lower_bound(keyInputs.begin(), keyInputs.end(), index, [](const KeyInputEntry& keyInputEntry, uint32_t index)->bool { return keyInputEntry.index < index; });
|
||||
if (iterator != keyInputs.end() && iterator->index == index) {
|
||||
return KEY_INPUT;
|
||||
}
|
||||
|
||||
return MULTISIGNATURE_INPUT;
|
||||
}
|
||||
|
||||
const KeyInput& Transaction::getKeyInput(uint32_t index) const {
|
||||
auto iterator = std::lower_bound(keyInputs.begin(), keyInputs.end(), index, [](const KeyInputEntry& keyInputEntry, uint32_t index)->bool { return keyInputEntry.index < index; });
|
||||
assert(iterator != keyInputs.end());
|
||||
assert(iterator->index == index);
|
||||
return iterator->input;
|
||||
}
|
||||
|
||||
const MultisignatureInput& Transaction::getMultisignatureInput(uint32_t index) const {
|
||||
auto iterator = std::lower_bound(multisignatureInputs.begin(), multisignatureInputs.end(), index, [](const MultisignatureInputEntry& multisignatureInputEntry, uint32_t index)->bool { return multisignatureInputEntry.index < index; });
|
||||
assert(iterator != multisignatureInputs.end());
|
||||
assert(iterator->index == index);
|
||||
return iterator->input;
|
||||
}
|
||||
|
||||
uint32_t Transaction::getOutputCount() const {
|
||||
return static_cast<uint32_t>(keyOutputs.size() + multisignatureOutputs.size());
|
||||
}
|
||||
|
||||
Transaction::OutputType Transaction::getOutputType(uint32_t index) const {
|
||||
auto iterator = std::lower_bound(keyOutputs.begin(), keyOutputs.end(), index, [](const KeyOutputEntry& keyOutputEntry, uint32_t index)->bool { return keyOutputEntry.index < index; });
|
||||
if (iterator != keyOutputs.end() && iterator->index == index) {
|
||||
return KEY_OUTPUT;
|
||||
}
|
||||
|
||||
return MULTISIGNATURE_OUTPUT;
|
||||
}
|
||||
|
||||
const KeyOutput& Transaction::getKeyOutput(uint32_t index) const {
|
||||
auto iterator = std::lower_bound(keyOutputs.begin(), keyOutputs.end(), index, [](const KeyOutputEntry& keyOutputEntry, uint32_t index)->bool { return keyOutputEntry.index < index; });
|
||||
assert(iterator != keyOutputs.end());
|
||||
assert(iterator->index == index);
|
||||
return iterator->output;
|
||||
}
|
||||
|
||||
const MultisignatureOutput& Transaction::getMultisignatureOutput(uint32_t index) const {
|
||||
auto iterator = std::lower_bound(multisignatureOutputs.begin(), multisignatureOutputs.end(), index, [](const MultisignatureOutputEntry& multisignatureOutputEntry, uint32_t index)->bool { return multisignatureOutputEntry.index < index; });
|
||||
assert(iterator != multisignatureOutputs.end());
|
||||
assert(iterator->index == index);
|
||||
return iterator->output;
|
||||
}
|
||||
|
||||
const std::vector<uint8_t>& Transaction::getExtra() const {
|
||||
return extra;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "KeyInput.h"
|
||||
#include "KeyOutput.h"
|
||||
#include "MultisignatureInput.h"
|
||||
#include "MultisignatureOutput.h"
|
||||
|
||||
namespace CryptoNote {
|
||||
|
||||
class Transaction {
|
||||
public:
|
||||
enum InputType {
|
||||
KEY_INPUT = 0,
|
||||
MULTISIGNATURE_INPUT = 1
|
||||
};
|
||||
|
||||
enum OutputType {
|
||||
KEY_OUTPUT = 0,
|
||||
MULTISIGNATURE_OUTPUT = 1
|
||||
};
|
||||
|
||||
struct KeyInputEntry {
|
||||
uint32_t index;
|
||||
KeyInput input;
|
||||
};
|
||||
|
||||
struct KeyOutputEntry {
|
||||
uint32_t index;
|
||||
KeyOutput output;
|
||||
};
|
||||
|
||||
struct MultisignatureInputEntry {
|
||||
uint32_t index;
|
||||
MultisignatureInput input;
|
||||
};
|
||||
|
||||
struct MultisignatureOutputEntry {
|
||||
uint32_t index;
|
||||
MultisignatureOutput output;
|
||||
};
|
||||
|
||||
Transaction(
|
||||
uint64_t unlockTime,
|
||||
std::vector<KeyInputEntry>&& keyInputs,
|
||||
std::vector<MultisignatureInputEntry>&& multisignatureInputs,
|
||||
std::vector<KeyOutputEntry>&& keyOutputs,
|
||||
std::vector<MultisignatureOutputEntry>&& multisignatureOutputs,
|
||||
std::vector<uint8_t>&& extra);
|
||||
Transaction(const Transaction& other) = delete;
|
||||
Transaction(Transaction&& other);
|
||||
Transaction& operator=(const Transaction& other) = delete;
|
||||
uint64_t getUnlockTime() const;
|
||||
uint32_t getInputCount() const;
|
||||
InputType getInputType(uint32_t index) const;
|
||||
const KeyInput& getKeyInput(uint32_t index) const;
|
||||
const MultisignatureInput& getMultisignatureInput(uint32_t index) const;
|
||||
uint32_t getOutputCount() const;
|
||||
OutputType getOutputType(uint32_t index) const;
|
||||
const KeyOutput& getKeyOutput(uint32_t index) const;
|
||||
const MultisignatureOutput& getMultisignatureOutput(uint32_t index) const;
|
||||
const std::vector<uint8_t>& getExtra() const;
|
||||
|
||||
private:
|
||||
uint64_t unlockTime;
|
||||
std::vector<KeyInputEntry> keyInputs;
|
||||
std::vector<MultisignatureInputEntry> multisignatureInputs;
|
||||
std::vector<KeyOutputEntry> keyOutputs;
|
||||
std::vector<MultisignatureOutputEntry> multisignatureOutputs;
|
||||
std::vector<uint8_t> extra;
|
||||
};
|
||||
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "UnsignedMultisignatureInput.h"
|
||||
|
||||
namespace CryptoNote {
|
||||
|
||||
UnsignedMultisignatureInput::UnsignedMultisignatureInput(uint64_t amount, uint32_t outputIndex) : amount(amount), outputIndex(outputIndex) {
|
||||
}
|
||||
|
||||
uint64_t UnsignedMultisignatureInput::getAmount() const {
|
||||
return amount;
|
||||
}
|
||||
|
||||
uint32_t UnsignedMultisignatureInput::getOutputIndex() const {
|
||||
return outputIndex;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,111 +0,0 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "UnsignedTransaction.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
namespace CryptoNote {
|
||||
|
||||
UnsignedTransaction::UnsignedTransaction(
|
||||
uint64_t unlockTime,
|
||||
std::vector<KeyInputEntry>&& keyInputs,
|
||||
std::vector<MultisignatureInputEntry>&& multisignatureInputs,
|
||||
std::vector<KeyOutputEntry>&& keyOutputs,
|
||||
std::vector<MultisignatureOutputEntry>&& multisignatureOutputs,
|
||||
std::vector<uint8_t>&& extra) :
|
||||
unlockTime(unlockTime),
|
||||
keyInputs(std::move(keyInputs)),
|
||||
multisignatureInputs(std::move(multisignatureInputs)),
|
||||
keyOutputs(std::move(keyOutputs)),
|
||||
multisignatureOutputs(std::move(multisignatureOutputs)),
|
||||
extra(std::move(extra)) {
|
||||
}
|
||||
|
||||
UnsignedTransaction::UnsignedTransaction(
|
||||
UnsignedTransaction&& other) :
|
||||
unlockTime(other.unlockTime),
|
||||
keyInputs(std::move(other.keyInputs)),
|
||||
multisignatureInputs(std::move(other.multisignatureInputs)),
|
||||
keyOutputs(std::move(other.keyOutputs)),
|
||||
multisignatureOutputs(std::move(other.multisignatureOutputs)),
|
||||
extra(std::move(other.extra)) {
|
||||
}
|
||||
|
||||
uint64_t UnsignedTransaction::getUnlockTime() const {
|
||||
return unlockTime;
|
||||
}
|
||||
|
||||
uint32_t UnsignedTransaction::getInputCount() const {
|
||||
return static_cast<uint32_t>(keyInputs.size() + multisignatureInputs.size());
|
||||
}
|
||||
|
||||
UnsignedTransaction::InputType UnsignedTransaction::getInputType(uint32_t index) const {
|
||||
auto iterator = std::lower_bound(keyInputs.begin(), keyInputs.end(), index, [](const KeyInputEntry& keyInputEntry, uint32_t index)->bool { return keyInputEntry.index < index; });
|
||||
if (iterator != keyInputs.end() && iterator->index == index) {
|
||||
return KEY_INPUT;
|
||||
}
|
||||
|
||||
return MULTISIGNATURE_INPUT;
|
||||
}
|
||||
|
||||
const UnsignedKeyInput& UnsignedTransaction::getKeyInput(uint32_t index) const {
|
||||
auto iterator = std::lower_bound(keyInputs.begin(), keyInputs.end(), index, [](const KeyInputEntry& keyInputEntry, uint32_t index)->bool { return keyInputEntry.index < index; });
|
||||
assert(iterator != keyInputs.end());
|
||||
assert(iterator->index == index);
|
||||
return iterator->input;
|
||||
}
|
||||
|
||||
const UnsignedMultisignatureInput& UnsignedTransaction::getMultisignatureInput(uint32_t index) const {
|
||||
auto iterator = std::lower_bound(multisignatureInputs.begin(), multisignatureInputs.end(), index, [](const MultisignatureInputEntry& multisignatureInputEntry, uint32_t index)->bool { return multisignatureInputEntry.index < index; });
|
||||
assert(iterator != multisignatureInputs.end());
|
||||
assert(iterator->index == index);
|
||||
return iterator->input;
|
||||
}
|
||||
|
||||
uint32_t UnsignedTransaction::getOutputCount() const {
|
||||
return static_cast<uint32_t>(keyOutputs.size() + multisignatureOutputs.size());
|
||||
}
|
||||
|
||||
UnsignedTransaction::OutputType UnsignedTransaction::getOutputType(uint32_t index) const {
|
||||
auto iterator = std::lower_bound(keyOutputs.begin(), keyOutputs.end(), index, [](const KeyOutputEntry& keyOutputEntry, uint32_t index)->bool { return keyOutputEntry.index < index; });
|
||||
if (iterator != keyOutputs.end() && iterator->index == index) {
|
||||
return KEY_OUTPUT;
|
||||
}
|
||||
|
||||
return MULTISIGNATURE_OUTPUT;
|
||||
}
|
||||
|
||||
const KeyOutput& UnsignedTransaction::getKeyOutput(uint32_t index) const {
|
||||
auto iterator = std::lower_bound(keyOutputs.begin(), keyOutputs.end(), index, [](const KeyOutputEntry& keyOutputEntry, uint32_t index)->bool { return keyOutputEntry.index < index; });
|
||||
assert(iterator != keyOutputs.end());
|
||||
assert(iterator->index == index);
|
||||
return iterator->output;
|
||||
}
|
||||
|
||||
const MultisignatureOutput& UnsignedTransaction::getMultisignatureOutput(uint32_t index) const {
|
||||
auto iterator = std::lower_bound(multisignatureOutputs.begin(), multisignatureOutputs.end(), index, [](const MultisignatureOutputEntry& multisignatureOutputEntry, uint32_t index)->bool { return multisignatureOutputEntry.index < index; });
|
||||
assert(iterator != multisignatureOutputs.end());
|
||||
assert(iterator->index == index);
|
||||
return iterator->output;
|
||||
}
|
||||
|
||||
const std::vector<uint8_t>& UnsignedTransaction::getExtra() const {
|
||||
return extra;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "KeyOutput.h"
|
||||
#include "MultisignatureOutput.h"
|
||||
#include "UnsignedKeyInput.h"
|
||||
#include "UnsignedMultisignatureInput.h"
|
||||
|
||||
namespace CryptoNote {
|
||||
|
||||
class UnsignedTransaction {
|
||||
public:
|
||||
enum InputType {
|
||||
KEY_INPUT = 0,
|
||||
MULTISIGNATURE_INPUT = 1
|
||||
};
|
||||
|
||||
enum OutputType {
|
||||
KEY_OUTPUT = 0,
|
||||
MULTISIGNATURE_OUTPUT = 1
|
||||
};
|
||||
|
||||
struct KeyInputEntry {
|
||||
uint32_t index;
|
||||
UnsignedKeyInput input;
|
||||
};
|
||||
|
||||
struct KeyOutputEntry {
|
||||
uint32_t index;
|
||||
KeyOutput output;
|
||||
};
|
||||
|
||||
struct MultisignatureInputEntry {
|
||||
uint32_t index;
|
||||
UnsignedMultisignatureInput input;
|
||||
};
|
||||
|
||||
struct MultisignatureOutputEntry {
|
||||
uint32_t index;
|
||||
MultisignatureOutput output;
|
||||
};
|
||||
|
||||
UnsignedTransaction(
|
||||
uint64_t unlockTime,
|
||||
std::vector<KeyInputEntry>&& keyInputs,
|
||||
std::vector<MultisignatureInputEntry>&& multisignatureInputs,
|
||||
std::vector<KeyOutputEntry>&& keyOutputs,
|
||||
std::vector<MultisignatureOutputEntry>&& multisignatureOutputs,
|
||||
std::vector<uint8_t>&& extra);
|
||||
UnsignedTransaction(const UnsignedTransaction& other) = delete;
|
||||
UnsignedTransaction(UnsignedTransaction&& other);
|
||||
UnsignedTransaction& operator=(const UnsignedTransaction& other) = delete;
|
||||
uint64_t getUnlockTime() const;
|
||||
uint32_t getInputCount() const;
|
||||
InputType getInputType(uint32_t index) const;
|
||||
const UnsignedKeyInput& getKeyInput(uint32_t index) const;
|
||||
const UnsignedMultisignatureInput& getMultisignatureInput(uint32_t index) const;
|
||||
uint32_t getOutputCount() const;
|
||||
OutputType getOutputType(uint32_t index) const;
|
||||
const KeyOutput& getKeyOutput(uint32_t index) const;
|
||||
const MultisignatureOutput& getMultisignatureOutput(uint32_t index) const;
|
||||
const std::vector<uint8_t>& getExtra() const;
|
||||
|
||||
private:
|
||||
uint64_t unlockTime;
|
||||
std::vector<KeyInputEntry> keyInputs;
|
||||
std::vector<MultisignatureInputEntry> multisignatureInputs;
|
||||
std::vector<KeyOutputEntry> keyOutputs;
|
||||
std::vector<MultisignatureOutputEntry> multisignatureOutputs;
|
||||
std::vector<uint8_t> extra;
|
||||
};
|
||||
|
||||
}
|
|
@ -74,6 +74,7 @@ const char CRYPTONOTE_BLOCKINDEXES_FILENAME[] = "blockindexes.dat
|
|||
const char CRYPTONOTE_BLOCKSCACHE_FILENAME[] = "blockscache.dat";
|
||||
const char CRYPTONOTE_POOLDATA_FILENAME[] = "poolstate.bin";
|
||||
const char P2P_NET_DATA_FILENAME[] = "p2pstate.bin";
|
||||
const char CRYPTONOTE_BLOCKCHAIN_INDICES_FILENAME[] = "blockchainindices.dat";
|
||||
const char MINER_CONFIG_FILE_NAME[] = "miner_conf.json";
|
||||
} // parameters
|
||||
|
||||
|
@ -95,7 +96,9 @@ const int RPC_DEFAULT_PORT = 8081;
|
|||
const size_t P2P_LOCAL_WHITE_PEERLIST_LIMIT = 1000;
|
||||
const size_t P2P_LOCAL_GRAY_PEERLIST_LIMIT = 5000;
|
||||
|
||||
const size_t P2P_CONNECTION_MAX_WRITE_BUFFER_SIZE = 16 * 1024 * 1024; // 16 MB
|
||||
const uint32_t P2P_DEFAULT_CONNECTIONS_COUNT = 8;
|
||||
const size_t P2P_DEFAULT_WHITELIST_CONNECTIONS_PERCENT = 70;
|
||||
const uint32_t P2P_DEFAULT_HANDSHAKE_INTERVAL = 60; // seconds
|
||||
const uint32_t P2P_DEFAULT_PACKET_MAX_SIZE = 50000000; // 50000000 bytes maximum packet size
|
||||
const uint32_t P2P_DEFAULT_PEERS_IN_HANDSHAKE = 250;
|
||||
|
@ -103,10 +106,7 @@ const uint32_t P2P_DEFAULT_CONNECTION_TIMEOUT = 5000; //
|
|||
const uint32_t P2P_DEFAULT_PING_CONNECTION_TIMEOUT = 2000; // 2 seconds
|
||||
const uint64_t P2P_DEFAULT_INVOKE_TIMEOUT = 60 * 2 * 1000; // 2 minutes
|
||||
const size_t P2P_DEFAULT_HANDSHAKE_INVOKE_TIMEOUT = 5000; // 5 seconds
|
||||
const char P2P_STAT_TRUSTED_PUB_KEY[] = "93467628927eaa0b13a4e52e61864a75aa475e67f6b5748eb3fc1d2fe468aed4";
|
||||
const size_t P2P_DEFAULT_WHITELIST_CONNECTIONS_PERCENT = 70;
|
||||
|
||||
const unsigned THREAD_STACK_SIZE = 5 * 1024 * 1024;
|
||||
const char P2P_STAT_TRUSTED_PUB_KEY[] = "93467628927eaa0b13a4e52e61864a75aa475e67f6b5748eb3fc1d2fe468aed4";
|
||||
|
||||
const char* const SEED_NODES[] = {
|
||||
"seed.bytecoin.org:8080",
|
||||
|
@ -122,7 +122,7 @@ const char* const SEED_NODES[] = {
|
|||
};
|
||||
|
||||
struct CheckpointData {
|
||||
uint64_t height;
|
||||
uint32_t height;
|
||||
const char* blockId;
|
||||
};
|
||||
|
||||
|
@ -154,7 +154,8 @@ const CheckpointData CHECKPOINTS[] = {
|
|||
{750300, "5117631dbeb5c14748a91127a515ecbf13f6849e14fda7ee03cd55da41f1710c"},
|
||||
{780000, "8dd55a9bae429e3685b90317281e633917023d3512eb7f37372209d1a5fc1070"},
|
||||
{785500, "de1a487d70964d25ed6f7de196866f357a293e867ee81313e7fd0352d0126bdd"},
|
||||
{789000, "acef490bbccce3b7b7ae8554a414f55413fbf4ca1472c6359b126a4439bd9f01"}
|
||||
{789000, "acef490bbccce3b7b7ae8554a414f55413fbf4ca1472c6359b126a4439bd9f01"},
|
||||
{796000, "04e387a00d35db21d4d93d04040b31f22573972a7e61d72cc07d0ab69bcb9c44"}
|
||||
};
|
||||
} // CryptoNote
|
||||
|
24
src/cryptonote_core/account.cpp → src/CryptoNoteCore/Account.cpp
Normal file → Executable file
24
src/cryptonote_core/account.cpp → src/CryptoNoteCore/Account.cpp
Normal file → Executable file
|
@ -15,35 +15,35 @@
|
|||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "account.h"
|
||||
#include "cryptonote_serialization.h"
|
||||
#include "Account.h"
|
||||
#include "CryptoNoteSerialization.h"
|
||||
|
||||
namespace CryptoNote {
|
||||
//-----------------------------------------------------------------
|
||||
account_base::account_base() {
|
||||
set_null();
|
||||
AccountBase::AccountBase() {
|
||||
setNull();
|
||||
}
|
||||
//-----------------------------------------------------------------
|
||||
void account_base::set_null() {
|
||||
m_keys = account_keys();
|
||||
void AccountBase::setNull() {
|
||||
m_keys = AccountKeys();
|
||||
}
|
||||
//-----------------------------------------------------------------
|
||||
void account_base::generate() {
|
||||
crypto::generate_keys(m_keys.m_account_address.m_spendPublicKey, m_keys.m_spend_secret_key);
|
||||
crypto::generate_keys(m_keys.m_account_address.m_viewPublicKey, m_keys.m_view_secret_key);
|
||||
void AccountBase::generate() {
|
||||
Crypto::generate_keys(m_keys.address.spendPublicKey, m_keys.spendSecretKey);
|
||||
Crypto::generate_keys(m_keys.address.viewPublicKey, m_keys.viewSecretKey);
|
||||
m_creation_timestamp = time(NULL);
|
||||
}
|
||||
//-----------------------------------------------------------------
|
||||
const account_keys &account_base::get_keys() const {
|
||||
const AccountKeys &AccountBase::getAccountKeys() const {
|
||||
return m_keys;
|
||||
}
|
||||
|
||||
void account_base::set_keys(const account_keys &keys) {
|
||||
void AccountBase::setAccountKeys(const AccountKeys &keys) {
|
||||
m_keys = keys;
|
||||
}
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
void account_base::serialize(ISerializer &s) {
|
||||
void AccountBase::serialize(ISerializer &s) {
|
||||
s(m_keys, "m_keys");
|
||||
s(m_creation_timestamp, "m_creation_timestamp");
|
||||
}
|
28
src/cryptonote_core/account.h → src/CryptoNoteCore/Account.h
Normal file → Executable file
28
src/cryptonote_core/account.h → src/CryptoNoteCore/Account.h
Normal file → Executable file
|
@ -17,33 +17,26 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "cryptonote_core/cryptonote_basic.h"
|
||||
#include "CryptoNoteCore/CryptoNoteBasic.h"
|
||||
#include "crypto/crypto.h"
|
||||
|
||||
namespace CryptoNote {
|
||||
template<bool is_store> struct AccountBaseSerializer;
|
||||
|
||||
class ISerializer;
|
||||
|
||||
struct account_keys {
|
||||
AccountPublicAddress m_account_address;
|
||||
crypto::secret_key m_spend_secret_key;
|
||||
crypto::secret_key m_view_secret_key;
|
||||
};
|
||||
|
||||
/************************************************************************/
|
||||
/* */
|
||||
/************************************************************************/
|
||||
class account_base {
|
||||
class AccountBase {
|
||||
public:
|
||||
account_base();
|
||||
AccountBase();
|
||||
void generate();
|
||||
|
||||
const account_keys& get_keys() const;
|
||||
void set_keys(const account_keys& keys);
|
||||
|
||||
const AccountKeys& getAccountKeys() const;
|
||||
void setAccountKeys(const AccountKeys& keys);
|
||||
uint64_t get_createtime() const { return m_creation_timestamp; }
|
||||
void set_createtime(uint64_t val) { m_creation_timestamp = val; }
|
||||
void serialize(ISerializer& s);
|
||||
|
||||
template <class t_archive>
|
||||
inline void serialize(t_archive &a, const unsigned int /*ver*/) {
|
||||
|
@ -51,14 +44,9 @@ namespace CryptoNote {
|
|||
a & m_creation_timestamp;
|
||||
}
|
||||
|
||||
void serialize(ISerializer& s);
|
||||
|
||||
private:
|
||||
void set_null();
|
||||
account_keys m_keys;
|
||||
void setNull();
|
||||
AccountKeys m_keys;
|
||||
uint64_t m_creation_timestamp;
|
||||
|
||||
friend struct AccountBaseSerializer<true>;
|
||||
friend struct AccountBaseSerializer<false>;
|
||||
};
|
||||
}
|
88
src/CryptoNoteCore/BlockIndex.cpp
Executable file
88
src/CryptoNoteCore/BlockIndex.cpp
Executable file
|
@ -0,0 +1,88 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "BlockIndex.h"
|
||||
|
||||
#include <boost/utility/value_init.hpp>
|
||||
|
||||
#include "CryptoNoteSerialization.h"
|
||||
#include "Serialization/SerializationOverloads.h"
|
||||
|
||||
namespace CryptoNote {
|
||||
Crypto::Hash BlockIndex::getBlockId(uint32_t height) const {
|
||||
assert(height < m_container.size());
|
||||
|
||||
return m_container[static_cast<size_t>(height)];
|
||||
}
|
||||
|
||||
std::vector<Crypto::Hash> BlockIndex::getBlockIds(uint32_t startBlockIndex, uint32_t maxCount) const {
|
||||
std::vector<Crypto::Hash> result;
|
||||
if (startBlockIndex >= m_container.size()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t count = std::min(static_cast<size_t>(maxCount), m_container.size() - static_cast<size_t>(startBlockIndex));
|
||||
result.reserve(count);
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
result.push_back(m_container[startBlockIndex + i]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool BlockIndex::findSupplement(const std::vector<Crypto::Hash>& ids, uint32_t& offset) const {
|
||||
for (const auto& id : ids) {
|
||||
if (getBlockHeight(id, offset)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<Crypto::Hash> BlockIndex::buildSparseChain(const Crypto::Hash& startBlockId) const {
|
||||
assert(m_index.count(startBlockId) > 0);
|
||||
|
||||
uint32_t startBlockHeight;
|
||||
getBlockHeight(startBlockId, startBlockHeight);
|
||||
|
||||
std::vector<Crypto::Hash> result;
|
||||
size_t sparseChainEnd = static_cast<size_t>(startBlockHeight + 1);
|
||||
for (size_t i = 1; i <= sparseChainEnd; i *= 2) {
|
||||
result.emplace_back(m_container[sparseChainEnd - i]);
|
||||
}
|
||||
|
||||
if (result.back() != m_container[0]) {
|
||||
result.emplace_back(m_container[0]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Crypto::Hash BlockIndex::getTailId() const {
|
||||
assert(!m_container.empty());
|
||||
return m_container.back();
|
||||
}
|
||||
|
||||
void BlockIndex::serialize(ISerializer& s) {
|
||||
if (s.type() == ISerializer::INPUT) {
|
||||
readSequence<Crypto::Hash>(std::back_inserter(m_container), "index", s);
|
||||
} else {
|
||||
writeSequence<Crypto::Hash>(m_container.begin(), m_container.end(), "index", s);
|
||||
}
|
||||
}
|
||||
}
|
34
src/cryptonote_core/BlockIndex.h → src/CryptoNoteCore/BlockIndex.h
Normal file → Executable file
34
src/cryptonote_core/BlockIndex.h → src/CryptoNoteCore/BlockIndex.h
Normal file → Executable file
|
@ -20,10 +20,12 @@
|
|||
#include <boost/multi_index/random_access_index.hpp>
|
||||
|
||||
#include "crypto/hash.h"
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
namespace CryptoNote
|
||||
{
|
||||
class ISerializer;
|
||||
|
||||
class BlockIndex {
|
||||
|
||||
public:
|
||||
|
@ -36,49 +38,47 @@ namespace CryptoNote
|
|||
}
|
||||
|
||||
// returns true if new element was inserted, false if already exists
|
||||
bool push(const crypto::hash& h) {
|
||||
bool push(const Crypto::Hash& h) {
|
||||
auto result = m_container.push_back(h);
|
||||
return result.second;
|
||||
}
|
||||
|
||||
bool hasBlock(const crypto::hash& h) const {
|
||||
bool hasBlock(const Crypto::Hash& h) const {
|
||||
return m_index.find(h) != m_index.end();
|
||||
}
|
||||
|
||||
bool getBlockHeight(const crypto::hash& h, uint64_t& height) const {
|
||||
bool getBlockHeight(const Crypto::Hash& h, uint32_t& height) const {
|
||||
auto hi = m_index.find(h);
|
||||
if (hi == m_index.end())
|
||||
return false;
|
||||
|
||||
height = std::distance(m_container.begin(), m_container.project<0>(hi));
|
||||
height = static_cast<uint32_t>(std::distance(m_container.begin(), m_container.project<0>(hi)));
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
return m_container.size();
|
||||
uint32_t size() const {
|
||||
return static_cast<uint32_t>(m_container.size());
|
||||
}
|
||||
|
||||
void clear() {
|
||||
m_container.clear();
|
||||
}
|
||||
|
||||
crypto::hash getBlockId(uint64_t height) const;
|
||||
bool getBlockIds(uint64_t startHeight, size_t maxCount, std::list<crypto::hash>& items) const;
|
||||
bool findSupplement(const std::list<crypto::hash>& ids, uint64_t& offset) const;
|
||||
bool getShortChainHistory(std::list<crypto::hash>& ids) const;
|
||||
crypto::hash getTailId() const;
|
||||
Crypto::Hash getBlockId(uint32_t height) const;
|
||||
std::vector<Crypto::Hash> getBlockIds(uint32_t startBlockIndex, uint32_t maxCount) const;
|
||||
bool findSupplement(const std::vector<Crypto::Hash>& ids, uint32_t& offset) const;
|
||||
std::vector<Crypto::Hash> buildSparseChain(const Crypto::Hash& startBlockId) const;
|
||||
Crypto::Hash getTailId() const;
|
||||
|
||||
template <class Archive> void serialize(Archive& ar, const unsigned int version) {
|
||||
ar & m_container;
|
||||
}
|
||||
void serialize(ISerializer& s);
|
||||
|
||||
private:
|
||||
|
||||
typedef boost::multi_index_container <
|
||||
crypto::hash,
|
||||
Crypto::Hash,
|
||||
boost::multi_index::indexed_by<
|
||||
boost::multi_index::random_access<>,
|
||||
boost::multi_index::hashed_unique<boost::multi_index::identity<crypto::hash>>
|
||||
boost::multi_index::hashed_unique<boost::multi_index::identity<Crypto::Hash>>
|
||||
>
|
||||
> ContainerT;
|
||||
|
File diff suppressed because it is too large
Load diff
382
src/CryptoNoteCore/Blockchain.h
Executable file
382
src/CryptoNoteCore/Blockchain.h
Executable file
|
@ -0,0 +1,382 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include "google/sparse_hash_set"
|
||||
#include "google/sparse_hash_map"
|
||||
|
||||
#include "Common/ObserverManager.h"
|
||||
#include "Common/Util.h"
|
||||
#include "CryptoNoteCore/BlockIndex.h"
|
||||
#include "CryptoNoteCore/Checkpoints.h"
|
||||
#include "CryptoNoteCore/Currency.h"
|
||||
#include "CryptoNoteCore/IBlockchainStorageObserver.h"
|
||||
#include "CryptoNoteCore/ITransactionValidator.h"
|
||||
#include "CryptoNoteCore/SwappedVector.h"
|
||||
#include "CryptoNoteCore/UpgradeDetector.h"
|
||||
#include "CryptoNoteCore/CryptoNoteFormatUtils.h"
|
||||
#include "CryptoNoteCore/TransactionPool.h"
|
||||
#include "CryptoNoteCore/BlockchainIndices.h"
|
||||
|
||||
#include "CryptoNoteCore/MessageQueue.h"
|
||||
#include "CryptoNoteCore/BlockchainMessages.h"
|
||||
#include "CryptoNoteCore/IntrusiveLinkedList.h"
|
||||
|
||||
#include <Logging/LoggerRef.h>
|
||||
|
||||
#undef ERROR
|
||||
|
||||
namespace CryptoNote {
|
||||
struct NOTIFY_REQUEST_GET_OBJECTS_request;
|
||||
struct NOTIFY_RESPONSE_GET_OBJECTS_request;
|
||||
struct COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_request;
|
||||
struct COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_response;
|
||||
struct COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_outs_for_amount;
|
||||
|
||||
using CryptoNote::BlockInfo;
|
||||
class Blockchain : public CryptoNote::ITransactionValidator {
|
||||
public:
|
||||
Blockchain(const Currency& currency, tx_memory_pool& tx_pool, Logging::ILogger& logger);
|
||||
|
||||
bool addObserver(IBlockchainStorageObserver* observer);
|
||||
bool removeObserver(IBlockchainStorageObserver* observer);
|
||||
|
||||
// ITransactionValidator
|
||||
virtual bool checkTransactionInputs(const CryptoNote::Transaction& tx, BlockInfo& maxUsedBlock) override;
|
||||
virtual bool checkTransactionInputs(const CryptoNote::Transaction& tx, BlockInfo& maxUsedBlock, BlockInfo& lastFailed) override;
|
||||
virtual bool haveSpentKeyImages(const CryptoNote::Transaction& tx) override;
|
||||
virtual bool checkTransactionSize(size_t blobSize) override;
|
||||
|
||||
bool init() { return init(Tools::getDefaultDataDirectory(), true); }
|
||||
bool init(const std::string& config_folder, bool load_existing);
|
||||
bool deinit();
|
||||
|
||||
bool getLowerBound(uint64_t timestamp, uint64_t startOffset, uint32_t& height);
|
||||
std::vector<Crypto::Hash> getBlockIds(uint32_t startHeight, uint32_t maxCount);
|
||||
|
||||
void setCheckpoints(Checkpoints&& chk_pts) { m_checkpoints = chk_pts; }
|
||||
bool getBlocks(uint32_t start_offset, uint32_t count, std::list<Block>& blocks, std::list<Transaction>& txs);
|
||||
bool getBlocks(uint32_t start_offset, uint32_t count, std::list<Block>& blocks);
|
||||
bool getAlternativeBlocks(std::list<Block>& blocks);
|
||||
uint32_t getAlternativeBlocksCount();
|
||||
Crypto::Hash getBlockIdByHeight(uint32_t height);
|
||||
bool getBlockByHash(const Crypto::Hash &h, Block &blk);
|
||||
bool getBlockHeight(const Crypto::Hash& blockId, uint32_t& blockHeight);
|
||||
|
||||
template<class archive_t> void serialize(archive_t & ar, const unsigned int version);
|
||||
|
||||
bool haveTransaction(const Crypto::Hash &id);
|
||||
bool haveTransactionKeyImagesAsSpent(const Transaction &tx);
|
||||
|
||||
uint32_t getCurrentBlockchainHeight(); //TODO rename to getCurrentBlockchainSize
|
||||
Crypto::Hash getTailId();
|
||||
Crypto::Hash getTailId(uint32_t& height);
|
||||
difficulty_type getDifficultyForNextBlock();
|
||||
uint64_t getCoinsInCirculation();
|
||||
uint8_t getBlockMajorVersionForHeight(uint32_t height) const;
|
||||
bool addNewBlock(const Block& bl_, block_verification_context& bvc);
|
||||
bool resetAndSetGenesisBlock(const Block& b);
|
||||
bool haveBlock(const Crypto::Hash& id);
|
||||
size_t getTotalTransactions();
|
||||
std::vector<Crypto::Hash> buildSparseChain();
|
||||
std::vector<Crypto::Hash> buildSparseChain(const Crypto::Hash& startBlockId);
|
||||
uint32_t findBlockchainSupplement(const std::vector<Crypto::Hash>& qblock_ids); // !!!!
|
||||
std::vector<Crypto::Hash> findBlockchainSupplement(const std::vector<Crypto::Hash>& remoteBlockIds, size_t maxCount,
|
||||
uint32_t& totalBlockCount, uint32_t& startBlockIndex);
|
||||
bool handleGetObjects(NOTIFY_REQUEST_GET_OBJECTS_request& arg, NOTIFY_RESPONSE_GET_OBJECTS_request& rsp); //Deprecated. Should be removed with CryptoNoteProtocolHandler.
|
||||
bool getRandomOutsByAmount(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_response& res);
|
||||
bool getBackwardBlocksSize(size_t from_height, std::vector<size_t>& sz, size_t count);
|
||||
bool getTransactionOutputGlobalIndexes(const Crypto::Hash& tx_id, std::vector<uint32_t>& indexs);
|
||||
bool get_out_by_msig_gindex(uint64_t amount, uint64_t gindex, MultisignatureOutput& out);
|
||||
bool checkTransactionInputs(const Transaction& tx, uint32_t& pmax_used_block_height, Crypto::Hash& max_used_block_id, BlockInfo* tail = 0);
|
||||
uint64_t getCurrentCumulativeBlocksizeLimit();
|
||||
bool isStoringBlockchain(){return m_is_blockchain_storing;}
|
||||
uint64_t blockDifficulty(size_t i);
|
||||
bool getBlockContainingTransaction(const Crypto::Hash& txId, Crypto::Hash& blockId, uint32_t& blockHeight);
|
||||
bool getAlreadyGeneratedCoins(const Crypto::Hash& hash, uint64_t& generatedCoins);
|
||||
bool getBlockSize(const Crypto::Hash& hash, size_t& size);
|
||||
bool getMultisigOutputReference(const MultisignatureInput& txInMultisig, std::pair<Crypto::Hash, size_t>& outputReference);
|
||||
bool getGeneratedTransactionsNumber(uint32_t height, uint64_t& generatedTransactions);
|
||||
bool getOrphanBlockIdsByHeight(uint32_t height, std::vector<Crypto::Hash>& blockHashes);
|
||||
bool getBlockIdsByTimestamp(uint64_t timestampBegin, uint64_t timestampEnd, uint32_t blocksNumberLimit, std::vector<Crypto::Hash>& hashes, uint32_t& blocksNumberWithinTimestamps);
|
||||
bool getTransactionIdsByPaymentId(const Crypto::Hash& paymentId, std::vector<Crypto::Hash>& transactionHashes);
|
||||
bool isBlockInMainChain(const Crypto::Hash& blockId);
|
||||
|
||||
template<class visitor_t> bool scanOutputKeysForIndexes(const KeyInput& tx_in_to_key, visitor_t& vis, uint32_t* pmax_related_block_height = NULL);
|
||||
|
||||
bool addMessageQueue(MessageQueue<BlockchainMessage>& messageQueue);
|
||||
bool removeMessageQueue(MessageQueue<BlockchainMessage>& messageQueue);
|
||||
|
||||
template<class t_ids_container, class t_blocks_container, class t_missed_container>
|
||||
bool getBlocks(const t_ids_container& block_ids, t_blocks_container& blocks, t_missed_container& missed_bs) {
|
||||
std::lock_guard<std::recursive_mutex> lk(m_blockchain_lock);
|
||||
|
||||
for (const auto& bl_id : block_ids) {
|
||||
uint32_t height = 0;
|
||||
if (!m_blockIndex.getBlockHeight(bl_id, height)) {
|
||||
missed_bs.push_back(bl_id);
|
||||
} else {
|
||||
if (!(height < m_blocks.size())) { logger(Logging::ERROR, Logging::BRIGHT_RED) << "Internal error: bl_id=" << Common::podToHex(bl_id)
|
||||
<< " have index record with offset=" << height << ", bigger then m_blocks.size()=" << m_blocks.size(); return false; }
|
||||
blocks.push_back(m_blocks[height].bl);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class t_ids_container, class t_tx_container, class t_missed_container>
|
||||
void getBlockchainTransactions(const t_ids_container& txs_ids, t_tx_container& txs, t_missed_container& missed_txs) {
|
||||
std::lock_guard<decltype(m_blockchain_lock)> bcLock(m_blockchain_lock);
|
||||
|
||||
for (const auto& tx_id : txs_ids) {
|
||||
auto it = m_transactionMap.find(tx_id);
|
||||
if (it == m_transactionMap.end()) {
|
||||
missed_txs.push_back(tx_id);
|
||||
} else {
|
||||
txs.push_back(transactionByIndex(it->second).tx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class t_ids_container, class t_tx_container, class t_missed_container>
|
||||
void getTransactions(const t_ids_container& txs_ids, t_tx_container& txs, t_missed_container& missed_txs, bool checkTxPool = false) {
|
||||
if (checkTxPool){
|
||||
std::lock_guard<decltype(m_tx_pool)> txLock(m_tx_pool);
|
||||
|
||||
getBlockchainTransactions(txs_ids, txs, missed_txs);
|
||||
|
||||
auto poolTxIds = std::move(missed_txs);
|
||||
missed_txs.clear();
|
||||
m_tx_pool.getTransactions(poolTxIds, txs, missed_txs);
|
||||
|
||||
} else {
|
||||
getBlockchainTransactions(txs_ids, txs, missed_txs);
|
||||
}
|
||||
}
|
||||
|
||||
//debug functions
|
||||
void print_blockchain(uint64_t start_index, uint64_t end_index);
|
||||
void print_blockchain_index();
|
||||
void print_blockchain_outs(const std::string& file);
|
||||
|
||||
struct TransactionIndex {
|
||||
uint32_t block;
|
||||
uint16_t transaction;
|
||||
|
||||
void serialize(ISerializer& s) {
|
||||
s(block, "block");
|
||||
s(transaction, "tx");
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
struct MultisignatureOutputUsage {
|
||||
TransactionIndex transactionIndex;
|
||||
uint16_t outputIndex;
|
||||
bool isUsed;
|
||||
|
||||
void serialize(ISerializer& s) {
|
||||
s(transactionIndex, "txindex");
|
||||
s(outputIndex, "outindex");
|
||||
s(isUsed, "used");
|
||||
}
|
||||
};
|
||||
|
||||
struct TransactionEntry {
|
||||
Transaction tx;
|
||||
std::vector<uint32_t> m_global_output_indexes;
|
||||
|
||||
void serialize(ISerializer& s) {
|
||||
s(tx, "tx");
|
||||
s(m_global_output_indexes, "indexes");
|
||||
}
|
||||
};
|
||||
|
||||
struct BlockEntry {
|
||||
Block bl;
|
||||
uint32_t height;
|
||||
uint64_t block_cumulative_size;
|
||||
difficulty_type cumulative_difficulty;
|
||||
uint64_t already_generated_coins;
|
||||
std::vector<TransactionEntry> transactions;
|
||||
|
||||
void serialize(ISerializer& s) {
|
||||
s(bl, "block");
|
||||
s(height, "height");
|
||||
s(block_cumulative_size, "block_cumulative_size");
|
||||
s(cumulative_difficulty, "cumulative_difficulty");
|
||||
s(already_generated_coins, "already_generated_coins");
|
||||
s(transactions, "transactions");
|
||||
}
|
||||
};
|
||||
|
||||
typedef google::sparse_hash_set<Crypto::KeyImage> key_images_container;
|
||||
typedef std::unordered_map<Crypto::Hash, BlockEntry> blocks_ext_by_hash;
|
||||
typedef google::sparse_hash_map<uint64_t, std::vector<std::pair<TransactionIndex, uint16_t>>> outputs_container; //Crypto::Hash - tx hash, size_t - index of out in transaction
|
||||
typedef google::sparse_hash_map<uint64_t, std::vector<MultisignatureOutputUsage>> MultisignatureOutputsContainer;
|
||||
|
||||
const Currency& m_currency;
|
||||
tx_memory_pool& m_tx_pool;
|
||||
std::recursive_mutex m_blockchain_lock; // TODO: add here reader/writer lock
|
||||
Crypto::cn_context m_cn_context;
|
||||
Tools::ObserverManager<IBlockchainStorageObserver> m_observerManager;
|
||||
|
||||
key_images_container m_spent_keys;
|
||||
size_t m_current_block_cumul_sz_limit;
|
||||
blocks_ext_by_hash m_alternative_chains; // Crypto::Hash -> block_extended_info
|
||||
outputs_container m_outputs;
|
||||
|
||||
std::string m_config_folder;
|
||||
Checkpoints m_checkpoints;
|
||||
std::atomic<bool> m_is_in_checkpoint_zone;
|
||||
std::atomic<bool> m_is_blockchain_storing;
|
||||
|
||||
typedef SwappedVector<BlockEntry> Blocks;
|
||||
typedef std::unordered_map<Crypto::Hash, uint32_t> BlockMap;
|
||||
typedef std::unordered_map<Crypto::Hash, TransactionIndex> TransactionMap;
|
||||
typedef BasicUpgradeDetector<Blocks> UpgradeDetector;
|
||||
|
||||
friend class BlockCacheSerializer;
|
||||
friend class BlockchainIndicesSerializer;
|
||||
|
||||
Blocks m_blocks;
|
||||
CryptoNote::BlockIndex m_blockIndex;
|
||||
TransactionMap m_transactionMap;
|
||||
MultisignatureOutputsContainer m_multisignatureOutputs;
|
||||
UpgradeDetector m_upgradeDetector;
|
||||
|
||||
PaymentIdIndex m_paymentIdIndex;
|
||||
TimestampBlocksIndex m_timestampIndex;
|
||||
GeneratedTransactionsIndex m_generatedTransactionsIndex;
|
||||
OrphanBlocksIndex m_orthanBlocksIndex;
|
||||
|
||||
IntrusiveLinkedList<MessageQueue<BlockchainMessage>> m_messageQueueList;
|
||||
|
||||
Logging::LoggerRef logger;
|
||||
|
||||
void rebuildCache();
|
||||
bool storeCache();
|
||||
bool switch_to_alternative_blockchain(std::list<blocks_ext_by_hash::iterator>& alt_chain, bool discard_disconnected_chain);
|
||||
bool handle_alternative_block(const Block& b, const Crypto::Hash& id, block_verification_context& bvc, bool sendNewAlternativeBlockMessage = true);
|
||||
difficulty_type get_next_difficulty_for_alternative_chain(const std::list<blocks_ext_by_hash::iterator>& alt_chain, BlockEntry& bei);
|
||||
bool prevalidate_miner_transaction(const Block& b, uint32_t height);
|
||||
bool validate_miner_transaction(const Block& b, uint32_t height, size_t cumulativeBlockSize, uint64_t alreadyGeneratedCoins, uint64_t fee, uint64_t& reward, int64_t& emissionChange);
|
||||
bool rollback_blockchain_switching(std::list<Block>& original_chain, size_t rollback_height);
|
||||
bool get_last_n_blocks_sizes(std::vector<size_t>& sz, size_t count);
|
||||
bool add_out_to_get_random_outs(std::vector<std::pair<TransactionIndex, uint16_t>>& amount_outs, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_outs_for_amount& result_outs, uint64_t amount, size_t i);
|
||||
bool is_tx_spendtime_unlocked(uint64_t unlock_time);
|
||||
size_t find_end_of_allowed_index(const std::vector<std::pair<TransactionIndex, uint16_t>>& amount_outs);
|
||||
bool check_block_timestamp_main(const Block& b);
|
||||
bool check_block_timestamp(std::vector<uint64_t> timestamps, const Block& b);
|
||||
uint64_t get_adjusted_time();
|
||||
bool complete_timestamps_vector(uint64_t start_height, std::vector<uint64_t>& timestamps);
|
||||
bool checkBlockVersion(const Block& b, const Crypto::Hash& blockHash);
|
||||
bool checkParentBlockSize(const Block& b, const Crypto::Hash& blockHash);
|
||||
bool checkCumulativeBlockSize(const Crypto::Hash& blockId, size_t cumulativeBlockSize, uint64_t height);
|
||||
std::vector<Crypto::Hash> doBuildSparseChain(const Crypto::Hash& startBlockId) const;
|
||||
bool getBlockCumulativeSize(const Block& block, size_t& cumulativeSize);
|
||||
bool update_next_comulative_size_limit();
|
||||
bool check_tx_input(const KeyInput& txin, const Crypto::Hash& tx_prefix_hash, const std::vector<Crypto::Signature>& sig, uint32_t* pmax_related_block_height = NULL);
|
||||
bool checkTransactionInputs(const Transaction& tx, const Crypto::Hash& tx_prefix_hash, uint32_t* pmax_used_block_height = NULL);
|
||||
bool checkTransactionInputs(const Transaction& tx, uint32_t* pmax_used_block_height = NULL);
|
||||
bool have_tx_keyimg_as_spent(const Crypto::KeyImage &key_im);
|
||||
const TransactionEntry& transactionByIndex(TransactionIndex index);
|
||||
bool pushBlock(const Block& blockData, block_verification_context& bvc);
|
||||
bool pushBlock(const Block& blockData, const std::vector<Transaction>& transactions, block_verification_context& bvc);
|
||||
bool pushBlock(BlockEntry& block);
|
||||
void popBlock(const Crypto::Hash& blockHash);
|
||||
bool pushTransaction(BlockEntry& block, const Crypto::Hash& transactionHash, TransactionIndex transactionIndex);
|
||||
void popTransaction(const Transaction& transaction, const Crypto::Hash& transactionHash);
|
||||
void popTransactions(const BlockEntry& block, const Crypto::Hash& minerTransactionHash);
|
||||
bool validateInput(const MultisignatureInput& input, const Crypto::Hash& transactionHash, const Crypto::Hash& transactionPrefixHash, const std::vector<Crypto::Signature>& transactionSignatures);
|
||||
|
||||
bool storeBlockchainIndices();
|
||||
bool loadBlockchainIndices();
|
||||
|
||||
bool loadTransactions(const Block& block, std::vector<Transaction>& transactions);
|
||||
void saveTransactions(const std::vector<Transaction>& transactions);
|
||||
|
||||
void sendMessage(const BlockchainMessage& message);
|
||||
|
||||
friend class LockedBlockchainStorage;
|
||||
};
|
||||
|
||||
class LockedBlockchainStorage: boost::noncopyable {
|
||||
public:
|
||||
|
||||
LockedBlockchainStorage(Blockchain& bc)
|
||||
: m_bc(bc), m_lock(bc.m_blockchain_lock) {}
|
||||
|
||||
Blockchain* operator -> () {
|
||||
return &m_bc;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Blockchain& m_bc;
|
||||
std::lock_guard<std::recursive_mutex> m_lock;
|
||||
};
|
||||
|
||||
template<class visitor_t> bool Blockchain::scanOutputKeysForIndexes(const KeyInput& tx_in_to_key, visitor_t& vis, uint32_t* pmax_related_block_height) {
|
||||
std::lock_guard<std::recursive_mutex> lk(m_blockchain_lock);
|
||||
auto it = m_outputs.find(tx_in_to_key.amount);
|
||||
if (it == m_outputs.end() || !tx_in_to_key.outputIndexes.size())
|
||||
return false;
|
||||
|
||||
std::vector<uint32_t> absolute_offsets = relative_output_offsets_to_absolute(tx_in_to_key.outputIndexes);
|
||||
std::vector<std::pair<TransactionIndex, uint16_t>>& amount_outs_vec = it->second;
|
||||
size_t count = 0;
|
||||
for (uint64_t i : absolute_offsets) {
|
||||
if(i >= amount_outs_vec.size() ) {
|
||||
logger(Logging::INFO) << "Wrong index in transaction inputs: " << i << ", expected maximum " << amount_outs_vec.size() - 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
//auto tx_it = m_transactionMap.find(amount_outs_vec[i].first);
|
||||
//if (!(tx_it != m_transactionMap.end())) { logger(ERROR, BRIGHT_RED) << "Wrong transaction id in output indexes: " << Common::podToHex(amount_outs_vec[i].first); return false; }
|
||||
|
||||
const TransactionEntry& tx = transactionByIndex(amount_outs_vec[i].first);
|
||||
|
||||
if (!(amount_outs_vec[i].second < tx.tx.outputs.size())) {
|
||||
logger(Logging::ERROR, Logging::BRIGHT_RED)
|
||||
<< "Wrong index in transaction outputs: "
|
||||
<< amount_outs_vec[i].second << ", expected less then "
|
||||
<< tx.tx.outputs.size();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!vis.handle_output(tx.tx, tx.tx.outputs[amount_outs_vec[i].second], amount_outs_vec[i].second)) {
|
||||
logger(Logging::INFO) << "Failed to handle_output for output no = " << count << ", with absolute offset " << i;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(count++ == absolute_offsets.size()-1 && pmax_related_block_height) {
|
||||
if (*pmax_related_block_height < amount_outs_vec[i].first.block) {
|
||||
*pmax_related_block_height = amount_outs_vec[i].first.block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
262
src/CryptoNoteCore/BlockchainIndices.cpp
Executable file
262
src/CryptoNoteCore/BlockchainIndices.cpp
Executable file
|
@ -0,0 +1,262 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#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();
|
||||
}
|
||||
|
||||
}
|
121
src/CryptoNoteCore/BlockchainIndices.h
Executable file
121
src/CryptoNoteCore/BlockchainIndices.h
Executable file
|
@ -0,0 +1,121 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
|
||||
#include "crypto/hash.h"
|
||||
#include "CryptoNoteBasic.h"
|
||||
|
||||
namespace CryptoNote {
|
||||
|
||||
class ISerializer;
|
||||
|
||||
class PaymentIdIndex {
|
||||
public:
|
||||
PaymentIdIndex() = default;
|
||||
|
||||
bool add(const Transaction& transaction);
|
||||
bool remove(const Transaction& transaction);
|
||||
bool find(const Crypto::Hash& paymentId, std::vector<Crypto::Hash>& transactionHashes);
|
||||
void clear();
|
||||
|
||||
void serialize(ISerializer& s);
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive& archive, unsigned int version) {
|
||||
archive & index;
|
||||
}
|
||||
private:
|
||||
std::unordered_multimap<Crypto::Hash, Crypto::Hash> index;
|
||||
};
|
||||
|
||||
class TimestampBlocksIndex {
|
||||
public:
|
||||
TimestampBlocksIndex() = default;
|
||||
|
||||
bool add(uint64_t timestamp, const Crypto::Hash& hash);
|
||||
bool remove(uint64_t timestamp, const Crypto::Hash& hash);
|
||||
bool find(uint64_t timestampBegin, uint64_t timestampEnd, uint32_t hashesNumberLimit, std::vector<Crypto::Hash>& hashes, uint32_t& hashesNumberWithinTimestamps);
|
||||
void clear();
|
||||
|
||||
void serialize(ISerializer& s);
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive& archive, unsigned int version) {
|
||||
archive & index;
|
||||
}
|
||||
private:
|
||||
std::multimap<uint64_t, Crypto::Hash> index;
|
||||
};
|
||||
|
||||
class TimestampTransactionsIndex {
|
||||
public:
|
||||
TimestampTransactionsIndex() = default;
|
||||
|
||||
bool add(uint64_t timestamp, const Crypto::Hash& hash);
|
||||
bool remove(uint64_t timestamp, const Crypto::Hash& hash);
|
||||
bool find(uint64_t timestampBegin, uint64_t timestampEnd, uint64_t hashesNumberLimit, std::vector<Crypto::Hash>& hashes, uint64_t& hashesNumberWithinTimestamps);
|
||||
void clear();
|
||||
|
||||
void serialize(ISerializer& s);
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive& archive, unsigned int version) {
|
||||
archive & index;
|
||||
}
|
||||
private:
|
||||
std::multimap<uint64_t, Crypto::Hash> index;
|
||||
};
|
||||
|
||||
class GeneratedTransactionsIndex {
|
||||
public:
|
||||
GeneratedTransactionsIndex();
|
||||
|
||||
bool add(const Block& block);
|
||||
bool remove(const Block& block);
|
||||
bool find(uint32_t height, uint64_t& generatedTransactions);
|
||||
void clear();
|
||||
|
||||
void serialize(ISerializer& s);
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive& archive, unsigned int version) {
|
||||
archive & index;
|
||||
archive & lastGeneratedTxNumber;
|
||||
}
|
||||
private:
|
||||
std::unordered_map<uint32_t, uint64_t> index;
|
||||
uint64_t lastGeneratedTxNumber;
|
||||
};
|
||||
|
||||
class OrphanBlocksIndex {
|
||||
public:
|
||||
OrphanBlocksIndex() = default;
|
||||
|
||||
bool add(const Block& block);
|
||||
bool remove(const Block& block);
|
||||
bool find(uint32_t height, std::vector<Crypto::Hash>& blockHashes);
|
||||
void clear();
|
||||
private:
|
||||
std::unordered_multimap<uint32_t, Crypto::Hash> index;
|
||||
};
|
||||
|
||||
}
|
109
src/CryptoNoteCore/BlockchainMessages.cpp
Normal file
109
src/CryptoNoteCore/BlockchainMessages.cpp
Normal file
|
@ -0,0 +1,109 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "CryptoNoteCore/BlockchainMessages.h"
|
||||
|
||||
namespace CryptoNote {
|
||||
|
||||
NewBlockMessage::NewBlockMessage(const Crypto::Hash& hash) : blockHash(hash) {}
|
||||
|
||||
void NewBlockMessage::get(Crypto::Hash& hash) const {
|
||||
hash = blockHash;
|
||||
}
|
||||
|
||||
NewAlternativeBlockMessage::NewAlternativeBlockMessage(const Crypto::Hash& hash) : blockHash(hash) {}
|
||||
|
||||
void NewAlternativeBlockMessage::get(Crypto::Hash& hash) const {
|
||||
hash = blockHash;
|
||||
}
|
||||
|
||||
ChainSwitchMessage::ChainSwitchMessage(std::vector<Crypto::Hash>&& hashes) : blocksFromCommonRoot(std::move(hashes)) {}
|
||||
|
||||
ChainSwitchMessage::ChainSwitchMessage(const ChainSwitchMessage& other) : blocksFromCommonRoot(other.blocksFromCommonRoot) {}
|
||||
|
||||
void ChainSwitchMessage::get(std::vector<Crypto::Hash>& hashes) const {
|
||||
hashes = blocksFromCommonRoot;
|
||||
}
|
||||
|
||||
BlockchainMessage::BlockchainMessage(NewBlockMessage&& message) : type(MessageType::NEW_BLOCK_MESSAGE), newBlockMessage(std::move(message)) {}
|
||||
|
||||
BlockchainMessage::BlockchainMessage(NewAlternativeBlockMessage&& message) : type(MessageType::NEW_ALTERNATIVE_BLOCK_MESSAGE), newAlternativeBlockMessage(std::move(message)) {}
|
||||
|
||||
BlockchainMessage::BlockchainMessage(ChainSwitchMessage&& message) : type(MessageType::CHAIN_SWITCH_MESSAGE) {
|
||||
chainSwitchMessage = new ChainSwitchMessage(std::move(message));
|
||||
}
|
||||
|
||||
BlockchainMessage::BlockchainMessage(const BlockchainMessage& other) : type(other.type) {
|
||||
switch (type) {
|
||||
case MessageType::NEW_BLOCK_MESSAGE:
|
||||
new (&newBlockMessage) NewBlockMessage(other.newBlockMessage);
|
||||
break;
|
||||
case MessageType::NEW_ALTERNATIVE_BLOCK_MESSAGE:
|
||||
new (&newAlternativeBlockMessage) NewAlternativeBlockMessage(other.newAlternativeBlockMessage);
|
||||
break;
|
||||
case MessageType::CHAIN_SWITCH_MESSAGE:
|
||||
chainSwitchMessage = new ChainSwitchMessage(*other.chainSwitchMessage);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BlockchainMessage::~BlockchainMessage() {
|
||||
switch (type) {
|
||||
case MessageType::NEW_BLOCK_MESSAGE:
|
||||
newBlockMessage.~NewBlockMessage();
|
||||
break;
|
||||
case MessageType::NEW_ALTERNATIVE_BLOCK_MESSAGE:
|
||||
newAlternativeBlockMessage.~NewAlternativeBlockMessage();
|
||||
break;
|
||||
case MessageType::CHAIN_SWITCH_MESSAGE:
|
||||
delete chainSwitchMessage;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BlockchainMessage::MessageType BlockchainMessage::getType() const {
|
||||
return type;
|
||||
}
|
||||
|
||||
bool BlockchainMessage::getNewBlockHash(Crypto::Hash& hash) const {
|
||||
if (type == MessageType::NEW_BLOCK_MESSAGE) {
|
||||
newBlockMessage.get(hash);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool BlockchainMessage::getNewAlternativeBlockHash(Crypto::Hash& hash) const {
|
||||
if (type == MessageType::NEW_ALTERNATIVE_BLOCK_MESSAGE) {
|
||||
newAlternativeBlockMessage.get(hash);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool BlockchainMessage::getChainSwitch(std::vector<Crypto::Hash>& hashes) const {
|
||||
if (type == MessageType::CHAIN_SWITCH_MESSAGE) {
|
||||
chainSwitchMessage->get(hashes);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
84
src/CryptoNoteCore/BlockchainMessages.h
Normal file
84
src/CryptoNoteCore/BlockchainMessages.h
Normal file
|
@ -0,0 +1,84 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <CryptoNote.h>
|
||||
|
||||
namespace CryptoNote {
|
||||
|
||||
class NewBlockMessage {
|
||||
public:
|
||||
NewBlockMessage(const Crypto::Hash& hash);
|
||||
NewBlockMessage() = default;
|
||||
void get(Crypto::Hash& hash) const;
|
||||
private:
|
||||
Crypto::Hash blockHash;
|
||||
};
|
||||
|
||||
class NewAlternativeBlockMessage {
|
||||
public:
|
||||
NewAlternativeBlockMessage(const Crypto::Hash& hash);
|
||||
NewAlternativeBlockMessage() = default;
|
||||
void get(Crypto::Hash& hash) const;
|
||||
private:
|
||||
Crypto::Hash blockHash;
|
||||
};
|
||||
|
||||
class ChainSwitchMessage {
|
||||
public:
|
||||
ChainSwitchMessage(std::vector<Crypto::Hash>&& hashes);
|
||||
ChainSwitchMessage(const ChainSwitchMessage& other);
|
||||
void get(std::vector<Crypto::Hash>& hashes) const;
|
||||
private:
|
||||
std::vector<Crypto::Hash> blocksFromCommonRoot;
|
||||
};
|
||||
|
||||
class BlockchainMessage {
|
||||
public:
|
||||
enum class MessageType {
|
||||
NEW_BLOCK_MESSAGE,
|
||||
NEW_ALTERNATIVE_BLOCK_MESSAGE,
|
||||
CHAIN_SWITCH_MESSAGE
|
||||
};
|
||||
|
||||
BlockchainMessage(NewBlockMessage&& message);
|
||||
BlockchainMessage(NewAlternativeBlockMessage&& message);
|
||||
BlockchainMessage(ChainSwitchMessage&& message);
|
||||
|
||||
BlockchainMessage(const BlockchainMessage& other);
|
||||
|
||||
~BlockchainMessage();
|
||||
|
||||
MessageType getType() const;
|
||||
|
||||
bool getNewBlockHash(Crypto::Hash& hash) const;
|
||||
bool getNewAlternativeBlockHash(Crypto::Hash& hash) const;
|
||||
bool getChainSwitch(std::vector<Crypto::Hash>& hashes) const;
|
||||
private:
|
||||
const MessageType type;
|
||||
|
||||
union {
|
||||
NewBlockMessage newBlockMessage;
|
||||
NewAlternativeBlockMessage newAlternativeBlockMessage;
|
||||
ChainSwitchMessage* chainSwitchMessage;
|
||||
};
|
||||
};
|
||||
|
||||
}
|
|
@ -15,17 +15,17 @@
|
|||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "checkpoints.h"
|
||||
#include "Checkpoints.h"
|
||||
#include "Common/StringTools.h"
|
||||
|
||||
using namespace Logging;
|
||||
|
||||
namespace CryptoNote {
|
||||
//---------------------------------------------------------------------------
|
||||
checkpoints::checkpoints(Logging::ILogger &log) : logger(log, "checkpoints") {}
|
||||
Checkpoints::Checkpoints(Logging::ILogger &log) : logger(log, "checkpoints") {}
|
||||
//---------------------------------------------------------------------------
|
||||
bool checkpoints::add_checkpoint(uint64_t height, const std::string &hash_str) {
|
||||
crypto::hash h = null_hash;
|
||||
bool Checkpoints::add_checkpoint(uint32_t height, const std::string &hash_str) {
|
||||
Crypto::Hash h = NULL_HASH;
|
||||
|
||||
if (!Common::podFromHex(hash_str, h)) {
|
||||
logger(ERROR) << "WRONG HASH IN CHECKPOINTS!!!";
|
||||
|
@ -41,11 +41,11 @@ bool checkpoints::add_checkpoint(uint64_t height, const std::string &hash_str) {
|
|||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
bool checkpoints::is_in_checkpoint_zone(uint64_t height) const {
|
||||
bool Checkpoints::is_in_checkpoint_zone(uint32_t height) const {
|
||||
return !m_points.empty() && (height <= (--m_points.end())->first);
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
bool checkpoints::check_block(uint64_t height, const crypto::hash &h,
|
||||
bool Checkpoints::check_block(uint32_t height, const Crypto::Hash &h,
|
||||
bool &is_a_checkpoint) const {
|
||||
auto it = m_points.find(height);
|
||||
is_a_checkpoint = it != m_points.end();
|
||||
|
@ -64,13 +64,13 @@ bool checkpoints::check_block(uint64_t height, const crypto::hash &h,
|
|||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
bool checkpoints::check_block(uint64_t height, const crypto::hash &h) const {
|
||||
bool Checkpoints::check_block(uint32_t height, const Crypto::Hash &h) const {
|
||||
bool ignored;
|
||||
return check_block(height, h, ignored);
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
bool checkpoints::is_alternative_block_allowed(uint64_t blockchain_height,
|
||||
uint64_t block_height) const {
|
||||
bool Checkpoints::is_alternative_block_allowed(uint32_t blockchain_height,
|
||||
uint32_t block_height) const {
|
||||
if (0 == block_height)
|
||||
return false;
|
||||
|
||||
|
@ -80,7 +80,7 @@ bool checkpoints::is_alternative_block_allowed(uint64_t blockchain_height,
|
|||
return true;
|
||||
|
||||
--it;
|
||||
uint64_t checkpoint_height = it->first;
|
||||
uint32_t checkpoint_height = it->first;
|
||||
return checkpoint_height < block_height;
|
||||
}
|
||||
}
|
18
src/cryptonote_core/checkpoints.h → src/CryptoNoteCore/Checkpoints.h
Normal file → Executable file
18
src/cryptonote_core/checkpoints.h → src/CryptoNoteCore/Checkpoints.h
Normal file → Executable file
|
@ -17,24 +17,24 @@
|
|||
|
||||
#pragma once
|
||||
#include <map>
|
||||
#include "cryptonote_basic_impl.h"
|
||||
#include "CryptoNoteBasicImpl.h"
|
||||
#include <Logging/LoggerRef.h>
|
||||
|
||||
namespace CryptoNote
|
||||
{
|
||||
class checkpoints
|
||||
class Checkpoints
|
||||
{
|
||||
public:
|
||||
checkpoints(Logging::ILogger& log);
|
||||
Checkpoints(Logging::ILogger& log);
|
||||
|
||||
bool add_checkpoint(uint64_t height, const std::string& hash_str);
|
||||
bool is_in_checkpoint_zone(uint64_t height) const;
|
||||
bool check_block(uint64_t height, const crypto::hash& h) const;
|
||||
bool check_block(uint64_t height, const crypto::hash& h, bool& is_a_checkpoint) const;
|
||||
bool is_alternative_block_allowed(uint64_t blockchain_height, uint64_t block_height) const;
|
||||
bool add_checkpoint(uint32_t height, const std::string& hash_str);
|
||||
bool is_in_checkpoint_zone(uint32_t height) const;
|
||||
bool check_block(uint32_t height, const Crypto::Hash& h) const;
|
||||
bool check_block(uint32_t height, const Crypto::Hash& h, bool& is_a_checkpoint) const;
|
||||
bool is_alternative_block_allowed(uint32_t blockchain_height, uint32_t block_height) const;
|
||||
|
||||
private:
|
||||
std::map<uint64_t, crypto::hash> m_points;
|
||||
std::map<uint32_t, Crypto::Hash> m_points;
|
||||
Logging::LoggerRef logger;
|
||||
};
|
||||
}
|
1031
src/CryptoNoteCore/Core.cpp
Executable file
1031
src/CryptoNoteCore/Core.cpp
Executable file
File diff suppressed because it is too large
Load diff
194
src/CryptoNoteCore/Core.h
Executable file
194
src/CryptoNoteCore/Core.h
Executable file
|
@ -0,0 +1,194 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/program_options/options_description.hpp>
|
||||
#include <boost/program_options/variables_map.hpp>
|
||||
|
||||
#include "P2p/NetNodeCommon.h"
|
||||
#include "CryptoNoteProtocol/CryptoNoteProtocolHandlerCommon.h"
|
||||
#include "Currency.h"
|
||||
#include "TransactionPool.h"
|
||||
#include "Blockchain.h"
|
||||
#include "CryptoNoteCore/IMinerHandler.h"
|
||||
#include "CryptoNoteCore/MinerConfig.h"
|
||||
#include "ICore.h"
|
||||
#include "ICoreObserver.h"
|
||||
#include "Common/ObserverManager.h"
|
||||
|
||||
#include "System/Dispatcher.h"
|
||||
#include "CryptoNoteCore/MessageQueue.h"
|
||||
#include "CryptoNoteCore/BlockchainMessages.h"
|
||||
|
||||
#include <Logging/LoggerMessage.h>
|
||||
|
||||
namespace CryptoNote {
|
||||
|
||||
struct core_stat_info;
|
||||
class miner;
|
||||
class CoreConfig;
|
||||
|
||||
class core : public ICore, public IMinerHandler, public IBlockchainStorageObserver, public ITxPoolObserver {
|
||||
public:
|
||||
core(const Currency& currency, i_cryptonote_protocol* pprotocol, Logging::ILogger& logger);
|
||||
~core();
|
||||
|
||||
bool on_idle();
|
||||
virtual bool handle_incoming_tx(const BinaryArray& tx_blob, tx_verification_context& tvc, bool keeped_by_block); //Deprecated. Should be removed with CryptoNoteProtocolHandler.
|
||||
bool handle_incoming_block_blob(const BinaryArray& block_blob, block_verification_context& bvc, bool control_miner, bool relay_block);
|
||||
virtual i_cryptonote_protocol* get_protocol(){return m_pprotocol;}
|
||||
const Currency& currency() const { return m_currency; }
|
||||
|
||||
//-------------------- IMinerHandler -----------------------
|
||||
virtual bool handle_block_found(Block& b);
|
||||
virtual bool get_block_template(Block& b, const AccountPublicAddress& adr, difficulty_type& diffic, uint32_t& height, const BinaryArray& ex_nonce);
|
||||
|
||||
bool addObserver(ICoreObserver* observer);
|
||||
bool removeObserver(ICoreObserver* observer);
|
||||
|
||||
miner& get_miner() { return *m_miner; }
|
||||
static void init_options(boost::program_options::options_description& desc);
|
||||
bool init(const CoreConfig& config, const MinerConfig& minerConfig, bool load_existing);
|
||||
bool set_genesis_block(const Block& b);
|
||||
bool deinit();
|
||||
|
||||
// ICore
|
||||
virtual size_t addChain(const std::vector<const IBlock*>& chain) override;
|
||||
virtual bool handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS_request& arg, NOTIFY_RESPONSE_GET_OBJECTS_request& rsp) override; //Deprecated. Should be removed with CryptoNoteProtocolHandler.
|
||||
virtual bool getBackwardBlocksSizes(uint32_t fromHeight, std::vector<size_t>& sizes, size_t count) override;
|
||||
virtual bool getBlockSize(const Crypto::Hash& hash, size_t& size) override;
|
||||
virtual bool getAlreadyGeneratedCoins(const Crypto::Hash& hash, uint64_t& generatedCoins) override;
|
||||
virtual bool getBlockReward(size_t medianSize, size_t currentBlockSize, uint64_t alreadyGeneratedCoins, uint64_t fee,
|
||||
bool penalizeFee, uint64_t& reward, int64_t& emissionChange) override;
|
||||
virtual bool scanOutputkeysForIndices(const KeyInput& txInToKey, std::list<std::pair<Crypto::Hash, size_t>>& outputReferences) override;
|
||||
virtual bool getBlockDifficulty(uint32_t height, difficulty_type& difficulty) override;
|
||||
virtual bool getBlockContainingTx(const Crypto::Hash& txId, Crypto::Hash& blockId, uint32_t& blockHeight) override;
|
||||
virtual bool getMultisigOutputReference(const MultisignatureInput& txInMultisig, std::pair<Crypto::Hash, size_t>& output_reference) override;
|
||||
virtual bool getGeneratedTransactionsNumber(uint32_t height, uint64_t& generatedTransactions) override;
|
||||
virtual bool getOrphanBlocksByHeight(uint32_t height, std::vector<Block>& blocks) override;
|
||||
virtual bool getBlocksByTimestamp(uint64_t timestampBegin, uint64_t timestampEnd, uint32_t blocksNumberLimit, std::vector<Block>& blocks, uint32_t& blocksNumberWithinTimestamps) override;
|
||||
virtual bool getPoolTransactionsByTimestamp(uint64_t timestampBegin, uint64_t timestampEnd, uint32_t transactionsNumberLimit, std::vector<Transaction>& transactions, uint64_t& transactionsNumberWithinTimestamps) override;
|
||||
virtual bool getTransactionsByPaymentId(const Crypto::Hash& paymentId, std::vector<Transaction>& transactions) override;
|
||||
virtual bool getOutByMSigGIndex(uint64_t amount, uint64_t gindex, MultisignatureOutput& out) override;
|
||||
virtual std::unique_ptr<IBlock> getBlock(const Crypto::Hash& blocksId) override;
|
||||
virtual bool handleIncomingTransaction(const Transaction& tx, const Crypto::Hash& txHash, size_t blobSize, tx_verification_context& tvc, bool keptByBlock) override;
|
||||
virtual std::error_code executeLocked(const std::function<std::error_code()>& func) override;
|
||||
|
||||
virtual bool addMessageQueue(MessageQueue<BlockchainMessage>& messageQueue) override;
|
||||
virtual bool removeMessageQueue(MessageQueue<BlockchainMessage>& messageQueue) override;
|
||||
|
||||
uint32_t get_current_blockchain_height();
|
||||
bool have_block(const Crypto::Hash& id);
|
||||
std::vector<Crypto::Hash> buildSparseChain() override;
|
||||
std::vector<Crypto::Hash> buildSparseChain(const Crypto::Hash& startBlockId) override;
|
||||
void on_synchronized();
|
||||
bool is_ready() override;
|
||||
|
||||
virtual void get_blockchain_top(uint32_t& height, Crypto::Hash& top_id);
|
||||
bool get_blocks(uint32_t start_offset, uint32_t count, std::list<Block>& blocks, std::list<Transaction>& txs);
|
||||
bool get_blocks(uint32_t start_offset, uint32_t count, std::list<Block>& blocks);
|
||||
template<class t_ids_container, class t_blocks_container, class t_missed_container>
|
||||
bool get_blocks(const t_ids_container& block_ids, t_blocks_container& blocks, t_missed_container& missed_bs)
|
||||
{
|
||||
return m_blockchain.getBlocks(block_ids, blocks, missed_bs);
|
||||
}
|
||||
virtual bool queryBlocks(const std::vector<Crypto::Hash>& block_ids, uint64_t timestamp,
|
||||
uint32_t& start_height, uint32_t& current_height, uint32_t& full_offset, std::vector<BlockFullInfo>& entries) override;
|
||||
virtual bool queryBlocksLite(const std::vector<Crypto::Hash>& knownBlockIds, uint64_t timestamp,
|
||||
uint32_t& resStartHeight, uint32_t& resCurrentHeight, uint32_t& resFullOffset, std::vector<BlockShortInfo>& entries) override;
|
||||
virtual Crypto::Hash getBlockIdByHeight(uint32_t height) override;
|
||||
void getTransactions(const std::vector<Crypto::Hash>& txs_ids, std::list<Transaction>& txs, std::list<Crypto::Hash>& missed_txs, bool checkTxPool = false) override;
|
||||
virtual bool getBlockByHash(const Crypto::Hash &h, Block &blk) override;
|
||||
virtual bool getBlockHeight(const Crypto::Hash& blockId, uint32_t& blockHeight) override;
|
||||
//void get_all_known_block_ids(std::list<Crypto::Hash> &main, std::list<Crypto::Hash> &alt, std::list<Crypto::Hash> &invalid);
|
||||
|
||||
bool get_alternative_blocks(std::list<Block>& blocks);
|
||||
size_t get_alternative_blocks_count();
|
||||
|
||||
void set_cryptonote_protocol(i_cryptonote_protocol* pprotocol);
|
||||
void set_checkpoints(Checkpoints&& chk_pts);
|
||||
|
||||
std::vector<Transaction> getPoolTransactions() override;
|
||||
size_t get_pool_transactions_count();
|
||||
size_t get_blockchain_total_transactions();
|
||||
//bool get_outs(uint64_t amount, std::list<Crypto::PublicKey>& pkeys);
|
||||
virtual std::vector<Crypto::Hash> findBlockchainSupplement(const std::vector<Crypto::Hash>& remoteBlockIds, size_t maxCount,
|
||||
uint32_t& totalBlockCount, uint32_t& startBlockIndex) override;
|
||||
bool get_stat_info(core_stat_info& st_inf);
|
||||
|
||||
virtual bool get_tx_outputs_gindexs(const Crypto::Hash& tx_id, std::vector<uint32_t>& indexs);
|
||||
Crypto::Hash get_tail_id();
|
||||
virtual bool get_random_outs_for_amounts(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_response& res);
|
||||
void pause_mining();
|
||||
void update_block_template_and_resume_mining();
|
||||
//Blockchain& get_blockchain_storage(){return m_blockchain;}
|
||||
//debug functions
|
||||
void print_blockchain(uint32_t start_index, uint32_t end_index);
|
||||
void print_blockchain_index();
|
||||
std::string print_pool(bool short_format);
|
||||
void print_blockchain_outs(const std::string& file);
|
||||
virtual bool getPoolChanges(const Crypto::Hash& tailBlockId, const std::vector<Crypto::Hash>& knownTxsIds,
|
||||
std::vector<Transaction>& addedTxs, std::vector<Crypto::Hash>& deletedTxsIds) override;
|
||||
virtual bool getPoolChangesLite(const Crypto::Hash& tailBlockId, const std::vector<Crypto::Hash>& knownTxsIds,
|
||||
std::vector<TransactionPrefixInfo>& addedTxs, std::vector<Crypto::Hash>& deletedTxsIds) override;
|
||||
virtual void getPoolChanges(const std::vector<Crypto::Hash>& knownTxsIds, std::vector<Transaction>& addedTxs,
|
||||
std::vector<Crypto::Hash>& deletedTxsIds) override;
|
||||
|
||||
uint64_t getNextBlockDifficulty();
|
||||
uint64_t getTotalGeneratedAmount();
|
||||
|
||||
private:
|
||||
bool add_new_tx(const Transaction& tx, const Crypto::Hash& tx_hash, size_t blob_size, tx_verification_context& tvc, bool keeped_by_block);
|
||||
bool load_state_data();
|
||||
bool parse_tx_from_blob(Transaction& tx, Crypto::Hash& tx_hash, Crypto::Hash& tx_prefix_hash, const BinaryArray& blob);
|
||||
bool handle_incoming_block(const Block& b, block_verification_context& bvc, bool control_miner, bool relay_block);
|
||||
|
||||
bool check_tx_syntax(const Transaction& tx);
|
||||
//check correct values, amounts and all lightweight checks not related with database
|
||||
bool check_tx_semantic(const Transaction& tx, bool keeped_by_block);
|
||||
//check if tx already in memory pool or in main blockchain
|
||||
|
||||
bool is_key_image_spent(const Crypto::KeyImage& key_im);
|
||||
|
||||
bool check_tx_ring_signature(const KeyInput& tx, const Crypto::Hash& tx_prefix_hash, const std::vector<Crypto::Signature>& sig);
|
||||
bool is_tx_spendtime_unlocked(uint64_t unlock_time);
|
||||
bool update_miner_block_template();
|
||||
bool handle_command_line(const boost::program_options::variables_map& vm);
|
||||
bool on_update_blocktemplate_interval();
|
||||
bool check_tx_inputs_keyimages_diff(const Transaction& tx);
|
||||
virtual void blockchainUpdated() override;
|
||||
virtual void txDeletedFromPool() override;
|
||||
void poolUpdated();
|
||||
|
||||
bool findStartAndFullOffsets(const std::vector<Crypto::Hash>& knownBlockIds, uint64_t timestamp, uint32_t& startOffset, uint32_t& startFullOffset);
|
||||
std::vector<Crypto::Hash> findIdsForShortBlocks(uint32_t startOffset, uint32_t startFullOffset);
|
||||
|
||||
const Currency& m_currency;
|
||||
Logging::LoggerRef logger;
|
||||
CryptoNote::RealTimeProvider m_timeProvider;
|
||||
tx_memory_pool m_mempool;
|
||||
Blockchain m_blockchain;
|
||||
i_cryptonote_protocol* m_pprotocol;
|
||||
std::unique_ptr<miner> m_miner;
|
||||
std::string m_config_folder;
|
||||
cryptonote_protocol_stub m_protocol_stub;
|
||||
friend class tx_validate_inputs;
|
||||
std::atomic<bool> m_starter_message_showed;
|
||||
Tools::ObserverManager<ICoreObserver> m_observerManager;
|
||||
};
|
||||
}
|
6
src/cryptonote_core/CoreConfig.cpp → src/CryptoNoteCore/CoreConfig.cpp
Normal file → Executable file
6
src/cryptonote_core/CoreConfig.cpp → src/CryptoNoteCore/CoreConfig.cpp
Normal file → Executable file
|
@ -17,13 +17,13 @@
|
|||
|
||||
#include "CoreConfig.h"
|
||||
|
||||
#include "Common/util.h"
|
||||
#include "Common/command_line.h"
|
||||
#include "Common/Util.h"
|
||||
#include "Common/CommandLine.h"
|
||||
|
||||
namespace CryptoNote {
|
||||
|
||||
CoreConfig::CoreConfig() {
|
||||
configFolder = tools::get_default_data_dir();
|
||||
configFolder = Tools::getDefaultDataDirectory();
|
||||
}
|
||||
|
||||
void CoreConfig::init(const boost::program_options::variables_map& options) {
|
15
src/payment_service/WalletServiceErrorCodes.cpp → src/CryptoNoteCore/CryptoNoteBasic.cpp
Normal file → Executable file
15
src/payment_service/WalletServiceErrorCodes.cpp → src/CryptoNoteCore/CryptoNoteBasic.cpp
Normal file → Executable file
|
@ -15,12 +15,15 @@
|
|||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "WalletServiceErrorCodes.h"
|
||||
#include "CryptoNoteBasic.h"
|
||||
#include "crypto/crypto.h"
|
||||
|
||||
namespace PaymentService {
|
||||
namespace error {
|
||||
namespace CryptoNote {
|
||||
|
||||
WalletServiceErrorCategory WalletServiceErrorCategory::INSTANCE;
|
||||
KeyPair generateKeyPair() {
|
||||
KeyPair k;
|
||||
Crypto::generate_keys(k.publicKey, k.secretKey);
|
||||
return k;
|
||||
}
|
||||
|
||||
} //namespace error
|
||||
} //namespace PaymentService
|
||||
}
|
46
src/CryptoNoteCore/CryptoNoteBasic.h
Executable file
46
src/CryptoNoteCore/CryptoNoteBasic.h
Executable file
|
@ -0,0 +1,46 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/utility/value_init.hpp>
|
||||
#include <CryptoNote.h>
|
||||
|
||||
namespace CryptoNote {
|
||||
const Crypto::Hash NULL_HASH = boost::value_initialized<Crypto::Hash>();
|
||||
const Crypto::PublicKey NULL_PUBLIC_KEY = boost::value_initialized<Crypto::PublicKey>();
|
||||
|
||||
KeyPair generateKeyPair();
|
||||
|
||||
struct ParentBlockSerializer {
|
||||
ParentBlockSerializer(ParentBlock& parentBlock, uint64_t& timestamp, uint32_t& nonce, bool hashingSerialization, bool headerOnly) :
|
||||
m_parentBlock(parentBlock), m_timestamp(timestamp), m_nonce(nonce), m_hashingSerialization(hashingSerialization), m_headerOnly(headerOnly) {
|
||||
}
|
||||
|
||||
ParentBlock& m_parentBlock;
|
||||
uint64_t& m_timestamp;
|
||||
uint32_t& m_nonce;
|
||||
bool m_hashingSerialization;
|
||||
bool m_headerOnly;
|
||||
};
|
||||
|
||||
inline ParentBlockSerializer makeParentBlockSerializer(const Block& b, bool hashingSerialization, bool headerOnly) {
|
||||
Block& blockRef = const_cast<Block&>(b);
|
||||
return ParentBlockSerializer(blockRef.parentBlock, blockRef.timestamp, blockRef.nonce, hashingSerialization, headerOnly);
|
||||
}
|
||||
|
||||
}
|
|
@ -15,18 +15,22 @@
|
|||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "cryptonote_basic_impl.h"
|
||||
#include "serialization/binary_utils.h"
|
||||
#include "serialization/vector.h"
|
||||
#include "cryptonote_format_utils.h"
|
||||
#include "Common/base58.h"
|
||||
#include "CryptoNoteBasicImpl.h"
|
||||
#include "CryptoNoteFormatUtils.h"
|
||||
#include "CryptoNoteTools.h"
|
||||
#include "CryptoNoteSerialization.h"
|
||||
|
||||
#include "Common/Base58.h"
|
||||
#include "crypto/hash.h"
|
||||
#include "Common/int-util.h"
|
||||
|
||||
using namespace Crypto;
|
||||
using namespace Common;
|
||||
|
||||
namespace CryptoNote {
|
||||
|
||||
/************************************************************************/
|
||||
/* Cryptonote helper functions */
|
||||
/* CryptoNote helper functions */
|
||||
/************************************************************************/
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
uint64_t getPenalizedAmount(uint64_t amount, size_t medianSize, size_t currentBlockSize) {
|
||||
|
@ -58,18 +62,18 @@ namespace CryptoNote {
|
|||
}
|
||||
//-----------------------------------------------------------------------
|
||||
std::string getAccountAddressAsStr(uint64_t prefix, const AccountPublicAddress& adr) {
|
||||
blobdata blob;
|
||||
bool r = t_serializable_object_to_blob(adr, blob);
|
||||
BinaryArray ba;
|
||||
bool r = toBinaryArray(adr, ba);
|
||||
assert(r);
|
||||
return tools::base58::encode_addr(prefix, blob);
|
||||
return Tools::Base58::encode_addr(prefix, Common::asString(ba));
|
||||
}
|
||||
//-----------------------------------------------------------------------
|
||||
bool is_coinbase(const Transaction& tx) {
|
||||
if(tx.vin.size() != 1) {
|
||||
if(tx.inputs.size() != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(tx.vin[0].type() != typeid(TransactionInputGenerate)) {
|
||||
if(tx.inputs[0].type() != typeid(BaseInput)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -77,17 +81,18 @@ namespace CryptoNote {
|
|||
}
|
||||
//-----------------------------------------------------------------------
|
||||
bool parseAccountAddressString(uint64_t& prefix, AccountPublicAddress& adr, const std::string& str) {
|
||||
blobdata data;
|
||||
std::string data;
|
||||
|
||||
return
|
||||
tools::base58::decode_addr(str, prefix, data) &&
|
||||
::serialization::parse_binary(data, adr) &&
|
||||
crypto::check_key(adr.m_spendPublicKey) &&
|
||||
crypto::check_key(adr.m_viewPublicKey);
|
||||
Tools::Base58::decode_addr(str, prefix, data) &&
|
||||
fromBinaryArray(adr, asBinaryArray(data)) &&
|
||||
// ::serialization::parse_binary(data, adr) &&
|
||||
check_key(adr.spendPublicKey) &&
|
||||
check_key(adr.viewPublicKey);
|
||||
}
|
||||
//-----------------------------------------------------------------------
|
||||
bool operator ==(const CryptoNote::Transaction& a, const CryptoNote::Transaction& b) {
|
||||
return CryptoNote::get_transaction_hash(a) == CryptoNote::get_transaction_hash(b);
|
||||
return getObjectHash(a) == getObjectHash(b);
|
||||
}
|
||||
//-----------------------------------------------------------------------
|
||||
bool operator ==(const CryptoNote::Block& a, const CryptoNote::Block& b) {
|
||||
|
@ -96,10 +101,6 @@ namespace CryptoNote {
|
|||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
bool parse_hash256(const std::string& str_hash, crypto::hash& hash) {
|
||||
if (!Common::podFromHex(str_hash, hash)) {
|
||||
std::cout << "invalid hash format: <" << str_hash << '>' << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
bool parse_hash256(const std::string& str_hash, Crypto::Hash& hash) {
|
||||
return Common::podFromHex(str_hash, hash);
|
||||
}
|
24
src/cryptonote_core/cryptonote_basic_impl.h → src/CryptoNoteCore/CryptoNoteBasicImpl.h
Normal file → Executable file
24
src/cryptonote_core/cryptonote_basic_impl.h → src/CryptoNoteCore/CryptoNoteBasicImpl.h
Normal file → Executable file
|
@ -20,7 +20,7 @@
|
|||
#include "Common/StringTools.h"
|
||||
#include "crypto/crypto.h"
|
||||
#include "crypto/hash.h"
|
||||
#include "cryptonote_core/cryptonote_basic.h"
|
||||
#include "CryptoNoteCore/CryptoNoteBasic.h"
|
||||
|
||||
|
||||
namespace CryptoNote {
|
||||
|
@ -28,16 +28,16 @@ namespace CryptoNote {
|
|||
/* */
|
||||
/************************************************************************/
|
||||
template<class t_array>
|
||||
struct array_hasher: std::unary_function<t_array&, std::size_t>
|
||||
struct array_hasher: std::unary_function<t_array&, size_t>
|
||||
{
|
||||
std::size_t operator()(const t_array& val) const
|
||||
size_t operator()(const t_array& val) const
|
||||
{
|
||||
return boost::hash_range(&val.data[0], &val.data[sizeof(val.data)]);
|
||||
}
|
||||
};
|
||||
|
||||
/************************************************************************/
|
||||
/* Cryptonote helper functions */
|
||||
/* CryptoNote helper functions */
|
||||
/************************************************************************/
|
||||
uint64_t getPenalizedAmount(uint64_t amount, size_t medianSize, size_t currentBlockSize);
|
||||
std::string getAccountAddressAsStr(uint64_t prefix, const AccountPublicAddress& adr);
|
||||
|
@ -53,13 +53,13 @@ std::ostream &print256(std::ostream &o, const T &v) {
|
|||
return o << "<" << Common::podToHex(v) << ">";
|
||||
}
|
||||
|
||||
bool parse_hash256(const std::string& str_hash, crypto::hash& hash);
|
||||
bool parse_hash256(const std::string& str_hash, Crypto::Hash& hash);
|
||||
|
||||
namespace crypto {
|
||||
inline std::ostream &operator <<(std::ostream &o, const crypto::public_key &v) { return print256(o, v); }
|
||||
inline std::ostream &operator <<(std::ostream &o, const crypto::secret_key &v) { return print256(o, v); }
|
||||
inline std::ostream &operator <<(std::ostream &o, const crypto::key_derivation &v) { return print256(o, v); }
|
||||
inline std::ostream &operator <<(std::ostream &o, const crypto::key_image &v) { return print256(o, v); }
|
||||
inline std::ostream &operator <<(std::ostream &o, const crypto::signature &v) { return print256(o, v); }
|
||||
inline std::ostream &operator <<(std::ostream &o, const crypto::hash &v) { return print256(o, v); }
|
||||
namespace Crypto {
|
||||
inline std::ostream &operator <<(std::ostream &o, const Crypto::PublicKey &v) { return print256(o, v); }
|
||||
inline std::ostream &operator <<(std::ostream &o, const Crypto::SecretKey &v) { return print256(o, v); }
|
||||
inline std::ostream &operator <<(std::ostream &o, const Crypto::KeyDerivation &v) { return print256(o, v); }
|
||||
inline std::ostream &operator <<(std::ostream &o, const Crypto::KeyImage &v) { return print256(o, v); }
|
||||
inline std::ostream &operator <<(std::ostream &o, const Crypto::Signature &v) { return print256(o, v); }
|
||||
inline std::ostream &operator <<(std::ostream &o, const Crypto::Hash &v) { return print256(o, v); }
|
||||
}
|
550
src/CryptoNoteCore/CryptoNoteFormatUtils.cpp
Normal file
550
src/CryptoNoteCore/CryptoNoteFormatUtils.cpp
Normal file
|
@ -0,0 +1,550 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "CryptoNoteFormatUtils.h"
|
||||
|
||||
#include <set>
|
||||
#include <Logging/LoggerRef.h>
|
||||
#include <Common/Varint.h>
|
||||
|
||||
#include "Serialization/BinaryOutputStreamSerializer.h"
|
||||
#include "Serialization/BinaryInputStreamSerializer.h"
|
||||
|
||||
#include "Account.h"
|
||||
#include "CryptoNoteBasicImpl.h"
|
||||
#include "CryptoNoteSerialization.h"
|
||||
#include "TransactionExtra.h"
|
||||
#include "CryptoNoteTools.h"
|
||||
|
||||
#include "CryptoNoteConfig.h"
|
||||
|
||||
using namespace Logging;
|
||||
using namespace Crypto;
|
||||
using namespace Common;
|
||||
|
||||
namespace CryptoNote {
|
||||
|
||||
bool parseAndValidateTransactionFromBinaryArray(const BinaryArray& tx_blob, Transaction& tx, Hash& tx_hash, Hash& tx_prefix_hash) {
|
||||
if (!fromBinaryArray(tx, tx_blob)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//TODO: validate tx
|
||||
cn_fast_hash(tx_blob.data(), tx_blob.size(), tx_hash);
|
||||
getObjectHash(*static_cast<TransactionPrefix*>(&tx), tx_prefix_hash);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool generate_key_image_helper(const AccountKeys& ack, const PublicKey& tx_public_key, size_t real_output_index, KeyPair& in_ephemeral, KeyImage& ki) {
|
||||
KeyDerivation recv_derivation;
|
||||
bool r = generate_key_derivation(tx_public_key, ack.viewSecretKey, recv_derivation);
|
||||
|
||||
assert(r && "key image helper: failed to generate_key_derivation");
|
||||
|
||||
if (!r) {
|
||||
return false;
|
||||
}
|
||||
|
||||
r = derive_public_key(recv_derivation, real_output_index, ack.address.spendPublicKey, in_ephemeral.publicKey);
|
||||
|
||||
assert(r && "key image helper: failed to derive_public_key");
|
||||
|
||||
if (!r) {
|
||||
return false;
|
||||
}
|
||||
|
||||
derive_secret_key(recv_derivation, real_output_index, ack.spendSecretKey, in_ephemeral.secretKey);
|
||||
generate_key_image(in_ephemeral.publicKey, in_ephemeral.secretKey, ki);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t power_integral(uint64_t a, uint64_t b) {
|
||||
if (b == 0)
|
||||
return 1;
|
||||
uint64_t total = a;
|
||||
for (uint64_t i = 1; i != b; i++)
|
||||
total *= a;
|
||||
return total;
|
||||
}
|
||||
|
||||
bool get_tx_fee(const Transaction& tx, uint64_t & fee) {
|
||||
uint64_t amount_in = 0;
|
||||
uint64_t amount_out = 0;
|
||||
|
||||
for (const auto& in : tx.inputs) {
|
||||
if (in.type() == typeid(KeyInput)) {
|
||||
amount_in += boost::get<KeyInput>(in).amount;
|
||||
} else if (in.type() == typeid(MultisignatureInput)) {
|
||||
amount_in += boost::get<MultisignatureInput>(in).amount;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& o : tx.outputs) {
|
||||
amount_out += o.amount;
|
||||
}
|
||||
|
||||
if (!(amount_in >= amount_out)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
fee = amount_in - amount_out;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t get_tx_fee(const Transaction& tx) {
|
||||
uint64_t r = 0;
|
||||
if (!get_tx_fee(tx, r))
|
||||
return 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
bool constructTransaction(
|
||||
const AccountKeys& sender_account_keys,
|
||||
const std::vector<TransactionSourceEntry>& sources,
|
||||
const std::vector<TransactionDestinationEntry>& destinations,
|
||||
std::vector<uint8_t> extra,
|
||||
Transaction& tx,
|
||||
uint64_t unlock_time,
|
||||
Logging::ILogger& log) {
|
||||
LoggerRef logger(log, "construct_tx");
|
||||
|
||||
tx.inputs.clear();
|
||||
tx.outputs.clear();
|
||||
tx.signatures.clear();
|
||||
|
||||
tx.version = CURRENT_TRANSACTION_VERSION;
|
||||
tx.unlockTime = unlock_time;
|
||||
|
||||
tx.extra = extra;
|
||||
KeyPair txkey = generateKeyPair();
|
||||
addTransactionPublicKeyToExtra(tx.extra, txkey.publicKey);
|
||||
|
||||
struct input_generation_context_data {
|
||||
KeyPair in_ephemeral;
|
||||
};
|
||||
|
||||
std::vector<input_generation_context_data> in_contexts;
|
||||
uint64_t summary_inputs_money = 0;
|
||||
//fill inputs
|
||||
for (const TransactionSourceEntry& src_entr : sources) {
|
||||
if (src_entr.realOutput >= src_entr.outputs.size()) {
|
||||
logger(ERROR) << "real_output index (" << src_entr.realOutput << ")bigger than output_keys.size()=" << src_entr.outputs.size();
|
||||
return false;
|
||||
}
|
||||
summary_inputs_money += src_entr.amount;
|
||||
|
||||
//KeyDerivation recv_derivation;
|
||||
in_contexts.push_back(input_generation_context_data());
|
||||
KeyPair& in_ephemeral = in_contexts.back().in_ephemeral;
|
||||
KeyImage img;
|
||||
if (!generate_key_image_helper(sender_account_keys, src_entr.realTransactionPublicKey, src_entr.realOutputIndexInTransaction, in_ephemeral, img))
|
||||
return false;
|
||||
|
||||
//check that derived key is equal with real output key
|
||||
if (!(in_ephemeral.publicKey == src_entr.outputs[src_entr.realOutput].second)) {
|
||||
logger(ERROR) << "derived public key mismatch with output public key! " << ENDL << "derived_key:"
|
||||
<< Common::podToHex(in_ephemeral.publicKey) << ENDL << "real output_public_key:"
|
||||
<< Common::podToHex(src_entr.outputs[src_entr.realOutput].second);
|
||||
return false;
|
||||
}
|
||||
|
||||
//put key image into tx input
|
||||
KeyInput input_to_key;
|
||||
input_to_key.amount = src_entr.amount;
|
||||
input_to_key.keyImage = img;
|
||||
|
||||
//fill outputs array and use relative offsets
|
||||
for (const TransactionSourceEntry::OutputEntry& out_entry : src_entr.outputs) {
|
||||
input_to_key.outputIndexes.push_back(out_entry.first);
|
||||
}
|
||||
|
||||
input_to_key.outputIndexes = absolute_output_offsets_to_relative(input_to_key.outputIndexes);
|
||||
tx.inputs.push_back(input_to_key);
|
||||
}
|
||||
|
||||
// "Shuffle" outs
|
||||
std::vector<TransactionDestinationEntry> shuffled_dsts(destinations);
|
||||
std::sort(shuffled_dsts.begin(), shuffled_dsts.end(), [](const TransactionDestinationEntry& de1, const TransactionDestinationEntry& de2) { return de1.amount < de2.amount; });
|
||||
|
||||
uint64_t summary_outs_money = 0;
|
||||
//fill outputs
|
||||
size_t output_index = 0;
|
||||
for (const TransactionDestinationEntry& dst_entr : shuffled_dsts) {
|
||||
if (!(dst_entr.amount > 0)) {
|
||||
logger(ERROR, BRIGHT_RED) << "Destination with wrong amount: " << dst_entr.amount;
|
||||
return false;
|
||||
}
|
||||
KeyDerivation derivation;
|
||||
PublicKey out_eph_public_key;
|
||||
bool r = generate_key_derivation(dst_entr.addr.viewPublicKey, txkey.secretKey, derivation);
|
||||
|
||||
if (!(r)) {
|
||||
logger(ERROR, BRIGHT_RED)
|
||||
<< "at creation outs: failed to generate_key_derivation("
|
||||
<< dst_entr.addr.viewPublicKey << ", " << txkey.secretKey << ")";
|
||||
return false;
|
||||
}
|
||||
|
||||
r = derive_public_key(derivation, output_index,
|
||||
dst_entr.addr.spendPublicKey,
|
||||
out_eph_public_key);
|
||||
if (!(r)) {
|
||||
logger(ERROR, BRIGHT_RED)
|
||||
<< "at creation outs: failed to derive_public_key(" << derivation
|
||||
<< ", " << output_index << ", " << dst_entr.addr.spendPublicKey
|
||||
<< ")";
|
||||
return false;
|
||||
}
|
||||
|
||||
TransactionOutput out;
|
||||
out.amount = dst_entr.amount;
|
||||
KeyOutput tk;
|
||||
tk.key = out_eph_public_key;
|
||||
out.target = tk;
|
||||
tx.outputs.push_back(out);
|
||||
output_index++;
|
||||
summary_outs_money += dst_entr.amount;
|
||||
}
|
||||
|
||||
//check money
|
||||
if (summary_outs_money > summary_inputs_money) {
|
||||
logger(ERROR) << "Transaction inputs money (" << summary_inputs_money << ") less than outputs money (" << summary_outs_money << ")";
|
||||
return false;
|
||||
}
|
||||
|
||||
//generate ring signatures
|
||||
Hash tx_prefix_hash;
|
||||
getObjectHash(*static_cast<TransactionPrefix*>(&tx), tx_prefix_hash);
|
||||
|
||||
size_t i = 0;
|
||||
for (const TransactionSourceEntry& src_entr : sources) {
|
||||
std::vector<const PublicKey*> keys_ptrs;
|
||||
for (const TransactionSourceEntry::OutputEntry& o : src_entr.outputs) {
|
||||
keys_ptrs.push_back(&o.second);
|
||||
}
|
||||
|
||||
tx.signatures.push_back(std::vector<Signature>());
|
||||
std::vector<Signature>& sigs = tx.signatures.back();
|
||||
sigs.resize(src_entr.outputs.size());
|
||||
generate_ring_signature(tx_prefix_hash, boost::get<KeyInput>(tx.inputs[i]).keyImage, keys_ptrs,
|
||||
in_contexts[i].in_ephemeral.secretKey, src_entr.realOutput, sigs.data());
|
||||
i++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool get_inputs_money_amount(const Transaction& tx, uint64_t& money) {
|
||||
money = 0;
|
||||
|
||||
for (const auto& in : tx.inputs) {
|
||||
uint64_t amount = 0;
|
||||
|
||||
if (in.type() == typeid(KeyInput)) {
|
||||
amount = boost::get<KeyInput>(in).amount;
|
||||
} else if (in.type() == typeid(MultisignatureInput)) {
|
||||
amount = boost::get<MultisignatureInput>(in).amount;
|
||||
}
|
||||
|
||||
money += amount;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t get_block_height(const Block& b) {
|
||||
if (b.baseTransaction.inputs.size() != 1) {
|
||||
return 0;
|
||||
}
|
||||
const auto& in = b.baseTransaction.inputs[0];
|
||||
if (in.type() != typeid(BaseInput)) {
|
||||
return 0;
|
||||
}
|
||||
return boost::get<BaseInput>(in).blockIndex;
|
||||
}
|
||||
|
||||
bool check_inputs_types_supported(const TransactionPrefix& tx) {
|
||||
for (const auto& in : tx.inputs) {
|
||||
if (in.type() != typeid(KeyInput) && in.type() != typeid(MultisignatureInput)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool check_outs_valid(const TransactionPrefix& tx, std::string* error) {
|
||||
for (const TransactionOutput& out : tx.outputs) {
|
||||
if (out.target.type() == typeid(KeyOutput)) {
|
||||
if (out.amount == 0) {
|
||||
if (error) {
|
||||
*error = "Zero amount ouput";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!check_key(boost::get<KeyOutput>(out.target).key)) {
|
||||
if (error) {
|
||||
*error = "Output with invalid key";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} else if (out.target.type() == typeid(MultisignatureOutput)) {
|
||||
const MultisignatureOutput& multisignatureOutput = ::boost::get<MultisignatureOutput>(out.target);
|
||||
if (multisignatureOutput.requiredSignatureCount > multisignatureOutput.keys.size()) {
|
||||
if (error) {
|
||||
*error = "Multisignature output with invalid required signature count";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
for (const PublicKey& key : multisignatureOutput.keys) {
|
||||
if (!check_key(key)) {
|
||||
if (error) {
|
||||
*error = "Multisignature output with invalid public key";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (error) {
|
||||
*error = "Output with invalid type";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool checkMultisignatureInputsDiff(const TransactionPrefix& tx) {
|
||||
std::set<std::pair<uint64_t, uint32_t>> inputsUsage;
|
||||
for (const auto& inv : tx.inputs) {
|
||||
if (inv.type() == typeid(MultisignatureInput)) {
|
||||
const MultisignatureInput& in = ::boost::get<MultisignatureInput>(inv);
|
||||
if (!inputsUsage.insert(std::make_pair(in.amount, in.outputIndex)).second) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool check_money_overflow(const TransactionPrefix &tx) {
|
||||
return check_inputs_overflow(tx) && check_outs_overflow(tx);
|
||||
}
|
||||
|
||||
bool check_inputs_overflow(const TransactionPrefix &tx) {
|
||||
uint64_t money = 0;
|
||||
|
||||
for (const auto &in : tx.inputs) {
|
||||
uint64_t amount = 0;
|
||||
|
||||
if (in.type() == typeid(KeyInput)) {
|
||||
amount = boost::get<KeyInput>(in).amount;
|
||||
} else if (in.type() == typeid(MultisignatureInput)) {
|
||||
amount = boost::get<MultisignatureInput>(in).amount;
|
||||
}
|
||||
|
||||
if (money > amount + money)
|
||||
return false;
|
||||
|
||||
money += amount;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool check_outs_overflow(const TransactionPrefix& tx) {
|
||||
uint64_t money = 0;
|
||||
for (const auto& o : tx.outputs) {
|
||||
if (money > o.amount + money)
|
||||
return false;
|
||||
money += o.amount;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t get_outs_money_amount(const Transaction& tx) {
|
||||
uint64_t outputs_amount = 0;
|
||||
for (const auto& o : tx.outputs) {
|
||||
outputs_amount += o.amount;
|
||||
}
|
||||
return outputs_amount;
|
||||
}
|
||||
|
||||
std::string short_hash_str(const Hash& h) {
|
||||
std::string res = Common::podToHex(h);
|
||||
|
||||
if (res.size() == 64) {
|
||||
auto erased_pos = res.erase(8, 48);
|
||||
res.insert(8, "....");
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool is_out_to_acc(const AccountKeys& acc, const KeyOutput& out_key, const KeyDerivation& derivation, size_t keyIndex) {
|
||||
PublicKey pk;
|
||||
derive_public_key(derivation, keyIndex, acc.address.spendPublicKey, pk);
|
||||
return pk == out_key.key;
|
||||
}
|
||||
|
||||
bool is_out_to_acc(const AccountKeys& acc, const KeyOutput& out_key, const PublicKey& tx_pub_key, size_t keyIndex) {
|
||||
KeyDerivation derivation;
|
||||
generate_key_derivation(tx_pub_key, acc.viewSecretKey, derivation);
|
||||
return is_out_to_acc(acc, out_key, derivation, keyIndex);
|
||||
}
|
||||
|
||||
bool lookup_acc_outs(const AccountKeys& acc, const Transaction& tx, std::vector<size_t>& outs, uint64_t& money_transfered) {
|
||||
PublicKey transactionPublicKey = getTransactionPublicKeyFromExtra(tx.extra);
|
||||
if (transactionPublicKey == NULL_PUBLIC_KEY)
|
||||
return false;
|
||||
return lookup_acc_outs(acc, tx, transactionPublicKey, outs, money_transfered);
|
||||
}
|
||||
|
||||
bool lookup_acc_outs(const AccountKeys& acc, const Transaction& tx, const PublicKey& tx_pub_key, std::vector<size_t>& outs, uint64_t& money_transfered) {
|
||||
money_transfered = 0;
|
||||
size_t keyIndex = 0;
|
||||
size_t outputIndex = 0;
|
||||
|
||||
KeyDerivation derivation;
|
||||
generate_key_derivation(tx_pub_key, acc.viewSecretKey, derivation);
|
||||
|
||||
for (const TransactionOutput& o : tx.outputs) {
|
||||
assert(o.target.type() == typeid(KeyOutput) || o.target.type() == typeid(MultisignatureOutput));
|
||||
if (o.target.type() == typeid(KeyOutput)) {
|
||||
if (is_out_to_acc(acc, boost::get<KeyOutput>(o.target), derivation, keyIndex)) {
|
||||
outs.push_back(outputIndex);
|
||||
money_transfered += o.amount;
|
||||
}
|
||||
|
||||
++keyIndex;
|
||||
} else if (o.target.type() == typeid(MultisignatureOutput)) {
|
||||
keyIndex += boost::get<MultisignatureOutput>(o.target).keys.size();
|
||||
}
|
||||
|
||||
++outputIndex;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool get_block_hashing_blob(const Block& b, BinaryArray& ba) {
|
||||
if (!toBinaryArray(static_cast<const BlockHeader&>(b), ba)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Hash treeRootHash = get_tx_tree_hash(b);
|
||||
ba.insert(ba.end(), treeRootHash.data, treeRootHash.data + 32);
|
||||
auto transactionCount = asBinaryArray(Tools::get_varint_data(b.transactionHashes.size() + 1));
|
||||
ba.insert(ba.end(), transactionCount.begin(), transactionCount.end());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool get_parent_block_hashing_blob(const Block& b, BinaryArray& blob) {
|
||||
auto serializer = makeParentBlockSerializer(b, true, true);
|
||||
return toBinaryArray(serializer, blob);
|
||||
}
|
||||
|
||||
bool get_block_hash(const Block& b, Hash& res) {
|
||||
BinaryArray ba;
|
||||
if (!get_block_hashing_blob(b, ba)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (BLOCK_MAJOR_VERSION_2 <= b.majorVersion) {
|
||||
BinaryArray parent_blob;
|
||||
auto serializer = makeParentBlockSerializer(b, true, false);
|
||||
if (!toBinaryArray(serializer, parent_blob))
|
||||
return false;
|
||||
|
||||
ba.insert(ba.end(), parent_blob.begin(), parent_blob.end());
|
||||
}
|
||||
|
||||
return getObjectHash(ba, res);
|
||||
}
|
||||
|
||||
Hash get_block_hash(const Block& b) {
|
||||
Hash p = NULL_HASH;
|
||||
get_block_hash(b, p);
|
||||
return p;
|
||||
}
|
||||
|
||||
bool get_aux_block_header_hash(const Block& b, Hash& res) {
|
||||
BinaryArray blob;
|
||||
if (!get_block_hashing_blob(b, blob)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return getObjectHash(blob, res);
|
||||
}
|
||||
|
||||
bool get_block_longhash(cn_context &context, const Block& b, Hash& res) {
|
||||
BinaryArray bd;
|
||||
if (b.majorVersion == BLOCK_MAJOR_VERSION_1) {
|
||||
if (!get_block_hashing_blob(b, bd)) {
|
||||
return false;
|
||||
}
|
||||
} else if (b.majorVersion == BLOCK_MAJOR_VERSION_2) {
|
||||
if (!get_parent_block_hashing_blob(b, bd)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
cn_slow_hash(context, bd.data(), bd.size(), res);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<uint32_t> relative_output_offsets_to_absolute(const std::vector<uint32_t>& off) {
|
||||
std::vector<uint32_t> res = off;
|
||||
for (size_t i = 1; i < res.size(); i++)
|
||||
res[i] += res[i - 1];
|
||||
return res;
|
||||
}
|
||||
|
||||
std::vector<uint32_t> absolute_output_offsets_to_relative(const std::vector<uint32_t>& off) {
|
||||
std::vector<uint32_t> res = off;
|
||||
if (!off.size())
|
||||
return res;
|
||||
std::sort(res.begin(), res.end());//just to be sure, actually it is already should be sorted
|
||||
for (size_t i = res.size() - 1; i != 0; i--)
|
||||
res[i] -= res[i - 1];
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void get_tx_tree_hash(const std::vector<Hash>& tx_hashes, Hash& h) {
|
||||
tree_hash(tx_hashes.data(), tx_hashes.size(), h);
|
||||
}
|
||||
|
||||
Hash get_tx_tree_hash(const std::vector<Hash>& tx_hashes) {
|
||||
Hash h = NULL_HASH;
|
||||
get_tx_tree_hash(tx_hashes, h);
|
||||
return h;
|
||||
}
|
||||
|
||||
Hash get_tx_tree_hash(const Block& b) {
|
||||
std::vector<Hash> txs_ids;
|
||||
Hash h = NULL_HASH;
|
||||
getObjectHash(b.baseTransaction, h);
|
||||
txs_ids.push_back(h);
|
||||
for (auto& th : b.transactionHashes) {
|
||||
txs_ids.push_back(th);
|
||||
}
|
||||
return get_tx_tree_hash(txs_ids);
|
||||
}
|
||||
|
||||
}
|
128
src/CryptoNoteCore/CryptoNoteFormatUtils.h
Executable file
128
src/CryptoNoteCore/CryptoNoteFormatUtils.h
Executable file
|
@ -0,0 +1,128 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/utility/value_init.hpp>
|
||||
|
||||
#include "CryptoNoteBasic.h"
|
||||
#include "CryptoNoteSerialization.h"
|
||||
|
||||
#include "Serialization/BinaryOutputStreamSerializer.h"
|
||||
#include "Serialization/BinaryInputStreamSerializer.h"
|
||||
|
||||
namespace Logging {
|
||||
class ILogger;
|
||||
}
|
||||
|
||||
namespace CryptoNote {
|
||||
|
||||
bool parseAndValidateTransactionFromBinaryArray(const BinaryArray& transactionBinaryArray, Transaction& transaction, Crypto::Hash& transactionHash, Crypto::Hash& transactionPrefixHash);
|
||||
|
||||
struct TransactionSourceEntry {
|
||||
typedef std::pair<uint32_t, Crypto::PublicKey> OutputEntry;
|
||||
|
||||
std::vector<OutputEntry> outputs; //index + key
|
||||
size_t realOutput; //index in outputs vector of real output_entry
|
||||
Crypto::PublicKey realTransactionPublicKey; //incoming real tx public key
|
||||
size_t realOutputIndexInTransaction; //index in transaction outputs vector
|
||||
uint64_t amount; //money
|
||||
};
|
||||
|
||||
struct TransactionDestinationEntry {
|
||||
uint64_t amount; //money
|
||||
AccountPublicAddress addr; //destination address
|
||||
|
||||
TransactionDestinationEntry() : amount(0), addr(boost::value_initialized<AccountPublicAddress>()) {}
|
||||
TransactionDestinationEntry(uint64_t amount, const AccountPublicAddress &addr) : amount(amount), addr(addr) {}
|
||||
};
|
||||
|
||||
|
||||
bool constructTransaction(
|
||||
const AccountKeys& senderAccountKeys,
|
||||
const std::vector<TransactionSourceEntry>& sources,
|
||||
const std::vector<TransactionDestinationEntry>& destinations,
|
||||
std::vector<uint8_t> extra, Transaction& transaction, uint64_t unlock_time, Logging::ILogger& log);
|
||||
|
||||
|
||||
bool is_out_to_acc(const AccountKeys& acc, const KeyOutput& out_key, const Crypto::PublicKey& tx_pub_key, size_t keyIndex);
|
||||
bool is_out_to_acc(const AccountKeys& acc, const KeyOutput& out_key, const Crypto::KeyDerivation& derivation, size_t keyIndex);
|
||||
bool lookup_acc_outs(const AccountKeys& acc, const Transaction& tx, const Crypto::PublicKey& tx_pub_key, std::vector<size_t>& outs, uint64_t& money_transfered);
|
||||
bool lookup_acc_outs(const AccountKeys& acc, const Transaction& tx, std::vector<size_t>& outs, uint64_t& money_transfered);
|
||||
bool get_tx_fee(const Transaction& tx, uint64_t & fee);
|
||||
uint64_t get_tx_fee(const Transaction& tx);
|
||||
bool generate_key_image_helper(const AccountKeys& ack, const Crypto::PublicKey& tx_public_key, size_t real_output_index, KeyPair& in_ephemeral, Crypto::KeyImage& ki);
|
||||
std::string short_hash_str(const Crypto::Hash& h);
|
||||
|
||||
bool get_block_hashing_blob(const Block& b, BinaryArray& blob);
|
||||
bool get_parent_block_hashing_blob(const Block& b, BinaryArray& blob);
|
||||
bool get_aux_block_header_hash(const Block& b, Crypto::Hash& res);
|
||||
bool get_block_hash(const Block& b, Crypto::Hash& res);
|
||||
Crypto::Hash get_block_hash(const Block& b);
|
||||
bool get_block_longhash(Crypto::cn_context &context, const Block& b, Crypto::Hash& res);
|
||||
bool get_inputs_money_amount(const Transaction& tx, uint64_t& money);
|
||||
uint64_t get_outs_money_amount(const Transaction& tx);
|
||||
bool check_inputs_types_supported(const TransactionPrefix& tx);
|
||||
bool check_outs_valid(const TransactionPrefix& tx, std::string* error = 0);
|
||||
bool checkMultisignatureInputsDiff(const TransactionPrefix& tx);
|
||||
|
||||
bool check_money_overflow(const TransactionPrefix& tx);
|
||||
bool check_outs_overflow(const TransactionPrefix& tx);
|
||||
bool check_inputs_overflow(const TransactionPrefix& tx);
|
||||
uint32_t get_block_height(const Block& b);
|
||||
std::vector<uint32_t> relative_output_offsets_to_absolute(const std::vector<uint32_t>& off);
|
||||
std::vector<uint32_t> absolute_output_offsets_to_relative(const std::vector<uint32_t>& off);
|
||||
|
||||
|
||||
// 62387455827 -> 455827 + 7000000 + 80000000 + 300000000 + 2000000000 + 60000000000, where 455827 <= dust_threshold
|
||||
template<typename chunk_handler_t, typename dust_handler_t>
|
||||
void decompose_amount_into_digits(uint64_t amount, uint64_t dust_threshold, const chunk_handler_t& chunk_handler, const dust_handler_t& dust_handler) {
|
||||
if (0 == amount) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool is_dust_handled = false;
|
||||
uint64_t dust = 0;
|
||||
uint64_t order = 1;
|
||||
while (0 != amount) {
|
||||
uint64_t chunk = (amount % 10) * order;
|
||||
amount /= 10;
|
||||
order *= 10;
|
||||
|
||||
if (dust + chunk <= dust_threshold) {
|
||||
dust += chunk;
|
||||
} else {
|
||||
if (!is_dust_handled && 0 != dust) {
|
||||
dust_handler(dust);
|
||||
is_dust_handled = true;
|
||||
}
|
||||
if (0 != chunk) {
|
||||
chunk_handler(chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_dust_handled && 0 != dust) {
|
||||
dust_handler(dust);
|
||||
}
|
||||
}
|
||||
|
||||
void get_tx_tree_hash(const std::vector<Crypto::Hash>& tx_hashes, Crypto::Hash& h);
|
||||
Crypto::Hash get_tx_tree_hash(const std::vector<Crypto::Hash>& tx_hashes);
|
||||
Crypto::Hash get_tx_tree_hash(const Block& b);
|
||||
|
||||
}
|
|
@ -15,34 +15,52 @@
|
|||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "cryptonote_serialization.h"
|
||||
#include "account.h"
|
||||
#include "CryptoNoteSerialization.h"
|
||||
|
||||
#include "serialization/ISerializer.h"
|
||||
#include "serialization/SerializationOverloads.h"
|
||||
#include "serialization/BinaryInputStreamSerializer.h"
|
||||
#include "serialization/BinaryOutputStreamSerializer.h"
|
||||
#include "crypto/crypto.h"
|
||||
#include "cryptonote_config.h"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
|
||||
#include "Serialization/ISerializer.h"
|
||||
#include "Serialization/SerializationOverloads.h"
|
||||
#include "Serialization/BinaryInputStreamSerializer.h"
|
||||
#include "Serialization/BinaryOutputStreamSerializer.h"
|
||||
|
||||
#include "Common/StringOutputStream.h"
|
||||
#include "crypto/crypto.h"
|
||||
|
||||
#include "Account.h"
|
||||
#include "CryptoNoteConfig.h"
|
||||
#include "CryptoNoteFormatUtils.h"
|
||||
#include "CryptoNoteTools.h"
|
||||
#include "TransactionExtra.h"
|
||||
|
||||
using namespace Common;
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace CryptoNote;
|
||||
using namespace Common;
|
||||
|
||||
size_t getSignaturesCount(const TransactionInput& input) {
|
||||
struct txin_signature_size_visitor : public boost::static_visitor < size_t > {
|
||||
size_t operator()(const BaseInput& txin) const { return 0; }
|
||||
size_t operator()(const KeyInput& txin) const { return txin.outputIndexes.size(); }
|
||||
size_t operator()(const MultisignatureInput& txin) const { return txin.signatureCount; }
|
||||
};
|
||||
|
||||
return boost::apply_visitor(txin_signature_size_visitor(), input);
|
||||
}
|
||||
|
||||
struct BinaryVariantTagGetter: boost::static_visitor<uint8_t> {
|
||||
uint8_t operator()(const CryptoNote::TransactionInputGenerate) { return 0xff; }
|
||||
uint8_t operator()(const CryptoNote::TransactionInputToScript) { return 0x0; }
|
||||
uint8_t operator()(const CryptoNote::TransactionInputToScriptHash) { return 0x1; }
|
||||
uint8_t operator()(const CryptoNote::TransactionInputToKey) { return 0x2; }
|
||||
uint8_t operator()(const CryptoNote::TransactionInputMultisignature) { return 0x3; }
|
||||
uint8_t operator()(const CryptoNote::TransactionOutputToScript) { return 0x0; }
|
||||
uint8_t operator()(const CryptoNote::TransactionOutputToScriptHash) { return 0x1; }
|
||||
uint8_t operator()(const CryptoNote::TransactionOutputToKey) { return 0x2; }
|
||||
uint8_t operator()(const CryptoNote::TransactionOutputMultisignature) { return 0x3; }
|
||||
uint8_t operator()(const CryptoNote::BaseInput) { return 0xff; }
|
||||
uint8_t operator()(const CryptoNote::KeyInput) { return 0x2; }
|
||||
uint8_t operator()(const CryptoNote::MultisignatureInput) { return 0x3; }
|
||||
uint8_t operator()(const CryptoNote::KeyOutput) { return 0x2; }
|
||||
uint8_t operator()(const CryptoNote::MultisignatureOutput) { return 0x3; }
|
||||
uint8_t operator()(const CryptoNote::Transaction) { return 0xcc; }
|
||||
uint8_t operator()(const CryptoNote::Block) { return 0xbb; }
|
||||
};
|
||||
|
@ -50,49 +68,30 @@ struct BinaryVariantTagGetter: boost::static_visitor<uint8_t> {
|
|||
struct VariantSerializer : boost::static_visitor<> {
|
||||
VariantSerializer(CryptoNote::ISerializer& serializer, const std::string& name) : s(serializer), name(name) {}
|
||||
|
||||
void operator() (CryptoNote::TransactionInputGenerate& param) { s(param, name); }
|
||||
void operator() (CryptoNote::TransactionInputToScript& param) { s(param, name); }
|
||||
void operator() (CryptoNote::TransactionInputToScriptHash& param) { s(param, name); }
|
||||
void operator() (CryptoNote::TransactionInputToKey& param) { s(param, name); }
|
||||
void operator() (CryptoNote::TransactionInputMultisignature& param) { s(param, name); }
|
||||
void operator() (CryptoNote::TransactionOutputToScript& param) { s(param, name); }
|
||||
void operator() (CryptoNote::TransactionOutputToScriptHash& param) { s(param, name); }
|
||||
void operator() (CryptoNote::TransactionOutputToKey& param) { s(param, name); }
|
||||
void operator() (CryptoNote::TransactionOutputMultisignature& param) { s(param, name); }
|
||||
template <typename T>
|
||||
void operator() (T& param) { s(param, name); }
|
||||
|
||||
CryptoNote::ISerializer& s;
|
||||
const std::string& name;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
void getVariantValue(CryptoNote::ISerializer& serializer, uint8_t tag, CryptoNote::TransactionInput& in) {
|
||||
switch(tag) {
|
||||
case 0xff: {
|
||||
CryptoNote::TransactionInputGenerate v;
|
||||
serializer(v, "data");
|
||||
in = v;
|
||||
break;
|
||||
}
|
||||
case 0x0: {
|
||||
CryptoNote::TransactionInputToScript v;
|
||||
serializer(v, "data");
|
||||
in = v;
|
||||
break;
|
||||
}
|
||||
case 0x1: {
|
||||
CryptoNote::TransactionInputToScriptHash v;
|
||||
serializer(v, "data");
|
||||
CryptoNote::BaseInput v;
|
||||
serializer(v, "value");
|
||||
in = v;
|
||||
break;
|
||||
}
|
||||
case 0x2: {
|
||||
CryptoNote::TransactionInputToKey v;
|
||||
serializer(v, "data");
|
||||
CryptoNote::KeyInput v;
|
||||
serializer(v, "value");
|
||||
in = v;
|
||||
break;
|
||||
}
|
||||
case 0x3: {
|
||||
CryptoNote::TransactionInputMultisignature v;
|
||||
serializer(v, "data");
|
||||
CryptoNote::MultisignatureInput v;
|
||||
serializer(v, "value");
|
||||
in = v;
|
||||
break;
|
||||
}
|
||||
|
@ -103,26 +102,14 @@ void getVariantValue(CryptoNote::ISerializer& serializer, uint8_t tag, CryptoNot
|
|||
|
||||
void getVariantValue(CryptoNote::ISerializer& serializer, uint8_t tag, CryptoNote::TransactionOutputTarget& out) {
|
||||
switch(tag) {
|
||||
case 0x0: {
|
||||
CryptoNote::TransactionOutputToScript v;
|
||||
serializer(v, "data");
|
||||
out = v;
|
||||
break;
|
||||
}
|
||||
case 0x1: {
|
||||
CryptoNote::TransactionOutputToScriptHash v;
|
||||
serializer(v, "data");
|
||||
out = v;
|
||||
break;
|
||||
}
|
||||
case 0x2: {
|
||||
CryptoNote::TransactionOutputToKey v;
|
||||
CryptoNote::KeyOutput v;
|
||||
serializer(v, "data");
|
||||
out = v;
|
||||
break;
|
||||
}
|
||||
case 0x3: {
|
||||
CryptoNote::TransactionOutputMultisignature v;
|
||||
CryptoNote::MultisignatureOutput v;
|
||||
serializer(v, "data");
|
||||
out = v;
|
||||
break;
|
||||
|
@ -137,8 +124,8 @@ bool serializePod(T& v, Common::StringView name, CryptoNote::ISerializer& serial
|
|||
return serializer.binary(&v, sizeof(v), name);
|
||||
}
|
||||
|
||||
bool serializeVarintVector(std::vector<uint64_t>& vector, CryptoNote::ISerializer& serializer, Common::StringView name) {
|
||||
std::size_t size = vector.size();
|
||||
bool serializeVarintVector(std::vector<uint32_t>& vector, CryptoNote::ISerializer& serializer, Common::StringView name) {
|
||||
size_t size = vector.size();
|
||||
|
||||
if (!serializer.beginArray(size, name)) {
|
||||
vector.clear();
|
||||
|
@ -157,21 +144,21 @@ bool serializeVarintVector(std::vector<uint64_t>& vector, CryptoNote::ISerialize
|
|||
|
||||
}
|
||||
|
||||
namespace crypto {
|
||||
namespace Crypto {
|
||||
|
||||
bool serialize(public_key& pubKey, Common::StringView name, CryptoNote::ISerializer& serializer) {
|
||||
bool serialize(PublicKey& pubKey, Common::StringView name, CryptoNote::ISerializer& serializer) {
|
||||
return serializePod(pubKey, name, serializer);
|
||||
}
|
||||
|
||||
bool serialize(secret_key& secKey, Common::StringView name, CryptoNote::ISerializer& serializer) {
|
||||
bool serialize(SecretKey& secKey, Common::StringView name, CryptoNote::ISerializer& serializer) {
|
||||
return serializePod(secKey, name, serializer);
|
||||
}
|
||||
|
||||
bool serialize(hash& h, Common::StringView name, CryptoNote::ISerializer& serializer) {
|
||||
bool serialize(Hash& h, Common::StringView name, CryptoNote::ISerializer& serializer) {
|
||||
return serializePod(h, name, serializer);
|
||||
}
|
||||
|
||||
bool serialize(key_image& keyImage, Common::StringView name, CryptoNote::ISerializer& serializer) {
|
||||
bool serialize(KeyImage& keyImage, Common::StringView name, CryptoNote::ISerializer& serializer) {
|
||||
return serializePod(keyImage, name, serializer);
|
||||
}
|
||||
|
||||
|
@ -179,10 +166,17 @@ bool serialize(chacha8_iv& chacha, Common::StringView name, CryptoNote::ISeriali
|
|||
return serializePod(chacha, name, serializer);
|
||||
}
|
||||
|
||||
bool serialize(signature& sig, Common::StringView name, CryptoNote::ISerializer& serializer) {
|
||||
bool serialize(Signature& sig, Common::StringView name, CryptoNote::ISerializer& serializer) {
|
||||
return serializePod(sig, name, serializer);
|
||||
}
|
||||
|
||||
bool serialize(EllipticCurveScalar& ecScalar, Common::StringView name, CryptoNote::ISerializer& serializer) {
|
||||
return serializePod(ecScalar, name, serializer);
|
||||
}
|
||||
|
||||
bool serialize(EllipticCurvePoint& ecPoint, Common::StringView name, CryptoNote::ISerializer& serializer) {
|
||||
return serializePod(ecPoint, name, serializer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -190,31 +184,35 @@ namespace CryptoNote {
|
|||
|
||||
void serialize(TransactionPrefix& txP, ISerializer& serializer) {
|
||||
serializer(txP.version, "version");
|
||||
|
||||
if (CURRENT_TRANSACTION_VERSION < txP.version) {
|
||||
throw std::runtime_error("Wrong transaction version");
|
||||
}
|
||||
|
||||
serializer(txP.unlockTime, "unlock_time");
|
||||
serializer(txP.vin, "vin");
|
||||
serializer(txP.vout, "vout");
|
||||
serializer(txP.inputs, "vin");
|
||||
serializer(txP.outputs, "vout");
|
||||
serializeAsBinary(txP.extra, "extra", serializer);
|
||||
}
|
||||
|
||||
void serialize(Transaction& tx, ISerializer& serializer) {
|
||||
serializer(tx.version, "version");
|
||||
serializer(tx.unlockTime, "unlock_time");
|
||||
serializer(tx.vin, "vin");
|
||||
serializer(tx.vout, "vout");
|
||||
serializeAsBinary(tx.extra, "extra", serializer);
|
||||
serialize(static_cast<TransactionPrefix&>(tx), serializer);
|
||||
|
||||
std::size_t sigSize = tx.vin.size();
|
||||
size_t sigSize = tx.inputs.size();
|
||||
//TODO: make arrays without sizes
|
||||
// serializer.beginArray(sigSize, "signatures");
|
||||
tx.signatures.resize(sigSize);
|
||||
|
||||
if (serializer.type() == ISerializer::INPUT) {
|
||||
tx.signatures.resize(sigSize);
|
||||
}
|
||||
|
||||
bool signaturesNotExpected = tx.signatures.empty();
|
||||
if (!signaturesNotExpected && tx.vin.size() != tx.signatures.size()) {
|
||||
if (!signaturesNotExpected && tx.inputs.size() != tx.signatures.size()) {
|
||||
throw std::runtime_error("Serialization error: unexpected signatures size");
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < tx.vin.size(); ++i) {
|
||||
size_t signatureSize = Transaction::getSignatureSize(tx.vin[i]);
|
||||
for (size_t i = 0; i < tx.inputs.size(); ++i) {
|
||||
size_t signatureSize = getSignaturesCount(tx.inputs[i]);
|
||||
if (signaturesNotExpected) {
|
||||
if (signatureSize == 0) {
|
||||
continue;
|
||||
|
@ -227,12 +225,18 @@ void serialize(Transaction& tx, ISerializer& serializer) {
|
|||
if (signatureSize != tx.signatures[i].size()) {
|
||||
throw std::runtime_error("Serialization error: unexpected signatures size");
|
||||
}
|
||||
} else {
|
||||
tx.signatures[i].resize(signatureSize);
|
||||
}
|
||||
|
||||
for (crypto::signature& sig: tx.signatures[i]) {
|
||||
serializePod(sig, "", serializer);
|
||||
for (Crypto::Signature& sig : tx.signatures[i]) {
|
||||
serializePod(sig, "", serializer);
|
||||
}
|
||||
|
||||
} else {
|
||||
std::vector<Crypto::Signature> signatures(signatureSize);
|
||||
for (Crypto::Signature& sig : signatures) {
|
||||
serializePod(sig, "", serializer);
|
||||
}
|
||||
|
||||
tx.signatures[i] = std::move(signatures);
|
||||
}
|
||||
}
|
||||
// serializer.endArray();
|
||||
|
@ -254,22 +258,19 @@ void serialize(TransactionInput& in, ISerializer& serializer) {
|
|||
}
|
||||
}
|
||||
|
||||
void serialize(TransactionInputGenerate& gen, ISerializer& serializer) {
|
||||
serializer(gen.height, "height");
|
||||
void serialize(BaseInput& gen, ISerializer& serializer) {
|
||||
serializer(gen.blockIndex, "height");
|
||||
}
|
||||
|
||||
void serialize(TransactionInputToScript& script, ISerializer& serializer) {}
|
||||
void serialize(TransactionInputToScriptHash& scripthash, ISerializer& serializer) {}
|
||||
|
||||
void serialize(TransactionInputToKey& key, ISerializer& serializer) {
|
||||
void serialize(KeyInput& key, ISerializer& serializer) {
|
||||
serializer(key.amount, "amount");
|
||||
serializeVarintVector(key.keyOffsets, serializer, "key_offsets");
|
||||
serializeVarintVector(key.outputIndexes, serializer, "key_offsets");
|
||||
serializer(key.keyImage, "k_image");
|
||||
}
|
||||
|
||||
void serialize(TransactionInputMultisignature& multisignature, ISerializer& serializer) {
|
||||
void serialize(MultisignatureInput& multisignature, ISerializer& serializer) {
|
||||
serializer(multisignature.amount, "amount");
|
||||
serializer(multisignature.signatures, "signatures");
|
||||
serializer(multisignature.signatureCount, "signatures");
|
||||
serializer(multisignature.outputIndex, "outputIndex");
|
||||
}
|
||||
|
||||
|
@ -294,16 +295,13 @@ void serialize(TransactionOutputTarget& output, ISerializer& serializer) {
|
|||
}
|
||||
}
|
||||
|
||||
void serialize(TransactionOutputToScript& script, ISerializer& serializer) {}
|
||||
void serialize(TransactionOutputToScriptHash& scripthash, ISerializer& serializer) {}
|
||||
|
||||
void serialize(TransactionOutputToKey& key, ISerializer& serializer) {
|
||||
void serialize(KeyOutput& key, ISerializer& serializer) {
|
||||
serializer(key.key, "key");
|
||||
}
|
||||
|
||||
void serialize(TransactionOutputMultisignature& multisignature, ISerializer& serializer) {
|
||||
void serialize(MultisignatureOutput& multisignature, ISerializer& serializer) {
|
||||
serializer(multisignature.keys, "keys");
|
||||
serializer(multisignature.requiredSignatures, "required_signatures");
|
||||
serializer(multisignature.requiredSignatureCount, "required_signatures");
|
||||
}
|
||||
|
||||
void serialize(ParentBlockSerializer& pbs, ISerializer& serializer) {
|
||||
|
@ -315,25 +313,25 @@ void serialize(ParentBlockSerializer& pbs, ISerializer& serializer) {
|
|||
|
||||
serializer(pbs.m_parentBlock.minorVersion, "minorVersion");
|
||||
serializer(pbs.m_timestamp, "timestamp");
|
||||
serializer(pbs.m_parentBlock.prevId, "prevId");
|
||||
serializer(pbs.m_parentBlock.previousBlockHash, "prevId");
|
||||
serializer.binary(&pbs.m_nonce, sizeof(pbs.m_nonce), "nonce");
|
||||
|
||||
if (pbs.m_hashingSerialization) {
|
||||
crypto::hash minerTxHash;
|
||||
if (!get_transaction_hash(pbs.m_parentBlock.minerTx, minerTxHash)) {
|
||||
Crypto::Hash minerTxHash;
|
||||
if (!getObjectHash(pbs.m_parentBlock.baseTransaction, minerTxHash)) {
|
||||
throw std::runtime_error("Get transaction hash error");
|
||||
}
|
||||
|
||||
crypto::hash merkleRoot;
|
||||
crypto::tree_hash_from_branch(pbs.m_parentBlock.minerTxBranch.data(), pbs.m_parentBlock.minerTxBranch.size(), minerTxHash, 0, merkleRoot);
|
||||
Crypto::Hash merkleRoot;
|
||||
Crypto::tree_hash_from_branch(pbs.m_parentBlock.baseTransactionBranch.data(), pbs.m_parentBlock.baseTransactionBranch.size(), minerTxHash, 0, merkleRoot);
|
||||
|
||||
serializer(merkleRoot, "merkleRoot");
|
||||
}
|
||||
|
||||
uint64_t txNum = static_cast<uint64_t>(pbs.m_parentBlock.numberOfTransactions);
|
||||
uint64_t txNum = static_cast<uint64_t>(pbs.m_parentBlock.transactionCount);
|
||||
serializer(txNum, "numberOfTransactions");
|
||||
pbs.m_parentBlock.numberOfTransactions = static_cast<uint16_t>(txNum);
|
||||
if (pbs.m_parentBlock.numberOfTransactions < 1) {
|
||||
pbs.m_parentBlock.transactionCount = static_cast<uint16_t>(txNum);
|
||||
if (pbs.m_parentBlock.transactionCount < 1) {
|
||||
throw std::runtime_error("Wrong transactions number");
|
||||
}
|
||||
|
||||
|
@ -341,29 +339,29 @@ void serialize(ParentBlockSerializer& pbs, ISerializer& serializer) {
|
|||
return;
|
||||
}
|
||||
|
||||
size_t branchSize = crypto::tree_depth(pbs.m_parentBlock.numberOfTransactions);
|
||||
size_t branchSize = Crypto::tree_depth(pbs.m_parentBlock.transactionCount);
|
||||
if (serializer.type() == ISerializer::OUTPUT) {
|
||||
if (pbs.m_parentBlock.minerTxBranch.size() != branchSize) {
|
||||
if (pbs.m_parentBlock.baseTransactionBranch.size() != branchSize) {
|
||||
throw std::runtime_error("Wrong miner transaction branch size");
|
||||
}
|
||||
} else {
|
||||
pbs.m_parentBlock.minerTxBranch.resize(branchSize);
|
||||
pbs.m_parentBlock.baseTransactionBranch.resize(branchSize);
|
||||
}
|
||||
|
||||
// serializer(m_parentBlock.minerTxBranch, "minerTxBranch");
|
||||
// serializer(m_parentBlock.baseTransactionBranch, "baseTransactionBranch");
|
||||
//TODO: Make arrays with computable size! This code won't work with json serialization!
|
||||
for (crypto::hash& hash: pbs.m_parentBlock.minerTxBranch) {
|
||||
for (Crypto::Hash& hash: pbs.m_parentBlock.baseTransactionBranch) {
|
||||
serializer(hash, "");
|
||||
}
|
||||
|
||||
serializer(pbs.m_parentBlock.minerTx, "minerTx");
|
||||
serializer(pbs.m_parentBlock.baseTransaction, "minerTx");
|
||||
|
||||
tx_extra_merge_mining_tag mmTag;
|
||||
if (!get_mm_tag_from_extra(pbs.m_parentBlock.minerTx.extra, mmTag)) {
|
||||
TransactionExtraMergeMiningTag mmTag;
|
||||
if (!getMergeMiningTagFromExtra(pbs.m_parentBlock.baseTransaction.extra, mmTag)) {
|
||||
throw std::runtime_error("Can't get extra merge mining tag");
|
||||
}
|
||||
|
||||
if (mmTag.depth > 8 * sizeof(crypto::hash)) {
|
||||
if (mmTag.depth > 8 * sizeof(Crypto::Hash)) {
|
||||
throw std::runtime_error("Wrong merge mining tag depth");
|
||||
}
|
||||
|
||||
|
@ -377,7 +375,7 @@ void serialize(ParentBlockSerializer& pbs, ISerializer& serializer) {
|
|||
|
||||
// serializer(m_parentBlock.blockchainBranch, "blockchainBranch");
|
||||
//TODO: Make arrays with computable size! This code won't work with json serialization!
|
||||
for (crypto::hash& hash: pbs.m_parentBlock.blockchainBranch) {
|
||||
for (Crypto::Hash& hash: pbs.m_parentBlock.blockchainBranch) {
|
||||
serializer(hash, "");
|
||||
}
|
||||
}
|
||||
|
@ -391,10 +389,10 @@ void serializeBlockHeader(BlockHeader& header, ISerializer& serializer) {
|
|||
serializer(header.minorVersion, "minor_version");
|
||||
if (header.majorVersion == BLOCK_MAJOR_VERSION_1) {
|
||||
serializer(header.timestamp, "timestamp");
|
||||
serializer(header.prevId, "prev_id");
|
||||
serializer(header.previousBlockHash, "prev_id");
|
||||
serializer.binary(&header.nonce, sizeof(header.nonce), "nonce");
|
||||
} else if (header.majorVersion == BLOCK_MAJOR_VERSION_2) {
|
||||
serializer(header.prevId, "prev_id");
|
||||
serializer(header.previousBlockHash, "prev_id");
|
||||
} else {
|
||||
throw std::runtime_error("Wrong major version");
|
||||
}
|
||||
|
@ -412,42 +410,48 @@ void serialize(Block& block, ISerializer& serializer) {
|
|||
serializer(parentBlockSerializer, "parent_block");
|
||||
}
|
||||
|
||||
serializer(block.minerTx, "miner_tx");
|
||||
serializer(block.txHashes, "tx_hashes");
|
||||
serializer(block.baseTransaction, "miner_tx");
|
||||
serializer(block.transactionHashes, "tx_hashes");
|
||||
}
|
||||
|
||||
void serialize(AccountPublicAddress& address, ISerializer& serializer) {
|
||||
serializer(address.m_spendPublicKey, "m_spend_public_key");
|
||||
serializer(address.m_viewPublicKey, "m_view_public_key");
|
||||
serializer(address.spendPublicKey, "m_spend_public_key");
|
||||
serializer(address.viewPublicKey, "m_view_public_key");
|
||||
}
|
||||
|
||||
void serialize(account_keys& keys, ISerializer& s) {
|
||||
s(keys.m_account_address, "m_account_address");
|
||||
s(keys.m_spend_secret_key, "m_spend_secret_key");
|
||||
s(keys.m_view_secret_key, "m_view_secret_key");
|
||||
void serialize(AccountKeys& keys, ISerializer& s) {
|
||||
s(keys.address, "m_account_address");
|
||||
s(keys.spendSecretKey, "m_spend_secret_key");
|
||||
s(keys.viewSecretKey, "m_view_secret_key");
|
||||
}
|
||||
|
||||
void doSerialize(tx_extra_merge_mining_tag& tag, ISerializer& serializer) {
|
||||
void doSerialize(TransactionExtraMergeMiningTag& tag, ISerializer& serializer) {
|
||||
uint64_t depth = static_cast<uint64_t>(tag.depth);
|
||||
serializer(depth, "depth");
|
||||
tag.depth = static_cast<size_t>(depth);
|
||||
serializer(tag.merkle_root, "merkle_root");
|
||||
serializer(tag.merkleRoot, "merkle_root");
|
||||
}
|
||||
|
||||
void serialize(tx_extra_merge_mining_tag& tag, ISerializer& serializer) {
|
||||
void serialize(TransactionExtraMergeMiningTag& tag, ISerializer& serializer) {
|
||||
if (serializer.type() == ISerializer::OUTPUT) {
|
||||
std::stringstream stream;
|
||||
BinaryOutputStreamSerializer output(stream);
|
||||
std::string field;
|
||||
StringOutputStream os(field);
|
||||
BinaryOutputStreamSerializer output(os);
|
||||
doSerialize(tag, output);
|
||||
std::string field = stream.str();
|
||||
serializer(field, "");
|
||||
} else {
|
||||
std::string field;
|
||||
serializer(field, "");
|
||||
std::stringstream stream(field);
|
||||
MemoryInputStream stream(field.data(), field.size());
|
||||
BinaryInputStreamSerializer input(stream);
|
||||
doSerialize(tag, input);
|
||||
}
|
||||
}
|
||||
|
||||
void serialize(KeyPair& keyPair, ISerializer& serializer) {
|
||||
serializer(keyPair.secretKey, "secret_key");
|
||||
serializer(keyPair.publicKey, "public_key");
|
||||
}
|
||||
|
||||
|
||||
} //namespace CryptoNote
|
50
src/cryptonote_core/cryptonote_serialization.h → src/CryptoNoteCore/CryptoNoteSerialization.h
Normal file → Executable file
50
src/cryptonote_core/cryptonote_serialization.h → src/CryptoNoteCore/CryptoNoteSerialization.h
Normal file → Executable file
|
@ -17,47 +17,51 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "cryptonote_basic.h"
|
||||
#include "serialization/ISerializer.h"
|
||||
#include "CryptoNoteBasic.h"
|
||||
#include "crypto/chacha8.h"
|
||||
#include "Serialization/ISerializer.h"
|
||||
#include "crypto/crypto.h"
|
||||
|
||||
namespace crypto {
|
||||
namespace Crypto {
|
||||
|
||||
bool serialize(public_key& pubKey, Common::StringView name, CryptoNote::ISerializer& serializer);
|
||||
bool serialize(secret_key& secKey, Common::StringView name, CryptoNote::ISerializer& serializer);
|
||||
bool serialize(hash& h, Common::StringView name, CryptoNote::ISerializer& serializer);
|
||||
bool serialize(PublicKey& pubKey, Common::StringView name, CryptoNote::ISerializer& serializer);
|
||||
bool serialize(SecretKey& secKey, Common::StringView name, CryptoNote::ISerializer& serializer);
|
||||
bool serialize(Hash& h, Common::StringView name, CryptoNote::ISerializer& serializer);
|
||||
bool serialize(chacha8_iv& chacha, Common::StringView name, CryptoNote::ISerializer& serializer);
|
||||
bool serialize(key_image& keyImage, Common::StringView name, CryptoNote::ISerializer& serializer);
|
||||
bool serialize(signature& sig, Common::StringView name, CryptoNote::ISerializer& serializer);
|
||||
bool serialize(KeyImage& keyImage, Common::StringView name, CryptoNote::ISerializer& serializer);
|
||||
bool serialize(Signature& sig, Common::StringView name, CryptoNote::ISerializer& serializer);
|
||||
bool serialize(EllipticCurveScalar& ecScalar, Common::StringView name, CryptoNote::ISerializer& serializer);
|
||||
bool serialize(EllipticCurvePoint& ecPoint, Common::StringView name, CryptoNote::ISerializer& serializer);
|
||||
|
||||
} //namespace crypto
|
||||
}
|
||||
|
||||
namespace CryptoNote {
|
||||
void serialize(ParentBlockSerializer& pbs, ISerializer& serializer);
|
||||
|
||||
struct AccountKeys;
|
||||
struct TransactionExtraMergeMiningTag;
|
||||
|
||||
void serialize(TransactionPrefix& txP, ISerializer& serializer);
|
||||
void serialize(Transaction& tx, ISerializer& serializer);
|
||||
void serialize(TransactionInput& in, ISerializer& serializer);
|
||||
void serialize(TransactionOutput& in, ISerializer& serializer);
|
||||
|
||||
void serialize(TransactionInputGenerate& gen, ISerializer& serializer);
|
||||
void serialize(TransactionInputToScript& script, ISerializer& serializer);
|
||||
void serialize(TransactionInputToScriptHash& scripthash, ISerializer& serializer);
|
||||
void serialize(TransactionInputToKey& key, ISerializer& serializer);
|
||||
void serialize(TransactionInputMultisignature& multisignature, ISerializer& serializer);
|
||||
void serialize(BaseInput& gen, ISerializer& serializer);
|
||||
void serialize(KeyInput& key, ISerializer& serializer);
|
||||
void serialize(MultisignatureInput& multisignature, ISerializer& serializer);
|
||||
|
||||
void serialize(TransactionOutput& output, ISerializer& serializer);
|
||||
|
||||
void serialize(TransactionOutputTarget& output, ISerializer& serializer);
|
||||
void serialize(KeyOutput& key, ISerializer& serializer);
|
||||
void serialize(MultisignatureOutput& multisignature, ISerializer& serializer);
|
||||
|
||||
void serialize(TransactionOutputToScript& script, ISerializer& serializer);
|
||||
void serialize(TransactionOutputToScriptHash& scripthash, ISerializer& serializer);
|
||||
void serialize(TransactionOutputToKey& key, ISerializer& serializer);
|
||||
void serialize(TransactionOutputMultisignature& multisignature, ISerializer& serializer);
|
||||
void serialize(BlockHeader& header, ISerializer& serializer);
|
||||
void serialize(Block& block, ISerializer& serializer);
|
||||
void serialize(tx_extra_merge_mining_tag& tag, ISerializer& serializer);
|
||||
void serialize(ParentBlockSerializer& pbs, ISerializer& serializer);
|
||||
void serialize(TransactionExtraMergeMiningTag& tag, ISerializer& serializer);
|
||||
|
||||
void serialize(AccountPublicAddress& address, ISerializer& serializer);
|
||||
void serialize(account_keys& keys, ISerializer& s);
|
||||
void serialize(AccountKeys& keys, ISerializer& s);
|
||||
|
||||
void serialize(KeyPair& keyPair, ISerializer& serializer);
|
||||
|
||||
} //namespace CryptoNote
|
||||
}
|
2
src/cryptonote_core/cryptonote_stat_info.h → src/CryptoNoteCore/CryptoNoteStatInfo.h
Normal file → Executable file
2
src/cryptonote_core/cryptonote_stat_info.h → src/CryptoNoteCore/CryptoNoteStatInfo.h
Normal file → Executable file
|
@ -17,7 +17,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "serialization/ISerializer.h"
|
||||
#include "Serialization/ISerializer.h"
|
||||
|
||||
namespace CryptoNote
|
||||
{
|
79
src/CryptoNoteCore/CryptoNoteTools.cpp
Executable file
79
src/CryptoNoteCore/CryptoNoteTools.cpp
Executable file
|
@ -0,0 +1,79 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "CryptoNoteTools.h"
|
||||
#include "CryptoNoteFormatUtils.h"
|
||||
|
||||
namespace CryptoNote {
|
||||
template<>
|
||||
bool toBinaryArray(const BinaryArray& object, BinaryArray& binaryArray) {
|
||||
try {
|
||||
Common::VectorOutputStream stream(binaryArray);
|
||||
BinaryOutputStreamSerializer serializer(stream);
|
||||
std::string oldBlob = Common::asString(object);
|
||||
serializer(oldBlob, "");
|
||||
} catch (std::exception&) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void getBinaryArrayHash(const BinaryArray& binaryArray, Crypto::Hash& hash) {
|
||||
cn_fast_hash(binaryArray.data(), binaryArray.size(), hash);
|
||||
}
|
||||
|
||||
Crypto::Hash getBinaryArrayHash(const BinaryArray& binaryArray) {
|
||||
Crypto::Hash hash;
|
||||
getBinaryArrayHash(binaryArray, hash);
|
||||
return hash;
|
||||
}
|
||||
|
||||
uint64_t getInputAmount(const Transaction& transaction) {
|
||||
uint64_t amount = 0;
|
||||
for (auto& input : transaction.inputs) {
|
||||
if (input.type() == typeid(KeyInput)) {
|
||||
amount += boost::get<KeyInput>(input).amount;
|
||||
} else if (input.type() == typeid(MultisignatureInput)) {
|
||||
amount += boost::get<MultisignatureInput>(input).amount;
|
||||
}
|
||||
}
|
||||
|
||||
return amount;
|
||||
}
|
||||
|
||||
uint64_t getOutputAmount(const Transaction& transaction) {
|
||||
uint64_t amount = 0;
|
||||
for (auto& output : transaction.outputs) {
|
||||
amount += output.amount;
|
||||
}
|
||||
|
||||
return amount;
|
||||
}
|
||||
|
||||
void decomposeAmount(uint64_t amount, uint64_t dustThreshold, std::vector<uint64_t>& decomposedAmounts) {
|
||||
decompose_amount_into_digits(amount, dustThreshold,
|
||||
[&](uint64_t amount) {
|
||||
decomposedAmounts.push_back(amount);
|
||||
},
|
||||
[&](uint64_t dust) {
|
||||
decomposedAmounts.push_back(dust);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
125
src/CryptoNoteCore/CryptoNoteTools.h
Executable file
125
src/CryptoNoteCore/CryptoNoteTools.h
Executable file
|
@ -0,0 +1,125 @@
|
|||
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
||||
//
|
||||
// This file is part of Bytecoin.
|
||||
//
|
||||
// Bytecoin is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Bytecoin is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <limits>
|
||||
#include "Common/MemoryInputStream.h"
|
||||
#include "Common/StringTools.h"
|
||||
#include "Common/VectorOutputStream.h"
|
||||
#include "Serialization/BinaryOutputStreamSerializer.h"
|
||||
#include "Serialization/BinaryInputStreamSerializer.h"
|
||||
#include "CryptoNoteSerialization.h"
|
||||
|
||||
namespace CryptoNote {
|
||||
|
||||
void getBinaryArrayHash(const BinaryArray& binaryArray, Crypto::Hash& hash);
|
||||
Crypto::Hash getBinaryArrayHash(const BinaryArray& binaryArray);
|
||||
|
||||
template<class T>
|
||||
bool toBinaryArray(const T& object, BinaryArray& binaryArray) {
|
||||
try {
|
||||
::Common::VectorOutputStream stream(binaryArray);
|
||||
BinaryOutputStreamSerializer serializer(stream);
|
||||
serialize(const_cast<T&>(object), serializer);
|
||||
} catch (std::exception&) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool toBinaryArray(const BinaryArray& object, BinaryArray& binaryArray);
|
||||
|
||||
template<class T>
|
||||
BinaryArray toBinaryArray(const T& object) {
|
||||
BinaryArray ba;
|
||||
toBinaryArray(object, ba);
|
||||
return ba;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool fromBinaryArray(T& object, const BinaryArray& binaryArray) {
|
||||
bool result = false;
|
||||
try {
|
||||
Common::MemoryInputStream stream(binaryArray.data(), binaryArray.size());
|
||||
BinaryInputStreamSerializer serializer(stream);
|
||||
serialize(object, serializer);
|
||||
result = stream.endOfStream(); // check that all data was consumed
|
||||
} catch (std::exception&) {
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool getObjectBinarySize(const T& object, size_t& size) {
|
||||
BinaryArray ba;
|
||||
if (!toBinaryArray(object, ba)) {
|
||||
size = (std::numeric_limits<size_t>::max)();
|
||||
return false;
|
||||
}
|
||||
|
||||
size = ba.size();
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
size_t getObjectBinarySize(const T& object) {
|
||||
size_t size;
|
||||
getObjectBinarySize(object, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool getObjectHash(const T& object, Crypto::Hash& hash) {
|
||||
BinaryArray ba;
|
||||
if (!toBinaryArray(object, ba)) {
|
||||
hash = NULL_HASH;
|
||||
return false;
|
||||
}
|
||||
|
||||
hash = getBinaryArrayHash(ba);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool getObjectHash(const T& object, Crypto::Hash& hash, size_t& size) {
|
||||
BinaryArray ba;
|
||||
if (!toBinaryArray(object, ba)) {
|
||||
hash = NULL_HASH;
|
||||
size = (std::numeric_limits<size_t>::max)();
|
||||
return false;
|
||||
}
|
||||
|
||||
size = ba.size();
|
||||
hash = getBinaryArrayHash(ba);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Crypto::Hash getObjectHash(const T& object) {
|
||||
Crypto::Hash hash;
|
||||
getObjectHash(object, hash);
|
||||
return hash;
|
||||
}
|
||||
|
||||
uint64_t getInputAmount(const Transaction& transaction);
|
||||
uint64_t getOutputAmount(const Transaction& transaction);
|
||||
void decomposeAmount(uint64_t amount, uint64_t dustThreshold, std::vector<uint64_t>& decomposedAmounts);
|
||||
}
|
89
src/cryptonote_core/Currency.cpp → src/CryptoNoteCore/Currency.cpp
Normal file → Executable file
89
src/cryptonote_core/Currency.cpp → src/CryptoNoteCore/Currency.cpp
Normal file → Executable file
|
@ -19,15 +19,21 @@
|
|||
#include <cctype>
|
||||
#include <boost/algorithm/string/trim.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include "../Common/base58.h"
|
||||
#include "../Common/Base58.h"
|
||||
#include "../Common/int-util.h"
|
||||
#include "account.h"
|
||||
#include "cryptonote_basic_impl.h"
|
||||
#include "cryptonote_format_utils.h"
|
||||
#include "../Common/StringTools.h"
|
||||
|
||||
#include "Account.h"
|
||||
#include "CryptoNoteBasicImpl.h"
|
||||
#include "CryptoNoteFormatUtils.h"
|
||||
#include "CryptoNoteTools.h"
|
||||
#include "TransactionExtra.h"
|
||||
#include "UpgradeDetector.h"
|
||||
|
||||
#undef ERROR
|
||||
|
||||
using namespace Logging;
|
||||
using namespace Common;
|
||||
|
||||
namespace CryptoNote {
|
||||
|
||||
|
@ -48,6 +54,7 @@ bool Currency::init() {
|
|||
m_blocksCacheFileName = "testnet_" + m_blocksCacheFileName;
|
||||
m_blockIndexesFileName = "testnet_" + m_blockIndexesFileName;
|
||||
m_txPoolFileName = "testnet_" + m_txPoolFileName;
|
||||
m_blockchinIndicesFileName = "testnet_" + m_blockchinIndicesFileName;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -58,17 +65,17 @@ bool Currency::generateGenesisBlock() {
|
|||
|
||||
//account_public_address ac = boost::value_initialized<AccountPublicAddress>();
|
||||
//std::vector<size_t> sz;
|
||||
//constructMinerTx(0, 0, 0, 0, 0, ac, m_genesisBlock.minerTx); // zero fee in genesis
|
||||
//blobdata txb = tx_to_blob(m_genesisBlock.minerTx);
|
||||
//constructMinerTx(0, 0, 0, 0, 0, ac, m_genesisBlock.baseTransaction); // zero fee in genesis
|
||||
//BinaryArray txb = toBinaryArray(m_genesisBlock.baseTransaction);
|
||||
//std::string hex_tx_represent = Common::toHex(txb);
|
||||
|
||||
// Hard code coinbase tx in genesis block, because through generating tx use random, but genesis should be always the same
|
||||
std::string genesisCoinbaseTxHex = "010a01ff0001ffffffffffff0f029b2e4c0281c0b02e7c53291a94d1d0cbff8883f8024f5142ee494ffbbd08807121013c086a48c15fb637a96991bc6d53caf77068b5ba6eeb3c82357228c49790584a";
|
||||
blobdata minerTxBlob;
|
||||
BinaryArray minerTxBlob;
|
||||
|
||||
bool r =
|
||||
hexToBlob(genesisCoinbaseTxHex, minerTxBlob) &&
|
||||
parse_and_validate_tx_from_blob(minerTxBlob, m_genesisBlock.minerTx);
|
||||
fromHex(genesisCoinbaseTxHex, minerTxBlob) &&
|
||||
fromBinaryArray(m_genesisBlock.baseTransaction, minerTxBlob);
|
||||
|
||||
if (!r) {
|
||||
logger(ERROR, BRIGHT_RED) << "failed to parse coinbase tx from hard coded blob";
|
||||
|
@ -122,22 +129,22 @@ size_t Currency::maxBlockCumulativeSize(uint64_t height) const {
|
|||
|
||||
bool Currency::constructMinerTx(uint32_t height, size_t medianSize, uint64_t alreadyGeneratedCoins, size_t currentBlockSize,
|
||||
uint64_t fee, const AccountPublicAddress& minerAddress, Transaction& tx,
|
||||
const blobdata& extraNonce/* = blobdata()*/, size_t maxOuts/* = 1*/,
|
||||
const BinaryArray& extraNonce/* = BinaryArray()*/, size_t maxOuts/* = 1*/,
|
||||
bool penalizeFee/* = false*/) const {
|
||||
tx.vin.clear();
|
||||
tx.vout.clear();
|
||||
tx.inputs.clear();
|
||||
tx.outputs.clear();
|
||||
tx.extra.clear();
|
||||
|
||||
KeyPair txkey = KeyPair::generate();
|
||||
add_tx_pub_key_to_extra(tx, txkey.pub);
|
||||
KeyPair txkey = generateKeyPair();
|
||||
addTransactionPublicKeyToExtra(tx.extra, txkey.publicKey);
|
||||
if (!extraNonce.empty()) {
|
||||
if (!add_extra_nonce_to_tx_extra(tx.extra, extraNonce)) {
|
||||
if (!addExtraNonceToTransactionExtra(tx.extra, extraNonce)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
TransactionInputGenerate in;
|
||||
in.height = height;
|
||||
BaseInput in;
|
||||
in.blockIndex = height;
|
||||
|
||||
uint64_t blockReward;
|
||||
int64_t emissionChange;
|
||||
|
@ -145,9 +152,6 @@ bool Currency::constructMinerTx(uint32_t height, size_t medianSize, uint64_t alr
|
|||
logger(INFO) << "Block is too big";
|
||||
return false;
|
||||
}
|
||||
#if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
|
||||
logger(DEBUGGING) << "Creating block template: reward " << blockReward << ", fee " << fee;
|
||||
#endif
|
||||
|
||||
std::vector<uint64_t> outAmounts;
|
||||
decompose_amount_into_digits(blockReward, m_defaultDustThreshold,
|
||||
|
@ -162,35 +166,35 @@ bool Currency::constructMinerTx(uint32_t height, size_t medianSize, uint64_t alr
|
|||
|
||||
uint64_t summaryAmounts = 0;
|
||||
for (size_t no = 0; no < outAmounts.size(); no++) {
|
||||
crypto::key_derivation derivation = boost::value_initialized<crypto::key_derivation>();
|
||||
crypto::public_key outEphemeralPubKey = boost::value_initialized<crypto::public_key>();
|
||||
Crypto::KeyDerivation derivation = boost::value_initialized<Crypto::KeyDerivation>();
|
||||
Crypto::PublicKey outEphemeralPubKey = boost::value_initialized<Crypto::PublicKey>();
|
||||
|
||||
bool r = crypto::generate_key_derivation(minerAddress.m_viewPublicKey, txkey.sec, derivation);
|
||||
bool r = Crypto::generate_key_derivation(minerAddress.viewPublicKey, txkey.secretKey, derivation);
|
||||
|
||||
if (!(r)) {
|
||||
logger(ERROR, BRIGHT_RED)
|
||||
<< "while creating outs: failed to generate_key_derivation("
|
||||
<< minerAddress.m_viewPublicKey << ", " << txkey.sec << ")";
|
||||
<< minerAddress.viewPublicKey << ", " << txkey.secretKey << ")";
|
||||
return false;
|
||||
}
|
||||
|
||||
r = crypto::derive_public_key(derivation, no, minerAddress.m_spendPublicKey, outEphemeralPubKey);
|
||||
r = Crypto::derive_public_key(derivation, no, minerAddress.spendPublicKey, outEphemeralPubKey);
|
||||
|
||||
if (!(r)) {
|
||||
logger(ERROR, BRIGHT_RED)
|
||||
<< "while creating outs: failed to derive_public_key("
|
||||
<< derivation << ", " << no << ", "
|
||||
<< minerAddress.m_spendPublicKey << ")";
|
||||
<< minerAddress.spendPublicKey << ")";
|
||||
return false;
|
||||
}
|
||||
|
||||
TransactionOutputToKey tk;
|
||||
KeyOutput tk;
|
||||
tk.key = outEphemeralPubKey;
|
||||
|
||||
TransactionOutput out;
|
||||
summaryAmounts += out.amount = outAmounts[no];
|
||||
out.target = tk;
|
||||
tx.vout.push_back(out);
|
||||
tx.outputs.push_back(out);
|
||||
}
|
||||
|
||||
if (!(summaryAmounts == blockReward)) {
|
||||
|
@ -201,12 +205,12 @@ bool Currency::constructMinerTx(uint32_t height, size_t medianSize, uint64_t alr
|
|||
tx.version = CURRENT_TRANSACTION_VERSION;
|
||||
//lock
|
||||
tx.unlockTime = height + m_minedMoneyUnlockWindow;
|
||||
tx.vin.push_back(in);
|
||||
tx.inputs.push_back(in);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string Currency::accountAddressAsString(const account_base& account) const {
|
||||
return getAccountAddressAsStr(m_publicAddressBase58Prefix, account.get_keys().m_account_address);
|
||||
std::string Currency::accountAddressAsString(const AccountBase& account) const {
|
||||
return getAccountAddressAsStr(m_publicAddressBase58Prefix, account.getAccountKeys().address);
|
||||
}
|
||||
|
||||
std::string Currency::accountAddressAsString(const AccountPublicAddress& accountPublicAddress) const {
|
||||
|
@ -316,8 +320,8 @@ difficulty_type Currency::nextDifficulty(std::vector<uint64_t> timestamps,
|
|||
return (low + timeSpan - 1) / timeSpan;
|
||||
}
|
||||
|
||||
bool Currency::checkProofOfWorkV1(crypto::cn_context& context, const Block& block, difficulty_type currentDiffic,
|
||||
crypto::hash& proofOfWork) const {
|
||||
bool Currency::checkProofOfWorkV1(Crypto::cn_context& context, const Block& block, difficulty_type currentDiffic,
|
||||
Crypto::Hash& proofOfWork) const {
|
||||
if (BLOCK_MAJOR_VERSION_1 != block.majorVersion) {
|
||||
return false;
|
||||
}
|
||||
|
@ -329,8 +333,8 @@ bool Currency::checkProofOfWorkV1(crypto::cn_context& context, const Block& bloc
|
|||
return check_hash(proofOfWork, currentDiffic);
|
||||
}
|
||||
|
||||
bool Currency::checkProofOfWorkV2(crypto::cn_context& context, const Block& block, difficulty_type currentDiffic,
|
||||
crypto::hash& proofOfWork) const {
|
||||
bool Currency::checkProofOfWorkV2(Crypto::cn_context& context, const Block& block, difficulty_type currentDiffic,
|
||||
Crypto::Hash& proofOfWork) const {
|
||||
if (BLOCK_MAJOR_VERSION_2 != block.majorVersion) {
|
||||
return false;
|
||||
}
|
||||
|
@ -343,8 +347,8 @@ bool Currency::checkProofOfWorkV2(crypto::cn_context& context, const Block& bloc
|
|||
return false;
|
||||
}
|
||||
|
||||
tx_extra_merge_mining_tag mmTag;
|
||||
if (!get_mm_tag_from_extra(block.parentBlock.minerTx.extra, mmTag)) {
|
||||
TransactionExtraMergeMiningTag mmTag;
|
||||
if (!getMergeMiningTagFromExtra(block.parentBlock.baseTransaction.extra, mmTag)) {
|
||||
logger(ERROR) << "merge mining tag wasn't found in extra of the parent block miner transaction";
|
||||
return false;
|
||||
}
|
||||
|
@ -353,16 +357,16 @@ bool Currency::checkProofOfWorkV2(crypto::cn_context& context, const Block& bloc
|
|||
return false;
|
||||
}
|
||||
|
||||
crypto::hash auxBlockHeaderHash;
|
||||
Crypto::Hash auxBlockHeaderHash;
|
||||
if (!get_aux_block_header_hash(block, auxBlockHeaderHash)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
crypto::hash auxBlocksMerkleRoot;
|
||||
crypto::tree_hash_from_branch(block.parentBlock.blockchainBranch.data(), block.parentBlock.blockchainBranch.size(),
|
||||
Crypto::Hash auxBlocksMerkleRoot;
|
||||
Crypto::tree_hash_from_branch(block.parentBlock.blockchainBranch.data(), block.parentBlock.blockchainBranch.size(),
|
||||
auxBlockHeaderHash, &m_genesisBlockHash, auxBlocksMerkleRoot);
|
||||
|
||||
if (auxBlocksMerkleRoot != mmTag.merkle_root) {
|
||||
if (auxBlocksMerkleRoot != mmTag.merkleRoot) {
|
||||
logger(ERROR, BRIGHT_YELLOW) << "Aux block hash wasn't found in merkle tree";
|
||||
return false;
|
||||
}
|
||||
|
@ -370,7 +374,7 @@ bool Currency::checkProofOfWorkV2(crypto::cn_context& context, const Block& bloc
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Currency::checkProofOfWork(crypto::cn_context& context, const Block& block, difficulty_type currentDiffic, crypto::hash& proofOfWork) const {
|
||||
bool Currency::checkProofOfWork(Crypto::cn_context& context, const Block& block, difficulty_type currentDiffic, Crypto::Hash& proofOfWork) const {
|
||||
switch (block.majorVersion) {
|
||||
case BLOCK_MAJOR_VERSION_1: return checkProofOfWorkV1(context, block, currentDiffic, proofOfWork);
|
||||
case BLOCK_MAJOR_VERSION_2: return checkProofOfWorkV2(context, block, currentDiffic, proofOfWork);
|
||||
|
@ -427,6 +431,7 @@ CurrencyBuilder::CurrencyBuilder(Logging::ILogger& log) : m_currency(log) {
|
|||
blocksCacheFileName(parameters::CRYPTONOTE_BLOCKSCACHE_FILENAME);
|
||||
blockIndexesFileName(parameters::CRYPTONOTE_BLOCKINDEXES_FILENAME);
|
||||
txPoolFileName(parameters::CRYPTONOTE_POOLDATA_FILENAME);
|
||||
blockchinIndicesFileName(parameters::CRYPTONOTE_BLOCKCHAIN_INDICES_FILENAME);
|
||||
|
||||
testnet(false);
|
||||
}
|
28
src/cryptonote_core/Currency.h → src/CryptoNoteCore/Currency.h
Normal file → Executable file
28
src/cryptonote_core/Currency.h → src/CryptoNoteCore/Currency.h
Normal file → Executable file
|
@ -21,15 +21,16 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
#include <boost/utility.hpp>
|
||||
#include "../cryptonote_config.h"
|
||||
#include "../CryptoNoteConfig.h"
|
||||
#include "../crypto/hash.h"
|
||||
#include "../cryptonote_protocol/blobdatatype.h"
|
||||
#include "../Logging/LoggerRef.h"
|
||||
#include "cryptonote_basic.h"
|
||||
#include "difficulty.h"
|
||||
#include "CryptoNoteBasic.h"
|
||||
#include "Difficulty.h"
|
||||
|
||||
namespace CryptoNote {
|
||||
|
||||
class AccountBase;
|
||||
|
||||
class Currency {
|
||||
public:
|
||||
uint64_t maxBlockHeight() const { return m_maxBlockHeight; }
|
||||
|
@ -83,11 +84,12 @@ public:
|
|||
const std::string& blocksCacheFileName() const { return m_blocksCacheFileName; }
|
||||
const std::string& blockIndexesFileName() const { return m_blockIndexesFileName; }
|
||||
const std::string& txPoolFileName() const { return m_txPoolFileName; }
|
||||
const std::string& blockchinIndicesFileName() const { return m_blockchinIndicesFileName; }
|
||||
|
||||
bool isTestnet() const { return m_testnet; }
|
||||
|
||||
const Block& genesisBlock() const { return m_genesisBlock; }
|
||||
const crypto::hash& genesisBlockHash() const { return m_genesisBlockHash; }
|
||||
const Crypto::Hash& genesisBlockHash() const { return m_genesisBlockHash; }
|
||||
|
||||
bool getBlockReward(size_t medianSize, size_t currentBlockSize, uint64_t alreadyGeneratedCoins, uint64_t fee,
|
||||
bool penalizeFee, uint64_t& reward, int64_t& emissionChange) const;
|
||||
|
@ -95,9 +97,9 @@ public:
|
|||
|
||||
bool constructMinerTx(uint32_t height, size_t medianSize, uint64_t alreadyGeneratedCoins, size_t currentBlockSize,
|
||||
uint64_t fee, const AccountPublicAddress& minerAddress, Transaction& tx,
|
||||
const blobdata& extraNonce = blobdata(), size_t maxOuts = 1, bool penalizeFee = false) const;
|
||||
const BinaryArray& extraNonce = BinaryArray(), size_t maxOuts = 1, bool penalizeFee = false) const;
|
||||
|
||||
std::string accountAddressAsString(const account_base& account) const;
|
||||
std::string accountAddressAsString(const AccountBase& account) const;
|
||||
std::string accountAddressAsString(const AccountPublicAddress& accountPublicAddress) const;
|
||||
bool parseAccountAddressString(const std::string& str, AccountPublicAddress& addr) const;
|
||||
|
||||
|
@ -106,9 +108,9 @@ public:
|
|||
|
||||
difficulty_type nextDifficulty(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulativeDifficulties) const;
|
||||
|
||||
bool checkProofOfWorkV1(crypto::cn_context& context, const Block& block, difficulty_type currentDiffic, crypto::hash& proofOfWork) const;
|
||||
bool checkProofOfWorkV2(crypto::cn_context& context, const Block& block, difficulty_type currentDiffic, crypto::hash& proofOfWork) const;
|
||||
bool checkProofOfWork(crypto::cn_context& context, const Block& block, difficulty_type currentDiffic, crypto::hash& proofOfWork) const;
|
||||
bool checkProofOfWorkV1(Crypto::cn_context& context, const Block& block, difficulty_type currentDiffic, Crypto::Hash& proofOfWork) const;
|
||||
bool checkProofOfWorkV2(Crypto::cn_context& context, const Block& block, difficulty_type currentDiffic, Crypto::Hash& proofOfWork) const;
|
||||
bool checkProofOfWork(Crypto::cn_context& context, const Block& block, difficulty_type currentDiffic, Crypto::Hash& proofOfWork) const;
|
||||
|
||||
private:
|
||||
Currency(Logging::ILogger& log) : logger(log, "currency") {
|
||||
|
@ -166,11 +168,12 @@ private:
|
|||
std::string m_blocksCacheFileName;
|
||||
std::string m_blockIndexesFileName;
|
||||
std::string m_txPoolFileName;
|
||||
std::string m_blockchinIndicesFileName;
|
||||
|
||||
bool m_testnet;
|
||||
|
||||
Block m_genesisBlock;
|
||||
crypto::hash m_genesisBlockHash;
|
||||
Crypto::Hash m_genesisBlockHash;
|
||||
|
||||
Logging::LoggerRef logger;
|
||||
|
||||
|
@ -234,7 +237,8 @@ public:
|
|||
CurrencyBuilder& blocksCacheFileName(const std::string& val) { m_currency.m_blocksCacheFileName = val; return *this; }
|
||||
CurrencyBuilder& blockIndexesFileName(const std::string& val) { m_currency.m_blockIndexesFileName = val; return *this; }
|
||||
CurrencyBuilder& txPoolFileName(const std::string& val) { m_currency.m_txPoolFileName = val; return *this; }
|
||||
|
||||
CurrencyBuilder& blockchinIndicesFileName(const std::string& val) { m_currency.m_blockchinIndicesFileName = val; return *this; }
|
||||
|
||||
CurrencyBuilder& testnet(bool val) { m_currency.m_testnet = val; return *this; }
|
||||
|
||||
private:
|
23
src/cryptonote_core/difficulty.cpp → src/CryptoNoteCore/Difficulty.cpp
Normal file → Executable file
23
src/cryptonote_core/difficulty.cpp → src/CryptoNoteCore/Difficulty.cpp
Normal file → Executable file
|
@ -23,24 +23,15 @@
|
|||
|
||||
#include "Common/int-util.h"
|
||||
#include "crypto/hash.h"
|
||||
#include "cryptonote_config.h"
|
||||
#include "difficulty.h"
|
||||
#include "CryptoNoteConfig.h"
|
||||
#include "Difficulty.h"
|
||||
|
||||
namespace CryptoNote {
|
||||
|
||||
using std::size_t;
|
||||
using std::uint64_t;
|
||||
using std::vector;
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <windows.h>
|
||||
#include <winnt.h>
|
||||
|
||||
static inline void mul(uint64_t a, uint64_t b, uint64_t &low, uint64_t &high) {
|
||||
low = mul128(a, b, &high);
|
||||
}
|
||||
|
||||
#else
|
||||
#if defined(__SIZEOF_INT128__)
|
||||
|
||||
static inline void mul(uint64_t a, uint64_t b, uint64_t &low, uint64_t &high) {
|
||||
typedef unsigned __int128 uint128_t;
|
||||
|
@ -49,6 +40,12 @@ namespace CryptoNote {
|
|||
high = (uint64_t) (res >> 64);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline void mul(uint64_t a, uint64_t b, uint64_t &low, uint64_t &high) {
|
||||
low = mul128(a, b, &high);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static inline bool cadd(uint64_t a, uint64_t b) {
|
||||
|
@ -59,7 +56,7 @@ namespace CryptoNote {
|
|||
return a + b < a || (c && a + b == (uint64_t) -1);
|
||||
}
|
||||
|
||||
bool check_hash(const crypto::hash &hash, difficulty_type difficulty) {
|
||||
bool check_hash(const Crypto::Hash &hash, difficulty_type difficulty) {
|
||||
uint64_t low, high, top, cur;
|
||||
// First check the highest word, this will most likely fail for a random hash.
|
||||
mul(swap64le(((const uint64_t *) &hash)[3]), difficulty, top, high);
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue