From 6c35e246340444ee4ce33cb1df8945aed99d5880 Mon Sep 17 00:00:00 2001 From: Antonio Juarez Date: Fri, 4 Sep 2015 17:14:17 +0100 Subject: [PATCH] IWallet implementation improvements --- include/IWallet.h | 2 +- src/CryptoNoteConfig.h | 3 +- src/NodeRpcProxy/NodeRpcProxy.cpp | 49 ++++++++++++++++++++++++++++++ src/NodeRpcProxy/NodeRpcProxy.h | 7 ++++- src/P2p/NetNode.cpp | 5 ++- src/Wallet/WalletGreen.cpp | 35 +++++++++++++-------- src/Wallet/WalletGreen.h | 6 ++-- src/Wallet/WalletIndices.h | 6 ++++ src/Wallet/WalletSerialization.cpp | 2 +- src/version.h.in | 4 +-- tests/UnitTests/ICoreStub.cpp | 18 +++++++++++ tests/UnitTests/ICoreStub.h | 8 ++--- 12 files changed, 116 insertions(+), 29 deletions(-) diff --git a/include/IWallet.h b/include/IWallet.h index 69b46441..72f6714b 100755 --- a/include/IWallet.h +++ b/include/IWallet.h @@ -121,7 +121,7 @@ public: virtual void start() = 0; virtual void stop() = 0; - //blocks until an event occured + //blocks until an event occurred virtual WalletEvent getEvent() = 0; }; diff --git a/src/CryptoNoteConfig.h b/src/CryptoNoteConfig.h index 0d1b3d7a..c89db609 100644 --- a/src/CryptoNoteConfig.h +++ b/src/CryptoNoteConfig.h @@ -163,7 +163,8 @@ const CheckpointData CHECKPOINTS[] = { {800000, "d7fa4eea02e5ce60b949136569c0ea7ac71ea46e0065311054072ac415560b86"}, {804000, "bcc8b3782499aae508c40d5587d1cc5d68281435ea9bfc6804a262047f7b934d"}, {810500, "302b2349f221232820adc3dadafd8a61b035491e33af669c78a687949eb0a381"}, - {816000, "32b7fdd4e4d715db81f8f09f4ba5e5c78e8113f2804d61a57378baee479ce745"} + {816000, "32b7fdd4e4d715db81f8f09f4ba5e5c78e8113f2804d61a57378baee479ce745"}, + {822000, "a3c9603c6813a0dc0efc40db288c356d1a7f02d1d2e47bee04346e73715f8984"} }; } // CryptoNote diff --git a/src/NodeRpcProxy/NodeRpcProxy.cpp b/src/NodeRpcProxy/NodeRpcProxy.cpp index f5adb0df..cab093ba 100644 --- a/src/NodeRpcProxy/NodeRpcProxy.cpp +++ b/src/NodeRpcProxy/NodeRpcProxy.cpp @@ -84,6 +84,7 @@ void NodeRpcProxy::resetInternalState() { m_nodeHeight.store(0, std::memory_order_relaxed); m_networkHeight.store(0, std::memory_order_relaxed); m_lastKnowHash = CryptoNote::NULL_HASH; + m_knownTxs.clear(); } void NodeRpcProxy::init(const INode::Callback& callback) { @@ -176,6 +177,39 @@ void NodeRpcProxy::workerThread(const INode::Callback& initialized_callback) { } void NodeRpcProxy::updateNodeStatus() { + bool updateBlockchain = true; + while (updateBlockchain) { + updateBlockchainStatus(); + updateBlockchain = !updatePoolStatus(); + } +} + +bool NodeRpcProxy::updatePoolStatus() { + std::vector knownTxs = getKnownTxsVector(); + Crypto::Hash tailBlock = m_lastKnowHash; + + bool isBcActual = false; + std::vector> addedTxs; + std::vector deletedTxsIds; + + std::error_code ec = doGetPoolSymmetricDifference(std::move(knownTxs), tailBlock, isBcActual, addedTxs, deletedTxsIds); + if (ec) { + return true; + } + + if (!isBcActual) { + return false; + } + + if (!addedTxs.empty() || !deletedTxsIds.empty()) { + updatePoolState(addedTxs, deletedTxsIds); + m_observerManager.notify(&INodeObserver::poolChanged); + } + + return true; +} + +void NodeRpcProxy::updateBlockchainStatus() { CryptoNote::COMMAND_RPC_GET_LAST_BLOCK_HEADER::request req = AUTO_VAL_INIT(req); CryptoNote::COMMAND_RPC_GET_LAST_BLOCK_HEADER::response rsp = AUTO_VAL_INIT(rsp); @@ -224,6 +258,21 @@ void NodeRpcProxy::updatePeerCount() { } } +void NodeRpcProxy::updatePoolState(const std::vector>& addedTxs, const std::vector& deletedTxsIds) { + for (const auto& hash : deletedTxsIds) { + m_knownTxs.erase(hash); + } + + for (const auto& tx : addedTxs) { + Hash hash = tx->getTransactionHash(); + m_knownTxs.emplace(std::move(hash)); + } +} + +std::vector NodeRpcProxy::getKnownTxsVector() const { + return std::vector(m_knownTxs.begin(), m_knownTxs.end()); +} + bool NodeRpcProxy::addObserver(INodeObserver* observer) { return m_observerManager.add(observer); } diff --git a/src/NodeRpcProxy/NodeRpcProxy.h b/src/NodeRpcProxy/NodeRpcProxy.h index 0cbfd9a8..2139a15d 100644 --- a/src/NodeRpcProxy/NodeRpcProxy.h +++ b/src/NodeRpcProxy/NodeRpcProxy.h @@ -22,6 +22,7 @@ #include #include #include +#include #include "Common/ObserverManager.h" #include "INode.h" @@ -68,7 +69,6 @@ public: virtual void getNewBlocks(std::vector&& knownBlockIds, std::vector& newBlocks, uint32_t& startHeight, const Callback& callback); virtual void getTransactionOutsGlobalIndices(const Crypto::Hash& transactionHash, std::vector& outsGlobalIndices, const Callback& callback) override; virtual void queryBlocks(std::vector&& knownBlockIds, uint64_t timestamp, std::vector& newBlocks, uint32_t& startHeight, const Callback& callback) override; - // TODO INodeObserver::poolChanged() notification NOT implemented!!! virtual void getPoolSymmetricDifference(std::vector&& knownPoolTxIds, Crypto::Hash knownBlockId, bool& isBcActual, std::vector>& newTxs, std::vector& deletedTxIds, const Callback& callback) override; virtual void getMultisignatureOutputByGlobalIndex(uint64_t amount, uint32_t gindex, MultisignatureOutput& out, const Callback& callback) override; @@ -87,9 +87,13 @@ private: void resetInternalState(); void workerThread(const Callback& initialized_callback); + std::vector getKnownTxsVector() const; void pullNodeStatusAndScheduleTheNext(); void updateNodeStatus(); + void updateBlockchainStatus(); + bool updatePoolStatus(); void updatePeerCount(); + void updatePoolState(const std::vector>& addedTxs, const std::vector& deletedTxsIds); std::error_code doRelayTransaction(const CryptoNote::Transaction& transaction); std::error_code doGetRandomOutsByAmounts(std::vector& amounts, uint64_t outsCount, @@ -144,6 +148,7 @@ private: //protect it with mutex if decided to add worker threads Crypto::Hash m_lastKnowHash; std::atomic m_lastLocalBlockTimestamp; + std::unordered_set m_knownTxs; bool m_connected; }; diff --git a/src/P2p/NetNode.cpp b/src/P2p/NetNode.cpp index 52882a0a..d4fe79e4 100644 --- a/src/P2p/NetNode.cpp +++ b/src/P2p/NetNode.cpp @@ -573,7 +573,10 @@ namespace CryptoNote get_local_node_data(arg.node_data); m_payload_handler.get_payload_sync_data(arg.payload_data); - proto.invoke(COMMAND_HANDSHAKE::ID, arg, rsp); + if (!proto.invoke(COMMAND_HANDSHAKE::ID, arg, rsp)) { + logger(Logging::ERROR) << context << "Failed to invoke COMMAND_HANDSHAKE, closing connection."; + return false; + } context.version = rsp.node_data.version; diff --git a/src/Wallet/WalletGreen.cpp b/src/Wallet/WalletGreen.cpp index 24c46698..a83b2e87 100755 --- a/src/Wallet/WalletGreen.cpp +++ b/src/Wallet/WalletGreen.cpp @@ -379,8 +379,9 @@ KeyPair WalletGreen::getViewKey() const { std::string WalletGreen::createAddress() { KeyPair spendKey; Crypto::generate_keys(spendKey.publicKey, spendKey.secretKey); + uint64_t creationTimestamp = static_cast(time(nullptr)); - return doCreateAddress(spendKey.publicKey, spendKey.secretKey); + return doCreateAddress(spendKey.publicKey, spendKey.secretKey, creationTimestamp); } std::string WalletGreen::createAddress(const Crypto::SecretKey& spendSecretKey) { @@ -389,14 +390,14 @@ std::string WalletGreen::createAddress(const Crypto::SecretKey& spendSecretKey) throw std::system_error(make_error_code(CryptoNote::error::KEY_GENERATION_ERROR)); } - return doCreateAddress(spendPublicKey, spendSecretKey); + return doCreateAddress(spendPublicKey, spendSecretKey, 0); } std::string WalletGreen::createAddress(const Crypto::PublicKey& spendPublicKey) { - return doCreateAddress(spendPublicKey, NULL_SECRET_KEY); + return doCreateAddress(spendPublicKey, NULL_SECRET_KEY, 0); } -std::string WalletGreen::doCreateAddress(const Crypto::PublicKey& spendPublicKey, const Crypto::SecretKey& spendSecretKey) { +std::string WalletGreen::doCreateAddress(const Crypto::PublicKey& spendPublicKey, const Crypto::SecretKey& spendSecretKey, uint64_t creationTimestamp) { throwIfNotInitialized(); throwIfStopped(); @@ -405,7 +406,7 @@ std::string WalletGreen::doCreateAddress(const Crypto::PublicKey& spendPublicKey } try { - addWallet(spendPublicKey, spendSecretKey); + addWallet(spendPublicKey, spendSecretKey, creationTimestamp); } catch (std::exception&) { if (m_walletsContainer.get().size() != 0) { m_blockchainSynchronizer.start(); @@ -419,7 +420,7 @@ std::string WalletGreen::doCreateAddress(const Crypto::PublicKey& spendPublicKey return m_currency.accountAddressAsString({ spendPublicKey, m_viewPublicKey }); } -void WalletGreen::addWallet(const Crypto::PublicKey& spendPublicKey, const Crypto::SecretKey& spendSecretKey) { +void WalletGreen::addWallet(const Crypto::PublicKey& spendPublicKey, const Crypto::SecretKey& spendSecretKey, uint64_t creationTimestamp) { auto& index = m_walletsContainer.get(); auto trackingMode = getTrackingMode(); @@ -434,8 +435,6 @@ void WalletGreen::addWallet(const Crypto::PublicKey& spendPublicKey, const Crypt throw std::system_error(make_error_code(error::ADDRESS_ALREADY_EXISTS)); } - time_t creationTimestamp = time(nullptr); - AccountSubscription sub; sub.keys.address.viewPublicKey = m_viewPublicKey; sub.keys.address.spendPublicKey = spendPublicKey; @@ -443,7 +442,7 @@ void WalletGreen::addWallet(const Crypto::PublicKey& spendPublicKey, const Crypt sub.keys.spendSecretKey = spendSecretKey; sub.transactionSpendableAge = m_transactionSoftLockTime; sub.syncStart.height = 0; - sub.syncStart.timestamp = static_cast(creationTimestamp) - (60 * 60 * 24); + sub.syncStart.timestamp = std::max(creationTimestamp, ACCOUNT_CREATE_TIME_ACCURACY) - ACCOUNT_CREATE_TIME_ACCURACY; auto& trSubscription = m_synchronizer.addSubscription(sub); ITransfersContainer* container = &trSubscription.getContainer(); @@ -452,7 +451,7 @@ void WalletGreen::addWallet(const Crypto::PublicKey& spendPublicKey, const Crypt wallet.spendPublicKey = spendPublicKey; wallet.spendSecretKey = spendSecretKey; wallet.container = container; - wallet.creationTimestamp = creationTimestamp; + wallet.creationTimestamp = static_cast(creationTimestamp); trSubscription.addObserver(this); index.insert(insertIt, std::move(wallet)); @@ -753,6 +752,12 @@ bool WalletGreen::updateWalletTransactionInfo(const Hash& hash, const CryptoNote updated = true; } + // Fix LegacyWallet error. Some old versions didn't fill extra field + if (transaction.extra.empty() && !info.extra.empty()) { + transaction.extra = Common::asString(info.extra); + updated = true; + } + bool isBase = info.totalAmountIn == 0; if (transaction.isBase != isBase) { transaction.isBase = isBase; @@ -767,7 +772,7 @@ bool WalletGreen::updateWalletTransactionInfo(const Hash& hash, const CryptoNote throw std::system_error(make_error_code(std::errc::invalid_argument)); } -size_t WalletGreen::insertIncomingTransaction(const TransactionInformation& info, int64_t txBalance) { +size_t WalletGreen::insertBlockchainTransaction(const TransactionInformation& info, int64_t txBalance) { auto& index = m_transactions.get(); WalletTransaction tx; @@ -1166,8 +1171,12 @@ void WalletGreen::transactionUpdated(ITransfersSubscription* object, const Hash& pushEvent(makeTransactionUpdatedEvent(id)); } } else { - auto id = insertIncomingTransaction(info, txBalance); - insertIncomingTransfer(id, m_currency.accountAddressAsString({ getWalletRecord(container).spendPublicKey, m_viewPublicKey }), txBalance); + auto id = insertBlockchainTransaction(info, txBalance); + if (txBalance > 0) { + AccountPublicAddress walletAddress{ getWalletRecord(container).spendPublicKey, m_viewPublicKey }; + insertIncomingTransfer(id, m_currency.accountAddressAsString(walletAddress), txBalance); + } + m_fusionTxsCache.emplace(id, isFusionTransaction(m_transactions.get()[id])); pushEvent(makeTransactionCreatedEvent(id)); diff --git a/src/Wallet/WalletGreen.h b/src/Wallet/WalletGreen.h index 65e1ae6f..1fdcf7f7 100755 --- a/src/Wallet/WalletGreen.h +++ b/src/Wallet/WalletGreen.h @@ -86,7 +86,7 @@ protected: void doShutdown(); void clearCaches(); void initWithKeys(const Crypto::PublicKey& viewPublicKey, const Crypto::SecretKey& viewSecretKey, const std::string& password); - std::string doCreateAddress(const Crypto::PublicKey& spendPublicKey, const Crypto::SecretKey& spendSecretKey); + std::string doCreateAddress(const Crypto::PublicKey& spendPublicKey, const Crypto::SecretKey& spendSecretKey, uint64_t creationTimestamp); struct InputInfo { TransactionTypes::InputKeyInfo keyInfo; @@ -133,7 +133,7 @@ protected: const WalletRecord& getWalletRecord(CryptoNote::ITransfersContainer* container) const; CryptoNote::AccountPublicAddress parseAddress(const std::string& address) const; - void addWallet(const Crypto::PublicKey& spendPublicKey, const Crypto::SecretKey& spendSecretKey); + void addWallet(const Crypto::PublicKey& spendPublicKey, const Crypto::SecretKey& spendSecretKey, uint64_t creationTimestamp); bool isOutputUsed(const TransactionOutputInformation& out) const; void markOutputsSpent(const Crypto::Hash& transactionHash, const std::vector& selectedTransfers); void deleteSpentOutputs(const Crypto::Hash& transactionHash); @@ -177,7 +177,7 @@ protected: size_t insertOutgoingTransaction(const Crypto::Hash& transactionHash, int64_t totalAmount, uint64_t fee, const BinaryArray& extra, uint64_t unlockTimestamp); bool transactionExists(const Crypto::Hash& hash); bool updateWalletTransactionInfo(const Crypto::Hash& hash, const CryptoNote::TransactionInformation& info); - size_t insertIncomingTransaction(const TransactionInformation& info, int64_t txBalance); + size_t insertBlockchainTransaction(const TransactionInformation& info, int64_t txBalance); void insertIncomingTransfer(size_t txId, const std::string& address, int64_t amount); void pushBackOutgoingTransfers(size_t txId, const std::vector &destinations); void insertUnlockTransactionJob(const Crypto::Hash& transactionHash, uint32_t blockHeight, CryptoNote::ITransfersContainer* container); diff --git a/src/Wallet/WalletIndices.h b/src/Wallet/WalletIndices.h index 4b7fac4f..82cd7ad0 100644 --- a/src/Wallet/WalletIndices.h +++ b/src/Wallet/WalletIndices.h @@ -30,6 +30,10 @@ #include #include +namespace CryptoNote { + +const uint64_t ACCOUNT_CREATE_TIME_ACCURACY = 60 * 60 * 24; + struct WalletRecord { Crypto::PublicKey spendPublicKey; Crypto::SecretKey spendSecretKey; @@ -122,3 +126,5 @@ typedef std::unordered_map TransactionChanges; typedef std::pair TransactionTransferPair; typedef std::vector WalletTransfers; + +} diff --git a/src/Wallet/WalletSerialization.cpp b/src/Wallet/WalletSerialization.cpp index b6a498a3..e03dba4b 100755 --- a/src/Wallet/WalletSerialization.cpp +++ b/src/Wallet/WalletSerialization.cpp @@ -726,7 +726,7 @@ void WalletSerializer::subscribeWallets() { sub.keys.spendSecretKey = wallet.spendSecretKey; sub.transactionSpendableAge = m_transactionSoftLockTime; sub.syncStart.height = 0; - sub.syncStart.timestamp = static_cast(wallet.creationTimestamp) - (60 * 60 * 24); + sub.syncStart.timestamp = std::max(static_cast(wallet.creationTimestamp), ACCOUNT_CREATE_TIME_ACCURACY) - ACCOUNT_CREATE_TIME_ACCURACY; auto& subscription = m_synchronizer.addSubscription(sub); bool r = index.modify(it, [&subscription] (WalletRecord& rec) { rec.container = &subscription.getContainer(); }); diff --git a/src/version.h.in b/src/version.h.in index b36e418b..18cb97e7 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -1,4 +1,4 @@ #define BUILD_COMMIT_ID "@VERSION@" -#define PROJECT_VERSION "1.0.8" -#define PROJECT_VERSION_BUILD_NO "608" +#define PROJECT_VERSION "1.0.8.1" +#define PROJECT_VERSION_BUILD_NO "614" #define PROJECT_VERSION_LONG PROJECT_VERSION "." PROJECT_VERSION_BUILD_NO "(" BUILD_COMMIT_ID ")" diff --git a/tests/UnitTests/ICoreStub.cpp b/tests/UnitTests/ICoreStub.cpp index 2fab23c1..2f7c2425 100755 --- a/tests/UnitTests/ICoreStub.cpp +++ b/tests/UnitTests/ICoreStub.cpp @@ -22,6 +22,24 @@ #include "CryptoNoteCore/IBlock.h" #include "CryptoNoteCore/VerificationContext.h" + +ICoreStub::ICoreStub() : + topHeight(0), + globalIndicesResult(false), + randomOutsResult(false), + poolTxVerificationResult(true), + poolChangesResult(true) { +} + +ICoreStub::ICoreStub(const CryptoNote::Block& genesisBlock) : + topHeight(0), + globalIndicesResult(false), + randomOutsResult(false), + poolTxVerificationResult(true), + poolChangesResult(true) { + addBlock(genesisBlock); +} + bool ICoreStub::addObserver(CryptoNote::ICoreObserver* observer) { return true; } diff --git a/tests/UnitTests/ICoreStub.h b/tests/UnitTests/ICoreStub.h index 8e240003..bf07b436 100644 --- a/tests/UnitTests/ICoreStub.h +++ b/tests/UnitTests/ICoreStub.h @@ -28,11 +28,8 @@ class ICoreStub: public CryptoNote::ICore { public: - ICoreStub() : topHeight(0), globalIndicesResult(false), randomOutsResult(false), poolTxVerificationResult(true) {}; - ICoreStub(const CryptoNote::Block& genesisBlock) : topHeight(0), globalIndicesResult(false), randomOutsResult(false), poolTxVerificationResult(true), - poolChangesResult(true) { - addBlock(genesisBlock); - }; + ICoreStub(); + ICoreStub(const CryptoNote::Block& genesisBlock); virtual bool addObserver(CryptoNote::ICoreObserver* observer); virtual bool removeObserver(CryptoNote::ICoreObserver* observer); @@ -124,6 +121,5 @@ private: std::unordered_map transactions; std::unordered_map transactionPool; bool poolTxVerificationResult; - bool poolChangesResult; };