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_PACKAGE_ALL_DEPENDENCY ON)
set(CMAKE_SUPPRESS_REGENERATION ON)
#enable_testing()
enable_testing()
project(Bytecoin)
@ -62,11 +62,14 @@ else()
else()
set(MINGW_FLAG "")
endif()
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND NOT (CMAKE_C_COMPILER_VERSION VERSION_LESS 5.1))
set(WARNINGS "${WARNINGS} -Wno-error=odr")
endif()
set(C_WARNINGS "-Waggregate-return -Wnested-externs -Wold-style-definition -Wstrict-prototypes")
set(CXX_WARNINGS "-Wno-reorder -Wno-missing-field-initializers")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 ${MINGW_FLAG} ${WARNINGS} ${C_WARNINGS} ${ARCH_FLAG} -maes")
if(NOT APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ${MINGW_FLAG} ${WARNINGS} ${CXX_WARNINGS} ${ARCH_FLAG} -maes")
if(APPLE)

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
- High-level API for blockchain explorer

View file

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

114
include/CryptoNote.h Normal file
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
#include <sstream>
#include "json_archive.h"
#include <cstdint>
namespace serialization {
namespace Crypto {
template<class T>
std::string dump_json(T &v)
{
std::stringstream ostr;
json_archive<true> oar(ostr);
assert(serialization::serialize(oar, v));
return ostr.str();
struct Hash {
uint8_t data[32];
};
} // namespace serialization
struct PublicKey {
uint8_t data[32];
};
struct SecretKey {
uint8_t data[32];
};
struct KeyDerivation {
uint8_t data[32];
};
struct KeyImage {
uint8_t data[32];
};
struct Signature {
uint8_t data[64];
};
}

View file

@ -29,7 +29,7 @@ public:
virtual ~IBlockchainObserver() {}
virtual void blockchainUpdated(const std::vector<BlockDetails>& newBlocks, const std::vector<BlockDetails>& orphanedBlocks) {}
virtual void poolUpdated(const std::vector<TransactionDetails>& newTransactions, const std::vector<std::pair<std::array<uint8_t, 32>, TransactionRemoveReason>>& removedTransactions) {}
virtual void poolUpdated(const std::vector<TransactionDetails>& newTransactions, const std::vector<std::pair<Crypto::Hash, TransactionRemoveReason>>& removedTransactions) {}
virtual void blockchainSynchronized(const BlockDetails& topBlock) {}
};
@ -44,13 +44,16 @@ public:
virtual void init() = 0;
virtual void shutdown() = 0;
virtual bool getBlocks(const std::vector<uint64_t>& blockHeights, std::vector<std::vector<BlockDetails>>& blocks) = 0;
virtual bool getBlocks(const std::vector<std::array<uint8_t, 32>>& blockHashes, std::vector<BlockDetails>& blocks) = 0;
virtual bool getBlocks(const std::vector<uint32_t>& blockHeights, std::vector<std::vector<BlockDetails>>& blocks) = 0;
virtual bool getBlocks(const std::vector<Crypto::Hash>& blockHashes, std::vector<BlockDetails>& blocks) = 0;
virtual bool getBlocks(uint64_t timestampBegin, uint64_t timestampEnd, uint32_t blocksNumberLimit, std::vector<BlockDetails>& blocks, uint32_t& blocksNumberWithinTimestamps) = 0;
virtual bool getBlockchainTop(BlockDetails& topBlock) = 0;
virtual bool getTransactions(const std::vector<std::array<uint8_t, 32>>& transactionHashes, std::vector<TransactionDetails>& transactions) = 0;
virtual bool getPoolState(const std::vector<std::array<uint8_t, 32>>& knownPoolTransactionHashes, std::array<uint8_t, 32> knownBlockchainTop, bool& isBlockchainActual, std::vector<TransactionDetails>& newTransactions, std::vector<std::array<uint8_t, 32>>& removedTransactions) = 0;
virtual bool getTransactions(const std::vector<Crypto::Hash>& transactionHashes, std::vector<TransactionDetails>& transactions) = 0;
virtual bool getTransactionsByPaymentId(const Crypto::Hash& paymentId, std::vector<TransactionDetails>& transactions) = 0;
virtual bool getPoolTransactions(uint64_t timestampBegin, uint64_t timestampEnd, uint32_t transactionsNumberLimit, std::vector<TransactionDetails>& transactions, uint64_t& transactionsNumberWithinTimestamps) = 0;
virtual bool getPoolState(const std::vector<Crypto::Hash>& knownPoolTransactionHashes, Crypto::Hash knownBlockchainTop, bool& isBlockchainActual, std::vector<TransactionDetails>& newTransactions, std::vector<Crypto::Hash>& removedTransactions) = 0;
virtual uint64_t getRewardBlocksWindow() = 0;
virtual uint64_t getFullRewardMaxBlockSize(uint8_t majorVersion) = 0;

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 "crypto/crypto.h"
#include "cryptonote_core/cryptonote_basic.h"
#include "cryptonote_protocol/cryptonote_protocol_defs.h"
#include "rpc/core_rpc_server_commands_defs.h"
#include "CryptoNoteCore/CryptoNoteBasic.h"
#include "CryptoNoteProtocol/CryptoNoteProtocolDefinitions.h"
#include "Rpc/CoreRpcServerCommandsDefinitions.h"
#include "BlockchainExplorerData.h"
#include "ITransaction.h"
namespace CryptoNote {
@ -35,15 +36,15 @@ class INodeObserver {
public:
virtual ~INodeObserver() {}
virtual void peerCountUpdated(size_t count) {}
virtual void localBlockchainUpdated(uint64_t height) {}
virtual void lastKnownBlockHeightUpdated(uint64_t height) {}
virtual void localBlockchainUpdated(uint32_t height) {}
virtual void lastKnownBlockHeightUpdated(uint32_t height) {}
virtual void poolChanged() {}
virtual void blockchainSynchronized(uint64_t topHeight) {}
virtual void blockchainSynchronized(uint32_t topHeight) {}
};
struct OutEntry {
uint64_t outGlobalIndex;
crypto::public_key outKey;
uint32_t outGlobalIndex;
Crypto::PublicKey outKey;
};
struct OutsForAmount {
@ -51,10 +52,16 @@ struct OutsForAmount {
std::vector<OutEntry> outs;
};
struct BlockCompleteEntry {
crypto::hash blockHash;
CryptoNote::blobdata block;
std::list<CryptoNote::blobdata> txs;
struct TransactionShortInfo {
Crypto::Hash txId;
TransactionPrefix txPrefix;
};
struct BlockShortEntry {
Crypto::Hash blockHash;
bool hasBlock;
CryptoNote::Block block;
std::vector<TransactionShortInfo> txsShortInfo;
};
class INode {
@ -69,22 +76,26 @@ public:
virtual bool shutdown() = 0;
virtual size_t getPeerCount() const = 0;
virtual uint64_t getLastLocalBlockHeight() const = 0;
virtual uint64_t getLastKnownBlockHeight() const = 0;
virtual uint64_t getLocalBlockCount() const = 0;
virtual uint64_t getKnownBlockCount() const = 0;
virtual uint32_t getLastLocalBlockHeight() const = 0;
virtual uint32_t getLastKnownBlockHeight() const = 0;
virtual uint32_t getLocalBlockCount() const = 0;
virtual uint32_t getKnownBlockCount() const = 0;
virtual uint64_t getLastLocalBlockTimestamp() const = 0;
virtual void relayTransaction(const Transaction& transaction, const Callback& callback) = 0;
virtual void getRandomOutsByAmounts(std::vector<uint64_t>&& amounts, uint64_t outsCount, std::vector<CryptoNote::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount>& result, const Callback& callback) = 0;
virtual void getNewBlocks(std::list<crypto::hash>&& knownBlockIds, std::list<CryptoNote::block_complete_entry>& newBlocks, uint64_t& startHeight, const Callback& callback) = 0;
virtual void getTransactionOutsGlobalIndices(const crypto::hash& transactionHash, std::vector<uint64_t>& outsGlobalIndices, const Callback& callback) = 0;
virtual void queryBlocks(std::list<crypto::hash>&& knownBlockIds, uint64_t timestamp, std::list<BlockCompleteEntry>& newBlocks, uint64_t& startHeight, const Callback& callback) = 0;
virtual void getPoolSymmetricDifference(std::vector<crypto::hash>&& known_pool_tx_ids, crypto::hash known_block_id, bool& is_bc_actual, std::vector<Transaction>& new_txs, std::vector<crypto::hash>& deleted_tx_ids, const Callback& callback) = 0;
virtual void getNewBlocks(std::vector<Crypto::Hash>&& knownBlockIds, std::vector<CryptoNote::block_complete_entry>& newBlocks, uint32_t& startHeight, const Callback& callback) = 0;
virtual void getTransactionOutsGlobalIndices(const Crypto::Hash& transactionHash, std::vector<uint32_t>& outsGlobalIndices, const Callback& callback) = 0;
virtual void queryBlocks(std::vector<Crypto::Hash>&& knownBlockIds, uint64_t timestamp, std::vector<BlockShortEntry>& newBlocks, uint32_t& startHeight, const Callback& callback) = 0;
virtual void getPoolSymmetricDifference(std::vector<Crypto::Hash>&& knownPoolTxIds, Crypto::Hash knownBlockId, bool& isBcActual, std::vector<std::unique_ptr<ITransactionReader>>& newTxs, std::vector<Crypto::Hash>& deletedTxIds, const Callback& callback) = 0;
virtual void getMultisignatureOutputByGlobalIndex(uint64_t amount, uint32_t gindex, MultisignatureOutput& out, const Callback& callback) = 0;
virtual void getBlocks(const std::vector<uint64_t>& blockHeights, std::vector<std::vector<BlockDetails>>& blocks, const Callback& callback) = 0;
virtual void getBlocks(const std::vector<crypto::hash>& blockHashes, std::vector<BlockDetails>& blocks, const Callback& callback) = 0;
virtual void getTransactions(const std::vector<crypto::hash>& transactionHashes, std::vector<TransactionDetails>& transactions, const Callback& callback) = 0;
virtual void getBlocks(const std::vector<uint32_t>& blockHeights, std::vector<std::vector<BlockDetails>>& blocks, const Callback& callback) = 0;
virtual void getBlocks(const std::vector<Crypto::Hash>& blockHashes, std::vector<BlockDetails>& blocks, const Callback& callback) = 0;
virtual void getBlocks(uint64_t timestampBegin, uint64_t timestampEnd, uint32_t blocksNumberLimit, std::vector<BlockDetails>& blocks, uint32_t& blocksNumberWithinTimestamps, const Callback& callback) = 0;
virtual void getTransactions(const std::vector<Crypto::Hash>& transactionHashes, std::vector<TransactionDetails>& transactions, const Callback& callback) = 0;
virtual void getTransactionsByPaymentId(const Crypto::Hash& paymentId, std::vector<TransactionDetails>& transactions, const Callback& callback) = 0;
virtual void getPoolTransactions(uint64_t timestampBegin, uint64_t timestampEnd, uint32_t transactionsNumberLimit, std::vector<TransactionDetails>& transactions, uint64_t& transactionsNumberWithinTimestamps, const Callback& callback) = 0;
virtual void isSynchronized(bool& syncStatus, const Callback& callback) = 0;
};

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

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

View file

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

View file

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

156
include/IWallet.h Normal file → Executable file
View file

@ -17,113 +17,99 @@
#pragma once
#include <array>
#include <cstdint>
#include <istream>
#include <limits>
#include <ostream>
#include <string>
#include <system_error>
#include <vector>
#include "CryptoNote.h"
namespace CryptoNote {
typedef size_t TransactionId;
typedef size_t TransferId;
typedef std::array<uint8_t, 32> TransactionHash;
const size_t WALLET_INVALID_TRANSACTION_ID = std::numeric_limits<size_t>::max();
const size_t WALLET_INVALID_TRANSFER_ID = std::numeric_limits<size_t>::max();
const uint32_t WALLET_UNCONFIRMED_TRANSACTION_HEIGHT = std::numeric_limits<uint32_t>::max();
struct Transfer {
enum class WalletTransactionState : uint8_t {
SUCCEEDED = 0,
FAILED,
CANCELLED
};
enum WalletEventType {
TRANSACTION_CREATED,
TRANSACTION_UPDATED,
BALANCE_UNLOCKED
};
struct WalletTransactionCreatedData {
size_t transactionIndex;
};
struct WalletTransactionUpdatedData {
size_t transactionIndex;
};
struct WalletEvent {
WalletEventType type;
union {
WalletTransactionCreatedData transactionCreated;
WalletTransactionUpdatedData transactionUpdated;
};
};
struct WalletTransaction {
WalletTransactionState state;
uint64_t timestamp;
uint32_t blockHeight;
Crypto::Hash hash;
int64_t totalAmount;
uint64_t fee;
uint64_t creationTime;
uint64_t unlockTime;
std::string extra;
};
struct WalletTransfer {
std::string address;
int64_t amount;
};
const TransactionId INVALID_TRANSACTION_ID = std::numeric_limits<TransactionId>::max();
const TransferId INVALID_TRANSFER_ID = std::numeric_limits<TransferId>::max();
const uint64_t UNCONFIRMED_TRANSACTION_HEIGHT = std::numeric_limits<uint64_t>::max();
enum class TransactionState : uint8_t {
Active, // --> {Deleted}
Deleted, // --> {Active}
Sending, // --> {Active, Cancelled, Failed}
Cancelled, // --> {}
Failed // --> {}
};
struct TransactionInfo {
TransferId firstTransferId;
size_t transferCount;
int64_t totalAmount;
uint64_t fee;
uint64_t sentTime;
uint64_t unlockTime;
TransactionHash hash;
bool isCoinbase;
uint64_t blockHeight;
uint64_t timestamp;
std::string extra;
TransactionState state;
};
typedef std::array<uint8_t, 32> WalletPublicKey;
typedef std::array<uint8_t, 32> WalletSecretKey;
struct WalletAccountKeys {
WalletPublicKey viewPublicKey;
WalletSecretKey viewSecretKey;
WalletPublicKey spendPublicKey;
WalletSecretKey spendSecretKey;
};
class IWalletObserver {
public:
virtual ~IWalletObserver() {}
virtual void initCompleted(std::error_code result) {}
virtual void saveCompleted(std::error_code result) {}
virtual void synchronizationProgressUpdated(uint64_t current, uint64_t total) {}
virtual void synchronizationCompleted(std::error_code result) {}
virtual void actualBalanceUpdated(uint64_t actualBalance) {}
virtual void pendingBalanceUpdated(uint64_t pendingBalance) {}
virtual void externalTransactionCreated(TransactionId transactionId) {}
virtual void sendTransactionCompleted(TransactionId transactionId, std::error_code result) {}
virtual void transactionUpdated(TransactionId transactionId) {}
};
class IWallet {
public:
virtual ~IWallet() {} ;
virtual void addObserver(IWalletObserver* observer) = 0;
virtual void removeObserver(IWalletObserver* observer) = 0;
virtual ~IWallet() {}
virtual void initAndGenerate(const std::string& password) = 0;
virtual void initAndLoad(std::istream& source, const std::string& password) = 0;
virtual void initWithKeys(const WalletAccountKeys& accountKeys, const std::string& password) = 0;
virtual void initialize(const std::string& password) = 0;
virtual void load(std::istream& source, const std::string& password) = 0;
virtual void shutdown() = 0;
virtual void reset() = 0;
virtual void save(std::ostream& destination, bool saveDetailed = true, bool saveCache = true) = 0;
virtual void changePassword(const std::string& oldPassword, const std::string& newPassword) = 0;
virtual void save(std::ostream& destination, bool saveDetails = true, bool saveCache = true) = 0;
virtual std::error_code changePassword(const std::string& oldPassword, const std::string& newPassword) = 0;
virtual size_t getAddressCount() const = 0;
virtual std::string getAddress(size_t index) const = 0;
virtual std::string createAddress() = 0;
virtual std::string createAddress(const KeyPair& spendKey) = 0;
virtual void deleteAddress(const std::string& address) = 0;
virtual std::string getAddress() = 0;
virtual uint64_t getActualBalance() const = 0;
virtual uint64_t getActualBalance(const std::string& address) const = 0;
virtual uint64_t getPendingBalance() const = 0;
virtual uint64_t getPendingBalance(const std::string& address) const = 0;
virtual uint64_t actualBalance() = 0;
virtual uint64_t pendingBalance() = 0;
virtual size_t getTransactionCount() const = 0;
virtual WalletTransaction getTransaction(size_t transactionIndex) const = 0;
virtual size_t getTransactionTransferCount(size_t transactionIndex) const = 0;
virtual WalletTransfer getTransactionTransfer(size_t transactionIndex, size_t transferIndex) const = 0;
virtual size_t getTransactionCount() = 0;
virtual size_t getTransferCount() = 0;
virtual size_t transfer(const WalletTransfer& destination, uint64_t fee, uint64_t mixIn = 0, const std::string& extra = "", uint64_t unlockTimestamp = 0) = 0;
virtual size_t transfer(const std::vector<WalletTransfer>& destinations, uint64_t fee, uint64_t mixIn = 0, const std::string& extra = "", uint64_t unlockTimestamp = 0) = 0;
virtual size_t transfer(const std::string& sourceAddress, const WalletTransfer& destination, uint64_t fee, uint64_t mixIn = 0, const std::string& extra = "", uint64_t unlockTimestamp = 0) = 0;
virtual size_t transfer(const std::string& sourceAddress, const std::vector<WalletTransfer>& destinations, uint64_t fee, uint64_t mixIn = 0, const std::string& extra = "", uint64_t unlockTimestamp = 0) = 0;
virtual TransactionId findTransactionByTransferId(TransferId transferId) = 0;
virtual bool getTransaction(TransactionId transactionId, TransactionInfo& transaction) = 0;
virtual bool getTransfer(TransferId transferId, Transfer& transfer) = 0;
virtual void start() = 0;
virtual void stop() = 0;
virtual TransactionId sendTransaction(const Transfer& transfer, uint64_t fee, const std::string& extra = "", uint64_t mixIn = 0, uint64_t unlockTimestamp = 0) = 0;
virtual TransactionId sendTransaction(const std::vector<Transfer>& transfers, uint64_t fee, const std::string& extra = "", uint64_t mixIn = 0, uint64_t unlockTimestamp = 0) = 0;
virtual std::error_code cancelTransaction(size_t transferId) = 0;
virtual void getAccountKeys(WalletAccountKeys& keys) = 0;
//blocks until an event occured
virtual WalletEvent getEvent() = 0;
};
}

116
include/IWalletLegacy.h Normal file
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 <memory>
#include "cryptonote_core/cryptonote_format_utils.h"
#include "CryptoNoteCore/CryptoNoteFormatUtils.h"
#include "CryptoNoteConfig.h"
#include "BlockchainExplorerErrors.h"
#include "ITransaction.h"
using namespace Logging;
using namespace Crypto;
namespace CryptoNote {
class ContextCounterHolder
{
public:
ContextCounterHolder(BlockchainExplorer::AsyncContextCounter& counter) : counter(counter) {}
~ContextCounterHolder() { counter.delAsyncContext(); }
private:
BlockchainExplorer::AsyncContextCounter& counter;
};
class NodeRequest {
public:
NodeRequest(const std::function<void(const INode::Callback&)>& request) : requestFunc(request) {}
std::error_code performBlocking() {
requestFunc(std::bind(&NodeRequest::completeionCallback, this, std::placeholders::_1));
return promise.get_future().get();
std::promise<std::error_code> promise;
std::future<std::error_code> future = promise.get_future();
requestFunc([&](std::error_code c){
blockingCompleteionCallback(std::move(promise), c);
});
return future.get();
}
void performAsync(const INode::Callback& callback) {
requestFunc(callback);
void performAsync(BlockchainExplorer::AsyncContextCounter& asyncContextCounter, const INode::Callback& callback) {
asyncContextCounter.addAsyncContext();
requestFunc(std::bind(&NodeRequest::asyncCompleteionCallback, callback, std::ref(asyncContextCounter), std::placeholders::_1));
}
private:
void completeionCallback(std::error_code ec) {
void blockingCompleteionCallback(std::promise<std::error_code> promise, std::error_code ec) {
promise.set_value(ec);
}
std::promise<std::error_code> promise;
static void asyncCompleteionCallback(const INode::Callback& callback, BlockchainExplorer::AsyncContextCounter& asyncContextCounter, std::error_code ec) {
ContextCounterHolder counterHolder(asyncContextCounter);
try {
callback(ec);
} catch (...) {
return;
}
}
const std::function<void(const INode::Callback&)> requestFunc;
};
BlockchainExplorer::BlockchainExplorer(INode& node, Logging::ILogger& logger) : node(node), logger(logger, "BlockchainExplorer"), state(NOT_INITIALIZED) {}
BlockchainExplorer::BlockchainExplorer(INode& node, Logging::ILogger& logger) :
node(node),
logger(logger, "BlockchainExplorer"),
state(NOT_INITIALIZED),
synchronized(false),
observersCounter(0) {}
BlockchainExplorer::~BlockchainExplorer() {}
@ -59,7 +91,7 @@ bool BlockchainExplorer::addObserver(IBlockchainObserver* observer) {
if (state.load() != INITIALIZED) {
throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED));
}
observersCounter.fetch_add(1);
return observerManager.add(observer);
}
@ -67,7 +99,9 @@ bool BlockchainExplorer::removeObserver(IBlockchainObserver* observer) {
if (state.load() != INITIALIZED) {
throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED));
}
if (observersCounter.load() != 0) {
observersCounter.fetch_sub(1);
}
return observerManager.remove(observer);
}
@ -98,10 +132,11 @@ void BlockchainExplorer::shutdown() {
throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED));
}
node.removeObserver(this);
asyncContextCounter.waitAsyncContextsFinish();
state.store(NOT_INITIALIZED);
}
bool BlockchainExplorer::getBlocks(const std::vector<uint64_t>& blockHeights, std::vector<std::vector<BlockDetails>>& blocks) {
bool BlockchainExplorer::getBlocks(const std::vector<uint32_t>& blockHeights, std::vector<std::vector<BlockDetails>>& blocks) {
if (state.load() != INITIALIZED) {
throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED));
}
@ -111,7 +146,7 @@ bool BlockchainExplorer::getBlocks(const std::vector<uint64_t>& blockHeights, st
std::bind(
static_cast<
void(INode::*)(
const std::vector<uint64_t>&,
const std::vector<uint32_t>&,
std::vector<std::vector<BlockDetails>>&,
const INode::Callback&
)
@ -131,7 +166,7 @@ bool BlockchainExplorer::getBlocks(const std::vector<uint64_t>& blockHeights, st
return true;
}
bool BlockchainExplorer::getBlocks(const std::vector<std::array<uint8_t, 32>>& blockHashes, std::vector<BlockDetails>& blocks) {
bool BlockchainExplorer::getBlocks(const std::vector<Hash>& blockHashes, std::vector<BlockDetails>& blocks) {
if (state.load() != INITIALIZED) {
throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED));
}
@ -141,13 +176,13 @@ bool BlockchainExplorer::getBlocks(const std::vector<std::array<uint8_t, 32>>& b
std::bind(
static_cast<
void(INode::*)(
const std::vector<crypto::hash>&,
const std::vector<Hash>&,
std::vector<BlockDetails>&,
const INode::Callback&
)
>(&INode::getBlocks),
std::ref(node),
std::cref(reinterpret_cast<const std::vector<crypto::hash>&>(blockHashes)),
std::cref(reinterpret_cast<const std::vector<Hash>&>(blockHashes)),
std::ref(blocks),
std::placeholders::_1
)
@ -161,15 +196,50 @@ bool BlockchainExplorer::getBlocks(const std::vector<std::array<uint8_t, 32>>& b
return true;
}
bool BlockchainExplorer::getBlocks(uint64_t timestampBegin, uint64_t timestampEnd, uint32_t blocksNumberLimit, std::vector<BlockDetails>& blocks, uint32_t& blocksNumberWithinTimestamps) {
if (state.load() != INITIALIZED) {
throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED));
}
logger(DEBUGGING) << "Get blocks by timestamp request came.";
NodeRequest request(
std::bind(
static_cast<
void(INode::*)(
uint64_t,
uint64_t,
uint32_t,
std::vector<BlockDetails>&,
uint32_t&,
const INode::Callback&
)
>(&INode::getBlocks),
std::ref(node),
timestampBegin,
timestampEnd,
blocksNumberLimit,
std::ref(blocks),
std::ref(blocksNumberWithinTimestamps),
std::placeholders::_1
)
);
std::error_code ec = request.performBlocking();
if (ec) {
logger(ERROR) << "Can't get blocks by timestamp: " << ec.message();
throw std::system_error(ec);
}
return true;
}
bool BlockchainExplorer::getBlockchainTop(BlockDetails& topBlock) {
if (state.load() != INITIALIZED) {
throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED));
}
logger(DEBUGGING) << "Get blockchain top request came.";
uint64_t lastHeight = node.getLastLocalBlockHeight();
uint32_t lastHeight = node.getLastLocalBlockHeight();
std::vector<uint64_t> heights;
std::vector<uint32_t> heights;
heights.push_back(std::move(lastHeight));
std::vector<std::vector<BlockDetails>> blocks;
@ -195,49 +265,105 @@ bool BlockchainExplorer::getBlockchainTop(BlockDetails& topBlock) {
return true;
}
bool BlockchainExplorer::getTransactions(const std::vector<std::array<uint8_t, 32>>& transactionHashes, std::vector<TransactionDetails>& transactions) {
bool BlockchainExplorer::getTransactions(const std::vector<Hash>& transactionHashes, std::vector<TransactionDetails>& transactions) {
if (state.load() != INITIALIZED) {
throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED));
}
logger(DEBUGGING) << "Get transactions request came.";
logger(DEBUGGING) << "Get transactions by hash request came.";
NodeRequest request(
std::bind(
&INode::getTransactions,
static_cast<
void(INode::*)(
const std::vector<Hash>&,
std::vector<TransactionDetails>&,
const INode::Callback&
)
>(&INode::getTransactions),
std::ref(node),
std::cref(reinterpret_cast<const std::vector<crypto::hash>&>(transactionHashes)),
std::cref(reinterpret_cast<const std::vector<Hash>&>(transactionHashes)),
std::ref(transactions),
std::placeholders::_1
)
);
std::error_code ec = request.performBlocking();
if (ec) {
logger(ERROR) << "Can't get transactions: " << ec.message();
logger(ERROR) << "Can't get transactions by hash: " << ec.message();
throw std::system_error(ec);
}
return true;
}
bool BlockchainExplorer::getPoolState(const std::vector<std::array<uint8_t, 32>>& knownPoolTransactionHashes, std::array<uint8_t, 32> knownBlockchainTopHash, bool& isBlockchainActual, std::vector<TransactionDetails>& newTransactions, std::vector<std::array<uint8_t, 32>>& removedTransactions) {
bool BlockchainExplorer::getPoolTransactions(uint64_t timestampBegin, uint64_t timestampEnd, uint32_t transactionsNumberLimit, std::vector<TransactionDetails>& transactions, uint64_t& transactionsNumberWithinTimestamps) {
if (state.load() != INITIALIZED) {
throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED));
}
logger(DEBUGGING) << "Get transactions by timestamp request came.";
NodeRequest request(
std::bind(
&INode::getPoolTransactions,
std::ref(node),
timestampBegin,
timestampEnd,
transactionsNumberLimit,
std::ref(transactions),
std::ref(transactionsNumberWithinTimestamps),
std::placeholders::_1
)
);
std::error_code ec = request.performBlocking();
if (ec) {
logger(ERROR) << "Can't get transactions by timestamp: " << ec.message();
throw std::system_error(ec);
}
return true;
}
bool BlockchainExplorer::getTransactionsByPaymentId(const Hash& paymentId, std::vector<TransactionDetails>& transactions) {
if (state.load() != INITIALIZED) {
throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED));
}
logger(DEBUGGING) << "Get transactions by payment id request came.";
NodeRequest request(
std::bind(
&INode::getTransactionsByPaymentId,
std::ref(node),
std::cref(reinterpret_cast<const Hash&>(paymentId)),
std::ref(transactions),
std::placeholders::_1
)
);
std::error_code ec = request.performBlocking();
if (ec) {
logger(ERROR) << "Can't get transactions by payment id: " << ec.message();
throw std::system_error(ec);
}
return true;
}
bool BlockchainExplorer::getPoolState(const std::vector<Hash>& knownPoolTransactionHashes, Hash knownBlockchainTopHash, bool& isBlockchainActual, std::vector<TransactionDetails>& newTransactions, std::vector<Hash>& removedTransactions) {
if (state.load() != INITIALIZED) {
throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED));
}
logger(DEBUGGING) << "Get pool state request came.";
std::vector<Transaction> rawNewTransactions;
std::vector<std::unique_ptr<ITransactionReader>> rawNewTransactions;
NodeRequest request(
[&](const INode::Callback& callback) {
std::vector<crypto::hash> hashes;
for (const std::array<uint8_t, 32>& hash : knownPoolTransactionHashes) {
hashes.push_back(std::move(reinterpret_cast<const crypto::hash&>(hash)));
std::vector<Hash> hashes;
for (Hash hash : knownPoolTransactionHashes) {
hashes.push_back(std::move(hash));
}
node.getPoolSymmetricDifference(
std::move(hashes),
reinterpret_cast<crypto::hash&>(knownBlockchainTopHash),
reinterpret_cast<Hash&>(knownBlockchainTopHash),
isBlockchainActual,
rawNewTransactions,
reinterpret_cast<std::vector<crypto::hash>&>(removedTransactions),
removedTransactions,
callback
);
}
@ -248,10 +374,10 @@ bool BlockchainExplorer::getPoolState(const std::vector<std::array<uint8_t, 32>>
throw std::system_error(ec);
}
std::vector<std::array<uint8_t, 32>> newTransactionsHashes;
for (const Transaction& rawTransaction : rawNewTransactions) {
crypto::hash transactionHash = get_transaction_hash(rawTransaction);
newTransactionsHashes.push_back(std::move(reinterpret_cast<const std::array<uint8_t, 32>&>(transactionHash)));
std::vector<Hash> newTransactionsHashes;
for (const auto& rawTransaction : rawNewTransactions) {
Hash transactionHash = rawTransaction->getTransactionHash();
newTransactionsHashes.push_back(std::move(transactionHash));
}
return getTransactions(newTransactionsHashes, newTransactions);
@ -295,27 +421,32 @@ bool BlockchainExplorer::isSynchronized() {
logger(ERROR) << "Can't get synchronization status: " << ec.message();
throw std::system_error(ec);
}
synchronized.store(syncStatus);
return syncStatus;
}
void BlockchainExplorer::poolChanged() {
logger(DEBUGGING) << "Got poolChanged notification.";
if (!synchronized.load() || observersCounter.load() == 0) {
return;
}
std::unique_lock<std::mutex> lock(mutex);
std::shared_ptr<std::vector<Transaction>> rawNewTransactionsPtr = std::make_shared<std::vector<Transaction>>();
std::shared_ptr<std::vector<crypto::hash>> removedTransactionsPtr = std::make_shared<std::vector<crypto::hash>>();
std::shared_ptr<std::vector<std::unique_ptr<ITransactionReader>>> rawNewTransactionsPtr = std::make_shared<std::vector<std::unique_ptr<ITransactionReader>>>();
std::shared_ptr<std::vector<Hash>> removedTransactionsPtr = std::make_shared<std::vector<Hash>>();
std::shared_ptr<bool> isBlockchainActualPtr = std::make_shared<bool>(false);
NodeRequest request(
[this, rawNewTransactionsPtr, removedTransactionsPtr, isBlockchainActualPtr](const INode::Callback& callback) {
std::vector<crypto::hash> hashes;
for (const crypto::hash& hash : knownPoolState) {
std::vector<Hash> hashes;
for (const Hash& hash : knownPoolState) {
hashes.push_back(std::move(hash));
}
node.getPoolSymmetricDifference(
std::move(hashes),
reinterpret_cast<crypto::hash&>(knownBlockchainTop.hash),
reinterpret_cast<Hash&>(knownBlockchainTop.hash),
*isBlockchainActualPtr,
*rawNewTransactionsPtr,
*removedTransactionsPtr,
@ -323,7 +454,7 @@ void BlockchainExplorer::poolChanged() {
);
}
);
request.performAsync(
request.performAsync(asyncContextCounter,
[this, rawNewTransactionsPtr, removedTransactionsPtr, isBlockchainActualPtr](std::error_code ec) {
if (ec) {
logger(ERROR) << "Can't send poolChanged notification because can't get pool symmetric difference: " << ec.message();
@ -336,22 +467,23 @@ void BlockchainExplorer::poolChanged() {
std::unique_lock<std::mutex> lock(mutex);
std::shared_ptr<std::vector<crypto::hash>> newTransactionsHashesPtr = std::make_shared<std::vector<crypto::hash>>();
for (const Transaction& rawTransaction : *rawNewTransactionsPtr) {
crypto::hash transactionHash = get_transaction_hash(rawTransaction);
std::shared_ptr<std::vector<Hash>> newTransactionsHashesPtr = std::make_shared<std::vector<Hash>>();
for (const auto& rawTransaction : *rawNewTransactionsPtr) {
auto hash = rawTransaction->getTransactionHash();
Hash transactionHash = reinterpret_cast<const Hash&>(hash);
bool inserted = knownPoolState.emplace(transactionHash).second;
if (inserted) {
newTransactionsHashesPtr->push_back(std::move(transactionHash));
}
}
std::shared_ptr<std::vector<std::pair<std::array<uint8_t, 32>, TransactionRemoveReason>>> removedTransactionsHashesPtr = std::make_shared<std::vector<std::pair<std::array<uint8_t, 32>, TransactionRemoveReason>>>();
for (const crypto::hash hash : *removedTransactionsPtr) {
std::shared_ptr<std::vector<std::pair<Hash, TransactionRemoveReason>>> removedTransactionsHashesPtr = std::make_shared<std::vector<std::pair<Hash, TransactionRemoveReason>>>();
for (const Hash hash : *removedTransactionsPtr) {
auto iter = knownPoolState.find(hash);
if (iter != knownPoolState.end()) {
removedTransactionsHashesPtr->push_back(
std::move(std::make_pair(
reinterpret_cast<const std::array<uint8_t, 32>&>(hash),
hash,
TransactionRemoveReason::INCLUDED_IN_BLOCK //Can't have real reason here.
))
);
@ -362,14 +494,20 @@ void BlockchainExplorer::poolChanged() {
std::shared_ptr<std::vector<TransactionDetails>> newTransactionsPtr = std::make_shared<std::vector<TransactionDetails>>();
NodeRequest request(
std::bind(
&INode::getTransactions,
static_cast<
void(INode::*)(
const std::vector<Hash>&,
std::vector<TransactionDetails>&,
const INode::Callback&
)
>(&INode::getTransactions),
std::ref(node),
std::cref(*newTransactionsHashesPtr),
std::ref(*newTransactionsPtr),
std::placeholders::_1
)
);
request.performAsync(
request.performAsync(asyncContextCounter,
[this, newTransactionsHashesPtr, newTransactionsPtr, removedTransactionsHashesPtr](std::error_code ec) {
if (ec) {
logger(ERROR) << "Can't send poolChanged notification because can't get transactions: " << ec.message();
@ -386,10 +524,16 @@ void BlockchainExplorer::poolChanged() {
}
void BlockchainExplorer::blockchainSynchronized(uint64_t topHeight) {
void BlockchainExplorer::blockchainSynchronized(uint32_t topHeight) {
logger(DEBUGGING) << "Got blockchainSynchronized notification.";
std::shared_ptr<std::vector<uint64_t>> blockHeightsPtr = std::make_shared<std::vector<uint64_t>>();
synchronized.store(true);
if (observersCounter.load() == 0) {
return;
}
std::shared_ptr<std::vector<uint32_t>> blockHeightsPtr = std::make_shared<std::vector<uint32_t>>();
std::shared_ptr<std::vector<std::vector<BlockDetails>>> blocksPtr = std::make_shared<std::vector<std::vector<BlockDetails>>>();
blockHeightsPtr->push_back(topHeight);
@ -398,7 +542,7 @@ void BlockchainExplorer::blockchainSynchronized(uint64_t topHeight) {
std::bind(
static_cast<
void(INode::*)(
const std::vector<uint64_t>&,
const std::vector<uint32_t>&,
std::vector<std::vector<BlockDetails>>&,
const INode::Callback&
)
@ -410,7 +554,7 @@ void BlockchainExplorer::blockchainSynchronized(uint64_t topHeight) {
)
);
request.performAsync(
request.performAsync(asyncContextCounter,
[this, blockHeightsPtr, blocksPtr, topHeight](std::error_code ec) {
if (ec) {
logger(ERROR) << "Can't send blockchainSynchronized notification because can't get blocks by height: " << ec.message();
@ -439,17 +583,22 @@ void BlockchainExplorer::blockchainSynchronized(uint64_t topHeight) {
);
}
void BlockchainExplorer::localBlockchainUpdated(uint64_t height) {
void BlockchainExplorer::localBlockchainUpdated(uint32_t height) {
logger(DEBUGGING) << "Got localBlockchainUpdated notification.";
if (observersCounter.load() == 0) {
knownBlockchainTopHeight = height;
return;
}
std::unique_lock<std::mutex> lock(mutex);
assert(height >= knownBlockchainTopHeight);
std::shared_ptr<std::vector<uint64_t>> blockHeightsPtr = std::make_shared<std::vector<uint64_t>>();
std::shared_ptr<std::vector<uint32_t>> blockHeightsPtr = std::make_shared<std::vector<uint32_t>>();
std::shared_ptr<std::vector<std::vector<BlockDetails>>> blocksPtr = std::make_shared<std::vector<std::vector<BlockDetails>>>();
for (size_t i = knownBlockchainTopHeight; i <= height; ++i) {
for (uint32_t i = knownBlockchainTopHeight; i <= height; ++i) {
blockHeightsPtr->push_back(i);
}
@ -459,7 +608,7 @@ void BlockchainExplorer::localBlockchainUpdated(uint64_t height) {
std::bind(
static_cast<
void(INode::*)(
const std::vector<uint64_t>&,
const std::vector<uint32_t>&,
std::vector<std::vector<BlockDetails>>&,
const INode::Callback&
)
@ -471,7 +620,7 @@ void BlockchainExplorer::localBlockchainUpdated(uint64_t height) {
)
);
request.performAsync(
request.performAsync(asyncContextCounter,
[this, blockHeightsPtr, blocksPtr](std::error_code ec) {
if (ec) {
logger(ERROR) << "Can't send blockchainUpdated notification because can't get blocks by height: " << ec.message();

29
src/BlockchainExplorer/BlockchainExplorer.h Normal file → Executable file
View file

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

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

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

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

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

View file

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

View file

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

View file

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

View file

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

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

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

View file

@ -16,3 +16,7 @@
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#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
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#include "command_line.h"
#include "CommandLine.h"
namespace command_line
{

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

View file

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

View file

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

View file

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

View file

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

View file

@ -16,3 +16,7 @@
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#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
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#include "MultisignatureOutput.h"
#include "MemoryInputStream.h"
#include <algorithm>
#include <cassert>
#include <cstring> // memcpy
namespace CryptoNote {
namespace Common {
MultisignatureOutput::MultisignatureOutput(uint64_t amount, std::vector<crypto::public_key>&& keys, uint32_t requiredSignatureCount) : amount(amount), keys(std::move(keys)), requiredSignatureCount(requiredSignatureCount) {
assert(requiredSignatureCount <= keys.size());
MemoryInputStream::MemoryInputStream(const void* buffer, size_t bufferSize) :
buffer(static_cast<const char*>(buffer)), bufferSize(bufferSize), position(0) {}
size_t MemoryInputStream::getPosition() const {
return position;
}
uint64_t MultisignatureOutput::getAmount() const {
return amount;
bool MemoryInputStream::endOfStream() const {
return position == bufferSize;
}
uint32_t MultisignatureOutput::getKeyCount() const {
return static_cast<uint32_t>(keys.size());
}
size_t MemoryInputStream::readSome(void* data, size_t size) {
assert(position <= bufferSize);
size_t readSize = std::min(size, bufferSize - position);
const crypto::public_key& MultisignatureOutput::getKey(uint32_t index) const {
return keys[index];
}
uint32_t MultisignatureOutput::getRequiredSignatureCount() const {
return requiredSignatureCount;
if (readSize > 0) {
memcpy(data, buffer + position, readSize);
position += readSize;
}
return readSize;
}
}

View file

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

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

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

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

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

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

@ -19,7 +19,7 @@
#include <functional>
namespace tools {
namespace Tools {
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 {
void read(IInputStream& in, void* data, std::size_t size) {
void read(IInputStream& in, void* data, size_t size) {
while (size > 0) {
std::size_t readSize = in.readSome(data, size);
size_t readSize = in.readSome(data, size);
if (readSize == 0) {
throw std::runtime_error("Failed to read from IInputStream");
}
@ -72,12 +72,12 @@ void read(IInputStream& in, uint64_t& value) {
read(in, &value, sizeof(value));
}
void read(IInputStream& in, std::vector<uint8_t>& data, std::size_t size) {
void read(IInputStream& in, std::vector<uint8_t>& data, size_t size) {
data.resize(size);
read(in, data.data(), size);
}
void read(IInputStream& in, std::string& data, std::size_t size) {
void read(IInputStream& in, std::string& data, size_t size) {
std::vector<char> temp(size);
read(in, temp.data(), size);
data.assign(temp.data(), size);
@ -92,7 +92,7 @@ void readVarint(IInputStream& in, uint8_t& value) {
throw std::runtime_error("readVarint, value overflow");
}
temp |= static_cast<std::size_t>(piece & 0x7f) << shift;
temp |= static_cast<size_t>(piece & 0x7f) << shift;
if ((piece & 0x80) == 0) {
if (piece == 0 && shift != 0) {
throw std::runtime_error("readVarint, invalid value representation");
@ -114,7 +114,7 @@ void readVarint(IInputStream& in, uint16_t& value) {
throw std::runtime_error("readVarint, value overflow");
}
temp |= static_cast<std::size_t>(piece & 0x7f) << shift;
temp |= static_cast<size_t>(piece & 0x7f) << shift;
if ((piece & 0x80) == 0) {
if (piece == 0 && shift != 0) {
throw std::runtime_error("readVarint, invalid value representation");
@ -136,7 +136,7 @@ void readVarint(IInputStream& in, uint32_t& value) {
throw std::runtime_error("readVarint, value overflow");
}
temp |= static_cast<std::size_t>(piece & 0x7f) << shift;
temp |= static_cast<size_t>(piece & 0x7f) << shift;
if ((piece & 0x80) == 0) {
if (piece == 0 && shift != 0) {
throw std::runtime_error("readVarint, invalid value representation");
@ -158,7 +158,7 @@ void readVarint(IInputStream& in, uint64_t& value) {
throw std::runtime_error("readVarint, value overflow");
}
temp |= static_cast<std::size_t>(piece & 0x7f) << shift;
temp |= static_cast<size_t>(piece & 0x7f) << shift;
if ((piece & 0x80) == 0) {
if (piece == 0 && shift != 0) {
throw std::runtime_error("readVarint, invalid value representation");
@ -171,9 +171,9 @@ void readVarint(IInputStream& in, uint64_t& value) {
value = temp;
}
void write(IOutputStream& out, const void* data, std::size_t size) {
void write(IOutputStream& out, const void* data, size_t size) {
while (size > 0) {
std::size_t writtenSize = out.writeSome(data, size);
size_t writtenSize = out.writeSome(data, size);
if (writtenSize == 0) {
throw std::runtime_error("Failed to write to IOutputStream");
}

View file

@ -26,7 +26,7 @@ namespace Common {
class IInputStream;
class IOutputStream;
void read(IInputStream& in, void* data, std::size_t size);
void read(IInputStream& in, void* data, size_t size);
void read(IInputStream& in, int8_t& value);
void read(IInputStream& in, int16_t& value);
void read(IInputStream& in, int32_t& value);
@ -35,14 +35,14 @@ void read(IInputStream& in, uint8_t& value);
void read(IInputStream& in, uint16_t& value);
void read(IInputStream& in, uint32_t& value);
void read(IInputStream& in, uint64_t& value);
void read(IInputStream& in, std::vector<uint8_t>& data, std::size_t size);
void read(IInputStream& in, std::string& data, std::size_t size);
void read(IInputStream& in, std::vector<uint8_t>& data, size_t size);
void read(IInputStream& in, std::string& data, size_t size);
void readVarint(IInputStream& in, uint8_t& value);
void readVarint(IInputStream& in, uint16_t& value);
void readVarint(IInputStream& in, uint32_t& value);
void readVarint(IInputStream& in, uint64_t& value);
void write(IOutputStream& out, const void* data, std::size_t size);
void write(IOutputStream& out, const void* data, size_t size);
void write(IOutputStream& out, int8_t value);
void write(IOutputStream& out, int16_t value);
void write(IOutputStream& out, int32_t value);
@ -61,7 +61,7 @@ template<typename T> T read(IInputStream& in) {
return value;
}
template<typename T> T read(IInputStream& in, std::size_t size) {
template<typename T> T read(IInputStream& in, size_t size) {
T value;
read(in, value, size);
return value;

View file

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

View file

@ -23,7 +23,7 @@ namespace Common {
StringInputStream::StringInputStream(const std::string& in) : in(in), offset(0) {
}
std::size_t StringInputStream::readSome(void* data, std::size_t size) {
size_t StringInputStream::readSome(void* data, size_t size) {
if (size > in.size() - offset) {
size = in.size() - offset;
}

View file

@ -25,11 +25,11 @@ namespace Common {
class StringInputStream : public IInputStream {
public:
StringInputStream(const std::string& in);
std::size_t readSome(void* data, std::size_t size) override;
size_t readSome(void* data, size_t size) override;
private:
const std::string& in;
std::size_t offset;
size_t offset;
};
}

View file

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

View file

@ -25,7 +25,7 @@ namespace Common {
class StringOutputStream : public IOutputStream {
public:
StringOutputStream(std::string& out);
std::size_t writeSome(const void* data, std::size_t size) override;
size_t writeSome(const void* data, size_t size) override;
private:
std::string& out;

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);
}
@ -51,6 +51,11 @@ std::string asString(const std::vector<uint8_t>& data) {
return std::string(reinterpret_cast<const char*>(data.data()), data.size());
}
std::vector<uint8_t> asBinaryArray(const std::string& data) {
auto dataPtr = reinterpret_cast<const uint8_t*>(data.data());
return std::vector<uint8_t>(dataPtr, dataPtr + data.size());
}
uint8_t fromHex(char character) {
uint8_t value = characterValues[static_cast<unsigned char>(character)];
if (value > 0x0f) {
@ -69,7 +74,7 @@ bool fromHex(char character, uint8_t& value) {
return true;
}
std::size_t fromHex(const std::string& text, void* data, std::size_t bufferSize) {
size_t fromHex(const std::string& text, void* data, size_t bufferSize) {
if ((text.size() & 1) != 0) {
throw std::runtime_error("fromHex: invalid string size");
}
@ -78,14 +83,14 @@ std::size_t fromHex(const std::string& text, void* data, std::size_t bufferSize)
throw std::runtime_error("fromHex: invalid buffer size");
}
for (std::size_t i = 0; i < text.size() >> 1; ++i) {
for (size_t i = 0; i < text.size() >> 1; ++i) {
static_cast<uint8_t*>(data)[i] = fromHex(text[i << 1]) << 4 | fromHex(text[(i << 1) + 1]);
}
return text.size() >> 1;
}
bool fromHex(const std::string& text, void* data, std::size_t bufferSize, std::size_t& size) {
bool fromHex(const std::string& text, void* data, size_t bufferSize, size_t& size) {
if ((text.size() & 1) != 0) {
return false;
}
@ -94,7 +99,7 @@ bool fromHex(const std::string& text, void* data, std::size_t bufferSize, std::s
return false;
}
for (std::size_t i = 0; i < text.size() >> 1; ++i) {
for (size_t i = 0; i < text.size() >> 1; ++i) {
uint8_t value1;
if (!fromHex(text[i << 1], value1)) {
return false;
@ -118,7 +123,7 @@ std::vector<uint8_t> fromHex(const std::string& text) {
}
std::vector<uint8_t> data(text.size() >> 1);
for (std::size_t i = 0; i < data.size(); ++i) {
for (size_t i = 0; i < data.size(); ++i) {
data[i] = fromHex(text[i << 1]) << 4 | fromHex(text[(i << 1) + 1]);
}
@ -130,7 +135,7 @@ bool fromHex(const std::string& text, std::vector<uint8_t>& data) {
return false;
}
for (std::size_t i = 0; i < text.size() >> 1; ++i) {
for (size_t i = 0; i < text.size() >> 1; ++i) {
uint8_t value1;
if (!fromHex(text[i << 1], value1)) {
return false;
@ -147,9 +152,9 @@ bool fromHex(const std::string& text, std::vector<uint8_t>& data) {
return true;
}
std::string toHex(const void* data, std::size_t size) {
std::string toHex(const void* data, size_t size) {
std::string text;
for (std::size_t i = 0; i < size; ++i) {
for (size_t i = 0; i < size; ++i) {
text += "0123456789abcdef"[static_cast<const uint8_t*>(data)[i] >> 4];
text += "0123456789abcdef"[static_cast<const uint8_t*>(data)[i] & 15];
}
@ -157,8 +162,8 @@ std::string toHex(const void* data, std::size_t size) {
return text;
}
void toHex(const void* data, std::size_t size, std::string& text) {
for (std::size_t i = 0; i < size; ++i) {
void toHex(const void* data, size_t size, std::string& text) {
for (size_t i = 0; i < size; ++i) {
text += "0123456789abcdef"[static_cast<const uint8_t*>(data)[i] >> 4];
text += "0123456789abcdef"[static_cast<const uint8_t*>(data)[i] & 15];
}
@ -166,7 +171,7 @@ void toHex(const void* data, std::size_t size, std::string& text) {
std::string toHex(const std::vector<uint8_t>& data) {
std::string text;
for (std::size_t i = 0; i < data.size(); ++i) {
for (size_t i = 0; i < data.size(); ++i) {
text += "0123456789abcdef"[data[i] >> 4];
text += "0123456789abcdef"[data[i] & 15];
}
@ -175,14 +180,14 @@ std::string toHex(const std::vector<uint8_t>& data) {
}
void toHex(const std::vector<uint8_t>& data, std::string& text) {
for (std::size_t i = 0; i < data.size(); ++i) {
for (size_t i = 0; i < data.size(); ++i) {
text += "0123456789abcdef"[data[i] >> 4];
text += "0123456789abcdef"[data[i] & 15];
}
}
std::string extract(std::string& text, char delimiter) {
std::size_t delimiterPosition = text.find(delimiter);
size_t delimiterPosition = text.find(delimiter);
std::string subText;
if (delimiterPosition != std::string::npos) {
subText = text.substr(0, delimiterPosition);
@ -194,8 +199,8 @@ std::string extract(std::string& text, char delimiter) {
return subText;
}
std::string extract(const std::string& text, char delimiter, std::size_t& offset) {
std::size_t delimiterPosition = text.find(delimiter, offset);
std::string extract(const std::string& text, char delimiter, size_t& offset) {
size_t delimiterPosition = text.find(delimiter, offset);
if (delimiterPosition != std::string::npos) {
offset = delimiterPosition + 1;
return text.substr(offset, delimiterPosition);

View file

@ -24,24 +24,25 @@
namespace Common {
std::string asString(const void* data, std::size_t size); // Does not throw
std::string asString(const void* data, size_t size); // Does not throw
std::string asString(const std::vector<uint8_t>& data); // Does not throw
std::vector<uint8_t> asBinaryArray(const std::string& data);
uint8_t fromHex(char character); // Returns value of hex 'character', throws on error
bool fromHex(char character, uint8_t& value); // Assigns value of hex 'character' to 'value', returns false on error, does not throw
std::size_t fromHex(const std::string& text, void* data, std::size_t bufferSize); // Assigns values of hex 'text' to buffer 'data' up to 'bufferSize', returns actual data size, throws on error
bool fromHex(const std::string& text, void* data, std::size_t bufferSize, std::size_t& size); // Assigns values of hex 'text' to buffer 'data' up to 'bufferSize', assigns actual data size to 'size', returns false on error, does not throw
size_t fromHex(const std::string& text, void* data, size_t bufferSize); // Assigns values of hex 'text' to buffer 'data' up to 'bufferSize', returns actual data size, throws on error
bool fromHex(const std::string& text, void* data, size_t bufferSize, size_t& size); // Assigns values of hex 'text' to buffer 'data' up to 'bufferSize', assigns actual data size to 'size', returns false on error, does not throw
std::vector<uint8_t> fromHex(const std::string& text); // Returns values of hex 'text', throws on error
bool fromHex(const std::string& text, std::vector<uint8_t>& data); // Appends values of hex 'text' to 'data', returns false on error, does not throw
template <typename T>
bool podFromHex(const std::string& text, T& val) {
std::size_t outSize;
size_t outSize;
return fromHex(text, &val, sizeof(val), outSize) && outSize == sizeof(val);
}
std::string toHex(const void* data, std::size_t size); // Returns hex representation of ('data', 'size'), does not throw
void toHex(const void* data, std::size_t size, std::string& text); // Appends hex representation of ('data', 'size') to 'text', does not throw
std::string toHex(const void* data, size_t size); // Returns hex representation of ('data', 'size'), does not throw
void toHex(const void* data, size_t size, std::string& text); // Appends hex representation of ('data', 'size') to 'text', does not throw
std::string toHex(const std::vector<uint8_t>& data); // Returns hex representation of 'data', does not throw
void toHex(const std::vector<uint8_t>& data, std::string& text); // Appends hex representation of 'data' to 'text', does not throw
@ -51,7 +52,7 @@ std::string podToHex(const T& s) {
}
std::string extract(std::string& text, char delimiter); // Does not throw
std::string extract(const std::string& text, char delimiter, std::size_t& offset); // Does not throw
std::string extract(const std::string& text, char delimiter, size_t& offset); // Does not throw
template<typename T> T fromString(const std::string& text) { // Throws on error
T value;
@ -72,7 +73,7 @@ template<typename T> bool fromString(const std::string& text, T& value) { // Doe
template<typename T> std::vector<T> fromDelimitedString(const std::string& source, char delimiter) { // Throws on error
std::vector<T> data;
for (std::size_t offset = 0; offset != source.size();) {
for (size_t offset = 0; offset != source.size();) {
data.emplace_back(fromString<T>(extract(source, delimiter, offset)));
}
@ -80,7 +81,7 @@ template<typename T> std::vector<T> fromDelimitedString(const std::string& sourc
}
template<typename T> bool fromDelimitedString(const std::string& source, char delimiter, std::vector<T>& data) { // Does not throw
for (std::size_t offset = 0; offset != source.size();) {
for (size_t offset = 0; offset != source.size();) {
T value;
if (!fromString<T>(extract(source, delimiter, offset), value)) {
return false;

View file

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

View file

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

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

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

2
src/Common/varint.h → src/Common/Varint.h Normal file → Executable file
View file

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

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

View file

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

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_POOLDATA_FILENAME[] = "poolstate.bin";
const char P2P_NET_DATA_FILENAME[] = "p2pstate.bin";
const char CRYPTONOTE_BLOCKCHAIN_INDICES_FILENAME[] = "blockchainindices.dat";
const char MINER_CONFIG_FILE_NAME[] = "miner_conf.json";
} // parameters
@ -95,7 +96,9 @@ const int RPC_DEFAULT_PORT = 8081;
const size_t P2P_LOCAL_WHITE_PEERLIST_LIMIT = 1000;
const size_t P2P_LOCAL_GRAY_PEERLIST_LIMIT = 5000;
const size_t P2P_CONNECTION_MAX_WRITE_BUFFER_SIZE = 16 * 1024 * 1024; // 16 MB
const uint32_t P2P_DEFAULT_CONNECTIONS_COUNT = 8;
const size_t P2P_DEFAULT_WHITELIST_CONNECTIONS_PERCENT = 70;
const uint32_t P2P_DEFAULT_HANDSHAKE_INTERVAL = 60; // seconds
const uint32_t P2P_DEFAULT_PACKET_MAX_SIZE = 50000000; // 50000000 bytes maximum packet size
const uint32_t P2P_DEFAULT_PEERS_IN_HANDSHAKE = 250;
@ -103,10 +106,7 @@ const uint32_t P2P_DEFAULT_CONNECTION_TIMEOUT = 5000; //
const uint32_t P2P_DEFAULT_PING_CONNECTION_TIMEOUT = 2000; // 2 seconds
const uint64_t P2P_DEFAULT_INVOKE_TIMEOUT = 60 * 2 * 1000; // 2 minutes
const size_t P2P_DEFAULT_HANDSHAKE_INVOKE_TIMEOUT = 5000; // 5 seconds
const char P2P_STAT_TRUSTED_PUB_KEY[] = "93467628927eaa0b13a4e52e61864a75aa475e67f6b5748eb3fc1d2fe468aed4";
const size_t P2P_DEFAULT_WHITELIST_CONNECTIONS_PERCENT = 70;
const unsigned THREAD_STACK_SIZE = 5 * 1024 * 1024;
const char P2P_STAT_TRUSTED_PUB_KEY[] = "93467628927eaa0b13a4e52e61864a75aa475e67f6b5748eb3fc1d2fe468aed4";
const char* const SEED_NODES[] = {
"seed.bytecoin.org:8080",
@ -122,7 +122,7 @@ const char* const SEED_NODES[] = {
};
struct CheckpointData {
uint64_t height;
uint32_t height;
const char* blockId;
};
@ -154,7 +154,8 @@ const CheckpointData CHECKPOINTS[] = {
{750300, "5117631dbeb5c14748a91127a515ecbf13f6849e14fda7ee03cd55da41f1710c"},
{780000, "8dd55a9bae429e3685b90317281e633917023d3512eb7f37372209d1a5fc1070"},
{785500, "de1a487d70964d25ed6f7de196866f357a293e867ee81313e7fd0352d0126bdd"},
{789000, "acef490bbccce3b7b7ae8554a414f55413fbf4ca1472c6359b126a4439bd9f01"}
{789000, "acef490bbccce3b7b7ae8554a414f55413fbf4ca1472c6359b126a4439bd9f01"},
{796000, "04e387a00d35db21d4d93d04040b31f22573972a7e61d72cc07d0ab69bcb9c44"}
};
} // CryptoNote

View file

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

View file

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

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

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

View file

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

1031
src/CryptoNoteCore/Core.cpp Executable file

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 "Common/util.h"
#include "Common/command_line.h"
#include "Common/Util.h"
#include "Common/CommandLine.h"
namespace CryptoNote {
CoreConfig::CoreConfig() {
configFolder = tools::get_default_data_dir();
configFolder = Tools::getDefaultDataDirectory();
}
void CoreConfig::init(const boost::program_options::variables_map& options) {

View file

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

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

View file

@ -20,7 +20,7 @@
#include "Common/StringTools.h"
#include "crypto/crypto.h"
#include "crypto/hash.h"
#include "cryptonote_core/cryptonote_basic.h"
#include "CryptoNoteCore/CryptoNoteBasic.h"
namespace CryptoNote {
@ -28,16 +28,16 @@ namespace CryptoNote {
/* */
/************************************************************************/
template<class t_array>
struct array_hasher: std::unary_function<t_array&, std::size_t>
struct array_hasher: std::unary_function<t_array&, size_t>
{
std::size_t operator()(const t_array& val) const
size_t operator()(const t_array& val) const
{
return boost::hash_range(&val.data[0], &val.data[sizeof(val.data)]);
}
};
/************************************************************************/
/* Cryptonote helper functions */
/* CryptoNote helper functions */
/************************************************************************/
uint64_t getPenalizedAmount(uint64_t amount, size_t medianSize, size_t currentBlockSize);
std::string getAccountAddressAsStr(uint64_t prefix, const AccountPublicAddress& adr);
@ -53,13 +53,13 @@ std::ostream &print256(std::ostream &o, const T &v) {
return o << "<" << Common::podToHex(v) << ">";
}
bool parse_hash256(const std::string& str_hash, crypto::hash& hash);
bool parse_hash256(const std::string& str_hash, Crypto::Hash& hash);
namespace crypto {
inline std::ostream &operator <<(std::ostream &o, const crypto::public_key &v) { return print256(o, v); }
inline std::ostream &operator <<(std::ostream &o, const crypto::secret_key &v) { return print256(o, v); }
inline std::ostream &operator <<(std::ostream &o, const crypto::key_derivation &v) { return print256(o, v); }
inline std::ostream &operator <<(std::ostream &o, const crypto::key_image &v) { return print256(o, v); }
inline std::ostream &operator <<(std::ostream &o, const crypto::signature &v) { return print256(o, v); }
inline std::ostream &operator <<(std::ostream &o, const crypto::hash &v) { return print256(o, v); }
namespace Crypto {
inline std::ostream &operator <<(std::ostream &o, const Crypto::PublicKey &v) { return print256(o, v); }
inline std::ostream &operator <<(std::ostream &o, const Crypto::SecretKey &v) { return print256(o, v); }
inline std::ostream &operator <<(std::ostream &o, const Crypto::KeyDerivation &v) { return print256(o, v); }
inline std::ostream &operator <<(std::ostream &o, const Crypto::KeyImage &v) { return print256(o, v); }
inline std::ostream &operator <<(std::ostream &o, const Crypto::Signature &v) { return print256(o, v); }
inline std::ostream &operator <<(std::ostream &o, const Crypto::Hash &v) { return print256(o, v); }
}

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

View file

@ -17,47 +17,51 @@
#pragma once
#include "cryptonote_basic.h"
#include "serialization/ISerializer.h"
#include "CryptoNoteBasic.h"
#include "crypto/chacha8.h"
#include "Serialization/ISerializer.h"
#include "crypto/crypto.h"
namespace crypto {
namespace Crypto {
bool serialize(public_key& pubKey, Common::StringView name, CryptoNote::ISerializer& serializer);
bool serialize(secret_key& secKey, Common::StringView name, CryptoNote::ISerializer& serializer);
bool serialize(hash& h, Common::StringView name, CryptoNote::ISerializer& serializer);
bool serialize(PublicKey& pubKey, Common::StringView name, CryptoNote::ISerializer& serializer);
bool serialize(SecretKey& secKey, Common::StringView name, CryptoNote::ISerializer& serializer);
bool serialize(Hash& h, Common::StringView name, CryptoNote::ISerializer& serializer);
bool serialize(chacha8_iv& chacha, Common::StringView name, CryptoNote::ISerializer& serializer);
bool serialize(key_image& keyImage, Common::StringView name, CryptoNote::ISerializer& serializer);
bool serialize(signature& sig, Common::StringView name, CryptoNote::ISerializer& serializer);
bool serialize(KeyImage& keyImage, Common::StringView name, CryptoNote::ISerializer& serializer);
bool serialize(Signature& sig, Common::StringView name, CryptoNote::ISerializer& serializer);
bool serialize(EllipticCurveScalar& ecScalar, Common::StringView name, CryptoNote::ISerializer& serializer);
bool serialize(EllipticCurvePoint& ecPoint, Common::StringView name, CryptoNote::ISerializer& serializer);
} //namespace crypto
}
namespace CryptoNote {
void serialize(ParentBlockSerializer& pbs, ISerializer& serializer);
struct AccountKeys;
struct TransactionExtraMergeMiningTag;
void serialize(TransactionPrefix& txP, ISerializer& serializer);
void serialize(Transaction& tx, ISerializer& serializer);
void serialize(TransactionInput& in, ISerializer& serializer);
void serialize(TransactionOutput& in, ISerializer& serializer);
void serialize(TransactionInputGenerate& gen, ISerializer& serializer);
void serialize(TransactionInputToScript& script, ISerializer& serializer);
void serialize(TransactionInputToScriptHash& scripthash, ISerializer& serializer);
void serialize(TransactionInputToKey& key, ISerializer& serializer);
void serialize(TransactionInputMultisignature& multisignature, ISerializer& serializer);
void serialize(BaseInput& gen, ISerializer& serializer);
void serialize(KeyInput& key, ISerializer& serializer);
void serialize(MultisignatureInput& multisignature, ISerializer& serializer);
void serialize(TransactionOutput& output, ISerializer& serializer);
void serialize(TransactionOutputTarget& output, ISerializer& serializer);
void serialize(KeyOutput& key, ISerializer& serializer);
void serialize(MultisignatureOutput& multisignature, ISerializer& serializer);
void serialize(TransactionOutputToScript& script, ISerializer& serializer);
void serialize(TransactionOutputToScriptHash& scripthash, ISerializer& serializer);
void serialize(TransactionOutputToKey& key, ISerializer& serializer);
void serialize(TransactionOutputMultisignature& multisignature, ISerializer& serializer);
void serialize(BlockHeader& header, ISerializer& serializer);
void serialize(Block& block, ISerializer& serializer);
void serialize(tx_extra_merge_mining_tag& tag, ISerializer& serializer);
void serialize(ParentBlockSerializer& pbs, ISerializer& serializer);
void serialize(TransactionExtraMergeMiningTag& tag, ISerializer& serializer);
void serialize(AccountPublicAddress& address, ISerializer& serializer);
void serialize(account_keys& keys, ISerializer& s);
void serialize(AccountKeys& keys, ISerializer& s);
void serialize(KeyPair& keyPair, ISerializer& serializer);
} //namespace CryptoNote
}

View file

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

View file

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

View file

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

Some files were not shown because too many files have changed in this diff Show more