Bytecoin v.1.0.6 release

This commit is contained in:
Antonio Juarez 2015-07-30 16:22:07 +01:00
parent b3a91f67d7
commit 50cdbfa424
573 changed files with 30735 additions and 21253 deletions

View file

@ -8,7 +8,7 @@ set(CMAKE_CONFIGURATION_TYPES Debug RelWithDebInfo Release CACHE TYPE INTERNAL)
set(CMAKE_SKIP_INSTALL_RULES ON) set(CMAKE_SKIP_INSTALL_RULES ON)
set(CMAKE_SKIP_PACKAGE_ALL_DEPENDENCY ON) set(CMAKE_SKIP_PACKAGE_ALL_DEPENDENCY ON)
set(CMAKE_SUPPRESS_REGENERATION ON) set(CMAKE_SUPPRESS_REGENERATION ON)
#enable_testing() enable_testing()
project(Bytecoin) project(Bytecoin)
@ -62,11 +62,14 @@ else()
else() else()
set(MINGW_FLAG "") set(MINGW_FLAG "")
endif() 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(C_WARNINGS "-Waggregate-return -Wnested-externs -Wold-style-definition -Wstrict-prototypes")
set(CXX_WARNINGS "-Wno-reorder -Wno-missing-field-initializers") 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") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 ${MINGW_FLAG} ${WARNINGS} ${C_WARNINGS} ${ARCH_FLAG} -maes")
if(NOT APPLE) if(NOT APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
endif() endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ${MINGW_FLAG} ${WARNINGS} ${CXX_WARNINGS} ${ARCH_FLAG} -maes") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ${MINGW_FLAG} ${WARNINGS} ${CXX_WARNINGS} ${ARCH_FLAG} -maes")
if(APPLE) if(APPLE)

View file

@ -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 Release notes 1.0.5
- High-level API for blockchain explorer - High-level API for blockchain explorer

View file

@ -21,6 +21,8 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "CryptoTypes.h"
#include <boost/variant.hpp> #include <boost/variant.hpp>
namespace CryptoNote { namespace CryptoNote {
@ -32,17 +34,17 @@ enum class TransactionRemoveReason : uint8_t
}; };
struct TransactionOutputToKeyDetails { struct TransactionOutputToKeyDetails {
std::array<uint8_t, 16> txOutKey; Crypto::PublicKey txOutKey;
}; };
struct TransactionOutputMultisignatureDetails { struct TransactionOutputMultisignatureDetails {
std::vector<std::array<uint8_t, 16>> keys; std::vector<Crypto::PublicKey> keys;
uint32_t requiredSignatures; uint32_t requiredSignatures;
}; };
struct TransactionOutputDetails { struct TransactionOutputDetails {
uint64_t amount; uint64_t amount;
uint64_t globalIndex; uint32_t globalIndex;
boost::variant< boost::variant<
TransactionOutputToKeyDetails, TransactionOutputToKeyDetails,
@ -50,17 +52,17 @@ struct TransactionOutputDetails {
}; };
struct TransactionOutputReferenceDetails { struct TransactionOutputReferenceDetails {
std::array<uint8_t, 32> transactionHash; Crypto::Hash transactionHash;
size_t number; size_t number;
}; };
struct TransactionInputGenerateDetails { struct TransactionInputGenerateDetails {
uint64_t height; uint32_t height;
}; };
struct TransactionInputToKeyDetails { struct TransactionInputToKeyDetails {
std::vector<uint64_t> keyOffsets; std::vector<uint32_t> outputIndexes;
std::array<uint8_t, 16> keyImage; Crypto::KeyImage keyImage;
uint64_t mixin; uint64_t mixin;
TransactionOutputReferenceDetails output; TransactionOutputReferenceDetails output;
}; };
@ -81,13 +83,13 @@ struct TransactionInputDetails {
struct TransactionExtraDetails { struct TransactionExtraDetails {
std::vector<size_t> padding; 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<std::string> nonce;
std::vector<uint8_t> raw; std::vector<uint8_t> raw;
}; };
struct TransactionDetails { struct TransactionDetails {
std::array<uint8_t, 32> hash; Crypto::Hash hash;
uint64_t size; uint64_t size;
uint64_t fee; uint64_t fee;
uint64_t totalInputsAmount; uint64_t totalInputsAmount;
@ -95,12 +97,12 @@ struct TransactionDetails {
uint64_t mixin; uint64_t mixin;
uint64_t unlockTime; uint64_t unlockTime;
uint64_t timestamp; uint64_t timestamp;
std::array<uint8_t, 32> paymentId; Crypto::Hash paymentId;
bool inBlockchain; bool inBlockchain;
std::array<uint8_t, 32> blockHash; Crypto::Hash blockHash;
uint64_t blockHeight; uint32_t blockHeight;
TransactionExtraDetails extra; 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<TransactionInputDetails> inputs;
std::vector<TransactionOutputDetails> outputs; std::vector<TransactionOutputDetails> outputs;
}; };
@ -109,11 +111,11 @@ struct BlockDetails {
uint8_t majorVersion; uint8_t majorVersion;
uint8_t minorVersion; uint8_t minorVersion;
uint64_t timestamp; uint64_t timestamp;
std::array<uint8_t, 32> prevBlockHash; Crypto::Hash prevBlockHash;
uint32_t nonce; uint32_t nonce;
bool isOrphaned; bool isOrphaned;
uint64_t height; uint32_t height;
std::array<uint8_t, 32> hash; Crypto::Hash hash;
uint64_t difficulty; uint64_t difficulty;
uint64_t reward; uint64_t reward;
uint64_t baseReward; uint64_t baseReward;

114
include/CryptoNote.h Normal file
View 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>;
}

View file

@ -17,18 +17,32 @@
#pragma once #pragma once
#include <sstream> #include <cstdint>
#include "json_archive.h"
namespace serialization { namespace Crypto {
template<class T> struct Hash {
std::string dump_json(T &v) uint8_t data[32];
{
std::stringstream ostr;
json_archive<true> oar(ostr);
assert(serialization::serialize(oar, v));
return ostr.str();
}; };
} // 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];
};
}

View file

@ -29,7 +29,7 @@ public:
virtual ~IBlockchainObserver() {} virtual ~IBlockchainObserver() {}
virtual void blockchainUpdated(const std::vector<BlockDetails>& newBlocks, const std::vector<BlockDetails>& orphanedBlocks) {} 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) {} virtual void blockchainSynchronized(const BlockDetails& topBlock) {}
}; };
@ -44,13 +44,16 @@ public:
virtual void init() = 0; virtual void init() = 0;
virtual void shutdown() = 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<uint32_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<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 getBlockchainTop(BlockDetails& topBlock) = 0;
virtual bool getTransactions(const std::vector<std::array<uint8_t, 32>>& transactionHashes, std::vector<TransactionDetails>& transactions) = 0; virtual bool getTransactions(const std::vector<Crypto::Hash>& 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 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 getRewardBlocksWindow() = 0;
virtual uint64_t getFullRewardMaxBlockSize(uint8_t majorVersion) = 0; virtual uint64_t getFullRewardMaxBlockSize(uint8_t majorVersion) = 0;

View file

@ -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
View file

@ -23,11 +23,12 @@
#include <vector> #include <vector>
#include "crypto/crypto.h" #include "crypto/crypto.h"
#include "cryptonote_core/cryptonote_basic.h" #include "CryptoNoteCore/CryptoNoteBasic.h"
#include "cryptonote_protocol/cryptonote_protocol_defs.h" #include "CryptoNoteProtocol/CryptoNoteProtocolDefinitions.h"
#include "rpc/core_rpc_server_commands_defs.h" #include "Rpc/CoreRpcServerCommandsDefinitions.h"
#include "BlockchainExplorerData.h" #include "BlockchainExplorerData.h"
#include "ITransaction.h"
namespace CryptoNote { namespace CryptoNote {
@ -35,15 +36,15 @@ class INodeObserver {
public: public:
virtual ~INodeObserver() {} virtual ~INodeObserver() {}
virtual void peerCountUpdated(size_t count) {} virtual void peerCountUpdated(size_t count) {}
virtual void localBlockchainUpdated(uint64_t height) {} virtual void localBlockchainUpdated(uint32_t height) {}
virtual void lastKnownBlockHeightUpdated(uint64_t height) {} virtual void lastKnownBlockHeightUpdated(uint32_t height) {}
virtual void poolChanged() {} virtual void poolChanged() {}
virtual void blockchainSynchronized(uint64_t topHeight) {} virtual void blockchainSynchronized(uint32_t topHeight) {}
}; };
struct OutEntry { struct OutEntry {
uint64_t outGlobalIndex; uint32_t outGlobalIndex;
crypto::public_key outKey; Crypto::PublicKey outKey;
}; };
struct OutsForAmount { struct OutsForAmount {
@ -51,10 +52,16 @@ struct OutsForAmount {
std::vector<OutEntry> outs; std::vector<OutEntry> outs;
}; };
struct BlockCompleteEntry { struct TransactionShortInfo {
crypto::hash blockHash; Crypto::Hash txId;
CryptoNote::blobdata block; TransactionPrefix txPrefix;
std::list<CryptoNote::blobdata> txs; };
struct BlockShortEntry {
Crypto::Hash blockHash;
bool hasBlock;
CryptoNote::Block block;
std::vector<TransactionShortInfo> txsShortInfo;
}; };
class INode { class INode {
@ -69,22 +76,26 @@ public:
virtual bool shutdown() = 0; virtual bool shutdown() = 0;
virtual size_t getPeerCount() const = 0; virtual size_t getPeerCount() const = 0;
virtual uint64_t getLastLocalBlockHeight() const = 0; virtual uint32_t getLastLocalBlockHeight() const = 0;
virtual uint64_t getLastKnownBlockHeight() const = 0; virtual uint32_t getLastKnownBlockHeight() const = 0;
virtual uint64_t getLocalBlockCount() const = 0; virtual uint32_t getLocalBlockCount() const = 0;
virtual uint64_t getKnownBlockCount() const = 0; virtual uint32_t getKnownBlockCount() const = 0;
virtual uint64_t getLastLocalBlockTimestamp() const = 0; virtual uint64_t getLastLocalBlockTimestamp() const = 0;
virtual void relayTransaction(const Transaction& transaction, const Callback& callback) = 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 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 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<uint64_t>& outsGlobalIndices, const Callback& callback) = 0; virtual void getTransactionOutsGlobalIndices(const Crypto::Hash& transactionHash, std::vector<uint32_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 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>&& 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 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<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(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(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; virtual void isSynchronized(bool& syncStatus, const Callback& callback) = 0;
}; };

106
include/ITransaction.h Normal file → Executable file
View file

@ -19,64 +19,27 @@
#include <array> #include <array>
#include <cstdint> #include <cstdint>
#include <string>
#include <vector> #include <vector>
#include "CryptoNote.h"
namespace CryptoNote { 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 { namespace TransactionTypes {
enum class InputType : uint8_t { Invalid, Key, Multisignature, Generating }; enum class InputType : uint8_t { Invalid, Key, Multisignature, Generating };
enum class OutputType : uint8_t { Invalid, Key, Multisignature }; 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 { struct GlobalOutput {
PublicKey targetKey; Crypto::PublicKey targetKey;
uint64_t outputIndex; uint32_t outputIndex;
}; };
typedef std::vector<GlobalOutput> GlobalOutputsContainer; typedef std::vector<GlobalOutput> GlobalOutputsContainer;
struct OutputKeyInfo { struct OutputKeyInfo {
PublicKey transactionPublicKey; Crypto::PublicKey transactionPublicKey;
size_t transactionIndex; size_t transactionIndex;
size_t outputInTransaction; size_t outputInTransaction;
}; };
@ -86,12 +49,6 @@ namespace TransactionTypes {
GlobalOutputsContainer outputs; GlobalOutputsContainer outputs;
OutputKeyInfo realOutput; OutputKeyInfo realOutput;
}; };
struct KeyPair {
PublicKey publicKey;
SecretKey secretKey;
};
} }
// //
@ -101,33 +58,34 @@ class ITransactionReader {
public: public:
virtual ~ITransactionReader() { } virtual ~ITransactionReader() { }
virtual Hash getTransactionHash() const = 0; virtual Crypto::Hash getTransactionHash() const = 0;
virtual Hash getTransactionPrefixHash() const = 0; virtual Crypto::Hash getTransactionPrefixHash() const = 0;
virtual PublicKey getTransactionPublicKey() const = 0; virtual Crypto::PublicKey getTransactionPublicKey() const = 0;
virtual bool getTransactionSecretKey(Crypto::SecretKey& key) const = 0;
virtual uint64_t getUnlockTime() const = 0; virtual uint64_t getUnlockTime() const = 0;
// extra // extra
virtual bool getPaymentId(Hash& paymentId) const = 0; virtual bool getPaymentId(Crypto::Hash& paymentId) const = 0;
virtual bool getExtraNonce(std::string& nonce) const = 0; virtual bool getExtraNonce(BinaryArray& nonce) const = 0;
virtual Blob getExtra() const = 0; virtual BinaryArray getExtra() const = 0;
// inputs // inputs
virtual size_t getInputCount() const = 0; virtual size_t getInputCount() const = 0;
virtual uint64_t getInputTotalAmount() const = 0; virtual uint64_t getInputTotalAmount() const = 0;
virtual TransactionTypes::InputType getInputType(size_t index) 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, KeyInput& input) const = 0;
virtual void getInput(size_t index, TransactionTypes::InputMultisignature& input) const = 0; virtual void getInput(size_t index, MultisignatureInput& input) const = 0;
// outputs // outputs
virtual size_t getOutputCount() const = 0; virtual size_t getOutputCount() const = 0;
virtual uint64_t getOutputTotalAmount() const = 0; virtual uint64_t getOutputTotalAmount() const = 0;
virtual TransactionTypes::OutputType getOutputType(size_t index) 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, KeyOutput& output, uint64_t& amount) const = 0;
virtual void getOutput(size_t index, TransactionTypes::OutputMultisignature& output) const = 0; virtual void getOutput(size_t index, MultisignatureOutput& output, uint64_t& amount) const = 0;
// signatures // signatures
virtual size_t getRequiredSignaturesCount(size_t inputIndex) const = 0; 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 // various checks
virtual bool validateInputs() const = 0; virtual bool validateInputs() const = 0;
@ -135,7 +93,7 @@ public:
virtual bool validateSignatures() const = 0; virtual bool validateSignatures() const = 0;
// serialized transaction // serialized transaction
virtual Blob getTransactionData() const = 0; virtual BinaryArray getTransactionData() const = 0;
}; };
// //
@ -150,25 +108,27 @@ public:
virtual void setUnlockTime(uint64_t unlockTime) = 0; virtual void setUnlockTime(uint64_t unlockTime) = 0;
// extra // extra
virtual void setPaymentId(const Hash& paymentId) = 0; virtual void setPaymentId(const Crypto::Hash& paymentId) = 0;
virtual void setExtraNonce(const std::string& nonce) = 0; virtual void setExtraNonce(const BinaryArray& nonce) = 0;
virtual void appendExtra(const Blob& extraData) = 0; virtual void appendExtra(const BinaryArray& extraData) = 0;
// Inputs/Outputs // Inputs/Outputs
virtual size_t addInput(const TransactionTypes::InputKey& input) = 0; virtual size_t addInput(const KeyInput& input) = 0;
virtual size_t addInput(const AccountKeys& senderKeys, const TransactionTypes::InputKeyInfo& info, TransactionTypes::KeyPair& ephKeys) = 0; virtual size_t addInput(const MultisignatureInput& input) = 0;
virtual size_t addInput(const TransactionTypes::InputMultisignature& 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 AccountPublicAddress& 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 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 // transaction info
virtual bool getTransactionSecretKey(SecretKey& key) const = 0; virtual void setTransactionSecretKey(const Crypto::SecretKey& key) = 0;
virtual void setTransactionSecretKey(const SecretKey& key) = 0;
// signing // signing
virtual void signInputKey(size_t input, const TransactionTypes::InputKeyInfo& info, const TransactionTypes::KeyPair& ephKeys) = 0; virtual void signInputKey(size_t input, const TransactionTypes::InputKeyInfo& info, const KeyPair& ephKeys) = 0;
virtual void signInputMultisignature(size_t input, const PublicKey& sourceTransactionKey, size_t outputIndex, const AccountKeys& accountKeys) = 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 : class ITransaction :

View file

@ -27,19 +27,19 @@
namespace CryptoNote { 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 { struct TransactionInformation {
// transaction info // transaction info
Hash transactionHash; Crypto::Hash transactionHash;
PublicKey publicKey; Crypto::PublicKey publicKey;
uint64_t blockHeight; uint32_t blockHeight;
uint64_t timestamp; uint64_t timestamp;
uint64_t unlockTime; uint64_t unlockTime;
uint64_t totalAmountIn; uint64_t totalAmountIn;
uint64_t totalAmountOut; uint64_t totalAmountOut;
std::vector<uint8_t> extra; std::vector<uint8_t> extra;
Hash paymentId; Crypto::Hash paymentId;
}; };
@ -47,24 +47,24 @@ struct TransactionOutputInformation {
// output info // output info
TransactionTypes::OutputType type; TransactionTypes::OutputType type;
uint64_t amount; uint64_t amount;
uint64_t globalOutputIndex; uint32_t globalOutputIndex;
uint32_t outputInTransaction; uint32_t outputInTransaction;
// transaction info // transaction info
Hash transactionHash; Crypto::Hash transactionHash;
PublicKey transactionPublicKey; Crypto::PublicKey transactionPublicKey;
union { union {
PublicKey outputKey; // Type: Key Crypto::PublicKey outputKey; // Type: Key
uint32_t requiredSignatures; // Type: Multisignature uint32_t requiredSignatures; // Type: Multisignature
}; };
}; };
struct TransactionSpentOutputInformation: public TransactionOutputInformation { struct TransactionSpentOutputInformation: public TransactionOutputInformation {
uint64_t spendingBlockHeight; uint32_t spendingBlockHeight;
uint64_t timestamp; uint64_t timestamp;
Hash spendingTransactionHash; Crypto::Hash spendingTransactionHash;
KeyImage keyImage; //!< \attention Used only for TransactionTypes::OutputType::Key Crypto::KeyImage keyImage; //!< \attention Used only for TransactionTypes::OutputType::Key
uint32_t inputInTransaction; uint32_t inputInTransaction;
}; };
@ -96,9 +96,9 @@ public:
virtual size_t transactionsCount() = 0; virtual size_t transactionsCount() = 0;
virtual uint64_t balance(uint32_t flags = IncludeDefault) = 0; virtual uint64_t balance(uint32_t flags = IncludeDefault) = 0;
virtual void getOutputs(std::vector<TransactionOutputInformation>& transfers, 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 bool getTransactionInformation(const Crypto::Hash& transactionHash, TransactionInformation& info, int64_t& txBalance) = 0;
virtual std::vector<TransactionOutputInformation> getTransactionOutputs(const Hash& transactionHash, uint32_t flags = IncludeDefault) = 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 void getUnconfirmedTransactions(std::vector<Crypto::Hash>& transactions) = 0;
virtual std::vector<TransactionSpentOutputInformation> getSpentOutputs() = 0; virtual std::vector<TransactionSpentOutputInformation> getSpentOutputs() = 0;
}; };

View file

@ -42,22 +42,23 @@ class ITransfersSubscription;
class ITransfersObserver { class ITransfersObserver {
public: public:
virtual void onError(ITransfersSubscription* object, 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 * \note The sender must guarantee that onTransactionDeleted() is called only after onTransactionUpdated() is called
* for the same \a transactionHash. * 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 > { class ITransfersSubscription : public IObservable < ITransfersObserver > {
public: public:
virtual ~ITransfersSubscription() {} virtual ~ITransfersSubscription() {}
virtual AccountAddress getAddress() = 0; virtual AccountPublicAddress getAddress() = 0;
virtual ITransfersContainer& getContainer() = 0; virtual ITransfersContainer& getContainer() = 0;
}; };
@ -66,10 +67,10 @@ public:
virtual ~ITransfersSynchronizer() {} virtual ~ITransfersSynchronizer() {}
virtual ITransfersSubscription& addSubscription(const AccountSubscription& acc) = 0; virtual ITransfersSubscription& addSubscription(const AccountSubscription& acc) = 0;
virtual bool removeSubscription(const AccountAddress& acc) = 0; virtual bool removeSubscription(const AccountPublicAddress& acc) = 0;
virtual void getSubscriptions(std::vector<AccountAddress>& subscriptions) = 0; virtual void getSubscriptions(std::vector<AccountPublicAddress>& subscriptions) = 0;
// returns nullptr if address is not found // 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
View file

@ -17,113 +17,99 @@
#pragma once #pragma once
#include <array>
#include <cstdint>
#include <istream>
#include <limits> #include <limits>
#include <ostream>
#include <string> #include <string>
#include <system_error>
#include <vector> #include <vector>
#include "CryptoNote.h"
namespace CryptoNote { namespace CryptoNote {
typedef size_t TransactionId; const size_t WALLET_INVALID_TRANSACTION_ID = std::numeric_limits<size_t>::max();
typedef size_t TransferId; const size_t WALLET_INVALID_TRANSFER_ID = std::numeric_limits<size_t>::max();
typedef std::array<uint8_t, 32> TransactionHash; 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; std::string address;
int64_t amount; 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 { class IWallet {
public: public:
virtual ~IWallet() {} ; virtual ~IWallet() {}
virtual void addObserver(IWalletObserver* observer) = 0;
virtual void removeObserver(IWalletObserver* observer) = 0;
virtual void initAndGenerate(const std::string& password) = 0; virtual void initialize(const std::string& password) = 0;
virtual void initAndLoad(std::istream& source, const std::string& password) = 0; virtual void load(std::istream& source, const std::string& password) = 0;
virtual void initWithKeys(const WalletAccountKeys& accountKeys, const std::string& password) = 0;
virtual void shutdown() = 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 size_t getTransactionCount() const = 0;
virtual uint64_t pendingBalance() = 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 transfer(const WalletTransfer& destination, uint64_t fee, uint64_t mixIn = 0, const std::string& extra = "", uint64_t unlockTimestamp = 0) = 0;
virtual size_t getTransferCount() = 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 void start() = 0;
virtual void stop() = 0;
virtual bool getTransaction(TransactionId transactionId, TransactionInfo& transaction) = 0;
virtual bool getTransfer(TransferId transferId, Transfer& transfer) = 0;
virtual TransactionId sendTransaction(const Transfer& transfer, uint64_t fee, const std::string& extra = "", uint64_t mixIn = 0, uint64_t unlockTimestamp = 0) = 0; //blocks until an event occured
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 WalletEvent getEvent() = 0;
virtual std::error_code cancelTransaction(size_t transferId) = 0;
virtual void getAccountKeys(WalletAccountKeys& keys) = 0;
}; };
} }

116
include/IWalletLegacy.h Normal file
View 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
View file

@ -21,37 +21,69 @@
#include <functional> #include <functional>
#include <memory> #include <memory>
#include "cryptonote_core/cryptonote_format_utils.h" #include "CryptoNoteCore/CryptoNoteFormatUtils.h"
#include "CryptoNoteConfig.h"
#include "BlockchainExplorerErrors.h" #include "BlockchainExplorerErrors.h"
#include "ITransaction.h"
using namespace Logging; using namespace Logging;
using namespace Crypto;
namespace CryptoNote { namespace CryptoNote {
class ContextCounterHolder
{
public:
ContextCounterHolder(BlockchainExplorer::AsyncContextCounter& counter) : counter(counter) {}
~ContextCounterHolder() { counter.delAsyncContext(); }
private:
BlockchainExplorer::AsyncContextCounter& counter;
};
class NodeRequest { class NodeRequest {
public: public:
NodeRequest(const std::function<void(const INode::Callback&)>& request) : requestFunc(request) {} NodeRequest(const std::function<void(const INode::Callback&)>& request) : requestFunc(request) {}
std::error_code performBlocking() { std::error_code performBlocking() {
requestFunc(std::bind(&NodeRequest::completeionCallback, this, std::placeholders::_1)); std::promise<std::error_code> promise;
return promise.get_future().get(); 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) { void performAsync(BlockchainExplorer::AsyncContextCounter& asyncContextCounter, const INode::Callback& callback) {
requestFunc(callback); asyncContextCounter.addAsyncContext();
requestFunc(std::bind(&NodeRequest::asyncCompleteionCallback, callback, std::ref(asyncContextCounter), std::placeholders::_1));
} }
private: private:
void completeionCallback(std::error_code ec) { void blockingCompleteionCallback(std::promise<std::error_code> promise, std::error_code ec) {
promise.set_value(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; 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() {} BlockchainExplorer::~BlockchainExplorer() {}
@ -59,7 +91,7 @@ bool BlockchainExplorer::addObserver(IBlockchainObserver* observer) {
if (state.load() != INITIALIZED) { if (state.load() != INITIALIZED) {
throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED)); throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED));
} }
observersCounter.fetch_add(1);
return observerManager.add(observer); return observerManager.add(observer);
} }
@ -67,7 +99,9 @@ bool BlockchainExplorer::removeObserver(IBlockchainObserver* observer) {
if (state.load() != INITIALIZED) { if (state.load() != INITIALIZED) {
throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_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); return observerManager.remove(observer);
} }
@ -98,10 +132,11 @@ void BlockchainExplorer::shutdown() {
throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED)); throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED));
} }
node.removeObserver(this); node.removeObserver(this);
asyncContextCounter.waitAsyncContextsFinish();
state.store(NOT_INITIALIZED); 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) { if (state.load() != INITIALIZED) {
throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_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( std::bind(
static_cast< static_cast<
void(INode::*)( void(INode::*)(
const std::vector<uint64_t>&, const std::vector<uint32_t>&,
std::vector<std::vector<BlockDetails>>&, std::vector<std::vector<BlockDetails>>&,
const INode::Callback& const INode::Callback&
) )
@ -131,7 +166,7 @@ bool BlockchainExplorer::getBlocks(const std::vector<uint64_t>& blockHeights, st
return true; 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) { if (state.load() != INITIALIZED) {
throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_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( std::bind(
static_cast< static_cast<
void(INode::*)( void(INode::*)(
const std::vector<crypto::hash>&, const std::vector<Hash>&,
std::vector<BlockDetails>&, std::vector<BlockDetails>&,
const INode::Callback& const INode::Callback&
) )
>(&INode::getBlocks), >(&INode::getBlocks),
std::ref(node), 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::ref(blocks),
std::placeholders::_1 std::placeholders::_1
) )
@ -161,15 +196,50 @@ bool BlockchainExplorer::getBlocks(const std::vector<std::array<uint8_t, 32>>& b
return true; 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) { bool BlockchainExplorer::getBlockchainTop(BlockDetails& topBlock) {
if (state.load() != INITIALIZED) { if (state.load() != INITIALIZED) {
throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED)); throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED));
} }
logger(DEBUGGING) << "Get blockchain top request came."; 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)); heights.push_back(std::move(lastHeight));
std::vector<std::vector<BlockDetails>> blocks; std::vector<std::vector<BlockDetails>> blocks;
@ -195,49 +265,105 @@ bool BlockchainExplorer::getBlockchainTop(BlockDetails& topBlock) {
return true; 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) { if (state.load() != INITIALIZED) {
throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_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( NodeRequest request(
std::bind( std::bind(
&INode::getTransactions, static_cast<
void(INode::*)(
const std::vector<Hash>&,
std::vector<TransactionDetails>&,
const INode::Callback&
)
>(&INode::getTransactions),
std::ref(node), 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::ref(transactions),
std::placeholders::_1 std::placeholders::_1
) )
); );
std::error_code ec = request.performBlocking(); std::error_code ec = request.performBlocking();
if (ec) { 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); throw std::system_error(ec);
} }
return true; 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) { if (state.load() != INITIALIZED) {
throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED)); throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED));
} }
logger(DEBUGGING) << "Get pool state request came."; logger(DEBUGGING) << "Get pool state request came.";
std::vector<Transaction> rawNewTransactions; std::vector<std::unique_ptr<ITransactionReader>> rawNewTransactions;
NodeRequest request( NodeRequest request(
[&](const INode::Callback& callback) { [&](const INode::Callback& callback) {
std::vector<crypto::hash> hashes; std::vector<Hash> hashes;
for (const std::array<uint8_t, 32>& hash : knownPoolTransactionHashes) { for (Hash hash : knownPoolTransactionHashes) {
hashes.push_back(std::move(reinterpret_cast<const crypto::hash&>(hash))); hashes.push_back(std::move(hash));
} }
node.getPoolSymmetricDifference( node.getPoolSymmetricDifference(
std::move(hashes), std::move(hashes),
reinterpret_cast<crypto::hash&>(knownBlockchainTopHash), reinterpret_cast<Hash&>(knownBlockchainTopHash),
isBlockchainActual, isBlockchainActual,
rawNewTransactions, rawNewTransactions,
reinterpret_cast<std::vector<crypto::hash>&>(removedTransactions), removedTransactions,
callback callback
); );
} }
@ -248,10 +374,10 @@ bool BlockchainExplorer::getPoolState(const std::vector<std::array<uint8_t, 32>>
throw std::system_error(ec); throw std::system_error(ec);
} }
std::vector<std::array<uint8_t, 32>> newTransactionsHashes; std::vector<Hash> newTransactionsHashes;
for (const Transaction& rawTransaction : rawNewTransactions) { for (const auto& rawTransaction : rawNewTransactions) {
crypto::hash transactionHash = get_transaction_hash(rawTransaction); Hash transactionHash = rawTransaction->getTransactionHash();
newTransactionsHashes.push_back(std::move(reinterpret_cast<const std::array<uint8_t, 32>&>(transactionHash))); newTransactionsHashes.push_back(std::move(transactionHash));
} }
return getTransactions(newTransactionsHashes, newTransactions); return getTransactions(newTransactionsHashes, newTransactions);
@ -295,27 +421,32 @@ bool BlockchainExplorer::isSynchronized() {
logger(ERROR) << "Can't get synchronization status: " << ec.message(); logger(ERROR) << "Can't get synchronization status: " << ec.message();
throw std::system_error(ec); throw std::system_error(ec);
} }
synchronized.store(syncStatus);
return syncStatus; return syncStatus;
} }
void BlockchainExplorer::poolChanged() { void BlockchainExplorer::poolChanged() {
logger(DEBUGGING) << "Got poolChanged notification."; logger(DEBUGGING) << "Got poolChanged notification.";
if (!synchronized.load() || observersCounter.load() == 0) {
return;
}
std::unique_lock<std::mutex> lock(mutex); 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<std::unique_ptr<ITransactionReader>>> rawNewTransactionsPtr = std::make_shared<std::vector<std::unique_ptr<ITransactionReader>>>();
std::shared_ptr<std::vector<crypto::hash>> removedTransactionsPtr = std::make_shared<std::vector<crypto::hash>>(); std::shared_ptr<std::vector<Hash>> removedTransactionsPtr = std::make_shared<std::vector<Hash>>();
std::shared_ptr<bool> isBlockchainActualPtr = std::make_shared<bool>(false); std::shared_ptr<bool> isBlockchainActualPtr = std::make_shared<bool>(false);
NodeRequest request( NodeRequest request(
[this, rawNewTransactionsPtr, removedTransactionsPtr, isBlockchainActualPtr](const INode::Callback& callback) { [this, rawNewTransactionsPtr, removedTransactionsPtr, isBlockchainActualPtr](const INode::Callback& callback) {
std::vector<crypto::hash> hashes; std::vector<Hash> hashes;
for (const crypto::hash& hash : knownPoolState) { for (const Hash& hash : knownPoolState) {
hashes.push_back(std::move(hash)); hashes.push_back(std::move(hash));
} }
node.getPoolSymmetricDifference( node.getPoolSymmetricDifference(
std::move(hashes), std::move(hashes),
reinterpret_cast<crypto::hash&>(knownBlockchainTop.hash), reinterpret_cast<Hash&>(knownBlockchainTop.hash),
*isBlockchainActualPtr, *isBlockchainActualPtr,
*rawNewTransactionsPtr, *rawNewTransactionsPtr,
*removedTransactionsPtr, *removedTransactionsPtr,
@ -323,7 +454,7 @@ void BlockchainExplorer::poolChanged() {
); );
} }
); );
request.performAsync( request.performAsync(asyncContextCounter,
[this, rawNewTransactionsPtr, removedTransactionsPtr, isBlockchainActualPtr](std::error_code ec) { [this, rawNewTransactionsPtr, removedTransactionsPtr, isBlockchainActualPtr](std::error_code ec) {
if (ec) { if (ec) {
logger(ERROR) << "Can't send poolChanged notification because can't get pool symmetric difference: " << ec.message(); 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::unique_lock<std::mutex> lock(mutex);
std::shared_ptr<std::vector<crypto::hash>> newTransactionsHashesPtr = std::make_shared<std::vector<crypto::hash>>(); std::shared_ptr<std::vector<Hash>> newTransactionsHashesPtr = std::make_shared<std::vector<Hash>>();
for (const Transaction& rawTransaction : *rawNewTransactionsPtr) { for (const auto& rawTransaction : *rawNewTransactionsPtr) {
crypto::hash transactionHash = get_transaction_hash(rawTransaction); auto hash = rawTransaction->getTransactionHash();
Hash transactionHash = reinterpret_cast<const Hash&>(hash);
bool inserted = knownPoolState.emplace(transactionHash).second; bool inserted = knownPoolState.emplace(transactionHash).second;
if (inserted) { if (inserted) {
newTransactionsHashesPtr->push_back(std::move(transactionHash)); 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>>>(); std::shared_ptr<std::vector<std::pair<Hash, TransactionRemoveReason>>> removedTransactionsHashesPtr = std::make_shared<std::vector<std::pair<Hash, TransactionRemoveReason>>>();
for (const crypto::hash hash : *removedTransactionsPtr) { for (const Hash hash : *removedTransactionsPtr) {
auto iter = knownPoolState.find(hash); auto iter = knownPoolState.find(hash);
if (iter != knownPoolState.end()) { if (iter != knownPoolState.end()) {
removedTransactionsHashesPtr->push_back( removedTransactionsHashesPtr->push_back(
std::move(std::make_pair( 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. 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>>(); std::shared_ptr<std::vector<TransactionDetails>> newTransactionsPtr = std::make_shared<std::vector<TransactionDetails>>();
NodeRequest request( NodeRequest request(
std::bind( std::bind(
&INode::getTransactions, static_cast<
void(INode::*)(
const std::vector<Hash>&,
std::vector<TransactionDetails>&,
const INode::Callback&
)
>(&INode::getTransactions),
std::ref(node), std::ref(node),
std::cref(*newTransactionsHashesPtr), std::cref(*newTransactionsHashesPtr),
std::ref(*newTransactionsPtr), std::ref(*newTransactionsPtr),
std::placeholders::_1 std::placeholders::_1
) )
); );
request.performAsync( request.performAsync(asyncContextCounter,
[this, newTransactionsHashesPtr, newTransactionsPtr, removedTransactionsHashesPtr](std::error_code ec) { [this, newTransactionsHashesPtr, newTransactionsPtr, removedTransactionsHashesPtr](std::error_code ec) {
if (ec) { if (ec) {
logger(ERROR) << "Can't send poolChanged notification because can't get transactions: " << ec.message(); 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."; 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>>>(); std::shared_ptr<std::vector<std::vector<BlockDetails>>> blocksPtr = std::make_shared<std::vector<std::vector<BlockDetails>>>();
blockHeightsPtr->push_back(topHeight); blockHeightsPtr->push_back(topHeight);
@ -398,7 +542,7 @@ void BlockchainExplorer::blockchainSynchronized(uint64_t topHeight) {
std::bind( std::bind(
static_cast< static_cast<
void(INode::*)( void(INode::*)(
const std::vector<uint64_t>&, const std::vector<uint32_t>&,
std::vector<std::vector<BlockDetails>>&, std::vector<std::vector<BlockDetails>>&,
const INode::Callback& 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) { [this, blockHeightsPtr, blocksPtr, topHeight](std::error_code ec) {
if (ec) { if (ec) {
logger(ERROR) << "Can't send blockchainSynchronized notification because can't get blocks by height: " << ec.message(); 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."; logger(DEBUGGING) << "Got localBlockchainUpdated notification.";
if (observersCounter.load() == 0) {
knownBlockchainTopHeight = height;
return;
}
std::unique_lock<std::mutex> lock(mutex); std::unique_lock<std::mutex> lock(mutex);
assert(height >= knownBlockchainTopHeight); 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>>>(); 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); blockHeightsPtr->push_back(i);
} }
@ -459,7 +608,7 @@ void BlockchainExplorer::localBlockchainUpdated(uint64_t height) {
std::bind( std::bind(
static_cast< static_cast<
void(INode::*)( void(INode::*)(
const std::vector<uint64_t>&, const std::vector<uint32_t>&,
std::vector<std::vector<BlockDetails>>&, std::vector<std::vector<BlockDetails>>&,
const INode::Callback& 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) { [this, blockHeightsPtr, blocksPtr](std::error_code ec) {
if (ec) { if (ec) {
logger(ERROR) << "Can't send blockchainUpdated notification because can't get blocks by height: " << ec.message(); 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
View file

@ -27,6 +27,8 @@
#include "Common/ObserverManager.h" #include "Common/ObserverManager.h"
#include "BlockchainExplorerErrors.h" #include "BlockchainExplorerErrors.h"
#include "Wallet/WalletAsyncContextCounter.h"
#include "Logging/LoggerRef.h" #include "Logging/LoggerRef.h"
namespace CryptoNote { namespace CryptoNote {
@ -46,13 +48,16 @@ public:
virtual bool addObserver(IBlockchainObserver* observer) override; virtual bool addObserver(IBlockchainObserver* observer) override;
virtual bool removeObserver(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<uint32_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<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 getBlockchainTop(BlockDetails& topBlock) override;
virtual bool getTransactions(const std::vector<std::array<uint8_t, 32>>& transactionHashes, std::vector<TransactionDetails>& transactions) override; virtual bool getTransactions(const std::vector<Crypto::Hash>& 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 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 getRewardBlocksWindow() override;
virtual uint64_t getFullRewardMaxBlockSize(uint8_t majorVersion) override; virtual uint64_t getFullRewardMaxBlockSize(uint8_t majorVersion) override;
@ -63,8 +68,10 @@ public:
virtual void shutdown() override; virtual void shutdown() override;
virtual void poolChanged() override; virtual void poolChanged() override;
virtual void blockchainSynchronized(uint64_t topHeight) override; virtual void blockchainSynchronized(uint32_t topHeight) override;
virtual void localBlockchainUpdated(uint64_t height) override; virtual void localBlockchainUpdated(uint32_t height) override;
typedef WalletAsyncContextCounter AsyncContextCounter;
private: private:
enum State { enum State {
@ -73,16 +80,20 @@ private:
}; };
BlockDetails knownBlockchainTop; BlockDetails knownBlockchainTop;
uint64_t knownBlockchainTopHeight; uint32_t knownBlockchainTopHeight;
std::unordered_set<crypto::hash> knownPoolState; std::unordered_set<Crypto::Hash> knownPoolState;
std::atomic<State> state; std::atomic<State> state;
tools::ObserverManager<IBlockchainObserver> observerManager; std::atomic<bool> synchronized;
std::atomic<uint32_t> observersCounter;
Tools::ObserverManager<IBlockchainObserver> observerManager;
std::mutex mutex; std::mutex mutex;
INode& node; INode& node;
Logging::LoggerRef logger; Logging::LoggerRef logger;
AsyncContextCounter asyncContextCounter;
}; };
} }

245
src/BlockchainExplorer/BlockchainExplorerDataBuilder.cpp Normal file → Executable file
View file

@ -21,23 +21,25 @@
#include <boost/range/combine.hpp> #include <boost/range/combine.hpp>
#include "Common/StringTools.h" #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 { namespace CryptoNote {
BlockchainExplorerDataBuilder::BlockchainExplorerDataBuilder(CryptoNote::ICore& core, CryptoNote::ICryptonoteProtocolQuery& protocol) : BlockchainExplorerDataBuilder::BlockchainExplorerDataBuilder(CryptoNote::ICore& core, CryptoNote::ICryptoNoteProtocolQuery& protocol) :
core(core), core(core),
protocol(protocol) protocol(protocol) {
{
} }
bool BlockchainExplorerDataBuilder::getMixin(const Transaction& transaction, uint64_t& mixin) { bool BlockchainExplorerDataBuilder::getMixin(const Transaction& transaction, uint64_t& mixin) {
mixin = 0; mixin = 0;
for (const TransactionInput& txin : transaction.vin) { for (const TransactionInput& txin : transaction.inputs) {
if (txin.type() != typeid(TransactionInputToKey)) { if (txin.type() != typeid(KeyInput)) {
continue; continue;
} }
uint64_t currentMixin = boost::get<TransactionInputToKey>(txin).keyOffsets.size(); uint64_t currentMixin = boost::get<KeyInput>(txin).outputIndexes.size();
if (currentMixin > mixin) { if (currentMixin > mixin) {
mixin = currentMixin; mixin = currentMixin;
} }
@ -45,75 +47,71 @@ bool BlockchainExplorerDataBuilder::getMixin(const Transaction& transaction, uin
return true; return true;
} }
bool BlockchainExplorerDataBuilder::getPaymentId(const Transaction& transaction, crypto::hash& paymentId) { bool BlockchainExplorerDataBuilder::getPaymentId(const Transaction& transaction, Crypto::Hash& paymentId) {
std::vector<tx_extra_field> txExtraFields; std::vector<TransactionExtraField> txExtraFields;
parse_tx_extra(transaction.extra, txExtraFields); parseTransactionExtra(transaction.extra, txExtraFields);
tx_extra_nonce extraNonce; TransactionExtraNonce extraNonce;
if (!find_tx_extra_field_by_type(txExtraFields, extraNonce)) { if (!findTransactionExtraFieldByType(txExtraFields, extraNonce)) {
return false; 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) { bool BlockchainExplorerDataBuilder::fillTxExtra(const std::vector<uint8_t>& rawExtra, TransactionExtraDetails& extraDetails) {
extraDetails.raw = rawExtra; extraDetails.raw = rawExtra;
std::vector<tx_extra_field> txExtraFields; std::vector<TransactionExtraField> txExtraFields;
parse_tx_extra(rawExtra, txExtraFields); parseTransactionExtra(rawExtra, txExtraFields);
for (const tx_extra_field& field : txExtraFields) { for (const TransactionExtraField& field : txExtraFields) {
if (typeid(tx_extra_padding) == field.type()) { if (typeid(TransactionExtraPadding) == field.type()) {
extraDetails.padding.push_back(std::move(boost::get<tx_extra_padding>(field).size)); extraDetails.padding.push_back(std::move(boost::get<TransactionExtraPadding>(field).size));
} } else if (typeid(TransactionExtraPublicKey) == field.type()) {
else if (typeid(tx_extra_pub_key) == field.type()) { extraDetails.publicKey.push_back(std::move(boost::get<TransactionExtraPublicKey>(field).publicKey));
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(TransactionExtraNonce) == field.type()) {
} extraDetails.nonce.push_back(std::move(Common::toHex(boost::get<TransactionExtraNonce>(field).nonce.data(), boost::get<TransactionExtraNonce>(field).nonce.size())));
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())));
} }
} }
return true; return true;
} }
size_t BlockchainExplorerDataBuilder::median(std::vector<size_t>& v) { size_t BlockchainExplorerDataBuilder::median(std::vector<size_t>& v) {
if(v.empty()) if (v.empty())
return boost::value_initialized<size_t>(); return boost::value_initialized<size_t>();
if(v.size() == 1) if (v.size() == 1)
return v[0]; return v[0];
size_t n = (v.size()) / 2; size_t n = (v.size()) / 2;
std::sort(v.begin(), v.end()); std::sort(v.begin(), v.end());
//nth_element(v.begin(), v.begin()+n-1, v.end()); //nth_element(v.begin(), v.begin()+n-1, v.end());
if(v.size()%2) if (v.size() % 2) {//1, 3, 5...
{//1, 3, 5...
return v[n]; return v[n];
}else } else {//2, 4, 6...
{//2, 4, 6... return (v[n - 1] + v[n]) / 2;
return (v[n-1] + v[n])/2;
} }
} }
bool BlockchainExplorerDataBuilder::fillBlockDetails(const Block &block, BlockDetails& blockDetails) { 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.majorVersion = block.majorVersion;
blockDetails.minorVersion = block.minorVersion; blockDetails.minorVersion = block.minorVersion;
blockDetails.timestamp = block.timestamp; 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.nonce = block.nonce;
blockDetails.hash = reinterpret_cast<const std::array<uint8_t, 32>&>(hash); blockDetails.hash = hash;
blockDetails.reward = 0; blockDetails.reward = 0;
for (const TransactionOutput& out : block.minerTx.vout) { for (const TransactionOutput& out : block.baseTransaction.outputs) {
blockDetails.reward += out.amount; blockDetails.reward += out.amount;
} }
if (block.minerTx.vin.front().type() != typeid(TransactionInputGenerate)) if (block.baseTransaction.inputs.front().type() != typeid(BaseInput))
return false; return false;
blockDetails.height = boost::get<TransactionInputGenerate>(block.minerTx.vin.front()).height; blockDetails.height = boost::get<BaseInput>(block.baseTransaction.inputs.front()).blockIndex;
crypto::hash tmpHash = core.getBlockIdByHeight(blockDetails.height); Crypto::Hash tmpHash = core.getBlockIdByHeight(blockDetails.height);
blockDetails.isOrphaned = hash != tmpHash; blockDetails.isOrphaned = hash != tmpHash;
if (!core.getBlockDifficulty(blockDetails.height, blockDetails.difficulty)) { if (!core.getBlockDifficulty(blockDetails.height, blockDetails.difficulty)) {
return false; return false;
} }
@ -130,20 +128,21 @@ bool BlockchainExplorerDataBuilder::fillBlockDetails(const Block &block, BlockDe
} }
blockDetails.transactionsCumulativeSize = blockSize; blockDetails.transactionsCumulativeSize = blockSize;
size_t blokBlobSize = get_object_blobsize(block); size_t blokBlobSize = getObjectBinarySize(block);
size_t minerTxBlobSize = get_object_blobsize(block.minerTx); size_t minerTxBlobSize = getObjectBinarySize(block.baseTransaction);
blockDetails.blockSize = blokBlobSize + blockDetails.transactionsCumulativeSize - minerTxBlobSize; blockDetails.blockSize = blokBlobSize + blockDetails.transactionsCumulativeSize - minerTxBlobSize;
if (!core.getAlreadyGeneratedCoins(hash, blockDetails.alreadyGeneratedCoins)) { if (!core.getAlreadyGeneratedCoins(hash, blockDetails.alreadyGeneratedCoins)) {
return false; return false;
} }
blockDetails.alreadyGeneratedTransactions = 0; //TODO if (!core.getGeneratedTransactionsNumber(blockDetails.height, blockDetails.alreadyGeneratedTransactions)) {
return false;
}
uint64_t prevBlockGeneratedCoins = 0; uint64_t prevBlockGeneratedCoins = 0;
if (blockDetails.height > 0) if (blockDetails.height > 0) {
{ if (!core.getAlreadyGeneratedCoins(block.previousBlockHash, prevBlockGeneratedCoins)) {
if (!core.getAlreadyGeneratedCoins(block.prevId, prevBlockGeneratedCoins)) {
return false; return false;
} }
} }
@ -151,45 +150,40 @@ bool BlockchainExplorerDataBuilder::fillBlockDetails(const Block &block, BlockDe
uint64_t currentReward = 0; uint64_t currentReward = 0;
int64_t emissionChange = 0; int64_t emissionChange = 0;
bool penalizeFee = block.majorVersion >= 2; 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; 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; return false;
} }
blockDetails.baseReward = maxReward; blockDetails.baseReward = maxReward;
if (maxReward == 0 && currentReward == 0) if (maxReward == 0 && currentReward == 0) {
{
blockDetails.penalty = static_cast<double>(0); blockDetails.penalty = static_cast<double>(0);
} } else {
else
{
if (maxReward < currentReward) { if (maxReward < currentReward) {
return false; return false;
} }
blockDetails.penalty = static_cast<double>(maxReward - currentReward) / static_cast<double>(maxReward); 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; TransactionDetails transactionDetails;
if (!fillTransactionDetails(block.minerTx, transactionDetails, block.timestamp)) { if (!fillTransactionDetails(block.baseTransaction, transactionDetails, block.timestamp)) {
return false; return false;
} }
blockDetails.transactions.push_back(std::move(transactionDetails)); blockDetails.transactions.push_back(std::move(transactionDetails));
std::list<Transaction> found; std::list<Transaction> found;
std::list<crypto::hash> missed; std::list<Crypto::Hash> missed;
core.getTransactions(block.txHashes, found, missed); core.getTransactions(block.transactionHashes, found, missed, blockDetails.isOrphaned);
if (found.size() != block.txHashes.size()) { if (found.size() != block.transactionHashes.size()) {
return false; return false;
} }
blockDetails.totalFeeAmount = 0; blockDetails.totalFeeAmount = 0;
for (const Transaction& tx : found) { for (const Transaction& tx : found) {
TransactionDetails transactionDetails; TransactionDetails transactionDetails;
if (!fillTransactionDetails(tx, transactionDetails, block.timestamp)) { 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) { bool BlockchainExplorerDataBuilder::fillTransactionDetails(const Transaction& transaction, TransactionDetails& transactionDetails, uint64_t timestamp) {
crypto::hash hash = get_transaction_hash(transaction); Crypto::Hash hash = getObjectHash(transaction);
transactionDetails.hash = reinterpret_cast<const std::array<uint8_t, 32>&>(hash); transactionDetails.hash = hash;
transactionDetails.timestamp = timestamp; transactionDetails.timestamp = timestamp;
crypto::hash blockHash; Crypto::Hash blockHash;
uint64_t blockHeight; uint32_t blockHeight;
if (!core.getBlockContainingTx(hash, blockHash, blockHeight)) { if (!core.getBlockContainingTx(hash, blockHash, blockHeight)) {
transactionDetails.inBlockchain = false; transactionDetails.inBlockchain = false;
transactionDetails.blockHeight = boost::value_initialized<uint64_t>(); transactionDetails.blockHeight = boost::value_initialized<uint32_t>();
transactionDetails.blockHash = boost::value_initialized<std::array<uint8_t, 32>>(); transactionDetails.blockHash = boost::value_initialized<Crypto::Hash>();
} else { } else {
transactionDetails.inBlockchain = true; transactionDetails.inBlockchain = true;
transactionDetails.blockHeight = blockHeight; transactionDetails.blockHeight = blockHeight;
transactionDetails.blockHash = reinterpret_cast<const std::array<uint8_t, 32>&>(blockHash); transactionDetails.blockHash = blockHash;
if (timestamp == 0) { if (timestamp == 0) {
Block block; Block block;
if (!core.getBlockByHash(blockHash, block)) { if (!core.getBlockByHash(blockHash, block)) {
@ -225,8 +219,8 @@ bool BlockchainExplorerDataBuilder::fillTransactionDetails(const Transaction& tr
transactionDetails.timestamp = block.timestamp; transactionDetails.timestamp = block.timestamp;
} }
} }
transactionDetails.size = get_object_blobsize(transaction); transactionDetails.size = getObjectBinarySize(transaction);
transactionDetails.unlockTime = transaction.unlockTime; transactionDetails.unlockTime = transaction.unlockTime;
transactionDetails.totalOutputsAmount = get_outs_money_amount(transaction); transactionDetails.totalOutputsAmount = get_outs_money_amount(transaction);
@ -236,7 +230,7 @@ bool BlockchainExplorerDataBuilder::fillTransactionDetails(const Transaction& tr
} }
transactionDetails.totalInputsAmount = inputsAmount; 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 //It's gen transaction
transactionDetails.fee = 0; transactionDetails.fee = 0;
transactionDetails.mixin = 0; transactionDetails.mixin = 0;
@ -252,106 +246,105 @@ bool BlockchainExplorerDataBuilder::fillTransactionDetails(const Transaction& tr
} }
transactionDetails.mixin = mixin; transactionDetails.mixin = mixin;
} }
crypto::hash paymentId; Crypto::Hash paymentId;
if (getPaymentId(transaction, 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); fillTxExtra(transaction.extra, transactionDetails.extra);
transactionDetails.signatures.reserve(transaction.signatures.size()); transactionDetails.signatures.reserve(transaction.signatures.size());
for (const std::vector<crypto::signature>& signatures : transaction.signatures) { for (const std::vector<Crypto::Signature>& signatures : transaction.signatures) {
std::vector<std::array<uint8_t, 32>> signaturesDetails; std::vector<Crypto::Signature> signaturesDetails;
signaturesDetails.reserve(signatures.size()); signaturesDetails.reserve(signatures.size());
for (const crypto::signature& signature : signatures) { for (const Crypto::Signature& signature : signatures) {
signaturesDetails.push_back(std::move(reinterpret_cast<const std::array<uint8_t, 32>&>(signature))); signaturesDetails.push_back(std::move(signature));
} }
transactionDetails.signatures.push_back(std::move(signaturesDetails)); transactionDetails.signatures.push_back(std::move(signaturesDetails));
} }
transactionDetails.inputs.reserve(transaction.vin.size()); transactionDetails.inputs.reserve(transaction.inputs.size());
for (const TransactionInput& txIn : transaction.vin) { for (const TransactionInput& txIn : transaction.inputs) {
TransactionInputDetails txInDetails; TransactionInputDetails txInDetails;
if (txIn.type() == typeid(TransactionInputGenerate)) { if (txIn.type() == typeid(BaseInput)) {
TransactionInputGenerateDetails txInGenDetails; TransactionInputGenerateDetails txInGenDetails;
txInGenDetails.height = boost::get<TransactionInputGenerate>(txIn).height; txInGenDetails.height = boost::get<BaseInput>(txIn).blockIndex;
txInDetails.amount = 0; txInDetails.amount = 0;
for (const TransactionOutput& out : transaction.vout) { for (const TransactionOutput& out : transaction.outputs) {
txInDetails.amount += out.amount; txInDetails.amount += out.amount;
} }
txInDetails.input = txInGenDetails; txInDetails.input = txInGenDetails;
} else if (txIn.type() == typeid(TransactionInputToKey)) { } else if (txIn.type() == typeid(KeyInput)) {
TransactionInputToKeyDetails txInToKeyDetails; TransactionInputToKeyDetails txInToKeyDetails;
const TransactionInputToKey& txInToKey = boost::get<TransactionInputToKey>(txIn); const KeyInput& txInToKey = boost::get<KeyInput>(txIn);
std::list<std::pair<crypto::hash, size_t>> outputReferences; std::list<std::pair<Crypto::Hash, size_t>> outputReferences;
if (!core.scanOutputkeysForIndices(txInToKey, outputReferences)) { if (!core.scanOutputkeysForIndices(txInToKey, outputReferences)) {
return false; return false;
} }
txInDetails.amount = txInToKey.amount; txInDetails.amount = txInToKey.amount;
txInToKeyDetails.keyOffsets = txInToKey.keyOffsets; txInToKeyDetails.outputIndexes = txInToKey.outputIndexes;
txInToKeyDetails.keyImage = reinterpret_cast<const std::array<uint8_t, 16>&>(txInToKey.keyImage); txInToKeyDetails.keyImage = txInToKey.keyImage;
txInToKeyDetails.mixin = txInToKey.keyOffsets.size(); txInToKeyDetails.mixin = txInToKey.outputIndexes.size();
txInToKeyDetails.output.number = outputReferences.back().second; 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; txInDetails.input = txInToKeyDetails;
} else if (txIn.type() == typeid(TransactionInputMultisignature)) { } else if (txIn.type() == typeid(MultisignatureInput)) {
TransactionInputMultisignatureDetails txInMultisigDetails; TransactionInputMultisignatureDetails txInMultisigDetails;
const TransactionInputMultisignature& txInMultisig = boost::get<TransactionInputMultisignature>(txIn); const MultisignatureInput& txInMultisig = boost::get<MultisignatureInput>(txIn);
txInDetails.amount = txInMultisig.amount; txInDetails.amount = txInMultisig.amount;
txInMultisigDetails.signatures = txInMultisig.signatures; txInMultisigDetails.signatures = txInMultisig.signatureCount;
std::pair<crypto::hash, size_t> outputReference; std::pair<Crypto::Hash, size_t> outputReference;
if (!core.getMultisigOutputReference(txInMultisig, outputReference)) { if (!core.getMultisigOutputReference(txInMultisig, outputReference)) {
return false; return false;
} }
txInMultisigDetails.output.number = outputReference.second; 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; txInDetails.input = txInMultisigDetails;
} else { } else {
return false; return false;
} }
transactionDetails.inputs.push_back(std::move(txInDetails)); transactionDetails.inputs.push_back(std::move(txInDetails));
} }
transactionDetails.outputs.reserve(transaction.vout.size()); transactionDetails.outputs.reserve(transaction.outputs.size());
std::vector<uint64_t> globalIndices; std::vector<uint32_t> globalIndices;
globalIndices.reserve(transaction.vout.size()); globalIndices.reserve(transaction.outputs.size());
if (!core.get_tx_outputs_gindexs(hash, globalIndices)) { if (!transactionDetails.inBlockchain || !core.get_tx_outputs_gindexs(hash, globalIndices)) {
for (size_t i = 0; i < transaction.vout.size(); ++i) { for (size_t i = 0; i < transaction.outputs.size(); ++i) {
globalIndices.push_back(0); globalIndices.push_back(0);
} }
} }
typedef boost::tuple<TransactionOutput, uint64_t> outputWithIndex; typedef boost::tuple<TransactionOutput, uint32_t> outputWithIndex;
auto range = boost::combine(transaction.vout, globalIndices); auto range = boost::combine(transaction.outputs, globalIndices);
for (const outputWithIndex& txOutput : range) { for (const outputWithIndex& txOutput : range) {
TransactionOutputDetails txOutDetails; TransactionOutputDetails txOutDetails;
txOutDetails.amount = txOutput.get<0>().amount; txOutDetails.amount = txOutput.get<0>().amount;
txOutDetails.globalIndex = txOutput.get<1>(); txOutDetails.globalIndex = txOutput.get<1>();
if (txOutput.get<0>().target.type() == typeid(TransactionOutputToKey)) { if (txOutput.get<0>().target.type() == typeid(KeyOutput)) {
TransactionOutputToKeyDetails txOutToKeyDetails; 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; txOutDetails.output = txOutToKeyDetails;
} else if (txOutput.get<0>().target.type() == typeid(TransactionOutputMultisignature)) { } else if (txOutput.get<0>().target.type() == typeid(MultisignatureOutput)) {
TransactionOutputMultisignatureDetails txOutMultisigDetails; 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()); txOutMultisigDetails.keys.reserve(txOutMultisig.keys.size());
for (const crypto::public_key& key : txOutMultisig.keys) { for (const Crypto::PublicKey& key : txOutMultisig.keys) {
txOutMultisigDetails.keys.push_back(std::move(reinterpret_cast<const std::array<uint8_t, 16>&>(key))); txOutMultisigDetails.keys.push_back(std::move(key));
} }
txOutMultisigDetails.requiredSignatures = txOutMultisig.requiredSignatures; txOutMultisigDetails.requiredSignatures = txOutMultisig.requiredSignatureCount;
txOutDetails.output = txOutMultisigDetails; txOutDetails.output = txOutMultisigDetails;
} else { } else {
return false; return false;
} }
transactionDetails.outputs.push_back(std::move(txOutDetails)); transactionDetails.outputs.push_back(std::move(txOutDetails));
} }
return true; return true;
} }

11
src/BlockchainExplorer/BlockchainExplorerDataBuilder.h Normal file → Executable file
View file

@ -20,8 +20,8 @@
#include <vector> #include <vector>
#include <array> #include <array>
#include "cryptonote_protocol/ICryptonoteProtocolQuery.h" #include "CryptoNoteProtocol/ICryptoNoteProtocolQuery.h"
#include "cryptonote_core/ICore.h" #include "CryptoNoteCore/ICore.h"
#include "BlockchainExplorerData.h" #include "BlockchainExplorerData.h"
namespace CryptoNote { namespace CryptoNote {
@ -29,7 +29,7 @@ namespace CryptoNote {
class BlockchainExplorerDataBuilder class BlockchainExplorerDataBuilder
{ {
public: public:
BlockchainExplorerDataBuilder(CryptoNote::ICore& core, CryptoNote::ICryptonoteProtocolQuery& protocol); BlockchainExplorerDataBuilder(CryptoNote::ICore& core, CryptoNote::ICryptoNoteProtocolQuery& protocol);
BlockchainExplorerDataBuilder(const BlockchainExplorerDataBuilder&) = delete; BlockchainExplorerDataBuilder(const BlockchainExplorerDataBuilder&) = delete;
BlockchainExplorerDataBuilder(BlockchainExplorerDataBuilder&&) = delete; BlockchainExplorerDataBuilder(BlockchainExplorerDataBuilder&&) = delete;
@ -40,13 +40,14 @@ public:
bool fillBlockDetails(const Block& block, BlockDetails& blockDetails); bool fillBlockDetails(const Block& block, BlockDetails& blockDetails);
bool fillTransactionDetails(const Transaction &tx, TransactionDetails& txRpcInfo, uint64_t timestamp = 0); bool fillTransactionDetails(const Transaction &tx, TransactionDetails& txRpcInfo, uint64_t timestamp = 0);
static bool getPaymentId(const Transaction& transaction, Crypto::Hash& paymentId);
private: private:
bool getMixin(const Transaction& transaction, uint64_t& mixin); 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); bool fillTxExtra(const std::vector<uint8_t>& rawExtra, TransactionExtraDetails& extraDetails);
size_t median(std::vector<size_t>& v); size_t median(std::vector<size_t>& v);
CryptoNote::ICore& core; CryptoNote::ICore& core;
CryptoNote::ICryptonoteProtocolQuery& protocol; CryptoNote::ICryptoNoteProtocolQuery& protocol;
}; };
} }

View file

@ -2,20 +2,19 @@ add_definitions(-DSTATICLIB)
file(GLOB_RECURSE BlockchainExplorer BlockchainExplorer/*) file(GLOB_RECURSE BlockchainExplorer BlockchainExplorer/*)
file(GLOB_RECURSE Common Common/*) file(GLOB_RECURSE Common Common/*)
file(GLOB_RECURSE ConnectivityTool connectivity_tool/*) file(GLOB_RECURSE ConnectivityTool ConnectivityTool/*)
file(GLOB_RECURSE Crypto crypto/*) file(GLOB_RECURSE Crypto crypto/*)
file(GLOB_RECURSE CryptoNote CryptoNote/*) file(GLOB_RECURSE CryptoNoteCore CryptoNoteCore/* CryptoNoteConfig.h)
file(GLOB_RECURSE CryptoNoteCore cryptonote_core/* cryptonote_config.h) file(GLOB_RECURSE CryptoNoteProtocol CryptoNoteProtocol/*)
file(GLOB_RECURSE CryptoNoteProtocol cryptonote_protocol/*) file(GLOB_RECURSE Daemon Daemon/*)
file(GLOB_RECURSE Daemon daemon/*)
file(GLOB_RECURSE Http HTTP/*) file(GLOB_RECURSE Http HTTP/*)
file(GLOB_RECURSE InProcessNode InProcessNode/*) file(GLOB_RECURSE InProcessNode InProcessNode/*)
file(GLOB_RECURSE Logging Logging/*) file(GLOB_RECURSE Logging Logging/*)
file(GLOB_RECURSE NodeRpcProxy node_rpc_proxy/*) file(GLOB_RECURSE NodeRpcProxy NodeRpcProxy/*)
file(GLOB_RECURSE P2p p2p/*) file(GLOB_RECURSE P2p P2p/*)
file(GLOB_RECURSE Rpc rpc/*) file(GLOB_RECURSE Rpc Rpc/*)
file(GLOB_RECURSE Serialization serialization/*) file(GLOB_RECURSE Serialization Serialization/*)
file(GLOB_RECURSE SimpleWallet simplewallet/*) file(GLOB_RECURSE SimpleWallet SimpleWallet/*)
if(MSVC) if(MSVC)
file(GLOB_RECURSE System System/* Platform/Windows/System/*) file(GLOB_RECURSE System System/* Platform/Windows/System/*)
elseif(APPLE) elseif(APPLE)
@ -23,17 +22,20 @@ file(GLOB_RECURSE System System/* Platform/OSX/System/*)
else() else()
file(GLOB_RECURSE System System/* Platform/Linux/System/*) file(GLOB_RECURSE System System/* Platform/Linux/System/*)
endif() endif()
file(GLOB_RECURSE Transfers transfers/*) file(GLOB_RECURSE Transfers Transfers/*)
file(GLOB_RECURSE Wallet wallet/*) file(GLOB_RECURSE Wallet Wallet/*)
file(GLOB_RECURSE PaymentService payment_service/*) 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(BlockchainExplorer ${BlockchainExplorer})
add_library(Common ${Common}) add_library(Common ${Common})
add_library(Crypto ${Crypto}) add_library(Crypto ${Crypto})
add_library(CryptoNote ${CryptoNote})
add_library(CryptoNoteCore ${CryptoNoteCore}) add_library(CryptoNoteCore ${CryptoNoteCore})
add_library(Http ${Http}) add_library(Http ${Http})
add_library(InProcessNode ${InProcessNode}) add_library(InProcessNode ${InProcessNode})
@ -44,27 +46,35 @@ add_library(P2P ${CryptoNoteProtocol} ${P2p})
add_library(Serialization ${Serialization}) add_library(Serialization ${Serialization})
add_library(System ${System}) add_library(System ${System})
add_library(Transfers ${Transfers}) 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(ConnectivityTool ${ConnectivityTool})
add_executable(Daemon ${Daemon}) add_executable(Daemon ${Daemon})
add_executable(SimpleWallet ${SimpleWallet}) 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(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(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(Rpc version)
add_dependencies(ConnectivityTool version) add_dependencies(ConnectivityTool version)
add_dependencies(Daemon version) add_dependencies(Daemon version)
add_dependencies(SimpleWallet version) add_dependencies(SimpleWallet version)
add_dependencies(PaymentGate version) add_dependencies(PaymentGateService version)
add_dependencies(P2P version) add_dependencies(P2P version)
set_property(TARGET ConnectivityTool PROPERTY OUTPUT_NAME "connectivity_tool") set_property(TARGET ConnectivityTool PROPERTY OUTPUT_NAME "connectivity_tool")
set_property(TARGET Daemon PROPERTY OUTPUT_NAME "bytecoind") set_property(TARGET Daemon PROPERTY OUTPUT_NAME "bytecoind")
set_property(TARGET SimpleWallet PROPERTY OUTPUT_NAME "simplewallet") set_property(TARGET SimpleWallet PROPERTY OUTPUT_NAME "simplewallet")
set_property(TARGET PaymentGate PROPERTY OUTPUT_NAME "walletd") set_property(TARGET PaymentGateService PROPERTY OUTPUT_NAME "walletd")

View file

@ -30,7 +30,7 @@ namespace Common {
// 'data' == 'nullptr' && 'size' > 0 - Undefined // 'data' == 'nullptr' && 'size' > 0 - Undefined
// 'data' != 'nullptr' && 'size' > 0 - NOTEMPTY NOTNIL // 'data' != 'nullptr' && 'size' > 0 - NOTEMPTY NOTNIL
// For signed integer 'Size', 'ArrayRef' with 'size' < 0 is undefined. // 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: public:
typedef ObjectType Object; typedef ObjectType Object;
typedef SizeType Size; typedef SizeType Size;

View file

@ -32,7 +32,7 @@ namespace Common {
// 'data' == 'nullptr' && 'size' > 0 - Undefined // 'data' == 'nullptr' && 'size' > 0 - Undefined
// 'data' != 'nullptr' && 'size' > 0 - NOTEMPTY NOTNIL // 'data' != 'nullptr' && 'size' > 0 - NOTEMPTY NOTNIL
// For signed integer 'Size', 'ArrayView' with 'size' < 0 is undefined. // 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: public:
typedef Object ObjectType; typedef Object ObjectType;
typedef Size SizeType; typedef Size SizeType;

View file

@ -15,7 +15,7 @@
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>. // along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#include "base58.h" #include "Base58.h"
#include <assert.h> #include <assert.h>
#include <string> #include <string>
@ -23,11 +23,11 @@
#include "crypto/hash.h" #include "crypto/hash.h"
#include "int-util.h" #include "int-util.h"
#include "varint.h" #include "Varint.h"
namespace tools namespace Tools
{ {
namespace base58 namespace Base58
{ {
namespace namespace
{ {
@ -227,7 +227,7 @@ namespace tools
{ {
std::string buf = get_varint_data(tag); std::string buf = get_varint_data(tag);
buf += data; 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); const char* hash_data = reinterpret_cast<const char*>(&hash);
buf.append(hash_data, addr_checksum_size); buf.append(hash_data, addr_checksum_size);
return encode(buf); return encode(buf);
@ -244,11 +244,11 @@ namespace tools
checksum = addr_data.substr(addr_data.size() - addr_checksum_size); checksum = addr_data.substr(addr_data.size() - addr_checksum_size);
addr_data.resize(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); std::string expected_checksum(reinterpret_cast<const char*>(&hash), addr_checksum_size);
if (expected_checksum != checksum) return false; 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; if (read <= 0) return false;
data = addr_data.substr(read); data = addr_data.substr(read);

4
src/Common/base58.h → src/Common/Base58.h Normal file → Executable file
View file

@ -20,9 +20,9 @@
#include <cstdint> #include <cstdint>
#include <string> #include <string>
namespace tools namespace Tools
{ {
namespace base58 namespace Base58
{ {
std::string encode(const std::string& data); std::string encode(const std::string& data);
bool decode(const std::string& enc, std::string& data); bool decode(const std::string& enc, std::string& data);

View file

@ -16,3 +16,7 @@
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>. // along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#include "BlockingQueue.h" #include "BlockingQueue.h"
namespace {
char suppressMSVCWarningLNK4221;
}

View file

@ -15,7 +15,7 @@
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>. // along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#include "command_line.h" #include "CommandLine.h"
namespace command_line namespace command_line
{ {

0
src/Common/command_line.h → src/Common/CommandLine.h Normal file → Executable file
View file

View file

@ -24,7 +24,7 @@ namespace Common {
class IInputStream { class IInputStream {
public: public:
virtual ~IInputStream() { } virtual ~IInputStream() { }
virtual std::size_t readSome(void* data, std::size_t size) = 0; virtual size_t readSome(void* data, size_t size) = 0;
}; };
} }

View file

@ -24,7 +24,7 @@ namespace Common {
class IOutputStream { class IOutputStream {
public: public:
virtual ~IOutputStream() { } 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;
}; };
} }

View file

@ -492,7 +492,7 @@ const JsonValue::String& JsonValue::getString() const {
return *reinterpret_cast<const String*>(valueString); return *reinterpret_cast<const String*>(valueString);
} }
std::size_t JsonValue::size() const { size_t JsonValue::size() const {
switch (type) { switch (type) {
case ARRAY: case ARRAY:
return reinterpret_cast<const Array*>(valueArray)->size(); 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) { if (type != ARRAY) {
throw std::runtime_error("JsonValue type is not 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); 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) { if (type != ARRAY) {
throw std::runtime_error("JsonValue type is not ARRAY"); throw std::runtime_error("JsonValue type is not ARRAY");
} }
@ -567,7 +567,7 @@ JsonValue& JsonValue::set(const Key& key, JsonValue&& value) {
return *this; return *this;
} }
std::size_t JsonValue::erase(const Key& key) { size_t JsonValue::erase(const Key& key) {
return getObject().erase(key); return getObject().erase(key);
} }
@ -595,7 +595,7 @@ std::ostream& operator<<(std::ostream& out, const JsonValue& jsonValue) {
out << '['; out << '[';
if (array.size() > 0) { if (array.size() > 0) {
out << array[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]; out << ',' << array[i];
} }
} }
@ -811,7 +811,7 @@ void JsonValue::readNull(std::istream& in) {
void JsonValue::readNumber(std::istream& in, char c) { void JsonValue::readNumber(std::istream& in, char c) {
std::string text; std::string text;
text += c; text += c;
std::size_t dots = 0; size_t dots = 0;
for (;;) { for (;;) {
int i = in.peek(); int i = in.peek();
if (i >= '0' && i <= '9') { if (i >= '0' && i <= '9') {

View file

@ -61,7 +61,7 @@ public:
JsonValue(Real value); JsonValue(Real value);
JsonValue(const String& value); JsonValue(const String& value);
JsonValue(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); new(valueString)String(value, size - 1);
type = STRING; type = STRING;
} }
@ -80,7 +80,7 @@ public:
JsonValue& operator=(Real value); JsonValue& operator=(Real value);
JsonValue& operator=(const String& value); JsonValue& operator=(const String& value);
JsonValue& operator=(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) { if (type != STRING) {
destructValue(); destructValue();
type = NIL; type = NIL;
@ -112,10 +112,10 @@ public:
String& getString(); String& getString();
const String& getString() const; const String& getString() const;
std::size_t size() const; size_t size() const;
JsonValue& operator[](std::size_t index); JsonValue& operator[](size_t index);
const JsonValue& operator[](std::size_t index) const; const JsonValue& operator[](size_t index) const;
JsonValue& pushBack(const JsonValue& value); JsonValue& pushBack(const JsonValue& value);
JsonValue& pushBack(JsonValue&& value); JsonValue& pushBack(JsonValue&& value);
@ -129,7 +129,7 @@ public:
JsonValue& set(const Key& key, const JsonValue& value); JsonValue& set(const Key& key, const JsonValue& value);
JsonValue& set(const Key& key, 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); static JsonValue fromString(const std::string& source);
std::string toString() const; std::string toString() const;

View file

@ -16,3 +16,7 @@
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>. // along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#include "Math.h" #include "Math.h"
namespace {
char suppressMSVCWarningLNK4221;
}

View file

@ -15,29 +15,34 @@
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>. // along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#include "MultisignatureOutput.h" #include "MemoryInputStream.h"
#include <algorithm>
#include <cassert> #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) { MemoryInputStream::MemoryInputStream(const void* buffer, size_t bufferSize) :
assert(requiredSignatureCount <= keys.size()); buffer(static_cast<const char*>(buffer)), bufferSize(bufferSize), position(0) {}
size_t MemoryInputStream::getPosition() const {
return position;
} }
uint64_t MultisignatureOutput::getAmount() const { bool MemoryInputStream::endOfStream() const {
return amount; return position == bufferSize;
} }
uint32_t MultisignatureOutput::getKeyCount() const { size_t MemoryInputStream::readSome(void* data, size_t size) {
return static_cast<uint32_t>(keys.size()); assert(position <= bufferSize);
} size_t readSize = std::min(size, bufferSize - position);
const crypto::public_key& MultisignatureOutput::getKey(uint32_t index) const { if (readSize > 0) {
return keys[index]; memcpy(data, buffer + position, readSize);
} position += readSize;
}
uint32_t MultisignatureOutput::getRequiredSignatureCount() const {
return requiredSignatureCount; return readSize;
} }
} }

View file

@ -17,21 +17,22 @@
#pragma once #pragma once
#include "../crypto/crypto.h" #include "IInputStream.h"
namespace CryptoNote { namespace Common {
class KeyOutput { class MemoryInputStream : public IInputStream {
public: public:
KeyOutput(uint64_t amount, const crypto::public_key& key); MemoryInputStream(const void* buffer, size_t bufferSize);
KeyOutput(const KeyOutput& other) = delete; size_t getPosition() const;
KeyOutput& operator=(const KeyOutput& other) = delete; bool endOfStream() const;
uint64_t getAmount() const;
const crypto::public_key& getKey() const; // IInputStream
virtual size_t readSome(void* data, size_t size) override;
private:
uint64_t amount;
crypto::public_key key;
};
private:
const char* buffer;
size_t bufferSize;
size_t position;
};
} }

3
src/Common/ObserverManager.h Normal file → Executable file
View file

@ -21,7 +21,7 @@
#include <mutex> #include <mutex>
#include <vector> #include <vector>
namespace tools { namespace Tools {
template<typename T> template<typename T>
class ObserverManager { class ObserverManager {
@ -39,6 +39,7 @@ public:
bool remove(T* observer) { bool remove(T* observer) {
std::unique_lock<std::mutex> lock(m_observersMutex); std::unique_lock<std::mutex> lock(m_observersMutex);
auto it = std::find(m_observers.begin(), m_observers.end(), observer); auto it = std::find(m_observers.begin(), m_observers.end(), observer);
if (m_observers.end() == it) { if (m_observers.end() == it) {
return false; return false;

23
src/Common/SignalHandler.cpp Normal file → Executable file
View file

@ -27,6 +27,7 @@
#include <Windows.h> #include <Windows.h>
#else #else
#include <signal.h> #include <signal.h>
#include <cstring>
#endif #endif
namespace { namespace {
@ -65,7 +66,7 @@ void posixHandler(int /*type*/) {
} }
namespace tools { namespace Tools {
bool SignalHandler::install(std::function<void(void)> t) bool SignalHandler::install(std::function<void(void)> t)
{ {
@ -76,9 +77,23 @@ namespace tools {
} }
return r; return r;
#else #else
signal(SIGINT, posixHandler); struct sigaction newMask;
signal(SIGTERM, posixHandler); std::memset(&newMask, 0, sizeof(struct sigaction));
signal(SIGPIPE, SIG_IGN); 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; m_handler = t;
return true; return true;
#endif #endif

2
src/Common/SignalHandler.h Normal file → Executable file
View file

@ -19,7 +19,7 @@
#include <functional> #include <functional>
namespace tools { namespace Tools {
class SignalHandler class SignalHandler
{ {

View 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();
}
}

View 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;
};
}

View 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;
}
}

View 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;
};
}

View file

@ -22,9 +22,9 @@
namespace Common { namespace Common {
void read(IInputStream& in, void* data, std::size_t size) { void read(IInputStream& in, void* data, size_t size) {
while (size > 0) { while (size > 0) {
std::size_t readSize = in.readSome(data, size); size_t readSize = in.readSome(data, size);
if (readSize == 0) { if (readSize == 0) {
throw std::runtime_error("Failed to read from IInputStream"); 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)); 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); data.resize(size);
read(in, data.data(), 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); std::vector<char> temp(size);
read(in, temp.data(), size); read(in, temp.data(), size);
data.assign(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"); 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 & 0x80) == 0) {
if (piece == 0 && shift != 0) { if (piece == 0 && shift != 0) {
throw std::runtime_error("readVarint, invalid value representation"); 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"); 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 & 0x80) == 0) {
if (piece == 0 && shift != 0) { if (piece == 0 && shift != 0) {
throw std::runtime_error("readVarint, invalid value representation"); 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"); 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 & 0x80) == 0) {
if (piece == 0 && shift != 0) { if (piece == 0 && shift != 0) {
throw std::runtime_error("readVarint, invalid value representation"); 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"); 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 & 0x80) == 0) {
if (piece == 0 && shift != 0) { if (piece == 0 && shift != 0) {
throw std::runtime_error("readVarint, invalid value representation"); throw std::runtime_error("readVarint, invalid value representation");
@ -171,9 +171,9 @@ void readVarint(IInputStream& in, uint64_t& value) {
value = temp; 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) { while (size > 0) {
std::size_t writtenSize = out.writeSome(data, size); size_t writtenSize = out.writeSome(data, size);
if (writtenSize == 0) { if (writtenSize == 0) {
throw std::runtime_error("Failed to write to IOutputStream"); throw std::runtime_error("Failed to write to IOutputStream");
} }

View file

@ -26,7 +26,7 @@ namespace Common {
class IInputStream; class IInputStream;
class IOutputStream; 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, int8_t& value);
void read(IInputStream& in, int16_t& value); void read(IInputStream& in, int16_t& value);
void read(IInputStream& in, int32_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, uint16_t& value);
void read(IInputStream& in, uint32_t& value); void read(IInputStream& in, uint32_t& value);
void read(IInputStream& in, uint64_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::vector<uint8_t>& data, size_t size);
void read(IInputStream& in, std::string& data, std::size_t size); void read(IInputStream& in, std::string& data, size_t size);
void readVarint(IInputStream& in, uint8_t& value); void readVarint(IInputStream& in, uint8_t& value);
void readVarint(IInputStream& in, uint16_t& value); void readVarint(IInputStream& in, uint16_t& value);
void readVarint(IInputStream& in, uint32_t& value); void readVarint(IInputStream& in, uint32_t& value);
void readVarint(IInputStream& in, uint64_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, int8_t value);
void write(IOutputStream& out, int16_t value); void write(IOutputStream& out, int16_t value);
void write(IOutputStream& out, int32_t value); void write(IOutputStream& out, int32_t value);
@ -61,7 +61,7 @@ template<typename T> T read(IInputStream& in) {
return value; 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; T value;
read(in, value, size); read(in, value, size);
return value; return value;

View file

@ -24,10 +24,10 @@
namespace Common { namespace Common {
// 'StringBuffer' is a string of fixed maximum size. // '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: public:
typedef char Object; typedef char Object;
typedef std::size_t Size; typedef size_t Size;
const static Size MAXIMUM_SIZE = MAXIMUM_SIZE_VALUE; const static Size MAXIMUM_SIZE = MAXIMUM_SIZE_VALUE;
const static Size INVALID; const static Size INVALID;
@ -549,6 +549,6 @@ protected:
Size size; 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();
} }

View file

@ -23,7 +23,7 @@ namespace Common {
StringInputStream::StringInputStream(const std::string& in) : in(in), offset(0) { 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) { if (size > in.size() - offset) {
size = in.size() - offset; size = in.size() - offset;
} }

View file

@ -25,11 +25,11 @@ namespace Common {
class StringInputStream : public IInputStream { class StringInputStream : public IInputStream {
public: public:
StringInputStream(const std::string& in); 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: private:
const std::string& in; const std::string& in;
std::size_t offset; size_t offset;
}; };
} }

View file

@ -22,7 +22,7 @@ namespace Common {
StringOutputStream::StringOutputStream(std::string& out) : out(out) { 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); out.append(static_cast<const char*>(data), size);
return size; return size;
} }

View file

@ -25,7 +25,7 @@ namespace Common {
class StringOutputStream : public IOutputStream { class StringOutputStream : public IOutputStream {
public: public:
StringOutputStream(std::string& out); 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: private:
std::string& out; std::string& out;

View file

@ -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); 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()); 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 fromHex(char character) {
uint8_t value = characterValues[static_cast<unsigned char>(character)]; uint8_t value = characterValues[static_cast<unsigned char>(character)];
if (value > 0x0f) { if (value > 0x0f) {
@ -69,7 +74,7 @@ bool fromHex(char character, uint8_t& value) {
return true; 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) { if ((text.size() & 1) != 0) {
throw std::runtime_error("fromHex: invalid string size"); 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"); 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]); static_cast<uint8_t*>(data)[i] = fromHex(text[i << 1]) << 4 | fromHex(text[(i << 1) + 1]);
} }
return text.size() >> 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) { if ((text.size() & 1) != 0) {
return false; return false;
} }
@ -94,7 +99,7 @@ bool fromHex(const std::string& text, void* data, std::size_t bufferSize, std::s
return false; 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; uint8_t value1;
if (!fromHex(text[i << 1], value1)) { if (!fromHex(text[i << 1], value1)) {
return false; return false;
@ -118,7 +123,7 @@ std::vector<uint8_t> fromHex(const std::string& text) {
} }
std::vector<uint8_t> data(text.size() >> 1); 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]); 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; 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; uint8_t value1;
if (!fromHex(text[i << 1], value1)) { if (!fromHex(text[i << 1], value1)) {
return false; return false;
@ -147,9 +152,9 @@ bool fromHex(const std::string& text, std::vector<uint8_t>& data) {
return true; return true;
} }
std::string toHex(const void* data, std::size_t size) { std::string toHex(const void* data, size_t size) {
std::string text; 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] >> 4];
text += "0123456789abcdef"[static_cast<const uint8_t*>(data)[i] & 15]; 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; return text;
} }
void toHex(const void* data, std::size_t size, std::string& text) { void 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] >> 4];
text += "0123456789abcdef"[static_cast<const uint8_t*>(data)[i] & 15]; 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 toHex(const std::vector<uint8_t>& data) {
std::string text; 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] >> 4];
text += "0123456789abcdef"[data[i] & 15]; 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) { 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] >> 4];
text += "0123456789abcdef"[data[i] & 15]; text += "0123456789abcdef"[data[i] & 15];
} }
} }
std::string extract(std::string& text, char delimiter) { std::string extract(std::string& text, char delimiter) {
std::size_t delimiterPosition = text.find(delimiter); size_t delimiterPosition = text.find(delimiter);
std::string subText; std::string subText;
if (delimiterPosition != std::string::npos) { if (delimiterPosition != std::string::npos) {
subText = text.substr(0, delimiterPosition); subText = text.substr(0, delimiterPosition);
@ -194,8 +199,8 @@ std::string extract(std::string& text, char delimiter) {
return subText; return subText;
} }
std::string extract(const std::string& text, char delimiter, std::size_t& offset) { std::string extract(const std::string& text, char delimiter, size_t& offset) {
std::size_t delimiterPosition = text.find(delimiter, offset); size_t delimiterPosition = text.find(delimiter, offset);
if (delimiterPosition != std::string::npos) { if (delimiterPosition != std::string::npos) {
offset = delimiterPosition + 1; offset = delimiterPosition + 1;
return text.substr(offset, delimiterPosition); return text.substr(offset, delimiterPosition);

View file

@ -24,24 +24,25 @@
namespace Common { 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::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 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 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 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, 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 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 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 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> template <typename T>
bool podFromHex(const std::string& text, T& val) { 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); 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 std::string toHex(const void* data, 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 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 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 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(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 template<typename T> T fromString(const std::string& text) { // Throws on error
T value; 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 template<typename T> std::vector<T> fromDelimitedString(const std::string& source, char delimiter) { // Throws on error
std::vector<T> data; 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))); 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 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; T value;
if (!fromString<T>(extract(source, delimiter, offset), value)) { if (!fromString<T>(extract(source, delimiter, offset), value)) {
return false; return false;

View file

@ -32,7 +32,7 @@ namespace Common {
class StringView { class StringView {
public: public:
typedef char Object; typedef char Object;
typedef std::size_t Size; typedef size_t Size;
const static Size INVALID; const static Size INVALID;
const static StringView EMPTY; const static StringView EMPTY;

View file

@ -15,12 +15,12 @@
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>. // along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#include "util.h" #include "Util.h"
#include <cstdio> #include <cstdio>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include "cryptonote_config.h" #include "CryptoNoteConfig.h"
#ifdef WIN32 #ifdef WIN32
#include <windows.h> #include <windows.h>
@ -31,7 +31,7 @@
#endif #endif
namespace tools namespace Tools
{ {
#ifdef WIN32 #ifdef WIN32
std::string get_windows_version_display_string() std::string get_windows_version_display_string()
@ -296,7 +296,7 @@ std::string get_nix_version_display_string()
} }
#endif #endif
std::string get_default_data_dir() std::string getDefaultDataDirectory()
{ {
//namespace fs = boost::filesystem; //namespace fs = boost::filesystem;
// Windows < Vista: C:\Documents and Settings\Username\Application Data\CRYPTONOTE_NAME // Windows < Vista: C:\Documents and Settings\Username\Application Data\CRYPTONOTE_NAME

4
src/Common/util.h → src/Common/Util.h Normal file → Executable file
View file

@ -20,9 +20,9 @@
#include <string> #include <string>
#include <system_error> #include <system_error>
namespace tools namespace Tools
{ {
std::string get_default_data_dir(); std::string getDefaultDataDirectory();
std::string get_os_version_string(); std::string get_os_version_string();
bool create_directories_if_necessary(const std::string& path); bool create_directories_if_necessary(const std::string& path);
std::error_code replace_file(const std::string& replacement_name, const std::string& replaced_name); 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
View file

@ -23,7 +23,7 @@
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
namespace tools { namespace Tools {
template<typename OutputIt, typename T> template<typename OutputIt, typename T>
typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value, void>::type typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value, void>::type

View 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;
}
}

View 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
View file

@ -1,26 +1,26 @@
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers // Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
// //
// This file is part of Bytecoin. // This file is part of Bytecoin.
// //
// Bytecoin is free software: you can redistribute it and/or modify // 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 // 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 // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// Bytecoin is distributed in the hope that it will be useful, // Bytecoin is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details. // GNU Lesser General Public License for more details.
// //
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>. // along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#pragma once #pragma once
#ifndef __cplusplus #ifndef __cplusplus
#ifdef __clang__ #ifdef __clang__
#define static_assert _Static_assert #define static_assert _Static_assert
#endif #endif
#endif #endif

View file

@ -18,6 +18,8 @@
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <boost/program_options.hpp> #include <boost/program_options.hpp>
#include <System/ContextGroup.h>
#include <System/ContextGroupTimeout.h>
#include <System/Dispatcher.h> #include <System/Dispatcher.h>
#include <System/Event.h> #include <System/Event.h>
#include <System/InterruptedException.h> #include <System/InterruptedException.h>
@ -27,14 +29,14 @@
#include <System/TcpConnector.h> #include <System/TcpConnector.h>
#include <System/Timer.h> #include <System/Timer.h>
#include "Common/command_line.h" #include "Common/CommandLine.h"
#include "Common/StringTools.h" #include "Common/StringTools.h"
#include "crypto/crypto.h" #include "crypto/crypto.h"
#include "p2p/p2p_protocol_defs.h" #include "P2p/P2pProtocolDefinitions.h"
#include "p2p/LevinProtocol.h" #include "P2p/LevinProtocol.h"
#include "rpc/core_rpc_server_commands_defs.h" #include "Rpc/CoreRpcServerCommandsDefinitions.h"
#include "rpc/HttpClient.h" #include "Rpc/HttpClient.h"
#include "serialization/SerializationTools.h" #include "Serialization/SerializationTools.h"
#include "version.h" #include "version.h"
namespace po = boost::program_options; namespace po = boost::program_options;
@ -65,33 +67,26 @@ struct response_schema {
boost::optional<COMMAND_REQUEST_NETWORK_STATE::response> ns_rsp; boost::optional<COMMAND_REQUEST_NETWORK_STATE::response> ns_rsp;
}; };
void withTimeout(System::Dispatcher& dispatcher, unsigned timeout, std::function<void()> f) {
template <typename SystemObj> std::string result;
void withTimeout(System::Dispatcher& dispatcher, SystemObj& obj, unsigned timeout, std::function<void()> f) { System::ContextGroup cg(dispatcher);
System::Event timeoutEvent(dispatcher); System::ContextGroupTimeout cgTimeout(dispatcher, cg, std::chrono::milliseconds(timeout));
System::Timer timeoutTimer(dispatcher);
cg.spawn([&] {
dispatcher.spawn([&](){
try { try {
timeoutTimer.sleep(std::chrono::milliseconds(timeout)); f();
obj.stop(); } catch (System::InterruptedException&) {
} catch (std::exception&) {} result = "Operation timeout";
timeoutEvent.set(); } catch (std::exception& e) {
result = e.what();
}
}); });
try { cg.wait();
f();
} catch (System::InterruptedException&) {
timeoutEvent.wait();
throw std::runtime_error("Operation timeout");
} catch (std::exception&) {
timeoutTimer.stop();
timeoutEvent.wait();
throw;
}
timeoutTimer.stop(); if (!result.empty()) {
timeoutEvent.wait(); 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 << " ]," << ENDL;
ss << " \"local_peerlist_white\": [" << ENDL; ss << " \"local_peerlist_white\": [" << ENDL;
i = 0; 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 << "}"; 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) if (networkState.local_peerlist_white.size() - 1 != i)
ss << ","; ss << ",";
@ -136,7 +131,7 @@ std::ostream& get_response_schema_as_json(std::ostream& ss, response_schema &rs)
ss << " \"local_peerlist_gray\": [" << ENDL; ss << " \"local_peerlist_gray\": [" << ENDL;
i = 0; 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 << "}"; 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) if (networkState.local_peerlist_gray.size() - 1 != i)
ss << ","; 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; 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 << pe.id << "\t" << pe.adr << "\t" << Common::timeIntervalToString(ns.local_time - pe.last_seen) << ENDL;
} }
std::cout << "Peer list gray:" << ns.my_id << 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; 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; 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)) { if(!command_line::has_arg(vm, arg_priv_key)) {
std::cout << "{" << ENDL << " \"status\": \"ERROR: " << "secret key not set \"" << ENDL << "}"; std::cout << "{" << ENDL << " \"status\": \"ERROR: " << "secret key not set \"" << ENDL << "}";
return false; return false;
} }
crypto::secret_key prvk; Crypto::SecretKey prvk;
if (!Common::podFromHex(command_line::get_arg(vm, arg_priv_key), prvk)) { if (!Common::podFromHex(command_line::get_arg(vm, arg_priv_key), prvk)) {
std::cout << "{" << ENDL << " \"status\": \"ERROR: " << "wrong secret key set \"" << ENDL << "}"; std::cout << "{" << ENDL << " \"status\": \"ERROR: " << "wrong secret key set \"" << ENDL << "}";
return false; return false;
@ -250,7 +245,7 @@ bool handle_request_stat(po::variables_map& vm, peerid_type peer_id) {
System::TcpConnection connection; System::TcpConnection connection;
withTimeout(dispatcher, connector, timeout, [&] { withTimeout(dispatcher, timeout, [&] {
connection = connector.connect(addr, command_line::get_arg(vm, arg_port)); 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) { if (!peer_id) {
COMMAND_REQUEST_PEER_ID::request req; COMMAND_REQUEST_PEER_ID::request req;
COMMAND_REQUEST_PEER_ID::response rsp; COMMAND_REQUEST_PEER_ID::response rsp;
withTimeout(dispatcher, connection, timeout, [&] { withTimeout(dispatcher, timeout, [&] {
levin.invoke(COMMAND_REQUEST_PEER_ID::ID, req, rsp); levin.invoke(COMMAND_REQUEST_PEER_ID::ID, req, rsp);
}); });
peer_id = rsp.my_id; 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; proof_of_trust pot;
pot.peer_id = peer_id; pot.peer_id = peer_id;
pot.time = time(NULL); pot.time = time(NULL);
crypto::public_key pubk; Crypto::PublicKey pubk;
Common::podFromHex(P2P_STAT_TRUSTED_PUB_KEY, pubk); Common::podFromHex(P2P_STAT_TRUSTED_PUB_KEY, pubk);
crypto::hash h = get_proof_of_trust_hash(pot); Crypto::Hash h = get_proof_of_trust_hash(pot);
crypto::generate_signature(h, pubk, prvk, pot.sign); Crypto::generate_signature(h, pubk, prvk, pot.sign);
if (command_line::get_arg(vm, arg_request_stat_info)) { if (command_line::get_arg(vm, arg_request_stat_info)) {
COMMAND_REQUEST_STAT_INFO::request req; 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; req.tr = pot;
try { try {
withTimeout(dispatcher, connection, timeout, [&] { withTimeout(dispatcher, timeout, [&] {
levin.invoke(COMMAND_REQUEST_STAT_INFO::ID, req, res); levin.invoke(COMMAND_REQUEST_STAT_INFO::ID, req, res);
}); });
rs.si_rsp = std::move(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)) { if (command_line::get_arg(vm, arg_request_net_state)) {
++pot.time; ++pot.time;
h = get_proof_of_trust_hash(pot); 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::request req{ pot };
COMMAND_REQUEST_NETWORK_STATE::response res; COMMAND_REQUEST_NETWORK_STATE::response res;
try { try {
withTimeout(dispatcher, connection, timeout, [&] { withTimeout(dispatcher, timeout, [&] {
levin.invoke(COMMAND_REQUEST_NETWORK_STATE::ID, req, res); levin.invoke(COMMAND_REQUEST_NETWORK_STATE::ID, req, res);
}); });
rs.ns_rsp = std::move(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() { bool generate_and_print_keys() {
crypto::public_key pk; Crypto::PublicKey pk;
crypto::secret_key sk; Crypto::SecretKey sk;
generate_keys(pk, sk); generate_keys(pk, sk);
std::cout << "PUBLIC KEY: " << Common::podToHex(pk) << ENDL std::cout << "PUBLIC KEY: " << Common::podToHex(pk) << ENDL
<< "PRIVATE KEY: " << Common::podToHex(sk); << "PRIVATE KEY: " << Common::podToHex(sk);

View file

@ -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;
}
}

View file

@ -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;
};
}

View file

@ -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;
}
}

View file

@ -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;
};
}

View file

@ -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;
}
}

View file

@ -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;
};
}

View file

@ -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];
}
}

View file

@ -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;
};
}

View file

@ -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;
}
}

View file

@ -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;
};
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
};
}

View file

@ -74,6 +74,7 @@ const char CRYPTONOTE_BLOCKINDEXES_FILENAME[] = "blockindexes.dat
const char CRYPTONOTE_BLOCKSCACHE_FILENAME[] = "blockscache.dat"; const char CRYPTONOTE_BLOCKSCACHE_FILENAME[] = "blockscache.dat";
const char CRYPTONOTE_POOLDATA_FILENAME[] = "poolstate.bin"; const char CRYPTONOTE_POOLDATA_FILENAME[] = "poolstate.bin";
const char P2P_NET_DATA_FILENAME[] = "p2pstate.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"; const char MINER_CONFIG_FILE_NAME[] = "miner_conf.json";
} // parameters } // 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_WHITE_PEERLIST_LIMIT = 1000;
const size_t P2P_LOCAL_GRAY_PEERLIST_LIMIT = 5000; 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 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_HANDSHAKE_INTERVAL = 60; // seconds
const uint32_t P2P_DEFAULT_PACKET_MAX_SIZE = 50000000; // 50000000 bytes maximum packet size const uint32_t P2P_DEFAULT_PACKET_MAX_SIZE = 50000000; // 50000000 bytes maximum packet size
const uint32_t P2P_DEFAULT_PEERS_IN_HANDSHAKE = 250; 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 uint32_t P2P_DEFAULT_PING_CONNECTION_TIMEOUT = 2000; // 2 seconds
const uint64_t P2P_DEFAULT_INVOKE_TIMEOUT = 60 * 2 * 1000; // 2 minutes const uint64_t P2P_DEFAULT_INVOKE_TIMEOUT = 60 * 2 * 1000; // 2 minutes
const size_t P2P_DEFAULT_HANDSHAKE_INVOKE_TIMEOUT = 5000; // 5 seconds const size_t P2P_DEFAULT_HANDSHAKE_INVOKE_TIMEOUT = 5000; // 5 seconds
const char P2P_STAT_TRUSTED_PUB_KEY[] = "93467628927eaa0b13a4e52e61864a75aa475e67f6b5748eb3fc1d2fe468aed4"; 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* const SEED_NODES[] = { const char* const SEED_NODES[] = {
"seed.bytecoin.org:8080", "seed.bytecoin.org:8080",
@ -122,7 +122,7 @@ const char* const SEED_NODES[] = {
}; };
struct CheckpointData { struct CheckpointData {
uint64_t height; uint32_t height;
const char* blockId; const char* blockId;
}; };
@ -154,7 +154,8 @@ const CheckpointData CHECKPOINTS[] = {
{750300, "5117631dbeb5c14748a91127a515ecbf13f6849e14fda7ee03cd55da41f1710c"}, {750300, "5117631dbeb5c14748a91127a515ecbf13f6849e14fda7ee03cd55da41f1710c"},
{780000, "8dd55a9bae429e3685b90317281e633917023d3512eb7f37372209d1a5fc1070"}, {780000, "8dd55a9bae429e3685b90317281e633917023d3512eb7f37372209d1a5fc1070"},
{785500, "de1a487d70964d25ed6f7de196866f357a293e867ee81313e7fd0352d0126bdd"}, {785500, "de1a487d70964d25ed6f7de196866f357a293e867ee81313e7fd0352d0126bdd"},
{789000, "acef490bbccce3b7b7ae8554a414f55413fbf4ca1472c6359b126a4439bd9f01"} {789000, "acef490bbccce3b7b7ae8554a414f55413fbf4ca1472c6359b126a4439bd9f01"},
{796000, "04e387a00d35db21d4d93d04040b31f22573972a7e61d72cc07d0ab69bcb9c44"}
}; };
} // CryptoNote } // CryptoNote

View file

@ -15,35 +15,35 @@
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>. // along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#include "account.h" #include "Account.h"
#include "cryptonote_serialization.h" #include "CryptoNoteSerialization.h"
namespace CryptoNote { namespace CryptoNote {
//----------------------------------------------------------------- //-----------------------------------------------------------------
account_base::account_base() { AccountBase::AccountBase() {
set_null(); setNull();
} }
//----------------------------------------------------------------- //-----------------------------------------------------------------
void account_base::set_null() { void AccountBase::setNull() {
m_keys = account_keys(); m_keys = AccountKeys();
} }
//----------------------------------------------------------------- //-----------------------------------------------------------------
void account_base::generate() { void AccountBase::generate() {
crypto::generate_keys(m_keys.m_account_address.m_spendPublicKey, m_keys.m_spend_secret_key); Crypto::generate_keys(m_keys.address.spendPublicKey, m_keys.spendSecretKey);
crypto::generate_keys(m_keys.m_account_address.m_viewPublicKey, m_keys.m_view_secret_key); Crypto::generate_keys(m_keys.address.viewPublicKey, m_keys.viewSecretKey);
m_creation_timestamp = time(NULL); m_creation_timestamp = time(NULL);
} }
//----------------------------------------------------------------- //-----------------------------------------------------------------
const account_keys &account_base::get_keys() const { const AccountKeys &AccountBase::getAccountKeys() const {
return m_keys; return m_keys;
} }
void account_base::set_keys(const account_keys &keys) { void AccountBase::setAccountKeys(const AccountKeys &keys) {
m_keys = keys; m_keys = keys;
} }
//----------------------------------------------------------------- //-----------------------------------------------------------------
void account_base::serialize(ISerializer &s) { void AccountBase::serialize(ISerializer &s) {
s(m_keys, "m_keys"); s(m_keys, "m_keys");
s(m_creation_timestamp, "m_creation_timestamp"); s(m_creation_timestamp, "m_creation_timestamp");
} }

View file

@ -17,33 +17,26 @@
#pragma once #pragma once
#include "cryptonote_core/cryptonote_basic.h" #include "CryptoNoteCore/CryptoNoteBasic.h"
#include "crypto/crypto.h" #include "crypto/crypto.h"
namespace CryptoNote { namespace CryptoNote {
template<bool is_store> struct AccountBaseSerializer;
class ISerializer; 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: public:
account_base(); AccountBase();
void generate(); void generate();
const account_keys& get_keys() const; const AccountKeys& getAccountKeys() const;
void set_keys(const account_keys& keys); void setAccountKeys(const AccountKeys& keys);
uint64_t get_createtime() const { return m_creation_timestamp; } uint64_t get_createtime() const { return m_creation_timestamp; }
void set_createtime(uint64_t val) { m_creation_timestamp = val; } void set_createtime(uint64_t val) { m_creation_timestamp = val; }
void serialize(ISerializer& s);
template <class t_archive> template <class t_archive>
inline void serialize(t_archive &a, const unsigned int /*ver*/) { inline void serialize(t_archive &a, const unsigned int /*ver*/) {
@ -51,14 +44,9 @@ namespace CryptoNote {
a & m_creation_timestamp; a & m_creation_timestamp;
} }
void serialize(ISerializer& s);
private: private:
void set_null(); void setNull();
account_keys m_keys; AccountKeys m_keys;
uint64_t m_creation_timestamp; uint64_t m_creation_timestamp;
friend struct AccountBaseSerializer<true>;
friend struct AccountBaseSerializer<false>;
}; };
} }

View 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);
}
}
}

View file

@ -20,10 +20,12 @@
#include <boost/multi_index/random_access_index.hpp> #include <boost/multi_index/random_access_index.hpp>
#include "crypto/hash.h" #include "crypto/hash.h"
#include <list> #include <vector>
namespace CryptoNote namespace CryptoNote
{ {
class ISerializer;
class BlockIndex { class BlockIndex {
public: public:
@ -36,49 +38,47 @@ namespace CryptoNote
} }
// returns true if new element was inserted, false if already exists // 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); auto result = m_container.push_back(h);
return result.second; 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(); 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); auto hi = m_index.find(h);
if (hi == m_index.end()) if (hi == m_index.end())
return false; 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; return true;
} }
size_t size() const { uint32_t size() const {
return m_container.size(); return static_cast<uint32_t>(m_container.size());
} }
void clear() { void clear() {
m_container.clear(); m_container.clear();
} }
crypto::hash getBlockId(uint64_t height) const; Crypto::Hash getBlockId(uint32_t height) const;
bool getBlockIds(uint64_t startHeight, size_t maxCount, std::list<crypto::hash>& items) const; std::vector<Crypto::Hash> getBlockIds(uint32_t startBlockIndex, uint32_t maxCount) const;
bool findSupplement(const std::list<crypto::hash>& ids, uint64_t& offset) const; bool findSupplement(const std::vector<Crypto::Hash>& ids, uint32_t& offset) const;
bool getShortChainHistory(std::list<crypto::hash>& ids) const; std::vector<Crypto::Hash> buildSparseChain(const Crypto::Hash& startBlockId) const;
crypto::hash getTailId() const; Crypto::Hash getTailId() const;
template <class Archive> void serialize(Archive& ar, const unsigned int version) { void serialize(ISerializer& s);
ar & m_container;
}
private: private:
typedef boost::multi_index_container < typedef boost::multi_index_container <
crypto::hash, Crypto::Hash,
boost::multi_index::indexed_by< boost::multi_index::indexed_by<
boost::multi_index::random_access<>, 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; > ContainerT;

382
src/CryptoNoteCore/Blockchain.h Executable file
View 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;
}
}

View 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();
}
}

View 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;
};
}

View 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;
}
}
}

View 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;
};
};
}

View file

@ -15,17 +15,17 @@
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>. // along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#include "checkpoints.h" #include "Checkpoints.h"
#include "Common/StringTools.h" #include "Common/StringTools.h"
using namespace Logging; using namespace Logging;
namespace CryptoNote { 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) { bool Checkpoints::add_checkpoint(uint32_t height, const std::string &hash_str) {
crypto::hash h = null_hash; Crypto::Hash h = NULL_HASH;
if (!Common::podFromHex(hash_str, h)) { if (!Common::podFromHex(hash_str, h)) {
logger(ERROR) << "WRONG HASH IN CHECKPOINTS!!!"; logger(ERROR) << "WRONG HASH IN CHECKPOINTS!!!";
@ -41,11 +41,11 @@ bool checkpoints::add_checkpoint(uint64_t height, const std::string &hash_str) {
return true; 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); 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 { bool &is_a_checkpoint) const {
auto it = m_points.find(height); auto it = m_points.find(height);
is_a_checkpoint = it != m_points.end(); 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; bool ignored;
return check_block(height, h, ignored); return check_block(height, h, ignored);
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool checkpoints::is_alternative_block_allowed(uint64_t blockchain_height, bool Checkpoints::is_alternative_block_allowed(uint32_t blockchain_height,
uint64_t block_height) const { uint32_t block_height) const {
if (0 == block_height) if (0 == block_height)
return false; return false;
@ -80,7 +80,7 @@ bool checkpoints::is_alternative_block_allowed(uint64_t blockchain_height,
return true; return true;
--it; --it;
uint64_t checkpoint_height = it->first; uint32_t checkpoint_height = it->first;
return checkpoint_height < block_height; return checkpoint_height < block_height;
} }
} }

View file

@ -17,24 +17,24 @@
#pragma once #pragma once
#include <map> #include <map>
#include "cryptonote_basic_impl.h" #include "CryptoNoteBasicImpl.h"
#include <Logging/LoggerRef.h> #include <Logging/LoggerRef.h>
namespace CryptoNote namespace CryptoNote
{ {
class checkpoints class Checkpoints
{ {
public: public:
checkpoints(Logging::ILogger& log); Checkpoints(Logging::ILogger& log);
bool add_checkpoint(uint64_t height, const std::string& hash_str); bool add_checkpoint(uint32_t height, const std::string& hash_str);
bool is_in_checkpoint_zone(uint64_t height) const; bool is_in_checkpoint_zone(uint32_t height) const;
bool check_block(uint64_t height, const crypto::hash& h) const; bool check_block(uint32_t height, const Crypto::Hash& h) const;
bool check_block(uint64_t height, const crypto::hash& h, bool& is_a_checkpoint) const; bool check_block(uint32_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 is_alternative_block_allowed(uint32_t blockchain_height, uint32_t block_height) const;
private: private:
std::map<uint64_t, crypto::hash> m_points; std::map<uint32_t, Crypto::Hash> m_points;
Logging::LoggerRef logger; Logging::LoggerRef logger;
}; };
} }

1031
src/CryptoNoteCore/Core.cpp Executable file

File diff suppressed because it is too large Load diff

194
src/CryptoNoteCore/Core.h Executable file
View 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;
};
}

View file

@ -17,13 +17,13 @@
#include "CoreConfig.h" #include "CoreConfig.h"
#include "Common/util.h" #include "Common/Util.h"
#include "Common/command_line.h" #include "Common/CommandLine.h"
namespace CryptoNote { namespace CryptoNote {
CoreConfig::CoreConfig() { CoreConfig::CoreConfig() {
configFolder = tools::get_default_data_dir(); configFolder = Tools::getDefaultDataDirectory();
} }
void CoreConfig::init(const boost::program_options::variables_map& options) { void CoreConfig::init(const boost::program_options::variables_map& options) {

View file

@ -15,12 +15,15 @@
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>. // along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#include "WalletServiceErrorCodes.h" #include "CryptoNoteBasic.h"
#include "crypto/crypto.h"
namespace PaymentService { namespace CryptoNote {
namespace error {
WalletServiceErrorCategory WalletServiceErrorCategory::INSTANCE; KeyPair generateKeyPair() {
KeyPair k;
Crypto::generate_keys(k.publicKey, k.secretKey);
return k;
}
} //namespace error }
} //namespace PaymentService

View 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);
}
}

View file

@ -15,18 +15,22 @@
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>. // along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#include "cryptonote_basic_impl.h" #include "CryptoNoteBasicImpl.h"
#include "serialization/binary_utils.h" #include "CryptoNoteFormatUtils.h"
#include "serialization/vector.h" #include "CryptoNoteTools.h"
#include "cryptonote_format_utils.h" #include "CryptoNoteSerialization.h"
#include "Common/base58.h"
#include "Common/Base58.h"
#include "crypto/hash.h" #include "crypto/hash.h"
#include "Common/int-util.h" #include "Common/int-util.h"
using namespace Crypto;
using namespace Common;
namespace CryptoNote { namespace CryptoNote {
/************************************************************************/ /************************************************************************/
/* Cryptonote helper functions */ /* CryptoNote helper functions */
/************************************************************************/ /************************************************************************/
//----------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------
uint64_t getPenalizedAmount(uint64_t amount, size_t medianSize, size_t currentBlockSize) { 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) { std::string getAccountAddressAsStr(uint64_t prefix, const AccountPublicAddress& adr) {
blobdata blob; BinaryArray ba;
bool r = t_serializable_object_to_blob(adr, blob); bool r = toBinaryArray(adr, ba);
assert(r); assert(r);
return tools::base58::encode_addr(prefix, blob); return Tools::Base58::encode_addr(prefix, Common::asString(ba));
} }
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
bool is_coinbase(const Transaction& tx) { bool is_coinbase(const Transaction& tx) {
if(tx.vin.size() != 1) { if(tx.inputs.size() != 1) {
return false; return false;
} }
if(tx.vin[0].type() != typeid(TransactionInputGenerate)) { if(tx.inputs[0].type() != typeid(BaseInput)) {
return false; return false;
} }
@ -77,17 +81,18 @@ namespace CryptoNote {
} }
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
bool parseAccountAddressString(uint64_t& prefix, AccountPublicAddress& adr, const std::string& str) { bool parseAccountAddressString(uint64_t& prefix, AccountPublicAddress& adr, const std::string& str) {
blobdata data; std::string data;
return return
tools::base58::decode_addr(str, prefix, data) && Tools::Base58::decode_addr(str, prefix, data) &&
::serialization::parse_binary(data, adr) && fromBinaryArray(adr, asBinaryArray(data)) &&
crypto::check_key(adr.m_spendPublicKey) && // ::serialization::parse_binary(data, adr) &&
crypto::check_key(adr.m_viewPublicKey); check_key(adr.spendPublicKey) &&
check_key(adr.viewPublicKey);
} }
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
bool operator ==(const CryptoNote::Transaction& a, const CryptoNote::Transaction& b) { 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) { 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) { bool parse_hash256(const std::string& str_hash, Crypto::Hash& hash) {
if (!Common::podFromHex(str_hash, hash)) { return Common::podFromHex(str_hash, hash);
std::cout << "invalid hash format: <" << str_hash << '>' << std::endl;
return false;
}
return true;
} }

View file

@ -20,7 +20,7 @@
#include "Common/StringTools.h" #include "Common/StringTools.h"
#include "crypto/crypto.h" #include "crypto/crypto.h"
#include "crypto/hash.h" #include "crypto/hash.h"
#include "cryptonote_core/cryptonote_basic.h" #include "CryptoNoteCore/CryptoNoteBasic.h"
namespace CryptoNote { namespace CryptoNote {
@ -28,16 +28,16 @@ namespace CryptoNote {
/* */ /* */
/************************************************************************/ /************************************************************************/
template<class t_array> 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)]); 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); uint64_t getPenalizedAmount(uint64_t amount, size_t medianSize, size_t currentBlockSize);
std::string getAccountAddressAsStr(uint64_t prefix, const AccountPublicAddress& adr); 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) << ">"; 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 { 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::PublicKey &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::SecretKey &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::KeyDerivation &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::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::Signature &v) { return print256(o, v); }
inline std::ostream &operator <<(std::ostream &o, const crypto::hash &v) { return print256(o, v); } inline std::ostream &operator <<(std::ostream &o, const Crypto::Hash &v) { return print256(o, v); }
} }

View 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);
}
}

View 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);
}

View file

@ -15,34 +15,52 @@
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>. // along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#include "cryptonote_serialization.h" #include "CryptoNoteSerialization.h"
#include "account.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 <algorithm>
#include <sstream>
#include <stdexcept>
#include <boost/variant/static_visitor.hpp> #include <boost/variant/static_visitor.hpp>
#include <boost/variant/apply_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 { 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> { struct BinaryVariantTagGetter: boost::static_visitor<uint8_t> {
uint8_t operator()(const CryptoNote::TransactionInputGenerate) { return 0xff; } uint8_t operator()(const CryptoNote::BaseInput) { return 0xff; }
uint8_t operator()(const CryptoNote::TransactionInputToScript) { return 0x0; } uint8_t operator()(const CryptoNote::KeyInput) { return 0x2; }
uint8_t operator()(const CryptoNote::TransactionInputToScriptHash) { return 0x1; } uint8_t operator()(const CryptoNote::MultisignatureInput) { return 0x3; }
uint8_t operator()(const CryptoNote::TransactionInputToKey) { return 0x2; } uint8_t operator()(const CryptoNote::KeyOutput) { return 0x2; }
uint8_t operator()(const CryptoNote::TransactionInputMultisignature) { return 0x3; } uint8_t operator()(const CryptoNote::MultisignatureOutput) { 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::Transaction) { return 0xcc; } uint8_t operator()(const CryptoNote::Transaction) { return 0xcc; }
uint8_t operator()(const CryptoNote::Block) { return 0xbb; } uint8_t operator()(const CryptoNote::Block) { return 0xbb; }
}; };
@ -50,49 +68,30 @@ struct BinaryVariantTagGetter: boost::static_visitor<uint8_t> {
struct VariantSerializer : boost::static_visitor<> { struct VariantSerializer : boost::static_visitor<> {
VariantSerializer(CryptoNote::ISerializer& serializer, const std::string& name) : s(serializer), name(name) {} VariantSerializer(CryptoNote::ISerializer& serializer, const std::string& name) : s(serializer), name(name) {}
void operator() (CryptoNote::TransactionInputGenerate& param) { s(param, name); } template <typename T>
void operator() (CryptoNote::TransactionInputToScript& param) { s(param, name); } void operator() (T& 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); }
CryptoNote::ISerializer& s; CryptoNote::ISerializer& s;
const std::string& name; std::string name;
}; };
void getVariantValue(CryptoNote::ISerializer& serializer, uint8_t tag, CryptoNote::TransactionInput& in) { void getVariantValue(CryptoNote::ISerializer& serializer, uint8_t tag, CryptoNote::TransactionInput& in) {
switch(tag) { switch(tag) {
case 0xff: { case 0xff: {
CryptoNote::TransactionInputGenerate v; CryptoNote::BaseInput v;
serializer(v, "data"); serializer(v, "value");
in = v;
break;
}
case 0x0: {
CryptoNote::TransactionInputToScript v;
serializer(v, "data");
in = v;
break;
}
case 0x1: {
CryptoNote::TransactionInputToScriptHash v;
serializer(v, "data");
in = v; in = v;
break; break;
} }
case 0x2: { case 0x2: {
CryptoNote::TransactionInputToKey v; CryptoNote::KeyInput v;
serializer(v, "data"); serializer(v, "value");
in = v; in = v;
break; break;
} }
case 0x3: { case 0x3: {
CryptoNote::TransactionInputMultisignature v; CryptoNote::MultisignatureInput v;
serializer(v, "data"); serializer(v, "value");
in = v; in = v;
break; 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) { void getVariantValue(CryptoNote::ISerializer& serializer, uint8_t tag, CryptoNote::TransactionOutputTarget& out) {
switch(tag) { 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: { case 0x2: {
CryptoNote::TransactionOutputToKey v; CryptoNote::KeyOutput v;
serializer(v, "data"); serializer(v, "data");
out = v; out = v;
break; break;
} }
case 0x3: { case 0x3: {
CryptoNote::TransactionOutputMultisignature v; CryptoNote::MultisignatureOutput v;
serializer(v, "data"); serializer(v, "data");
out = v; out = v;
break; break;
@ -137,8 +124,8 @@ bool serializePod(T& v, Common::StringView name, CryptoNote::ISerializer& serial
return serializer.binary(&v, sizeof(v), name); return serializer.binary(&v, sizeof(v), name);
} }
bool serializeVarintVector(std::vector<uint64_t>& vector, CryptoNote::ISerializer& serializer, Common::StringView name) { bool serializeVarintVector(std::vector<uint32_t>& vector, CryptoNote::ISerializer& serializer, Common::StringView name) {
std::size_t size = vector.size(); size_t size = vector.size();
if (!serializer.beginArray(size, name)) { if (!serializer.beginArray(size, name)) {
vector.clear(); 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); 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); 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); 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); return serializePod(keyImage, name, serializer);
} }
@ -179,10 +166,17 @@ bool serialize(chacha8_iv& chacha, Common::StringView name, CryptoNote::ISeriali
return serializePod(chacha, name, serializer); 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); 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) { void serialize(TransactionPrefix& txP, ISerializer& serializer) {
serializer(txP.version, "version"); serializer(txP.version, "version");
if (CURRENT_TRANSACTION_VERSION < txP.version) {
throw std::runtime_error("Wrong transaction version");
}
serializer(txP.unlockTime, "unlock_time"); serializer(txP.unlockTime, "unlock_time");
serializer(txP.vin, "vin"); serializer(txP.inputs, "vin");
serializer(txP.vout, "vout"); serializer(txP.outputs, "vout");
serializeAsBinary(txP.extra, "extra", serializer); serializeAsBinary(txP.extra, "extra", serializer);
} }
void serialize(Transaction& tx, ISerializer& serializer) { void serialize(Transaction& tx, ISerializer& serializer) {
serializer(tx.version, "version"); serialize(static_cast<TransactionPrefix&>(tx), serializer);
serializer(tx.unlockTime, "unlock_time");
serializer(tx.vin, "vin");
serializer(tx.vout, "vout");
serializeAsBinary(tx.extra, "extra", serializer);
std::size_t sigSize = tx.vin.size(); size_t sigSize = tx.inputs.size();
//TODO: make arrays without sizes //TODO: make arrays without sizes
// serializer.beginArray(sigSize, "signatures"); // serializer.beginArray(sigSize, "signatures");
tx.signatures.resize(sigSize);
if (serializer.type() == ISerializer::INPUT) {
tx.signatures.resize(sigSize);
}
bool signaturesNotExpected = tx.signatures.empty(); 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"); throw std::runtime_error("Serialization error: unexpected signatures size");
} }
for (size_t i = 0; i < tx.vin.size(); ++i) { for (size_t i = 0; i < tx.inputs.size(); ++i) {
size_t signatureSize = Transaction::getSignatureSize(tx.vin[i]); size_t signatureSize = getSignaturesCount(tx.inputs[i]);
if (signaturesNotExpected) { if (signaturesNotExpected) {
if (signatureSize == 0) { if (signatureSize == 0) {
continue; continue;
@ -227,12 +225,18 @@ void serialize(Transaction& tx, ISerializer& serializer) {
if (signatureSize != tx.signatures[i].size()) { if (signatureSize != tx.signatures[i].size()) {
throw std::runtime_error("Serialization error: unexpected signatures size"); throw std::runtime_error("Serialization error: unexpected signatures size");
} }
} else {
tx.signatures[i].resize(signatureSize);
}
for (crypto::signature& sig: tx.signatures[i]) { for (Crypto::Signature& sig : tx.signatures[i]) {
serializePod(sig, "", serializer); 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(); // serializer.endArray();
@ -254,22 +258,19 @@ void serialize(TransactionInput& in, ISerializer& serializer) {
} }
} }
void serialize(TransactionInputGenerate& gen, ISerializer& serializer) { void serialize(BaseInput& gen, ISerializer& serializer) {
serializer(gen.height, "height"); serializer(gen.blockIndex, "height");
} }
void serialize(TransactionInputToScript& script, ISerializer& serializer) {} void serialize(KeyInput& key, ISerializer& serializer) {
void serialize(TransactionInputToScriptHash& scripthash, ISerializer& serializer) {}
void serialize(TransactionInputToKey& key, ISerializer& serializer) {
serializer(key.amount, "amount"); serializer(key.amount, "amount");
serializeVarintVector(key.keyOffsets, serializer, "key_offsets"); serializeVarintVector(key.outputIndexes, serializer, "key_offsets");
serializer(key.keyImage, "k_image"); serializer(key.keyImage, "k_image");
} }
void serialize(TransactionInputMultisignature& multisignature, ISerializer& serializer) { void serialize(MultisignatureInput& multisignature, ISerializer& serializer) {
serializer(multisignature.amount, "amount"); serializer(multisignature.amount, "amount");
serializer(multisignature.signatures, "signatures"); serializer(multisignature.signatureCount, "signatures");
serializer(multisignature.outputIndex, "outputIndex"); serializer(multisignature.outputIndex, "outputIndex");
} }
@ -294,16 +295,13 @@ void serialize(TransactionOutputTarget& output, ISerializer& serializer) {
} }
} }
void serialize(TransactionOutputToScript& script, ISerializer& serializer) {} void serialize(KeyOutput& key, ISerializer& serializer) {
void serialize(TransactionOutputToScriptHash& scripthash, ISerializer& serializer) {}
void serialize(TransactionOutputToKey& key, ISerializer& serializer) {
serializer(key.key, "key"); serializer(key.key, "key");
} }
void serialize(TransactionOutputMultisignature& multisignature, ISerializer& serializer) { void serialize(MultisignatureOutput& multisignature, ISerializer& serializer) {
serializer(multisignature.keys, "keys"); serializer(multisignature.keys, "keys");
serializer(multisignature.requiredSignatures, "required_signatures"); serializer(multisignature.requiredSignatureCount, "required_signatures");
} }
void serialize(ParentBlockSerializer& pbs, ISerializer& serializer) { 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_parentBlock.minorVersion, "minorVersion");
serializer(pbs.m_timestamp, "timestamp"); 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"); serializer.binary(&pbs.m_nonce, sizeof(pbs.m_nonce), "nonce");
if (pbs.m_hashingSerialization) { if (pbs.m_hashingSerialization) {
crypto::hash minerTxHash; Crypto::Hash minerTxHash;
if (!get_transaction_hash(pbs.m_parentBlock.minerTx, minerTxHash)) { if (!getObjectHash(pbs.m_parentBlock.baseTransaction, minerTxHash)) {
throw std::runtime_error("Get transaction hash error"); throw std::runtime_error("Get transaction hash error");
} }
crypto::hash merkleRoot; Crypto::Hash merkleRoot;
crypto::tree_hash_from_branch(pbs.m_parentBlock.minerTxBranch.data(), pbs.m_parentBlock.minerTxBranch.size(), minerTxHash, 0, merkleRoot); Crypto::tree_hash_from_branch(pbs.m_parentBlock.baseTransactionBranch.data(), pbs.m_parentBlock.baseTransactionBranch.size(), minerTxHash, 0, merkleRoot);
serializer(merkleRoot, "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"); serializer(txNum, "numberOfTransactions");
pbs.m_parentBlock.numberOfTransactions = static_cast<uint16_t>(txNum); pbs.m_parentBlock.transactionCount = static_cast<uint16_t>(txNum);
if (pbs.m_parentBlock.numberOfTransactions < 1) { if (pbs.m_parentBlock.transactionCount < 1) {
throw std::runtime_error("Wrong transactions number"); throw std::runtime_error("Wrong transactions number");
} }
@ -341,29 +339,29 @@ void serialize(ParentBlockSerializer& pbs, ISerializer& serializer) {
return; 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 (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"); throw std::runtime_error("Wrong miner transaction branch size");
} }
} else { } 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! //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(hash, "");
} }
serializer(pbs.m_parentBlock.minerTx, "minerTx"); serializer(pbs.m_parentBlock.baseTransaction, "minerTx");
tx_extra_merge_mining_tag mmTag; TransactionExtraMergeMiningTag mmTag;
if (!get_mm_tag_from_extra(pbs.m_parentBlock.minerTx.extra, mmTag)) { if (!getMergeMiningTagFromExtra(pbs.m_parentBlock.baseTransaction.extra, mmTag)) {
throw std::runtime_error("Can't get extra merge mining tag"); 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"); throw std::runtime_error("Wrong merge mining tag depth");
} }
@ -377,7 +375,7 @@ void serialize(ParentBlockSerializer& pbs, ISerializer& serializer) {
// serializer(m_parentBlock.blockchainBranch, "blockchainBranch"); // serializer(m_parentBlock.blockchainBranch, "blockchainBranch");
//TODO: Make arrays with computable size! This code won't work with json serialization! //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, ""); serializer(hash, "");
} }
} }
@ -391,10 +389,10 @@ void serializeBlockHeader(BlockHeader& header, ISerializer& serializer) {
serializer(header.minorVersion, "minor_version"); serializer(header.minorVersion, "minor_version");
if (header.majorVersion == BLOCK_MAJOR_VERSION_1) { if (header.majorVersion == BLOCK_MAJOR_VERSION_1) {
serializer(header.timestamp, "timestamp"); serializer(header.timestamp, "timestamp");
serializer(header.prevId, "prev_id"); serializer(header.previousBlockHash, "prev_id");
serializer.binary(&header.nonce, sizeof(header.nonce), "nonce"); serializer.binary(&header.nonce, sizeof(header.nonce), "nonce");
} else if (header.majorVersion == BLOCK_MAJOR_VERSION_2) { } else if (header.majorVersion == BLOCK_MAJOR_VERSION_2) {
serializer(header.prevId, "prev_id"); serializer(header.previousBlockHash, "prev_id");
} else { } else {
throw std::runtime_error("Wrong major version"); throw std::runtime_error("Wrong major version");
} }
@ -412,42 +410,48 @@ void serialize(Block& block, ISerializer& serializer) {
serializer(parentBlockSerializer, "parent_block"); serializer(parentBlockSerializer, "parent_block");
} }
serializer(block.minerTx, "miner_tx"); serializer(block.baseTransaction, "miner_tx");
serializer(block.txHashes, "tx_hashes"); serializer(block.transactionHashes, "tx_hashes");
} }
void serialize(AccountPublicAddress& address, ISerializer& serializer) { void serialize(AccountPublicAddress& address, ISerializer& serializer) {
serializer(address.m_spendPublicKey, "m_spend_public_key"); serializer(address.spendPublicKey, "m_spend_public_key");
serializer(address.m_viewPublicKey, "m_view_public_key"); serializer(address.viewPublicKey, "m_view_public_key");
} }
void serialize(account_keys& keys, ISerializer& s) { void serialize(AccountKeys& keys, ISerializer& s) {
s(keys.m_account_address, "m_account_address"); s(keys.address, "m_account_address");
s(keys.m_spend_secret_key, "m_spend_secret_key"); s(keys.spendSecretKey, "m_spend_secret_key");
s(keys.m_view_secret_key, "m_view_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); uint64_t depth = static_cast<uint64_t>(tag.depth);
serializer(depth, "depth"); serializer(depth, "depth");
tag.depth = static_cast<size_t>(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) { if (serializer.type() == ISerializer::OUTPUT) {
std::stringstream stream; std::string field;
BinaryOutputStreamSerializer output(stream); StringOutputStream os(field);
BinaryOutputStreamSerializer output(os);
doSerialize(tag, output); doSerialize(tag, output);
std::string field = stream.str();
serializer(field, ""); serializer(field, "");
} else { } else {
std::string field; std::string field;
serializer(field, ""); serializer(field, "");
std::stringstream stream(field); MemoryInputStream stream(field.data(), field.size());
BinaryInputStreamSerializer input(stream); BinaryInputStreamSerializer input(stream);
doSerialize(tag, input); doSerialize(tag, input);
} }
} }
void serialize(KeyPair& keyPair, ISerializer& serializer) {
serializer(keyPair.secretKey, "secret_key");
serializer(keyPair.publicKey, "public_key");
}
} //namespace CryptoNote } //namespace CryptoNote

View file

@ -17,47 +17,51 @@
#pragma once #pragma once
#include "cryptonote_basic.h" #include "CryptoNoteBasic.h"
#include "serialization/ISerializer.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(PublicKey& pubKey, Common::StringView name, CryptoNote::ISerializer& serializer);
bool serialize(secret_key& secKey, 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(Hash& h, Common::StringView name, CryptoNote::ISerializer& serializer);
bool serialize(chacha8_iv& chacha, 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(KeyImage& keyImage, Common::StringView name, CryptoNote::ISerializer& serializer);
bool serialize(signature& sig, 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 { namespace CryptoNote {
void serialize(ParentBlockSerializer& pbs, ISerializer& serializer);
struct AccountKeys;
struct TransactionExtraMergeMiningTag;
void serialize(TransactionPrefix& txP, ISerializer& serializer); void serialize(TransactionPrefix& txP, ISerializer& serializer);
void serialize(Transaction& tx, ISerializer& serializer); void serialize(Transaction& tx, ISerializer& serializer);
void serialize(TransactionInput& in, ISerializer& serializer); void serialize(TransactionInput& in, ISerializer& serializer);
void serialize(TransactionOutput& in, ISerializer& serializer); void serialize(TransactionOutput& in, ISerializer& serializer);
void serialize(TransactionInputGenerate& gen, ISerializer& serializer); void serialize(BaseInput& gen, ISerializer& serializer);
void serialize(TransactionInputToScript& script, ISerializer& serializer); void serialize(KeyInput& key, ISerializer& serializer);
void serialize(TransactionInputToScriptHash& scripthash, ISerializer& serializer); void serialize(MultisignatureInput& multisignature, ISerializer& serializer);
void serialize(TransactionInputToKey& key, ISerializer& serializer);
void serialize(TransactionInputMultisignature& multisignature, ISerializer& serializer);
void serialize(TransactionOutput& output, ISerializer& serializer); void serialize(TransactionOutput& output, ISerializer& serializer);
void serialize(TransactionOutputTarget& 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(BlockHeader& header, ISerializer& serializer);
void serialize(Block& block, 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(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 }

View file

@ -17,7 +17,7 @@
#pragma once #pragma once
#include "serialization/ISerializer.h" #include "Serialization/ISerializer.h"
namespace CryptoNote namespace CryptoNote
{ {

View 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);
}
);
}
}

View 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);
}

View file

@ -19,15 +19,21 @@
#include <cctype> #include <cctype>
#include <boost/algorithm/string/trim.hpp> #include <boost/algorithm/string/trim.hpp>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include "../Common/base58.h" #include "../Common/Base58.h"
#include "../Common/int-util.h" #include "../Common/int-util.h"
#include "account.h" #include "../Common/StringTools.h"
#include "cryptonote_basic_impl.h"
#include "cryptonote_format_utils.h" #include "Account.h"
#include "CryptoNoteBasicImpl.h"
#include "CryptoNoteFormatUtils.h"
#include "CryptoNoteTools.h"
#include "TransactionExtra.h"
#include "UpgradeDetector.h" #include "UpgradeDetector.h"
#undef ERROR #undef ERROR
using namespace Logging; using namespace Logging;
using namespace Common;
namespace CryptoNote { namespace CryptoNote {
@ -48,6 +54,7 @@ bool Currency::init() {
m_blocksCacheFileName = "testnet_" + m_blocksCacheFileName; m_blocksCacheFileName = "testnet_" + m_blocksCacheFileName;
m_blockIndexesFileName = "testnet_" + m_blockIndexesFileName; m_blockIndexesFileName = "testnet_" + m_blockIndexesFileName;
m_txPoolFileName = "testnet_" + m_txPoolFileName; m_txPoolFileName = "testnet_" + m_txPoolFileName;
m_blockchinIndicesFileName = "testnet_" + m_blockchinIndicesFileName;
} }
return true; return true;
@ -58,17 +65,17 @@ bool Currency::generateGenesisBlock() {
//account_public_address ac = boost::value_initialized<AccountPublicAddress>(); //account_public_address ac = boost::value_initialized<AccountPublicAddress>();
//std::vector<size_t> sz; //std::vector<size_t> sz;
//constructMinerTx(0, 0, 0, 0, 0, ac, m_genesisBlock.minerTx); // zero fee in genesis //constructMinerTx(0, 0, 0, 0, 0, ac, m_genesisBlock.baseTransaction); // zero fee in genesis
//blobdata txb = tx_to_blob(m_genesisBlock.minerTx); //BinaryArray txb = toBinaryArray(m_genesisBlock.baseTransaction);
//std::string hex_tx_represent = Common::toHex(txb); //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 // Hard code coinbase tx in genesis block, because through generating tx use random, but genesis should be always the same
std::string genesisCoinbaseTxHex = "010a01ff0001ffffffffffff0f029b2e4c0281c0b02e7c53291a94d1d0cbff8883f8024f5142ee494ffbbd08807121013c086a48c15fb637a96991bc6d53caf77068b5ba6eeb3c82357228c49790584a"; std::string genesisCoinbaseTxHex = "010a01ff0001ffffffffffff0f029b2e4c0281c0b02e7c53291a94d1d0cbff8883f8024f5142ee494ffbbd08807121013c086a48c15fb637a96991bc6d53caf77068b5ba6eeb3c82357228c49790584a";
blobdata minerTxBlob; BinaryArray minerTxBlob;
bool r = bool r =
hexToBlob(genesisCoinbaseTxHex, minerTxBlob) && fromHex(genesisCoinbaseTxHex, minerTxBlob) &&
parse_and_validate_tx_from_blob(minerTxBlob, m_genesisBlock.minerTx); fromBinaryArray(m_genesisBlock.baseTransaction, minerTxBlob);
if (!r) { if (!r) {
logger(ERROR, BRIGHT_RED) << "failed to parse coinbase tx from hard coded blob"; 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, bool Currency::constructMinerTx(uint32_t height, size_t medianSize, uint64_t alreadyGeneratedCoins, size_t currentBlockSize,
uint64_t fee, const AccountPublicAddress& minerAddress, Transaction& tx, 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 { bool penalizeFee/* = false*/) const {
tx.vin.clear(); tx.inputs.clear();
tx.vout.clear(); tx.outputs.clear();
tx.extra.clear(); tx.extra.clear();
KeyPair txkey = KeyPair::generate(); KeyPair txkey = generateKeyPair();
add_tx_pub_key_to_extra(tx, txkey.pub); addTransactionPublicKeyToExtra(tx.extra, txkey.publicKey);
if (!extraNonce.empty()) { if (!extraNonce.empty()) {
if (!add_extra_nonce_to_tx_extra(tx.extra, extraNonce)) { if (!addExtraNonceToTransactionExtra(tx.extra, extraNonce)) {
return false; return false;
} }
} }
TransactionInputGenerate in; BaseInput in;
in.height = height; in.blockIndex = height;
uint64_t blockReward; uint64_t blockReward;
int64_t emissionChange; 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"; logger(INFO) << "Block is too big";
return false; return false;
} }
#if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
logger(DEBUGGING) << "Creating block template: reward " << blockReward << ", fee " << fee;
#endif
std::vector<uint64_t> outAmounts; std::vector<uint64_t> outAmounts;
decompose_amount_into_digits(blockReward, m_defaultDustThreshold, 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; uint64_t summaryAmounts = 0;
for (size_t no = 0; no < outAmounts.size(); no++) { for (size_t no = 0; no < outAmounts.size(); no++) {
crypto::key_derivation derivation = boost::value_initialized<crypto::key_derivation>(); Crypto::KeyDerivation derivation = boost::value_initialized<Crypto::KeyDerivation>();
crypto::public_key outEphemeralPubKey = boost::value_initialized<crypto::public_key>(); 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)) { if (!(r)) {
logger(ERROR, BRIGHT_RED) logger(ERROR, BRIGHT_RED)
<< "while creating outs: failed to generate_key_derivation(" << "while creating outs: failed to generate_key_derivation("
<< minerAddress.m_viewPublicKey << ", " << txkey.sec << ")"; << minerAddress.viewPublicKey << ", " << txkey.secretKey << ")";
return false; 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)) { if (!(r)) {
logger(ERROR, BRIGHT_RED) logger(ERROR, BRIGHT_RED)
<< "while creating outs: failed to derive_public_key(" << "while creating outs: failed to derive_public_key("
<< derivation << ", " << no << ", " << derivation << ", " << no << ", "
<< minerAddress.m_spendPublicKey << ")"; << minerAddress.spendPublicKey << ")";
return false; return false;
} }
TransactionOutputToKey tk; KeyOutput tk;
tk.key = outEphemeralPubKey; tk.key = outEphemeralPubKey;
TransactionOutput out; TransactionOutput out;
summaryAmounts += out.amount = outAmounts[no]; summaryAmounts += out.amount = outAmounts[no];
out.target = tk; out.target = tk;
tx.vout.push_back(out); tx.outputs.push_back(out);
} }
if (!(summaryAmounts == blockReward)) { if (!(summaryAmounts == blockReward)) {
@ -201,12 +205,12 @@ bool Currency::constructMinerTx(uint32_t height, size_t medianSize, uint64_t alr
tx.version = CURRENT_TRANSACTION_VERSION; tx.version = CURRENT_TRANSACTION_VERSION;
//lock //lock
tx.unlockTime = height + m_minedMoneyUnlockWindow; tx.unlockTime = height + m_minedMoneyUnlockWindow;
tx.vin.push_back(in); tx.inputs.push_back(in);
return true; return true;
} }
std::string Currency::accountAddressAsString(const account_base& account) const { std::string Currency::accountAddressAsString(const AccountBase& account) const {
return getAccountAddressAsStr(m_publicAddressBase58Prefix, account.get_keys().m_account_address); return getAccountAddressAsStr(m_publicAddressBase58Prefix, account.getAccountKeys().address);
} }
std::string Currency::accountAddressAsString(const AccountPublicAddress& accountPublicAddress) const { 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; return (low + timeSpan - 1) / timeSpan;
} }
bool Currency::checkProofOfWorkV1(crypto::cn_context& context, const Block& block, difficulty_type currentDiffic, bool Currency::checkProofOfWorkV1(Crypto::cn_context& context, const Block& block, difficulty_type currentDiffic,
crypto::hash& proofOfWork) const { Crypto::Hash& proofOfWork) const {
if (BLOCK_MAJOR_VERSION_1 != block.majorVersion) { if (BLOCK_MAJOR_VERSION_1 != block.majorVersion) {
return false; return false;
} }
@ -329,8 +333,8 @@ bool Currency::checkProofOfWorkV1(crypto::cn_context& context, const Block& bloc
return check_hash(proofOfWork, currentDiffic); return check_hash(proofOfWork, currentDiffic);
} }
bool Currency::checkProofOfWorkV2(crypto::cn_context& context, const Block& block, difficulty_type currentDiffic, bool Currency::checkProofOfWorkV2(Crypto::cn_context& context, const Block& block, difficulty_type currentDiffic,
crypto::hash& proofOfWork) const { Crypto::Hash& proofOfWork) const {
if (BLOCK_MAJOR_VERSION_2 != block.majorVersion) { if (BLOCK_MAJOR_VERSION_2 != block.majorVersion) {
return false; return false;
} }
@ -343,8 +347,8 @@ bool Currency::checkProofOfWorkV2(crypto::cn_context& context, const Block& bloc
return false; return false;
} }
tx_extra_merge_mining_tag mmTag; TransactionExtraMergeMiningTag mmTag;
if (!get_mm_tag_from_extra(block.parentBlock.minerTx.extra, mmTag)) { if (!getMergeMiningTagFromExtra(block.parentBlock.baseTransaction.extra, mmTag)) {
logger(ERROR) << "merge mining tag wasn't found in extra of the parent block miner transaction"; logger(ERROR) << "merge mining tag wasn't found in extra of the parent block miner transaction";
return false; return false;
} }
@ -353,16 +357,16 @@ bool Currency::checkProofOfWorkV2(crypto::cn_context& context, const Block& bloc
return false; return false;
} }
crypto::hash auxBlockHeaderHash; Crypto::Hash auxBlockHeaderHash;
if (!get_aux_block_header_hash(block, auxBlockHeaderHash)) { if (!get_aux_block_header_hash(block, auxBlockHeaderHash)) {
return false; return false;
} }
crypto::hash auxBlocksMerkleRoot; Crypto::Hash auxBlocksMerkleRoot;
crypto::tree_hash_from_branch(block.parentBlock.blockchainBranch.data(), block.parentBlock.blockchainBranch.size(), Crypto::tree_hash_from_branch(block.parentBlock.blockchainBranch.data(), block.parentBlock.blockchainBranch.size(),
auxBlockHeaderHash, &m_genesisBlockHash, auxBlocksMerkleRoot); 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"; logger(ERROR, BRIGHT_YELLOW) << "Aux block hash wasn't found in merkle tree";
return false; return false;
} }
@ -370,7 +374,7 @@ bool Currency::checkProofOfWorkV2(crypto::cn_context& context, const Block& bloc
return true; 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) { switch (block.majorVersion) {
case BLOCK_MAJOR_VERSION_1: return checkProofOfWorkV1(context, block, currentDiffic, proofOfWork); case BLOCK_MAJOR_VERSION_1: return checkProofOfWorkV1(context, block, currentDiffic, proofOfWork);
case BLOCK_MAJOR_VERSION_2: return checkProofOfWorkV2(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); blocksCacheFileName(parameters::CRYPTONOTE_BLOCKSCACHE_FILENAME);
blockIndexesFileName(parameters::CRYPTONOTE_BLOCKINDEXES_FILENAME); blockIndexesFileName(parameters::CRYPTONOTE_BLOCKINDEXES_FILENAME);
txPoolFileName(parameters::CRYPTONOTE_POOLDATA_FILENAME); txPoolFileName(parameters::CRYPTONOTE_POOLDATA_FILENAME);
blockchinIndicesFileName(parameters::CRYPTONOTE_BLOCKCHAIN_INDICES_FILENAME);
testnet(false); testnet(false);
} }

View file

@ -21,15 +21,16 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <boost/utility.hpp> #include <boost/utility.hpp>
#include "../cryptonote_config.h" #include "../CryptoNoteConfig.h"
#include "../crypto/hash.h" #include "../crypto/hash.h"
#include "../cryptonote_protocol/blobdatatype.h"
#include "../Logging/LoggerRef.h" #include "../Logging/LoggerRef.h"
#include "cryptonote_basic.h" #include "CryptoNoteBasic.h"
#include "difficulty.h" #include "Difficulty.h"
namespace CryptoNote { namespace CryptoNote {
class AccountBase;
class Currency { class Currency {
public: public:
uint64_t maxBlockHeight() const { return m_maxBlockHeight; } uint64_t maxBlockHeight() const { return m_maxBlockHeight; }
@ -83,11 +84,12 @@ public:
const std::string& blocksCacheFileName() const { return m_blocksCacheFileName; } const std::string& blocksCacheFileName() const { return m_blocksCacheFileName; }
const std::string& blockIndexesFileName() const { return m_blockIndexesFileName; } const std::string& blockIndexesFileName() const { return m_blockIndexesFileName; }
const std::string& txPoolFileName() const { return m_txPoolFileName; } const std::string& txPoolFileName() const { return m_txPoolFileName; }
const std::string& blockchinIndicesFileName() const { return m_blockchinIndicesFileName; }
bool isTestnet() const { return m_testnet; } bool isTestnet() const { return m_testnet; }
const Block& genesisBlock() const { return m_genesisBlock; } 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 getBlockReward(size_t medianSize, size_t currentBlockSize, uint64_t alreadyGeneratedCoins, uint64_t fee,
bool penalizeFee, uint64_t& reward, int64_t& emissionChange) const; 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, bool constructMinerTx(uint32_t height, size_t medianSize, uint64_t alreadyGeneratedCoins, size_t currentBlockSize,
uint64_t fee, const AccountPublicAddress& minerAddress, Transaction& tx, 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; std::string accountAddressAsString(const AccountPublicAddress& accountPublicAddress) const;
bool parseAccountAddressString(const std::string& str, AccountPublicAddress& addr) 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; 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 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 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 checkProofOfWork(Crypto::cn_context& context, const Block& block, difficulty_type currentDiffic, Crypto::Hash& proofOfWork) const;
private: private:
Currency(Logging::ILogger& log) : logger(log, "currency") { Currency(Logging::ILogger& log) : logger(log, "currency") {
@ -166,11 +168,12 @@ private:
std::string m_blocksCacheFileName; std::string m_blocksCacheFileName;
std::string m_blockIndexesFileName; std::string m_blockIndexesFileName;
std::string m_txPoolFileName; std::string m_txPoolFileName;
std::string m_blockchinIndicesFileName;
bool m_testnet; bool m_testnet;
Block m_genesisBlock; Block m_genesisBlock;
crypto::hash m_genesisBlockHash; Crypto::Hash m_genesisBlockHash;
Logging::LoggerRef logger; Logging::LoggerRef logger;
@ -234,7 +237,8 @@ public:
CurrencyBuilder& blocksCacheFileName(const std::string& val) { m_currency.m_blocksCacheFileName = val; return *this; } 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& 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& 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; } CurrencyBuilder& testnet(bool val) { m_currency.m_testnet = val; return *this; }
private: private:

View file

@ -23,24 +23,15 @@
#include "Common/int-util.h" #include "Common/int-util.h"
#include "crypto/hash.h" #include "crypto/hash.h"
#include "cryptonote_config.h" #include "CryptoNoteConfig.h"
#include "difficulty.h" #include "Difficulty.h"
namespace CryptoNote { namespace CryptoNote {
using std::size_t;
using std::uint64_t; using std::uint64_t;
using std::vector; using std::vector;
#if defined(_MSC_VER) #if defined(__SIZEOF_INT128__)
#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
static inline void mul(uint64_t a, uint64_t b, uint64_t &low, uint64_t &high) { static inline void mul(uint64_t a, uint64_t b, uint64_t &low, uint64_t &high) {
typedef unsigned __int128 uint128_t; typedef unsigned __int128 uint128_t;
@ -49,6 +40,12 @@ namespace CryptoNote {
high = (uint64_t) (res >> 64); 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 #endif
static inline bool cadd(uint64_t a, uint64_t b) { 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); 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; uint64_t low, high, top, cur;
// First check the highest word, this will most likely fail for a random hash. // First check the highest word, this will most likely fail for a random hash.
mul(swap64le(((const uint64_t *) &hash)[3]), difficulty, top, high); 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