diff --git a/ReleaseNotes.txt b/ReleaseNotes.txt index 97dbeae3..bea3de1a 100644 --- a/ReleaseNotes.txt +++ b/ReleaseNotes.txt @@ -1,3 +1,7 @@ +Release notes 1.1.1 + +- New API for CryptoNote RPC Wallet + Release notes 1.1.0 - CryptoNote RPC Wallet diff --git a/external/gtest/include/gtest/gtest-spi.h b/external/gtest/include/gtest/gtest-spi.h index f63fa9a1..f59ec6d7 100644 --- a/external/gtest/include/gtest/gtest-spi.h +++ b/external/gtest/include/gtest/gtest-spi.h @@ -75,7 +75,7 @@ class GTEST_API_ ScopedFakeTestPartResultReporter // // This method is from the TestPartResultReporterInterface // interface. - virtual void ReportTestPartResult(const TestPartResult& result); + virtual void ReportTestPartResult(const TestPartResult& result) override; private: void Init(); diff --git a/external/gtest/include/gtest/gtest-test-part.h b/external/gtest/include/gtest/gtest-test-part.h index 77eb8448..b93b114f 100644 --- a/external/gtest/include/gtest/gtest-test-part.h +++ b/external/gtest/include/gtest/gtest-test-part.h @@ -162,8 +162,8 @@ class GTEST_API_ HasNewFatalFailureHelper : public TestPartResultReporterInterface { public: HasNewFatalFailureHelper(); - virtual ~HasNewFatalFailureHelper(); - virtual void ReportTestPartResult(const TestPartResult& result); + virtual ~HasNewFatalFailureHelper() override; + virtual void ReportTestPartResult(const TestPartResult& result) override; bool has_new_fatal_failure() const { return has_new_fatal_failure_; } private: bool has_new_fatal_failure_; diff --git a/external/gtest/include/gtest/gtest.h b/external/gtest/include/gtest/gtest.h index 6fa0a392..82b58dc7 100644 --- a/external/gtest/include/gtest/gtest.h +++ b/external/gtest/include/gtest/gtest.h @@ -1011,21 +1011,21 @@ class TestEventListener { // above. class EmptyTestEventListener : public TestEventListener { public: - virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {} + virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) override {} virtual void OnTestIterationStart(const UnitTest& /*unit_test*/, - int /*iteration*/) {} - virtual void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) {} - virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {} - virtual void OnTestCaseStart(const TestCase& /*test_case*/) {} - virtual void OnTestStart(const TestInfo& /*test_info*/) {} - virtual void OnTestPartResult(const TestPartResult& /*test_part_result*/) {} - virtual void OnTestEnd(const TestInfo& /*test_info*/) {} - virtual void OnTestCaseEnd(const TestCase& /*test_case*/) {} - virtual void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) {} - virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {} + int /*iteration*/) override {} + virtual void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) override {} + virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) override {} + virtual void OnTestCaseStart(const TestCase& /*test_case*/) override {} + virtual void OnTestStart(const TestInfo& /*test_info*/) override {} + virtual void OnTestPartResult(const TestPartResult& /*test_part_result*/) override {} + virtual void OnTestEnd(const TestInfo& /*test_info*/) override {} + virtual void OnTestCaseEnd(const TestCase& /*test_case*/) override {} + virtual void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) override {} + virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) override {} virtual void OnTestIterationEnd(const UnitTest& /*unit_test*/, - int /*iteration*/) {} - virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {} + int /*iteration*/) override {} + virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) override {} }; // TestEventListeners lets users add listeners to track events in Google Test. diff --git a/external/gtest/include/gtest/internal/gtest-death-test-internal.h b/external/gtest/include/gtest/internal/gtest-death-test-internal.h index 2b3a78f5..a82aec1f 100644 --- a/external/gtest/include/gtest/internal/gtest-death-test-internal.h +++ b/external/gtest/include/gtest/internal/gtest-death-test-internal.h @@ -148,7 +148,7 @@ class DeathTestFactory { class DefaultDeathTestFactory : public DeathTestFactory { public: virtual bool Create(const char* statement, const RE* regex, - const char* file, int line, DeathTest** test); + const char* file, int line, DeathTest** test) override; }; // Returns true if exit_status describes a process that was terminated diff --git a/external/gtest/include/gtest/internal/gtest-internal.h b/external/gtest/include/gtest/internal/gtest-internal.h index 0dcc3a31..064fcfa4 100644 --- a/external/gtest/include/gtest/internal/gtest-internal.h +++ b/external/gtest/include/gtest/internal/gtest-internal.h @@ -451,7 +451,7 @@ class TestFactoryBase { template class TestFactoryImpl : public TestFactoryBase { public: - virtual Test* CreateTest() { return new TestClass; } + virtual Test* CreateTest() override { return new TestClass; } }; #if GTEST_OS_WINDOWS @@ -1138,7 +1138,7 @@ class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\ public:\ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\ private:\ - virtual void TestBody();\ + virtual void TestBody() override;\ static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;\ GTEST_DISALLOW_COPY_AND_ASSIGN_(\ GTEST_TEST_CLASS_NAME_(test_case_name, test_name));\ diff --git a/external/gtest/include/gtest/internal/gtest-param-util.h b/external/gtest/include/gtest/internal/gtest-param-util.h index d5e1028b..86ac88f7 100644 --- a/external/gtest/include/gtest/internal/gtest-param-util.h +++ b/external/gtest/include/gtest/internal/gtest-param-util.h @@ -270,12 +270,12 @@ class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface { template ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end) : container_(begin, end) {} - virtual ~ValuesInIteratorRangeGenerator() {} + virtual ~ValuesInIteratorRangeGenerator() override {} - virtual ParamIteratorInterface* Begin() const { + virtual ParamIteratorInterface* Begin() const override { return new Iterator(this, container_.begin()); } - virtual ParamIteratorInterface* End() const { + virtual ParamIteratorInterface* End() const override { return new Iterator(this, container_.end()); } @@ -287,16 +287,16 @@ class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface { Iterator(const ParamGeneratorInterface* base, typename ContainerType::const_iterator iterator) : base_(base), iterator_(iterator) {} - virtual ~Iterator() {} + virtual ~Iterator() override {} - virtual const ParamGeneratorInterface* BaseGenerator() const { + virtual const ParamGeneratorInterface* BaseGenerator() const override { return base_; } - virtual void Advance() { + virtual void Advance() override { ++iterator_; value_.reset(); } - virtual ParamIteratorInterface* Clone() const { + virtual ParamIteratorInterface* Clone() const override { return new Iterator(*this); } // We need to use cached value referenced by iterator_ because *iterator_ @@ -306,12 +306,12 @@ class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface { // can advance iterator_ beyond the end of the range, and we cannot // detect that fact. The client code, on the other hand, is // responsible for not calling Current() on an out-of-range iterator. - virtual const T* Current() const { + virtual const T* Current() const override { if (value_.get() == NULL) value_.reset(new T(*iterator_)); return value_.get(); } - virtual bool Equals(const ParamIteratorInterface& other) const { + virtual bool Equals(const ParamIteratorInterface& other) const override { // Having the same base generator guarantees that the other // iterator is of the same type and we can downcast. GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) @@ -355,7 +355,7 @@ class ParameterizedTestFactory : public TestFactoryBase { typedef typename TestClass::ParamType ParamType; explicit ParameterizedTestFactory(ParamType parameter) : parameter_(parameter) {} - virtual Test* CreateTest() { + virtual Test* CreateTest() override { TestClass::SetParam(¶meter_); return new TestClass(); } @@ -454,9 +454,9 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase { : test_case_name_(name) {} // Test case base name for display purposes. - virtual const string& GetTestCaseName() const { return test_case_name_; } + virtual const string& GetTestCaseName() const override { return test_case_name_; } // Test case id to verify identity. - virtual TypeId GetTestCaseTypeId() const { return GetTypeId(); } + virtual TypeId GetTestCaseTypeId() const override { return GetTypeId(); } // TEST_P macro uses AddTestPattern() to record information // about a single test in a LocalTestInfo structure. // test_case_name is the base name of the test case (without invocation @@ -484,7 +484,7 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase { // This method should not be called more then once on any single // instance of a ParameterizedTestCaseInfoBase derived class. // UnitTest has a guard to prevent from calling this method more then once. - virtual void RegisterTests() { + virtual void RegisterTests() override { for (typename TestInfoContainer::iterator test_it = tests_.begin(); test_it != tests_.end(); ++test_it) { linked_ptr test_info = *test_it; diff --git a/external/gtest/include/gtest/internal/gtest-port.h b/external/gtest/include/gtest/internal/gtest-port.h index dc4fe0cb..2c87972d 100644 --- a/external/gtest/include/gtest/internal/gtest-port.h +++ b/external/gtest/include/gtest/internal/gtest-port.h @@ -1296,7 +1296,7 @@ class ThreadWithParam : public ThreadWithParamBase { } } - virtual void Run() { + virtual void Run() override { if (thread_can_start_ != NULL) thread_can_start_->WaitForNotification(); func_(param_); diff --git a/external/gtest/src/gtest-death-test.cc b/external/gtest/src/gtest-death-test.cc index a6023fce..c158d0b8 100644 --- a/external/gtest/src/gtest-death-test.cc +++ b/external/gtest/src/gtest-death-test.cc @@ -373,8 +373,8 @@ class DeathTestImpl : public DeathTest { // read_fd_ is expected to be closed and cleared by a derived class. ~DeathTestImpl() { GTEST_DEATH_TEST_CHECK_(read_fd_ == -1); } - void Abort(AbortReason reason); - virtual bool Passed(bool status_ok); + void Abort(AbortReason reason) override; + virtual bool Passed(bool status_ok) override; const char* statement() const { return statement_; } const RE* regex() const { return regex_; } @@ -778,7 +778,7 @@ class ForkingDeathTest : public DeathTestImpl { ForkingDeathTest(const char* statement, const RE* regex); // All of these virtual functions are inherited from DeathTest. - virtual int Wait(); + virtual int Wait() override; protected: void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; } @@ -814,7 +814,7 @@ class NoExecDeathTest : public ForkingDeathTest { public: NoExecDeathTest(const char* a_statement, const RE* a_regex) : ForkingDeathTest(a_statement, a_regex) { } - virtual TestRole AssumeRole(); + virtual TestRole AssumeRole() override; }; // The AssumeRole process for a fork-and-run death test. It implements a @@ -870,7 +870,7 @@ class ExecDeathTest : public ForkingDeathTest { ExecDeathTest(const char* a_statement, const RE* a_regex, const char* file, int line) : ForkingDeathTest(a_statement, a_regex), file_(file), line_(line) { } - virtual TestRole AssumeRole(); + virtual TestRole AssumeRole() override; private: static ::std::vector GetArgvsForDeathTestChildProcess() { diff --git a/external/gtest/src/gtest-internal-inl.h b/external/gtest/src/gtest-internal-inl.h index 35df303c..65561806 100644 --- a/external/gtest/src/gtest-internal-inl.h +++ b/external/gtest/src/gtest-internal-inl.h @@ -441,10 +441,10 @@ class OsStackTraceGetter : public OsStackTraceGetterInterface { public: OsStackTraceGetter() : caller_frame_(NULL) {} - virtual string CurrentStackTrace(int max_depth, int skip_count) + virtual string CurrentStackTrace(int max_depth, int skip_count) override GTEST_LOCK_EXCLUDED_(mutex_); - virtual void UponLeavingGTest() GTEST_LOCK_EXCLUDED_(mutex_); + virtual void UponLeavingGTest() override GTEST_LOCK_EXCLUDED_(mutex_); // This string is inserted in place of stack frames that are part of // Google Test's implementation. @@ -477,7 +477,7 @@ class DefaultGlobalTestPartResultReporter explicit DefaultGlobalTestPartResultReporter(UnitTestImpl* unit_test); // Implements the TestPartResultReporterInterface. Reports the test part // result in the current test. - virtual void ReportTestPartResult(const TestPartResult& result); + virtual void ReportTestPartResult(const TestPartResult& result) override; private: UnitTestImpl* const unit_test_; @@ -493,7 +493,7 @@ class DefaultPerThreadTestPartResultReporter explicit DefaultPerThreadTestPartResultReporter(UnitTestImpl* unit_test); // Implements the TestPartResultReporterInterface. The implementation just // delegates to the current global test part result reporter of *unit_test_. - virtual void ReportTestPartResult(const TestPartResult& result); + virtual void ReportTestPartResult(const TestPartResult& result) override; private: UnitTestImpl* const unit_test_; @@ -1100,7 +1100,7 @@ class StreamingListener : public EmptyTestEventListener { } // Sends a string to the socket. - virtual void Send(const string& message) { + virtual void Send(const string& message) override { GTEST_CHECK_(sockfd_ != -1) << "Send() can be called only when there is a connection."; @@ -1117,7 +1117,7 @@ class StreamingListener : public EmptyTestEventListener { void MakeConnection(); // Closes the socket. - void CloseConnection() { + void CloseConnection() override { GTEST_CHECK_(sockfd_ != -1) << "CloseConnection() can be called only when there is a connection."; @@ -1141,11 +1141,11 @@ class StreamingListener : public EmptyTestEventListener { explicit StreamingListener(AbstractSocketWriter* socket_writer) : socket_writer_(socket_writer) { Start(); } - void OnTestProgramStart(const UnitTest& /* unit_test */) { + void OnTestProgramStart(const UnitTest& /* unit_test */) override { SendLn("event=TestProgramStart"); } - void OnTestProgramEnd(const UnitTest& unit_test) { + void OnTestProgramEnd(const UnitTest& unit_test) override { // Note that Google Test current only report elapsed time for each // test iteration, not for the entire test program. SendLn("event=TestProgramEnd&passed=" + FormatBool(unit_test.Passed())); @@ -1154,39 +1154,39 @@ class StreamingListener : public EmptyTestEventListener { socket_writer_->CloseConnection(); } - void OnTestIterationStart(const UnitTest& /* unit_test */, int iteration) { + void OnTestIterationStart(const UnitTest& /* unit_test */, int iteration) override { SendLn("event=TestIterationStart&iteration=" + StreamableToString(iteration)); } - void OnTestIterationEnd(const UnitTest& unit_test, int /* iteration */) { + void OnTestIterationEnd(const UnitTest& unit_test, int /* iteration */) override { SendLn("event=TestIterationEnd&passed=" + FormatBool(unit_test.Passed()) + "&elapsed_time=" + StreamableToString(unit_test.elapsed_time()) + "ms"); } - void OnTestCaseStart(const TestCase& test_case) { + void OnTestCaseStart(const TestCase& test_case) override { SendLn(std::string("event=TestCaseStart&name=") + test_case.name()); } - void OnTestCaseEnd(const TestCase& test_case) { + void OnTestCaseEnd(const TestCase& test_case) override { SendLn("event=TestCaseEnd&passed=" + FormatBool(test_case.Passed()) + "&elapsed_time=" + StreamableToString(test_case.elapsed_time()) + "ms"); } - void OnTestStart(const TestInfo& test_info) { + void OnTestStart(const TestInfo& test_info) override { SendLn(std::string("event=TestStart&name=") + test_info.name()); } - void OnTestEnd(const TestInfo& test_info) { + void OnTestEnd(const TestInfo& test_info) override { SendLn("event=TestEnd&passed=" + FormatBool((test_info.result())->Passed()) + "&elapsed_time=" + StreamableToString((test_info.result())->elapsed_time()) + "ms"); } - void OnTestPartResult(const TestPartResult& test_part_result) { + void OnTestPartResult(const TestPartResult& test_part_result) override { const char* file_name = test_part_result.file_name(); if (file_name == NULL) file_name = ""; diff --git a/external/gtest/src/gtest.cc b/external/gtest/src/gtest.cc index 6de53dd0..e3ad4f35 100644 --- a/external/gtest/src/gtest.cc +++ b/external/gtest/src/gtest.cc @@ -2697,19 +2697,19 @@ class PrettyUnitTestResultPrinter : public TestEventListener { } // The following methods override what's in the TestEventListener class. - virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {} - virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration); - virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test); - virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {} - virtual void OnTestCaseStart(const TestCase& test_case); - virtual void OnTestStart(const TestInfo& test_info); - virtual void OnTestPartResult(const TestPartResult& result); - virtual void OnTestEnd(const TestInfo& test_info); - virtual void OnTestCaseEnd(const TestCase& test_case); - virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test); - virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {} - virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); - virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) override {} + virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration) override; + virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test) override; + virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) override {} + virtual void OnTestCaseStart(const TestCase& test_case) override; + virtual void OnTestStart(const TestInfo& test_info) override; + virtual void OnTestPartResult(const TestPartResult& result) override; + virtual void OnTestEnd(const TestInfo& test_info) override; + virtual void OnTestCaseEnd(const TestCase& test_case) override; + virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test) override; + virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) override {} + virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration) override; + virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) override {} private: static void PrintFailedTests(const UnitTest& unit_test); @@ -2908,19 +2908,19 @@ class TestEventRepeater : public TestEventListener { bool forwarding_enabled() const { return forwarding_enabled_; } void set_forwarding_enabled(bool enable) { forwarding_enabled_ = enable; } - virtual void OnTestProgramStart(const UnitTest& unit_test); - virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration); - virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test); - virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test); - virtual void OnTestCaseStart(const TestCase& test_case); - virtual void OnTestStart(const TestInfo& test_info); - virtual void OnTestPartResult(const TestPartResult& result); - virtual void OnTestEnd(const TestInfo& test_info); - virtual void OnTestCaseEnd(const TestCase& test_case); - virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test); - virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test); - virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); - virtual void OnTestProgramEnd(const UnitTest& unit_test); + virtual void OnTestProgramStart(const UnitTest& unit_test) override; + virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration) override; + virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test) override; + virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test) override; + virtual void OnTestCaseStart(const TestCase& test_case) override; + virtual void OnTestStart(const TestInfo& test_info) override; + virtual void OnTestPartResult(const TestPartResult& result) override; + virtual void OnTestEnd(const TestInfo& test_info) override; + virtual void OnTestCaseEnd(const TestCase& test_case) override; + virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test) override; + virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test) override; + virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration) override; + virtual void OnTestProgramEnd(const UnitTest& unit_test) override; private: // Controls whether events will be forwarded to listeners_. Set to false @@ -3013,7 +3013,7 @@ class XmlUnitTestResultPrinter : public EmptyTestEventListener { public: explicit XmlUnitTestResultPrinter(const char* output_file); - virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); + virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration) override; private: // Is c a whitespace character that is normalized to a space character diff --git a/include/BlockchainExplorerData.h b/include/BlockchainExplorerData.h index ac216488..0a3cdbea 100644 --- a/include/BlockchainExplorerData.h +++ b/include/BlockchainExplorerData.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/include/CryptoNote.h b/include/CryptoNote.h index 709a30bc..ec10a78c 100644 --- a/include/CryptoNote.h +++ b/include/CryptoNote.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/include/CryptoTypes.h b/include/CryptoTypes.h index bf593eba..519aea05 100644 --- a/include/CryptoTypes.h +++ b/include/CryptoTypes.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/include/IBlockchainExplorer.h b/include/IBlockchainExplorer.h index 6fd8c8d1..eb8349a9 100644 --- a/include/IBlockchainExplorer.h +++ b/include/IBlockchainExplorer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/include/INode.h b/include/INode.h index f5145b95..3fef2dc1 100644 --- a/include/INode.h +++ b/include/INode.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/include/IObservable.h b/include/IObservable.h index a16551ff..f1245f69 100644 --- a/include/IObservable.h +++ b/include/IObservable.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/include/IStreamSerializable.h b/include/IStreamSerializable.h index 93836500..cf9ffa23 100644 --- a/include/IStreamSerializable.h +++ b/include/IStreamSerializable.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/include/ITransaction.h b/include/ITransaction.h index 7b2a5849..43cb891d 100644 --- a/include/ITransaction.h +++ b/include/ITransaction.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/include/ITransfersContainer.h b/include/ITransfersContainer.h index 20bb1212..cee1de16 100644 --- a/include/ITransfersContainer.h +++ b/include/ITransfersContainer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -84,7 +84,8 @@ public: virtual size_t transactionsCount() const = 0; virtual uint64_t balance(uint32_t flags = IncludeDefault) const = 0; virtual void getOutputs(std::vector& transfers, uint32_t flags = IncludeDefault) const = 0; - virtual bool getTransactionInformation(const Crypto::Hash& transactionHash, TransactionInformation& info, int64_t& txBalance) const = 0; + virtual bool getTransactionInformation(const Crypto::Hash& transactionHash, TransactionInformation& info, + uint64_t* amountIn = nullptr, uint64_t* amountOut = nullptr) const = 0; virtual std::vector getTransactionOutputs(const Crypto::Hash& transactionHash, uint32_t flags = IncludeDefault) const = 0; //only type flags are feasible for this function virtual std::vector getTransactionInputs(const Crypto::Hash& transactionHash, uint32_t flags) const = 0; diff --git a/include/ITransfersSynchronizer.h b/include/ITransfersSynchronizer.h index 2cec42a8..11ada519 100644 --- a/include/ITransfersSynchronizer.h +++ b/include/ITransfersSynchronizer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -49,6 +49,16 @@ public: virtual ITransfersContainer& getContainer() = 0; }; +class ITransfersSynchronizerObserver { +public: + virtual void onBlocksAdded(const Crypto::PublicKey& viewPublicKey, const std::vector& blockHashes) {} + virtual void onBlockchainDetach(const Crypto::PublicKey& viewPublicKey, uint32_t blockIndex) {} + virtual void onTransactionDeleteBegin(const Crypto::PublicKey& viewPublicKey, Crypto::Hash transactionHash) {} + virtual void onTransactionDeleteEnd(const Crypto::PublicKey& viewPublicKey, Crypto::Hash transactionHash) {} + virtual void onTransactionUpdated(const Crypto::PublicKey& viewPublicKey, const Crypto::Hash& transactionHash, + const std::vector& containers) {} +}; + class ITransfersSynchronizer : public IStreamSerializable { public: virtual ~ITransfersSynchronizer() {} @@ -58,6 +68,7 @@ public: virtual void getSubscriptions(std::vector& subscriptions) = 0; // returns nullptr if address is not found virtual ITransfersSubscription* getSubscription(const AccountPublicAddress& acc) = 0; + virtual std::vector getViewKeyKnownBlocks(const Crypto::PublicKey& publicViewKey) = 0; }; } diff --git a/include/IWallet.h b/include/IWallet.h index b6be1978..17b23727 100644 --- a/include/IWallet.h +++ b/include/IWallet.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -18,7 +18,9 @@ const uint32_t WALLET_UNCONFIRMED_TRANSACTION_HEIGHT = std::numeric_limits sourceAddresses; + std::vector destinations; + uint64_t fee = 0; + uint64_t mixIn = 0; + std::string extra; + uint64_t unlockTimestamp = 0; + DonationSettings donation; + std::string changeDestination; +}; + +struct WalletTransactionWithTransfers { + WalletTransaction transaction; + std::vector transfers; +}; + +struct TransactionsInBlockInfo { + Crypto::Hash blockHash; + std::vector transactions; +}; + class IWallet { public: virtual ~IWallet() {} @@ -84,6 +124,7 @@ public: virtual size_t getAddressCount() const = 0; virtual std::string getAddress(size_t index) const = 0; virtual KeyPair getAddressSpendKey(size_t index) const = 0; + virtual KeyPair getAddressSpendKey(const std::string& address) const = 0; virtual KeyPair getViewKey() const = 0; virtual std::string createAddress() = 0; virtual std::string createAddress(const Crypto::SecretKey& spendSecretKey) = 0; @@ -100,10 +141,19 @@ public: virtual size_t getTransactionTransferCount(size_t transactionIndex) const = 0; virtual WalletTransfer getTransactionTransfer(size_t transactionIndex, size_t transferIndex) const = 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& 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& destinations, uint64_t fee, uint64_t mixIn = 0, const std::string& extra = "", uint64_t unlockTimestamp = 0) = 0; + virtual WalletTransactionWithTransfers getTransaction(const Crypto::Hash& transactionHash) const = 0; + virtual std::vector getTransactions(const Crypto::Hash& blockHash, size_t count) const = 0; + virtual std::vector getTransactions(uint32_t blockIndex, size_t count) const = 0; + virtual std::vector getBlockHashes(uint32_t blockIndex, size_t count) const = 0; + virtual uint32_t getBlockCount() const = 0; + virtual std::vector getUnconfirmedTransactions() const = 0; + virtual std::vector getDelayedTransactionIds() const = 0; + + virtual size_t transfer(const TransactionParameters& sendingTransaction) = 0; + + virtual size_t makeTransaction(const TransactionParameters& sendingTransaction) = 0; + virtual void commitTransaction(size_t transactionId) = 0; + virtual void rollbackUncommitedTransaction(size_t transactionId) = 0; virtual void start() = 0; virtual void stop() = 0; diff --git a/include/IWalletLegacy.h b/include/IWalletLegacy.h index 74a90606..19b0d5d6 100644 --- a/include/IWalletLegacy.h +++ b/include/IWalletLegacy.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/BlockchainExplorer/BlockchainExplorer.cpp b/src/BlockchainExplorer/BlockchainExplorer.cpp index 8fd3380f..389fa22b 100755 --- a/src/BlockchainExplorer/BlockchainExplorer.cpp +++ b/src/BlockchainExplorer/BlockchainExplorer.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -65,12 +65,76 @@ private: const std::function requestFunc; }; +BlockchainExplorer::PoolUpdateGuard::PoolUpdateGuard() : + m_state(State::NONE) { +} + +bool BlockchainExplorer::PoolUpdateGuard::beginUpdate() { + auto state = m_state.load(); + for (;;) { + switch (state) { + case State::NONE: + if (m_state.compare_exchange_weak(state, State::UPDATING)) { + return true; + } + break; + + case State::UPDATING: + if (m_state.compare_exchange_weak(state, State::UPDATE_REQUIRED)) { + return false; + } + break; + + case State::UPDATE_REQUIRED: + return false; + + default: + assert(false); + return false; + } + } +} + +bool BlockchainExplorer::PoolUpdateGuard::endUpdate() { + auto state = m_state.load(); + for (;;) { + assert(state != State::NONE); + + if (m_state.compare_exchange_weak(state, State::NONE)) { + return state == State::UPDATE_REQUIRED; + } + } +} + +class ScopeExitHandler { +public: + ScopeExitHandler(std::function&& handler) : + m_handler(std::move(handler)), + m_cancelled(false) { + } + + ~ScopeExitHandler() { + if (!m_cancelled) { + m_handler(); + } + } + + void reset() { + m_cancelled = true; + } + +private: + std::function m_handler; + bool m_cancelled; +}; + BlockchainExplorer::BlockchainExplorer(INode& node, Logging::ILogger& logger) : node(node), logger(logger, "BlockchainExplorer"), state(NOT_INITIALIZED), synchronized(false), - observersCounter(0) {} + observersCounter(0) { +} BlockchainExplorer::~BlockchainExplorer() {} @@ -416,6 +480,12 @@ void BlockchainExplorer::poolChanged() { return; } + if (!poolUpdateGuard.beginUpdate()) { + return; + } + + ScopeExitHandler poolUpdateEndGuard(std::bind(&BlockchainExplorer::poolUpdateEndHandler, this)); + std::unique_lock lock(mutex); std::shared_ptr>> rawNewTransactionsPtr = std::make_shared>>(); @@ -438,8 +508,11 @@ void BlockchainExplorer::poolChanged() { ); } ); + request.performAsync(asyncContextCounter, [this, rawNewTransactionsPtr, removedTransactionsPtr, isBlockchainActualPtr](std::error_code ec) { + ScopeExitHandler poolUpdateEndGuard(std::bind(&BlockchainExplorer::poolUpdateEndHandler, this)); + if (ec) { logger(ERROR) << "Can't send poolChanged notification because can't get pool symmetric difference: " << ec.message(); return; @@ -461,12 +534,10 @@ void BlockchainExplorer::poolChanged() { for (const Hash hash : *removedTransactionsPtr) { auto iter = knownPoolState.find(hash); if (iter != knownPoolState.end()) { - removedTransactionsHashesPtr->push_back( - std::move(std::make_pair( - hash, - TransactionRemoveReason::INCLUDED_IN_BLOCK //Can't have real reason here. - )) - ); + removedTransactionsHashesPtr->push_back({ + hash, + TransactionRemoveReason::INCLUDED_IN_BLOCK // Can't have real reason here. + }); knownPoolState.erase(iter); } } @@ -487,21 +558,34 @@ void BlockchainExplorer::poolChanged() { std::placeholders::_1 ) ); + request.performAsync(asyncContextCounter, [this, newTransactionsHashesPtr, newTransactionsPtr, removedTransactionsHashesPtr](std::error_code ec) { + ScopeExitHandler poolUpdateEndGuard(std::bind(&BlockchainExplorer::poolUpdateEndHandler, this)); + if (ec) { logger(ERROR) << "Can't send poolChanged notification because can't get transactions: " << ec.message(); return; } + if (!newTransactionsPtr->empty() || !removedTransactionsHashesPtr->empty()) { observerManager.notify(&IBlockchainObserver::poolUpdated, *newTransactionsPtr, *removedTransactionsHashesPtr); logger(DEBUGGING) << "poolUpdated notification was successfully sent."; } } ); + + poolUpdateEndGuard.reset(); } ); - + + poolUpdateEndGuard.reset(); +} + +void BlockchainExplorer::poolUpdateEndHandler() { + if (poolUpdateGuard.endUpdate()) { + poolChanged(); + } } void BlockchainExplorer::blockchainSynchronized(uint32_t topHeight) { diff --git a/src/BlockchainExplorer/BlockchainExplorer.h b/src/BlockchainExplorer/BlockchainExplorer.h index ecfce61c..882e425d 100755 --- a/src/BlockchainExplorer/BlockchainExplorer.h +++ b/src/BlockchainExplorer/BlockchainExplorer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -61,6 +61,25 @@ public: typedef WalletAsyncContextCounter AsyncContextCounter; private: + void poolUpdateEndHandler(); + + class PoolUpdateGuard { + public: + PoolUpdateGuard(); + + bool beginUpdate(); + bool endUpdate(); + + private: + enum class State { + NONE, + UPDATING, + UPDATE_REQUIRED + }; + + std::atomic m_state; + }; + enum State { NOT_INITIALIZED, INITIALIZED @@ -81,6 +100,6 @@ private: Logging::LoggerRef logger; AsyncContextCounter asyncContextCounter; - + PoolUpdateGuard poolUpdateGuard; }; } diff --git a/src/BlockchainExplorer/BlockchainExplorerDataBuilder.cpp b/src/BlockchainExplorer/BlockchainExplorerDataBuilder.cpp index e54998be..6b3e612a 100755 --- a/src/BlockchainExplorer/BlockchainExplorerDataBuilder.cpp +++ b/src/BlockchainExplorer/BlockchainExplorerDataBuilder.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -54,7 +54,7 @@ bool BlockchainExplorerDataBuilder::fillTxExtra(const std::vector& rawE } else if (typeid(TransactionExtraPublicKey) == field.type()) { extraDetails.publicKey.push_back(std::move(boost::get(field).publicKey)); } else if (typeid(TransactionExtraNonce) == field.type()) { - extraDetails.nonce.push_back(std::move(Common::toHex(boost::get(field).nonce.data(), boost::get(field).nonce.size()))); + extraDetails.nonce.push_back(Common::toHex(boost::get(field).nonce.data(), boost::get(field).nonce.size())); } } return true; diff --git a/src/BlockchainExplorer/BlockchainExplorerDataBuilder.h b/src/BlockchainExplorer/BlockchainExplorerDataBuilder.h index 18e43824..c59cf3d6 100755 --- a/src/BlockchainExplorer/BlockchainExplorerDataBuilder.h +++ b/src/BlockchainExplorer/BlockchainExplorerDataBuilder.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/BlockchainExplorer/BlockchainExplorerErrors.cpp b/src/BlockchainExplorer/BlockchainExplorerErrors.cpp index cfeb3796..c31bad54 100644 --- a/src/BlockchainExplorer/BlockchainExplorerErrors.cpp +++ b/src/BlockchainExplorer/BlockchainExplorerErrors.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/BlockchainExplorer/BlockchainExplorerErrors.h b/src/BlockchainExplorer/BlockchainExplorerErrors.h index ab63cb22..8c2bd47f 100644 --- a/src/BlockchainExplorer/BlockchainExplorerErrors.h +++ b/src/BlockchainExplorer/BlockchainExplorerErrors.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -21,15 +21,15 @@ class BlockchainExplorerErrorCategory : public std::error_category { public: static BlockchainExplorerErrorCategory INSTANCE; - virtual const char* name() const throw() { + virtual const char* name() const throw() override { return "BlockchainExplorerErrorCategory"; } - virtual std::error_condition default_error_condition(int ev) const throw() { + virtual std::error_condition default_error_condition(int ev) const throw() override { return std::error_condition(ev, *this); } - virtual std::string message(int ev) const { + virtual std::string message(int ev) const override { switch (ev) { case static_cast(BlockchainExplorerErrorCodes::NOT_INITIALIZED): return "Object was not initialized"; case static_cast(BlockchainExplorerErrorCodes::ALREADY_INITIALIZED): return "Object has been already initialized"; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8712c995..b02ec289 100755 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -30,6 +30,7 @@ file(GLOB_RECURSE JsonRpcServer JsonRpcServer/*) file(GLOB_RECURSE PaymentGate PaymentGate/*) file(GLOB_RECURSE PaymentGateService PaymentGateService/*) +file(GLOB_RECURSE Miner Miner/*) source_group("" FILES $${Common} ${ConnectivityTool} ${Crypto} ${CryptoNoteCore} ${CryptoNoteProtocol} ${Daemon} ${JsonRpcServer} ${Http} ${Logging} ${NodeRpcProxy} ${P2p} ${Rpc} ${Serialization} ${SimpleWallet} ${System} ${Transfers} ${Wallet} ${WalletLegacy}) @@ -54,17 +55,17 @@ add_executable(ConnectivityTool ${ConnectivityTool}) add_executable(Daemon ${Daemon}) add_executable(SimpleWallet ${SimpleWallet}) add_executable(PaymentGateService ${PaymentGateService}) +add_executable(Miner ${Miner}) +if (MSVC) + target_link_libraries(System ws2_32) +endif () 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 BlockchainExplorer ${Boost_LIBRARIES}) target_link_libraries(SimpleWallet Wallet NodeRpcProxy Transfers Rpc Http Serialization CryptoNoteCore System Logging Common Crypto ${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 () +target_link_libraries(Miner CryptoNoteCore Rpc Serialization System Http Logging Common Crypto ${Boost_LIBRARIES}) add_dependencies(Rpc version) @@ -77,5 +78,6 @@ add_dependencies(P2P version) set_property(TARGET ConnectivityTool PROPERTY OUTPUT_NAME "connectivity_tool") set_property(TARGET SimpleWallet PROPERTY OUTPUT_NAME "simplewallet") set_property(TARGET PaymentGateService PROPERTY OUTPUT_NAME "walletd") +set_property(TARGET Miner PROPERTY OUTPUT_NAME "miner") #TODO Specify the name of daemon for your currency set_property(TARGET Daemon PROPERTY OUTPUT_NAME "cryptonoted") diff --git a/src/Common/ArrayRef.h b/src/Common/ArrayRef.h index 55e858eb..af5c53b7 100755 --- a/src/Common/ArrayRef.h +++ b/src/Common/ArrayRef.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/ArrayView.h b/src/Common/ArrayView.h index 5eb1ef3c..efa23ee5 100755 --- a/src/Common/ArrayView.h +++ b/src/Common/ArrayView.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/Base58.cpp b/src/Common/Base58.cpp index b06c8b36..7cf17b4a 100644 --- a/src/Common/Base58.cpp +++ b/src/Common/Base58.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/Base58.h b/src/Common/Base58.h index 07b82329..e509e90d 100644 --- a/src/Common/Base58.h +++ b/src/Common/Base58.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/BlockingQueue.cpp b/src/Common/BlockingQueue.cpp index ae74e612..9804fc89 100644 --- a/src/Common/BlockingQueue.cpp +++ b/src/Common/BlockingQueue.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/BlockingQueue.h b/src/Common/BlockingQueue.h index 3804ca6d..e8631add 100644 --- a/src/Common/BlockingQueue.h +++ b/src/Common/BlockingQueue.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/CommandLine.cpp b/src/Common/CommandLine.cpp index 5e81df40..84ce6d01 100644 --- a/src/Common/CommandLine.cpp +++ b/src/Common/CommandLine.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/CommandLine.h b/src/Common/CommandLine.h index 34cb05f1..b46cad4e 100644 --- a/src/Common/CommandLine.h +++ b/src/Common/CommandLine.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/ConsoleHandler.cpp b/src/Common/ConsoleHandler.cpp index e1fbb209..e135024a 100644 --- a/src/Common/ConsoleHandler.cpp +++ b/src/Common/ConsoleHandler.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/ConsoleHandler.h b/src/Common/ConsoleHandler.h index 5af4427b..895f1fe9 100644 --- a/src/Common/ConsoleHandler.h +++ b/src/Common/ConsoleHandler.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/ConsoleTools.cpp b/src/Common/ConsoleTools.cpp index 13ea1a0a..42cd128c 100644 --- a/src/Common/ConsoleTools.cpp +++ b/src/Common/ConsoleTools.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/ConsoleTools.h b/src/Common/ConsoleTools.h index 1f555221..19c59521 100644 --- a/src/Common/ConsoleTools.h +++ b/src/Common/ConsoleTools.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/IInputStream.cpp b/src/Common/IInputStream.cpp index 6fb7975c..6d95e488 100644 --- a/src/Common/IInputStream.cpp +++ b/src/Common/IInputStream.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/IInputStream.h b/src/Common/IInputStream.h index a12650b0..ed95ffff 100755 --- a/src/Common/IInputStream.h +++ b/src/Common/IInputStream.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/IOutputStream.cpp b/src/Common/IOutputStream.cpp index 35ca58c4..8bda2ee6 100644 --- a/src/Common/IOutputStream.cpp +++ b/src/Common/IOutputStream.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/IOutputStream.h b/src/Common/IOutputStream.h index 630c2651..773a77a2 100755 --- a/src/Common/IOutputStream.h +++ b/src/Common/IOutputStream.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/JsonValue.cpp b/src/Common/JsonValue.cpp index 8db0c38d..fe2a831d 100644 --- a/src/Common/JsonValue.cpp +++ b/src/Common/JsonValue.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/JsonValue.h b/src/Common/JsonValue.h index 98ab1293..45bb2d2d 100644 --- a/src/Common/JsonValue.h +++ b/src/Common/JsonValue.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/Math.cpp b/src/Common/Math.cpp index 72fa9773..1e595c0a 100644 --- a/src/Common/Math.cpp +++ b/src/Common/Math.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/Math.h b/src/Common/Math.h index d39dd871..474e505a 100644 --- a/src/Common/Math.h +++ b/src/Common/Math.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/MemoryInputStream.cpp b/src/Common/MemoryInputStream.cpp index c3f23506..d86ec466 100644 --- a/src/Common/MemoryInputStream.cpp +++ b/src/Common/MemoryInputStream.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/MemoryInputStream.h b/src/Common/MemoryInputStream.h index e5567c8e..507f422f 100644 --- a/src/Common/MemoryInputStream.h +++ b/src/Common/MemoryInputStream.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/ObserverManager.h b/src/Common/ObserverManager.h index 5e887c50..b3705728 100644 --- a/src/Common/ObserverManager.h +++ b/src/Common/ObserverManager.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -107,6 +107,32 @@ public: } } + template + void notify(F notification, const Arg0& arg0, const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, const Arg4& arg4) { + std::vector observersCopy; + { + std::unique_lock lock(m_observersMutex); + observersCopy = m_observers; + } + + for (T* observer : observersCopy) { + (observer->*notification)(arg0, arg1, arg2, arg3, arg4); + } + } + + template + void notify(F notification, const Arg0& arg0, const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, const Arg4& arg4, const Arg5& arg5) { + std::vector observersCopy; + { + std::unique_lock lock(m_observersMutex); + observersCopy = m_observers; + } + + for (T* observer : observersCopy) { + (observer->*notification)(arg0, arg1, arg2, arg3, arg4, arg5); + } + } + #else template diff --git a/src/Common/PathTools.cpp b/src/Common/PathTools.cpp index 33922f7b..30c3fd2d 100644 --- a/src/Common/PathTools.cpp +++ b/src/Common/PathTools.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/PathTools.h b/src/Common/PathTools.h index 87c7171d..4ffc11c7 100644 --- a/src/Common/PathTools.h +++ b/src/Common/PathTools.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/ScopeExit.cpp b/src/Common/ScopeExit.cpp new file mode 100644 index 00000000..c552938b --- /dev/null +++ b/src/Common/ScopeExit.cpp @@ -0,0 +1,24 @@ +// Copyright (c) 2011-2016 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "ScopeExit.h" + +namespace Tools { + +ScopeExit::ScopeExit(std::function&& handler) : + m_handler(std::move(handler)), + m_cancelled(false) { +} + +ScopeExit::~ScopeExit() { + if (!m_cancelled) { + m_handler(); + } +} + +void ScopeExit::cancel() { + m_cancelled = true; +} + +} diff --git a/src/Common/ScopeExit.h b/src/Common/ScopeExit.h new file mode 100644 index 00000000..143fe870 --- /dev/null +++ b/src/Common/ScopeExit.h @@ -0,0 +1,28 @@ +// Copyright (c) 2011-2016 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#pragma once + +#include + +namespace Tools { + +class ScopeExit { +public: + ScopeExit(std::function&& handler); + ~ScopeExit(); + + ScopeExit(const ScopeExit&) = delete; + ScopeExit(ScopeExit&&) = delete; + ScopeExit& operator=(const ScopeExit&) = delete; + ScopeExit& operator=(ScopeExit&&) = delete; + + void cancel(); + +private: + std::function m_handler; + bool m_cancelled; +}; + +} diff --git a/src/Common/ShuffleGenerator.h b/src/Common/ShuffleGenerator.h index adb33b56..c5a848ce 100644 --- a/src/Common/ShuffleGenerator.h +++ b/src/Common/ShuffleGenerator.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/SignalHandler.cpp b/src/Common/SignalHandler.cpp index 0f5e5b25..cc57ebc9 100755 --- a/src/Common/SignalHandler.cpp +++ b/src/Common/SignalHandler.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/SignalHandler.h b/src/Common/SignalHandler.h index 76b62e43..c15f81cf 100755 --- a/src/Common/SignalHandler.h +++ b/src/Common/SignalHandler.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/StdInputStream.cpp b/src/Common/StdInputStream.cpp index 9354c506..4af8a326 100644 --- a/src/Common/StdInputStream.cpp +++ b/src/Common/StdInputStream.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/StdInputStream.h b/src/Common/StdInputStream.h index 6c0d7d27..4e2f7dc8 100644 --- a/src/Common/StdInputStream.h +++ b/src/Common/StdInputStream.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/StdOutputStream.cpp b/src/Common/StdOutputStream.cpp index f442de5a..0c3637d8 100644 --- a/src/Common/StdOutputStream.cpp +++ b/src/Common/StdOutputStream.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/StdOutputStream.h b/src/Common/StdOutputStream.h index c200a428..ae5047cf 100644 --- a/src/Common/StdOutputStream.h +++ b/src/Common/StdOutputStream.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/StreamTools.cpp b/src/Common/StreamTools.cpp index a0a832fa..8db601e2 100755 --- a/src/Common/StreamTools.cpp +++ b/src/Common/StreamTools.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -145,7 +145,7 @@ void readVarint(IInputStream& in, uint64_t& value) { throw std::runtime_error("readVarint, value overflow"); } - temp |= static_cast(piece & 0x7f) << shift; + temp |= static_cast(piece & 0x7f) << shift; if ((piece & 0x80) == 0) { if (piece == 0 && shift != 0) { throw std::runtime_error("readVarint, invalid value representation"); diff --git a/src/Common/StreamTools.h b/src/Common/StreamTools.h index f5fa8a76..fa9a4021 100755 --- a/src/Common/StreamTools.h +++ b/src/Common/StreamTools.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/StringBuffer.h b/src/Common/StringBuffer.h index 6bb77349..48f16f75 100755 --- a/src/Common/StringBuffer.h +++ b/src/Common/StringBuffer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -19,6 +19,8 @@ public: const static Size MAXIMUM_SIZE = MAXIMUM_SIZE_VALUE; const static Size INVALID; + static_assert(MAXIMUM_SIZE != 0, "StringBuffer's size must not be zero"); + // Default constructor. // After construction, 'StringBuffer' is empty, that is 'size' == 0 StringBuffer() : size(0) { @@ -189,7 +191,6 @@ public: // Compare two strings character-wise. bool operator<(StringView other) const { - assert(data != nullptr || size == 0); Size count = other.getSize() < size ? other.getSize() : size; for (Size i = 0; i < count; ++i) { Object char1 = *(data + i); @@ -341,7 +342,6 @@ public: // Looks for the last occurence of 'object' in 'StringView', // returns index or INVALID if there are no occurences. Size findLast(const Object& object) const { - assert(data != nullptr || size == 0); for (Size i = 0; i < size; ++i) { if (*(data + (size - 1 - i)) == object) { return size - 1 - i; diff --git a/src/Common/StringInputStream.cpp b/src/Common/StringInputStream.cpp index 621f8ded..5cf0bd91 100755 --- a/src/Common/StringInputStream.cpp +++ b/src/Common/StringInputStream.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/StringInputStream.h b/src/Common/StringInputStream.h index 3864ad33..dd16efb2 100755 --- a/src/Common/StringInputStream.h +++ b/src/Common/StringInputStream.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/StringOutputStream.cpp b/src/Common/StringOutputStream.cpp index 63fb0696..27b9b187 100755 --- a/src/Common/StringOutputStream.cpp +++ b/src/Common/StringOutputStream.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/StringOutputStream.h b/src/Common/StringOutputStream.h index 861d8bd0..2a685d51 100755 --- a/src/Common/StringOutputStream.h +++ b/src/Common/StringOutputStream.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/StringTools.cpp b/src/Common/StringTools.cpp index 1f20cb15..385440cf 100755 --- a/src/Common/StringTools.cpp +++ b/src/Common/StringTools.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/StringTools.h b/src/Common/StringTools.h index fa44cb81..8d2a88a6 100755 --- a/src/Common/StringTools.h +++ b/src/Common/StringTools.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/StringView.cpp b/src/Common/StringView.cpp index d4d777c1..a789149e 100755 --- a/src/Common/StringView.cpp +++ b/src/Common/StringView.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/StringView.h b/src/Common/StringView.h index 93f73b0d..b4a191bc 100755 --- a/src/Common/StringView.h +++ b/src/Common/StringView.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/Util.cpp b/src/Common/Util.cpp index f0e1642d..f6ef06c4 100644 --- a/src/Common/Util.cpp +++ b/src/Common/Util.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -346,4 +346,9 @@ std::string get_nix_version_display_string() return std::error_code(code, std::system_category()); } + bool directoryExists(const std::string& path) { + boost::system::error_code ec; + return boost::filesystem::is_directory(path, ec); + } + } diff --git a/src/Common/Util.h b/src/Common/Util.h index 024a2afb..247ce90b 100644 --- a/src/Common/Util.h +++ b/src/Common/Util.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -13,4 +13,5 @@ namespace Tools 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); + bool directoryExists(const std::string& path); } diff --git a/src/Common/Varint.h b/src/Common/Varint.h index f82bae5f..86ff69b5 100644 --- a/src/Common/Varint.h +++ b/src/Common/Varint.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/VectorOutputStream.cpp b/src/Common/VectorOutputStream.cpp index ceb9919c..0ef41eb6 100644 --- a/src/Common/VectorOutputStream.cpp +++ b/src/Common/VectorOutputStream.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/VectorOutputStream.h b/src/Common/VectorOutputStream.h index ab84486b..5bc2173b 100644 --- a/src/Common/VectorOutputStream.h +++ b/src/Common/VectorOutputStream.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/int-util.h b/src/Common/int-util.h index 1d47f821..7f81dbbf 100644 --- a/src/Common/int-util.h +++ b/src/Common/int-util.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/pod-class.h b/src/Common/pod-class.h index 1e4334df..e91f8e4f 100644 --- a/src/Common/pod-class.h +++ b/src/Common/pod-class.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Common/static_assert.h b/src/Common/static_assert.h index 3e94a156..584c4edf 100644 --- a/src/Common/static_assert.h +++ b/src/Common/static_assert.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/ConnectivityTool/ConnectivityTool.cpp b/src/ConnectivityTool/ConnectivityTool.cpp index 5d17d85e..15738884 100755 --- a/src/ConnectivityTool/ConnectivityTool.cpp +++ b/src/ConnectivityTool/ConnectivityTool.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteConfig.h b/src/CryptoNoteConfig.h index 240776f2..4506f667 100644 --- a/src/CryptoNoteConfig.h +++ b/src/CryptoNoteConfig.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/Account.cpp b/src/CryptoNoteCore/Account.cpp index fc3a14b0..c1c16623 100755 --- a/src/CryptoNoteCore/Account.cpp +++ b/src/CryptoNoteCore/Account.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/Account.h b/src/CryptoNoteCore/Account.h index e00a5e41..863fbf96 100644 --- a/src/CryptoNoteCore/Account.h +++ b/src/CryptoNoteCore/Account.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/BlockIndex.cpp b/src/CryptoNoteCore/BlockIndex.cpp index b4f58a13..d6cf5a1c 100755 --- a/src/CryptoNoteCore/BlockIndex.cpp +++ b/src/CryptoNoteCore/BlockIndex.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/BlockIndex.h b/src/CryptoNoteCore/BlockIndex.h index c146a700..046b818c 100644 --- a/src/CryptoNoteCore/BlockIndex.h +++ b/src/CryptoNoteCore/BlockIndex.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/Blockchain.cpp b/src/CryptoNoteCore/Blockchain.cpp index 76c00953..3d42db48 100644 --- a/src/CryptoNoteCore/Blockchain.cpp +++ b/src/CryptoNoteCore/Blockchain.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -306,7 +306,6 @@ m_currency(currency), m_tx_pool(tx_pool), m_current_block_cumul_sz_limit(0), m_is_in_checkpoint_zone(false), -m_is_blockchain_storing(false), m_checkpoints(logger) { m_outputs.set_deleted_key(0); @@ -753,7 +752,7 @@ bool Blockchain::switch_to_alternative_blockchain(std::list m_is_in_checkpoint_zone; - std::atomic m_is_blockchain_storing; typedef SwappedVector Blocks; typedef std::unordered_map BlockMap; diff --git a/src/CryptoNoteCore/BlockchainIndices.cpp b/src/CryptoNoteCore/BlockchainIndices.cpp index e4bf2db7..0a67d3c2 100755 --- a/src/CryptoNoteCore/BlockchainIndices.cpp +++ b/src/CryptoNoteCore/BlockchainIndices.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/BlockchainIndices.h b/src/CryptoNoteCore/BlockchainIndices.h index b320ced7..66d56760 100755 --- a/src/CryptoNoteCore/BlockchainIndices.h +++ b/src/CryptoNoteCore/BlockchainIndices.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/BlockchainMessages.cpp b/src/CryptoNoteCore/BlockchainMessages.cpp index b3acb2d1..9e0dc70e 100644 --- a/src/CryptoNoteCore/BlockchainMessages.cpp +++ b/src/CryptoNoteCore/BlockchainMessages.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/BlockchainMessages.h b/src/CryptoNoteCore/BlockchainMessages.h index 543b2923..aa555f23 100644 --- a/src/CryptoNoteCore/BlockchainMessages.h +++ b/src/CryptoNoteCore/BlockchainMessages.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/Checkpoints.cpp b/src/CryptoNoteCore/Checkpoints.cpp index f927d25d..8fb76ced 100644 --- a/src/CryptoNoteCore/Checkpoints.cpp +++ b/src/CryptoNoteCore/Checkpoints.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/Checkpoints.h b/src/CryptoNoteCore/Checkpoints.h index 01dea81a..7e8e62f7 100644 --- a/src/CryptoNoteCore/Checkpoints.h +++ b/src/CryptoNoteCore/Checkpoints.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/Core.cpp b/src/CryptoNoteCore/Core.cpp index d0fba69c..65ef3961 100755 --- a/src/CryptoNoteCore/Core.cpp +++ b/src/CryptoNoteCore/Core.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -86,11 +86,6 @@ bool core::handle_command_line(const boost::program_options::variables_map& vm) return true; } -bool core::is_ready() { - return !m_blockchain.isStoringBlockchain(); -} - - uint32_t core::get_current_blockchain_height() { return m_blockchain.getCurrentBlockchainHeight(); } diff --git a/src/CryptoNoteCore/Core.h b/src/CryptoNoteCore/Core.h index b623db69..3e6e2fd5 100755 --- a/src/CryptoNoteCore/Core.h +++ b/src/CryptoNoteCore/Core.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -35,18 +35,18 @@ namespace CryptoNote { 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;} + bool on_idle() override; + virtual bool handle_incoming_tx(const BinaryArray& tx_blob, tx_verification_context& tvc, bool keeped_by_block) override; //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) override; + virtual i_cryptonote_protocol* get_protocol() override {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); + virtual bool handle_block_found(Block& b) override; + virtual bool get_block_template(Block& b, const AccountPublicAddress& adr, difficulty_type& diffic, uint32_t& height, const BinaryArray& ex_nonce) override; - bool addObserver(ICoreObserver* observer); - bool removeObserver(ICoreObserver* observer); + bool addObserver(ICoreObserver* observer) override; + bool removeObserver(ICoreObserver* observer) override; miner& get_miner() { return *m_miner; } static void init_options(boost::program_options::options_description& desc); @@ -80,13 +80,12 @@ namespace CryptoNote { virtual bool removeMessageQueue(MessageQueue& messageQueue) override; uint32_t get_current_blockchain_height(); - bool have_block(const Crypto::Hash& id); + bool have_block(const Crypto::Hash& id) override; std::vector buildSparseChain() override; std::vector buildSparseChain(const Crypto::Hash& startBlockId) override; - void on_synchronized(); - bool is_ready() override; + void on_synchronized() override; - virtual void get_blockchain_top(uint32_t& height, Crypto::Hash& top_id); + virtual void get_blockchain_top(uint32_t& height, Crypto::Hash& top_id) override; bool get_blocks(uint32_t start_offset, uint32_t count, std::list& blocks, std::list& txs); bool get_blocks(uint32_t start_offset, uint32_t count, std::list& blocks); template @@ -116,13 +115,13 @@ namespace CryptoNote { //bool get_outs(uint64_t amount, std::list& pkeys); virtual std::vector findBlockchainSupplement(const std::vector& remoteBlockIds, size_t maxCount, uint32_t& totalBlockCount, uint32_t& startBlockIndex) override; - bool get_stat_info(core_stat_info& st_inf); + bool get_stat_info(core_stat_info& st_inf) override; - virtual bool get_tx_outputs_gindexs(const Crypto::Hash& tx_id, std::vector& indexs); + virtual bool get_tx_outputs_gindexs(const Crypto::Hash& tx_id, std::vector& indexs) override; 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(); + 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) override; + void pause_mining() override; + void update_block_template_and_resume_mining() override; //Blockchain& get_blockchain_storage(){return m_blockchain;} //debug functions void print_blockchain(uint32_t start_index, uint32_t end_index); diff --git a/src/CryptoNoteCore/CoreConfig.cpp b/src/CryptoNoteCore/CoreConfig.cpp index 3bffb363..4b9e36e0 100644 --- a/src/CryptoNoteCore/CoreConfig.cpp +++ b/src/CryptoNoteCore/CoreConfig.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -16,6 +16,7 @@ CoreConfig::CoreConfig() { void CoreConfig::init(const boost::program_options::variables_map& options) { if (options.count(command_line::arg_data_dir.name) != 0 && (!options[command_line::arg_data_dir.name].defaulted() || configFolder == Tools::getDefaultDataDirectory())) { configFolder = command_line::get_arg(options, command_line::arg_data_dir); + configFolderDefaulted = options[command_line::arg_data_dir.name].defaulted(); } } diff --git a/src/CryptoNoteCore/CoreConfig.h b/src/CryptoNoteCore/CoreConfig.h index 0b741f49..d79f4516 100644 --- a/src/CryptoNoteCore/CoreConfig.h +++ b/src/CryptoNoteCore/CoreConfig.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -18,6 +18,7 @@ public: void init(const boost::program_options::variables_map& options); std::string configFolder; + bool configFolderDefaulted = true; }; } //namespace CryptoNote diff --git a/src/CryptoNoteCore/CryptoNoteBasic.cpp b/src/CryptoNoteCore/CryptoNoteBasic.cpp index 8d98749c..df683a49 100755 --- a/src/CryptoNoteCore/CryptoNoteBasic.cpp +++ b/src/CryptoNoteCore/CryptoNoteBasic.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/CryptoNoteBasic.h b/src/CryptoNoteCore/CryptoNoteBasic.h index c8f4a9a9..c1f25d94 100755 --- a/src/CryptoNoteCore/CryptoNoteBasic.h +++ b/src/CryptoNoteCore/CryptoNoteBasic.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/CryptoNoteBasicImpl.cpp b/src/CryptoNoteCore/CryptoNoteBasicImpl.cpp index c10f70e4..25897dbb 100644 --- a/src/CryptoNoteCore/CryptoNoteBasicImpl.cpp +++ b/src/CryptoNoteCore/CryptoNoteBasicImpl.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/CryptoNoteBasicImpl.h b/src/CryptoNoteCore/CryptoNoteBasicImpl.h index 41c1505b..f67ff6c3 100644 --- a/src/CryptoNoteCore/CryptoNoteBasicImpl.h +++ b/src/CryptoNoteCore/CryptoNoteBasicImpl.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/CryptoNoteFormatUtils.cpp b/src/CryptoNoteCore/CryptoNoteFormatUtils.cpp index f5c919c6..d4526fa4 100644 --- a/src/CryptoNoteCore/CryptoNoteFormatUtils.cpp +++ b/src/CryptoNoteCore/CryptoNoteFormatUtils.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/CryptoNoteFormatUtils.h b/src/CryptoNoteCore/CryptoNoteFormatUtils.h index 9318c4e0..b08fe984 100755 --- a/src/CryptoNoteCore/CryptoNoteFormatUtils.h +++ b/src/CryptoNoteCore/CryptoNoteFormatUtils.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/CryptoNoteSerialization.cpp b/src/CryptoNoteCore/CryptoNoteSerialization.cpp index 3e094991..8e19753c 100644 --- a/src/CryptoNoteCore/CryptoNoteSerialization.cpp +++ b/src/CryptoNoteCore/CryptoNoteSerialization.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/CryptoNoteSerialization.h b/src/CryptoNoteCore/CryptoNoteSerialization.h index 81b7f321..cbb7ba64 100755 --- a/src/CryptoNoteCore/CryptoNoteSerialization.h +++ b/src/CryptoNoteCore/CryptoNoteSerialization.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/CryptoNoteStatInfo.h b/src/CryptoNoteCore/CryptoNoteStatInfo.h index b6fb8ee8..62bcd5e5 100644 --- a/src/CryptoNoteCore/CryptoNoteStatInfo.h +++ b/src/CryptoNoteCore/CryptoNoteStatInfo.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/CryptoNoteTools.cpp b/src/CryptoNoteCore/CryptoNoteTools.cpp index f22b2604..1f1a00f9 100755 --- a/src/CryptoNoteCore/CryptoNoteTools.cpp +++ b/src/CryptoNoteCore/CryptoNoteTools.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/CryptoNoteTools.h b/src/CryptoNoteCore/CryptoNoteTools.h index 1d5c275b..296b18b2 100755 --- a/src/CryptoNoteCore/CryptoNoteTools.h +++ b/src/CryptoNoteCore/CryptoNoteTools.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/Currency.cpp b/src/CryptoNoteCore/Currency.cpp index 2f783b57..bfdc7b9e 100755 --- a/src/CryptoNoteCore/Currency.cpp +++ b/src/CryptoNoteCore/Currency.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/Currency.h b/src/CryptoNoteCore/Currency.h index 85a01a9d..30b727ef 100755 --- a/src/CryptoNoteCore/Currency.h +++ b/src/CryptoNoteCore/Currency.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/Difficulty.cpp b/src/CryptoNoteCore/Difficulty.cpp index fd7346ba..ec5ef0b0 100644 --- a/src/CryptoNoteCore/Difficulty.cpp +++ b/src/CryptoNoteCore/Difficulty.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/Difficulty.h b/src/CryptoNoteCore/Difficulty.h index 448a1c3a..8418f704 100644 --- a/src/CryptoNoteCore/Difficulty.h +++ b/src/CryptoNoteCore/Difficulty.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/IBlock.cpp b/src/CryptoNoteCore/IBlock.cpp index 6603936b..d5e8fab3 100644 --- a/src/CryptoNoteCore/IBlock.cpp +++ b/src/CryptoNoteCore/IBlock.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/IBlock.h b/src/CryptoNoteCore/IBlock.h index 94dd645c..eacf2209 100644 --- a/src/CryptoNoteCore/IBlock.h +++ b/src/CryptoNoteCore/IBlock.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/IBlockchainStorageObserver.h b/src/CryptoNoteCore/IBlockchainStorageObserver.h index 5b111bd0..e3f9086a 100644 --- a/src/CryptoNoteCore/IBlockchainStorageObserver.h +++ b/src/CryptoNoteCore/IBlockchainStorageObserver.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/ICore.h b/src/CryptoNoteCore/ICore.h index 5851d2df..d6a3db0c 100755 --- a/src/CryptoNoteCore/ICore.h +++ b/src/CryptoNoteCore/ICore.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -55,7 +55,6 @@ public: virtual bool handle_incoming_block_blob(const CryptoNote::BinaryArray& block_blob, CryptoNote::block_verification_context& bvc, bool control_miner, bool relay_block) = 0; virtual bool handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS_request& arg, NOTIFY_RESPONSE_GET_OBJECTS_request& rsp) = 0; //Deprecated. Should be removed with CryptoNoteProtocolHandler. virtual void on_synchronized() = 0; - virtual bool is_ready() = 0; virtual size_t addChain(const std::vector& chain) = 0; virtual void get_blockchain_top(uint32_t& height, Crypto::Hash& top_id) = 0; diff --git a/src/CryptoNoteCore/ICoreObserver.h b/src/CryptoNoteCore/ICoreObserver.h index 6f109acd..3ec4c3bb 100644 --- a/src/CryptoNoteCore/ICoreObserver.h +++ b/src/CryptoNoteCore/ICoreObserver.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/IMinerHandler.h b/src/CryptoNoteCore/IMinerHandler.h index 54959b2b..fcadccc2 100644 --- a/src/CryptoNoteCore/IMinerHandler.h +++ b/src/CryptoNoteCore/IMinerHandler.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/ITimeProvider.cpp b/src/CryptoNoteCore/ITimeProvider.cpp index 60417f0d..ec4da850 100644 --- a/src/CryptoNoteCore/ITimeProvider.cpp +++ b/src/CryptoNoteCore/ITimeProvider.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/ITimeProvider.h b/src/CryptoNoteCore/ITimeProvider.h index 9dd70137..0ef15972 100644 --- a/src/CryptoNoteCore/ITimeProvider.h +++ b/src/CryptoNoteCore/ITimeProvider.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -14,7 +14,7 @@ namespace CryptoNote { }; struct RealTimeProvider : public ITimeProvider { - virtual time_t now() { + virtual time_t now() override { return time(nullptr); } }; diff --git a/src/CryptoNoteCore/ITransactionValidator.h b/src/CryptoNoteCore/ITransactionValidator.h index e593cb1a..c32339d9 100644 --- a/src/CryptoNoteCore/ITransactionValidator.h +++ b/src/CryptoNoteCore/ITransactionValidator.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/ITxPoolObserver.h b/src/CryptoNoteCore/ITxPoolObserver.h index 0b7b70f4..ec91924b 100644 --- a/src/CryptoNoteCore/ITxPoolObserver.h +++ b/src/CryptoNoteCore/ITxPoolObserver.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/IntrusiveLinkedList.h b/src/CryptoNoteCore/IntrusiveLinkedList.h index d01897a6..7183593e 100644 --- a/src/CryptoNoteCore/IntrusiveLinkedList.h +++ b/src/CryptoNoteCore/IntrusiveLinkedList.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/MessageQueue.h b/src/CryptoNoteCore/MessageQueue.h index 81aae4df..29bd7dee 100644 --- a/src/CryptoNoteCore/MessageQueue.h +++ b/src/CryptoNoteCore/MessageQueue.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/Miner.cpp b/src/CryptoNoteCore/Miner.cpp index bef83708..772b7035 100644 --- a/src/CryptoNoteCore/Miner.cpp +++ b/src/CryptoNoteCore/Miner.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/Miner.h b/src/CryptoNoteCore/Miner.h index 924af413..22448c25 100644 --- a/src/CryptoNoteCore/Miner.h +++ b/src/CryptoNoteCore/Miner.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/MinerConfig.cpp b/src/CryptoNoteCore/MinerConfig.cpp index 6b1f4062..765eff23 100644 --- a/src/CryptoNoteCore/MinerConfig.cpp +++ b/src/CryptoNoteCore/MinerConfig.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/MinerConfig.h b/src/CryptoNoteCore/MinerConfig.h index c86af6cc..f0ebdc2b 100644 --- a/src/CryptoNoteCore/MinerConfig.h +++ b/src/CryptoNoteCore/MinerConfig.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/OnceInInterval.h b/src/CryptoNoteCore/OnceInInterval.h index 54715fa3..46e25fa9 100644 --- a/src/CryptoNoteCore/OnceInInterval.h +++ b/src/CryptoNoteCore/OnceInInterval.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/SwappedMap.cpp b/src/CryptoNoteCore/SwappedMap.cpp index c9ec192a..1b8ef024 100755 --- a/src/CryptoNoteCore/SwappedMap.cpp +++ b/src/CryptoNoteCore/SwappedMap.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/SwappedMap.h b/src/CryptoNoteCore/SwappedMap.h index 18fb9b1d..dd32945c 100644 --- a/src/CryptoNoteCore/SwappedMap.h +++ b/src/CryptoNoteCore/SwappedMap.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/SwappedVector.cpp b/src/CryptoNoteCore/SwappedVector.cpp index 1f940ac0..cb7f41c6 100755 --- a/src/CryptoNoteCore/SwappedVector.cpp +++ b/src/CryptoNoteCore/SwappedVector.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/SwappedVector.h b/src/CryptoNoteCore/SwappedVector.h index 2c3ccec1..22c529ee 100644 --- a/src/CryptoNoteCore/SwappedVector.h +++ b/src/CryptoNoteCore/SwappedVector.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/Transaction.cpp b/src/CryptoNoteCore/Transaction.cpp index 73936bf6..3bf880ce 100755 --- a/src/CryptoNoteCore/Transaction.cpp +++ b/src/CryptoNoteCore/Transaction.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/TransactionApi.h b/src/CryptoNoteCore/TransactionApi.h index 9881fde0..800dc43f 100755 --- a/src/CryptoNoteCore/TransactionApi.h +++ b/src/CryptoNoteCore/TransactionApi.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/TransactionApiExtra.h b/src/CryptoNoteCore/TransactionApiExtra.h index 446ba614..70ff859a 100644 --- a/src/CryptoNoteCore/TransactionApiExtra.h +++ b/src/CryptoNoteCore/TransactionApiExtra.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/TransactionExtra.cpp b/src/CryptoNoteCore/TransactionExtra.cpp index 2f1e8f00..4f836283 100755 --- a/src/CryptoNoteCore/TransactionExtra.cpp +++ b/src/CryptoNoteCore/TransactionExtra.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/TransactionExtra.h b/src/CryptoNoteCore/TransactionExtra.h index 30a3a35e..ae3c1b22 100755 --- a/src/CryptoNoteCore/TransactionExtra.h +++ b/src/CryptoNoteCore/TransactionExtra.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/TransactionPool.cpp b/src/CryptoNoteCore/TransactionPool.cpp index 265735b4..71fd81a7 100644 --- a/src/CryptoNoteCore/TransactionPool.cpp +++ b/src/CryptoNoteCore/TransactionPool.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/TransactionPool.h b/src/CryptoNoteCore/TransactionPool.h index 2b923530..405066cf 100644 --- a/src/CryptoNoteCore/TransactionPool.h +++ b/src/CryptoNoteCore/TransactionPool.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/TransactionPrefixImpl.cpp b/src/CryptoNoteCore/TransactionPrefixImpl.cpp index c295154f..77849226 100755 --- a/src/CryptoNoteCore/TransactionPrefixImpl.cpp +++ b/src/CryptoNoteCore/TransactionPrefixImpl.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/TransactionUtils.cpp b/src/CryptoNoteCore/TransactionUtils.cpp index 9708aed6..ed7ad4f2 100755 --- a/src/CryptoNoteCore/TransactionUtils.cpp +++ b/src/CryptoNoteCore/TransactionUtils.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/TransactionUtils.h b/src/CryptoNoteCore/TransactionUtils.h index 07f89078..64496488 100755 --- a/src/CryptoNoteCore/TransactionUtils.h +++ b/src/CryptoNoteCore/TransactionUtils.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteCore/VerificationContext.h b/src/CryptoNoteCore/VerificationContext.h index db0f3748..218d41bc 100644 --- a/src/CryptoNoteCore/VerificationContext.h +++ b/src/CryptoNoteCore/VerificationContext.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteProtocol/CryptoNoteProtocolDefinitions.h b/src/CryptoNoteProtocol/CryptoNoteProtocolDefinitions.h index e8e9b838..d7693c89 100644 --- a/src/CryptoNoteProtocol/CryptoNoteProtocolDefinitions.h +++ b/src/CryptoNoteProtocol/CryptoNoteProtocolDefinitions.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteProtocol/CryptoNoteProtocolHandler.cpp b/src/CryptoNoteProtocol/CryptoNoteProtocolHandler.cpp index 34dc4568..7d54cefd 100644 --- a/src/CryptoNoteProtocol/CryptoNoteProtocolHandler.cpp +++ b/src/CryptoNoteProtocol/CryptoNoteProtocolHandler.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -95,6 +95,9 @@ bool CryptoNoteProtocolHandler::start_sync(CryptoNoteConnectionContext& context) logger(Logging::TRACE) << context << "Starting synchronization"; if (context.m_state == CryptoNoteConnectionContext::state_synchronizing) { + assert(context.m_needed_objects.empty()); + assert(context.m_requested_objects.empty()); + NOTIFY_REQUEST_CHAIN::request r = boost::value_initialized(); r.block_ids = m_core.buildSparseChain(); logger(Logging::TRACE) << context << "-->>NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << r.block_ids.size(); @@ -342,15 +345,16 @@ int CryptoNoteProtocolHandler::handle_response_get_objects(int command, NOTIFY_R } } - auto req_it = context.m_requested_objects.find(get_block_hash(b)); + auto blockHash = get_block_hash(b); + auto req_it = context.m_requested_objects.find(blockHash); if (req_it == context.m_requested_objects.end()) { - logger(Logging::ERROR) << context << "sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << Common::podToHex(getBinaryArrayHash(asBinaryArray(block_entry.block))) + logger(Logging::ERROR) << context << "sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << Common::podToHex(blockHash) << " wasn't requested, dropping connection"; context.m_state = CryptoNoteConnectionContext::state_shutdown; return 1; } if (b.transactionHashes.size() != block_entry.txs.size()) { - logger(Logging::ERROR) << context << "sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << Common::podToHex(getBinaryArrayHash(asBinaryArray(block_entry.block))) + logger(Logging::ERROR) << context << "sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << Common::podToHex(blockHash) << ", transactionHashes.size()=" << b.transactionHashes.size() << " mismatch with block_complete_entry.m_txs.size()=" << block_entry.txs.size() << ", dropping connection"; context.m_state = CryptoNoteConnectionContext::state_shutdown; return 1; @@ -424,6 +428,8 @@ int CryptoNoteProtocolHandler::processObjects(CryptoNoteConnectionContext& conte } else if (bvc.m_already_exists) { logger(Logging::DEBUGGING) << context << "Block already exists, switching to idle state"; context.m_state = CryptoNoteConnectionContext::state_idle; + context.m_needed_objects.clear(); + context.m_requested_objects.clear(); return 1; } diff --git a/src/CryptoNoteProtocol/CryptoNoteProtocolHandler.h b/src/CryptoNoteProtocol/CryptoNoteProtocolHandler.h index 3831f4bd..fa59b386 100755 --- a/src/CryptoNoteProtocol/CryptoNoteProtocolHandler.h +++ b/src/CryptoNoteProtocol/CryptoNoteProtocolHandler.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -37,8 +37,8 @@ namespace CryptoNote CryptoNoteProtocolHandler(const Currency& currency, System::Dispatcher& dispatcher, ICore& rcore, IP2pEndpoint* p_net_layout, Logging::ILogger& log); - virtual bool addObserver(ICryptoNoteProtocolObserver* observer); - virtual bool removeObserver(ICryptoNoteProtocolObserver* observer); + virtual bool addObserver(ICryptoNoteProtocolObserver* observer) override; + virtual bool removeObserver(ICryptoNoteProtocolObserver* observer) override; void set_p2p_endpoint(IP2pEndpoint* p2p); // ICore& get_core() { return m_core; } @@ -55,8 +55,8 @@ namespace CryptoNote bool get_payload_sync_data(CORE_SYNC_DATA& hshd); bool process_payload_sync_data(const CORE_SYNC_DATA& hshd, CryptoNoteConnectionContext& context, bool is_inital); int handleCommand(bool is_notify, int command, const BinaryArray& in_buff, BinaryArray& buff_out, CryptoNoteConnectionContext& context, bool& handled); - virtual size_t getPeerCount() const; - virtual uint32_t getObservedHeight() const; + virtual size_t getPeerCount() const override; + virtual uint32_t getObservedHeight() const override; void requestMissingPoolTransactions(const CryptoNoteConnectionContext& context); private: diff --git a/src/CryptoNoteProtocol/CryptoNoteProtocolHandlerCommon.h b/src/CryptoNoteProtocol/CryptoNoteProtocolHandlerCommon.h index 51cff64b..9a7b1b5d 100644 --- a/src/CryptoNoteProtocol/CryptoNoteProtocolHandlerCommon.h +++ b/src/CryptoNoteProtocol/CryptoNoteProtocolHandlerCommon.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteProtocol/ICryptoNoteProtocolObserver.h b/src/CryptoNoteProtocol/ICryptoNoteProtocolObserver.h index 25e4e795..983b63f7 100644 --- a/src/CryptoNoteProtocol/ICryptoNoteProtocolObserver.h +++ b/src/CryptoNoteProtocol/ICryptoNoteProtocolObserver.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/CryptoNoteProtocol/ICryptoNoteProtocolQuery.h b/src/CryptoNoteProtocol/ICryptoNoteProtocolQuery.h index 706fe7d1..f34401fe 100644 --- a/src/CryptoNoteProtocol/ICryptoNoteProtocolQuery.h +++ b/src/CryptoNoteProtocol/ICryptoNoteProtocolQuery.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Daemon/Daemon.cpp b/src/Daemon/Daemon.cpp index acd87a8f..771c1cee 100755 --- a/src/Daemon/Daemon.cpp +++ b/src/Daemon/Daemon.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -218,11 +218,21 @@ int main(int argc, char* argv[]) RpcServerConfig rpcConfig; rpcConfig.init(vm); + if (!coreConfig.configFolderDefaulted) { + if (!Tools::directoryExists(coreConfig.configFolder)) { + throw std::runtime_error("Directory does not exist: " + coreConfig.configFolder); + } + } else { + if (!Tools::create_directories_if_necessary(coreConfig.configFolder)) { + throw std::runtime_error("Can't create directory: " + coreConfig.configFolder); + } + } + System::Dispatcher dispatcher; CryptoNote::CryptoNoteProtocolHandler cprotocol(currency, dispatcher, ccore, nullptr, logManager); CryptoNote::NodeServer p2psrv(dispatcher, cprotocol, logManager); - CryptoNote::RpcServer rpcServer(dispatcher, logManager, ccore, p2psrv); + CryptoNote::RpcServer rpcServer(dispatcher, logManager, ccore, p2psrv, cprotocol); cprotocol.set_p2p_endpoint(&p2psrv); ccore.set_cryptonote_protocol(&cprotocol); diff --git a/src/Daemon/DaemonCommandsHandler.cpp b/src/Daemon/DaemonCommandsHandler.cpp index 3188c945..2fd30993 100755 --- a/src/Daemon/DaemonCommandsHandler.cpp +++ b/src/Daemon/DaemonCommandsHandler.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Daemon/DaemonCommandsHandler.h b/src/Daemon/DaemonCommandsHandler.h index 97b892df..1bc96f07 100755 --- a/src/Daemon/DaemonCommandsHandler.h +++ b/src/Daemon/DaemonCommandsHandler.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/HTTP/HttpParser.cpp b/src/HTTP/HttpParser.cpp index ddfe26cc..af4183d1 100644 --- a/src/HTTP/HttpParser.cpp +++ b/src/HTTP/HttpParser.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/HTTP/HttpParser.h b/src/HTTP/HttpParser.h index 1cee19a8..aeb62554 100644 --- a/src/HTTP/HttpParser.h +++ b/src/HTTP/HttpParser.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/HTTP/HttpParserErrorCodes.cpp b/src/HTTP/HttpParserErrorCodes.cpp index b38ebe72..ef7eaf73 100755 --- a/src/HTTP/HttpParserErrorCodes.cpp +++ b/src/HTTP/HttpParserErrorCodes.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/HTTP/HttpParserErrorCodes.h b/src/HTTP/HttpParserErrorCodes.h index ef97f43f..985643aa 100755 --- a/src/HTTP/HttpParserErrorCodes.h +++ b/src/HTTP/HttpParserErrorCodes.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -22,15 +22,15 @@ class HttpParserErrorCategory : public std::error_category { public: static HttpParserErrorCategory INSTANCE; - virtual const char* name() const throw() { + virtual const char* name() const throw() override { return "HttpParserErrorCategory"; } - virtual std::error_condition default_error_condition(int ev) const throw() { + virtual std::error_condition default_error_condition(int ev) const throw() override { return std::error_condition(ev, *this); } - virtual std::string message(int ev) const { + virtual std::string message(int ev) const override { switch (ev) { case STREAM_NOT_GOOD: return "The stream is not good"; case END_OF_STREAM: return "The stream is ended"; diff --git a/src/HTTP/HttpRequest.cpp b/src/HTTP/HttpRequest.cpp index 88e241e1..755ade2e 100644 --- a/src/HTTP/HttpRequest.cpp +++ b/src/HTTP/HttpRequest.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/HTTP/HttpRequest.h b/src/HTTP/HttpRequest.h index d0e5198f..b080824d 100644 --- a/src/HTTP/HttpRequest.h +++ b/src/HTTP/HttpRequest.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/HTTP/HttpResponse.cpp b/src/HTTP/HttpResponse.cpp index 27a21523..bdc3b1a1 100644 --- a/src/HTTP/HttpResponse.cpp +++ b/src/HTTP/HttpResponse.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -28,7 +28,7 @@ const char* getErrorBody(CryptoNote::HttpResponse::HTTP_STATUS status) { case CryptoNote::HttpResponse::STATUS_404: return "Requested url is not found\n"; case CryptoNote::HttpResponse::STATUS_500: - return "Internal server error is occured\n"; + return "Internal server error is occurred\n"; default: throw std::runtime_error("Error body for given status is not available"); } diff --git a/src/HTTP/HttpResponse.h b/src/HTTP/HttpResponse.h index 02970992..b4595432 100644 --- a/src/HTTP/HttpResponse.h +++ b/src/HTTP/HttpResponse.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/InProcessNode/InProcessNode.cpp b/src/InProcessNode/InProcessNode.cpp index bb0863a5..3383e034 100644 --- a/src/InProcessNode/InProcessNode.cpp +++ b/src/InProcessNode/InProcessNode.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/InProcessNode/InProcessNode.h b/src/InProcessNode/InProcessNode.h index f973a8e5..63911e91 100644 --- a/src/InProcessNode/InProcessNode.h +++ b/src/InProcessNode/InProcessNode.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -38,9 +38,9 @@ public: virtual bool addObserver(INodeObserver* observer) override; virtual bool removeObserver(INodeObserver* observer) override; - virtual size_t getPeerCount() const; - virtual uint32_t getLastLocalBlockHeight() const; - virtual uint32_t getLastKnownBlockHeight() const; + virtual size_t getPeerCount() const override; + virtual uint32_t getLastLocalBlockHeight() const override; + virtual uint32_t getLastKnownBlockHeight() const override; virtual uint32_t getLocalBlockCount() const override; virtual uint32_t getKnownBlockCount() const override; virtual uint64_t getLastLocalBlockTimestamp() const override; diff --git a/src/InProcessNode/InProcessNodeErrors.cpp b/src/InProcessNode/InProcessNodeErrors.cpp index 53bf011f..02333178 100644 --- a/src/InProcessNode/InProcessNodeErrors.cpp +++ b/src/InProcessNode/InProcessNodeErrors.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/InProcessNode/InProcessNodeErrors.h b/src/InProcessNode/InProcessNodeErrors.h index ddd89f6a..f6292a95 100644 --- a/src/InProcessNode/InProcessNodeErrors.h +++ b/src/InProcessNode/InProcessNodeErrors.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -23,15 +23,15 @@ class InProcessNodeErrorCategory : public std::error_category { public: static InProcessNodeErrorCategory INSTANCE; - virtual const char* name() const throw() { + virtual const char* name() const throw() override { return "InProcessNodeErrorCategory"; } - virtual std::error_condition default_error_condition(int ev) const throw() { + virtual std::error_condition default_error_condition(int ev) const throw() override { return std::error_condition(ev, *this); } - virtual std::string message(int ev) const { + virtual std::string message(int ev) const override { switch (ev) { case NOT_INITIALIZED: return "Object was not initialized"; case ALREADY_INITIALIZED: return "Object has been already initialized"; diff --git a/src/JsonRpcServer/JsonRpcServer.cpp b/src/JsonRpcServer/JsonRpcServer.cpp index 2deea603..3fecce55 100755 --- a/src/JsonRpcServer/JsonRpcServer.cpp +++ b/src/JsonRpcServer/JsonRpcServer.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/JsonRpcServer/JsonRpcServer.h b/src/JsonRpcServer/JsonRpcServer.h index 6bb7e62f..b787885f 100755 --- a/src/JsonRpcServer/JsonRpcServer.h +++ b/src/JsonRpcServer/JsonRpcServer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Logging/CommonLogger.cpp b/src/Logging/CommonLogger.cpp index 38cd90da..0c2a8433 100755 --- a/src/Logging/CommonLogger.cpp +++ b/src/Logging/CommonLogger.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Logging/CommonLogger.h b/src/Logging/CommonLogger.h index 6a11b058..71654924 100755 --- a/src/Logging/CommonLogger.h +++ b/src/Logging/CommonLogger.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Logging/ConsoleLogger.cpp b/src/Logging/ConsoleLogger.cpp index c8b18918..36987d45 100755 --- a/src/Logging/ConsoleLogger.cpp +++ b/src/Logging/ConsoleLogger.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Logging/ConsoleLogger.h b/src/Logging/ConsoleLogger.h index b9cf19e0..5fce84fa 100755 --- a/src/Logging/ConsoleLogger.h +++ b/src/Logging/ConsoleLogger.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Logging/FileLogger.cpp b/src/Logging/FileLogger.cpp index c872b147..cae7818c 100755 --- a/src/Logging/FileLogger.cpp +++ b/src/Logging/FileLogger.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Logging/FileLogger.h b/src/Logging/FileLogger.h index 6ed41470..2284f9a6 100755 --- a/src/Logging/FileLogger.h +++ b/src/Logging/FileLogger.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Logging/ILogger.cpp b/src/Logging/ILogger.cpp index 658d7305..a451300a 100755 --- a/src/Logging/ILogger.cpp +++ b/src/Logging/ILogger.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Logging/ILogger.h b/src/Logging/ILogger.h index 63f3807b..72eaa75c 100755 --- a/src/Logging/ILogger.h +++ b/src/Logging/ILogger.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Logging/LoggerGroup.cpp b/src/Logging/LoggerGroup.cpp index 0855722f..a0eab7c2 100644 --- a/src/Logging/LoggerGroup.cpp +++ b/src/Logging/LoggerGroup.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Logging/LoggerGroup.h b/src/Logging/LoggerGroup.h index f4a9a353..11a50d4e 100755 --- a/src/Logging/LoggerGroup.h +++ b/src/Logging/LoggerGroup.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Logging/LoggerManager.cpp b/src/Logging/LoggerManager.cpp index 51d4c41f..3e6979c3 100755 --- a/src/Logging/LoggerManager.cpp +++ b/src/Logging/LoggerManager.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Logging/LoggerManager.h b/src/Logging/LoggerManager.h index 702e789f..b461cb99 100755 --- a/src/Logging/LoggerManager.h +++ b/src/Logging/LoggerManager.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Logging/LoggerMessage.cpp b/src/Logging/LoggerMessage.cpp index 92d669ee..443339fe 100644 --- a/src/Logging/LoggerMessage.cpp +++ b/src/Logging/LoggerMessage.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Logging/LoggerMessage.h b/src/Logging/LoggerMessage.h index 40165fb4..41ead09f 100755 --- a/src/Logging/LoggerMessage.h +++ b/src/Logging/LoggerMessage.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Logging/LoggerRef.cpp b/src/Logging/LoggerRef.cpp index bb582440..284b80bd 100755 --- a/src/Logging/LoggerRef.cpp +++ b/src/Logging/LoggerRef.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Logging/LoggerRef.h b/src/Logging/LoggerRef.h index 5d48778d..072b0d4d 100755 --- a/src/Logging/LoggerRef.h +++ b/src/Logging/LoggerRef.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Logging/StreamLogger.cpp b/src/Logging/StreamLogger.cpp index 5fce745e..cdfc5fc1 100755 --- a/src/Logging/StreamLogger.cpp +++ b/src/Logging/StreamLogger.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Logging/StreamLogger.h b/src/Logging/StreamLogger.h index 054c8fdb..54464c5f 100755 --- a/src/Logging/StreamLogger.h +++ b/src/Logging/StreamLogger.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Miner/BlockchainMonitor.cpp b/src/Miner/BlockchainMonitor.cpp new file mode 100644 index 00000000..e2b7baf2 --- /dev/null +++ b/src/Miner/BlockchainMonitor.cpp @@ -0,0 +1,92 @@ +// Copyright (c) 2011-2016 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "BlockchainMonitor.h" + +#include "Common/StringTools.h" + +#include +#include +#include + +#include "Rpc/CoreRpcServerCommandsDefinitions.h" +#include "Rpc/JsonRpc.h" +#include "Rpc/HttpClient.h" + +BlockchainMonitor::BlockchainMonitor(System::Dispatcher& dispatcher, const std::string& daemonHost, uint16_t daemonPort, size_t pollingInterval, Logging::ILogger& logger): + m_dispatcher(dispatcher), + m_daemonHost(daemonHost), + m_daemonPort(daemonPort), + m_pollingInterval(pollingInterval), + m_stopped(false), + m_httpEvent(dispatcher), + m_sleepingContext(dispatcher), + m_logger(logger, "BlockchainMonitor") { + + m_httpEvent.set(); +} + +void BlockchainMonitor::waitBlockchainUpdate() { + m_logger(Logging::DEBUGGING) << "Waiting for blockchain updates"; + m_stopped = false; + + Crypto::Hash lastBlockHash = requestLastBlockHash(); + + while(!m_stopped) { + m_sleepingContext.spawn([this] () { + System::Timer timer(m_dispatcher); + timer.sleep(std::chrono::seconds(m_pollingInterval)); + }); + + m_sleepingContext.wait(); + + if (lastBlockHash != requestLastBlockHash()) { + m_logger(Logging::DEBUGGING) << "Blockchain has been updated"; + break; + } + } + + if (m_stopped) { + m_logger(Logging::DEBUGGING) << "Blockchain monitor has been stopped"; + throw System::InterruptedException(); + } +} + +void BlockchainMonitor::stop() { + m_logger(Logging::DEBUGGING) << "Sending stop signal to blockchain monitor"; + m_stopped = true; + + m_sleepingContext.interrupt(); + m_sleepingContext.wait(); +} + +Crypto::Hash BlockchainMonitor::requestLastBlockHash() { + m_logger(Logging::DEBUGGING) << "Requesting last block hash"; + + try { + CryptoNote::HttpClient client(m_dispatcher, m_daemonHost, m_daemonPort); + + CryptoNote::COMMAND_RPC_GET_LAST_BLOCK_HEADER::request request; + CryptoNote::COMMAND_RPC_GET_LAST_BLOCK_HEADER::response response; + + System::EventLock lk(m_httpEvent); + CryptoNote::JsonRpc::invokeJsonRpcCommand(client, "getlastblockheader", request, response); + + if (response.status != CORE_RPC_STATUS_OK) { + throw std::runtime_error("Core responded with wrong status: " + response.status); + } + + Crypto::Hash blockHash; + if (!Common::podFromHex(response.block_header.hash, blockHash)) { + throw std::runtime_error("Couldn't parse block hash: " + response.block_header.hash); + } + + m_logger(Logging::DEBUGGING) << "Last block hash: " << Common::podToHex(blockHash); + + return blockHash; + } catch (std::exception& e) { + m_logger(Logging::ERROR) << "Failed to request last block hash: " << e.what(); + throw; + } +} diff --git a/src/Miner/BlockchainMonitor.h b/src/Miner/BlockchainMonitor.h new file mode 100644 index 00000000..59b1ebcb --- /dev/null +++ b/src/Miner/BlockchainMonitor.h @@ -0,0 +1,33 @@ +// Copyright (c) 2011-2016 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#pragma once + +#include "CryptoTypes.h" + +#include +#include +#include + +#include "Logging/LoggerRef.h" + +class BlockchainMonitor { +public: + BlockchainMonitor(System::Dispatcher& dispatcher, const std::string& daemonHost, uint16_t daemonPort, size_t pollingInterval, Logging::ILogger& logger); + + void waitBlockchainUpdate(); + void stop(); +private: + System::Dispatcher& m_dispatcher; + std::string m_daemonHost; + uint16_t m_daemonPort; + size_t m_pollingInterval; + bool m_stopped; + System::Event m_httpEvent; + System::ContextGroup m_sleepingContext; + + Logging::LoggerRef m_logger; + + Crypto::Hash requestLastBlockHash(); +}; diff --git a/src/Miner/Miner.cpp b/src/Miner/Miner.cpp new file mode 100644 index 00000000..a31ea224 --- /dev/null +++ b/src/Miner/Miner.cpp @@ -0,0 +1,144 @@ +// Copyright (c) 2011-2016 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "Miner.h" + +#include + +#include "crypto/crypto.h" +#include "CryptoNoteCore/CryptoNoteFormatUtils.h" + +#include + +namespace CryptoNote { + +Miner::Miner(System::Dispatcher& dispatcher, Logging::ILogger& logger) : + m_dispatcher(dispatcher), + m_miningStopped(dispatcher), + m_state(MiningState::MINING_STOPPED), + m_logger(logger, "Miner") { +} + +Miner::~Miner() { + assert(m_state != MiningState::MINING_IN_PROGRESS); +} + +Block Miner::mine(const BlockMiningParameters& blockMiningParameters, size_t threadCount) { + if (threadCount == 0) { + throw std::runtime_error("Miner requires at least one thread"); + } + + if (m_state == MiningState::MINING_IN_PROGRESS) { + throw std::runtime_error("Mining is already in progress"); + } + + m_state = MiningState::MINING_IN_PROGRESS; + m_miningStopped.clear(); + + runWorkers(blockMiningParameters, threadCount); + + assert(m_state != MiningState::MINING_IN_PROGRESS); + if (m_state == MiningState::MINING_STOPPED) { + m_logger(Logging::DEBUGGING) << "Mining has been stopped"; + throw System::InterruptedException(); + } + + assert(m_state == MiningState::BLOCK_FOUND); + return m_block; +} + +void Miner::stop() { + MiningState state = MiningState::MINING_IN_PROGRESS; + + if (m_state.compare_exchange_weak(state, MiningState::MINING_STOPPED)) { + m_miningStopped.wait(); + m_miningStopped.clear(); + } +} + +void Miner::runWorkers(BlockMiningParameters blockMiningParameters, size_t threadCount) { + assert(threadCount > 0); + + m_logger(Logging::INFO) << "Starting mining for difficulty " << blockMiningParameters.difficulty; + + try { + blockMiningParameters.blockTemplate.nonce = Crypto::rand(); + + for (size_t i = 0; i < threadCount; ++i) { + m_workers.emplace_back(std::unique_ptr> ( + new System::RemoteContext(m_dispatcher, std::bind(&Miner::workerFunc, this, blockMiningParameters.blockTemplate, blockMiningParameters.difficulty, threadCount))) + ); + + blockMiningParameters.blockTemplate.nonce++; + } + + m_workers.clear(); + + } catch (std::exception& e) { + m_logger(Logging::ERROR) << "Error occured during mining: " << e.what(); + m_state = MiningState::MINING_STOPPED; + } + + m_miningStopped.set(); +} + +void Miner::workerFunc(const Block& blockTemplate, difficulty_type difficulty, uint32_t nonceStep) { + try { + Block block = blockTemplate; + Crypto::cn_context cryptoContext; + + while (m_state == MiningState::MINING_IN_PROGRESS) { + Crypto::Hash hash; + if (!get_block_longhash(cryptoContext, block, hash)) { + //error occured + m_logger(Logging::DEBUGGING) << "calculating long hash error occured"; + m_state = MiningState::MINING_STOPPED; + return; + } + + if (check_hash(hash, difficulty)) { + m_logger(Logging::INFO) << "Found block for difficulty " << difficulty; + + if (!setStateBlockFound()) { + m_logger(Logging::DEBUGGING) << "block is already found or mining stopped"; + return; + } + + m_block = block; + return; + } + + block.nonce += nonceStep; + } + } catch (std::exception& e) { + m_logger(Logging::ERROR) << "Miner got error: " << e.what(); + m_state = MiningState::MINING_STOPPED; + } +} + +bool Miner::setStateBlockFound() { + auto state = m_state.load(); + + for (;;) { + switch (state) { + case MiningState::BLOCK_FOUND: + return false; + + case MiningState::MINING_IN_PROGRESS: + if (m_state.compare_exchange_weak(state, MiningState::BLOCK_FOUND)) { + return true; + } + break; + + case MiningState::MINING_STOPPED: + return false; + + default: + assert(false); + return false; + } + } +} + +} //namespace CryptoNote diff --git a/src/Miner/Miner.h b/src/Miner/Miner.h new file mode 100644 index 00000000..5f268be4 --- /dev/null +++ b/src/Miner/Miner.h @@ -0,0 +1,54 @@ +// Copyright (c) 2011-2016 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#pragma once + +#include +#include + +#include +#include +#include + +#include "CryptoNote.h" +#include "CryptoNoteCore/Difficulty.h" + +#include "Logging/LoggerRef.h" + +namespace CryptoNote { + +struct BlockMiningParameters { + Block blockTemplate; + difficulty_type difficulty; +}; + +class Miner { +public: + Miner(System::Dispatcher& dispatcher, Logging::ILogger& logger); + ~Miner(); + + Block mine(const BlockMiningParameters& blockMiningParameters, size_t threadCount); + + //NOTE! this is blocking method + void stop(); + +private: + System::Dispatcher& m_dispatcher; + System::Event m_miningStopped; + + enum class MiningState : uint8_t { MINING_STOPPED, BLOCK_FOUND, MINING_IN_PROGRESS}; + std::atomic m_state; + + std::vector>> m_workers; + + Block m_block; + + Logging::LoggerRef m_logger; + + void runWorkers(BlockMiningParameters blockMiningParameters, size_t threadCount); + void workerFunc(const Block& blockTemplate, difficulty_type difficulty, uint32_t nonceStep); + bool setStateBlockFound(); +}; + +} //namespace CryptoNote diff --git a/src/Miner/MinerEvent.h b/src/Miner/MinerEvent.h new file mode 100644 index 00000000..ba2f510c --- /dev/null +++ b/src/Miner/MinerEvent.h @@ -0,0 +1,18 @@ +// Copyright (c) 2011-2016 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#pragma once + +namespace Miner { + +enum class MinerEventType: uint8_t { + BLOCK_MINED, + BLOCKCHAIN_UPDATED, +}; + +struct MinerEvent { + MinerEventType type; +}; + +} //namespace Miner diff --git a/src/Miner/MinerManager.cpp b/src/Miner/MinerManager.cpp new file mode 100644 index 00000000..00afa936 --- /dev/null +++ b/src/Miner/MinerManager.cpp @@ -0,0 +1,246 @@ +// Copyright (c) 2011-2016 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "MinerManager.h" + +#include +#include +#include + +#include "Common/StringTools.h" +#include "CryptoNoteConfig.h" +#include "CryptoNoteCore/CryptoNoteTools.h" +#include "CryptoNoteCore/CryptoNoteFormatUtils.h" +#include "CryptoNoteCore/TransactionExtra.h" +#include "Rpc/HttpClient.h" +#include "Rpc/CoreRpcServerCommandsDefinitions.h" +#include "Rpc/JsonRpc.h" + +using namespace CryptoNote; + +namespace Miner { + +namespace { + +MinerEvent BlockMinedEvent() { + MinerEvent event; + event.type = MinerEventType::BLOCK_MINED; + return event; +} + +MinerEvent BlockchainUpdatedEvent() { + MinerEvent event; + event.type = MinerEventType::BLOCKCHAIN_UPDATED; + return event; +} + +} + +MinerManager::MinerManager(System::Dispatcher& dispatcher, const CryptoNote::MiningConfig& config, Logging::ILogger& logger) : + m_dispatcher(dispatcher), + m_logger(logger, "MinerManager"), + m_contextGroup(dispatcher), + m_config(config), + m_miner(dispatcher, logger), + m_blockchainMonitor(dispatcher, m_config.daemonHost, m_config.daemonPort, m_config.scanPeriod, logger), + m_eventOccurred(dispatcher), + m_httpEvent(dispatcher), + m_lastBlockTimestamp(0) { + + m_httpEvent.set(); +} + +MinerManager::~MinerManager() { +} + +void MinerManager::start() { + m_logger(Logging::DEBUGGING) << "starting"; + + BlockMiningParameters params; + for (;;) { + m_logger(Logging::INFO) << "requesting mining parameters"; + + try { + params = requestMiningParameters(m_dispatcher, m_config.daemonHost, m_config.daemonPort, m_config.miningAddress); + } catch (ConnectException& e) { + m_logger(Logging::WARNING) << "Couldn't connect to daemon: " << e.what(); + System::Timer timer(m_dispatcher); + timer.sleep(std::chrono::seconds(m_config.scanPeriod)); + continue; + } + + adjustBlockTemplate(params.blockTemplate); + break; + } + + startBlockchainMonitoring(); + startMining(params); + + eventLoop(); +} + +void MinerManager::eventLoop() { + size_t blocksMined = 0; + + for (;;) { + m_logger(Logging::DEBUGGING) << "waiting for event"; + MinerEvent event = waitEvent(); + + switch (event.type) { + case MinerEventType::BLOCK_MINED: { + m_logger(Logging::DEBUGGING) << "got BLOCK_MINED event"; + stopBlockchainMonitoring(); + + if (submitBlock(m_minedBlock, m_config.daemonHost, m_config.daemonPort)) { + m_lastBlockTimestamp = m_minedBlock.timestamp; + + if (m_config.blocksLimit != 0 && ++blocksMined == m_config.blocksLimit) { + m_logger(Logging::INFO) << "Miner mined requested " << m_config.blocksLimit << " blocks. Quitting"; + return; + } + } + + BlockMiningParameters params = requestMiningParameters(m_dispatcher, m_config.daemonHost, m_config.daemonPort, m_config.miningAddress); + adjustBlockTemplate(params.blockTemplate); + + startBlockchainMonitoring(); + startMining(params); + break; + } + + case MinerEventType::BLOCKCHAIN_UPDATED: { + m_logger(Logging::DEBUGGING) << "got BLOCKCHAIN_UPDATED event"; + stopMining(); + stopBlockchainMonitoring(); + BlockMiningParameters params = requestMiningParameters(m_dispatcher, m_config.daemonHost, m_config.daemonPort, m_config.miningAddress); + adjustBlockTemplate(params.blockTemplate); + + startBlockchainMonitoring(); + startMining(params); + break; + } + + default: + assert(false); + return; + } + } +} + +MinerEvent MinerManager::waitEvent() { + while(m_events.empty()) { + m_eventOccurred.wait(); + m_eventOccurred.clear(); + } + + MinerEvent event = std::move(m_events.front()); + m_events.pop(); + + return event; +} + +void MinerManager::pushEvent(MinerEvent&& event) { + m_events.push(std::move(event)); + m_eventOccurred.set(); +} + +void MinerManager::startMining(const CryptoNote::BlockMiningParameters& params) { + m_contextGroup.spawn([this, params] () { + try { + m_minedBlock = m_miner.mine(params, m_config.threadCount); + pushEvent(BlockMinedEvent()); + } catch (System::InterruptedException&) { + } catch (std::exception& e) { + m_logger(Logging::ERROR) << "Miner context unexpectedly finished: " << e.what(); + } + }); +} + +void MinerManager::stopMining() { + m_miner.stop(); +} + +void MinerManager::startBlockchainMonitoring() { + m_contextGroup.spawn([this] () { + try { + m_blockchainMonitor.waitBlockchainUpdate(); + pushEvent(BlockchainUpdatedEvent()); + } catch (System::InterruptedException&) { + } catch (std::exception& e) { + m_logger(Logging::ERROR) << "BlockchainMonitor context unexpectedly finished: " << e.what(); + } + }); +} + +void MinerManager::stopBlockchainMonitoring() { + m_blockchainMonitor.stop(); +} + +bool MinerManager::submitBlock(const Block& minedBlock, const std::string& daemonHost, uint16_t daemonPort) { + try { + HttpClient client(m_dispatcher, daemonHost, daemonPort); + + COMMAND_RPC_SUBMITBLOCK::request request; + request.emplace_back(Common::toHex(toBinaryArray(minedBlock))); + + COMMAND_RPC_SUBMITBLOCK::response response; + + System::EventLock lk(m_httpEvent); + JsonRpc::invokeJsonRpcCommand(client, "submitblock", request, response); + + m_logger(Logging::INFO) << "Block has been successfully submitted. Block hash: " << Common::podToHex(get_block_hash(minedBlock)); + return true; + } catch (std::exception& e) { + m_logger(Logging::WARNING) << "Couldn't submit block: " << Common::podToHex(get_block_hash(minedBlock)) << ", reason: " << e.what(); + return false; + } +} + +BlockMiningParameters MinerManager::requestMiningParameters(System::Dispatcher& dispatcher, const std::string& daemonHost, uint16_t daemonPort, const std::string& miningAddress) { + try { + HttpClient client(dispatcher, daemonHost, daemonPort); + + COMMAND_RPC_GETBLOCKTEMPLATE::request request; + request.wallet_address = miningAddress; + request.reserve_size = 0; + + COMMAND_RPC_GETBLOCKTEMPLATE::response response; + + System::EventLock lk(m_httpEvent); + JsonRpc::invokeJsonRpcCommand(client, "getblocktemplate", request, response); + + if (response.status != CORE_RPC_STATUS_OK) { + throw std::runtime_error("Core responded with wrong status: " + response.status); + } + + BlockMiningParameters params; + params.difficulty = response.difficulty; + + if(!fromBinaryArray(params.blockTemplate, Common::fromHex(response.blocktemplate_blob))) { + throw std::runtime_error("Couldn't deserialize block template"); + } + + m_logger(Logging::DEBUGGING) << "Requested block template with previous block hash: " << Common::podToHex(params.blockTemplate.previousBlockHash); + return params; + } catch (std::exception& e) { + m_logger(Logging::WARNING) << "Couldn't get block template: " << e.what(); + throw; + } +} + + +void MinerManager::adjustBlockTemplate(CryptoNote::Block& blockTemplate) const { + if (m_config.firstBlockTimestamp == 0) { + //no need to fix timestamp + return; + } + + if (m_lastBlockTimestamp == 0) { + blockTemplate.timestamp = m_config.firstBlockTimestamp; + } else if (m_lastBlockTimestamp != 0 && m_config.blockTimestampInterval != 0) { + blockTemplate.timestamp = m_lastBlockTimestamp + m_config.blockTimestampInterval; + } +} + +} //namespace Miner diff --git a/src/Miner/MinerManager.h b/src/Miner/MinerManager.h new file mode 100644 index 00000000..5fc157a8 --- /dev/null +++ b/src/Miner/MinerManager.h @@ -0,0 +1,63 @@ +// Copyright (c) 2011-2016 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#pragma once + +#include + +#include +#include + +#include "BlockchainMonitor.h" +#include "Logging/LoggerRef.h" +#include "Miner.h" +#include "MinerEvent.h" +#include "MiningConfig.h" + +namespace System { +class Dispatcher; +} + +namespace Miner { + +class MinerManager { +public: + MinerManager(System::Dispatcher& dispatcher, const CryptoNote::MiningConfig& config, Logging::ILogger& logger); + ~MinerManager(); + + void start(); + +private: + System::Dispatcher& m_dispatcher; + Logging::LoggerRef m_logger; + System::ContextGroup m_contextGroup; + CryptoNote::MiningConfig m_config; + CryptoNote::Miner m_miner; + BlockchainMonitor m_blockchainMonitor; + + System::Event m_eventOccurred; + System::Event m_httpEvent; + std::queue m_events; + + CryptoNote::Block m_minedBlock; + + uint64_t m_lastBlockTimestamp; + + void eventLoop(); + MinerEvent waitEvent(); + void pushEvent(MinerEvent&& event); + + void startMining(const CryptoNote::BlockMiningParameters& params); + void stopMining(); + + void startBlockchainMonitoring(); + void stopBlockchainMonitoring(); + + bool submitBlock(const CryptoNote::Block& minedBlock, const std::string& daemonHost, uint16_t daemonPort); + CryptoNote::BlockMiningParameters requestMiningParameters(System::Dispatcher& dispatcher, const std::string& daemonHost, uint16_t daemonPort, const std::string& miningAddress); + + void adjustBlockTemplate(CryptoNote::Block& blockTemplate) const; +}; + +} //namespace Miner diff --git a/src/Miner/MiningConfig.cpp b/src/Miner/MiningConfig.cpp new file mode 100644 index 00000000..3895efdd --- /dev/null +++ b/src/Miner/MiningConfig.cpp @@ -0,0 +1,125 @@ +// Copyright (c) 2011-2016 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "MiningConfig.h" + +#include +#include + +#include +#include +#include +#include + +#include "CryptoNoteConfig.h" +#include "Logging/ILogger.h" + +namespace po = boost::program_options; + +namespace CryptoNote { + +namespace { + +const size_t DEFAULT_SCANT_PERIOD = 30; +const char* DEFAULT_DAEMON_HOST = "127.0.0.1"; +const size_t CONCURRENCY_LEVEL = std::thread::hardware_concurrency(); + +po::options_description cmdOptions; + +void parseDaemonAddress(const std::string& daemonAddress, std::string& daemonHost, uint16_t& daemonPort) { + std::vector splittedAddress; + boost::algorithm::split(splittedAddress, daemonAddress, boost::algorithm::is_any_of(":")); + + if (splittedAddress.size() != 2) { + throw std::runtime_error("Wrong daemon address format"); + } + + if (splittedAddress[0].empty() || splittedAddress[1].empty()) { + throw std::runtime_error("Wrong daemon address format"); + } + + daemonHost = splittedAddress[0]; + + try { + daemonPort = boost::lexical_cast(splittedAddress[1]); + } catch (std::exception&) { + throw std::runtime_error("Wrong daemon address format"); + } +} + +} + +MiningConfig::MiningConfig(): help(false) { + cmdOptions.add_options() + ("help,h", "produce this help message and exit") + ("address", po::value(), "Valid cryptonote miner's address") + ("daemon-host", po::value()->default_value(DEFAULT_DAEMON_HOST), "Daemon host") + ("daemon-rpc-port", po::value()->default_value(static_cast(RPC_DEFAULT_PORT)), "Daemon's RPC port") + ("daemon-address", po::value(), "Daemon host:port. If you use this option you must not use --daemon-host and --daemon-port options") + ("threads", po::value()->default_value(CONCURRENCY_LEVEL), "Mining threads count. Must not be greater than you concurrency level. Default value is your hardware concurrency level") + ("scan-time", po::value()->default_value(DEFAULT_SCANT_PERIOD), "Blockchain polling interval (seconds). How often miner will check blockchain for updates") + ("log-level", po::value()->default_value(1), "Log level. Must be 0..5") + ("limit", po::value()->default_value(0), "Mine exact quantity of blocks. 0 means no limit") + ("first-block-timestamp", po::value()->default_value(0), "Set timestamp to the first mined block. 0 means leave timestamp unchanged") + ("block-timestamp-interval", po::value()->default_value(0), "Timestamp step for each subsequent block. May be set only if --first-block-timestamp has been set." + " If not set blocks' timestamps remain unchanged"); +} + +void MiningConfig::parse(int argc, char** argv) { + po::variables_map options; + po::store(po::parse_command_line(argc, argv, cmdOptions), options); + po::notify(options); + + if (options.count("help") != 0) { + help = true; + return; + } + + if (options.count("address") == 0) { + throw std::runtime_error("Specify --address option"); + } + + miningAddress = options["address"].as(); + + if (!options["daemon-address"].empty()) { + if (!options["daemon-host"].defaulted() || !options["daemon-rpc-port"].defaulted()) { + throw std::runtime_error("Either --daemon-host or --daemon-rpc-port is already specified. You must not specify --daemon-address"); + } + + parseDaemonAddress(options["daemon-address"].as(), daemonHost, daemonPort); + } else { + daemonHost = options["daemon-host"].as(); + daemonPort = options["daemon-rpc-port"].as(); + } + + threadCount = options["threads"].as(); + if (threadCount == 0 || threadCount > CONCURRENCY_LEVEL) { + throw std::runtime_error("--threads option must be 1.." + std::to_string(CONCURRENCY_LEVEL)); + } + + scanPeriod = options["scan-time"].as(); + if (scanPeriod == 0) { + throw std::runtime_error("--scan-time must not be zero"); + } + + logLevel = static_cast(options["log-level"].as()); + if (logLevel > static_cast(Logging::TRACE)) { + throw std::runtime_error("--log-level value is too big"); + } + + blocksLimit = options["limit"].as(); + + if (!options["block-timestamp-interval"].defaulted() && options["first-block-timestamp"].defaulted()) { + throw std::runtime_error("If you specify --block-timestamp-interval you must specify --first-block-timestamp either"); + } + + firstBlockTimestamp = options["first-block-timestamp"].as(); + blockTimestampInterval = options["block-timestamp-interval"].as(); +} + +void MiningConfig::printHelp() { + std::cout << cmdOptions << std::endl; +} + +} diff --git a/src/Miner/MiningConfig.h b/src/Miner/MiningConfig.h new file mode 100644 index 00000000..41b3ff01 --- /dev/null +++ b/src/Miner/MiningConfig.h @@ -0,0 +1,30 @@ +// Copyright (c) 2011-2016 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#pragma once + +#include +#include + +namespace CryptoNote { + +struct MiningConfig { + MiningConfig(); + + void parse(int argc, char** argv); + void printHelp(); + + std::string miningAddress; + std::string daemonHost; + uint16_t daemonPort; + size_t threadCount; + size_t scanPeriod; + uint8_t logLevel; + size_t blocksLimit; + uint64_t firstBlockTimestamp; + int64_t blockTimestampInterval; + bool help; +}; + +} //namespace CryptoNote diff --git a/src/Miner/main.cpp b/src/Miner/main.cpp new file mode 100644 index 00000000..deea5a98 --- /dev/null +++ b/src/Miner/main.cpp @@ -0,0 +1,39 @@ +// Copyright (c) 2011-2016 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "Common/SignalHandler.h" + +#include "Logging/LoggerGroup.h" +#include "Logging/ConsoleLogger.h" +#include "Logging/LoggerRef.h" + +#include "MinerManager.h" + +#include + +int main(int argc, char** argv) { + try { + CryptoNote::MiningConfig config; + config.parse(argc, argv); + + if (config.help) { + config.printHelp(); + return 0; + } + + Logging::LoggerGroup loggerGroup; + Logging::ConsoleLogger consoleLogger(static_cast(config.logLevel)); + loggerGroup.addLogger(consoleLogger); + + System::Dispatcher dispatcher; + Miner::MinerManager app(dispatcher, config, loggerGroup); + + app.start(); + } catch (std::exception& e) { + std::cerr << "Fatal: " << e.what() << std::endl; + return 1; + } + + return 0; +} diff --git a/src/NodeRpcProxy/NodeErrors.cpp b/src/NodeRpcProxy/NodeErrors.cpp index 341bd67c..bcac096f 100644 --- a/src/NodeRpcProxy/NodeErrors.cpp +++ b/src/NodeRpcProxy/NodeErrors.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/NodeRpcProxy/NodeErrors.h b/src/NodeRpcProxy/NodeErrors.h index b10981e8..294ec142 100644 --- a/src/NodeRpcProxy/NodeErrors.h +++ b/src/NodeRpcProxy/NodeErrors.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -26,15 +26,15 @@ class NodeErrorCategory : public std::error_category { public: static NodeErrorCategory INSTANCE; - virtual const char* name() const throw() { + virtual const char* name() const throw() override { return "NodeErrorCategory"; } - virtual std::error_condition default_error_condition(int ev) const throw() { + virtual std::error_condition default_error_condition(int ev) const throw() override { return std::error_condition(ev, *this); } - virtual std::string message(int ev) const { + virtual std::string message(int ev) const override { switch (ev) { case NOT_INITIALIZED: return "Object was not initialized"; case ALREADY_INITIALIZED: return "Object has been already initialized"; diff --git a/src/NodeRpcProxy/NodeRpcProxy.cpp b/src/NodeRpcProxy/NodeRpcProxy.cpp index 3edb995c..b1b4a549 100644 --- a/src/NodeRpcProxy/NodeRpcProxy.cpp +++ b/src/NodeRpcProxy/NodeRpcProxy.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -212,36 +212,36 @@ void NodeRpcProxy::updateBlockchainStatus() { m_lastKnowHash = blockHash; m_nodeHeight.store(static_cast(rsp.block_header.height), std::memory_order_relaxed); m_lastLocalBlockTimestamp.store(rsp.block_header.timestamp, std::memory_order_relaxed); - // TODO request and update network height - m_networkHeight.store(static_cast(rsp.block_header.height), std::memory_order_relaxed); - m_observerManager.notify(&INodeObserver::lastKnownBlockHeightUpdated, m_networkHeight.load(std::memory_order_relaxed)); - //if (m_networkHeight.load(std::memory_order_relaxed) != rsp.block_header.network_height) { - // m_networkHeight.store(rsp.block_header.height, std::memory_order_relaxed); - // m_observerManager.notify(&INodeObserver::lastKnownBlockHeightUpdated, m_networkHeight); - //} m_observerManager.notify(&INodeObserver::localBlockchainUpdated, m_nodeHeight.load(std::memory_order_relaxed)); } } - updatePeerCount(); + CryptoNote::COMMAND_RPC_GET_INFO::request getInfoReq = AUTO_VAL_INIT(getInfoReq); + CryptoNote::COMMAND_RPC_GET_INFO::response getInfoResp = AUTO_VAL_INIT(getInfoResp); + + ec = jsonCommand("/getinfo", getInfoReq, getInfoResp); + if (!ec) { + //a quirk to let wallets work with previous versions daemons. + //Previous daemons didn't have the 'last_known_block_index' parameter in RPC so it may have zero value. + auto lastKnownBlockIndex = std::max(getInfoResp.last_known_block_index, m_nodeHeight.load(std::memory_order_relaxed)); + if (m_networkHeight.load(std::memory_order_relaxed) != lastKnownBlockIndex) { + m_networkHeight.store(lastKnownBlockIndex, std::memory_order_relaxed); + m_observerManager.notify(&INodeObserver::lastKnownBlockHeightUpdated, m_networkHeight.load(std::memory_order_relaxed)); + } + + updatePeerCount(getInfoResp.incoming_connections_count + getInfoResp.outgoing_connections_count); + } + if (m_connected != m_httpClient->isConnected()) { m_connected = m_httpClient->isConnected(); m_rpcProxyObserverManager.notify(&INodeRpcProxyObserver::connectionStatusUpdated, m_connected); } } -void NodeRpcProxy::updatePeerCount() { - CryptoNote::COMMAND_RPC_GET_INFO::request req = AUTO_VAL_INIT(req); - CryptoNote::COMMAND_RPC_GET_INFO::response rsp = AUTO_VAL_INIT(rsp); - - std::error_code ec = jsonCommand("/getinfo", req, rsp); - - if (!ec) { - size_t peerCount = rsp.incoming_connections_count + rsp.outgoing_connections_count; - if (peerCount != m_peerCount) { - m_peerCount = peerCount; - m_observerManager.notify(&INodeObserver::peerCountUpdated, m_peerCount.load(std::memory_order_relaxed)); - } +void NodeRpcProxy::updatePeerCount(size_t peerCount) { + if (peerCount != m_peerCount) { + m_peerCount = peerCount; + m_observerManager.notify(&INodeObserver::peerCountUpdated, m_peerCount.load(std::memory_order_relaxed)); } } @@ -293,7 +293,7 @@ uint32_t NodeRpcProxy::getLocalBlockCount() const { } uint32_t NodeRpcProxy::getKnownBlockCount() const { - return m_networkHeight.load(std::memory_order_relaxed); + return m_networkHeight.load(std::memory_order_relaxed) + 1; } uint64_t NodeRpcProxy::getLastLocalBlockTimestamp() const { diff --git a/src/NodeRpcProxy/NodeRpcProxy.h b/src/NodeRpcProxy/NodeRpcProxy.h index 9782a615..70274727 100644 --- a/src/NodeRpcProxy/NodeRpcProxy.h +++ b/src/NodeRpcProxy/NodeRpcProxy.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -35,25 +35,25 @@ public: NodeRpcProxy(const std::string& nodeHost, unsigned short nodePort); virtual ~NodeRpcProxy(); - virtual bool addObserver(CryptoNote::INodeObserver* observer); - virtual bool removeObserver(CryptoNote::INodeObserver* observer); + virtual bool addObserver(CryptoNote::INodeObserver* observer) override; + virtual bool removeObserver(CryptoNote::INodeObserver* observer) override; virtual bool addObserver(CryptoNote::INodeRpcProxyObserver* observer); virtual bool removeObserver(CryptoNote::INodeRpcProxyObserver* observer); - virtual void init(const Callback& callback); - virtual bool shutdown(); + virtual void init(const Callback& callback) override; + virtual bool shutdown() override; - virtual size_t getPeerCount() const; - virtual uint32_t getLastLocalBlockHeight() const; - virtual uint32_t getLastKnownBlockHeight() const; + virtual size_t getPeerCount() const override; + virtual uint32_t getLastLocalBlockHeight() const override; + virtual uint32_t getLastKnownBlockHeight() const override; virtual uint32_t getLocalBlockCount() const override; virtual uint32_t getKnownBlockCount() const override; virtual uint64_t getLastLocalBlockTimestamp() const override; - virtual void relayTransaction(const CryptoNote::Transaction& transaction, const Callback& callback); - virtual void getRandomOutsByAmounts(std::vector&& amounts, uint64_t outsCount, std::vector& result, const Callback& callback); - virtual void getNewBlocks(std::vector&& knownBlockIds, std::vector& newBlocks, uint32_t& startHeight, const Callback& callback); + virtual void relayTransaction(const CryptoNote::Transaction& transaction, const Callback& callback) override; + virtual void getRandomOutsByAmounts(std::vector&& amounts, uint64_t outsCount, std::vector& result, const Callback& callback) override; + virtual void getNewBlocks(std::vector&& knownBlockIds, std::vector& newBlocks, uint32_t& startHeight, const Callback& callback) override; 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; virtual void getPoolSymmetricDifference(std::vector&& knownPoolTxIds, Crypto::Hash knownBlockId, bool& isBcActual, @@ -79,7 +79,7 @@ private: void updateNodeStatus(); void updateBlockchainStatus(); bool updatePoolStatus(); - void updatePeerCount(); + void updatePeerCount(size_t peerCount); void updatePoolState(const std::vector>& addedTxs, const std::vector& deletedTxsIds); std::error_code doRelayTransaction(const CryptoNote::Transaction& transaction); diff --git a/src/P2p/ConnectionContext.h b/src/P2p/ConnectionContext.h index 0d8d95dd..435b0826 100755 --- a/src/P2p/ConnectionContext.h +++ b/src/P2p/ConnectionContext.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/P2p/IP2pNodeInternal.cpp b/src/P2p/IP2pNodeInternal.cpp index 16afd764..676eae87 100644 --- a/src/P2p/IP2pNodeInternal.cpp +++ b/src/P2p/IP2pNodeInternal.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/P2p/IP2pNodeInternal.h b/src/P2p/IP2pNodeInternal.h index 9111ab9e..20166008 100644 --- a/src/P2p/IP2pNodeInternal.h +++ b/src/P2p/IP2pNodeInternal.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/P2p/LevinProtocol.cpp b/src/P2p/LevinProtocol.cpp index 9144d6ae..fab0ebbe 100644 --- a/src/P2p/LevinProtocol.cpp +++ b/src/P2p/LevinProtocol.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/P2p/LevinProtocol.h b/src/P2p/LevinProtocol.h index bcfc288d..2164193f 100755 --- a/src/P2p/LevinProtocol.h +++ b/src/P2p/LevinProtocol.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/P2p/NetNode.cpp b/src/P2p/NetNode.cpp index 1dac2a4e..ddee5452 100644 --- a/src/P2p/NetNode.cpp +++ b/src/P2p/NetNode.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/P2p/NetNode.h b/src/P2p/NetNode.h index 36f8e954..3d37d034 100644 --- a/src/P2p/NetNode.h +++ b/src/P2p/NetNode.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/P2p/NetNodeCommon.h b/src/P2p/NetNodeCommon.h index f4a2213a..2272bf9d 100755 --- a/src/P2p/NetNodeCommon.h +++ b/src/P2p/NetNodeCommon.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -21,10 +21,10 @@ namespace CryptoNote { }; struct p2p_endpoint_stub: public IP2pEndpoint { - virtual void relay_notify_to_all(int command, const BinaryArray& data_buff, const net_connection_id* excludeConnection) {} - virtual bool invoke_notify_to_peer(int command, const BinaryArray& req_buff, const CryptoNote::CryptoNoteConnectionContext& context) { return true; } - virtual void for_each_connection(std::function f) {} - virtual uint64_t get_connections_count() { return 0; } - virtual void externalRelayNotifyToAll(int command, const BinaryArray& data_buff) {} + virtual void relay_notify_to_all(int command, const BinaryArray& data_buff, const net_connection_id* excludeConnection) override {} + virtual bool invoke_notify_to_peer(int command, const BinaryArray& req_buff, const CryptoNote::CryptoNoteConnectionContext& context) override { return true; } + virtual void for_each_connection(std::function f) override {} + virtual uint64_t get_connections_count() override { return 0; } + virtual void externalRelayNotifyToAll(int command, const BinaryArray& data_buff) override {} }; } diff --git a/src/P2p/NetNodeConfig.cpp b/src/P2p/NetNodeConfig.cpp index ece143b6..a6ffa48c 100644 --- a/src/P2p/NetNodeConfig.cpp +++ b/src/P2p/NetNodeConfig.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -67,6 +67,7 @@ NetNodeConfig::NetNodeConfig() { allowLocalIp = false; hideMyPort = false; configFolder = Tools::getDefaultDataDirectory(); + testnet = false; } bool NetNodeConfig::init(const boost::program_options::variables_map& vm) diff --git a/src/P2p/NetNodeConfig.h b/src/P2p/NetNodeConfig.h index 458bd338..a65e23d8 100644 --- a/src/P2p/NetNodeConfig.h +++ b/src/P2p/NetNodeConfig.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -57,7 +57,7 @@ private: bool hideMyPort; std::string configFolder; std::string p2pStateFilename; - bool testnet = false; + bool testnet; }; } //namespace nodetool diff --git a/src/P2p/P2pConnectionProxy.cpp b/src/P2p/P2pConnectionProxy.cpp index aa0c2f51..21552ecd 100644 --- a/src/P2p/P2pConnectionProxy.cpp +++ b/src/P2p/P2pConnectionProxy.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/P2p/P2pConnectionProxy.h b/src/P2p/P2pConnectionProxy.h index e710043c..419d6267 100644 --- a/src/P2p/P2pConnectionProxy.h +++ b/src/P2p/P2pConnectionProxy.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/P2p/P2pContext.cpp b/src/P2p/P2pContext.cpp index 38995fdd..9bb2bdc5 100755 --- a/src/P2p/P2pContext.cpp +++ b/src/P2p/P2pContext.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/P2p/P2pContext.h b/src/P2p/P2pContext.h index f1b0e7df..96375bfc 100755 --- a/src/P2p/P2pContext.h +++ b/src/P2p/P2pContext.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/P2p/P2pContextOwner.cpp b/src/P2p/P2pContextOwner.cpp index 828ab285..b89ff989 100644 --- a/src/P2p/P2pContextOwner.cpp +++ b/src/P2p/P2pContextOwner.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/P2p/P2pContextOwner.h b/src/P2p/P2pContextOwner.h index 49dc19f4..58f367f7 100644 --- a/src/P2p/P2pContextOwner.h +++ b/src/P2p/P2pContextOwner.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/P2p/P2pInterfaces.cpp b/src/P2p/P2pInterfaces.cpp index 90afb00b..fe91f166 100644 --- a/src/P2p/P2pInterfaces.cpp +++ b/src/P2p/P2pInterfaces.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/P2p/P2pInterfaces.h b/src/P2p/P2pInterfaces.h index a952067e..170c3e40 100644 --- a/src/P2p/P2pInterfaces.h +++ b/src/P2p/P2pInterfaces.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/P2p/P2pNetworks.h b/src/P2p/P2pNetworks.h index c934c052..90401a03 100644 --- a/src/P2p/P2pNetworks.h +++ b/src/P2p/P2pNetworks.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/P2p/P2pNode.cpp b/src/P2p/P2pNode.cpp index 135bc8b5..b7a0d4e3 100755 --- a/src/P2p/P2pNode.cpp +++ b/src/P2p/P2pNode.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/P2p/P2pNode.h b/src/P2p/P2pNode.h index a5d97fba..2813edc4 100755 --- a/src/P2p/P2pNode.h +++ b/src/P2p/P2pNode.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/P2p/P2pNodeConfig.cpp b/src/P2p/P2pNodeConfig.cpp index b3600f61..19bb1095 100644 --- a/src/P2p/P2pNodeConfig.cpp +++ b/src/P2p/P2pNodeConfig.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/P2p/P2pNodeConfig.h b/src/P2p/P2pNodeConfig.h index 488f3d5c..1bbc74da 100644 --- a/src/P2p/P2pNodeConfig.h +++ b/src/P2p/P2pNodeConfig.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/P2p/P2pProtocolDefinitions.h b/src/P2p/P2pProtocolDefinitions.h index bb43e8c1..5bc807b2 100755 --- a/src/P2p/P2pProtocolDefinitions.h +++ b/src/P2p/P2pProtocolDefinitions.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/P2p/P2pProtocolTypes.h b/src/P2p/P2pProtocolTypes.h index efde1150..7a97602d 100755 --- a/src/P2p/P2pProtocolTypes.h +++ b/src/P2p/P2pProtocolTypes.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/P2p/PeerListManager.cpp b/src/P2p/PeerListManager.cpp index 0261bef0..9403a9b7 100755 --- a/src/P2p/PeerListManager.cpp +++ b/src/P2p/PeerListManager.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/P2p/PeerListManager.h b/src/P2p/PeerListManager.h index 3a8e7032..a77eb8cd 100644 --- a/src/P2p/PeerListManager.h +++ b/src/P2p/PeerListManager.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/PaymentGate/NodeFactory.cpp b/src/PaymentGate/NodeFactory.cpp index 9ab96091..1a3eb8f6 100644 --- a/src/PaymentGate/NodeFactory.cpp +++ b/src/PaymentGate/NodeFactory.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -13,13 +13,13 @@ namespace PaymentService { class NodeRpcStub: public CryptoNote::INode { public: virtual ~NodeRpcStub() {} - virtual bool addObserver(CryptoNote::INodeObserver* observer) { return true; } - virtual bool removeObserver(CryptoNote::INodeObserver* observer) { return true; } + virtual bool addObserver(CryptoNote::INodeObserver* observer) override { return true; } + virtual bool removeObserver(CryptoNote::INodeObserver* observer) override { return true; } - virtual void init(const Callback& callback) { } - virtual bool shutdown() { return true; } + virtual void init(const Callback& callback) override { } + virtual bool shutdown() override { return true; } - virtual size_t getPeerCount() const { return 0; } + virtual size_t getPeerCount() const override { return 0; } virtual uint32_t getLastLocalBlockHeight() const override { return 0; } virtual uint32_t getLastKnownBlockHeight() const override { return 0; } virtual uint32_t getLocalBlockCount() const override { return 0; } @@ -43,7 +43,7 @@ public: }; virtual void getPoolSymmetricDifference(std::vector&& knownPoolTxIds, Crypto::Hash knownBlockId, bool& isBcActual, - std::vector>& newTxs, std::vector& deletedTxIds, const Callback& callback) { + std::vector>& newTxs, std::vector& deletedTxIds, const Callback& callback) override { isBcActual = true; callback(std::error_code()); } diff --git a/src/PaymentGate/NodeFactory.h b/src/PaymentGate/NodeFactory.h index fb09a113..2563ce18 100644 --- a/src/PaymentGate/NodeFactory.h +++ b/src/PaymentGate/NodeFactory.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/PaymentGate/PaymentServiceJsonRpcMessages.cpp b/src/PaymentGate/PaymentServiceJsonRpcMessages.cpp index 4f0d8d19..72f29ef9 100755 --- a/src/PaymentGate/PaymentServiceJsonRpcMessages.cpp +++ b/src/PaymentGate/PaymentServiceJsonRpcMessages.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -7,181 +7,271 @@ namespace PaymentService { -void TransferDestination::serialize(CryptoNote::ISerializer& serializer) { - bool r = serializer(amount, "amount"); - r &= serializer(address, "address"); +void Reset::Request::serialize(CryptoNote::ISerializer& serializer) { + serializer(viewSecretKey, "viewSecretKey"); +} - if (!r) { +void Reset::Response::serialize(CryptoNote::ISerializer& serializer) { +} + +void GetViewKey::Request::serialize(CryptoNote::ISerializer& serializer) { +} + +void GetViewKey::Response::serialize(CryptoNote::ISerializer& serializer) { + serializer(viewSecretKey, "viewSecretKey"); +} + +void GetStatus::Request::serialize(CryptoNote::ISerializer& serializer) { +} + +void GetStatus::Response::serialize(CryptoNote::ISerializer& serializer) { + serializer(blockCount, "blockCount"); + serializer(knownBlockCount, "knownBlockCount"); + serializer(lastBlockHash, "lastBlockHash"); + serializer(peerCount, "peerCount"); +} + +void GetAddresses::Request::serialize(CryptoNote::ISerializer& serializer) { +} + +void GetAddresses::Response::serialize(CryptoNote::ISerializer& serializer) { + serializer(addresses, "addresses"); +} + +void CreateAddress::Request::serialize(CryptoNote::ISerializer& serializer) { + bool hasSecretKey = serializer(spendSecretKey, "spendSecretKey"); + bool hasPublicKey = serializer(spendPublicKey, "spendPublicKey"); + + if (hasSecretKey && hasPublicKey) { + //TODO: replace it with error codes throw RequestSerializationError(); } } -void SendTransactionRequest::serialize(CryptoNote::ISerializer& serializer) { - bool r = serializer(destinations, "destinations"); - r &= serializer(fee, "fee"); - r &= serializer(mixin, "mixin"); - serializer(unlockTime, "unlock_time"); - serializer(paymentId, "payment_id"); - - if (!r) { - throw RequestSerializationError(); - } -} - -void SendTransactionResponse::serialize(CryptoNote::ISerializer& serializer) { - serializer(transactionId, "transaction_id"); -} - -void GetAddressRequest::serialize(CryptoNote::ISerializer& serializer) { - serializer(index, "index"); -} - -void DeleteAddressRequest::serialize(CryptoNote::ISerializer& serializer) { - bool r = serializer(address, "address"); - - if (!r) { - throw RequestSerializationError(); - } -} - -void DeleteAddressResponse::serialize(CryptoNote::ISerializer& serializer) { -} - -void CreateAddressResponse::serialize(CryptoNote::ISerializer& serializer) { +void CreateAddress::Response::serialize(CryptoNote::ISerializer& serializer) { serializer(address, "address"); } -void GetAddressCountResponse::serialize(CryptoNote::ISerializer& serializer) { - serializer(count, "count"); -} - -void GetAddressResponse::serialize(CryptoNote::ISerializer& serializer) { - serializer(address, "address"); -} - -void GetActualBalanceRequest::serialize(CryptoNote::ISerializer& serializer) { - bool r = serializer(address, "address"); - - if (!r) { - throw std::runtime_error("Required parameter is missing"); +void DeleteAddress::Request::serialize(CryptoNote::ISerializer& serializer) { + if (!serializer(address, "address")) { + throw RequestSerializationError(); } } -void GetPendingBalanceRequest::serialize(CryptoNote::ISerializer& serializer) { +void DeleteAddress::Response::serialize(CryptoNote::ISerializer& serializer) { +} + +void GetSpendKeys::Request::serialize(CryptoNote::ISerializer& serializer) { + if (!serializer(address, "address")) { + throw RequestSerializationError(); + } +} + +void GetSpendKeys::Response::serialize(CryptoNote::ISerializer& serializer) { + serializer(spendSecretKey, "spendSecretKey"); + serializer(spendPublicKey, "spendPublicKey"); +} + +void GetBalance::Request::serialize(CryptoNote::ISerializer& serializer) { serializer(address, "address"); } -void GetActualBalanceResponse::serialize(CryptoNote::ISerializer& serializer) { - serializer(actualBalance, "actual_balance"); +void GetBalance::Response::serialize(CryptoNote::ISerializer& serializer) { + serializer(availableBalance, "availableBalance"); + serializer(lockedAmount, "lockedAmount"); } -void GetPendingBalanceResponse::serialize(CryptoNote::ISerializer& serializer) { - serializer(pendingBalance, "pending_balance"); -} - -void GetTransactionsCountResponse::serialize(CryptoNote::ISerializer& serializer) { - serializer(transactionsCount, "transactions_count"); -} - -void GetTransfersCountResponse::serialize(CryptoNote::ISerializer& serializer) { - serializer(transfersCount, "transfers_count"); -} - -void GetTransactionIdByTransferIdRequest::serialize(CryptoNote::ISerializer& serializer) { - bool r = serializer(transferId, "transfer_id"); +void GetBlockHashes::Request::serialize(CryptoNote::ISerializer& serializer) { + bool r = serializer(firstBlockIndex, "firstBlockIndex"); + r &= serializer(blockCount, "blockCount"); if (!r) { throw RequestSerializationError(); } } -void GetTransactionIdByTransferIdResponse::serialize(CryptoNote::ISerializer& serializer) { - serializer(transactionid, "transaction_id"); +void GetBlockHashes::Response::serialize(CryptoNote::ISerializer& serializer) { + serializer(blockHashes, "blockHashes"); } -void GetTransactionRequest::serialize(CryptoNote::ISerializer& serializer) { - bool r = serializer(transactionId, "transaction_id"); +void TransactionHashesInBlockRpcInfo::serialize(CryptoNote::ISerializer& serializer) { + serializer(blockHash, "blockHash"); + serializer(transactionHashes, "transactionHashes"); +} - if (!r) { +void GetTransactionHashes::Request::serialize(CryptoNote::ISerializer& serializer) { + serializer(addresses, "addresses"); + + if (serializer(blockHash, "blockHash") == serializer(firstBlockIndex, "firstBlockIndex")) { throw RequestSerializationError(); } -} -void TransactionRpcInfo::serialize(CryptoNote::ISerializer& serializer) { - serializer(firstTransferId, "first_transfer_id"); - serializer(transferCount, "transfer_count"); - serializer(totalAmount, "total_amount"); - serializer(fee, "fee"); - serializer(hash, "hash"); - serializer(blockHeight, "block_height"); - serializer(timestamp, "timestamp"); - serializer(extra, "extra"); - serializer(transfers, "transfers"); -} - -void GetTransactionResponse::serialize(CryptoNote::ISerializer& serializer) { - serializer(found, "found"); - - if (found) { - serializer(transactionInfo, "transaction_info"); + if (!serializer(blockCount, "blockCount")) { + throw RequestSerializationError(); } + + serializer(paymentId, "paymentId"); } -void ListTransactionsRequest::serialize(CryptoNote::ISerializer& serializer) { - bool r = serializer(startingTransactionId, "starting_transaction_id"); - r &= serializer(maxTransactionCount, "max_transaction_count"); - - if (!r) { - throw std::runtime_error("Required parameter is missing"); - } -} - -void ListTransactionsResponse::serialize(CryptoNote::ISerializer& serializer) { - serializer(transactions, "transactions"); +void GetTransactionHashes::Response::serialize(CryptoNote::ISerializer& serializer) { + serializer(items, "items"); } void TransferRpcInfo::serialize(CryptoNote::ISerializer& serializer) { + serializer(type, "type"); serializer(address, "address"); serializer(amount, "amount"); } -void GetTransferRequest::serialize(CryptoNote::ISerializer& serializer) { - bool r = serializer(transferId, "transfer_id"); - - if (!r) { - throw RequestSerializationError(); - } -} - -void GetTransferResponse::serialize(CryptoNote::ISerializer& serializer) { - serializer(found, "found"); - if (found) { - serializer(transferInfo, "transfer_info"); - } -} - -void GetIncomingPaymentsRequest::serialize(CryptoNote::ISerializer& serializer) { - bool r = serializer(payments, "payments"); - - if (!r) { - throw RequestSerializationError(); - } -} - -void PaymentsById::serialize(CryptoNote::ISerializer& serializer) { - serializer(id, "id"); - serializer(payments, "payments"); -} - -void GetIncomingPaymentsResponse::serialize(CryptoNote::ISerializer& serializer) { - serializer(payments, "payments"); -} - -void PaymentDetails::serialize(CryptoNote::ISerializer& serializer) { - serializer(txHash, "tx_hash"); +void TransactionRpcInfo::serialize(CryptoNote::ISerializer& serializer) { + serializer(state, "state"); + serializer(transactionHash, "transactionHash"); + serializer(blockIndex, "blockIndex"); + serializer(timestamp, "timestamp"); + serializer(isBase, "isBase"); + serializer(unlockTime, "unlockTime"); serializer(amount, "amount"); - serializer(blockHeight, "block_height"); - serializer(unlockTime, "unlock_time"); + serializer(fee, "fee"); + serializer(transfers, "transfers"); + serializer(extra, "extra"); + serializer(paymentId, "paymentId"); +} + +void GetTransaction::Request::serialize(CryptoNote::ISerializer& serializer) { + if (!serializer(transactionHash, "transactionHash")) { + throw RequestSerializationError(); + } +} + +void GetTransaction::Response::serialize(CryptoNote::ISerializer& serializer) { + serializer(transaction, "transaction"); +} + +void TransactionsInBlockRpcInfo::serialize(CryptoNote::ISerializer& serializer) { + serializer(blockHash, "blockHash"); + serializer(transactions, "transactions"); +} + +void GetTransactions::Request::serialize(CryptoNote::ISerializer& serializer) { + serializer(addresses, "addresses"); + + if (serializer(blockHash, "blockHash") == serializer(firstBlockIndex, "firstBlockIndex")) { + throw RequestSerializationError(); + } + + if (!serializer(blockCount, "blockCount")) { + throw RequestSerializationError(); + } + + serializer(paymentId, "paymentId"); +} + +void GetTransactions::Response::serialize(CryptoNote::ISerializer& serializer) { + serializer(items, "items"); +} + +void GetUnconfirmedTransactionHashes::Request::serialize(CryptoNote::ISerializer& serializer) { + serializer(addresses, "addresses"); +} + +void GetUnconfirmedTransactionHashes::Response::serialize(CryptoNote::ISerializer& serializer) { + serializer(transactionHashes, "transactionHashes"); +} + +void WalletRpcOrder::serialize(CryptoNote::ISerializer& serializer) { + bool r = serializer(address, "address"); + r &= serializer(amount, "amount"); + + if (!r) { + throw RequestSerializationError(); + } +} + +void SendTransaction::Request::serialize(CryptoNote::ISerializer& serializer) { + serializer(sourceAddresses, "addresses"); + + if (!serializer(transfers, "transfers")) { + throw RequestSerializationError(); + } + + serializer(changeAddress, "changeAddress"); + + if (!serializer(fee, "fee")) { + throw RequestSerializationError(); + } + + if (!serializer(anonymity, "anonymity")) { + throw RequestSerializationError(); + } + + bool hasExtra = serializer(extra, "extra"); + bool hasPaymentId = serializer(paymentId, "paymentId"); + + if (hasExtra && hasPaymentId) { + throw RequestSerializationError(); + } + + serializer(unlockTime, "unlockTime"); +} + +void SendTransaction::Response::serialize(CryptoNote::ISerializer& serializer) { + serializer(transactionHash, "transactionHash"); +} + +void CreateDelayedTransaction::Request::serialize(CryptoNote::ISerializer& serializer) { + serializer(addresses, "addresses"); + + if (!serializer(transfers, "transfers")) { + throw RequestSerializationError(); + } + + serializer(changeAddress, "changeAddress"); + + if (!serializer(fee, "fee")) { + throw RequestSerializationError(); + } + + if (!serializer(anonymity, "anonymity")) { + throw RequestSerializationError(); + } + + bool hasExtra = serializer(extra, "extra"); + bool hasPaymentId = serializer(paymentId, "paymentId"); + + if (hasExtra && hasPaymentId) { + throw RequestSerializationError(); + } + + serializer(unlockTime, "unlockTime"); +} + +void CreateDelayedTransaction::Response::serialize(CryptoNote::ISerializer& serializer) { + serializer(transactionHash, "transactionHash"); +} + +void GetDelayedTransactionHashes::Request::serialize(CryptoNote::ISerializer& serializer) { +} + +void GetDelayedTransactionHashes::Response::serialize(CryptoNote::ISerializer& serializer) { + serializer(transactionHashes, "transactionHashes"); +} + +void DeleteDelayedTransaction::Request::serialize(CryptoNote::ISerializer& serializer) { + if (!serializer(transactionHash, "transactionHash")) { + throw RequestSerializationError(); + } +} + +void DeleteDelayedTransaction::Response::serialize(CryptoNote::ISerializer& serializer) { +} + +void SendDelayedTransaction::Request::serialize(CryptoNote::ISerializer& serializer) { + if (!serializer(transactionHash, "transactionHash")) { + throw RequestSerializationError(); + } +} + +void SendDelayedTransaction::Response::serialize(CryptoNote::ISerializer& serializer) { } } diff --git a/src/PaymentGate/PaymentServiceJsonRpcMessages.h b/src/PaymentGate/PaymentServiceJsonRpcMessages.h index 10778fb3..ce40272b 100644 --- a/src/PaymentGate/PaymentServiceJsonRpcMessages.h +++ b/src/PaymentGate/PaymentServiceJsonRpcMessages.h @@ -1,129 +1,174 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #pragma once #include +#include #include #include "Serialization/ISerializer.h" namespace PaymentService { +const uint32_t DEFAULT_ANONYMITY_LEVEL = 6; + class RequestSerializationError: public std::exception { public: virtual const char* what() const throw() override { return "Request error"; } }; -struct TransferDestination { - uint64_t amount; - std::string address; +struct Reset { + struct Request { + std::string viewSecretKey; + + void serialize(CryptoNote::ISerializer& serializer); + }; + + struct Response { + void serialize(CryptoNote::ISerializer& serializer); + }; +}; + +struct GetViewKey { + struct Request { + void serialize(CryptoNote::ISerializer& serializer); + }; + + struct Response { + std::string viewSecretKey; + + void serialize(CryptoNote::ISerializer& serializer); + }; +}; + +struct GetStatus { + struct Request { + void serialize(CryptoNote::ISerializer& serializer); + }; + + struct Response { + uint32_t blockCount; + uint32_t knownBlockCount; + std::string lastBlockHash; + uint32_t peerCount; + + void serialize(CryptoNote::ISerializer& serializer); + }; +}; + +struct GetAddresses { + struct Request { + void serialize(CryptoNote::ISerializer& serializer); + }; + + struct Response { + std::vector addresses; + + void serialize(CryptoNote::ISerializer& serializer); + }; +}; + +struct CreateAddress { + struct Request { + std::string spendSecretKey; + std::string spendPublicKey; + + void serialize(CryptoNote::ISerializer& serializer); + }; + + struct Response { + std::string address; + + void serialize(CryptoNote::ISerializer& serializer); + }; +}; + +struct DeleteAddress { + struct Request { + std::string address; + + void serialize(CryptoNote::ISerializer& serializer); + }; + + struct Response { + void serialize(CryptoNote::ISerializer& serializer); + }; +}; + +struct GetSpendKeys { + struct Request { + std::string address; + + void serialize(CryptoNote::ISerializer& serializer); + }; + + struct Response { + std::string spendSecretKey; + std::string spendPublicKey; + + void serialize(CryptoNote::ISerializer& serializer); + }; +}; + +struct GetBalance { + struct Request { + std::string address; + + void serialize(CryptoNote::ISerializer& serializer); + }; + + struct Response { + uint64_t availableBalance; + uint64_t lockedAmount; + + void serialize(CryptoNote::ISerializer& serializer); + }; +}; + +struct GetBlockHashes { + struct Request { + uint32_t firstBlockIndex; + uint32_t blockCount; + + void serialize(CryptoNote::ISerializer& serializer); + }; + + struct Response { + std::vector blockHashes; + + void serialize(CryptoNote::ISerializer& serializer); + }; +}; + +struct TransactionHashesInBlockRpcInfo { + std::string blockHash; + std::vector transactionHashes; void serialize(CryptoNote::ISerializer& serializer); }; -struct SendTransactionRequest { - SendTransactionRequest() : unlockTime(0) {} +struct GetTransactionHashes { + struct Request { + std::vector addresses; + std::string blockHash; + uint32_t firstBlockIndex = std::numeric_limits::max(); + uint32_t blockCount; + std::string paymentId; - std::vector destinations; - uint64_t fee; - uint64_t mixin; - uint64_t unlockTime; - std::string paymentId; + void serialize(CryptoNote::ISerializer& serializer); + }; - void serialize(CryptoNote::ISerializer& serializer); -}; + struct Response { + std::vector items; -struct SendTransactionResponse { - uint64_t transactionId; - void serialize(CryptoNote::ISerializer& serializer); -}; - -struct GetAddressRequest { - GetAddressRequest() : index(0) {} - - size_t index; - void serialize(CryptoNote::ISerializer& serializer); -}; - -struct GetAddressCountResponse { - std::size_t count; - void serialize(CryptoNote::ISerializer& serializer); -}; - -struct DeleteAddressRequest { - std::string address; - void serialize(CryptoNote::ISerializer& serializer); -}; - -struct DeleteAddressResponse { - void serialize(CryptoNote::ISerializer& serializer); -}; - -struct CreateAddressResponse { - std::string address; - void serialize(CryptoNote::ISerializer& serializer); -}; - -struct GetAddressResponse { - std::string address; - void serialize(CryptoNote::ISerializer& serializer); -}; - -struct GetActualBalanceRequest { - std::string address; - void serialize(CryptoNote::ISerializer& serializer); -}; - -struct GetActualBalanceResponse { - uint64_t actualBalance; - - void serialize(CryptoNote::ISerializer& serializer); -}; - -struct GetPendingBalanceRequest { - std::string address; - void serialize(CryptoNote::ISerializer& serializer); -}; - -struct GetPendingBalanceResponse { - uint64_t pendingBalance; - - void serialize(CryptoNote::ISerializer& serializer); -}; - -struct GetTransactionsCountResponse { - uint64_t transactionsCount; - - void serialize(CryptoNote::ISerializer& serializer); -}; - -struct GetTransfersCountResponse { - uint64_t transfersCount; - - void serialize(CryptoNote::ISerializer& serializer); -}; - -struct GetTransactionIdByTransferIdRequest { - uint64_t transferId; - - void serialize(CryptoNote::ISerializer& serializer); -}; - -struct GetTransactionIdByTransferIdResponse { - uint64_t transactionid; - - void serialize(CryptoNote::ISerializer& serializer); -}; - -struct GetTransactionRequest { - uint64_t transactionId; - - void serialize(CryptoNote::ISerializer& serializer); + void serialize(CryptoNote::ISerializer& serializer); + }; }; struct TransferRpcInfo { + uint8_t type; std::string address; int64_t amount; @@ -131,79 +176,157 @@ struct TransferRpcInfo { }; struct TransactionRpcInfo { - uint64_t firstTransferId; - uint64_t transferCount; - int64_t totalAmount; - uint64_t fee; - std::string hash; - uint64_t blockHeight; + uint8_t state; + std::string transactionHash; + uint32_t blockIndex; uint64_t timestamp; - std::string extra; + bool isBase; + uint64_t unlockTime; + int64_t amount; + uint64_t fee; std::vector transfers; + std::string extra; + std::string paymentId; void serialize(CryptoNote::ISerializer& serializer); }; -struct GetTransactionResponse { - bool found; - TransactionRpcInfo transactionInfo; +struct GetTransaction { + struct Request { + std::string transactionHash; - void serialize(CryptoNote::ISerializer& serializer); + void serialize(CryptoNote::ISerializer& serializer); + }; + + struct Response { + TransactionRpcInfo transaction; + + void serialize(CryptoNote::ISerializer& serializer); + }; }; -struct ListTransactionsRequest { - uint32_t startingTransactionId; - uint32_t maxTransactionCount; - - void serialize(CryptoNote::ISerializer& serializer); -}; - -struct ListTransactionsResponse { +struct TransactionsInBlockRpcInfo { + std::string blockHash; std::vector transactions; void serialize(CryptoNote::ISerializer& serializer); }; -struct GetTransferRequest { - uint64_t transferId; +struct GetTransactions { + struct Request { + std::vector addresses; + std::string blockHash; + uint32_t firstBlockIndex = std::numeric_limits::max(); + uint32_t blockCount; + std::string paymentId; - void serialize(CryptoNote::ISerializer& serializer); + void serialize(CryptoNote::ISerializer& serializer); + }; + + struct Response { + std::vector items; + + void serialize(CryptoNote::ISerializer& serializer); + }; }; -struct GetTransferResponse { - bool found; - TransferRpcInfo transferInfo; +struct GetUnconfirmedTransactionHashes { + struct Request { + std::vector addresses; - void serialize(CryptoNote::ISerializer& serializer); + void serialize(CryptoNote::ISerializer& serializer); + }; + + struct Response { + std::vector transactionHashes; + + void serialize(CryptoNote::ISerializer& serializer); + }; }; -struct GetIncomingPaymentsRequest { - std::vector payments; - - void serialize(CryptoNote::ISerializer& serializer); -}; - -struct PaymentDetails -{ - std::string txHash; +struct WalletRpcOrder { + std::string address; uint64_t amount; - uint64_t blockHeight; - uint64_t unlockTime; void serialize(CryptoNote::ISerializer& serializer); }; -struct PaymentsById { - std::string id; - std::vector payments; +struct SendTransaction { + struct Request { + std::vector sourceAddresses; + std::vector transfers; + std::string changeAddress; + uint64_t fee = 0; + uint32_t anonymity = DEFAULT_ANONYMITY_LEVEL; + std::string extra; + std::string paymentId; + uint64_t unlockTime = 0; - void serialize(CryptoNote::ISerializer& serializer); + void serialize(CryptoNote::ISerializer& serializer); + }; + + struct Response { + std::string transactionHash; + + void serialize(CryptoNote::ISerializer& serializer); + }; }; -struct GetIncomingPaymentsResponse { - std::vector payments; +struct CreateDelayedTransaction { + struct Request { + std::vector addresses; + std::vector transfers; + std::string changeAddress; + uint64_t fee = 0; + uint32_t anonymity = DEFAULT_ANONYMITY_LEVEL; + std::string extra; + std::string paymentId; + uint64_t unlockTime = 0; - void serialize(CryptoNote::ISerializer& serializer); + void serialize(CryptoNote::ISerializer& serializer); + }; + + struct Response { + std::string transactionHash; + + void serialize(CryptoNote::ISerializer& serializer); + }; +}; + +struct GetDelayedTransactionHashes { + struct Request { + void serialize(CryptoNote::ISerializer& serializer); + }; + + struct Response { + std::vector transactionHashes; + + void serialize(CryptoNote::ISerializer& serializer); + }; +}; + +struct DeleteDelayedTransaction { + struct Request { + std::string transactionHash; + + void serialize(CryptoNote::ISerializer& serializer); + }; + + struct Response { + void serialize(CryptoNote::ISerializer& serializer); + }; +}; + +struct SendDelayedTransaction { + struct Request { + std::string transactionHash; + + void serialize(CryptoNote::ISerializer& serializer); + }; + + struct Response { + void serialize(CryptoNote::ISerializer& serializer); + }; }; } //namespace PaymentService diff --git a/src/PaymentGate/PaymentServiceJsonRpcServer.cpp b/src/PaymentGate/PaymentServiceJsonRpcServer.cpp index 035b2c86..b1daf646 100755 --- a/src/PaymentGate/PaymentServiceJsonRpcServer.cpp +++ b/src/PaymentGate/PaymentServiceJsonRpcServer.cpp @@ -1,13 +1,14 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "PaymentServiceJsonRpcServer.h" +#include + #include "PaymentServiceJsonRpcMessages.h" #include "WalletService.h" -#include "Common/JsonValue.h" #include "Serialization/JsonInputValueSerializer.h" #include "Serialization/JsonOutputStreamSerializer.h" @@ -18,299 +19,157 @@ PaymentServiceJsonRpcServer::PaymentServiceJsonRpcServer(System::Dispatcher& sys , service(service) , logger(loggerGroup, "PaymentServiceJsonRpcServer") { + handlers.emplace("reset", jsonHandler(std::bind(&PaymentServiceJsonRpcServer::handleReset, this, std::placeholders::_1, std::placeholders::_2))); + handlers.emplace("createAddress", jsonHandler(std::bind(&PaymentServiceJsonRpcServer::handleCreateAddress, this, std::placeholders::_1, std::placeholders::_2))); + handlers.emplace("deleteAddress", jsonHandler(std::bind(&PaymentServiceJsonRpcServer::handleDeleteAddress, this, std::placeholders::_1, std::placeholders::_2))); + handlers.emplace("getSpendKeys", jsonHandler(std::bind(&PaymentServiceJsonRpcServer::handleGetSpendKeys, this, std::placeholders::_1, std::placeholders::_2))); + handlers.emplace("getBalance", jsonHandler(std::bind(&PaymentServiceJsonRpcServer::handleGetBalance, this, std::placeholders::_1, std::placeholders::_2))); + handlers.emplace("getBlockHashes", jsonHandler(std::bind(&PaymentServiceJsonRpcServer::handleGetBlockHashes, this, std::placeholders::_1, std::placeholders::_2))); + handlers.emplace("getTransactionHashes", jsonHandler(std::bind(&PaymentServiceJsonRpcServer::handleGetTransactionHashes, this, std::placeholders::_1, std::placeholders::_2))); + handlers.emplace("getTransactions", jsonHandler(std::bind(&PaymentServiceJsonRpcServer::handleGetTransactions, this, std::placeholders::_1, std::placeholders::_2))); + handlers.emplace("getUnconfirmedTransactionHashes", jsonHandler(std::bind(&PaymentServiceJsonRpcServer::handleGetUnconfirmedTransactionHashes, this, std::placeholders::_1, std::placeholders::_2))); + handlers.emplace("getTransaction", jsonHandler(std::bind(&PaymentServiceJsonRpcServer::handleGetTransaction, this, std::placeholders::_1, std::placeholders::_2))); + handlers.emplace("sendTransaction", jsonHandler(std::bind(&PaymentServiceJsonRpcServer::handleSendTransaction, this, std::placeholders::_1, std::placeholders::_2))); + handlers.emplace("createDelayedTransaction", jsonHandler(std::bind(&PaymentServiceJsonRpcServer::handleCreateDelayedTransaction, this, std::placeholders::_1, std::placeholders::_2))); + handlers.emplace("getDelayedTransactionHashes", jsonHandler(std::bind(&PaymentServiceJsonRpcServer::handleGetDelayedTransactionHashes, this, std::placeholders::_1, std::placeholders::_2))); + handlers.emplace("deleteDelayedTransaction", jsonHandler(std::bind(&PaymentServiceJsonRpcServer::handleDeleteDelayedTransaction, this, std::placeholders::_1, std::placeholders::_2))); + handlers.emplace("sendDelayedTransaction", jsonHandler(std::bind(&PaymentServiceJsonRpcServer::handleSendDelayedTransaction, this, std::placeholders::_1, std::placeholders::_2))); + handlers.emplace("getViewKey", jsonHandler(std::bind(&PaymentServiceJsonRpcServer::handleGetViewKey, this, std::placeholders::_1, std::placeholders::_2))); + handlers.emplace("getStatus", jsonHandler(std::bind(&PaymentServiceJsonRpcServer::handleGetStatus, this, std::placeholders::_1, std::placeholders::_2))); + handlers.emplace("getAddresses", jsonHandler(std::bind(&PaymentServiceJsonRpcServer::handleGetAddresses, this, std::placeholders::_1, std::placeholders::_2))); } void PaymentServiceJsonRpcServer::processJsonRpcRequest(const Common::JsonValue& req, Common::JsonValue& resp) { try { prepareJsonResponse(req, resp); + if (!req.contains("method")) { + logger(Logging::WARNING) << "Field \"method\" is not found in json request: " << req; + makeGenericErrorReponse(resp, "Invalid Request", -3600); + return; + } + + if (!req("method").isString()) { + logger(Logging::WARNING) << "Field \"method\" is not a string type: " << req; + makeGenericErrorReponse(resp, "Invalid Request", -3600); + return; + } + std::string method = req("method").getString(); - CryptoNote::JsonOutputStreamSerializer outputSerializer; - - if (method == "send_transaction") { - SendTransactionRequest sendReq; - SendTransactionResponse sendResp; - - //XXX: refactor it when migrate to different exception types in different subsystems! - try { - CryptoNote::JsonInputValueSerializer inputSerializer(req("params")); - serialize(sendReq, inputSerializer); - } catch (std::exception&) { - makeGenericErrorReponse(resp, "Invalid Request", -32600); - return; - } - - std::error_code ec = service.sendTransaction(sendReq, sendResp); - if (ec) { - makeErrorResponse(ec, resp); - return; - } - - serialize(sendResp, outputSerializer); - } else if (method == "get_address") { - GetAddressRequest getAddrReq; - GetAddressResponse getAddrResp; - - //XXX: refactor it when migrate to different exception types in different subsystems! - try { - CryptoNote::JsonInputValueSerializer inputSerializer(req("params")); - serialize(getAddrReq, inputSerializer); - } catch (std::exception&) { - makeGenericErrorReponse(resp, "Invalid Request", -32600); - return; - } - - std::error_code ec = service.getAddress(getAddrReq.index, getAddrResp.address); - if (ec) { - makeErrorResponse(ec, resp); - return; - } - - serialize(getAddrResp, outputSerializer); - } else if (method == "create_address") { - CreateAddressResponse createAddrResp; - - std::error_code ec = service.createAddress(createAddrResp.address); - if (ec) { - makeErrorResponse(ec, resp); - return; - } - - serialize(createAddrResp, outputSerializer); - } else if (method == "get_address_count") { - GetAddressCountResponse addressCountResp; - - std::error_code ec = service.getAddressCount(addressCountResp.count); - if (ec) { - makeErrorResponse(ec, resp); - return; - } - - serialize(addressCountResp, outputSerializer); - } else if (method == "delete_address") { - DeleteAddressRequest delAddrReq; - DeleteAddressResponse delAddrResp; - - //XXX: refactor it when migrate to different exception types in different subsystems! - try { - CryptoNote::JsonInputValueSerializer inputSerializer(req("params")); - serialize(delAddrReq, inputSerializer); - } catch (std::exception&) { - makeGenericErrorReponse(resp, "Invalid Request", -32600); - return; - } - - std::error_code ec = service.deleteAddress(delAddrReq.address); - if (ec) { - makeErrorResponse(ec, resp); - return; - } - - serialize(delAddrResp, outputSerializer); - } else if (method == "get_actual_balance") { - GetActualBalanceRequest actualReq; - GetActualBalanceResponse actualResp; - - //XXX: refactor it when migrate to different exception types in different subsystems! - try { - CryptoNote::JsonInputValueSerializer inputSerializer(req("params")); - serialize(actualReq, inputSerializer); - } catch (std::exception&) { - makeGenericErrorReponse(resp, "Invalid Request", -32600); - return; - } - - std::error_code ec; - if (actualReq.address == "") { - ec = service.getActualBalance(actualResp.actualBalance); - } else { - ec = service.getActualBalance(actualReq.address, actualResp.actualBalance); - } - - if (ec) { - makeErrorResponse(ec, resp); - return; - } - - serialize(actualResp, outputSerializer); - } else if (method == "get_pending_balance") { - GetPendingBalanceRequest pendingReq; - GetPendingBalanceResponse pendingResp; - - //XXX: refactor it when migrate to different exception types in different subsystems! - try { - CryptoNote::JsonInputValueSerializer inputSerializer(req("params")); - serialize(pendingReq, inputSerializer); - } catch (std::exception&) { - makeGenericErrorReponse(resp, "Invalid Request", -32600); - return; - } - - std::error_code ec; - if (pendingReq.address == "") { - ec = service.getPendingBalance(pendingResp.pendingBalance); - } else { - ec = service.getPendingBalance(pendingReq.address, pendingResp.pendingBalance); - } - - if (ec) { - makeErrorResponse(ec, resp); - return; - } - - serialize(pendingResp, outputSerializer); - } else if (method == "get_transactions_count") { - GetTransactionsCountResponse txResp; - - std::error_code ec = service.getTransactionsCount(txResp.transactionsCount); - if (ec) { - makeErrorResponse(ec, resp); - return; - } - - serialize(txResp, outputSerializer); - } else if (method == "get_transfers_count") { - GetTransfersCountResponse trResp; - - std::error_code ec = service.getTransfersCount(trResp.transfersCount); - if (ec) { - makeErrorResponse(ec, resp); - return; - } - - serialize(trResp, outputSerializer); - } else if (method == "get_transaction_id_by_transfer_id") { - GetTransactionIdByTransferIdRequest getReq; - GetTransactionIdByTransferIdResponse getResp; - - //XXX: refactor it when migrate to different exception types in different subsystems! - try { - CryptoNote::JsonInputValueSerializer inputSerializer(req("params")); - serialize(getReq, inputSerializer); - } catch (std::exception&) { - makeGenericErrorReponse(resp, "Invalid Request", -32600); - return; - } - - size_t txId; - std::error_code ec = service.getTransactionByTransferId(getReq.transferId, txId); - getResp.transactionid = txId; - if (ec) { - makeErrorResponse(ec, resp); - return; - } - - serialize(getResp, outputSerializer); - } else if (method == "get_transaction") { - GetTransactionRequest getReq; - GetTransactionResponse getResp; - - //XXX: refactor it when migrate to different exception types in different subsystems! - try { - CryptoNote::JsonInputValueSerializer inputSerializer(req("params")); - serialize(getReq, inputSerializer); - } catch (std::exception&) { - makeGenericErrorReponse(resp, "Invalid Request", -32600); - return; - } - - std::error_code ec = service.getTransaction(getReq.transactionId, getResp.found, getResp.transactionInfo); - if (ec) { - makeErrorResponse(ec, resp); - return; - } - - serialize(getResp, outputSerializer); - } else if (method == "list_transactions") { - ListTransactionsRequest listReq; - ListTransactionsResponse listResp; - - //XXX: refactor it when migrate to different exception types in different subsystems! - try { - CryptoNote::JsonInputValueSerializer inputSerializer(req("params")); - serialize(listReq, inputSerializer); - } catch (std::exception&) { - makeGenericErrorReponse(resp, "Invalid Request", -32600); - return; - } - - std::error_code ec = service.listTransactions(static_cast(listReq.startingTransactionId), listReq.maxTransactionCount, listResp.transactions); - if (ec) { - makeErrorResponse(ec, resp); - return; - } - - serialize(listResp, outputSerializer); - } else if (method == "get_transfer") { - GetTransferRequest getReq; - GetTransferResponse getResp; - - //XXX: refactor it when migrate to different exception types in different subsystems! - try { - CryptoNote::JsonInputValueSerializer inputSerializer(req("params")); - serialize(getReq, inputSerializer); - } catch (std::exception&) { - makeGenericErrorReponse(resp, "Invalid Request", -32600); - return; - } - - std::error_code ec = service.getTransfer(getReq.transferId, getResp.found, getResp.transferInfo); - if (ec) { - makeErrorResponse(ec, resp); - return; - } - - serialize(getResp, outputSerializer); - } else if (method == "get_incoming_payments") { - GetIncomingPaymentsRequest getReq; - GetIncomingPaymentsResponse getResp; - - //XXX: refactor it when migrate to different exception types in different subsystems! - try { - CryptoNote::JsonInputValueSerializer inputSerializer(req("params")); - serialize(getReq, inputSerializer); - } catch (std::exception&) { - makeGenericErrorReponse(resp, "Invalid Request", -32600); - return; - } - - WalletService::IncomingPayments payments; - std::error_code ec = service.getIncomingPayments(getReq.payments, payments); - if (ec) { - if (ec == make_error_code(std::errc::argument_out_of_domain)) { - makeGenericErrorReponse(resp, "Invalid Request", -32600); - } else { - makeErrorResponse(ec, resp); - } - - return; - } - - for (auto p: payments) { - PaymentsById pbid; - pbid.id = std::move(p.first); - pbid.payments = std::move(p.second); - - getResp.payments.push_back(std::move(pbid)); - } - - serialize(getResp, outputSerializer); - } else { - logger(Logging::DEBUGGING) << "Requested method not found: " << method; + auto it = handlers.find(method); + if (it == handlers.end()) { + logger(Logging::WARNING) << "Requested method not found: " << method; makeMethodNotFoundResponse(resp); return; } - fillJsonResponse(outputSerializer.getValue(), resp); + logger(Logging::DEBUGGING) << method << " request came"; - } catch (RequestSerializationError&) { - logger(Logging::WARNING) << "Wrong request came"; - makeGenericErrorReponse(resp, "Invalid Request", -32600); + Common::JsonValue params(Common::JsonValue::OBJECT); + if (req.contains("params")) { + params = req("params"); + } + + it->second(params, resp); } catch (std::exception& e) { logger(Logging::WARNING) << "Error occurred while processing JsonRpc request: " << e.what(); makeGenericErrorReponse(resp, e.what()); } } +std::error_code PaymentServiceJsonRpcServer::handleReset(const Reset::Request& request, Reset::Response& response) { + if (request.viewSecretKey.empty()) { + return service.resetWallet(); + } else { + return service.replaceWithNewWallet(request.viewSecretKey); + } +} + +std::error_code PaymentServiceJsonRpcServer::handleCreateAddress(const CreateAddress::Request& request, CreateAddress::Response& response) { + if (request.spendSecretKey.empty() && request.spendPublicKey.empty()) { + return service.createAddress(response.address); + } else if (!request.spendSecretKey.empty()) { + return service.createAddress(request.spendSecretKey, response.address); + } else { + return service.createTrackingAddress(request.spendPublicKey, response.address); + } +} + +std::error_code PaymentServiceJsonRpcServer::handleDeleteAddress(const DeleteAddress::Request& request, DeleteAddress::Response& response) { + return service.deleteAddress(request.address); +} + +std::error_code PaymentServiceJsonRpcServer::handleGetSpendKeys(const GetSpendKeys::Request& request, GetSpendKeys::Response& response) { + return service.getSpendkeys(request.address, response.spendPublicKey, response.spendSecretKey); +} + +std::error_code PaymentServiceJsonRpcServer::handleGetBalance(const GetBalance::Request& request, GetBalance::Response& response) { + if (!request.address.empty()) { + return service.getBalance(request.address, response.availableBalance, response.lockedAmount); + } else { + return service.getBalance(response.availableBalance, response.lockedAmount); + } +} + +std::error_code PaymentServiceJsonRpcServer::handleGetBlockHashes(const GetBlockHashes::Request& request, GetBlockHashes::Response& response) { + return service.getBlockHashes(request.firstBlockIndex, request.blockCount, response.blockHashes); +} + +std::error_code PaymentServiceJsonRpcServer::handleGetTransactionHashes(const GetTransactionHashes::Request& request, GetTransactionHashes::Response& response) { + if (!request.blockHash.empty()) { + return service.getTransactionHashes(request.addresses, request.blockHash, request.blockCount, request.paymentId, response.items); + } else { + return service.getTransactionHashes(request.addresses, request.firstBlockIndex, request.blockCount, request.paymentId, response.items); + } +} + +std::error_code PaymentServiceJsonRpcServer::handleGetTransactions(const GetTransactions::Request& request, GetTransactions::Response& response) { + if (!request.blockHash.empty()) { + return service.getTransactions(request.addresses, request.blockHash, request.blockCount, request.paymentId, response.items); + } else { + return service.getTransactions(request.addresses, request.firstBlockIndex, request.blockCount, request.paymentId, response.items); + } +} + +std::error_code PaymentServiceJsonRpcServer::handleGetUnconfirmedTransactionHashes(const GetUnconfirmedTransactionHashes::Request& request, GetUnconfirmedTransactionHashes::Response& response) { + return service.getUnconfirmedTransactionHashes(request.addresses, response.transactionHashes); +} + +std::error_code PaymentServiceJsonRpcServer::handleGetTransaction(const GetTransaction::Request& request, GetTransaction::Response& response) { + return service.getTransaction(request.transactionHash, response.transaction); +} + +std::error_code PaymentServiceJsonRpcServer::handleSendTransaction(const SendTransaction::Request& request, SendTransaction::Response& response) { + return service.sendTransaction(request, response.transactionHash); +} + +std::error_code PaymentServiceJsonRpcServer::handleCreateDelayedTransaction(const CreateDelayedTransaction::Request& request, CreateDelayedTransaction::Response& response) { + return service.createDelayedTransaction(request, response.transactionHash); +} + +std::error_code PaymentServiceJsonRpcServer::handleGetDelayedTransactionHashes(const GetDelayedTransactionHashes::Request& request, GetDelayedTransactionHashes::Response& response) { + return service.getDelayedTransactionHashes(response.transactionHashes); +} + +std::error_code PaymentServiceJsonRpcServer::handleDeleteDelayedTransaction(const DeleteDelayedTransaction::Request& request, DeleteDelayedTransaction::Response& response) { + return service.deleteDelayedTransaction(request.transactionHash); +} + +std::error_code PaymentServiceJsonRpcServer::handleSendDelayedTransaction(const SendDelayedTransaction::Request& request, SendDelayedTransaction::Response& response) { + return service.sendDelayedTransaction(request.transactionHash); +} + +std::error_code PaymentServiceJsonRpcServer::handleGetViewKey(const GetViewKey::Request& request, GetViewKey::Response& response) { + return service.getViewKey(response.viewSecretKey); +} + +std::error_code PaymentServiceJsonRpcServer::handleGetStatus(const GetStatus::Request& request, GetStatus::Response& response) { + return service.getStatus(response.blockCount, response.knownBlockCount, response.lastBlockHash, response.peerCount); +} + +std::error_code PaymentServiceJsonRpcServer::handleGetAddresses(const GetAddresses::Request& request, GetAddresses::Response& response) { + return service.getAddresses(response.addresses); +} + } diff --git a/src/PaymentGate/PaymentServiceJsonRpcServer.h b/src/PaymentGate/PaymentServiceJsonRpcServer.h index f976d464..fc3f5dfb 100644 --- a/src/PaymentGate/PaymentServiceJsonRpcServer.h +++ b/src/PaymentGate/PaymentServiceJsonRpcServer.h @@ -1,10 +1,16 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #pragma once +#include + +#include "Common/JsonValue.h" #include "JsonRpcServer/JsonRpcServer.h" +#include "PaymentServiceJsonRpcMessages.h" +#include "Serialization/JsonInputValueSerializer.h" +#include "Serialization/JsonOutputStreamSerializer.h" namespace PaymentService { @@ -21,6 +27,56 @@ protected: private: WalletService& service; Logging::LoggerRef logger; + + typedef std::function HandlerFunction; + + template + HandlerFunction jsonHandler(RequestHandler handler) { + return [handler] (const Common::JsonValue& jsonRpcParams, Common::JsonValue& jsonResponse) mutable { + RequestType request; + ResponseType response; + + try { + CryptoNote::JsonInputValueSerializer inputSerializer(const_cast(jsonRpcParams)); + serialize(request, inputSerializer); + } catch (std::exception&) { + makeGenericErrorReponse(jsonResponse, "Invalid Request", -32600); + return; + } + + std::error_code ec = handler(request, response); + if (ec) { + makeErrorResponse(ec, jsonResponse); + return; + } + + CryptoNote::JsonOutputStreamSerializer outputSerializer; + serialize(response, outputSerializer); + fillJsonResponse(outputSerializer.getValue(), jsonResponse); + }; + } + + std::unordered_map handlers; + + std::error_code handleReset(const Reset::Request& request, Reset::Response& response); + std::error_code handleCreateAddress(const CreateAddress::Request& request, CreateAddress::Response& response); + std::error_code handleDeleteAddress(const DeleteAddress::Request& request, DeleteAddress::Response& response); + std::error_code handleGetSpendKeys(const GetSpendKeys::Request& request, GetSpendKeys::Response& response); + std::error_code handleGetBalance(const GetBalance::Request& request, GetBalance::Response& response); + std::error_code handleGetBlockHashes(const GetBlockHashes::Request& request, GetBlockHashes::Response& response); + std::error_code handleGetTransactionHashes(const GetTransactionHashes::Request& request, GetTransactionHashes::Response& response); + std::error_code handleGetTransactions(const GetTransactions::Request& request, GetTransactions::Response& response); + std::error_code handleGetUnconfirmedTransactionHashes(const GetUnconfirmedTransactionHashes::Request& request, GetUnconfirmedTransactionHashes::Response& response); + std::error_code handleGetTransaction(const GetTransaction::Request& request, GetTransaction::Response& response); + std::error_code handleSendTransaction(const SendTransaction::Request& request, SendTransaction::Response& response); + std::error_code handleCreateDelayedTransaction(const CreateDelayedTransaction::Request& request, CreateDelayedTransaction::Response& response); + std::error_code handleGetDelayedTransactionHashes(const GetDelayedTransactionHashes::Request& request, GetDelayedTransactionHashes::Response& response); + std::error_code handleDeleteDelayedTransaction(const DeleteDelayedTransaction::Request& request, DeleteDelayedTransaction::Response& response); + std::error_code handleSendDelayedTransaction(const SendDelayedTransaction::Request& request, SendDelayedTransaction::Response& response); + std::error_code handleGetViewKey(const GetViewKey::Request& request, GetViewKey::Response& response); + std::error_code handleGetStatus(const GetStatus::Request& request, GetStatus::Response& response); + std::error_code handleGetAddresses(const GetAddresses::Request& request, GetAddresses::Response& response); + }; -} //namespace PaymentService +}//namespace PaymentService diff --git a/src/PaymentGate/WalletFactory.cpp b/src/PaymentGate/WalletFactory.cpp index 5e22f494..d8306ae4 100644 --- a/src/PaymentGate/WalletFactory.cpp +++ b/src/PaymentGate/WalletFactory.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/PaymentGate/WalletFactory.h b/src/PaymentGate/WalletFactory.h index 5fc7f5e1..8f40b788 100644 --- a/src/PaymentGate/WalletFactory.h +++ b/src/PaymentGate/WalletFactory.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/PaymentGate/WalletService.cpp b/src/PaymentGate/WalletService.cpp index 548d26cd..3998190f 100755 --- a/src/PaymentGate/WalletService.cpp +++ b/src/PaymentGate/WalletService.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -17,27 +17,26 @@ #include "Common/Util.h" #include "crypto/crypto.h" +#include "CryptoNote.h" #include "CryptoNoteCore/CryptoNoteFormatUtils.h" #include "CryptoNoteCore/CryptoNoteBasicImpl.h" #include "CryptoNoteCore/TransactionExtra.h" +#include + #include "PaymentServiceJsonRpcMessages.h" #include "WalletFactory.h" #include "NodeFactory.h" #include "Wallet/LegacyKeysImporter.h" +#include "Wallet/WalletErrors.h" +#include "Wallet/WalletUtils.h" +#include "WalletServiceErrorCategory.h" + +namespace PaymentService { namespace { -void addPaymentIdToExtra(const std::string& paymentId, std::string& extra) { - std::vector extraVector; - if (!CryptoNote::createTxExtraWithPaymentId(paymentId, extraVector)) { - throw std::runtime_error("Couldn't add payment id to extra"); - } - - std::copy(extraVector.begin(), extraVector.end(), std::back_inserter(extra)); -} - bool checkPaymentId(const std::string& paymentId) { if (paymentId.size() != 64) { return false; @@ -60,6 +59,96 @@ bool checkPaymentId(const std::string& paymentId) { }); } +Crypto::Hash parsePaymentId(const std::string& paymentIdStr) { + if (!checkPaymentId(paymentIdStr)) { + throw std::system_error(make_error_code(CryptoNote::error::WalletServiceErrorCode::WRONG_PAYMENT_ID_FORMAT)); + } + + Crypto::Hash paymentId; + bool r = Common::podFromHex(paymentIdStr, paymentId); + assert(r); + + return paymentId; +} + +bool getPaymentIdFromExtra(const std::string& binaryString, Crypto::Hash& paymentId) { + return CryptoNote::getPaymentIdFromTxExtra(Common::asBinaryArray(binaryString), paymentId); +} + +std::string getPaymentIdStringFromExtra(const std::string& binaryString) { + Crypto::Hash paymentId; + + if (!getPaymentIdFromExtra(binaryString, paymentId)) { + return std::string(); + } + + return Common::podToHex(paymentId); +} + +} + +struct TransactionsInBlockInfoFilter { + TransactionsInBlockInfoFilter(const std::vector& addressesVec, const std::string& paymentIdStr) { + addresses.insert(addressesVec.begin(), addressesVec.end()); + + if (!paymentIdStr.empty()) { + paymentId = parsePaymentId(paymentIdStr); + havePaymentId = true; + } else { + havePaymentId = false; + } + } + + bool checkTransaction(const CryptoNote::WalletTransactionWithTransfers& transaction) const { + if (havePaymentId) { + Crypto::Hash transactionPaymentId; + if (!getPaymentIdFromExtra(transaction.transaction.extra, transactionPaymentId)) { + return false; + } + + if (paymentId != transactionPaymentId) { + return false; + } + } + + if (addresses.empty()) { + return true; + } + + bool haveAddress = false; + for (const CryptoNote::WalletTransfer& transfer: transaction.transfers) { + if (addresses.find(transfer.address) != addresses.end()) { + haveAddress = true; + break; + } + } + + return haveAddress; + } + + std::unordered_set addresses; + bool havePaymentId = false; + Crypto::Hash paymentId; +}; + +namespace { + +void addPaymentIdToExtra(const std::string& paymentId, std::string& extra) { + std::vector extraVector; + if (!CryptoNote::createTxExtraWithPaymentId(paymentId, extraVector)) { + throw std::runtime_error("Couldn't add payment id to extra"); + } + + std::copy(extraVector.begin(), extraVector.end(), std::back_inserter(extra)); +} + +void validatePaymentId(const std::string& paymentId, Logging::LoggerRef logger) { + if (!checkPaymentId(paymentId)) { + logger(Logging::WARNING) << "Can't validate payment id: " << paymentId; + throw std::system_error(make_error_code(CryptoNote::error::WalletServiceErrorCode::WRONG_PAYMENT_ID_FORMAT)); + } +} + bool createOutputBinaryFile(const std::string& filename, std::fstream& file) { file.open(filename.c_str(), std::fstream::in | std::fstream::out | std::ofstream::binary); if (file) { @@ -101,11 +190,146 @@ void replaceWalletFiles(const std::string &path, const std::string &tempFilePath Tools::replace_file(tempFilePath, path); } +Crypto::Hash parseHash(const std::string& hashString, Logging::LoggerRef logger) { + Crypto::Hash hash; + + if (!Common::podFromHex(hashString, hash)) { + logger(Logging::WARNING) << "Can't parse hash string " << hashString; + throw std::system_error(make_error_code(CryptoNote::error::WalletServiceErrorCode::WRONG_HASH_FORMAT)); + } + + return hash; } -namespace PaymentService { +std::vector filterTransactions( + const std::vector& blocks, + const TransactionsInBlockInfoFilter& filter) { + + std::vector result; + + for (const auto& block: blocks) { + CryptoNote::TransactionsInBlockInfo item; + item.blockHash = block.blockHash; + + for (const auto& transaction: block.transactions) { + if (transaction.transaction.state != CryptoNote::WalletTransactionState::DELETED && filter.checkTransaction(transaction)) { + item.transactions.push_back(transaction); + } + } + + result.push_back(std::move(item)); + } + + return result; +} + +PaymentService::TransactionRpcInfo convertTransactionWithTransfersToTransactionRpcInfo( + const CryptoNote::WalletTransactionWithTransfers& transactionWithTransfers) { + + PaymentService::TransactionRpcInfo transactionInfo; + + transactionInfo.state = static_cast(transactionWithTransfers.transaction.state); + transactionInfo.transactionHash = Common::podToHex(transactionWithTransfers.transaction.hash); + transactionInfo.blockIndex = transactionWithTransfers.transaction.blockHeight; + transactionInfo.timestamp = transactionWithTransfers.transaction.timestamp; + transactionInfo.isBase = transactionWithTransfers.transaction.isBase; + transactionInfo.unlockTime = transactionWithTransfers.transaction.unlockTime; + transactionInfo.amount = transactionWithTransfers.transaction.totalAmount; + transactionInfo.fee = transactionWithTransfers.transaction.fee; + transactionInfo.extra = Common::toHex(transactionWithTransfers.transaction.extra.data(), transactionWithTransfers.transaction.extra.size()); + transactionInfo.paymentId = getPaymentIdStringFromExtra(transactionWithTransfers.transaction.extra); + + for (const CryptoNote::WalletTransfer& transfer: transactionWithTransfers.transfers) { + PaymentService::TransferRpcInfo rpcTransfer; + rpcTransfer.address = transfer.address; + rpcTransfer.amount = transfer.amount; + rpcTransfer.type = static_cast(transfer.type); + + transactionInfo.transfers.push_back(std::move(rpcTransfer)); + } + + return transactionInfo; +} + +std::vector convertTransactionsInBlockInfoToTransactionsInBlockRpcInfo( + const std::vector& blocks) { + + std::vector rpcBlocks; + rpcBlocks.reserve(blocks.size()); + for (const auto& block: blocks) { + PaymentService::TransactionsInBlockRpcInfo rpcBlock; + rpcBlock.blockHash = Common::podToHex(block.blockHash); + + for (const CryptoNote::WalletTransactionWithTransfers& transactionWithTransfers: block.transactions) { + PaymentService::TransactionRpcInfo transactionInfo = convertTransactionWithTransfersToTransactionRpcInfo(transactionWithTransfers); + rpcBlock.transactions.push_back(std::move(transactionInfo)); + } + + rpcBlocks.push_back(std::move(rpcBlock)); + } + + return rpcBlocks; +} + +std::vector convertTransactionsInBlockInfoToTransactionHashesInBlockRpcInfo( + const std::vector& blocks) { + + std::vector transactionHashes; + transactionHashes.reserve(blocks.size()); + for (const CryptoNote::TransactionsInBlockInfo& block: blocks) { + PaymentService::TransactionHashesInBlockRpcInfo item; + item.blockHash = Common::podToHex(block.blockHash); + + for (const CryptoNote::WalletTransactionWithTransfers& transaction: block.transactions) { + item.transactionHashes.emplace_back(Common::podToHex(transaction.transaction.hash)); + } + + transactionHashes.push_back(std::move(item)); + } + + return transactionHashes; +} + +void validateAddresses(const std::vector& addresses, const CryptoNote::Currency& currency, Logging::LoggerRef logger) { + for (const auto& address: addresses) { + if (!CryptoNote::validateAddress(address, currency)) { + logger(Logging::WARNING) << "Can't validate address " << address; + throw std::system_error(make_error_code(CryptoNote::error::BAD_ADDRESS)); + } + } +} + +std::vector collectDestinationAddresses(const std::vector& orders) { + std::vector result; + + result.reserve(orders.size()); + for (const auto& order: orders) { + result.push_back(order.address); + } + + return result; +} + +std::vector convertWalletRpcOrdersToWalletOrders(const std::vector& orders) { + std::vector result; + result.reserve(orders.size()); + + for (const auto& order: orders) { + result.emplace_back(CryptoNote::WalletOrder {order.address, order.amount}); + } + + return result; +} + +} void createWalletFile(std::fstream& walletFile, const std::string& filename) { + boost::filesystem::path pathToWalletFile(filename); + boost::filesystem::path directory = pathToWalletFile.parent_path(); + if (!directory.empty() && !Tools::directoryExists(directory.string())) { + throw std::runtime_error("Directory does not exist: " + directory.string()); + } + walletFile.open(filename.c_str(), std::fstream::in | std::fstream::out | std::fstream::binary); if (walletFile) { walletFile.close(); @@ -118,12 +342,12 @@ void createWalletFile(std::fstream& walletFile, const std::string& filename) { walletFile.open(filename.c_str(), std::fstream::in | std::fstream::out | std::fstream::binary); } -void saveWallet(CryptoNote::IWallet* wallet, std::fstream& walletFile, bool saveDetailed = true, bool saveCache = true) { - wallet->save(walletFile, saveDetailed, saveCache); +void saveWallet(CryptoNote::IWallet& wallet, std::fstream& walletFile, bool saveDetailed = true, bool saveCache = true) { + wallet.save(walletFile, saveDetailed, saveCache); walletFile.flush(); } -void secureSaveWallet(CryptoNote::IWallet* wallet, const std::string& path, bool saveDetailed = true, bool saveCache = true) { +void secureSaveWallet(CryptoNote::IWallet& wallet, const std::string& path, bool saveDetailed = true, bool saveCache = true) { std::fstream tempFile; std::string tempFilePath = createTemporaryFile(path, tempFile); @@ -158,7 +382,7 @@ void generateNewWallet(const CryptoNote::Currency ¤cy, const WalletConfigu log(Logging::INFO) << "New wallet is generated. Address: " << address; - saveWallet(wallet, walletFile, false, false); + saveWallet(*wallet, walletFile, false, false); log(Logging::INFO) << "Wallet is saved"; } @@ -176,38 +400,39 @@ void importLegacyKeys(const std::string &legacyKeysFile, const WalletConfigurati } WalletService::WalletService(const CryptoNote::Currency& currency, System::Dispatcher& sys, CryptoNote::INode& node, - const WalletConfiguration& conf, Logging::ILogger& logger) : + CryptoNote::IWallet& wallet, const WalletConfiguration& conf, Logging::ILogger& logger) : + currency(currency), + wallet(wallet), + node(node), config(conf), inited(false), logger(logger, "WalletService"), - txIdIndex(boost::get<0>(paymentsCache)), - paymentIdIndex(boost::get<1>(paymentsCache)), dispatcher(sys), + readyEvent(dispatcher), refreshContext(dispatcher) { - wallet.reset(WalletFactory::createWallet(currency, node, dispatcher)); + readyEvent.set(); } WalletService::~WalletService() { - if (wallet) { - if (inited) { - wallet->stop(); - refreshContext.wait(); - wallet->shutdown(); - } + if (inited) { + wallet.stop(); + refreshContext.wait(); + wallet.shutdown(); } } void WalletService::init() { loadWallet(); - loadPaymentsCacheAndTransferIndices(); + loadTransactionIdIndex(); + refreshContext.spawn([this] { refresh(); }); inited = true; } void WalletService::saveWallet() { - PaymentService::secureSaveWallet(wallet.get(), config.walletFile, true, true); + PaymentService::secureSaveWallet(wallet, config.walletFile, true, true); logger(Logging::INFO) << "Wallet is saved"; } @@ -220,335 +445,563 @@ void WalletService::loadWallet() { logger(Logging::INFO) << "Loading wallet"; - wallet->load(inputWalletFile, config.walletPassword); + wallet.load(inputWalletFile, config.walletPassword); logger(Logging::INFO) << "Wallet loading is finished."; } -void WalletService::loadPaymentsCacheAndTransferIndices() { - size_t txCount = wallet->getTransactionCount(); - transfersIndices.resize(1); - transfersIndices[0] = 0; +void WalletService::loadTransactionIdIndex() { + transactionIdIndex.clear(); - logger(Logging::DEBUGGING) << "seeking for payments among " << txCount << " transactions"; - - for (size_t id = 0; id < txCount; ++id) { - CryptoNote::WalletTransaction tx = wallet->getTransaction(id); - - transfersIndices.push_back(transfersIndices[id] + wallet->getTransactionTransferCount(id)); - - if (tx.totalAmount < 0) { - logger(Logging::DEBUGGING) << "tx " << id << " has negative amount"; - continue; - } - - std::vector extraVector(tx.extra.begin(), tx.extra.end()); - - Crypto::Hash paymentId; - if (!CryptoNote::getPaymentIdFromTxExtra(extraVector, paymentId)) { - logger(Logging::DEBUGGING) << "tx " << id << " has no payment id"; - continue; - } - - logger(Logging::DEBUGGING) << "transaction " << id << " has been inserted with payment id " << paymentId; - insertTransaction(id, paymentId, tx.blockHeight != CryptoNote::WALLET_UNCONFIRMED_TRANSACTION_HEIGHT); + for (size_t i = 0; i < wallet.getTransactionCount(); ++i) { + transactionIdIndex.emplace(Common::podToHex(wallet.getTransaction(i).hash), i); } } -std::error_code WalletService::sendTransaction(const SendTransactionRequest& req, SendTransactionResponse& resp) { - assert(wallet); - logger(Logging::DEBUGGING) << "Send transaction request came"; - +std::error_code WalletService::resetWallet() { try { - std::vector transfers; - makeTransfers(req.destinations, transfers); + System::EventLock lk(readyEvent); - std::string extra; - if (!req.paymentId.empty()) { - addPaymentIdToExtra(req.paymentId, extra); + logger(Logging::INFO) << "Reseting wallet"; + + if (!inited) { + logger(Logging::WARNING) << "Reset impossible: Wallet Service is not initialized"; + return make_error_code(CryptoNote::error::NOT_INITIALIZED); } - size_t txId = wallet->transfer(transfers, req.fee, req.mixin, extra, req.unlockTime); - if (txId == CryptoNote::WALLET_INVALID_TRANSACTION_ID) { - logger(Logging::WARNING) << "Unable to send transaction"; - throw std::runtime_error("Error occured while sending transaction"); - } - - resp.transactionId = txId; + reset(); + logger(Logging::INFO) << "Wallet has been reset"; } catch (std::system_error& x) { - logger(Logging::WARNING) << "Error while sending transaction: " << x.what(); + logger(Logging::WARNING) << "Error while reseting wallet: " << x.what(); return x.code(); + } catch (std::exception& x) { + logger(Logging::WARNING) << "Error while reseting wallet: " << x.what(); + return make_error_code(CryptoNote::error::INTERNAL_WALLET_ERROR); } return std::error_code(); } -void WalletService::makeTransfers(const std::vector& destinations, std::vector& transfers) { - transfers.reserve(destinations.size()); - - for (auto dest: destinations) { - transfers.push_back( { dest.address, static_cast(dest.amount) } ); - } -} - -std::error_code WalletService::getAddress(size_t index, std::string& address) { - logger(Logging::DEBUGGING) << "Get address request came"; - +std::error_code WalletService::replaceWithNewWallet(const std::string& viewSecretKeyText) { try { - address = wallet->getAddress(index); + System::EventLock lk(readyEvent); + + Crypto::SecretKey viewSecretKey; + if (!Common::podFromHex(viewSecretKeyText, viewSecretKey)) { + logger(Logging::WARNING) << "Cannot restore view secret key: " << viewSecretKeyText; + return make_error_code(CryptoNote::error::WalletServiceErrorCode::WRONG_KEY_FORMAT); + } + + Crypto::PublicKey viewPublicKey; + if (!Crypto::secret_key_to_public_key(viewSecretKey, viewPublicKey)) { + logger(Logging::WARNING) << "Cannot derive view public key, wrong secret key: " << viewSecretKeyText; + return make_error_code(CryptoNote::error::WalletServiceErrorCode::WRONG_KEY_FORMAT); + } + + replaceWithNewWallet(viewSecretKey); + logger(Logging::INFO) << "The container has been replaced"; } catch (std::system_error& x) { - logger(Logging::WARNING) << "Error while getting address: " << x.what(); + logger(Logging::WARNING) << "Error while replacing container: " << x.what(); return x.code(); + } catch (std::exception& x) { + logger(Logging::WARNING) << "Error while replacing container: " << x.what(); + return make_error_code(CryptoNote::error::INTERNAL_WALLET_ERROR); } return std::error_code(); } -std::error_code WalletService::getAddressCount(std::size_t& count) { - logger(Logging::DEBUGGING) << "Get address count request came"; - count = wallet->getAddressCount(); - return std::error_code(); -} - -std::error_code WalletService::createAddress(std::string& address) { - logger(Logging::DEBUGGING) << "Create address request came"; - +std::error_code WalletService::createAddress(const std::string& spendSecretKeyText, std::string& address) { try { - address = wallet->createAddress(); + System::EventLock lk(readyEvent); + + logger(Logging::DEBUGGING) << "Creating address"; + + Crypto::SecretKey secretKey; + if (!Common::podFromHex(spendSecretKeyText, secretKey)) { + logger(Logging::WARNING) << "Wrong key format: " << spendSecretKeyText; + return make_error_code(CryptoNote::error::WalletServiceErrorCode::WRONG_KEY_FORMAT); + } + + address = wallet.createAddress(secretKey); } catch (std::system_error& x) { logger(Logging::WARNING) << "Error while creating address: " << x.what(); return x.code(); } + logger(Logging::DEBUGGING) << "Created address " << address; + + return std::error_code(); +} + +std::error_code WalletService::createAddress(std::string& address) { + try { + System::EventLock lk(readyEvent); + + logger(Logging::DEBUGGING) << "Creating address"; + + address = wallet.createAddress(); + } catch (std::system_error& x) { + logger(Logging::WARNING) << "Error while creating address: " << x.what(); + return x.code(); + } + + logger(Logging::DEBUGGING) << "Created address " << address; + + return std::error_code(); +} + +std::error_code WalletService::createTrackingAddress(const std::string& spendPublicKeyText, std::string& address) { + try { + System::EventLock lk(readyEvent); + + logger(Logging::DEBUGGING) << "Creating tracking address"; + + Crypto::PublicKey publicKey; + if (!Common::podFromHex(spendPublicKeyText, publicKey)) { + logger(Logging::WARNING) << "Wrong key format: " << spendPublicKeyText; + return make_error_code(CryptoNote::error::WalletServiceErrorCode::WRONG_KEY_FORMAT); + } + + address = wallet.createAddress(publicKey); + } catch (std::system_error& x) { + logger(Logging::WARNING) << "Error while creating tracking address: " << x.what(); + return x.code(); + } + + logger(Logging::DEBUGGING) << "Created address " << address; return std::error_code(); } std::error_code WalletService::deleteAddress(const std::string& address) { - logger(Logging::DEBUGGING) << "Delete address request came"; - try { - wallet->deleteAddress(address); + System::EventLock lk(readyEvent); + + logger(Logging::DEBUGGING) << "Delete address request came"; + wallet.deleteAddress(address); } catch (std::system_error& x) { logger(Logging::WARNING) << "Error while deleting address: " << x.what(); return x.code(); } + logger(Logging::DEBUGGING) << "Address " << address << " successfully deleted"; return std::error_code(); } -std::error_code WalletService::getActualBalance(const std::string& address, uint64_t& actualBalance) { - logger(Logging::DEBUGGING) << "Get actual balance for address: " << address << " request came"; - +std::error_code WalletService::getSpendkeys(const std::string& address, std::string& publicSpendKeyText, std::string& secretSpendKeyText) { try { - actualBalance = wallet->getActualBalance(address); + System::EventLock lk(readyEvent); + + CryptoNote::KeyPair key = wallet.getAddressSpendKey(address); + + publicSpendKeyText = Common::podToHex(key.publicKey); + secretSpendKeyText = Common::podToHex(key.secretKey); + } catch (std::system_error& x) { - logger(Logging::WARNING) << "Unable to get actual balance: " << x.what(); + logger(Logging::WARNING) << "Error while getting spend key: " << x.what(); return x.code(); } return std::error_code(); } -std::error_code WalletService::getPendingBalance(const std::string& address, uint64_t& pendingBalance) { - logger(Logging::DEBUGGING) << "Get pending balance for address: " << address <<" request came"; - +std::error_code WalletService::getBalance(const std::string& address, uint64_t& availableBalance, uint64_t& lockedAmount) { try { - pendingBalance = wallet->getPendingBalance(address); + System::EventLock lk(readyEvent); + logger(Logging::DEBUGGING) << "Getting balance for address " << address; + + availableBalance = wallet.getActualBalance(address); + lockedAmount = wallet.getPendingBalance(address); } catch (std::system_error& x) { - logger(Logging::WARNING) << "Unable to get pending balance: " << x.what(); + logger(Logging::WARNING) << "Error while getting balance: " << x.what(); + return x.code(); + } + + logger(Logging::DEBUGGING) << address << " actual balance: " << availableBalance << ", pending: " << lockedAmount; + return std::error_code(); +} + +std::error_code WalletService::getBalance(uint64_t& availableBalance, uint64_t& lockedAmount) { + try { + System::EventLock lk(readyEvent); + logger(Logging::DEBUGGING) << "Getting wallet balance"; + + availableBalance = wallet.getActualBalance(); + lockedAmount = wallet.getPendingBalance(); + } catch (std::system_error& x) { + logger(Logging::WARNING) << "Error while getting balance: " << x.what(); + return x.code(); + } + + logger(Logging::DEBUGGING) << "Wallet actual balance: " << availableBalance << ", pending: " << lockedAmount; + return std::error_code(); +} + +std::error_code WalletService::getBlockHashes(uint32_t firstBlockIndex, uint32_t blockCount, std::vector& blockHashes) { + try { + System::EventLock lk(readyEvent); + std::vector hashes = wallet.getBlockHashes(firstBlockIndex, blockCount); + + blockHashes.reserve(hashes.size()); + for (const auto& hash: hashes) { + blockHashes.push_back(Common::podToHex(hash)); + } + } catch (std::system_error& x) { + logger(Logging::WARNING) << "Error while getting block hashes: " << x.what(); return x.code(); } return std::error_code(); } -std::error_code WalletService::getActualBalance(uint64_t& actualBalance) { - logger(Logging::DEBUGGING) << "Get actual balance request came"; - +std::error_code WalletService::getViewKey(std::string& viewSecretKey) { try { - actualBalance = wallet->getActualBalance(); + System::EventLock lk(readyEvent); + CryptoNote::KeyPair viewKey = wallet.getViewKey(); + viewSecretKey = Common::podToHex(viewKey.secretKey); } catch (std::system_error& x) { - logger(Logging::WARNING) << "Unable to get actual balance: " << x.what(); + logger(Logging::WARNING) << "Error while getting view key: " << x.what(); return x.code(); } return std::error_code(); } -std::error_code WalletService::getPendingBalance(uint64_t& pendingBalance) { - logger(Logging::DEBUGGING) << "Get pending balance request came"; - +std::error_code WalletService::getTransactionHashes(const std::vector& addresses, const std::string& blockHashString, + uint32_t blockCount, const std::string& paymentId, std::vector& transactionHashes) { try { - pendingBalance = wallet->getPendingBalance(); - } catch (std::system_error& x) { - logger(Logging::WARNING) << "Unable to get pending balance: " << x.what(); - return x.code(); - } + System::EventLock lk(readyEvent); + validateAddresses(addresses, currency, logger); - return std::error_code(); -} - -std::error_code WalletService::getTransactionsCount(uint64_t& txCount) { - logger(Logging::DEBUGGING) << "Get get transactions count request came"; - - try { - txCount = wallet->getTransactionCount(); - } catch (std::system_error& x) { - logger(Logging::WARNING) << "Unable to get transactions count: " << x.what(); - return x.code(); - } - - return std::error_code(); -} - -std::error_code WalletService::getTransfersCount(uint64_t& trCount) { - logger(Logging::DEBUGGING) << "Get transfers count request came"; - trCount = static_cast(transfersIndices.back()); - return std::error_code(); -} - -std::error_code WalletService::getTransactionByTransferId(size_t transferId, size_t& transactionId) { - logger(Logging::DEBUGGING) << "getTransactionByTransferId request came"; - - if (transferId >= transfersIndices.back()) { - logger(Logging::WARNING) << "Transfer ID:" << transferId<<" is out of domain"; - return std::make_error_code(std::errc::argument_out_of_domain); - } - - auto nextTxId = std::upper_bound(transfersIndices.begin(), transfersIndices.end(), transferId); - transactionId = (nextTxId - transfersIndices.begin()) - 1; - - return std::error_code(); -} - -void WalletService::fillTransactionRpcInfo(size_t txId, const CryptoNote::WalletTransaction& tx, TransactionRpcInfo& rpcInfo) { - rpcInfo.firstTransferId = transfersIndices[txId]; - rpcInfo.transferCount = wallet->getTransactionTransferCount(txId); - rpcInfo.totalAmount = tx.totalAmount; - rpcInfo.fee = tx.fee; - rpcInfo.blockHeight = tx.blockHeight; - rpcInfo.timestamp = tx.timestamp; - rpcInfo.extra = Common::toHex(tx.extra.data(), tx.extra.size()); - rpcInfo.hash = Common::podToHex(tx.hash); - for (size_t transferId = 0; transferId < rpcInfo.transferCount; ++transferId) { - auto transfer = wallet->getTransactionTransfer(txId, transferId); - TransferRpcInfo rpcTransfer{ transfer.address, transfer.amount }; - rpcInfo.transfers.push_back(rpcTransfer); - } -} - -std::error_code WalletService::getTransaction(size_t txId, bool& found, TransactionRpcInfo& rpcInfo) { - logger(Logging::DEBUGGING) << "getTransaction request came"; - - found = false; - - try { - if (txId + 1 >= transfersIndices.size()) { - logger(Logging::WARNING) << "Unable to get transaction " << txId << ": argument out of domain."; - return std::make_error_code(std::errc::argument_out_of_domain); + if (!paymentId.empty()) { + validatePaymentId(paymentId, logger); } - auto tx = wallet->getTransaction(txId); + TransactionsInBlockInfoFilter transactionFilter(addresses, paymentId); + Crypto::Hash blockHash = parseHash(blockHashString, logger); - fillTransactionRpcInfo(txId, tx, rpcInfo); - - found = true; + transactionHashes = getRpcTransactionHashes(blockHash, blockCount, transactionFilter); } catch (std::system_error& x) { - logger(Logging::WARNING) << "Unable to get transaction: " << x.what(); + logger(Logging::WARNING) << "Error while getting transactions: " << x.what(); return x.code(); + } catch (std::exception& x) { + logger(Logging::WARNING) << "Error while getting transactions: " << x.what(); + return make_error_code(CryptoNote::error::INTERNAL_WALLET_ERROR); } return std::error_code(); } -std::error_code WalletService::listTransactions(size_t startingTxId, uint32_t maxTxCount, std::vector& txsRpcInfo) { - logger(Logging::DEBUGGING) << "listTransactions request came"; +std::error_code WalletService::getTransactionHashes(const std::vector& addresses, uint32_t firstBlockIndex, + uint32_t blockCount, const std::string& paymentId, std::vector& transactionHashes) { + try { + System::EventLock lk(readyEvent); + validateAddresses(addresses, currency, logger); - if (maxTxCount == 0) { - txsRpcInfo.clear(); - return std::error_code(); + if (!paymentId.empty()) { + validatePaymentId(paymentId, logger); + } + + TransactionsInBlockInfoFilter transactionFilter(addresses, paymentId); + transactionHashes = getRpcTransactionHashes(firstBlockIndex, blockCount, transactionFilter); + + } catch (std::system_error& x) { + logger(Logging::WARNING) << "Error while getting transactions: " << x.what(); + return x.code(); + } catch (std::exception& x) { + logger(Logging::WARNING) << "Error while getting transactions: " << x.what(); + return make_error_code(CryptoNote::error::INTERNAL_WALLET_ERROR); } + return std::error_code(); +} + +std::error_code WalletService::getTransactions(const std::vector& addresses, const std::string& blockHashString, + uint32_t blockCount, const std::string& paymentId, std::vector& transactions) { try { - size_t endTxId; - if (startingTxId > std::numeric_limits::max() - static_cast(maxTxCount)) { - endTxId = static_cast(wallet->getTransactionCount()); + System::EventLock lk(readyEvent); + validateAddresses(addresses, currency, logger); + + if (!paymentId.empty()) { + validatePaymentId(paymentId, logger); + } + + TransactionsInBlockInfoFilter transactionFilter(addresses, paymentId); + + Crypto::Hash blockHash = parseHash(blockHashString, logger); + + transactions = getRpcTransactions(blockHash, blockCount, transactionFilter); + } catch (std::system_error& x) { + logger(Logging::WARNING) << "Error while getting transactions: " << x.what(); + return x.code(); + } catch (std::exception& x) { + logger(Logging::WARNING) << "Error while getting transactions: " << x.what(); + return make_error_code(CryptoNote::error::INTERNAL_WALLET_ERROR); + } + + return std::error_code(); +} + +std::error_code WalletService::getTransactions(const std::vector& addresses, uint32_t firstBlockIndex, + uint32_t blockCount, const std::string& paymentId, std::vector& transactions) { + try { + System::EventLock lk(readyEvent); + validateAddresses(addresses, currency, logger); + + if (!paymentId.empty()) { + validatePaymentId(paymentId, logger); + } + + TransactionsInBlockInfoFilter transactionFilter(addresses, paymentId); + + transactions = getRpcTransactions(firstBlockIndex, blockCount, transactionFilter); + } catch (std::system_error& x) { + logger(Logging::WARNING) << "Error while getting transactions: " << x.what(); + return x.code(); + } catch (std::exception& x) { + logger(Logging::WARNING) << "Error while getting transactions: " << x.what(); + return make_error_code(CryptoNote::error::INTERNAL_WALLET_ERROR); + } + + return std::error_code(); +} + +std::error_code WalletService::getTransaction(const std::string& transactionHash, TransactionRpcInfo& transaction) { + try { + System::EventLock lk(readyEvent); + Crypto::Hash hash = parseHash(transactionHash, logger); + + CryptoNote::WalletTransactionWithTransfers transactionWithTransfers = wallet.getTransaction(hash); + + if (transactionWithTransfers.transaction.state == CryptoNote::WalletTransactionState::DELETED) { + logger(Logging::WARNING) << "Transaction " << transactionHash << " is deleted"; + return make_error_code(CryptoNote::error::OBJECT_NOT_FOUND); + } + + transaction = convertTransactionWithTransfersToTransactionRpcInfo(transactionWithTransfers); + } catch (std::system_error& x) { + logger(Logging::WARNING) << "Error while getting transaction: " << x.what(); + return x.code(); + } catch (std::exception& x) { + logger(Logging::WARNING) << "Error while getting transaction: " << x.what(); + return make_error_code(CryptoNote::error::INTERNAL_WALLET_ERROR); + } + + return std::error_code(); +} + +std::error_code WalletService::getAddresses(std::vector& addresses) { + try { + System::EventLock lk(readyEvent); + + addresses.clear(); + addresses.reserve(wallet.getAddressCount()); + + for (size_t i = 0; i < wallet.getAddressCount(); ++i) { + addresses.push_back(wallet.getAddress(i)); + } + } catch (std::exception& e) { + logger(Logging::WARNING) << "Can't get addresses: " << e.what(); + return make_error_code(CryptoNote::error::INTERNAL_WALLET_ERROR); + } + + return std::error_code(); +} + +std::error_code WalletService::sendTransaction(const SendTransaction::Request& request, std::string& transactionHash) { + try { + System::EventLock lk(readyEvent); + + validateAddresses(request.sourceAddresses, currency, logger); + validateAddresses(collectDestinationAddresses(request.transfers), currency, logger); + if (!request.changeAddress.empty()) { + validateAddresses({ request.changeAddress }, currency, logger); + } + + CryptoNote::TransactionParameters sendParams; + if (!request.paymentId.empty()) { + addPaymentIdToExtra(request.paymentId, sendParams.extra); } else { - endTxId = startingTxId + static_cast(maxTxCount); - endTxId = std::min(endTxId, static_cast(wallet->getTransactionCount())); + sendParams.extra = Common::asString(Common::fromHex(request.extra)); } - txsRpcInfo.resize(endTxId - startingTxId); + sendParams.sourceAddresses = request.sourceAddresses; + sendParams.destinations = convertWalletRpcOrdersToWalletOrders(request.transfers); + sendParams.fee = request.fee; + sendParams.mixIn = request.anonymity; + sendParams.unlockTimestamp = request.unlockTime; + sendParams.changeDestination = request.changeAddress; - for (auto txId = startingTxId; txId < endTxId; ++txId) { - assert(txId < wallet->getTransactionCount()); - auto tx = wallet->getTransaction(txId); - fillTransactionRpcInfo(txId, tx, txsRpcInfo[txId - startingTxId]); - } + size_t transactionId = wallet.transfer(sendParams); + transactionHash = Common::podToHex(wallet.getTransaction(transactionId).hash); + + logger(Logging::DEBUGGING) << "Transaction " << transactionHash << " has been sent"; } catch (std::system_error& x) { - logger(Logging::WARNING) << "Unable to list transaction: " << x.what(); + logger(Logging::WARNING) << "Error while sending transaction: " << x.what(); return x.code(); + } catch (std::exception& x) { + logger(Logging::WARNING) << "Error while sending transaction: " << x.what(); + return make_error_code(CryptoNote::error::INTERNAL_WALLET_ERROR); } return std::error_code(); } -std::error_code WalletService::getTransfer(size_t globalTransferId, bool& found, TransferRpcInfo& rpcInfo) { - logger(Logging::DEBUGGING) << "getTransfer request came"; - found = false; +std::error_code WalletService::createDelayedTransaction(const CreateDelayedTransaction::Request& request, std::string& transactionHash) { try { - size_t txId = (std::upper_bound(transfersIndices.begin(), transfersIndices.end(), globalTransferId) - transfersIndices.begin()) - 1; - size_t fakeTxId = transfersIndices.size() - 1; + System::EventLock lk(readyEvent); - if (txId == fakeTxId) { - return std::error_code(); + validateAddresses(request.addresses, currency, logger); + validateAddresses(collectDestinationAddresses(request.transfers), currency, logger); + if (!request.changeAddress.empty()) { + validateAddresses({ request.changeAddress }, currency, logger); } - auto transferId = globalTransferId - transfersIndices[txId]; - auto transfer = wallet->getTransactionTransfer(txId, transferId); + CryptoNote::TransactionParameters sendParams; + if (!request.paymentId.empty()) { + addPaymentIdToExtra(request.paymentId, sendParams.extra); + } else { + sendParams.extra = Common::asString(Common::fromHex(request.extra)); + } - rpcInfo.address = transfer.address; - rpcInfo.amount = transfer.amount; - found = true; + sendParams.sourceAddresses = request.addresses; + sendParams.destinations = convertWalletRpcOrdersToWalletOrders(request.transfers); + sendParams.fee = request.fee; + sendParams.mixIn = request.anonymity; + sendParams.unlockTimestamp = request.unlockTime; + sendParams.changeDestination = request.changeAddress; + + size_t transactionId = wallet.makeTransaction(sendParams); + transactionHash = Common::podToHex(wallet.getTransaction(transactionId).hash); + + logger(Logging::DEBUGGING) << "Delayed transaction " << transactionHash << " has been created"; } catch (std::system_error& x) { - logger(Logging::WARNING) << "Unable to get transfer: " << x.what(); + logger(Logging::WARNING) << "Error while creating delayed transaction: " << x.what(); return x.code(); + } catch (std::exception& x) { + logger(Logging::WARNING) << "Error while creating delayed transaction: " << x.what(); + return make_error_code(CryptoNote::error::INTERNAL_WALLET_ERROR); } return std::error_code(); } -std::error_code WalletService::getIncomingPayments(const std::vector& payments, IncomingPayments& result) { - logger(Logging::DEBUGGING) << "getIncomingPayments request came"; - +std::error_code WalletService::getDelayedTransactionHashes(std::vector& transactionHashes) { try { - for (const std::string& payment: payments) { + System::EventLock lk(readyEvent); - if (!checkPaymentId(payment)) { - return make_error_code(std::errc::argument_out_of_domain); - } + std::vector transactionIds = wallet.getDelayedTransactionIds(); + transactionHashes.reserve(transactionIds.size()); - std::string paymentString = payment; - std::transform(paymentString.begin(), paymentString.end(), paymentString.begin(), ::tolower); - auto pair = paymentIdIndex.equal_range(paymentString); + for (auto id: transactionIds) { + transactionHashes.emplace_back(Common::podToHex(wallet.getTransaction(id).hash)); + } - for (auto it = pair.first; it != pair.second; ++it) { - auto tx = wallet->getTransaction(it->transactionId); + } catch (std::system_error& x) { + logger(Logging::WARNING) << "Error while getting delayed transaction hashes: " << x.what(); + return x.code(); + } catch (std::exception& x) { + logger(Logging::WARNING) << "Error while getting delayed transaction hashes: " << x.what(); + return make_error_code(CryptoNote::error::INTERNAL_WALLET_ERROR); + } - std::string hashString = Common::podToHex(tx.hash); + return std::error_code(); +} - PaymentDetails details; - details.txHash = std::move(hashString); - details.amount = static_cast(tx.totalAmount); - details.blockHeight = tx.blockHeight; - details.unlockTime = tx.unlockTime; +std::error_code WalletService::deleteDelayedTransaction(const std::string& transactionHash) { + try { + System::EventLock lk(readyEvent); - result[it->paymentId].push_back(std::move(details)); + parseHash(transactionHash, logger); //validate transactionHash parameter + + auto idIt = transactionIdIndex.find(transactionHash); + if (idIt == transactionIdIndex.end()) { + return make_error_code(CryptoNote::error::WalletServiceErrorCode::OBJECT_NOT_FOUND); + } + + size_t transactionId = idIt->second; + wallet.rollbackUncommitedTransaction(transactionId); + + logger(Logging::DEBUGGING) << "Delayed transaction " << transactionHash << " has been canceled"; + } catch (std::system_error& x) { + logger(Logging::WARNING) << "Error while deleting delayed transaction hashes: " << x.what(); + return x.code(); + } catch (std::exception& x) { + logger(Logging::WARNING) << "Error while deleting delayed transaction hashes: " << x.what(); + return make_error_code(CryptoNote::error::INTERNAL_WALLET_ERROR); + } + + return std::error_code(); +} + +std::error_code WalletService::sendDelayedTransaction(const std::string& transactionHash) { + try { + System::EventLock lk(readyEvent); + + parseHash(transactionHash, logger); //validate transactionHash parameter + + auto idIt = transactionIdIndex.find(transactionHash); + if (idIt == transactionIdIndex.end()) { + return make_error_code(CryptoNote::error::WalletServiceErrorCode::OBJECT_NOT_FOUND); + } + + size_t transactionId = idIt->second; + wallet.commitTransaction(transactionId); + + logger(Logging::DEBUGGING) << "Delayed transaction " << transactionHash << " has been sent"; + } catch (std::system_error& x) { + logger(Logging::WARNING) << "Error while sending delayed transaction hashes: " << x.what(); + return x.code(); + } catch (std::exception& x) { + logger(Logging::WARNING) << "Error while sending delayed transaction hashes: " << x.what(); + return make_error_code(CryptoNote::error::INTERNAL_WALLET_ERROR); + } + + return std::error_code(); +} + +std::error_code WalletService::getUnconfirmedTransactionHashes(const std::vector& addresses, std::vector& transactionHashes) { + try { + System::EventLock lk(readyEvent); + + validateAddresses(addresses, currency, logger); + + std::vector transactions = wallet.getUnconfirmedTransactions(); + + TransactionsInBlockInfoFilter transactionFilter(addresses, ""); + + for (const auto& transaction: transactions) { + if (transactionFilter.checkTransaction(transaction)) { + transactionHashes.emplace_back(Common::podToHex(transaction.transaction.hash)); } } } catch (std::system_error& x) { - logger(Logging::WARNING) << "Unable to get payments: " << x.what(); + logger(Logging::WARNING) << "Error while getting unconfirmed transaction hashes: " << x.what(); return x.code(); + } catch (std::exception& x) { + logger(Logging::WARNING) << "Error while getting unconfirmed transaction hashes: " << x.what(); + return make_error_code(CryptoNote::error::INTERNAL_WALLET_ERROR); + } + + return std::error_code(); +} + +std::error_code WalletService::getStatus(uint32_t& blockCount, uint32_t& knownBlockCount, std::string& lastBlockHash, uint32_t& peerCount) { + try { + System::EventLock lk(readyEvent); + + knownBlockCount = node.getKnownBlockCount(); + peerCount = node.getPeerCount(); + blockCount = wallet.getBlockCount(); + + auto lastHashes = wallet.getBlockHashes(blockCount - 1, 1); + lastBlockHash = Common::podToHex(lastHashes.back()); + } catch (std::system_error& x) { + logger(Logging::WARNING) << "Error while getting status: " << x.what(); + return x.code(); + } catch (std::exception& x) { + logger(Logging::WARNING) << "Error while getting status: " << x.what(); + return make_error_code(CryptoNote::error::INTERNAL_WALLET_ERROR); } return std::error_code(); @@ -556,43 +1009,85 @@ std::error_code WalletService::getIncomingPayments(const std::vectorgetEvent(); - if (event.type == CryptoNote::TRANSACTION_CREATED || event.type == CryptoNote::TRANSACTION_UPDATED) { - size_t transactionId; - if (event.type == CryptoNote::TRANSACTION_CREATED) { - transactionId = event.transactionCreated.transactionIndex; - transfersIndices.push_back(transfersIndices[transactionId] + wallet->getTransactionTransferCount(transactionId)); - } else { - transactionId = event.transactionUpdated.transactionIndex; - } - - auto tx = wallet->getTransaction(transactionId); - logger(Logging::DEBUGGING) << "Transaction updated " << transactionId << " extra size: " << tx.extra.size(); - if (tx.totalAmount < 0) { - continue; - } - - std::vector extraVector(tx.extra.begin(), tx.extra.end()); - Crypto::Hash paymentId; - if (!CryptoNote::getPaymentIdFromTxExtra(extraVector, paymentId)) { - logger(Logging::DEBUGGING) << "transaction " << transactionId << " has no payment id"; - continue; - } - - insertTransaction(transactionId, paymentId, tx.blockHeight != CryptoNote::WALLET_UNCONFIRMED_TRANSACTION_HEIGHT); - logger(Logging::DEBUGGING) << "transaction " << transactionId << " has been added to payments cache"; + auto event = wallet.getEvent(); + if (event.type == CryptoNote::TRANSACTION_CREATED) { + size_t transactionId = event.transactionCreated.transactionIndex; + transactionIdIndex.emplace(Common::podToHex(wallet.getTransaction(transactionId).hash), transactionId); } } } catch (std::system_error& e) { - logger(Logging::TRACE) << "refresh is stopped: " << e.what(); + logger(Logging::DEBUGGING) << "refresh is stopped: " << e.what(); } catch (std::exception& e) { logger(Logging::WARNING) << "exception thrown in refresh(): " << e.what(); } } -void WalletService::insertTransaction(size_t id, const Crypto::Hash& paymentIdBin, bool confirmed) { - paymentsCache.insert(PaymentItem{ Common::podToHex(paymentIdBin), id, confirmed}); +void WalletService::reset() { + PaymentService::secureSaveWallet(wallet, config.walletFile, false, false); + wallet.stop(); + wallet.shutdown(); + inited = false; + refreshContext.wait(); + + wallet.start(); + init(); +} + +void WalletService::replaceWithNewWallet(const Crypto::SecretKey& viewSecretKey) { + wallet.stop(); + wallet.shutdown(); + inited = false; + refreshContext.wait(); + + transactionIdIndex.clear(); + + wallet.start(); + wallet.initializeWithViewKey(viewSecretKey, config.walletPassword); + inited = true; +} + +std::vector WalletService::getTransactions(const Crypto::Hash& blockHash, size_t blockCount) const { + std::vector result = wallet.getTransactions(blockHash, blockCount); + if (result.empty()) { + throw std::system_error(make_error_code(CryptoNote::error::WalletServiceErrorCode::OBJECT_NOT_FOUND)); + } + + return result; +} + +std::vector WalletService::getTransactions(uint32_t firstBlockIndex, size_t blockCount) const { + std::vector result = wallet.getTransactions(firstBlockIndex, blockCount); + if (result.empty()) { + throw std::system_error(make_error_code(CryptoNote::error::WalletServiceErrorCode::OBJECT_NOT_FOUND)); + } + + return result; +} + +std::vector WalletService::getRpcTransactionHashes(const Crypto::Hash& blockHash, size_t blockCount, const TransactionsInBlockInfoFilter& filter) const { + std::vector allTransactions = getTransactions(blockHash, blockCount); + std::vector filteredTransactions = filterTransactions(allTransactions, filter); + return convertTransactionsInBlockInfoToTransactionHashesInBlockRpcInfo(filteredTransactions); +} + +std::vector WalletService::getRpcTransactionHashes(uint32_t firstBlockIndex, size_t blockCount, const TransactionsInBlockInfoFilter& filter) const { + std::vector allTransactions = getTransactions(firstBlockIndex, blockCount); + std::vector filteredTransactions = filterTransactions(allTransactions, filter); + return convertTransactionsInBlockInfoToTransactionHashesInBlockRpcInfo(filteredTransactions); +} + +std::vector WalletService::getRpcTransactions(const Crypto::Hash& blockHash, size_t blockCount, const TransactionsInBlockInfoFilter& filter) const { + std::vector allTransactions = getTransactions(blockHash, blockCount); + std::vector filteredTransactions = filterTransactions(allTransactions, filter); + return convertTransactionsInBlockInfoToTransactionsInBlockRpcInfo(filteredTransactions); +} + +std::vector WalletService::getRpcTransactions(uint32_t firstBlockIndex, size_t blockCount, const TransactionsInBlockInfoFilter& filter) const { + std::vector allTransactions = getTransactions(firstBlockIndex, blockCount); + std::vector filteredTransactions = filterTransactions(allTransactions, filter); + return convertTransactionsInBlockInfoToTransactionsInBlockRpcInfo(filteredTransactions); } } //namespace PaymentService diff --git a/src/PaymentGate/WalletService.h b/src/PaymentGate/WalletService.h index 725fb7b3..42602e07 100755 --- a/src/PaymentGate/WalletService.h +++ b/src/PaymentGate/WalletService.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -22,12 +22,6 @@ namespace PaymentService { -struct SendTransactionRequest; -struct SendTransactionResponse; -struct TransferDestination; -struct TransactionRpcInfo; -struct TransferRpcInfo; - struct WalletConfiguration { std::string walletFile; std::string walletPassword; @@ -35,71 +29,74 @@ struct WalletConfiguration { void generateNewWallet(const CryptoNote::Currency ¤cy, const WalletConfiguration &conf, Logging::ILogger &logger, System::Dispatcher& dispatcher); +struct TransactionsInBlockInfoFilter; + class WalletService { public: - typedef std::map > IncomingPayments; - - explicit WalletService(const CryptoNote::Currency& currency, System::Dispatcher& sys, CryptoNote::INode& node, const WalletConfiguration& conf, Logging::ILogger& logger); + WalletService(const CryptoNote::Currency& currency, System::Dispatcher& sys, CryptoNote::INode& node, CryptoNote::IWallet& wallet, const WalletConfiguration& conf, Logging::ILogger& logger); virtual ~WalletService(); void init(); void saveWallet(); - std::error_code sendTransaction(const SendTransactionRequest& req, SendTransactionResponse& resp); - std::error_code getIncomingPayments(const std::vector& payments, IncomingPayments& result); - std::error_code getAddress(size_t index, std::string& address); - std::error_code getAddressCount(size_t& count); + std::error_code resetWallet(); + std::error_code replaceWithNewWallet(const std::string& viewSecretKey); + std::error_code createAddress(const std::string& spendSecretKeyText, std::string& address); std::error_code createAddress(std::string& address); + std::error_code createTrackingAddress(const std::string& spendPublicKeyText, std::string& address); std::error_code deleteAddress(const std::string& address); - std::error_code getActualBalance(const std::string& address, uint64_t& actualBalance); - std::error_code getPendingBalance(const std::string& address, uint64_t& pendingBalance); - std::error_code getActualBalance(uint64_t& actualBalance); - std::error_code getPendingBalance(uint64_t& pendingBalance); - std::error_code getTransactionsCount(uint64_t& txCount); - std::error_code getTransfersCount(uint64_t& trCount); - std::error_code getTransactionByTransferId(size_t transfer, size_t& transaction); - std::error_code getTransaction(size_t txId, bool& found, TransactionRpcInfo& rpcInfo); - std::error_code listTransactions(size_t startingTxId, uint32_t maxTxCount, std::vector& txsRpcInfo); - std::error_code getTransfer(size_t txId, bool& found, TransferRpcInfo& rpcInfo); + std::error_code getSpendkeys(const std::string& address, std::string& publicSpendKeyText, std::string& secretSpendKeyText); + std::error_code getBalance(const std::string& address, uint64_t& availableBalance, uint64_t& lockedAmount); + std::error_code getBalance(uint64_t& availableBalance, uint64_t& lockedAmount); + std::error_code getBlockHashes(uint32_t firstBlockIndex, uint32_t blockCount, std::vector& blockHashes); + std::error_code getViewKey(std::string& viewSecretKey); + std::error_code getTransactionHashes(const std::vector& addresses, const std::string& blockHash, + uint32_t blockCount, const std::string& paymentId, std::vector& transactionHashes); + std::error_code getTransactionHashes(const std::vector& addresses, uint32_t firstBlockIndex, + uint32_t blockCount, const std::string& paymentId, std::vector& transactionHashes); + std::error_code getTransactions(const std::vector& addresses, const std::string& blockHash, + uint32_t blockCount, const std::string& paymentId, std::vector& transactionHashes); + std::error_code getTransactions(const std::vector& addresses, uint32_t firstBlockIndex, + uint32_t blockCount, const std::string& paymentId, std::vector& transactionHashes); + std::error_code getTransaction(const std::string& transactionHash, TransactionRpcInfo& transaction); + std::error_code getAddresses(std::vector& addresses); + std::error_code sendTransaction(const SendTransaction::Request& request, std::string& transactionHash); + std::error_code createDelayedTransaction(const CreateDelayedTransaction::Request& request, std::string& transactionHash); + std::error_code getDelayedTransactionHashes(std::vector& transactionHashes); + std::error_code deleteDelayedTransaction(const std::string& transactionHash); + std::error_code sendDelayedTransaction(const std::string& transactionHash); + std::error_code getUnconfirmedTransactionHashes(const std::vector& addresses, std::vector& transactionHashes); + std::error_code getStatus(uint32_t& blockCount, uint32_t& knownBlockCount, std::string& lastBlockHash, uint32_t& peerCount); private: void refresh(); + void reset(); void loadWallet(); - void loadPaymentsCacheAndTransferIndices(); - void insertTransaction(size_t id, const Crypto::Hash& paymentIdBin, bool confirmed); + void loadTransactionIdIndex(); - void fillTransactionRpcInfo(size_t txId, const CryptoNote::WalletTransaction& tx, TransactionRpcInfo& rpcInfo); - void makeTransfers(const std::vector& destinations, std::vector& transfers); + void replaceWithNewWallet(const Crypto::SecretKey& viewSecretKey); - struct PaymentItem { - std::string paymentId; - size_t transactionId; - bool confirmed; - }; + std::vector getTransactions(const Crypto::Hash& blockHash, size_t blockCount) const; + std::vector getTransactions(uint32_t firstBlockIndex, size_t blockCount) const; - typedef boost::multi_index::hashed_unique TxIdIndex; - typedef boost::multi_index::hashed_non_unique PaymentIndex; - typedef boost::multi_index::multi_index_container< - PaymentItem, - boost::multi_index::indexed_by< - TxIdIndex, - PaymentIndex - > - > PaymentsContainer; + std::vector getRpcTransactionHashes(const Crypto::Hash& blockHash, size_t blockCount, const TransactionsInBlockInfoFilter& filter) const; + std::vector getRpcTransactionHashes(uint32_t firstBlockIndex, size_t blockCount, const TransactionsInBlockInfoFilter& filter) const; - std::unique_ptr wallet; - CryptoNote::INode* node; + std::vector getRpcTransactions(const Crypto::Hash& blockHash, size_t blockCount, const TransactionsInBlockInfoFilter& filter) const; + std::vector getRpcTransactions(uint32_t firstBlockIndex, size_t blockCount, const TransactionsInBlockInfoFilter& filter) const; + + const CryptoNote::Currency& currency; + CryptoNote::IWallet& wallet; + CryptoNote::INode& node; const WalletConfiguration& config; bool inited; Logging::LoggerRef logger; - std::vector transfersIndices; System::Dispatcher& dispatcher; + System::Event readyEvent; System::ContextGroup refreshContext; - PaymentsContainer paymentsCache; - PaymentsContainer::nth_index<0>::type& txIdIndex; - PaymentsContainer::nth_index<1>::type& paymentIdIndex; + std::map transactionIdIndex; }; } //namespace PaymentService diff --git a/src/PaymentGate/WalletServiceErrorCategory.cpp b/src/PaymentGate/WalletServiceErrorCategory.cpp new file mode 100644 index 00000000..80aef5d6 --- /dev/null +++ b/src/PaymentGate/WalletServiceErrorCategory.cpp @@ -0,0 +1,13 @@ +// Copyright (c) 2011-2016 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "WalletServiceErrorCategory.h" + +namespace CryptoNote { +namespace error { + +WalletServiceErrorCategory WalletServiceErrorCategory::INSTANCE; + +} +} diff --git a/src/PaymentGate/WalletServiceErrorCategory.h b/src/PaymentGate/WalletServiceErrorCategory.h new file mode 100644 index 00000000..5858239d --- /dev/null +++ b/src/PaymentGate/WalletServiceErrorCategory.h @@ -0,0 +1,62 @@ +// Copyright (c) 2011-2016 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#pragma once + +#include +#include + +namespace CryptoNote { +namespace error { + +enum class WalletServiceErrorCode { + WRONG_KEY_FORMAT = 1, + WRONG_PAYMENT_ID_FORMAT, + WRONG_HASH_FORMAT, + OBJECT_NOT_FOUND +}; + +// custom category: +class WalletServiceErrorCategory : public std::error_category { +public: + static WalletServiceErrorCategory INSTANCE; + + virtual const char* name() const throw() override { + return "WalletServiceErrorCategory"; + } + + virtual std::error_condition default_error_condition(int ev) const throw() override { + return std::error_condition(ev, *this); + } + + virtual std::string message(int ev) const override { + WalletServiceErrorCode code = static_cast(ev); + + switch (code) { + case WalletServiceErrorCode::WRONG_KEY_FORMAT: return "Wrong key format"; + case WalletServiceErrorCode::WRONG_PAYMENT_ID_FORMAT: return "Wrong payment id format"; + case WalletServiceErrorCode::WRONG_HASH_FORMAT: return "Wrong block id format"; + case WalletServiceErrorCode::OBJECT_NOT_FOUND: return "Requested object not found"; + default: return "Unknown error"; + } + } + +private: + WalletServiceErrorCategory() { + } +}; + +} //namespace error +} //namespace CryptoNote + +inline std::error_code make_error_code(CryptoNote::error::WalletServiceErrorCode e) { + return std::error_code(static_cast(e), CryptoNote::error::WalletServiceErrorCategory::INSTANCE); +} + +namespace std { + +template <> +struct is_error_code_enum: public true_type {}; + +} diff --git a/src/PaymentGateService/ConfigurationManager.cpp b/src/PaymentGateService/ConfigurationManager.cpp index c0a270ae..9ca20e27 100755 --- a/src/PaymentGateService/ConfigurationManager.cpp +++ b/src/PaymentGateService/ConfigurationManager.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -26,13 +26,13 @@ bool ConfigurationManager::init(int argc, char** argv) { po::options_description confGeneralOptions; confGeneralOptions.add(cmdGeneralOptions).add_options() - ("testnet", po::value(), "") - ("local", po::value(), ""); + ("testnet", po::bool_switch(), "") + ("local", po::bool_switch(), ""); cmdGeneralOptions.add_options() ("help,h", "produce this help message and exit") - ("local", "start with local node (remote is default)") - ("testnet", "testnet mode"); + ("local", po::bool_switch(), "start with local node (remote is default)") + ("testnet", po::bool_switch(), "testnet mode"); command_line::add_arg(cmdGeneralOptions, command_line::arg_data_dir, Tools::getDefaultDataDirectory()); command_line::add_arg(confGeneralOptions, command_line::arg_data_dir, Tools::getDefaultDataDirectory()); @@ -77,9 +77,8 @@ bool ConfigurationManager::init(int argc, char** argv) { coreConfig.init(confOptions); remoteNodeConfig.init(confOptions); - if (confOptions.count("local")) { - startInprocess = confOptions["local"].as(); - } + netNodeConfig.setTestnet(confOptions["testnet"].as()); + startInprocess = confOptions["local"].as(); } //command line options should override options from config file @@ -88,7 +87,11 @@ bool ConfigurationManager::init(int argc, char** argv) { coreConfig.init(cmdOptions); remoteNodeConfig.init(cmdOptions); - if (cmdOptions.count("local")) { + if (cmdOptions["testnet"].as()) { + netNodeConfig.setTestnet(true); + } + + if (cmdOptions["local"].as()) { startInprocess = true; } diff --git a/src/PaymentGateService/ConfigurationManager.h b/src/PaymentGateService/ConfigurationManager.h index a276d1ba..d397c782 100755 --- a/src/PaymentGateService/ConfigurationManager.h +++ b/src/PaymentGateService/ConfigurationManager.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/PaymentGateService/PaymentGateService.cpp b/src/PaymentGateService/PaymentGateService.cpp index 637a7b06..5e0ee59e 100755 --- a/src/PaymentGateService/PaymentGateService.cpp +++ b/src/PaymentGateService/PaymentGateService.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -15,6 +15,7 @@ #include "CryptoNoteCore/Core.h" #include "CryptoNoteProtocol/CryptoNoteProtocolHandler.h" #include "P2p/NetNode.h" +#include "PaymentGate/WalletFactory.h" #include #ifdef ERROR @@ -73,8 +74,8 @@ bool PaymentGateService::init(int argc, char** argv) { WalletConfiguration PaymentGateService::getWalletConfig() const { return WalletConfiguration{ - config.gateConfiguration.walletFile, - config.gateConfiguration.walletPassword + config.gateConfiguration.containerFile, + config.gateConfiguration.containerPassword }; } @@ -119,6 +120,16 @@ void PaymentGateService::stop() { } void PaymentGateService::runInProcess(Logging::LoggerRef& log) { + if (!config.coreConfig.configFolderDefaulted) { + if (!Tools::directoryExists(config.coreConfig.configFolder)) { + throw std::runtime_error("Directory does not exist: " + config.coreConfig.configFolder); + } + } else { + if (!Tools::create_directories_if_necessary(config.coreConfig.configFolder)) { + throw std::runtime_error("Can't create directory: " + config.coreConfig.configFolder); + } + } + log(Logging::INFO) << "Starting Payment Gate with local node"; CryptoNote::Currency currency = currencyBuilder.currency(); @@ -146,7 +157,7 @@ void PaymentGateService::runInProcess(Logging::LoggerRef& log) { node->init([&initPromise, &log](std::error_code ec) { if (ec) { - log(Logging::INFO) << "Failed to init node: " << ec.message(); + log(Logging::WARNING, Logging::YELLOW) << "Failed to init node: " << ec.message(); } else { log(Logging::INFO) << "node is inited successfully"; } @@ -193,28 +204,27 @@ void PaymentGateService::runRpcProxy(Logging::LoggerRef& log) { void PaymentGateService::runWalletService(const CryptoNote::Currency& currency, CryptoNote::INode& node) { PaymentService::WalletConfiguration walletConfiguration{ - config.gateConfiguration.walletFile, - config.gateConfiguration.walletPassword + config.gateConfiguration.containerFile, + config.gateConfiguration.containerPassword }; - service = new PaymentService::WalletService(currency, *dispatcher, node, walletConfiguration, logger); + std::unique_ptr wallet (WalletFactory::createWallet(currency, node, *dispatcher)); + + service = new PaymentService::WalletService(currency, *dispatcher, node, *wallet, walletConfiguration, logger); std::unique_ptr serviceGuard(service); try { service->init(); } catch (std::exception& e) { - Logging::LoggerRef(logger, "run")(Logging::ERROR) << "Failed to init walletService reason: " << e.what(); + Logging::LoggerRef(logger, "run")(Logging::ERROR, Logging::BRIGHT_RED) << "Failed to init walletService reason: " << e.what(); return; } if (config.gateConfiguration.printAddresses) { // print addresses and exit - size_t addressCount = 0; - service->getAddressCount(addressCount); - for (size_t i = 0; i < addressCount; ++i) { - std::string address; - if (service->getAddress(i, address) == std::error_code()) { - std::cout << "Address: " << address << std::endl; - } + std::vector addresses; + service->getAddresses(addresses); + for (const auto& address: addresses) { + std::cout << "Address: " << address << std::endl; } } else { PaymentService::PaymentServiceJsonRpcServer rpcServer(*dispatcher, *stopEvent, *service, logger); @@ -223,7 +233,7 @@ void PaymentGateService::runWalletService(const CryptoNote::Currency& currency, try { service->saveWallet(); } catch (std::exception& ex) { - Logging::LoggerRef(logger, "saveWallet")(Logging::WARNING) << "Couldn't save wallet: " << ex.what(); + Logging::LoggerRef(logger, "saveWallet")(Logging::WARNING, Logging::YELLOW) << "Couldn't save container: " << ex.what(); } } } diff --git a/src/PaymentGateService/PaymentGateService.h b/src/PaymentGateService/PaymentGateService.h index 63a589e7..c4daa177 100644 --- a/src/PaymentGateService/PaymentGateService.h +++ b/src/PaymentGateService/PaymentGateService.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/PaymentGateService/PaymentServiceConfiguration.cpp b/src/PaymentGateService/PaymentServiceConfiguration.cpp index 45ce0c73..cd755731 100644 --- a/src/PaymentGateService/PaymentServiceConfiguration.cpp +++ b/src/PaymentGateService/PaymentServiceConfiguration.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -15,7 +15,7 @@ namespace po = boost::program_options; namespace PaymentService { Configuration::Configuration() { - generateNewWallet = false; + generateNewContainer = false; daemonize = false; registerService = false; unregisterService = false; @@ -31,9 +31,9 @@ void Configuration::initOptions(boost::program_options::options_description& des desc.add_options() ("bind-address", po::value()->default_value("0.0.0.0"), "payment service bind address") ("bind-port", po::value()->default_value(8070), "payment service bind port") - ("wallet-file,w", po::value(), "wallet file") - ("wallet-password,p", po::value(), "wallet password") - ("generate-wallet,g", "generate new wallet file and exit") + ("container-file,w", po::value(), "container file") + ("container-password,p", po::value(), "container password") + ("generate-container,g", "generate new container file with one wallet and exit") ("daemon,d", "run as daemon in Unix or as service in Windows") #ifdef _WIN32 ("register-service", "register service and exit (Windows only)") @@ -62,7 +62,7 @@ void Configuration::init(const boost::program_options::variables_map& options) { throw ConfigurationError("It's impossible to use both \"register-service\" and \"unregister-service\" at the same time"); } - if (options.count("testnet") != 0) { + if (options["testnet"].as()) { testnet = true; } @@ -90,16 +90,16 @@ void Configuration::init(const boost::program_options::variables_map& options) { bindPort = options["bind-port"].as(); } - if (options.count("wallet-file") != 0) { - walletFile = options["wallet-file"].as(); + if (options.count("container-file") != 0) { + containerFile = options["container-file"].as(); } - if (options.count("wallet-password") != 0) { - walletPassword = options["wallet-password"].as(); + if (options.count("container-password") != 0) { + containerPassword = options["container-password"].as(); } - if (options.count("generate-wallet") != 0) { - generateNewWallet = true; + if (options.count("generate-container") != 0) { + generateNewContainer = true; } if (options.count("address") != 0) { @@ -107,8 +107,8 @@ void Configuration::init(const boost::program_options::variables_map& options) { } if (!registerService && !unregisterService) { - if (walletFile.empty() || walletPassword.empty()) { - throw ConfigurationError("Both wallet-file and wallet-password parameters are required"); + if (containerFile.empty() || containerPassword.empty()) { + throw ConfigurationError("Both container-file and container-password parameters are required"); } } } diff --git a/src/PaymentGateService/PaymentServiceConfiguration.h b/src/PaymentGateService/PaymentServiceConfiguration.h index 66ad8597..c3ee794f 100644 --- a/src/PaymentGateService/PaymentServiceConfiguration.h +++ b/src/PaymentGateService/PaymentServiceConfiguration.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -26,12 +26,12 @@ struct Configuration { std::string bindAddress; uint16_t bindPort; - std::string walletFile; - std::string walletPassword; + std::string containerFile; + std::string containerPassword; std::string logFile; std::string serverRoot; - bool generateNewWallet; + bool generateNewContainer; bool daemonize; bool registerService; bool unregisterService; diff --git a/src/PaymentGateService/RpcNodeConfiguration.cpp b/src/PaymentGateService/RpcNodeConfiguration.cpp index ad9383d9..80764f4d 100644 --- a/src/PaymentGateService/RpcNodeConfiguration.cpp +++ b/src/PaymentGateService/RpcNodeConfiguration.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/PaymentGateService/RpcNodeConfiguration.h b/src/PaymentGateService/RpcNodeConfiguration.h index 62d0fecb..71f24c06 100644 --- a/src/PaymentGateService/RpcNodeConfiguration.h +++ b/src/PaymentGateService/RpcNodeConfiguration.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/PaymentGateService/main.cpp b/src/PaymentGateService/main.cpp index 45aacfed..a71fe504 100644 --- a/src/PaymentGateService/main.cpp +++ b/src/PaymentGateService/main.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -46,7 +46,7 @@ std::string GetLastErrorMessage(DWORD errorMessageID) void __stdcall serviceHandler(DWORD fdwControl) { if (fdwControl == SERVICE_CONTROL_STOP) { Logging::LoggerRef log(ppg->getLogger(), "serviceHandler"); - log(Logging::INFO) << "Stop signal caught"; + log(Logging::INFO, Logging::BRIGHT_YELLOW) << "Stop signal caught"; SERVICE_STATUS serviceStatus{ SERVICE_WIN32_OWN_PROCESS, SERVICE_STOP_PENDING, 0, NO_ERROR, 0, 0, 0 }; SetServiceStatus(serviceStatusHandle, &serviceStatus); @@ -60,26 +60,26 @@ void __stdcall serviceMain(DWORD dwArgc, char **lpszArgv) { serviceStatusHandle = RegisterServiceCtrlHandler("PaymentGate", serviceHandler); if (serviceStatusHandle == NULL) { - logRef(Logging::FATAL) << "Couldn't make RegisterServiceCtrlHandler call: " << GetLastErrorMessage(GetLastError()); + logRef(Logging::FATAL, Logging::BRIGHT_RED) << "Couldn't make RegisterServiceCtrlHandler call: " << GetLastErrorMessage(GetLastError()); return; } SERVICE_STATUS serviceStatus{ SERVICE_WIN32_OWN_PROCESS, SERVICE_START_PENDING, 0, NO_ERROR, 0, 1, 3000 }; if (SetServiceStatus(serviceStatusHandle, &serviceStatus) != TRUE) { - logRef(Logging::FATAL) << "Couldn't make SetServiceStatus call: " << GetLastErrorMessage(GetLastError()); + logRef(Logging::FATAL, Logging::BRIGHT_RED) << "Couldn't make SetServiceStatus call: " << GetLastErrorMessage(GetLastError()); return; } serviceStatus = { SERVICE_WIN32_OWN_PROCESS, SERVICE_RUNNING, SERVICE_ACCEPT_STOP, NO_ERROR, 0, 0, 0 }; if (SetServiceStatus(serviceStatusHandle, &serviceStatus) != TRUE) { - logRef(Logging::FATAL) << "Couldn't make SetServiceStatus call: " << GetLastErrorMessage(GetLastError()); + logRef(Logging::FATAL, Logging::BRIGHT_RED) << "Couldn't make SetServiceStatus call: " << GetLastErrorMessage(GetLastError()); return; } try { ppg->run(); } catch (std::exception& ex) { - logRef(Logging::FATAL) << "Error occured: " << ex.what(); + logRef(Logging::FATAL, Logging::BRIGHT_RED) << "Error occurred: " << ex.what(); } serviceStatus = { SERVICE_WIN32_OWN_PROCESS, SERVICE_STOPPED, 0, NO_ERROR, 0, 0, 0 }; @@ -125,10 +125,14 @@ int runDaemon() { { NULL, NULL } }; + Logging::LoggerRef logRef(ppg->getLogger(), "RunService"); + if (StartServiceCtrlDispatcher(serviceTable) != TRUE) { + logRef(Logging::FATAL, Logging::BRIGHT_RED) << "Couldn't start service: " << GetLastErrorMessage(GetLastError()); return 1; } + logRef(Logging::INFO) << "Service stopped"; return 0; #else @@ -138,7 +142,7 @@ int runDaemon() { //parent return 0; } else if (daemonResult < 0) { - //error occured + //error occurred return 1; } @@ -161,7 +165,7 @@ int registerService() { for (;;) { if (GetModuleFileName(NULL, pathBuff, ARRAYSIZE(pathBuff)) == 0) { - logRef(Logging::FATAL) << "GetModuleFileName failed with error: " << GetLastErrorMessage(GetLastError()); + logRef(Logging::FATAL, Logging::BRIGHT_RED) << "GetModuleFileName failed with error: " << GetLastErrorMessage(GetLastError()); ret = 1; break; } @@ -173,7 +177,7 @@ int registerService() { scManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE); if (scManager == NULL) { - logRef(Logging::FATAL) << "OpenSCManager failed with error: " << GetLastErrorMessage(GetLastError()); + logRef(Logging::FATAL, Logging::BRIGHT_RED) << "OpenSCManager failed with error: " << GetLastErrorMessage(GetLastError()); ret = 1; break; } @@ -182,7 +186,7 @@ int registerService() { SERVICE_ERROR_NORMAL, modulePath.c_str(), NULL, NULL, NULL, NULL, NULL); if (scService == NULL) { - logRef(Logging::FATAL) << "CreateService failed with error: " << GetLastErrorMessage(GetLastError()); + logRef(Logging::FATAL, Logging::BRIGHT_RED) << "CreateService failed with error: " << GetLastErrorMessage(GetLastError()); ret = 1; break; } @@ -218,14 +222,14 @@ int unregisterService() { for (;;) { scManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); if (scManager == NULL) { - logRef(Logging::FATAL) << "OpenSCManager failed with error: " << GetLastErrorMessage(GetLastError()); + logRef(Logging::FATAL, Logging::BRIGHT_RED) << "OpenSCManager failed with error: " << GetLastErrorMessage(GetLastError()); ret = 1; break; } scService = OpenService(scManager, SERVICE_NAME, SERVICE_STOP | SERVICE_QUERY_STATUS | DELETE); if (scService == NULL) { - logRef(Logging::FATAL) << "OpenService failed with error: " << GetLastErrorMessage(GetLastError()); + logRef(Logging::FATAL, Logging::BRIGHT_RED) << "OpenService failed with error: " << GetLastErrorMessage(GetLastError()); ret = 1; break; } @@ -247,12 +251,12 @@ int unregisterService() { if (ssSvcStatus.dwCurrentState == SERVICE_STOPPED) { logRef(Logging::INFO) << SERVICE_NAME << " is stopped"; } else { - logRef(Logging::FATAL) << SERVICE_NAME << " failed to stop" << std::endl; + logRef(Logging::FATAL, Logging::BRIGHT_RED) << SERVICE_NAME << " failed to stop" << std::endl; } } if (!DeleteService(scService)) { - logRef(Logging::FATAL) << "DeleteService failed with error: " << GetLastErrorMessage(GetLastError()); + logRef(Logging::FATAL, Logging::BRIGHT_RED) << "DeleteService failed with error: " << GetLastErrorMessage(GetLastError()); ret = 1; break; } @@ -288,7 +292,7 @@ int main(int argc, char** argv) { const auto& config = pg.getConfig(); - if (config.gateConfiguration.generateNewWallet) { + if (config.gateConfiguration.generateNewContainer) { System::Dispatcher d; generateNewWallet(pg.getCurrency(), pg.getWalletConfig(), pg.getLogger(), d); return 0; diff --git a/src/Platform/Linux/System/Dispatcher.cpp b/src/Platform/Linux/System/Dispatcher.cpp index 0adb985c..1da9365d 100644 --- a/src/Platform/Linux/System/Dispatcher.cpp +++ b/src/Platform/Linux/System/Dispatcher.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/Linux/System/Dispatcher.h b/src/Platform/Linux/System/Dispatcher.h index 7b9752ac..7604e9fa 100644 --- a/src/Platform/Linux/System/Dispatcher.h +++ b/src/Platform/Linux/System/Dispatcher.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/Linux/System/ErrorMessage.cpp b/src/Platform/Linux/System/ErrorMessage.cpp index b699ae3e..eb81609f 100644 --- a/src/Platform/Linux/System/ErrorMessage.cpp +++ b/src/Platform/Linux/System/ErrorMessage.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/Linux/System/ErrorMessage.h b/src/Platform/Linux/System/ErrorMessage.h index 945624cf..2d7cecb0 100644 --- a/src/Platform/Linux/System/ErrorMessage.h +++ b/src/Platform/Linux/System/ErrorMessage.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/Linux/System/Future.h b/src/Platform/Linux/System/Future.h index ec4c4ba6..ebe47722 100644 --- a/src/Platform/Linux/System/Future.h +++ b/src/Platform/Linux/System/Future.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/Linux/System/Ipv4Resolver.cpp b/src/Platform/Linux/System/Ipv4Resolver.cpp index 61c765ea..92aad69e 100755 --- a/src/Platform/Linux/System/Ipv4Resolver.cpp +++ b/src/Platform/Linux/System/Ipv4Resolver.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/Linux/System/Ipv4Resolver.h b/src/Platform/Linux/System/Ipv4Resolver.h index fb97b140..b662e6aa 100644 --- a/src/Platform/Linux/System/Ipv4Resolver.h +++ b/src/Platform/Linux/System/Ipv4Resolver.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/Linux/System/TcpConnection.cpp b/src/Platform/Linux/System/TcpConnection.cpp index d6bc9a8f..7eff4b4a 100644 --- a/src/Platform/Linux/System/TcpConnection.cpp +++ b/src/Platform/Linux/System/TcpConnection.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/Linux/System/TcpConnection.h b/src/Platform/Linux/System/TcpConnection.h index 79641c43..3ef3621b 100644 --- a/src/Platform/Linux/System/TcpConnection.h +++ b/src/Platform/Linux/System/TcpConnection.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/Linux/System/TcpConnector.cpp b/src/Platform/Linux/System/TcpConnector.cpp index d515892a..1696e0ec 100644 --- a/src/Platform/Linux/System/TcpConnector.cpp +++ b/src/Platform/Linux/System/TcpConnector.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/Linux/System/TcpConnector.h b/src/Platform/Linux/System/TcpConnector.h index fa31f68c..a9947480 100644 --- a/src/Platform/Linux/System/TcpConnector.h +++ b/src/Platform/Linux/System/TcpConnector.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/Linux/System/TcpListener.cpp b/src/Platform/Linux/System/TcpListener.cpp index 2c28a108..4f6d7f50 100644 --- a/src/Platform/Linux/System/TcpListener.cpp +++ b/src/Platform/Linux/System/TcpListener.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/Linux/System/TcpListener.h b/src/Platform/Linux/System/TcpListener.h index ccfa18e2..9981ceab 100644 --- a/src/Platform/Linux/System/TcpListener.h +++ b/src/Platform/Linux/System/TcpListener.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/Linux/System/Timer.cpp b/src/Platform/Linux/System/Timer.cpp index 4535521a..efa92b93 100644 --- a/src/Platform/Linux/System/Timer.cpp +++ b/src/Platform/Linux/System/Timer.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/Linux/System/Timer.h b/src/Platform/Linux/System/Timer.h index 040a993c..13e77d23 100644 --- a/src/Platform/Linux/System/Timer.h +++ b/src/Platform/Linux/System/Timer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/OSX/System/Context.c b/src/Platform/OSX/System/Context.c index 95b4b87b..8838818c 100644 --- a/src/Platform/OSX/System/Context.c +++ b/src/Platform/OSX/System/Context.c @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/OSX/System/Context.h b/src/Platform/OSX/System/Context.h index b80472e5..b94bdbae 100755 --- a/src/Platform/OSX/System/Context.h +++ b/src/Platform/OSX/System/Context.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/OSX/System/Dispatcher.cpp b/src/Platform/OSX/System/Dispatcher.cpp index 06f6a5b0..fec11f3f 100644 --- a/src/Platform/OSX/System/Dispatcher.cpp +++ b/src/Platform/OSX/System/Dispatcher.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/OSX/System/Dispatcher.h b/src/Platform/OSX/System/Dispatcher.h index a985594d..096ea542 100644 --- a/src/Platform/OSX/System/Dispatcher.h +++ b/src/Platform/OSX/System/Dispatcher.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/OSX/System/ErrorMessage.cpp b/src/Platform/OSX/System/ErrorMessage.cpp index b699ae3e..eb81609f 100644 --- a/src/Platform/OSX/System/ErrorMessage.cpp +++ b/src/Platform/OSX/System/ErrorMessage.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/OSX/System/ErrorMessage.h b/src/Platform/OSX/System/ErrorMessage.h index 945624cf..2d7cecb0 100644 --- a/src/Platform/OSX/System/ErrorMessage.h +++ b/src/Platform/OSX/System/ErrorMessage.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/OSX/System/Future.h b/src/Platform/OSX/System/Future.h index 53a3af3b..20a23494 100644 --- a/src/Platform/OSX/System/Future.h +++ b/src/Platform/OSX/System/Future.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/OSX/System/Ipv4Resolver.cpp b/src/Platform/OSX/System/Ipv4Resolver.cpp index 61c765ea..92aad69e 100755 --- a/src/Platform/OSX/System/Ipv4Resolver.cpp +++ b/src/Platform/OSX/System/Ipv4Resolver.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/OSX/System/Ipv4Resolver.h b/src/Platform/OSX/System/Ipv4Resolver.h index fb97b140..b662e6aa 100644 --- a/src/Platform/OSX/System/Ipv4Resolver.h +++ b/src/Platform/OSX/System/Ipv4Resolver.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/OSX/System/TcpConnection.cpp b/src/Platform/OSX/System/TcpConnection.cpp index bccf13dd..bb8f2b01 100644 --- a/src/Platform/OSX/System/TcpConnection.cpp +++ b/src/Platform/OSX/System/TcpConnection.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/OSX/System/TcpConnection.h b/src/Platform/OSX/System/TcpConnection.h index 130c3f28..bedd7ced 100644 --- a/src/Platform/OSX/System/TcpConnection.h +++ b/src/Platform/OSX/System/TcpConnection.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/OSX/System/TcpConnector.cpp b/src/Platform/OSX/System/TcpConnector.cpp index 4bc40d86..ea4bab71 100644 --- a/src/Platform/OSX/System/TcpConnector.cpp +++ b/src/Platform/OSX/System/TcpConnector.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/OSX/System/TcpConnector.h b/src/Platform/OSX/System/TcpConnector.h index fa31f68c..a9947480 100644 --- a/src/Platform/OSX/System/TcpConnector.h +++ b/src/Platform/OSX/System/TcpConnector.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/OSX/System/TcpListener.cpp b/src/Platform/OSX/System/TcpListener.cpp index ce4a3db1..9f097645 100644 --- a/src/Platform/OSX/System/TcpListener.cpp +++ b/src/Platform/OSX/System/TcpListener.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/OSX/System/TcpListener.h b/src/Platform/OSX/System/TcpListener.h index f59f121d..f67e3d36 100644 --- a/src/Platform/OSX/System/TcpListener.h +++ b/src/Platform/OSX/System/TcpListener.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/OSX/System/Timer.cpp b/src/Platform/OSX/System/Timer.cpp index 90651a59..916cf980 100644 --- a/src/Platform/OSX/System/Timer.cpp +++ b/src/Platform/OSX/System/Timer.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/OSX/System/Timer.h b/src/Platform/OSX/System/Timer.h index d696a280..f8bda6f1 100644 --- a/src/Platform/OSX/System/Timer.h +++ b/src/Platform/OSX/System/Timer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/Windows/System/Dispatcher.cpp b/src/Platform/Windows/System/Dispatcher.cpp index 4db5556d..12434608 100644 --- a/src/Platform/Windows/System/Dispatcher.cpp +++ b/src/Platform/Windows/System/Dispatcher.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/Windows/System/Dispatcher.h b/src/Platform/Windows/System/Dispatcher.h index c9c6e1b1..37b74005 100644 --- a/src/Platform/Windows/System/Dispatcher.h +++ b/src/Platform/Windows/System/Dispatcher.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/Windows/System/ErrorMessage.cpp b/src/Platform/Windows/System/ErrorMessage.cpp index f340d234..8d98ccdb 100755 --- a/src/Platform/Windows/System/ErrorMessage.cpp +++ b/src/Platform/Windows/System/ErrorMessage.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/Windows/System/ErrorMessage.h b/src/Platform/Windows/System/ErrorMessage.h index de09e27d..cb5b32d8 100644 --- a/src/Platform/Windows/System/ErrorMessage.h +++ b/src/Platform/Windows/System/ErrorMessage.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/Windows/System/Future.h b/src/Platform/Windows/System/Future.h index 4ac7a90d..6edb652c 100644 --- a/src/Platform/Windows/System/Future.h +++ b/src/Platform/Windows/System/Future.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/Windows/System/Ipv4Resolver.cpp b/src/Platform/Windows/System/Ipv4Resolver.cpp index 0c18e223..2a0e2bbf 100755 --- a/src/Platform/Windows/System/Ipv4Resolver.cpp +++ b/src/Platform/Windows/System/Ipv4Resolver.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/Windows/System/Ipv4Resolver.h b/src/Platform/Windows/System/Ipv4Resolver.h index 4be2a5f8..84ba94a0 100755 --- a/src/Platform/Windows/System/Ipv4Resolver.h +++ b/src/Platform/Windows/System/Ipv4Resolver.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/Windows/System/TcpConnection.cpp b/src/Platform/Windows/System/TcpConnection.cpp index 16328a51..3526856e 100644 --- a/src/Platform/Windows/System/TcpConnection.cpp +++ b/src/Platform/Windows/System/TcpConnection.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/Windows/System/TcpConnection.h b/src/Platform/Windows/System/TcpConnection.h index 4fb01492..0a0c1c28 100644 --- a/src/Platform/Windows/System/TcpConnection.h +++ b/src/Platform/Windows/System/TcpConnection.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/Windows/System/TcpConnector.cpp b/src/Platform/Windows/System/TcpConnector.cpp index c9648c6b..a4187609 100644 --- a/src/Platform/Windows/System/TcpConnector.cpp +++ b/src/Platform/Windows/System/TcpConnector.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/Windows/System/TcpConnector.h b/src/Platform/Windows/System/TcpConnector.h index 4bedbd9f..ec6220d5 100644 --- a/src/Platform/Windows/System/TcpConnector.h +++ b/src/Platform/Windows/System/TcpConnector.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/Windows/System/TcpListener.cpp b/src/Platform/Windows/System/TcpListener.cpp index afa31aa2..997bad25 100644 --- a/src/Platform/Windows/System/TcpListener.cpp +++ b/src/Platform/Windows/System/TcpListener.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/Windows/System/TcpListener.h b/src/Platform/Windows/System/TcpListener.h index cacae067..dc516761 100644 --- a/src/Platform/Windows/System/TcpListener.h +++ b/src/Platform/Windows/System/TcpListener.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/Windows/System/Timer.cpp b/src/Platform/Windows/System/Timer.cpp index 9346411c..be2aaa90 100644 --- a/src/Platform/Windows/System/Timer.cpp +++ b/src/Platform/Windows/System/Timer.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/Windows/System/Timer.h b/src/Platform/Windows/System/Timer.h index f27d9032..a9131b72 100644 --- a/src/Platform/Windows/System/Timer.h +++ b/src/Platform/Windows/System/Timer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/mingw/alloca.h b/src/Platform/mingw/alloca.h index 011dfb0c..5c48d295 100644 --- a/src/Platform/mingw/alloca.h +++ b/src/Platform/mingw/alloca.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/msc/alloca.h b/src/Platform/msc/alloca.h index 29f0f7f6..46871cf8 100644 --- a/src/Platform/msc/alloca.h +++ b/src/Platform/msc/alloca.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/msc/stdbool.h b/src/Platform/msc/stdbool.h index cf698000..e6bd3ae4 100644 --- a/src/Platform/msc/stdbool.h +++ b/src/Platform/msc/stdbool.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Platform/msc/sys/param.h b/src/Platform/msc/sys/param.h index 2a1e34dc..e7c0c48a 100644 --- a/src/Platform/msc/sys/param.h +++ b/src/Platform/msc/sys/param.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Rpc/CoreRpcServerCommandsDefinitions.h b/src/Rpc/CoreRpcServerCommandsDefinitions.h index 814675cc..0c978cef 100755 --- a/src/Rpc/CoreRpcServerCommandsDefinitions.h +++ b/src/Rpc/CoreRpcServerCommandsDefinitions.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -264,6 +264,7 @@ struct COMMAND_RPC_GET_INFO { uint64_t incoming_connections_count; uint64_t white_peerlist_size; uint64_t grey_peerlist_size; + uint32_t last_known_block_index; void serialize(ISerializer &s) { KV_MEMBER(status) @@ -276,6 +277,7 @@ struct COMMAND_RPC_GET_INFO { KV_MEMBER(incoming_connections_count) KV_MEMBER(white_peerlist_size) KV_MEMBER(grey_peerlist_size) + KV_MEMBER(last_known_block_index) } }; }; diff --git a/src/Rpc/CoreRpcServerErrorCodes.h b/src/Rpc/CoreRpcServerErrorCodes.h index 9ae9e2a8..472a566c 100644 --- a/src/Rpc/CoreRpcServerErrorCodes.h +++ b/src/Rpc/CoreRpcServerErrorCodes.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Rpc/HttpClient.cpp b/src/Rpc/HttpClient.cpp index 93fe4f13..a37629c4 100644 --- a/src/Rpc/HttpClient.cpp +++ b/src/Rpc/HttpClient.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Rpc/HttpClient.h b/src/Rpc/HttpClient.h index 516a0169..166f1b11 100755 --- a/src/Rpc/HttpClient.h +++ b/src/Rpc/HttpClient.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Rpc/HttpServer.cpp b/src/Rpc/HttpServer.cpp index 2746a088..14b2304a 100755 --- a/src/Rpc/HttpServer.cpp +++ b/src/Rpc/HttpServer.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Rpc/HttpServer.h b/src/Rpc/HttpServer.h index d3b7f698..c29959a0 100755 --- a/src/Rpc/HttpServer.h +++ b/src/Rpc/HttpServer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Rpc/JsonRpc.cpp b/src/Rpc/JsonRpc.cpp index 7ce2e919..00b53e22 100755 --- a/src/Rpc/JsonRpc.cpp +++ b/src/Rpc/JsonRpc.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Rpc/JsonRpc.h b/src/Rpc/JsonRpc.h index 95e02f9a..cd9268ac 100755 --- a/src/Rpc/JsonRpc.h +++ b/src/Rpc/JsonRpc.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Rpc/RpcServer.cpp b/src/Rpc/RpcServer.cpp index 87328546..b3c656c4 100755 --- a/src/Rpc/RpcServer.cpp +++ b/src/Rpc/RpcServer.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -14,6 +14,9 @@ #include "CryptoNoteCore/IBlock.h" #include "CryptoNoteCore/Miner.h" #include "CryptoNoteCore/TransactionExtra.h" + +#include "CryptoNoteProtocol/ICryptoNoteProtocolQuery.h" + #include "P2p/NetNode.h" #include "CoreRpcServerErrorCodes.h" @@ -65,50 +68,50 @@ RpcServer::HandlerFunction jsonMethod(bool (RpcServer::*handler)(typename Comman } -std::unordered_map RpcServer::s_handlers = { +std::unordered_map> RpcServer::s_handlers = { // binary handlers - { "/getblocks.bin", binMethod(&RpcServer::on_get_blocks) }, - { "/queryblocks.bin", binMethod(&RpcServer::on_query_blocks) }, - { "/queryblockslite.bin", binMethod(&RpcServer::on_query_blocks_lite) }, - { "/get_o_indexes.bin", binMethod(&RpcServer::on_get_indexes) }, - { "/getrandom_outs.bin", binMethod(&RpcServer::on_get_random_outs) }, - { "/get_pool_changes.bin", binMethod(&RpcServer::onGetPoolChanges) }, - { "/get_pool_changes_lite.bin", binMethod(&RpcServer::onGetPoolChangesLite) }, + { "/getblocks.bin", { binMethod(&RpcServer::on_get_blocks), false } }, + { "/queryblocks.bin", { binMethod(&RpcServer::on_query_blocks), false } }, + { "/queryblockslite.bin", { binMethod(&RpcServer::on_query_blocks_lite), false } }, + { "/get_o_indexes.bin", { binMethod(&RpcServer::on_get_indexes), false } }, + { "/getrandom_outs.bin", { binMethod(&RpcServer::on_get_random_outs), false } }, + { "/get_pool_changes.bin", { binMethod(&RpcServer::onGetPoolChanges), false } }, + { "/get_pool_changes_lite.bin", { binMethod(&RpcServer::onGetPoolChangesLite), false } }, // json handlers - { "/getinfo", jsonMethod(&RpcServer::on_get_info) }, - { "/getheight", jsonMethod(&RpcServer::on_get_height) }, - { "/gettransactions", jsonMethod(&RpcServer::on_get_transactions)}, - { "/sendrawtransaction", jsonMethod(&RpcServer::on_send_raw_tx) }, - { "/start_mining", jsonMethod(&RpcServer::on_start_mining) }, - { "/stop_mining", jsonMethod(&RpcServer::on_stop_mining) }, - { "/stop_daemon", jsonMethod(&RpcServer::on_stop_daemon) }, + { "/getinfo", { jsonMethod(&RpcServer::on_get_info), true } }, + { "/getheight", { jsonMethod(&RpcServer::on_get_height), true } }, + { "/gettransactions", { jsonMethod(&RpcServer::on_get_transactions), false } }, + { "/sendrawtransaction", { jsonMethod(&RpcServer::on_send_raw_tx), false } }, + { "/start_mining", { jsonMethod(&RpcServer::on_start_mining), false } }, + { "/stop_mining", { jsonMethod(&RpcServer::on_stop_mining), false } }, + { "/stop_daemon", { jsonMethod(&RpcServer::on_stop_daemon), true } }, // json rpc - { "/json_rpc", std::bind(&RpcServer::processJsonRpcRequest, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3) } + { "/json_rpc", { std::bind(&RpcServer::processJsonRpcRequest, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3), true } } }; -RpcServer::RpcServer(System::Dispatcher& dispatcher, Logging::ILogger& log, core& c, NodeServer& p2p) : - HttpServer(dispatcher, log), logger(log, "RpcServer"), m_core(c), m_p2p(p2p) { +RpcServer::RpcServer(System::Dispatcher& dispatcher, Logging::ILogger& log, core& c, NodeServer& p2p, const ICryptoNoteProtocolQuery& protocolQuery) : + HttpServer(dispatcher, log), logger(log, "RpcServer"), m_core(c), m_p2p(p2p), m_protocolQuery(protocolQuery) { } void RpcServer::processRequest(const HttpRequest& request, HttpResponse& response) { auto url = request.getUrl(); - + auto it = s_handlers.find(url); if (it == s_handlers.end()) { response.setStatus(HttpResponse::STATUS_404); return; } - if (url != "/json_rpc" && !checkCoreReady()) { + if (!it->second.allowBusyCore && !isCoreReady()) { response.setStatus(HttpResponse::STATUS_500); response.setBody("Core is busy"); return; } - it->second(this, request, response); + it->second.handler(this, request, response); } bool RpcServer::processJsonRpcRequest(const HttpRequest& request, HttpResponse& response) { @@ -125,15 +128,15 @@ bool RpcServer::processJsonRpcRequest(const HttpRequest& request, HttpResponse& jsonRequest.parseRequest(request.getBody()); jsonResponse.setId(jsonRequest.getId()); // copy id - static std::unordered_map jsonRpcHandlers = { - { "getblockcount", makeMemberMethod(&RpcServer::on_getblockcount) }, - { "on_getblockhash", makeMemberMethod(&RpcServer::on_getblockhash) }, - { "getblocktemplate", makeMemberMethod(&RpcServer::on_getblocktemplate) }, - { "getcurrencyid", makeMemberMethod(&RpcServer::on_get_currency_id) }, - { "submitblock", makeMemberMethod(&RpcServer::on_submitblock) }, - { "getlastblockheader", makeMemberMethod(&RpcServer::on_get_last_block_header) }, - { "getblockheaderbyhash", makeMemberMethod(&RpcServer::on_get_block_header_by_hash) }, - { "getblockheaderbyheight", makeMemberMethod(&RpcServer::on_get_block_header_by_height) } + static std::unordered_map> jsonRpcHandlers = { + { "getblockcount", { makeMemberMethod(&RpcServer::on_getblockcount), true } }, + { "on_getblockhash", { makeMemberMethod(&RpcServer::on_getblockhash), false } }, + { "getblocktemplate", { makeMemberMethod(&RpcServer::on_getblocktemplate), false } }, + { "getcurrencyid", { makeMemberMethod(&RpcServer::on_get_currency_id), true } }, + { "submitblock", { makeMemberMethod(&RpcServer::on_submitblock), false } }, + { "getlastblockheader", { makeMemberMethod(&RpcServer::on_get_last_block_header), false } }, + { "getblockheaderbyhash", { makeMemberMethod(&RpcServer::on_get_block_header_by_hash), false } }, + { "getblockheaderbyheight", { makeMemberMethod(&RpcServer::on_get_block_header_by_height), false } } }; auto it = jsonRpcHandlers.find(jsonRequest.getMethod()); @@ -141,11 +144,11 @@ bool RpcServer::processJsonRpcRequest(const HttpRequest& request, HttpResponse& throw JsonRpcError(JsonRpc::errMethodNotFound); } - if (jsonRequest.getMethod() != "getcurrencyid" && !checkCoreReady()) { + if (!it->second.allowBusyCore && !isCoreReady()) { throw JsonRpcError(CORE_RPC_ERROR_CODE_CORE_BUSY, "Core is busy"); } - it->second(this, jsonRequest, jsonResponse); + it->second.handler(this, jsonRequest, jsonResponse); } catch (const JsonRpcError& err) { jsonResponse.setError(err); @@ -158,10 +161,8 @@ bool RpcServer::processJsonRpcRequest(const HttpRequest& request, HttpResponse& return true; } -#define CHECK_CORE_READY() - -bool RpcServer::checkCoreReady() { - return m_core.is_ready() && m_p2p.get_payload_object().isSynchronized(); +bool RpcServer::isCoreReady() { + return m_core.currency().isTestnet() || m_p2p.get_payload_object().isSynchronized(); } // @@ -206,8 +207,6 @@ bool RpcServer::on_get_blocks(const COMMAND_RPC_GET_BLOCKS_FAST::request& req, C } bool RpcServer::on_query_blocks(const COMMAND_RPC_QUERY_BLOCKS::request& req, COMMAND_RPC_QUERY_BLOCKS::response& res) { - CHECK_CORE_READY(); - uint32_t startHeight; uint32_t currentHeight; uint32_t fullOffset; @@ -225,8 +224,6 @@ bool RpcServer::on_query_blocks(const COMMAND_RPC_QUERY_BLOCKS::request& req, CO } bool RpcServer::on_query_blocks_lite(const COMMAND_RPC_QUERY_BLOCKS_LITE::request& req, COMMAND_RPC_QUERY_BLOCKS_LITE::response& res) { - CHECK_CORE_READY(); - uint32_t startHeight; uint32_t currentHeight; uint32_t fullOffset; @@ -243,8 +240,6 @@ bool RpcServer::on_query_blocks_lite(const COMMAND_RPC_QUERY_BLOCKS_LITE::reques } bool RpcServer::on_get_indexes(const COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::request& req, COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::response& res) { - CHECK_CORE_READY(); - std::vector outputIndexes; if (!m_core.get_tx_outputs_gindexs(req.txid, outputIndexes)) { res.status = "Failed"; @@ -258,7 +253,6 @@ bool RpcServer::on_get_indexes(const COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES:: } bool RpcServer::on_get_random_outs(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res) { - CHECK_CORE_READY(); res.status = "Failed"; if (!m_core.get_random_outs_for_amounts(req, res)) { return true; @@ -288,8 +282,6 @@ bool RpcServer::on_get_random_outs(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOU } bool RpcServer::onGetPoolChanges(const COMMAND_RPC_GET_POOL_CHANGES::request& req, COMMAND_RPC_GET_POOL_CHANGES::response& rsp) { - CHECK_CORE_READY(); - rsp.status = CORE_RPC_STATUS_OK; std::vector addedTransactions; rsp.isTailBlockActual = m_core.getPoolChanges(req.tailBlockId, req.knownTxsIds, addedTransactions, rsp.deletedTxsIds); @@ -307,8 +299,6 @@ bool RpcServer::onGetPoolChanges(const COMMAND_RPC_GET_POOL_CHANGES::request& re bool RpcServer::onGetPoolChangesLite(const COMMAND_RPC_GET_POOL_CHANGES_LITE::request& req, COMMAND_RPC_GET_POOL_CHANGES_LITE::response& rsp) { - CHECK_CORE_READY(); - rsp.status = CORE_RPC_STATUS_OK; rsp.isTailBlockActual = m_core.getPoolChangesLite(req.tailBlockId, req.knownTxsIds, rsp.addedTxs, rsp.deletedTxsIds); @@ -330,19 +320,18 @@ bool RpcServer::on_get_info(const COMMAND_RPC_GET_INFO::request& req, COMMAND_RP res.incoming_connections_count = total_conn - res.outgoing_connections_count; res.white_peerlist_size = m_p2p.getPeerlistManager().get_white_peers_count(); res.grey_peerlist_size = m_p2p.getPeerlistManager().get_gray_peers_count(); + res.last_known_block_index = std::max(static_cast(1), m_protocolQuery.getObservedHeight()) - 1; res.status = CORE_RPC_STATUS_OK; return true; } bool RpcServer::on_get_height(const COMMAND_RPC_GET_HEIGHT::request& req, COMMAND_RPC_GET_HEIGHT::response& res) { - CHECK_CORE_READY(); res.height = m_core.get_current_blockchain_height(); res.status = CORE_RPC_STATUS_OK; return true; } bool RpcServer::on_get_transactions(const COMMAND_RPC_GET_TRANSACTIONS::request& req, COMMAND_RPC_GET_TRANSACTIONS::response& res) { - CHECK_CORE_READY(); std::vector vh; for (const auto& tx_hex_str : req.txs_hashes) { BinaryArray b; @@ -374,8 +363,6 @@ bool RpcServer::on_get_transactions(const COMMAND_RPC_GET_TRANSACTIONS::request& } bool RpcServer::on_send_raw_tx(const COMMAND_RPC_SEND_RAW_TX::request& req, COMMAND_RPC_SEND_RAW_TX::response& res) { - CHECK_CORE_READY(); - BinaryArray tx_blob; if (!fromHex(req.tx_as_hex, tx_blob)) { @@ -416,7 +403,6 @@ bool RpcServer::on_send_raw_tx(const COMMAND_RPC_SEND_RAW_TX::request& req, COMM } bool RpcServer::on_start_mining(const COMMAND_RPC_START_MINING::request& req, COMMAND_RPC_START_MINING::response& res) { - CHECK_CORE_READY(); AccountPublicAddress adr; if (!m_core.currency().parseAccountAddressString(req.miner_address, adr)) { res.status = "Failed, wrong address"; @@ -433,7 +419,6 @@ bool RpcServer::on_start_mining(const COMMAND_RPC_START_MINING::request& req, CO } bool RpcServer::on_stop_mining(const COMMAND_RPC_STOP_MINING::request& req, COMMAND_RPC_STOP_MINING::response& res) { - CHECK_CORE_READY(); if (!m_core.get_miner().stop()) { res.status = "Failed, mining not stopped"; return true; @@ -443,7 +428,6 @@ bool RpcServer::on_stop_mining(const COMMAND_RPC_STOP_MINING::request& req, COMM } bool RpcServer::on_stop_daemon(const COMMAND_RPC_STOP_DAEMON::request& req, COMMAND_RPC_STOP_DAEMON::response& res) { - CHECK_CORE_READY(); if (m_core.currency().isTestnet()) { m_p2p.sendStopSignal(); res.status = CORE_RPC_STATUS_OK; diff --git a/src/Rpc/RpcServer.h b/src/Rpc/RpcServer.h index f24237e2..f68ff6c4 100755 --- a/src/Rpc/RpcServer.h +++ b/src/Rpc/RpcServer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -14,21 +14,28 @@ namespace CryptoNote { class core; class NodeServer; +class ICryptoNoteProtocolQuery; class RpcServer : public HttpServer { public: - RpcServer(System::Dispatcher& dispatcher, Logging::ILogger& log, core& c, NodeServer& p2p); + RpcServer(System::Dispatcher& dispatcher, Logging::ILogger& log, core& c, NodeServer& p2p, const ICryptoNoteProtocolQuery& protocolQuery); typedef std::function HandlerFunction; private: + template + struct RpcHandler { + const Handler handler; + const bool allowBusyCore; + }; + typedef void (RpcServer::*HandlerPtr)(const HttpRequest& request, HttpResponse& response); - static std::unordered_map s_handlers; + static std::unordered_map> s_handlers; virtual void processRequest(const HttpRequest& request, HttpResponse& response) override; bool processJsonRpcRequest(const HttpRequest& request, HttpResponse& response); - bool checkCoreReady(); + bool isCoreReady(); // binary handlers bool on_get_blocks(const COMMAND_RPC_GET_BLOCKS_FAST::request& req, COMMAND_RPC_GET_BLOCKS_FAST::response& res); @@ -63,6 +70,7 @@ private: Logging::LoggerRef logger; core& m_core; NodeServer& m_p2p; + const ICryptoNoteProtocolQuery& m_protocolQuery; }; } diff --git a/src/Rpc/RpcServerConfig.cpp b/src/Rpc/RpcServerConfig.cpp index f26515da..7d3eff46 100755 --- a/src/Rpc/RpcServerConfig.cpp +++ b/src/Rpc/RpcServerConfig.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Rpc/RpcServerConfig.h b/src/Rpc/RpcServerConfig.h index 8185c0cf..dc2aa5d4 100644 --- a/src/Rpc/RpcServerConfig.h +++ b/src/Rpc/RpcServerConfig.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Serialization/BinaryInputStreamSerializer.cpp b/src/Serialization/BinaryInputStreamSerializer.cpp index e22bb038..9a504611 100644 --- a/src/Serialization/BinaryInputStreamSerializer.cpp +++ b/src/Serialization/BinaryInputStreamSerializer.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Serialization/BinaryInputStreamSerializer.h b/src/Serialization/BinaryInputStreamSerializer.h index 9965788c..0db221c8 100644 --- a/src/Serialization/BinaryInputStreamSerializer.h +++ b/src/Serialization/BinaryInputStreamSerializer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -15,7 +15,7 @@ public: BinaryInputStreamSerializer(Common::IInputStream& strm) : stream(strm) {} virtual ~BinaryInputStreamSerializer() {} - virtual ISerializer::SerializerType type() const; + virtual ISerializer::SerializerType type() const override; virtual bool beginObject(Common::StringView name) override; virtual void endObject() override; diff --git a/src/Serialization/BinaryOutputStreamSerializer.cpp b/src/Serialization/BinaryOutputStreamSerializer.cpp index 009b618e..71bbec01 100644 --- a/src/Serialization/BinaryOutputStreamSerializer.cpp +++ b/src/Serialization/BinaryOutputStreamSerializer.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Serialization/BinaryOutputStreamSerializer.h b/src/Serialization/BinaryOutputStreamSerializer.h index 9421df8e..4ac936dd 100644 --- a/src/Serialization/BinaryOutputStreamSerializer.h +++ b/src/Serialization/BinaryOutputStreamSerializer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -15,7 +15,7 @@ public: BinaryOutputStreamSerializer(Common::IOutputStream& strm) : stream(strm) {} virtual ~BinaryOutputStreamSerializer() {} - virtual ISerializer::SerializerType type() const; + virtual ISerializer::SerializerType type() const override; virtual bool beginObject(Common::StringView name) override; virtual void endObject() override; diff --git a/src/Serialization/BinarySerializationTools.h b/src/Serialization/BinarySerializationTools.h index 494a3dc7..d34a585f 100644 --- a/src/Serialization/BinarySerializationTools.h +++ b/src/Serialization/BinarySerializationTools.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Serialization/ISerializer.h b/src/Serialization/ISerializer.h index 2df18b87..c2db7310 100644 --- a/src/Serialization/ISerializer.h +++ b/src/Serialization/ISerializer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Serialization/IStream.h b/src/Serialization/IStream.h index 8cab4f90..2e6b106c 100644 --- a/src/Serialization/IStream.h +++ b/src/Serialization/IStream.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Serialization/JsonInputStreamSerializer.cpp b/src/Serialization/JsonInputStreamSerializer.cpp index f05a04c4..82225bbb 100644 --- a/src/Serialization/JsonInputStreamSerializer.cpp +++ b/src/Serialization/JsonInputStreamSerializer.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Serialization/JsonInputStreamSerializer.h b/src/Serialization/JsonInputStreamSerializer.h index 3e75102c..4ddcc382 100644 --- a/src/Serialization/JsonInputStreamSerializer.h +++ b/src/Serialization/JsonInputStreamSerializer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Serialization/JsonInputValueSerializer.cpp b/src/Serialization/JsonInputValueSerializer.cpp index cb288d85..f6f69adf 100644 --- a/src/Serialization/JsonInputValueSerializer.cpp +++ b/src/Serialization/JsonInputValueSerializer.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Serialization/JsonInputValueSerializer.h b/src/Serialization/JsonInputValueSerializer.h index 0f8a06e8..86438f07 100644 --- a/src/Serialization/JsonInputValueSerializer.h +++ b/src/Serialization/JsonInputValueSerializer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -16,7 +16,7 @@ public: JsonInputValueSerializer(Common::JsonValue&& value); virtual ~JsonInputValueSerializer(); - SerializerType type() const; + SerializerType type() const override; virtual bool beginObject(Common::StringView name) override; virtual void endObject() override; diff --git a/src/Serialization/JsonOutputStreamSerializer.cpp b/src/Serialization/JsonOutputStreamSerializer.cpp index a323bada..d0608608 100644 --- a/src/Serialization/JsonOutputStreamSerializer.cpp +++ b/src/Serialization/JsonOutputStreamSerializer.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Serialization/JsonOutputStreamSerializer.h b/src/Serialization/JsonOutputStreamSerializer.h index 4d9efeb0..6a6eb5ac 100644 --- a/src/Serialization/JsonOutputStreamSerializer.h +++ b/src/Serialization/JsonOutputStreamSerializer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -15,7 +15,7 @@ public: JsonOutputStreamSerializer(); virtual ~JsonOutputStreamSerializer(); - SerializerType type() const; + SerializerType type() const override; virtual bool beginObject(Common::StringView name) override; virtual void endObject() override; diff --git a/src/Serialization/KVBinaryCommon.h b/src/Serialization/KVBinaryCommon.h index 205c6d7e..96c0d77e 100644 --- a/src/Serialization/KVBinaryCommon.h +++ b/src/Serialization/KVBinaryCommon.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Serialization/KVBinaryInputStreamSerializer.cpp b/src/Serialization/KVBinaryInputStreamSerializer.cpp index e1b7f610..403e9858 100644 --- a/src/Serialization/KVBinaryInputStreamSerializer.cpp +++ b/src/Serialization/KVBinaryInputStreamSerializer.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Serialization/KVBinaryInputStreamSerializer.h b/src/Serialization/KVBinaryInputStreamSerializer.h index db757771..09fe2fe0 100644 --- a/src/Serialization/KVBinaryInputStreamSerializer.h +++ b/src/Serialization/KVBinaryInputStreamSerializer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Serialization/KVBinaryOutputStreamSerializer.cpp b/src/Serialization/KVBinaryOutputStreamSerializer.cpp index 2097965b..8de59b86 100644 --- a/src/Serialization/KVBinaryOutputStreamSerializer.cpp +++ b/src/Serialization/KVBinaryOutputStreamSerializer.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Serialization/KVBinaryOutputStreamSerializer.h b/src/Serialization/KVBinaryOutputStreamSerializer.h index a04f1133..c92431d1 100644 --- a/src/Serialization/KVBinaryOutputStreamSerializer.h +++ b/src/Serialization/KVBinaryOutputStreamSerializer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -19,7 +19,7 @@ public: void dump(Common::IOutputStream& target); - virtual ISerializer::SerializerType type() const; + virtual ISerializer::SerializerType type() const override; virtual bool beginObject(Common::StringView name) override; virtual void endObject() override; diff --git a/src/Serialization/MemoryStream.cpp b/src/Serialization/MemoryStream.cpp index fdd70bec..c83d9130 100644 --- a/src/Serialization/MemoryStream.cpp +++ b/src/Serialization/MemoryStream.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Serialization/MemoryStream.h b/src/Serialization/MemoryStream.h index d7703207..486aa289 100644 --- a/src/Serialization/MemoryStream.h +++ b/src/Serialization/MemoryStream.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Serialization/SerializationOverloads.cpp b/src/Serialization/SerializationOverloads.cpp index 69ad3364..d341b89c 100644 --- a/src/Serialization/SerializationOverloads.cpp +++ b/src/Serialization/SerializationOverloads.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Serialization/SerializationOverloads.h b/src/Serialization/SerializationOverloads.h index a01046b2..a2e827c0 100644 --- a/src/Serialization/SerializationOverloads.h +++ b/src/Serialization/SerializationOverloads.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Serialization/SerializationTools.h b/src/Serialization/SerializationTools.h index fe1126ae..d352e3f2 100644 --- a/src/Serialization/SerializationTools.h +++ b/src/Serialization/SerializationTools.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/SimpleWallet/PasswordContainer.cpp b/src/SimpleWallet/PasswordContainer.cpp index 2ada2495..a3c65c8f 100644 --- a/src/SimpleWallet/PasswordContainer.cpp +++ b/src/SimpleWallet/PasswordContainer.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/SimpleWallet/PasswordContainer.h b/src/SimpleWallet/PasswordContainer.h index 4b9934a6..c82ffd42 100644 --- a/src/SimpleWallet/PasswordContainer.h +++ b/src/SimpleWallet/PasswordContainer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/SimpleWallet/SimpleWallet.cpp b/src/SimpleWallet/SimpleWallet.cpp index cb91d7e7..fe6c491c 100644 --- a/src/SimpleWallet/SimpleWallet.cpp +++ b/src/SimpleWallet/SimpleWallet.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -451,7 +451,8 @@ simple_wallet::simple_wallet(System::Dispatcher& dispatcher, const CryptoNote::C logManager(log), logger(log, "simplewallet"), m_refresh_progress_reporter(*this), - m_initResultPromise(nullptr) { + m_initResultPromise(nullptr), + m_walletSynchronized(false) { m_consoleHandler.setHandler("start_mining", boost::bind(&simple_wallet::start_mining, this, _1), "start_mining [] - Start mining in daemon"); m_consoleHandler.setHandler("stop_mining", boost::bind(&simple_wallet::stop_mining, this, _1), "Stop mining in daemon"); //m_consoleHandler.setHandler("refresh", boost::bind(&simple_wallet::refresh, this, _1), "Resynchronize transactions and balance"); @@ -721,8 +722,21 @@ bool simple_wallet::save(const std::vector &args) } bool simple_wallet::reset(const std::vector &args) { + { + std::unique_lock lock(m_walletSynchronizedMutex); + m_walletSynchronized = false; + } + m_wallet->reset(); - success_msg_writer(true) << "Reset is complete successfully"; + success_msg_writer(true) << "Reset completed successfully."; + + std::unique_lock lock(m_walletSynchronizedMutex); + while (!m_walletSynchronized) { + m_walletSynchronizedCV.wait(lock); + } + + std::cout << std::endl; + return true; } @@ -801,10 +815,6 @@ void simple_wallet::initCompleted(std::error_code result) { } } //---------------------------------------------------------------------------------------------------- -void simple_wallet::localBlockchainUpdated(uint32_t height) { - m_refresh_progress_reporter.update(height, false); -} -//---------------------------------------------------------------------------------------------------- void simple_wallet::connectionStatusUpdated(bool connected) { if (connected) { logger(INFO, GREEN) << "Wallet connected to daemon."; @@ -841,6 +851,19 @@ void simple_wallet::externalTransactionCreated(CryptoNote::TransactionId transac } } //---------------------------------------------------------------------------------------------------- +void simple_wallet::synchronizationCompleted(std::error_code result) { + std::unique_lock lock(m_walletSynchronizedMutex); + m_walletSynchronized = true; + m_walletSynchronizedCV.notify_one(); +} + +void simple_wallet::synchronizationProgressUpdated(uint32_t current, uint32_t total) { + std::unique_lock lock(m_walletSynchronizedMutex); + if (!m_walletSynchronized) { + m_refresh_progress_reporter.update(current, false); + } +} + bool simple_wallet::show_balance(const std::vector& args/* = std::vector()*/) { success_msg_writer() << "available balance: " << m_currency.formatAmount(m_wallet->actualBalance()) << ", locked amount: " << m_currency.formatAmount(m_wallet->pendingBalance()); @@ -997,6 +1020,15 @@ bool simple_wallet::transfer(const std::vector &args) { } //---------------------------------------------------------------------------------------------------- bool simple_wallet::run() { + { + std::unique_lock lock(m_walletSynchronizedMutex); + while (!m_walletSynchronized) { + m_walletSynchronizedCV.wait(lock); + } + } + + std::cout << std::endl; + std::string addr_start = m_wallet->getAddress().substr(0, 6); m_consoleHandler.start(false, "[wallet " + addr_start + "]: ", Common::Console::Color::BrightYellow); return true; diff --git a/src/SimpleWallet/SimpleWallet.h b/src/SimpleWallet/SimpleWallet.h index a2e55174..1006d85c 100644 --- a/src/SimpleWallet/SimpleWallet.h +++ b/src/SimpleWallet/SimpleWallet.h @@ -1,11 +1,13 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #pragma once -#include +#include #include +#include +#include #include @@ -82,13 +84,11 @@ namespace CryptoNote void printConnectionError() const; - //---------------- IWalletObserver ------------------------- + //---------------- IWalletLegacyObserver ------------------------- virtual void initCompleted(std::error_code result) override; virtual void externalTransactionCreated(CryptoNote::TransactionId transactionId) override; - //---------------------------------------------------------- - - //----------------- INodeObserver -------------------------- - virtual void localBlockchainUpdated(uint32_t height) override; + virtual void synchronizationCompleted(std::error_code result) override; + virtual void synchronizationProgressUpdated(uint32_t current, uint32_t total) override; //---------------------------------------------------------- //----------------- INodeRpcProxyObserver -------------------------- @@ -117,8 +117,7 @@ namespace CryptoNote m_blockchain_height = (std::max)(m_blockchain_height, height); } - if (std::chrono::milliseconds(1) < current_time - m_print_time || force) - { + if (std::chrono::milliseconds(1) < current_time - m_print_time || force) { std::cout << "Height " << height << " of " << m_blockchain_height << '\r'; m_print_time = current_time; } @@ -127,17 +126,9 @@ namespace CryptoNote private: void update_blockchain_height() { - std::string err; uint64_t blockchain_height = m_simple_wallet.m_node->getLastLocalBlockHeight(); - if (err.empty()) - { - m_blockchain_height = blockchain_height; - m_blockchain_height_update_time = std::chrono::system_clock::now(); - } - else - { - std::cerr << "Failed to get current blockchain height: " << err; - } + m_blockchain_height = blockchain_height; + m_blockchain_height_update_time = std::chrono::system_clock::now(); } private: @@ -169,5 +160,9 @@ namespace CryptoNote std::unique_ptr m_node; std::unique_ptr m_wallet; refresh_progress_reporter_t m_refresh_progress_reporter; + + bool m_walletSynchronized; + std::mutex m_walletSynchronizedMutex; + std::condition_variable m_walletSynchronizedCV; }; } diff --git a/src/System/Context.h b/src/System/Context.h index 96fa5e5f..ef35767c 100755 --- a/src/System/Context.h +++ b/src/System/Context.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/System/ContextGroup.cpp b/src/System/ContextGroup.cpp index 16734122..6cdf7da8 100755 --- a/src/System/ContextGroup.cpp +++ b/src/System/ContextGroup.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/System/ContextGroup.h b/src/System/ContextGroup.h index 056b32f3..3961042b 100755 --- a/src/System/ContextGroup.h +++ b/src/System/ContextGroup.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/System/ContextGroupTimeout.cpp b/src/System/ContextGroupTimeout.cpp index 73819408..e574e1ec 100755 --- a/src/System/ContextGroupTimeout.cpp +++ b/src/System/ContextGroupTimeout.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/System/ContextGroupTimeout.h b/src/System/ContextGroupTimeout.h index c6b9c58f..9eec8968 100755 --- a/src/System/ContextGroupTimeout.h +++ b/src/System/ContextGroupTimeout.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/System/Event.cpp b/src/System/Event.cpp index 216ad204..ff74f0a3 100755 --- a/src/System/Event.cpp +++ b/src/System/Event.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/System/Event.h b/src/System/Event.h index 10768b4c..06dbba4f 100644 --- a/src/System/Event.h +++ b/src/System/Event.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/System/EventLock.cpp b/src/System/EventLock.cpp index 77da4385..172fe902 100755 --- a/src/System/EventLock.cpp +++ b/src/System/EventLock.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/System/EventLock.h b/src/System/EventLock.h index c31d311f..bee00199 100755 --- a/src/System/EventLock.h +++ b/src/System/EventLock.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/System/InterruptedException.cpp b/src/System/InterruptedException.cpp index 62cafcb3..25bbe1f5 100644 --- a/src/System/InterruptedException.cpp +++ b/src/System/InterruptedException.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/System/InterruptedException.h b/src/System/InterruptedException.h index 5d2db650..03c7ec55 100644 --- a/src/System/InterruptedException.h +++ b/src/System/InterruptedException.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -10,7 +10,7 @@ namespace System { class InterruptedException : public std::exception { public: - const char* what() const throw() { + virtual const char* what() const throw() override { return "interrupted"; } }; diff --git a/src/System/Ipv4Address.cpp b/src/System/Ipv4Address.cpp index cee50e58..5d023d03 100755 --- a/src/System/Ipv4Address.cpp +++ b/src/System/Ipv4Address.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/System/Ipv4Address.h b/src/System/Ipv4Address.h index 73075fba..30f49511 100755 --- a/src/System/Ipv4Address.h +++ b/src/System/Ipv4Address.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/System/OperationTimeout.h b/src/System/OperationTimeout.h index 53f3072a..6d2a1125 100755 --- a/src/System/OperationTimeout.h +++ b/src/System/OperationTimeout.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/System/RemoteContext.h b/src/System/RemoteContext.h index bb39650f..c3969143 100644 --- a/src/System/RemoteContext.h +++ b/src/System/RemoteContext.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/System/RemoteEventLock.cpp b/src/System/RemoteEventLock.cpp index be52c897..4249673a 100755 --- a/src/System/RemoteEventLock.cpp +++ b/src/System/RemoteEventLock.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/System/RemoteEventLock.h b/src/System/RemoteEventLock.h index 7119d923..08dd2553 100755 --- a/src/System/RemoteEventLock.h +++ b/src/System/RemoteEventLock.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/System/TcpStream.cpp b/src/System/TcpStream.cpp index c7dbed77..c9e11c3d 100644 --- a/src/System/TcpStream.cpp +++ b/src/System/TcpStream.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/System/TcpStream.h b/src/System/TcpStream.h index 5073fb45..d369cace 100644 --- a/src/System/TcpStream.h +++ b/src/System/TcpStream.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Transfers/BlockchainSynchronizer.cpp b/src/Transfers/BlockchainSynchronizer.cpp index 36bbea4e..1a88f33e 100644 --- a/src/Transfers/BlockchainSynchronizer.cpp +++ b/src/Transfers/BlockchainSynchronizer.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -28,7 +28,10 @@ inline std::vector stringToVector(const std::string& s) { namespace CryptoNote { BlockchainSynchronizer::BlockchainSynchronizer(INode& node, const Hash& genesisBlockHash) : -m_node(node), m_genesisBlockHash(genesisBlockHash), m_currentState(State::stopped), m_futureState(State::stopped), shouldSyncConsumersPool(true) { + m_node(node), + m_genesisBlockHash(genesisBlockHash), + m_currentState(State::stopped), + m_futureState(State::stopped) { } BlockchainSynchronizer::~BlockchainSynchronizer() { @@ -44,7 +47,6 @@ void BlockchainSynchronizer::addConsumer(IBlockchainConsumer* consumer) { } m_consumers.insert(std::make_pair(consumer, std::make_shared(m_genesisBlockHash))); - shouldSyncConsumersPool = true; } bool BlockchainSynchronizer::removeConsumer(IBlockchainConsumer* consumer) { @@ -57,23 +59,81 @@ bool BlockchainSynchronizer::removeConsumer(IBlockchainConsumer* consumer) { return m_consumers.erase(consumer) > 0; } -IStreamSerializable* BlockchainSynchronizer::getConsumerState(IBlockchainConsumer* consumer) { - assert(consumer != nullptr); - - if (!(checkIfStopped() && checkIfShouldStop())) { - throw std::runtime_error("Can't get consumer state, because BlockchainSynchronizer isn't stopped"); - } - +IStreamSerializable* BlockchainSynchronizer::getConsumerState(IBlockchainConsumer* consumer) const { std::unique_lock lk(m_consumersMutex); - - auto it = m_consumers.find(consumer); - if (it == m_consumers.end()) { - return nullptr; - } - - return it->second.get(); + return getConsumerSynchronizationState(consumer); } +std::vector BlockchainSynchronizer::getConsumerKnownBlocks(IBlockchainConsumer& consumer) const { + std::unique_lock lk(m_consumersMutex); + + auto state = getConsumerSynchronizationState(&consumer); + if (state == nullptr) { + throw std::invalid_argument("Consumer not found"); + } + + return state->getKnownBlockHashes(); +} + +std::future BlockchainSynchronizer::addUnconfirmedTransaction(const ITransactionReader& transaction) { + std::unique_lock lock(m_stateMutex); + + if (m_currentState == State::stopped || m_futureState == State::stopped) { + throw std::runtime_error("Can't add transaction, because BlockchainSynchronizer is stopped"); + } + + std::promise promise; + auto future = promise.get_future(); + m_addTransactionTasks.emplace_back(&transaction, std::move(promise)); + m_hasWork.notify_one(); + + return future; +} + +std::future BlockchainSynchronizer::removeUnconfirmedTransaction(const Crypto::Hash& transactionHash) { + std::unique_lock lock(m_stateMutex); + + if (m_currentState == State::stopped || m_futureState == State::stopped) { + throw std::runtime_error("Can't remove transaction, because BlockchainSynchronizer is stopped"); + } + + std::promise promise; + auto future = promise.get_future(); + m_removeTransactionTasks.emplace_back(&transactionHash, std::move(promise)); + m_hasWork.notify_one(); + + return future; +} + +std::error_code BlockchainSynchronizer::doAddUnconfirmedTransaction(const ITransactionReader& transaction) { + std::unique_lock lk(m_consumersMutex); + + std::error_code ec; + auto addIt = m_consumers.begin(); + for (; addIt != m_consumers.end(); ++addIt) { + ec = addIt->first->addUnconfirmedTransaction(transaction); + if (ec) { + break; + } + } + + if (ec) { + auto transactionHash = transaction.getTransactionHash(); + for (auto rollbackIt = m_consumers.begin(); rollbackIt != addIt; ++rollbackIt) { + rollbackIt->first->removeUnconfirmedTransaction(transactionHash); + } + } + + return ec; +} + +void BlockchainSynchronizer::doRemoveUnconfirmedTransaction(const Crypto::Hash& transactionHash) { + std::unique_lock lk(m_consumersMutex); + + for (auto& consumer : m_consumers) { + consumer.first->removeUnconfirmedTransaction(transactionHash); + } +} void BlockchainSynchronizer::save(std::ostream& os) { os.write(reinterpret_cast(&m_genesisBlockHash), sizeof(m_genesisBlockHash)); @@ -90,16 +150,14 @@ void BlockchainSynchronizer::load(std::istream& in) { //--------------------------- FSM ------------------------------------ bool BlockchainSynchronizer::setFutureState(State s) { - return setFutureStateIf(s, std::bind( - [](State futureState, State s) -> bool { - return s > futureState; - }, std::ref(m_futureState), s)); + return setFutureStateIf(s, [this, s] { return s > m_futureState; }); } bool BlockchainSynchronizer::setFutureStateIf(State s, std::function&& pred) { std::unique_lock lk(m_stateMutex); if (pred()) { m_futureState = s; + m_hasWork.notify_one(); return true; } @@ -116,10 +174,37 @@ void BlockchainSynchronizer::actualizeFutureState() { m_node.removeObserver(this); } + while (!m_removeTransactionTasks.empty()) { + auto& task = m_removeTransactionTasks.front(); + const Crypto::Hash& transactionHash = *task.first; + auto detachedPromise = std::move(task.second); + m_removeTransactionTasks.pop_front(); + + try { + doRemoveUnconfirmedTransaction(transactionHash); + detachedPromise.set_value(); + } catch (...) { + detachedPromise.set_exception(std::current_exception()); + } + } + + while (!m_addTransactionTasks.empty()) { + auto& task = m_addTransactionTasks.front(); + const ITransactionReader& transaction = *task.first; + auto detachedPromise = std::move(task.second); + m_addTransactionTasks.pop_front(); + + try { + auto ec = doAddUnconfirmedTransaction(transaction); + detachedPromise.set_value(ec); + } catch (...) { + detachedPromise.set_exception(std::current_exception()); + } + } + m_currentState = m_futureState; switch (m_futureState) { case State::stopped: - m_futureState = State::stopped; break; case State::blockchainSync: m_futureState = State::poolSync; @@ -132,21 +217,22 @@ void BlockchainSynchronizer::actualizeFutureState() { startPoolSync(); break; case State::idle: - m_futureState = State::idle; + m_hasWork.wait(lk, [this] { + return m_futureState != State::idle || !m_removeTransactionTasks.empty() || !m_addTransactionTasks.empty(); + }); lk.unlock(); - std::this_thread::sleep_for(std::chrono::milliseconds(200)); break; default: break; } } -bool BlockchainSynchronizer::checkIfShouldStop() { +bool BlockchainSynchronizer::checkIfShouldStop() const { std::unique_lock lk(m_stateMutex); return m_futureState == State::stopped; } -bool BlockchainSynchronizer::checkIfStopped() { +bool BlockchainSynchronizer::checkIfStopped() const { std::unique_lock lk(m_stateMutex); return m_currentState == State::stopped; } @@ -165,16 +251,11 @@ void BlockchainSynchronizer::start() { throw std::runtime_error("Can't start, because BlockchainSynchronizer has no consumers"); } - if (!setFutureStateIf(State::blockchainSync, std::bind( - [](State currentState, State futureState) -> bool { - return currentState == State::stopped && futureState == State::stopped; - }, std::ref(m_currentState), std::ref(m_futureState)))) { + if (!setFutureStateIf(State::blockchainSync, [this] { return m_currentState == State::stopped && m_futureState == State::stopped; })) { throw std::runtime_error("BlockchainSynchronizer already started"); } - shouldSyncConsumersPool = true; - - workingThread.reset(new std::thread([this] {this->workingProcedure(); })); + workingThread.reset(new std::thread([this] { workingProcedure(); })); } void BlockchainSynchronizer::stop() { @@ -188,7 +269,11 @@ void BlockchainSynchronizer::stop() { workingThread.reset(); } -void BlockchainSynchronizer::lastKnownBlockHeightUpdated(uint32_t height) { +void BlockchainSynchronizer::localBlockchainUpdated(uint32_t /*height*/) { + setFutureState(State::blockchainSync); +} + +void BlockchainSynchronizer::lastKnownBlockHeightUpdated(uint32_t /*height*/) { setFutureState(State::blockchainSync); } @@ -197,52 +282,27 @@ void BlockchainSynchronizer::poolChanged() { } //--------------------------- FSM END ------------------------------------ -BlockchainSynchronizer::GetPoolRequest BlockchainSynchronizer::getUnionPoolHistory() { - GetPoolRequest request; - std::unordered_set unionHistory; - { - std::unique_lock lk(m_consumersMutex); - for (auto& consumer : m_consumers) { - std::vector consumerKnownIds; - consumer.first->getKnownPoolTxIds(consumerKnownIds); - for (auto& txId : consumerKnownIds) { - unionHistory.insert(txId); +void BlockchainSynchronizer::getPoolUnionAndIntersection(std::unordered_set& poolUnion, std::unordered_set& poolIntersection) const { + std::unique_lock lk(m_consumersMutex); + + auto itConsumers = m_consumers.begin(); + poolUnion = itConsumers->first->getKnownPoolTxIds(); + poolIntersection = itConsumers->first->getKnownPoolTxIds(); + ++itConsumers; + + for (; itConsumers != m_consumers.end(); ++itConsumers) { + const std::unordered_set& consumerKnownIds = itConsumers->first->getKnownPoolTxIds(); + + poolUnion.insert(consumerKnownIds.begin(), consumerKnownIds.end()); + + for (auto itIntersection = poolIntersection.begin(); itIntersection != poolIntersection.end();) { + if (consumerKnownIds.count(*itIntersection) == 0) { + itIntersection = poolIntersection.erase(itIntersection); + } else { + ++itIntersection; } } } - - for (auto& id : unionHistory) { - request.knownTxIds.push_back(id); - } - - request.lastKnownBlock = lastBlockId; - return request; -} - -BlockchainSynchronizer::GetPoolRequest BlockchainSynchronizer::getIntersectedPoolHistory() { - GetPoolRequest request; - { - std::unique_lock lk(m_consumersMutex); - auto it = m_consumers.begin(); - - it->first->getKnownPoolTxIds(request.knownTxIds); - ++it; - - for (; it != m_consumers.end(); ++it) { //iterate over consumers - std::vector consumerKnownIds; - it->first->getKnownPoolTxIds(consumerKnownIds); - for (auto itReq = request.knownTxIds.begin(); itReq != request.knownTxIds.end();) { //iterate over intersection - if (std::count(consumerKnownIds.begin(), consumerKnownIds.end(), *itReq) == 0) { //consumer doesn't contain id from intersection, so delete this id from intersection - itReq = request.knownTxIds.erase(itReq); - } else { - ++itReq; - } - } - } - } - - request.lastKnownBlock = lastBlockId; - return request; } BlockchainSynchronizer::GetBlocksRequest BlockchainSynchronizer::getCommonHistory() { @@ -277,42 +337,34 @@ void BlockchainSynchronizer::startBlockchainSync() { try { if (!req.knownBlocks.empty()) { - asyncOperationCompleted = std::promise(); - asyncOperationWaitFuture = asyncOperationCompleted.get_future(); + auto queryBlocksCompleted = std::promise(); + auto queryBlocksWaitFuture = queryBlocksCompleted.get_future(); - m_node.queryBlocks - (std::move(req.knownBlocks), req.syncStart.timestamp, response.newBlocks, response.startHeight, - std::bind(&BlockchainSynchronizer::onGetBlocksCompleted, this, std::placeholders::_1)); + m_node.queryBlocks( + std::move(req.knownBlocks), + req.syncStart.timestamp, + response.newBlocks, + response.startHeight, + [&queryBlocksCompleted](std::error_code ec) { + auto detachedPromise = std::move(queryBlocksCompleted); + detachedPromise.set_value(ec); + }); - std::error_code ec = asyncOperationWaitFuture.get(); + std::error_code ec = queryBlocksWaitFuture.get(); if (ec) { - setFutureStateIf(State::idle, std::bind( - [](State futureState) -> bool { - return futureState != State::stopped; - }, std::ref(m_futureState))); + setFutureStateIf(State::idle, [this] { return m_futureState != State::stopped; }); m_observerManager.notify(&IBlockchainSynchronizerObserver::synchronizationCompleted, ec); } else { processBlocks(response); } } - } catch (std::exception& e) { - std::cout << e.what() << std::endl; - setFutureStateIf(State::idle, std::bind( - [](State futureState) -> bool { - return futureState != State::stopped; - }, std::ref(m_futureState))); - m_observerManager.notify( - &IBlockchainSynchronizerObserver::synchronizationCompleted, - std::make_error_code(std::errc::invalid_argument)); + } catch (std::exception&) { + setFutureStateIf(State::idle, [this] { return m_futureState != State::stopped; }); + m_observerManager.notify(&IBlockchainSynchronizerObserver::synchronizationCompleted, std::make_error_code(std::errc::invalid_argument)); } } -void BlockchainSynchronizer::onGetBlocksCompleted(std::error_code ec) { - decltype(asyncOperationCompleted) detachedPromise = std::move(asyncOperationCompleted); - detachedPromise.set_value(ec); -} - void BlockchainSynchronizer::processBlocks(GetBlocksResponse& response) { BlockchainInterval interval; interval.startHeight = response.startHeight; @@ -322,6 +374,7 @@ void BlockchainSynchronizer::processBlocks(GetBlocksResponse& response) { if (checkIfShouldStop()) { break; } + CompleteBlock completeBlock; completeBlock.blockHash = block.blockHash; interval.blocks.push_back(completeBlock.blockHash); @@ -331,19 +384,11 @@ void BlockchainSynchronizer::processBlocks(GetBlocksResponse& response) { try { for (const auto& txShortInfo : block.txsShortInfo) { - completeBlock.transactions.push_back(createTransactionPrefix(txShortInfo.txPrefix, - reinterpret_cast(txShortInfo.txId))); + completeBlock.transactions.push_back(createTransactionPrefix(txShortInfo.txPrefix, reinterpret_cast(txShortInfo.txId))); } } catch (std::exception&) { - setFutureStateIf(State::idle, std::bind( - [](State futureState) -> bool { - return futureState != State::stopped; - }, std::ref(m_futureState))); - - m_observerManager.notify( - &IBlockchainSynchronizerObserver::synchronizationCompleted, - std::make_error_code(std::errc::invalid_argument)); - + setFutureStateIf(State::idle, [this] { return m_futureState != State::stopped; }); + m_observerManager.notify(&IBlockchainSynchronizerObserver::synchronizationCompleted, std::make_error_code(std::errc::invalid_argument)); return; } } @@ -359,23 +404,19 @@ void BlockchainSynchronizer::processBlocks(GetBlocksResponse& response) { lk.unlock(); switch (result) { - case UpdateConsumersResult::errorOccured: - if (setFutureStateIf(State::idle, std::bind( - [](State futureState) -> bool { - return futureState != State::stopped; - }, std::ref(m_futureState)))) { - m_observerManager.notify( - &IBlockchainSynchronizerObserver::synchronizationCompleted, - std::make_error_code(std::errc::invalid_argument)); + case UpdateConsumersResult::errorOccurred: + if (setFutureStateIf(State::idle, [this] { return m_futureState != State::stopped; })) { + m_observerManager.notify(&IBlockchainSynchronizerObserver::synchronizationCompleted, std::make_error_code(std::errc::invalid_argument)); } - break; + case UpdateConsumersResult::nothingChanged: if (m_node.getLastKnownBlockHeight() != m_node.getLastLocalBlockHeight()) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); } else { break; } + case UpdateConsumersResult::addedNewBlocks: setFutureState(State::blockchainSync); m_observerManager.notify( @@ -391,12 +432,11 @@ void BlockchainSynchronizer::processBlocks(GetBlocksResponse& response) { } if (checkIfShouldStop()) { //Sic! - m_observerManager.notify( - &IBlockchainSynchronizerObserver::synchronizationCompleted, - std::make_error_code(std::errc::interrupted)); + m_observerManager.notify(&IBlockchainSynchronizerObserver::synchronizationCompleted, std::make_error_code(std::errc::interrupted)); } } +/// \pre m_consumersMutex is locked BlockchainSynchronizer::UpdateConsumersResult BlockchainSynchronizer::updateConsumers(const BlockchainInterval& interval, const std::vector& blocks) { bool smthChanged = false; @@ -411,18 +451,12 @@ BlockchainSynchronizer::UpdateConsumersResult BlockchainSynchronizer::updateCons if (result.hasNewBlocks) { uint32_t startOffset = result.newBlockHeight - interval.startHeight; // update consumer - if (kv.first->onNewBlocks( - blocks.data() + startOffset, - result.newBlockHeight, - static_cast(blocks.size()) - startOffset)) { + if (kv.first->onNewBlocks(blocks.data() + startOffset, result.newBlockHeight, static_cast(blocks.size()) - startOffset)) { // update state if consumer succeeded - kv.second->addBlocks( - interval.blocks.data() + startOffset, - result.newBlockHeight, - static_cast(interval.blocks.size()) - startOffset); + kv.second->addBlocks(interval.blocks.data() + startOffset, result.newBlockHeight, static_cast(interval.blocks.size()) - startOffset); smthChanged = true; } else { - return UpdateConsumersResult::errorOccured; + return UpdateConsumersResult::errorOccurred; } } } @@ -431,57 +465,41 @@ BlockchainSynchronizer::UpdateConsumersResult BlockchainSynchronizer::updateCons } void BlockchainSynchronizer::startPoolSync() { + std::unordered_set unionPoolHistory; + std::unordered_set intersectedPoolHistory; + getPoolUnionAndIntersection(unionPoolHistory, intersectedPoolHistory); + + GetPoolRequest unionRequest; + unionRequest.knownTxIds.assign(unionPoolHistory.begin(), unionPoolHistory.end()); + unionRequest.lastKnownBlock = lastBlockId; + GetPoolResponse unionResponse; - GetPoolRequest unionRequest = getUnionPoolHistory(); - - asyncOperationCompleted = std::promise(); - asyncOperationWaitFuture = asyncOperationCompleted.get_future(); - unionResponse.isLastKnownBlockActual = false; - m_node.getPoolSymmetricDifference(std::move(unionRequest.knownTxIds), std::move(unionRequest.lastKnownBlock), unionResponse.isLastKnownBlockActual, - unionResponse.newTxs, unionResponse.deletedTxIds, std::bind(&BlockchainSynchronizer::onGetPoolChanges, this, std::placeholders::_1)); - - std::error_code ec = asyncOperationWaitFuture.get(); + std::error_code ec = getPoolSymmetricDifferenceSync(std::move(unionRequest), unionResponse); if (ec) { - setFutureStateIf(State::idle, std::bind( - [](State futureState) -> bool { - return futureState != State::stopped; - }, std::ref(m_futureState))); - m_observerManager.notify( - &IBlockchainSynchronizerObserver::synchronizationCompleted, - ec); + setFutureStateIf(State::idle, [this] { return m_futureState != State::stopped; }); + m_observerManager.notify(&IBlockchainSynchronizerObserver::synchronizationCompleted, ec); } else { //get union ok if (!unionResponse.isLastKnownBlockActual) { //bc outdated setFutureState(State::blockchainSync); } else { - if (!shouldSyncConsumersPool) { //usual case, start pool processing - m_observerManager.notify( - &IBlockchainSynchronizerObserver::synchronizationCompleted, - processPoolTxs(unionResponse)); - } else {// first launch, we should sync consumers' pools, so let's ask for intersection + if (unionPoolHistory == intersectedPoolHistory) { //usual case, start pool processing + m_observerManager.notify(&IBlockchainSynchronizerObserver::synchronizationCompleted, processPoolTxs(unionResponse)); + } else { + GetPoolRequest intersectionRequest; + intersectionRequest.knownTxIds.assign(intersectedPoolHistory.begin(), intersectedPoolHistory.end()); + intersectionRequest.lastKnownBlock = lastBlockId; + GetPoolResponse intersectionResponse; - GetPoolRequest intersectionRequest = getIntersectedPoolHistory(); - - asyncOperationCompleted = std::promise(); - asyncOperationWaitFuture = asyncOperationCompleted.get_future(); - intersectionResponse.isLastKnownBlockActual = false; - m_node.getPoolSymmetricDifference(std::move(intersectionRequest.knownTxIds), std::move(intersectionRequest.lastKnownBlock), intersectionResponse.isLastKnownBlockActual, - intersectionResponse.newTxs, intersectionResponse.deletedTxIds, std::bind(&BlockchainSynchronizer::onGetPoolChanges, this, std::placeholders::_1)); - - std::error_code ec2 = asyncOperationWaitFuture.get(); + std::error_code ec2 = getPoolSymmetricDifferenceSync(std::move(intersectionRequest), intersectionResponse); if (ec2) { - setFutureStateIf(State::idle, std::bind( - [](State futureState) -> bool { - return futureState != State::stopped; - }, std::ref(m_futureState))); - m_observerManager.notify( - &IBlockchainSynchronizerObserver::synchronizationCompleted, - ec2); + setFutureStateIf(State::idle, [this] { return m_futureState != State::stopped; }); + m_observerManager.notify(&IBlockchainSynchronizerObserver::synchronizationCompleted, ec2); } else { //get intersection ok if (!intersectionResponse.isLastKnownBlockActual) { //bc outdated setFutureState(State::blockchainSync); @@ -490,13 +508,7 @@ void BlockchainSynchronizer::startPoolSync() { std::error_code ec3 = processPoolTxs(intersectionResponse); //notify about error, or success - m_observerManager.notify( - &IBlockchainSynchronizerObserver::synchronizationCompleted, - ec3); - - if (!ec3) { - shouldSyncConsumersPool = false; - } + m_observerManager.notify(&IBlockchainSynchronizerObserver::synchronizationCompleted, ec3); } } } @@ -504,9 +516,22 @@ void BlockchainSynchronizer::startPoolSync() { } } -void BlockchainSynchronizer::onGetPoolChanges(std::error_code ec) { - decltype(asyncOperationCompleted) detachedPromise = std::move(asyncOperationCompleted); - detachedPromise.set_value(ec); +std::error_code BlockchainSynchronizer::getPoolSymmetricDifferenceSync(GetPoolRequest&& request, GetPoolResponse& response) { + auto promise = std::promise(); + auto future = promise.get_future(); + + m_node.getPoolSymmetricDifference( + std::move(request.knownTxIds), + std::move(request.lastKnownBlock), + response.isLastKnownBlockActual, + response.newTxs, + response.deletedTxIds, + [&promise](std::error_code ec) { + auto detachedPromise = std::move(promise); + detachedPromise.set_value(ec); + }); + + return future.get(); } std::error_code BlockchainSynchronizer::processPoolTxs(GetPoolResponse& response) { @@ -528,4 +553,20 @@ std::error_code BlockchainSynchronizer::processPoolTxs(GetPoolResponse& response return error; } +///pre: m_consumersMutex is locked +SynchronizationState* BlockchainSynchronizer::getConsumerSynchronizationState(IBlockchainConsumer* consumer) const { + assert(consumer != nullptr); + + if (!(checkIfStopped() && checkIfShouldStop())) { + throw std::runtime_error("Can't get consumer state, because BlockchainSynchronizer isn't stopped"); + } + + auto it = m_consumers.find(consumer); + if (it == m_consumers.end()) { + return nullptr; + } + + return it->second.get(); +} + } diff --git a/src/Transfers/BlockchainSynchronizer.h b/src/Transfers/BlockchainSynchronizer.h index 8f96edfd..d6726942 100644 --- a/src/Transfers/BlockchainSynchronizer.h +++ b/src/Transfers/BlockchainSynchronizer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -28,7 +28,11 @@ public: // IBlockchainSynchronizer virtual void addConsumer(IBlockchainConsumer* consumer) override; virtual bool removeConsumer(IBlockchainConsumer* consumer) override; - virtual IStreamSerializable* getConsumerState(IBlockchainConsumer* consumer) override; + virtual IStreamSerializable* getConsumerState(IBlockchainConsumer* consumer) const override; + virtual std::vector getConsumerKnownBlocks(IBlockchainConsumer& consumer) const override; + + virtual std::future addUnconfirmedTransaction(const ITransactionReader& transaction) override; + virtual std::future removeUnconfirmedTransaction(const Crypto::Hash& transactionHash) override; virtual void start() override; virtual void stop() override; @@ -38,6 +42,7 @@ public: virtual void load(std::istream& in) override; // INodeObserver + virtual void localBlockchainUpdated(uint32_t height) override; virtual void lastKnownBlockHeightUpdated(uint32_t height) override; virtual void poolChanged() override; @@ -68,7 +73,6 @@ private: Crypto::Hash lastKnownBlock; }; - enum class State { //prioritized finite states idle = 0, //DO poolSync = 1, //NOT @@ -79,32 +83,33 @@ private: enum class UpdateConsumersResult { nothingChanged = 0, addedNewBlocks = 1, - errorOccured = 2 + errorOccurred = 2 }; //void startSync(); void startPoolSync(); void startBlockchainSync(); - void onGetBlocksCompleted(std::error_code ec); void processBlocks(GetBlocksResponse& response); UpdateConsumersResult updateConsumers(const BlockchainInterval& interval, const std::vector& blocks); - void onGetPoolChanges(std::error_code ec); std::error_code processPoolTxs(GetPoolResponse& response); - + std::error_code getPoolSymmetricDifferenceSync(GetPoolRequest&& request, GetPoolResponse& response); + std::error_code doAddUnconfirmedTransaction(const ITransactionReader& transaction); + void doRemoveUnconfirmedTransaction(const Crypto::Hash& transactionHash); + ///second parameter is used only in case of errors returned into callback from INode, such as aborted or connection lost bool setFutureState(State s); bool setFutureStateIf(State s, std::function&& pred); void actualizeFutureState(); - bool checkIfShouldStop(); - bool checkIfStopped(); + bool checkIfShouldStop() const; + bool checkIfStopped() const; void workingProcedure(); GetBlocksRequest getCommonHistory(); - GetPoolRequest getUnionPoolHistory(); - GetPoolRequest getIntersectedPoolHistory(); + void getPoolUnionAndIntersection(std::unordered_set& poolUnion, std::unordered_set& poolIntersection) const; + SynchronizationState* getConsumerSynchronizationState(IBlockchainConsumer* consumer) const ; typedef std::map> ConsumersMap; @@ -117,14 +122,12 @@ private: State m_currentState; State m_futureState; std::unique_ptr workingThread; + std::list>> m_addTransactionTasks; + std::list>> m_removeTransactionTasks; - std::future asyncOperationWaitFuture; - std::promise asyncOperationCompleted; - - std::mutex m_consumersMutex; - std::mutex m_stateMutex; - - bool shouldSyncConsumersPool; + mutable std::mutex m_consumersMutex; + mutable std::mutex m_stateMutex; + std::condition_variable m_hasWork; }; } diff --git a/src/Transfers/CommonTypes.h b/src/Transfers/CommonTypes.h index 03d695c8..f574c2eb 100644 --- a/src/Transfers/CommonTypes.h +++ b/src/Transfers/CommonTypes.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Transfers/IBlockchainSynchronizer.h b/src/Transfers/IBlockchainSynchronizer.h index 2ee526bc..e3dbfd2e 100644 --- a/src/Transfers/IBlockchainSynchronizer.h +++ b/src/Transfers/IBlockchainSynchronizer.h @@ -1,11 +1,13 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #pragma once #include +#include #include +#include #include "crypto/crypto.h" #include "CryptoNoteCore/CryptoNoteBasic.h" @@ -24,16 +26,29 @@ public: virtual void synchronizationCompleted(std::error_code result) {} }; -class IBlockchainConsumer { +class IBlockchainConsumerObserver; + +class IBlockchainConsumer : public IObservable { public: virtual ~IBlockchainConsumer() {} virtual SynchronizationStart getSyncStart() = 0; - virtual void getKnownPoolTxIds(std::vector& ids) = 0; + virtual const std::unordered_set& getKnownPoolTxIds() const = 0; virtual void onBlockchainDetach(uint32_t height) = 0; virtual bool onNewBlocks(const CompleteBlock* blocks, uint32_t startHeight, uint32_t count) = 0; virtual std::error_code onPoolUpdated(const std::vector>& addedTransactions, const std::vector& deletedTransactions) = 0; + + virtual std::error_code addUnconfirmedTransaction(const ITransactionReader& transaction) = 0; + virtual void removeUnconfirmedTransaction(const Crypto::Hash& transactionHash) = 0; }; +class IBlockchainConsumerObserver { +public: + virtual void onBlocksAdded(IBlockchainConsumer* consumer, const std::vector& blockHashes) {} + virtual void onBlockchainDetach(IBlockchainConsumer* consumer, uint32_t blockIndex) {} + virtual void onTransactionDeleteBegin(IBlockchainConsumer* consumer, Crypto::Hash transactionHash) {} + virtual void onTransactionDeleteEnd(IBlockchainConsumer* consumer, Crypto::Hash transactionHash) {} + virtual void onTransactionUpdated(IBlockchainConsumer* consumer, const Crypto::Hash& transactionHash, const std::vector& containers) {} +}; class IBlockchainSynchronizer : public IObservable, @@ -41,7 +56,11 @@ class IBlockchainSynchronizer : public: virtual void addConsumer(IBlockchainConsumer* consumer) = 0; virtual bool removeConsumer(IBlockchainConsumer* consumer) = 0; - virtual IStreamSerializable* getConsumerState(IBlockchainConsumer* consumer) = 0; + virtual IStreamSerializable* getConsumerState(IBlockchainConsumer* consumer) const = 0; + virtual std::vector getConsumerKnownBlocks(IBlockchainConsumer& consumer) const = 0; + + virtual std::future addUnconfirmedTransaction(const ITransactionReader& transaction) = 0; + virtual std::future removeUnconfirmedTransaction(const Crypto::Hash& transactionHash) = 0; virtual void start() = 0; virtual void stop() = 0; diff --git a/src/Transfers/IObservableImpl.h b/src/Transfers/IObservableImpl.h index 101da38e..745036ec 100644 --- a/src/Transfers/IObservableImpl.h +++ b/src/Transfers/IObservableImpl.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Transfers/SynchronizationState.cpp b/src/Transfers/SynchronizationState.cpp index 81275a96..a1196afd 100644 --- a/src/Transfers/SynchronizationState.cpp +++ b/src/Transfers/SynchronizationState.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -90,6 +90,10 @@ uint32_t SynchronizationState::getHeight() const { return static_cast(m_blockchain.size()); } +const std::vector& SynchronizationState::getKnownBlockHashes() const { + return m_blockchain; +} + void SynchronizationState::save(std::ostream& os) { StdOutputStream stream(os); CryptoNote::BinaryOutputStreamSerializer s(stream); diff --git a/src/Transfers/SynchronizationState.h b/src/Transfers/SynchronizationState.h index a5a85ad8..12aeec05 100644 --- a/src/Transfers/SynchronizationState.h +++ b/src/Transfers/SynchronizationState.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -34,6 +34,7 @@ public: void detach(uint32_t height); void addBlocks(const Crypto::Hash* blockHashes, uint32_t height, uint32_t count); uint32_t getHeight() const; + const std::vector& getKnownBlockHashes() const; // IStreamSerializable virtual void save(std::ostream& os) override; diff --git a/src/Transfers/TransfersConsumer.cpp b/src/Transfers/TransfersConsumer.cpp index 13e1f04c..48fb0add 100644 --- a/src/Transfers/TransfersConsumer.cpp +++ b/src/Transfers/TransfersConsumer.cpp @@ -1,15 +1,17 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "TransfersConsumer.h" -#include "CommonTypes.h" +#include + +#include "CommonTypes.h" #include "Common/BlockingQueue.h" #include "CryptoNoteCore/CryptoNoteFormatUtils.h" #include "CryptoNoteCore/TransactionApi.h" -#include "IWalletLegacy.h" +#include "IWallet.h" #include "INode.h" #include @@ -77,6 +79,17 @@ void findMyOutputs( } } +std::vector getBlockHashes(const CryptoNote::CompleteBlock* blocks, size_t count) { + std::vector result; + result.reserve(count); + + for (size_t i = 0; i < count; ++i) { + result.push_back(blocks[i].blockHash); + } + + return result; +} + } namespace CryptoNote { @@ -120,6 +133,19 @@ void TransfersConsumer::getSubscriptions(std::vector& subs } } +void TransfersConsumer::initTransactionPool(const std::unordered_set& uncommitedTransactions) { + for (auto itSubscriptions = m_subscriptions.begin(); itSubscriptions != m_subscriptions.end(); ++itSubscriptions) { + std::vector unconfirmedTransactions; + itSubscriptions->second->getContainer().getUnconfirmedTransactions(unconfirmedTransactions); + + for (auto itTransactions = unconfirmedTransactions.begin(); itTransactions != unconfirmedTransactions.end(); ++itTransactions) { + if (uncommitedTransactions.count(*itTransactions) == 0) { + m_poolTxs.emplace(*itTransactions); + } + } + } +} + void TransfersConsumer::updateSyncStart() { SynchronizationStart start; @@ -140,6 +166,8 @@ SynchronizationStart TransfersConsumer::getSyncStart() { } void TransfersConsumer::onBlockchainDetach(uint32_t height) { + m_observerManager.notify(&IBlockchainConsumerObserver::onBlockchainDetach, this, height); + for (const auto& kv : m_subscriptions) { kv.second->onBlockchainDetach(height); } @@ -240,24 +268,23 @@ bool TransfersConsumer::onNewBlocks(const CompleteBlock* blocks, uint32_t startH } } + std::vector blockHashes = getBlockHashes(blocks, count); if (!processingError) { + m_observerManager.notify(&IBlockchainConsumerObserver::onBlocksAdded, this, blockHashes); + // sort by block height and transaction index in block std::sort(preprocessedTransactions.begin(), preprocessedTransactions.end(), [](const PreprocessedTx& a, const PreprocessedTx& b) { return std::tie(a.blockInfo.height, a.blockInfo.transactionIndex) < std::tie(b.blockInfo.height, b.blockInfo.transactionIndex); }); for (const auto& tx : preprocessedTransactions) { - processingError = processTransaction(tx.blockInfo, *tx.tx, tx); - if (processingError) { - break; - } + processTransaction(tx.blockInfo, *tx.tx, tx); } - } - - if (processingError) { + } else { forEachSubscription([&](TransfersSubscription& sub) { sub.onError(processingError, startHeight); }); + return false; } @@ -272,44 +299,55 @@ bool TransfersConsumer::onNewBlocks(const CompleteBlock* blocks, uint32_t startH std::error_code TransfersConsumer::onPoolUpdated(const std::vector>& addedTransactions, const std::vector& deletedTransactions) { TransactionBlockInfo unconfirmedBlockInfo; unconfirmedBlockInfo.timestamp = 0; - unconfirmedBlockInfo.height = WALLET_LEGACY_UNCONFIRMED_TRANSACTION_HEIGHT; + unconfirmedBlockInfo.height = WALLET_UNCONFIRMED_TRANSACTION_HEIGHT; + std::error_code processingError; for (auto& cryptonoteTransaction : addedTransactions) { + m_poolTxs.emplace(cryptonoteTransaction->getTransactionHash()); processingError = processTransaction(unconfirmedBlockInfo, *cryptonoteTransaction.get()); if (processingError) { - break; - } - } + for (auto& sub : m_subscriptions) { + sub.second->onError(processingError, WALLET_UNCONFIRMED_TRANSACTION_HEIGHT); + } - if (processingError) { - for (auto& sub : m_subscriptions) { - sub.second->onError(processingError, WALLET_LEGACY_UNCONFIRMED_TRANSACTION_HEIGHT); + return processingError; } - - return processingError; } for (auto& deletedTxHash : deletedTransactions) { - for (auto& sub: m_subscriptions) { + m_poolTxs.erase(deletedTxHash); + + m_observerManager.notify(&IBlockchainConsumerObserver::onTransactionDeleteBegin, this, deletedTxHash); + for (auto& sub : m_subscriptions) { sub.second->deleteUnconfirmedTransaction(*reinterpret_cast(&deletedTxHash)); } + + m_observerManager.notify(&IBlockchainConsumerObserver::onTransactionDeleteEnd, this, deletedTxHash); } return std::error_code(); } -void TransfersConsumer::getKnownPoolTxIds(std::vector& ids) { - ids.clear(); - std::unordered_set knownIds; - for (auto& sub : m_subscriptions) { - std::vector subscriptionUnconfirmedTxIds; - sub.second->getContainer().getUnconfirmedTransactions(subscriptionUnconfirmedTxIds); - knownIds.insert(subscriptionUnconfirmedTxIds.begin(), subscriptionUnconfirmedTxIds.end()); - } - - ids.assign(knownIds.begin(), knownIds.end()); +const std::unordered_set& TransfersConsumer::getKnownPoolTxIds() const { + return m_poolTxs; } +std::error_code TransfersConsumer::addUnconfirmedTransaction(const ITransactionReader& transaction) { + TransactionBlockInfo unconfirmedBlockInfo; + unconfirmedBlockInfo.height = WALLET_UNCONFIRMED_TRANSACTION_HEIGHT; + unconfirmedBlockInfo.timestamp = 0; + unconfirmedBlockInfo.transactionIndex = 0; + + return processTransaction(unconfirmedBlockInfo, transaction); +} + +void TransfersConsumer::removeUnconfirmedTransaction(const Crypto::Hash& transactionHash) { + m_observerManager.notify(&IBlockchainConsumerObserver::onTransactionDeleteBegin, this, transactionHash); + for (auto& subscription : m_subscriptions) { + subscription.second->deleteUnconfirmedTransaction(transactionHash); + } + m_observerManager.notify(&IBlockchainConsumerObserver::onTransactionDeleteEnd, this, transactionHash); +} std::error_code createTransfers( const AccountKeys& account, @@ -340,7 +378,7 @@ std::error_code createTransfers( info.type = outType; info.transactionPublicKey = txPubKey; info.outputInTransaction = idx; - info.globalOutputIndex = (blockInfo.height == WALLET_LEGACY_UNCONFIRMED_TRANSACTION_HEIGHT) ? + info.globalOutputIndex = (blockInfo.height == WALLET_UNCONFIRMED_TRANSACTION_HEIGHT) ? UNCONFIRMED_TRANSACTION_GLOBAL_OUTPUT_INDEX : globalIdxs[idx]; if (outType == TransactionTypes::OutputType::Key) { @@ -386,7 +424,7 @@ std::error_code TransfersConsumer::preprocessOutputs(const TransactionBlockInfo& std::error_code errorCode; auto txHash = tx.getTransactionHash(); - if (blockInfo.height != WALLET_LEGACY_UNCONFIRMED_TRANSACTION_HEIGHT) { + if (blockInfo.height != WALLET_UNCONFIRMED_TRANSACTION_HEIGHT) { errorCode = getGlobalIndices(reinterpret_cast(txHash), info.globalIdxs); if (errorCode) { return errorCode; @@ -414,50 +452,52 @@ std::error_code TransfersConsumer::processTransaction(const TransactionBlockInfo return ec; } - return processTransaction(blockInfo, tx, info); + processTransaction(blockInfo, tx, info); + return std::error_code(); } - -std::error_code TransfersConsumer::processTransaction(const TransactionBlockInfo& blockInfo, const ITransactionReader& tx, const PreprocessInfo& info) { - std::error_code errorCode; +void TransfersConsumer::processTransaction(const TransactionBlockInfo& blockInfo, const ITransactionReader& tx, const PreprocessInfo& info) { std::vector emptyOutputs; + std::vector transactionContainers; + bool someContainerUpdated = false; for (auto& kv : m_subscriptions) { auto it = info.outputs.find(kv.first); auto& subscriptionOutputs = (it == info.outputs.end()) ? emptyOutputs : it->second; - errorCode = processOutputs(blockInfo, *kv.second, tx, subscriptionOutputs, info.globalIdxs); - if (errorCode) { - return errorCode; + + bool containerContainsTx; + bool containerUpdated; + processOutputs(blockInfo, *kv.second, tx, subscriptionOutputs, info.globalIdxs, containerContainsTx, containerUpdated); + someContainerUpdated = someContainerUpdated || containerUpdated; + if (containerContainsTx) { + transactionContainers.emplace_back(&kv.second->getContainer()); } } - return std::error_code(); -} - - - -std::error_code TransfersConsumer::processOutputs(const TransactionBlockInfo& blockInfo, TransfersSubscription& sub, - const ITransactionReader& tx, const std::vector& transfers, const std::vector& globalIdxs) { - - if (blockInfo.height != WALLET_LEGACY_UNCONFIRMED_TRANSACTION_HEIGHT) { - TransactionInformation subscribtionTxInfo; - int64_t txBalance; - if (sub.getContainer().getTransactionInformation(tx.getTransactionHash(), subscribtionTxInfo, txBalance)) { - if (subscribtionTxInfo.blockHeight == WALLET_LEGACY_UNCONFIRMED_TRANSACTION_HEIGHT) { - // pool->blockchain - sub.markTransactionConfirmed(blockInfo, tx.getTransactionHash(), globalIdxs); - return std::error_code(); - } else { - // - Subscription already has this transaction as confirmed, so why are we here? - // - Because, for instance, some another subscription doesn't have this transactions, so it is given to us again. - return std::error_code(); - } - } + if (someContainerUpdated) { + m_observerManager.notify(&IBlockchainConsumerObserver::onTransactionUpdated, this, tx.getTransactionHash(), transactionContainers); } - - sub.addTransaction(blockInfo, tx, transfers); - return std::error_code(); } +void TransfersConsumer::processOutputs(const TransactionBlockInfo& blockInfo, TransfersSubscription& sub, const ITransactionReader& tx, + const std::vector& transfers, const std::vector& globalIdxs, bool& contains, bool& updated) { + + TransactionInformation subscribtionTxInfo; + contains = sub.getContainer().getTransactionInformation(tx.getTransactionHash(), subscribtionTxInfo); + updated = false; + + if (contains) { + if (subscribtionTxInfo.blockHeight == WALLET_UNCONFIRMED_TRANSACTION_HEIGHT && blockInfo.height != WALLET_UNCONFIRMED_TRANSACTION_HEIGHT) { + // pool->blockchain + sub.markTransactionConfirmed(blockInfo, tx.getTransactionHash(), globalIdxs); + updated = true; + } else { + assert(subscribtionTxInfo.blockHeight == blockInfo.height); + } + } else { + updated = sub.addTransaction(blockInfo, tx, transfers); + contains = updated; + } +} std::error_code TransfersConsumer::getGlobalIndices(const Hash& transactionHash, std::vector& outsGlobalIndices) { std::promise prom; diff --git a/src/Transfers/TransfersConsumer.h b/src/Transfers/TransfersConsumer.h index c6f71782..9e837e17 100755 --- a/src/Transfers/TransfersConsumer.h +++ b/src/Transfers/TransfersConsumer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -19,8 +19,7 @@ namespace CryptoNote { class INode; -class TransfersConsumer : public IBlockchainConsumer { - +class TransfersConsumer: public IObservableImpl { public: TransfersConsumer(const CryptoNote::Currency& currency, INode& node, const Crypto::SecretKey& viewSecret); @@ -30,13 +29,18 @@ public: bool removeSubscription(const AccountPublicAddress& address); ITransfersSubscription* getSubscription(const AccountPublicAddress& acc); void getSubscriptions(std::vector& subscriptions); + + void initTransactionPool(const std::unordered_set& uncommitedTransactions); // IBlockchainConsumer virtual SynchronizationStart getSyncStart() override; virtual void onBlockchainDetach(uint32_t height) override; virtual bool onNewBlocks(const CompleteBlock* blocks, uint32_t startHeight, uint32_t count) override; virtual std::error_code onPoolUpdated(const std::vector>& addedTransactions, const std::vector& deletedTransactions) override; - virtual void getKnownPoolTxIds(std::vector& ids) override; + virtual const std::unordered_set& getKnownPoolTxIds() const override; + + virtual std::error_code addUnconfirmedTransaction(const ITransactionReader& transaction) override; + virtual void removeUnconfirmedTransaction(const Crypto::Hash& transactionHash) override; private: @@ -54,9 +58,9 @@ private: std::error_code preprocessOutputs(const TransactionBlockInfo& blockInfo, const ITransactionReader& tx, PreprocessInfo& info); std::error_code processTransaction(const TransactionBlockInfo& blockInfo, const ITransactionReader& tx); - std::error_code processTransaction(const TransactionBlockInfo& blockInfo, const ITransactionReader& tx, const PreprocessInfo& info); - std::error_code processOutputs(const TransactionBlockInfo& blockInfo, TransfersSubscription& sub, const ITransactionReader& tx, - const std::vector& outputs, const std::vector& globalIdxs); + void processTransaction(const TransactionBlockInfo& blockInfo, const ITransactionReader& tx, const PreprocessInfo& info); + void processOutputs(const TransactionBlockInfo& blockInfo, TransfersSubscription& sub, const ITransactionReader& tx, + const std::vector& outputs, const std::vector& globalIdxs, bool& contains, bool& updated); std::error_code getGlobalIndices(const Crypto::Hash& transactionHash, std::vector& outsGlobalIndices); @@ -67,6 +71,7 @@ private: // map { spend public key -> subscription } std::unordered_map> m_subscriptions; std::unordered_set m_spendKeys; + std::unordered_set m_poolTxs; INode& m_node; const CryptoNote::Currency& m_currency; diff --git a/src/Transfers/TransfersContainer.cpp b/src/Transfers/TransfersContainer.cpp index 54725b54..4ebf9f23 100644 --- a/src/Transfers/TransfersContainer.cpp +++ b/src/Transfers/TransfersContainer.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -243,11 +243,11 @@ bool TransfersContainer::addTransactionOutputs(const TransactionBlockInfo& block assert(result.second); } else { if (info.type == TransactionTypes::OutputType::Multisignature) { - SpentOutputDescriptor descriptor(transfer); - if (m_availableTransfers.get().count(descriptor) > 0 || - m_spentTransfers.get().count(descriptor) > 0) { - throw std::runtime_error("Transfer already exists"); - } + SpentOutputDescriptor descriptor(transfer); + if (m_availableTransfers.get().count(descriptor) > 0 || + m_spentTransfers.get().count(descriptor) > 0) { + throw std::runtime_error("Transfer already exists"); + } } auto result = m_availableTransfers.emplace(std::move(info)); @@ -328,10 +328,10 @@ bool TransfersContainer::addTransactionInputs(const TransactionBlockInfo& block, outputDescriptorIndex.erase(availableOutputIt); inputsAdded = true; - } + } } else { assert(inputType == TransactionTypes::InputType::Generating); - } + } } return inputsAdded; @@ -348,7 +348,7 @@ bool TransfersContainer::deleteUnconfirmedTransaction(const Hash& transactionHas } else { deleteTransactionTransfers(it->transactionHash); m_transactions.erase(it); - return true; + return true; } } @@ -388,12 +388,12 @@ bool TransfersContainer::markTransactionConfirmed(const TransactionBlockInfo& bl transfer.globalOutputIndex = globalIndices[transfer.outputInTransaction]; if (transfer.type == TransactionTypes::OutputType::Multisignature) { - SpentOutputDescriptor descriptor(transfer); - if (m_availableTransfers.get().count(descriptor) > 0 || - m_spentTransfers.get().count(descriptor) > 0) { - // This exception breaks TransfersContainer consistency - throw std::runtime_error("Transfer already exists"); - } + SpentOutputDescriptor descriptor(transfer); + if (m_availableTransfers.get().count(descriptor) > 0 || + m_spentTransfers.get().count(descriptor) > 0) { + // This exception breaks TransfersContainer consistency + throw std::runtime_error("Transfer already exists"); + } } auto result = m_availableTransfers.emplace(std::move(transfer)); @@ -404,7 +404,7 @@ bool TransfersContainer::markTransactionConfirmed(const TransactionBlockInfo& bl if (transfer.type == TransactionTypes::OutputType::Key) { updateTransfersVisibility(transfer.keyImage); - } + } } auto& spendingTransactionIndex = m_spentTransfers.get(); @@ -417,7 +417,7 @@ bool TransfersContainer::markTransactionConfirmed(const TransactionBlockInfo& bl spendingTransactionIndex.replace(transferIt, transfer); } - return true; + return true; } /** @@ -459,7 +459,7 @@ void TransfersContainer::deleteTransactionTransfers(const Hash& transactionHash) updateTransfersVisibility(keyImage); } else { it = transactionTransfersIndex.erase(it); - } + } } } @@ -630,7 +630,7 @@ void TransfersContainer::getOutputs(std::vector& t } } -bool TransfersContainer::getTransactionInformation(const Hash& transactionHash, TransactionInformation& info, int64_t& txBalance) const { +bool TransfersContainer::getTransactionInformation(const Hash& transactionHash, TransactionInformation& info, uint64_t* amountIn, uint64_t* amountOut) const { std::lock_guard lk(m_mutex); auto it = m_transactions.find(transactionHash); if (it == m_transactions.end()) { @@ -639,32 +639,35 @@ bool TransfersContainer::getTransactionInformation(const Hash& transactionHash, info = *it; - int64_t amountOut = 0; - if (info.blockHeight == WALLET_LEGACY_UNCONFIRMED_TRANSACTION_HEIGHT) { - auto unconfirmedOutputsRange = m_unconfirmedTransfers.get().equal_range(transactionHash); - for (auto it = unconfirmedOutputsRange.first; it != unconfirmedOutputsRange.second; ++it) { - amountOut += static_cast(it->amount); - } - } else { - auto availableOutputsRange = m_availableTransfers.get().equal_range(transactionHash); - for (auto it = availableOutputsRange.first; it != availableOutputsRange.second; ++it) { - amountOut += static_cast(it->amount); - } + if (amountOut != nullptr) { + *amountOut = 0; - auto spentOutputsRange = m_spentTransfers.get().equal_range(transactionHash); - for (auto it = spentOutputsRange.first; it != spentOutputsRange.second; ++it) { - amountOut += static_cast(it->amount); + if (info.blockHeight == WALLET_LEGACY_UNCONFIRMED_TRANSACTION_HEIGHT) { + auto unconfirmedOutputsRange = m_unconfirmedTransfers.get().equal_range(transactionHash); + for (auto it = unconfirmedOutputsRange.first; it != unconfirmedOutputsRange.second; ++it) { + *amountOut += it->amount; + } + } else { + auto availableOutputsRange = m_availableTransfers.get().equal_range(transactionHash); + for (auto it = availableOutputsRange.first; it != availableOutputsRange.second; ++it) { + *amountOut += it->amount; + } + + auto spentOutputsRange = m_spentTransfers.get().equal_range(transactionHash); + for (auto it = spentOutputsRange.first; it != spentOutputsRange.second; ++it) { + *amountOut += it->amount; + } } } - int64_t amountIn = 0; - auto rangeInputs = m_spentTransfers.get().equal_range(transactionHash); - for (auto it = rangeInputs.first; it != rangeInputs.second; ++it) { - amountIn += static_cast(it->amount); + if (amountIn != nullptr) { + *amountIn = 0; + auto rangeInputs = m_spentTransfers.get().equal_range(transactionHash); + for (auto it = rangeInputs.first; it != rangeInputs.second; ++it) { + *amountIn += it->amount; + } } - txBalance = amountOut - amountIn; - return true; } diff --git a/src/Transfers/TransfersContainer.h b/src/Transfers/TransfersContainer.h index 2f25fda2..096af1ad 100644 --- a/src/Transfers/TransfersContainer.h +++ b/src/Transfers/TransfersContainer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -152,7 +152,8 @@ public: virtual size_t transactionsCount() const override; virtual uint64_t balance(uint32_t flags) const override; virtual void getOutputs(std::vector& transfers, uint32_t flags) const override; - virtual bool getTransactionInformation(const Crypto::Hash& transactionHash, TransactionInformation& info, int64_t& txBalance) const override; + virtual bool getTransactionInformation(const Crypto::Hash& transactionHash, TransactionInformation& info, + uint64_t* amountIn = nullptr, uint64_t* amountOut = nullptr) const override; virtual std::vector getTransactionOutputs(const Crypto::Hash& transactionHash, uint32_t flags) const override; //only type flags are feasible for this function virtual std::vector getTransactionInputs(const Crypto::Hash& transactionHash, uint32_t flags) const override; diff --git a/src/Transfers/TransfersSubscription.cpp b/src/Transfers/TransfersSubscription.cpp index e2e2cdfb..1243d469 100644 --- a/src/Transfers/TransfersSubscription.cpp +++ b/src/Transfers/TransfersSubscription.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -39,12 +39,14 @@ const AccountKeys& TransfersSubscription::getKeys() const { return subscription.keys; } -void TransfersSubscription::addTransaction(const TransactionBlockInfo& blockInfo, const ITransactionReader& tx, +bool TransfersSubscription::addTransaction(const TransactionBlockInfo& blockInfo, const ITransactionReader& tx, const std::vector& transfersList) { bool added = transfers.addTransaction(blockInfo, tx, transfersList); if (added) { m_observerManager.notify(&ITransfersObserver::onTransactionUpdated, this, tx.getTransactionHash()); } + + return added; } AccountPublicAddress TransfersSubscription::getAddress() { @@ -56,8 +58,9 @@ ITransfersContainer& TransfersSubscription::getContainer() { } void TransfersSubscription::deleteUnconfirmedTransaction(const Hash& transactionHash) { - transfers.deleteUnconfirmedTransaction(transactionHash); - m_observerManager.notify(&ITransfersObserver::onTransactionDeleted, this, transactionHash); + if (transfers.deleteUnconfirmedTransaction(transactionHash)) { + m_observerManager.notify(&ITransfersObserver::onTransactionDeleted, this, transactionHash); + } } void TransfersSubscription::markTransactionConfirmed(const TransactionBlockInfo& block, const Hash& transactionHash, diff --git a/src/Transfers/TransfersSubscription.h b/src/Transfers/TransfersSubscription.h index 0af99f0d..ce29dc0d 100644 --- a/src/Transfers/TransfersSubscription.h +++ b/src/Transfers/TransfersSubscription.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -19,7 +19,7 @@ public: void onError(const std::error_code& ec, uint32_t height); bool advanceHeight(uint32_t height); const AccountKeys& getKeys() const; - void addTransaction(const TransactionBlockInfo& blockInfo, const ITransactionReader& tx, + bool addTransaction(const TransactionBlockInfo& blockInfo, const ITransactionReader& tx, const std::vector& transfers); void deleteUnconfirmedTransaction(const Crypto::Hash& transactionHash); diff --git a/src/Transfers/TransfersSynchronizer.cpp b/src/Transfers/TransfersSynchronizer.cpp index 5f1afb04..6579dcb9 100644 --- a/src/Transfers/TransfersSynchronizer.cpp +++ b/src/Transfers/TransfersSynchronizer.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -28,13 +28,21 @@ TransfersSyncronizer::~TransfersSyncronizer() { } } +void TransfersSyncronizer::initTransactionPool(const std::unordered_set& uncommitedTransactions) { + for (auto it = m_consumers.begin(); it != m_consumers.end(); ++it) { + it->second->initTransactionPool(uncommitedTransactions); + } +} + ITransfersSubscription& TransfersSyncronizer::addSubscription(const AccountSubscription& acc) { auto it = m_consumers.find(acc.keys.address.viewPublicKey); if (it == m_consumers.end()) { std::unique_ptr consumer( new TransfersConsumer(m_currency, m_node, acc.keys.viewSecretKey)); + m_sync.addConsumer(consumer.get()); + consumer->addObserver(this); it = m_consumers.insert(std::make_pair(acc.keys.address.viewPublicKey, std::move(consumer))).first; } @@ -49,6 +57,8 @@ bool TransfersSyncronizer::removeSubscription(const AccountPublicAddress& acc) { if (it->second->removeSubscription(acc)) { m_sync.removeConsumer(it->second.get()); m_consumers.erase(it); + + m_subscribers.erase(acc.viewPublicKey); } return true; @@ -62,7 +72,68 @@ void TransfersSyncronizer::getSubscriptions(std::vector& s ITransfersSubscription* TransfersSyncronizer::getSubscription(const AccountPublicAddress& acc) { auto it = m_consumers.find(acc.viewPublicKey); - return (it == m_consumers.end()) ? 0 : it->second->getSubscription(acc); + return (it == m_consumers.end()) ? nullptr : it->second->getSubscription(acc); +} + +std::vector TransfersSyncronizer::getViewKeyKnownBlocks(const Crypto::PublicKey& publicViewKey) { + auto it = m_consumers.find(publicViewKey); + if (it == m_consumers.end()) { + throw std::invalid_argument("Consumer not found"); + } + + return m_sync.getConsumerKnownBlocks(*it->second); +} + +void TransfersSyncronizer::onBlocksAdded(IBlockchainConsumer* consumer, const std::vector& blockHashes) { + auto it = findSubscriberForConsumer(consumer); + if (it != m_subscribers.end()) { + it->second->notify(&ITransfersSynchronizerObserver::onBlocksAdded, it->first, blockHashes); + } +} + +void TransfersSyncronizer::onBlockchainDetach(IBlockchainConsumer* consumer, uint32_t blockIndex) { + auto it = findSubscriberForConsumer(consumer); + if (it != m_subscribers.end()) { + it->second->notify(&ITransfersSynchronizerObserver::onBlockchainDetach, it->first, blockIndex); + } +} + +void TransfersSyncronizer::onTransactionDeleteBegin(IBlockchainConsumer* consumer, Crypto::Hash transactionHash) { + auto it = findSubscriberForConsumer(consumer); + if (it != m_subscribers.end()) { + it->second->notify(&ITransfersSynchronizerObserver::onTransactionDeleteBegin, it->first, transactionHash); + } +} + +void TransfersSyncronizer::onTransactionDeleteEnd(IBlockchainConsumer* consumer, Crypto::Hash transactionHash) { + auto it = findSubscriberForConsumer(consumer); + if (it != m_subscribers.end()) { + it->second->notify(&ITransfersSynchronizerObserver::onTransactionDeleteEnd, it->first, transactionHash); + } +} + +void TransfersSyncronizer::onTransactionUpdated(IBlockchainConsumer* consumer, const Crypto::Hash& transactionHash, + const std::vector& containers) { + + auto it = findSubscriberForConsumer(consumer); + if (it != m_subscribers.end()) { + it->second->notify(&ITransfersSynchronizerObserver::onTransactionUpdated, it->first, transactionHash, containers); + } +} + +void TransfersSyncronizer::subscribeConsumerNotifications(const Crypto::PublicKey& viewPublicKey, ITransfersSynchronizerObserver* observer) { + auto it = m_subscribers.find(viewPublicKey); + if (it != m_subscribers.end()) { + it->second->add(observer); + return; + } + + auto insertedIt = m_subscribers.emplace(viewPublicKey, std::unique_ptr(new SubscribersNotifier())).first; + insertedIt->second->add(observer); +} + +void TransfersSyncronizer::unsubscribeConsumerNotifications(const Crypto::PublicKey& viewPublicKey, ITransfersSynchronizerObserver* observer) { + m_subscribers.at(viewPublicKey)->remove(observer); } void TransfersSyncronizer::save(std::ostream& os) { @@ -220,4 +291,30 @@ void TransfersSyncronizer::load(std::istream& is) { } +bool TransfersSyncronizer::findViewKeyForConsumer(IBlockchainConsumer* consumer, Crypto::PublicKey& viewKey) const { + //since we have only couple of consumers linear complexity is fine + auto it = std::find_if(m_consumers.begin(), m_consumers.end(), [consumer] (const ConsumersContainer::value_type& subscription) { + return subscription.second.get() == consumer; + }); + + if (it == m_consumers.end()) { + return false; + } + + viewKey = it->first; + return true; +} + +TransfersSyncronizer::SubscribersContainer::const_iterator TransfersSyncronizer::findSubscriberForConsumer(IBlockchainConsumer* consumer) const { + Crypto::PublicKey viewKey; + if (findViewKeyForConsumer(consumer, viewKey)) { + auto it = m_subscribers.find(viewKey); + if (it != m_subscribers.end()) { + return it; + } + } + + return m_subscribers.end(); +} + } diff --git a/src/Transfers/TransfersSynchronizer.h b/src/Transfers/TransfersSynchronizer.h index 9bc740c1..fe34cf76 100644 --- a/src/Transfers/TransfersSynchronizer.h +++ b/src/Transfers/TransfersSynchronizer.h @@ -1,9 +1,10 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #pragma once +#include "Common/ObserverManager.h" #include "ITransfersSynchronizer.h" #include "IBlockchainSynchronizer.h" #include "TypeHelpers.h" @@ -21,31 +22,50 @@ namespace CryptoNote { class TransfersConsumer; class INode; -class TransfersSyncronizer : public ITransfersSynchronizer { +class TransfersSyncronizer : public ITransfersSynchronizer, public IBlockchainConsumerObserver { public: - TransfersSyncronizer(const CryptoNote::Currency& currency, IBlockchainSynchronizer& sync, INode& node); - ~TransfersSyncronizer(); + virtual ~TransfersSyncronizer(); + + void initTransactionPool(const std::unordered_set& uncommitedTransactions); // ITransfersSynchronizer virtual ITransfersSubscription& addSubscription(const AccountSubscription& acc) override; virtual bool removeSubscription(const AccountPublicAddress& acc) override; virtual void getSubscriptions(std::vector& subscriptions) override; virtual ITransfersSubscription* getSubscription(const AccountPublicAddress& acc) override; + virtual std::vector getViewKeyKnownBlocks(const Crypto::PublicKey& publicViewKey) override; + + void subscribeConsumerNotifications(const Crypto::PublicKey& viewPublicKey, ITransfersSynchronizerObserver* observer); + void unsubscribeConsumerNotifications(const Crypto::PublicKey& viewPublicKey, ITransfersSynchronizerObserver* observer); // IStreamSerializable virtual void save(std::ostream& os) override; virtual void load(std::istream& in) override; private: - // map { view public key -> consumer } - std::unordered_map> m_consumers; + typedef std::unordered_map> ConsumersContainer; + ConsumersContainer m_consumers; + + typedef Tools::ObserverManager SubscribersNotifier; + typedef std::unordered_map> SubscribersContainer; + SubscribersContainer m_subscribers; // std::unordered_map> m_subscriptions; IBlockchainSynchronizer& m_sync; INode& m_node; const CryptoNote::Currency& m_currency; + + virtual void onBlocksAdded(IBlockchainConsumer* consumer, const std::vector& blockHashes) override; + virtual void onBlockchainDetach(IBlockchainConsumer* consumer, uint32_t blockIndex) override; + virtual void onTransactionDeleteBegin(IBlockchainConsumer* consumer, Crypto::Hash transactionHash) override; + virtual void onTransactionDeleteEnd(IBlockchainConsumer* consumer, Crypto::Hash transactionHash) override; + virtual void onTransactionUpdated(IBlockchainConsumer* consumer, const Crypto::Hash& transactionHash, + const std::vector& containers) override; + + bool findViewKeyForConsumer(IBlockchainConsumer* consumer, Crypto::PublicKey& viewKey) const; + SubscribersContainer::const_iterator findSubscriberForConsumer(IBlockchainConsumer* consumer) const; }; } diff --git a/src/Transfers/TypeHelpers.h b/src/Transfers/TypeHelpers.h index 31e59e39..ab9c8e78 100644 --- a/src/Transfers/TypeHelpers.h +++ b/src/Transfers/TypeHelpers.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Wallet/IFusionManager.h b/src/Wallet/IFusionManager.h index 763a07f1..56967ec3 100644 --- a/src/Wallet/IFusionManager.h +++ b/src/Wallet/IFusionManager.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Wallet/LegacyKeysImporter.cpp b/src/Wallet/LegacyKeysImporter.cpp index 46b7c357..12ca093d 100755 --- a/src/Wallet/LegacyKeysImporter.cpp +++ b/src/Wallet/LegacyKeysImporter.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Wallet/LegacyKeysImporter.h b/src/Wallet/LegacyKeysImporter.h index c3e6af07..e32f8022 100644 --- a/src/Wallet/LegacyKeysImporter.h +++ b/src/Wallet/LegacyKeysImporter.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Wallet/WalletAsyncContextCounter.cpp b/src/Wallet/WalletAsyncContextCounter.cpp index b4b3b183..e9aba186 100644 --- a/src/Wallet/WalletAsyncContextCounter.cpp +++ b/src/Wallet/WalletAsyncContextCounter.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Wallet/WalletAsyncContextCounter.h b/src/Wallet/WalletAsyncContextCounter.h index 9bf89375..d1de047c 100644 --- a/src/Wallet/WalletAsyncContextCounter.h +++ b/src/Wallet/WalletAsyncContextCounter.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Wallet/WalletErrors.cpp b/src/Wallet/WalletErrors.cpp index da86edd2..5e28da44 100644 --- a/src/Wallet/WalletErrors.cpp +++ b/src/Wallet/WalletErrors.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Wallet/WalletErrors.h b/src/Wallet/WalletErrors.h index 5d4ccd2a..f52677f1 100644 --- a/src/Wallet/WalletErrors.h +++ b/src/Wallet/WalletErrors.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -32,7 +32,12 @@ enum WalletErrorCodes { KEY_GENERATION_ERROR, INDEX_OUT_OF_RANGE, ADDRESS_ALREADY_EXISTS, - TRACKING_MODE + TRACKING_MODE, + WRONG_PARAMETERS, + OBJECT_NOT_FOUND, + WALLET_NOT_FOUND, + CHANGE_ADDRESS_REQUIRED, + CHANGE_ADDRESS_NOT_FOUND }; // custom category: @@ -40,20 +45,20 @@ class WalletErrorCategory : public std::error_category { public: static WalletErrorCategory INSTANCE; - virtual const char* name() const throw() { + virtual const char* name() const throw() override { return "WalletErrorCategory"; } - virtual std::error_condition default_error_condition(int ev) const throw() { + virtual std::error_condition default_error_condition(int ev) const throw() override { return std::error_condition(ev, *this); } - virtual std::string message(int ev) const { + virtual std::string message(int ev) const override { switch (ev) { case NOT_INITIALIZED: return "Object was not initialized"; case WRONG_PASSWORD: return "The password is wrong"; case ALREADY_INITIALIZED: return "The object is already initialized"; - case INTERNAL_WALLET_ERROR: return "Internal error occured"; + case INTERNAL_WALLET_ERROR: return "Internal error occurred"; case MIXIN_COUNT_TOO_BIG: return "MixIn count is too big"; case BAD_ADDRESS: return "Bad address"; case TRANSACTION_SIZE_TOO_BIG: return "Transaction size is too big"; @@ -70,6 +75,11 @@ public: case INDEX_OUT_OF_RANGE: return "Index is out of range"; case ADDRESS_ALREADY_EXISTS: return "Address already exists"; case TRACKING_MODE: return "The wallet is in tracking mode"; + case WRONG_PARAMETERS: return "Wrong parameters passed"; + case OBJECT_NOT_FOUND: return "Object not found"; + case WALLET_NOT_FOUND: return "Requested wallet not found"; + case CHANGE_ADDRESS_REQUIRED: return "Change address required"; + case CHANGE_ADDRESS_NOT_FOUND: return "Change address not found"; default: return "Unknown error"; } } @@ -85,3 +95,10 @@ private: inline std::error_code make_error_code(CryptoNote::error::WalletErrorCodes e) { return std::error_code(static_cast(e), CryptoNote::error::WalletErrorCategory::INSTANCE); } + +namespace std { + +template <> +struct is_error_code_enum: public true_type {}; + +} diff --git a/src/Wallet/WalletGreen.cpp b/src/Wallet/WalletGreen.cpp index 06dc02b1..4e10b3e8 100755 --- a/src/Wallet/WalletGreen.cpp +++ b/src/Wallet/WalletGreen.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -12,10 +12,13 @@ #include #include #include + #include +#include #include "ITransaction.h" +#include "Common/ScopeExit.h" #include "Common/ShuffleGenerator.h" #include "Common/StdInputStream.h" #include "Common/StdOutputStream.h" @@ -29,6 +32,7 @@ #include "Transfers/TransfersContainer.h" #include "WalletSerialization.h" #include "WalletErrors.h" +#include "WalletUtils.h" using namespace Common; using namespace Crypto; @@ -46,16 +50,24 @@ void parseAddressString(const std::string& string, const CryptoNote::Currency& c } } -bool validateAddress(const std::string& address, const CryptoNote::Currency& currency) { - CryptoNote::AccountPublicAddress ignore; - return currency.parseAccountAddressString(address, ignore); +void validateAddresses(const std::vector& addresses, const CryptoNote::Currency& currency) { + for (const auto& address: addresses) { + if (!CryptoNote::validateAddress(address, currency)) { + throw std::system_error(make_error_code(CryptoNote::error::BAD_ADDRESS)); + } + } } -void validateAddresses(const std::vector& destinations, const CryptoNote::Currency& currency) { - for (const auto& destination: destinations) { - if (!validateAddress(destination.address, currency)) { +void validateOrders(const std::vector& orders, const CryptoNote::Currency& currency) { + for (const auto& order: orders) { + if (!CryptoNote::validateAddress(order.address, currency)) { throw std::system_error(make_error_code(CryptoNote::error::BAD_ADDRESS)); } + + if (order.amount >= static_cast(std::numeric_limits::max())) { + throw std::system_error(make_error_code(CryptoNote::error::WRONG_AMOUNT), + "Order amount must not exceed " + std::to_string(std::numeric_limits::max())); + } } } @@ -140,6 +152,74 @@ size_t getTransactionSize(const ITransactionReader& transaction) { return transaction.getTransactionData().size(); } +std::vector convertOrdersToTransfers(const std::vector& orders) { + std::vector transfers; + transfers.reserve(orders.size()); + + for (const auto& order: orders) { + WalletTransfer transfer; + + if (order.amount > static_cast(std::numeric_limits::max())) { + throw std::system_error(make_error_code(CryptoNote::error::WRONG_AMOUNT), + "Order amount must not exceed " + std::to_string(std::numeric_limits::max())); + } + + transfer.type = WalletTransferType::USUAL; + transfer.address = order.address; + transfer.amount = static_cast(order.amount); + + transfers.emplace_back(std::move(transfer)); + } + + return transfers; +} + +uint64_t calculateDonationAmount(uint64_t freeAmount, uint64_t donationThreshold, uint64_t dustThreshold) { + std::vector decomposedAmounts; + decomposeAmount(freeAmount, dustThreshold, decomposedAmounts); + + std::sort(decomposedAmounts.begin(), decomposedAmounts.end(), std::greater()); + + uint64_t donationAmount = 0; + for (auto amount: decomposedAmounts) { + if (amount > donationThreshold - donationAmount) { + continue; + } + + donationAmount += amount; + } + + assert(donationAmount <= freeAmount); + return donationAmount; +} + +uint64_t pushDonationTransferIfPossible(const DonationSettings& donation, uint64_t freeAmount, uint64_t dustThreshold, std::vector& destinations) { + uint64_t donationAmount = 0; + if (!donation.address.empty() && donation.threshold != 0) { + if (donation.threshold > static_cast(std::numeric_limits::max())) { + throw std::system_error(make_error_code(error::WRONG_AMOUNT), + "Donation threshold must not exceed " + std::to_string(std::numeric_limits::max())); + } + + donationAmount = calculateDonationAmount(freeAmount, donation.threshold, dustThreshold); + if (donationAmount != 0) { + destinations.emplace_back(WalletTransfer {WalletTransferType::DONATION, donation.address, static_cast(donationAmount)}); + } + } + + return donationAmount; +} + +CryptoNote::AccountPublicAddress parseAccountAddressString(const std::string& addressString, const CryptoNote::Currency& currency) { + CryptoNote::AccountPublicAddress address; + + if (!currency.parseAccountAddressString(addressString, address)) { + throw std::system_error(make_error_code(CryptoNote::error::BAD_ADDRESS)); + } + + return address; +} + } namespace CryptoNote { @@ -148,10 +228,15 @@ WalletGreen::WalletGreen(System::Dispatcher& dispatcher, const Currency& currenc m_dispatcher(dispatcher), m_currency(currency), m_node(node), + m_stopped(false), + m_blockchainSynchronizerStarted(false), m_blockchainSynchronizer(node, currency.genesisBlockHash()), m_synchronizer(currency, m_blockchainSynchronizer, node), - m_eventOccured(m_dispatcher), + m_eventOccurred(m_dispatcher), m_readyEvent(m_dispatcher), + m_state(WalletState::NOT_INITIALIZED), + m_actualBalance(0), + m_pendingBalance(0), m_transactionSoftLockTime(transactionSoftLockTime) { m_upperTransactionSizeLimit = m_currency.blockGrantedFullRewardZone() * 2 - m_currency.minerTxBlobReservedSize(); @@ -191,7 +276,11 @@ void WalletGreen::shutdown() { } void WalletGreen::doShutdown() { - m_blockchainSynchronizer.stop(); + if (m_walletsContainer.size() != 0) { + m_synchronizer.unsubscribeConsumerNotifications(m_viewPublicKey, this); + } + + stopBlockchainSynchronizer(); m_blockchainSynchronizer.removeObserver(this); clearCaches(); @@ -208,14 +297,14 @@ void WalletGreen::clearCaches() { std::for_each(subscriptions.begin(), subscriptions.end(), [this] (const AccountPublicAddress& address) { m_synchronizer.removeSubscription(address); }); m_walletsContainer.clear(); - m_spentOutputs.clear(); m_unlockTransactionsJob.clear(); m_transactions.clear(); m_transfers.clear(); - m_change.clear(); + m_uncommitedTransactions.clear(); m_actualBalance = 0; m_pendingBalance = 0; m_fusionTxsCache.clear(); + m_blockchain.clear(); } void WalletGreen::initWithKeys(const Crypto::PublicKey& viewPublicKey, const Crypto::SecretKey& viewSecretKey, const std::string& password) { @@ -229,6 +318,9 @@ void WalletGreen::initWithKeys(const Crypto::PublicKey& viewPublicKey, const Cry m_viewSecretKey = viewSecretKey; m_password = password; + assert(m_blockchain.empty()); + m_blockchain.push_back(m_currency.genesisBlockHash()); + m_blockchainSynchronizer.addObserver(this); m_state = WalletState::INITIALIZED; @@ -238,18 +330,27 @@ void WalletGreen::save(std::ostream& destination, bool saveDetails, bool saveCac throwIfNotInitialized(); throwIfStopped(); - if (m_walletsContainer.get().size() != 0) { - m_blockchainSynchronizer.stop(); - } + stopBlockchainSynchronizer(); unsafeSave(destination, saveDetails, saveCache); - if (m_walletsContainer.get().size() != 0) { - m_blockchainSynchronizer.start(); - } + startBlockchainSynchronizer(); } void WalletGreen::unsafeSave(std::ostream& destination, bool saveDetails, bool saveCache) { + WalletTransactions transactions; + WalletTransfers transfers; + + if (saveDetails && !saveCache) { + filterOutTransactions(transactions, transfers, [] (const WalletTransaction& tx) { + return tx.state == WalletTransactionState::CREATED || tx.state == WalletTransactionState::DELETED; + }); + } else if (saveDetails) { + filterOutTransactions(transactions, transfers, [] (const WalletTransaction& tx) { + return tx.state == WalletTransactionState::DELETED; + }); + } + WalletSerializer s( *this, m_viewPublicKey, @@ -258,12 +359,11 @@ void WalletGreen::unsafeSave(std::ostream& destination, bool saveDetails, bool s m_pendingBalance, m_walletsContainer, m_synchronizer, - m_spentOutputs, m_unlockTransactionsJob, - m_change, - m_transactions, - m_transfers, - m_transactionSoftLockTime + transactions, + transfers, + m_transactionSoftLockTime, + m_uncommitedTransactions ); StdOutputStream output(destination); @@ -277,14 +377,18 @@ void WalletGreen::load(std::istream& source, const std::string& password) { throwIfStopped(); - if (m_walletsContainer.get().size() != 0) { - m_blockchainSynchronizer.stop(); - } + stopBlockchainSynchronizer(); unsafeLoad(source, password); + assert(m_blockchain.empty()); if (m_walletsContainer.get().size() != 0) { - m_blockchainSynchronizer.start(); + m_synchronizer.subscribeConsumerNotifications(m_viewPublicKey, this); + getViewKeyKnownBlocks(m_viewPublicKey); + + startBlockchainSynchronizer(); + } else { + m_blockchain.push_back(m_currency.genesisBlockHash()); } m_state = WalletState::INITIALIZED; @@ -299,12 +403,11 @@ void WalletGreen::unsafeLoad(std::istream& source, const std::string& password) m_pendingBalance, m_walletsContainer, m_synchronizer, - m_spentOutputs, m_unlockTransactionsJob, - m_change, m_transactions, m_transfers, - m_transactionSoftLockTime + m_transactionSoftLockTime, + m_uncommitedTransactions ); StdInputStream inputStream(source); @@ -337,7 +440,7 @@ std::string WalletGreen::getAddress(size_t index) const { throwIfStopped(); if (index >= m_walletsContainer.get().size()) { - throw std::system_error(std::make_error_code(std::errc::invalid_argument)); + throw std::system_error(make_error_code(std::errc::invalid_argument)); } const WalletRecord& wallet = m_walletsContainer.get()[index]; @@ -349,13 +452,27 @@ KeyPair WalletGreen::getAddressSpendKey(size_t index) const { throwIfStopped(); if (index >= m_walletsContainer.get().size()) { - throw std::system_error(std::make_error_code(std::errc::invalid_argument)); + throw std::system_error(make_error_code(std::errc::invalid_argument)); } const WalletRecord& wallet = m_walletsContainer.get()[index]; return {wallet.spendPublicKey, wallet.spendSecretKey}; } +KeyPair WalletGreen::getAddressSpendKey(const std::string& address) const { + throwIfNotInitialized(); + throwIfStopped(); + + CryptoNote::AccountPublicAddress pubAddr = parseAddress(address); + + auto it = m_walletsContainer.get().find(pubAddr.spendPublicKey); + if (it == m_walletsContainer.get().end()) { + throw std::system_error(make_error_code(error::OBJECT_NOT_FOUND)); + } + + return {it->spendPublicKey, it->spendSecretKey}; +} + KeyPair WalletGreen::getViewKey() const { throwIfNotInitialized(); throwIfStopped(); @@ -381,33 +498,44 @@ std::string WalletGreen::createAddress(const Crypto::SecretKey& spendSecretKey) } std::string WalletGreen::createAddress(const Crypto::PublicKey& spendPublicKey) { + if (!Crypto::check_key(spendPublicKey)) { + throw std::system_error(make_error_code(error::WRONG_PARAMETERS), "Wrong public key format"); + } + return doCreateAddress(spendPublicKey, NULL_SECRET_KEY, 0); } std::string WalletGreen::doCreateAddress(const Crypto::PublicKey& spendPublicKey, const Crypto::SecretKey& spendSecretKey, uint64_t creationTimestamp) { + assert(creationTimestamp <= std::numeric_limits::max() - m_currency.blockFutureTimeLimit()); + throwIfNotInitialized(); throwIfStopped(); - if (m_walletsContainer.get().size() != 0) { - m_blockchainSynchronizer.stop(); - } + stopBlockchainSynchronizer(); + std::string address; try { - addWallet(spendPublicKey, spendSecretKey, creationTimestamp); - } catch (std::exception&) { - if (m_walletsContainer.get().size() != 0) { - m_blockchainSynchronizer.start(); - } + address = addWallet(spendPublicKey, spendSecretKey, creationTimestamp); + auto currentTime = static_cast(time(nullptr)); + if (creationTimestamp + m_currency.blockFutureTimeLimit() < currentTime) { + std::string password = m_password; + std::stringstream ss; + unsafeSave(ss, true, false); + shutdown(); + load(ss, password); + } + } catch (std::exception&) { + startBlockchainSynchronizer(); throw; } - m_blockchainSynchronizer.start(); + startBlockchainSynchronizer(); - return m_currency.accountAddressAsString({ spendPublicKey, m_viewPublicKey }); + return address; } -void WalletGreen::addWallet(const Crypto::PublicKey& spendPublicKey, const Crypto::SecretKey& spendSecretKey, uint64_t creationTimestamp) { +std::string WalletGreen::addWallet(const Crypto::PublicKey& spendPublicKey, const Crypto::SecretKey& spendSecretKey, uint64_t creationTimestamp) { auto& index = m_walletsContainer.get(); auto trackingMode = getTrackingMode(); @@ -442,6 +570,13 @@ void WalletGreen::addWallet(const Crypto::PublicKey& spendPublicKey, const Crypt trSubscription.addObserver(this); index.insert(insertIt, std::move(wallet)); + + if (index.size() == 1) { + m_synchronizer.subscribeConsumerNotifications(m_viewPublicKey, this); + getViewKeyKnownBlocks(m_viewPublicKey); + } + + return m_currency.accountAddressAsString({ spendPublicKey, m_viewPublicKey }); } void WalletGreen::deleteAddress(const std::string& address) { @@ -452,21 +587,32 @@ void WalletGreen::deleteAddress(const std::string& address) { auto it = m_walletsContainer.get().find(pubAddr.spendPublicKey); if (it == m_walletsContainer.get().end()) { - throw std::system_error(std::make_error_code(std::errc::invalid_argument)); + throw std::system_error(make_error_code(error::OBJECT_NOT_FOUND)); } - m_blockchainSynchronizer.stop(); + stopBlockchainSynchronizer(); m_actualBalance -= it->actualBalance; m_pendingBalance -= it->pendingBalance; m_synchronizer.removeSubscription(pubAddr); - m_spentOutputs.get().erase(&(*it)); + deleteContainerFromUnlockTransactionJobs(it->container); + std::vector deletedTransactions; + std::vector updatedTransactions = deleteTransfersForAddress(address, deletedTransactions); + deleteFromUncommitedTransactions(deletedTransactions); + m_walletsContainer.get().erase(it); if (m_walletsContainer.get().size() != 0) { - m_blockchainSynchronizer.start(); + startBlockchainSynchronizer(); + } else { + m_blockchain.clear(); + m_blockchain.push_back(m_currency.genesisBlockHash()); + } + + for (auto transactionId: updatedTransactions) { + pushEvent(makeTransactionUpdatedEvent(transactionId)); } } @@ -522,7 +668,7 @@ size_t WalletGreen::getTransactionTransferCount(size_t transactionIndex) const { throwIfNotInitialized(); throwIfStopped(); - auto bounds = getTransactionTransfers(transactionIndex); + auto bounds = getTransactionTransfersRange(transactionIndex); return static_cast(std::distance(bounds.first, bounds.second)); } @@ -530,20 +676,16 @@ WalletTransfer WalletGreen::getTransactionTransfer(size_t transactionIndex, size throwIfNotInitialized(); throwIfStopped(); - auto bounds = getTransactionTransfers(transactionIndex); + auto bounds = getTransactionTransfersRange(transactionIndex); if (transferIndex >= static_cast(std::distance(bounds.first, bounds.second))) { - throw std::system_error(std::make_error_code(std::errc::invalid_argument)); + throw std::system_error(make_error_code(std::errc::invalid_argument)); } - auto it = bounds.first; - std::advance(it, transferIndex); - return it->second; + return std::next(bounds.first, transferIndex)->second; } -std::pair WalletGreen::getTransactionTransfers( - size_t transactionIndex) const { - +WalletGreen::TransfersRange WalletGreen::getTransactionTransfersRange(size_t transactionIndex) const { auto val = std::make_pair(transactionIndex, WalletTransfer()); auto bounds = std::equal_range(m_transfers.begin(), m_transfers.end(), val, [] (const TransactionTransferPair& a, const TransactionTransferPair& b) { @@ -553,88 +695,37 @@ std::pair Wall return bounds; } -size_t WalletGreen::transfer(const WalletTransfer& destination, - uint64_t fee, - uint64_t mixIn, - std::string const& extra, - uint64_t unlockTimestamp) -{ - std::vector destinations { destination }; - return transfer(destinations, fee, mixIn, extra, unlockTimestamp); +size_t WalletGreen::transfer(const TransactionParameters& transactionParameters) { + Tools::ScopeExit releaseContext([this] { + m_dispatcher.yield(); + }); + + System::EventLock lk(m_readyEvent); + + throwIfNotInitialized(); + throwIfTrackingMode(); + throwIfStopped(); + + return doTransfer(transactionParameters); } -size_t WalletGreen::transfer( - const std::vector& destinations, +void WalletGreen::prepareTransaction(std::vector&& wallets, + const std::vector& orders, uint64_t fee, uint64_t mixIn, const std::string& extra, - uint64_t unlockTimestamp) { + uint64_t unlockTimestamp, + const DonationSettings& donation, + const CryptoNote::AccountPublicAddress& changeDestination, + PreparedTransaction& preparedTransaction) { - System::EventLock lk(m_readyEvent); - - throwIfNotInitialized(); - throwIfStopped(); - throwIfTrackingMode(); - - return doTransfer(pickWalletsWithMoney(), destinations, fee, mixIn, extra, unlockTimestamp); -} - -size_t WalletGreen::transfer( - const std::string& sourceAddress, - const WalletTransfer& destination, - uint64_t fee, - uint64_t mixIn, - std::string const& extra, - uint64_t unlockTimestamp) { - std::vector destinations { destination }; - return transfer(sourceAddress, destinations, fee, mixIn, extra, unlockTimestamp); -} - -size_t WalletGreen::transfer( - const std::string& sourceAddress, - const std::vector& destinations, - uint64_t fee, - uint64_t mixIn, - const std::string& extra, - uint64_t unlockTimestamp) { - System::EventLock lk(m_readyEvent); - - throwIfNotInitialized(); - throwIfStopped(); - throwIfTrackingMode(); - - WalletOuts wallet = pickWallet(sourceAddress); - std::vector wallets; - - if (!wallet.outs.empty()) { - wallets.push_back(wallet); - } - - return doTransfer(std::move(wallets), destinations, fee, mixIn, extra, unlockTimestamp); -} - -size_t WalletGreen::doTransfer(std::vector&& wallets, - const std::vector& destinations, - uint64_t fee, - uint64_t mixIn, - const std::string& extra, - uint64_t unlockTimestamp) { - if (destinations.empty()) { - throw std::system_error(make_error_code(error::ZERO_DESTINATION)); - } - - if (fee < m_currency.minimumFee()) { - throw std::system_error(make_error_code(error::FEE_TOO_SMALL)); - } - - validateAddresses(destinations, m_currency); - - uint64_t neededMoney = countNeededMoney(destinations, fee); + preparedTransaction.destinations = convertOrdersToTransfers(orders); + preparedTransaction.neededMoney = countNeededMoney(preparedTransaction.destinations, fee); std::vector selectedTransfers; - uint64_t foundMoney = selectTransfers(neededMoney, mixIn == 0, m_currency.defaultDustThreshold(), std::move(wallets), selectedTransfers); + uint64_t foundMoney = selectTransfers(preparedTransaction.neededMoney, mixIn == 0, m_currency.defaultDustThreshold(), std::move(wallets), selectedTransfers); - if (foundMoney < neededMoney) { + if (foundMoney < preparedTransaction.neededMoney) { throw std::system_error(make_error_code(error::WRONG_AMOUNT), "Not enough money"); } @@ -648,115 +739,277 @@ size_t WalletGreen::doTransfer(std::vector&& wallets, std::vector keysInfo; prepareInputs(selectedTransfers, mixinResult, mixIn, keysInfo); - WalletTransfer changeDestination; - changeDestination.address = m_currency.accountAddressAsString({ m_walletsContainer.get()[0].spendPublicKey, m_viewPublicKey }); - changeDestination.amount = foundMoney - neededMoney; + uint64_t donationAmount = pushDonationTransferIfPossible(donation, foundMoney - preparedTransaction.neededMoney, m_currency.defaultDustThreshold(), preparedTransaction.destinations); + preparedTransaction.changeAmount = foundMoney - preparedTransaction.neededMoney - donationAmount; - std::vector decomposedOutputs; - splitDestinations(destinations, changeDestination, m_currency.defaultDustThreshold(), m_currency, decomposedOutputs); + std::vector decomposedOutputs = splitDestinations(preparedTransaction.destinations, m_currency.defaultDustThreshold(), m_currency); + if (preparedTransaction.changeAmount != 0) { + WalletTransfer changeTransfer; + changeTransfer.type = WalletTransferType::CHANGE; + changeTransfer.address = m_currency.accountAddressAsString(changeDestination); + changeTransfer.amount = static_cast(preparedTransaction.changeAmount); + preparedTransaction.destinations.emplace_back(std::move(changeTransfer)); - std::unique_ptr tx = makeTransaction(decomposedOutputs, keysInfo, extra, unlockTimestamp); + auto splittedChange = splitAmount(preparedTransaction.changeAmount, changeDestination, m_currency.defaultDustThreshold()); + decomposedOutputs.emplace_back(std::move(splittedChange)); + } - size_t txId = insertOutgoingTransaction(tx->getTransactionHash(), -static_cast(neededMoney), fee, tx->getExtra(), unlockTimestamp); - pushBackOutgoingTransfers(txId, destinations); - m_fusionTxsCache.emplace(txId, false); + preparedTransaction.transaction = makeTransaction(decomposedOutputs, keysInfo, extra, unlockTimestamp); +} - markOutputsSpent(tx->getTransactionHash(), selectedTransfers); +void WalletGreen::validateTransactionParameters(const TransactionParameters& transactionParameters) { + if (transactionParameters.destinations.empty()) { + throw std::system_error(make_error_code(error::ZERO_DESTINATION)); + } - try { - sendTransaction(tx.get()); - } catch (std::exception&) { - deleteSpentOutputs(tx->getTransactionHash()); - pushEvent(makeTransactionCreatedEvent(txId)); - throw; + if (transactionParameters.fee < m_currency.minimumFee()) { + throw std::system_error(make_error_code(error::FEE_TOO_SMALL)); + } + + if (transactionParameters.donation.address.empty() != (transactionParameters.donation.threshold == 0)) { + throw std::system_error(make_error_code(error::WRONG_PARAMETERS), "DonationSettings must have both address and threshold parameters filled"); + } + + validateAddresses(transactionParameters.sourceAddresses, m_currency); + + auto badAddr = std::find_if(transactionParameters.sourceAddresses.begin(), transactionParameters.sourceAddresses.end(), [this](const std::string& addr) { + return !isMyAddress(addr); + }); + if (badAddr != transactionParameters.sourceAddresses.end()) { + throw std::system_error(make_error_code(error::BAD_ADDRESS), "Source address must belong to current container: " + *badAddr); + } + + validateOrders(transactionParameters.destinations, m_currency); + + if (transactionParameters.changeDestination.empty()) { + if (transactionParameters.sourceAddresses.size() > 1) { + throw std::system_error(make_error_code(error::CHANGE_ADDRESS_REQUIRED), "Set change destination address"); + } else if (transactionParameters.sourceAddresses.empty() && m_walletsContainer.size() > 1) { + throw std::system_error(make_error_code(error::CHANGE_ADDRESS_REQUIRED), "Set change destination address"); + } + } else { + if (!CryptoNote::validateAddress(transactionParameters.changeDestination, m_currency)) { + throw std::system_error(make_error_code(CryptoNote::error::BAD_ADDRESS), "Wrong change address"); + } + + if (!isMyAddress(transactionParameters.changeDestination)) { + throw std::system_error(make_error_code(error::CHANGE_ADDRESS_NOT_FOUND), "Change destination address not found in current container"); + } + } +} + +size_t WalletGreen::doTransfer(const TransactionParameters& transactionParameters) { + validateTransactionParameters(transactionParameters); + CryptoNote::AccountPublicAddress changeDestination = getChangeDestination(transactionParameters.changeDestination, transactionParameters.sourceAddresses); + + std::vector wallets; + if (!transactionParameters.sourceAddresses.empty()) { + wallets = pickWallets(transactionParameters.sourceAddresses); + } else { + wallets = pickWalletsWithMoney(); + } + + PreparedTransaction preparedTransaction; + prepareTransaction(std::move(wallets), + transactionParameters.destinations, + transactionParameters.fee, + transactionParameters.mixIn, + transactionParameters.extra, + transactionParameters.unlockTimestamp, + transactionParameters.donation, + changeDestination, + preparedTransaction); + + return validateSaveAndSendTransaction(*preparedTransaction.transaction, preparedTransaction.destinations, false, true); +} + +size_t WalletGreen::makeTransaction(const TransactionParameters& sendingTransaction) { + throwIfNotInitialized(); + throwIfTrackingMode(); + throwIfStopped(); + + Tools::ScopeExit releaseContext([this] { + m_dispatcher.yield(); + }); + + System::EventLock lk(m_readyEvent); + + validateTransactionParameters(sendingTransaction); + CryptoNote::AccountPublicAddress changeDestination = getChangeDestination(sendingTransaction.changeDestination, sendingTransaction.sourceAddresses); + + std::vector wallets; + if (!sendingTransaction.sourceAddresses.empty()) { + wallets = pickWallets(sendingTransaction.sourceAddresses); + } else { + wallets = pickWalletsWithMoney(); + } + + PreparedTransaction preparedTransaction; + prepareTransaction( + std::move(wallets), + sendingTransaction.destinations, + sendingTransaction.fee, + sendingTransaction.mixIn, + sendingTransaction.extra, + sendingTransaction.unlockTimestamp, + sendingTransaction.donation, + changeDestination, + preparedTransaction); + + return validateSaveAndSendTransaction(*preparedTransaction.transaction, preparedTransaction.destinations, false, false); +} + +void WalletGreen::commitTransaction(size_t transactionId) { + System::EventLock lk(m_readyEvent); + + throwIfNotInitialized(); + throwIfStopped(); + throwIfTrackingMode(); + + if (transactionId >= m_transactions.size()) { + throw std::system_error(make_error_code(CryptoNote::error::INDEX_OUT_OF_RANGE)); + } + + auto txIt = std::next(m_transactions.get().begin(), transactionId); + if (m_uncommitedTransactions.count(transactionId) == 0 || txIt->state != WalletTransactionState::CREATED) { + throw std::system_error(make_error_code(error::TX_TRANSFER_IMPOSSIBLE)); + } + + System::Event completion(m_dispatcher); + std::error_code ec; + + m_node.relayTransaction(m_uncommitedTransactions[transactionId], [&ec, &completion, this](std::error_code error) { + ec = error; + this->m_dispatcher.remoteSpawn(std::bind(asyncRequestCompletion, std::ref(completion))); + }); + completion.wait(); + + if (!ec) { + updateTransactionStateAndPushEvent(transactionId, WalletTransactionState::SUCCEEDED); + m_uncommitedTransactions.erase(transactionId); + } else { + throw std::system_error(ec); + } +} + +void WalletGreen::rollbackUncommitedTransaction(size_t transactionId) { + Tools::ScopeExit releaseContext([this] { + m_dispatcher.yield(); + }); + + System::EventLock lk(m_readyEvent); + + throwIfNotInitialized(); + throwIfStopped(); + throwIfTrackingMode(); + + if (transactionId >= m_transactions.size()) { + throw std::system_error(make_error_code(CryptoNote::error::INDEX_OUT_OF_RANGE)); } auto txIt = m_transactions.get().begin(); - std::advance(txIt, txId); - m_transactions.get().modify(txIt, - [] (WalletTransaction& tx) { tx.state = WalletTransactionState::SUCCEEDED; }); + std::advance(txIt, transactionId); + if (m_uncommitedTransactions.count(transactionId) == 0 || txIt->state != WalletTransactionState::CREATED) { + throw std::system_error(make_error_code(error::TX_CANCEL_IMPOSSIBLE)); + } - m_change[tx->getTransactionHash()] = changeDestination.amount; - updateUsedWalletsBalances(selectedTransfers); - - pushEvent(makeTransactionCreatedEvent(txId)); - - return txId; + removeUnconfirmedTransaction(getObjectHash(m_uncommitedTransactions[transactionId])); + m_uncommitedTransactions.erase(transactionId); } -void WalletGreen::pushBackOutgoingTransfers(size_t txId, const std::vector &destinations) { +void WalletGreen::pushBackOutgoingTransfers(size_t txId, const std::vector& destinations) { + for (const auto& dest: destinations) { - WalletTransfer d { dest.address, -dest.amount }; - m_transfers.push_back(std::make_pair(txId, d)); + WalletTransfer d; + d.type = dest.type; + d.address = dest.address; + d.amount = dest.amount; + + m_transfers.emplace_back(txId, std::move(d)); } } -size_t WalletGreen::insertOutgoingTransaction(const Hash& transactionHash, int64_t totalAmount, uint64_t fee, const BinaryArray& extra, uint64_t unlockTimestamp) { +size_t WalletGreen::insertOutgoingTransactionAndPushEvent(const Hash& transactionHash, uint64_t fee, const BinaryArray& extra, uint64_t unlockTimestamp) { WalletTransaction insertTx; - insertTx.state = WalletTransactionState::FAILED; + insertTx.state = WalletTransactionState::CREATED; insertTx.creationTime = static_cast(time(nullptr)); insertTx.unlockTime = unlockTimestamp; insertTx.blockHeight = CryptoNote::WALLET_UNCONFIRMED_TRANSACTION_HEIGHT; insertTx.extra.assign(reinterpret_cast(extra.data()), extra.size()); insertTx.fee = fee; insertTx.hash = transactionHash; - insertTx.totalAmount = totalAmount; + insertTx.totalAmount = 0; // 0 until transactionHandlingEnd() is called insertTx.timestamp = 0; //0 until included in a block insertTx.isBase = false; size_t txId = m_transactions.get().size(); m_transactions.get().push_back(std::move(insertTx)); + pushEvent(makeTransactionCreatedEvent(txId)); + return txId; } -bool WalletGreen::transactionExists(const Hash& hash) { - auto& hashIndex = m_transactions.get(); - auto it = hashIndex.find(hash); - return it != hashIndex.end(); -} +void WalletGreen::updateTransactionStateAndPushEvent(size_t transactionId, WalletTransactionState state) { + auto it = std::next(m_transactions.get().begin(), transactionId); -bool WalletGreen::updateWalletTransactionInfo(const Hash& hash, const CryptoNote::TransactionInformation& info) { - auto& hashIndex = m_transactions.get(); - - bool updated = false; - auto it = hashIndex.find(hash); - if (it != hashIndex.end()) { - bool r = hashIndex.modify(it, [&info, &updated] (WalletTransaction& transaction) { - if (transaction.blockHeight != info.blockHeight) { - transaction.blockHeight = info.blockHeight; - updated = true; - } - - if (transaction.timestamp != info.timestamp) { - transaction.timestamp = info.timestamp; - updated = true; - } - - if (transaction.state != WalletTransactionState::SUCCEEDED) { - //transaction may be deleted first then added again - transaction.state = WalletTransactionState::SUCCEEDED; - 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; - updated = true; - } + if (it->state != state) { + m_transactions.get().modify(it, [state](WalletTransaction& tx) { + tx.state = state; }); - assert(r); - return updated; + pushEvent(makeTransactionUpdatedEvent(transactionId)); } +} - throw std::system_error(make_error_code(std::errc::invalid_argument)); +bool WalletGreen::updateWalletTransactionInfo(size_t transactionId, const CryptoNote::TransactionInformation& info, int64_t totalAmount) { + auto& txIdIndex = m_transactions.get(); + assert(transactionId < txIdIndex.size()); + auto it = std::next(txIdIndex.begin(), transactionId); + + bool updated = false; + bool r = txIdIndex.modify(it, [&info, totalAmount, &updated](WalletTransaction& transaction) { + if (transaction.blockHeight != info.blockHeight) { + transaction.blockHeight = info.blockHeight; + updated = true; + } + + if (transaction.timestamp != info.timestamp) { + transaction.timestamp = info.timestamp; + updated = true; + } + + bool isSucceeded = transaction.state == WalletTransactionState::SUCCEEDED; + // If transaction was sent to daemon, it can not have CREATED and FAILED states, its state can be SUCCEEDED, CANCELLED or DELETED + bool wasSent = transaction.state != WalletTransactionState::CREATED && transaction.state != WalletTransactionState::FAILED; + bool isConfirmed = transaction.blockHeight != WALLET_UNCONFIRMED_TRANSACTION_HEIGHT; + if (!isSucceeded && (wasSent || isConfirmed)) { + //transaction may be deleted first then added again + transaction.state = WalletTransactionState::SUCCEEDED; + updated = true; + } + + if (transaction.totalAmount != totalAmount) { + transaction.totalAmount = totalAmount; + 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; + updated = true; + } + }); + + assert(r); + + return updated; } size_t WalletGreen::insertBlockchainTransaction(const TransactionInformation& info, int64_t txBalance) { @@ -767,24 +1020,218 @@ size_t WalletGreen::insertBlockchainTransaction(const TransactionInformation& in tx.timestamp = info.timestamp; tx.blockHeight = info.blockHeight; tx.hash = info.transactionHash; - tx.fee = info.totalAmountIn - info.totalAmountOut; + tx.isBase = info.totalAmountIn == 0; + if (tx.isBase) { + tx.fee = 0; + } else { + tx.fee = info.totalAmountIn - info.totalAmountOut; + } + tx.unlockTime = info.unlockTime; tx.extra.assign(reinterpret_cast(info.extra.data()), info.extra.size()); tx.totalAmount = txBalance; tx.creationTime = info.timestamp; - tx.isBase = info.totalAmountIn == 0; + size_t txId = index.size(); index.push_back(std::move(tx)); - return index.size() - 1; + + return txId; } -void WalletGreen::insertIncomingTransfer(size_t txId, const std::string& address, int64_t amount) { - auto it = std::upper_bound(m_transfers.begin(), m_transfers.end(), txId, [] (size_t val, const TransactionTransferPair& a) { - return val < a.first; +bool WalletGreen::updateTransactionTransfers(size_t transactionId, const std::vector& containerAmountsList, + int64_t allInputsAmount, int64_t allOutputsAmount) { + + assert(allInputsAmount <= 0); + assert(allOutputsAmount >= 0); + + bool updated = false; + + auto transfersRange = getTransactionTransfersRange(transactionId); + // Iterators can be invalidated, so the first transfer is addressed by its index + size_t firstTransferIdx = std::distance(m_transfers.cbegin(), transfersRange.first); + + TransfersMap initialTransfers = getKnownTransfersMap(transactionId, firstTransferIdx); + + std::unordered_set myInputAddresses; + std::unordered_set myOutputAddresses; + int64_t myInputsAmount = 0; + int64_t myOutputsAmount = 0; + for (auto containerAmount : containerAmountsList) { + AccountPublicAddress address{ getWalletRecord(containerAmount.container).spendPublicKey, m_viewPublicKey }; + std::string addressString = m_currency.accountAddressAsString(address); + + updated |= updateAddressTransfers(transactionId, firstTransferIdx, addressString, initialTransfers[addressString].input, containerAmount.amounts.input); + updated |= updateAddressTransfers(transactionId, firstTransferIdx, addressString, initialTransfers[addressString].output, containerAmount.amounts.output); + + myInputsAmount += containerAmount.amounts.input; + myOutputsAmount += containerAmount.amounts.output; + + if (containerAmount.amounts.input != 0) { + myInputAddresses.emplace(addressString); + } + + if (containerAmount.amounts.output != 0) { + myOutputAddresses.emplace(addressString); + } + } + + assert(myInputsAmount >= allInputsAmount); + assert(myOutputsAmount <= allOutputsAmount); + + int64_t knownInputsAmount = 0; + int64_t knownOutputsAmount = 0; + auto updatedTransfers = getKnownTransfersMap(transactionId, firstTransferIdx); + for (const auto& pair : updatedTransfers) { + knownInputsAmount += pair.second.input; + knownOutputsAmount += pair.second.output; + } + + assert(myInputsAmount >= knownInputsAmount); + assert(myOutputsAmount <= knownOutputsAmount); + + updated |= updateUnknownTransfers(transactionId, firstTransferIdx, myInputAddresses, knownInputsAmount, myInputsAmount, allInputsAmount, false); + updated |= updateUnknownTransfers(transactionId, firstTransferIdx, myOutputAddresses, knownOutputsAmount, myOutputsAmount, allOutputsAmount, true); + + return updated; +} + +WalletGreen::TransfersMap WalletGreen::getKnownTransfersMap(size_t transactionId, size_t firstTransferIdx) const { + TransfersMap result; + + for (auto it = std::next(m_transfers.begin(), firstTransferIdx); it != m_transfers.end() && it->first == transactionId; ++it) { + const auto& address = it->second.address; + + if (!address.empty()) { + if (it->second.amount < 0) { + result[address].input += it->second.amount; + } else { + assert(it->second.amount > 0); + result[address].output += it->second.amount; + } + } + } + + return result; +} + +bool WalletGreen::updateAddressTransfers(size_t transactionId, size_t firstTransferIdx, const std::string& address, int64_t knownAmount, int64_t targetAmount) { + assert((knownAmount > 0 && targetAmount > 0) || (knownAmount < 0 && targetAmount < 0) || knownAmount == 0 || targetAmount == 0); + + bool updated = false; + + if (knownAmount != targetAmount) { + if (knownAmount == 0) { + appendTransfer(transactionId, firstTransferIdx, address, targetAmount); + updated = true; + } else if (targetAmount == 0) { + assert(knownAmount != 0); + updated |= eraseTransfersByAddress(transactionId, firstTransferIdx, address, knownAmount > 0); + } else { + updated |= adjustTransfer(transactionId, firstTransferIdx, address, targetAmount); + } + } + + return updated; +} + +bool WalletGreen::updateUnknownTransfers(size_t transactionId, size_t firstTransferIdx, const std::unordered_set& myAddresses, + int64_t knownAmount, int64_t myAmount, int64_t totalAmount, bool isOutput) { + + bool updated = false; + + if (std::abs(knownAmount) > std::abs(totalAmount)) { + updated |= eraseForeignTransfers(transactionId, firstTransferIdx, myAddresses, isOutput); + if (totalAmount == myAmount) { + updated |= eraseTransfersByAddress(transactionId, firstTransferIdx, std::string(), isOutput); + } else { + assert(std::abs(totalAmount) > std::abs(myAmount)); + updated |= adjustTransfer(transactionId, firstTransferIdx, std::string(), totalAmount - myAmount); + } + } else if (knownAmount == totalAmount) { + updated |= eraseTransfersByAddress(transactionId, firstTransferIdx, std::string(), isOutput); + } else { + assert(std::abs(totalAmount) > std::abs(knownAmount)); + updated |= adjustTransfer(transactionId, firstTransferIdx, std::string(), totalAmount - knownAmount); + } + + return updated; +} + +void WalletGreen::appendTransfer(size_t transactionId, size_t firstTransferIdx, const std::string& address, int64_t amount) { + auto it = std::next(m_transfers.begin(), firstTransferIdx); + auto insertIt = std::upper_bound(it, m_transfers.end(), transactionId, [](size_t transactionId, const TransactionTransferPair& pair) { + return transactionId < pair.first; }); - WalletTransfer tr { address, amount }; - m_transfers.insert(it, std::make_pair(txId, std::move(tr))); + WalletTransfer transfer{ WalletTransferType::USUAL, address, amount }; + m_transfers.emplace(insertIt, std::piecewise_construct, std::forward_as_tuple(transactionId), std::forward_as_tuple(transfer)); +} + +bool WalletGreen::adjustTransfer(size_t transactionId, size_t firstTransferIdx, const std::string& address, int64_t amount) { + assert(amount != 0); + + bool updated = false; + bool updateOutputTransfers = amount > 0; + bool firstAddressTransferFound = false; + auto it = std::next(m_transfers.begin(), firstTransferIdx); + while (it != m_transfers.end() && it->first == transactionId) { + assert(it->second.amount != 0); + bool transferIsOutput = it->second.amount > 0; + if (transferIsOutput == updateOutputTransfers && it->second.address == address) { + if (firstAddressTransferFound) { + it = m_transfers.erase(it); + updated = true; + } else { + if (it->second.amount != amount) { + it->second.amount = amount; + updated = true; + } + + firstAddressTransferFound = true; + ++it; + } + } else { + ++it; + } + } + + if (!firstAddressTransferFound) { + WalletTransfer transfer{ WalletTransferType::USUAL, address, amount }; + m_transfers.emplace(it, std::piecewise_construct, std::forward_as_tuple(transactionId), std::forward_as_tuple(transfer)); + updated = true; + } + + return updated; +} + +bool WalletGreen::eraseTransfers(size_t transactionId, size_t firstTransferIdx, std::function&& predicate) { + bool erased = false; + auto it = std::next(m_transfers.begin(), firstTransferIdx); + while (it != m_transfers.end() && it->first == transactionId) { + bool transferIsOutput = it->second.amount > 0; + if (predicate(transferIsOutput, it->second.address)) { + it = m_transfers.erase(it); + erased = true; + } else { + ++it; + } + } + + return erased; +} + +bool WalletGreen::eraseTransfersByAddress(size_t transactionId, size_t firstTransferIdx, const std::string& address, bool eraseOutputTransfers) { + return eraseTransfers(transactionId, firstTransferIdx, [&address, eraseOutputTransfers](bool isOutput, const std::string& transferAddress) { + return eraseOutputTransfers == isOutput && address == transferAddress; + }); +} + +bool WalletGreen::eraseForeignTransfers(size_t transactionId, size_t firstTransferIdx, const std::unordered_set& knownAddresses, + bool eraseOutputTransfers) { + + return eraseTransfers(transactionId, firstTransferIdx, [this, &knownAddresses, eraseOutputTransfers](bool isOutput, const std::string& transferAddress) { + return eraseOutputTransfers == isOutput && knownAddresses.count(transferAddress) == 0; + }); } std::unique_ptr WalletGreen::makeTransaction(const std::vector& decomposedOutputs, @@ -792,12 +1239,23 @@ std::unique_ptr WalletGreen::makeTransaction(const std std::unique_ptr tx = createTransaction(); + typedef std::pair AmountToAddress; + std::vector amountsToAddresses; for (const auto& output: decomposedOutputs) { for (auto amount: output.amounts) { - tx->addOutput(amount, output.receiver); + amountsToAddresses.emplace_back(AmountToAddress{&output.receiver, amount}); } } + std::shuffle(amountsToAddresses.begin(), amountsToAddresses.end(), std::default_random_engine{Crypto::rand()}); + std::sort(amountsToAddresses.begin(), amountsToAddresses.end(), [] (const AmountToAddress& left, const AmountToAddress& right) { + return left.second < right.second; + }); + + for (const auto& amountToAddress: amountsToAddresses) { + tx->addOutput(amountToAddress.second, *amountToAddress.first); + } + tx->setUnlockTime(unlockTimestamp); tx->appendExtra(Common::asBinaryArray(extra)); @@ -813,23 +1271,12 @@ std::unique_ptr WalletGreen::makeTransaction(const std return tx; } -void WalletGreen::sendTransaction(ITransaction* tx) { +void WalletGreen::sendTransaction(const CryptoNote::Transaction& cryptoNoteTransaction) { System::Event completion(m_dispatcher); std::error_code ec; - CryptoNote::Transaction oldTxFormat; - - const auto& ba = tx->getTransactionData(); - - if (ba.size() > m_upperTransactionSizeLimit) { - throw std::system_error(make_error_code(error::TRANSACTION_SIZE_TOO_BIG)); - } - - if (!fromBinaryArray(oldTxFormat, ba)) { - throw std::system_error(make_error_code(error::INTERNAL_WALLET_ERROR)); - } throwIfStopped(); - m_node.relayTransaction(oldTxFormat, [&ec, &completion, this] (std::error_code error) { + m_node.relayTransaction(cryptoNoteTransaction, [&ec, &completion, this](std::error_code error) { ec = error; this->m_dispatcher.remoteSpawn(std::bind(asyncRequestCompletion, std::ref(completion))); }); @@ -840,6 +1287,51 @@ void WalletGreen::sendTransaction(ITransaction* tx) { } } +size_t WalletGreen::validateSaveAndSendTransaction(const ITransactionReader& transaction, const std::vector& destinations, bool isFusion, bool send) { + BinaryArray transactionData = transaction.getTransactionData(); + + if (transactionData.size() > m_upperTransactionSizeLimit) { + throw std::system_error(make_error_code(error::TRANSACTION_SIZE_TOO_BIG)); + } + + CryptoNote::Transaction cryptoNoteTransaction; + if (!fromBinaryArray(cryptoNoteTransaction, transactionData)) { + throw std::system_error(make_error_code(error::INTERNAL_WALLET_ERROR), "Failed to deserialize created transaction"); + } + + uint64_t fee = transaction.getInputTotalAmount() - transaction.getOutputTotalAmount(); + size_t transactionId = insertOutgoingTransactionAndPushEvent(transaction.getTransactionHash(), fee, transaction.getExtra(), transaction.getUnlockTime()); + Tools::ScopeExit rollbackTransactionInsertion([this, transactionId] { + updateTransactionStateAndPushEvent(transactionId, WalletTransactionState::FAILED); + }); + + m_fusionTxsCache.emplace(transactionId, isFusion); + pushBackOutgoingTransfers(transactionId, destinations); + + addUnconfirmedTransaction(transaction); + Tools::ScopeExit rollbackAddingUnconfirmedTransaction([this, &transaction] { + try { + removeUnconfirmedTransaction(transaction.getTransactionHash()); + } catch (...) { + // Ignore any exceptions. If rollback fails then the transaction is stored as unconfirmed and will be deleted after wallet relaunch + // during transaction pool synchronization + } + }); + + if (send) { + sendTransaction(cryptoNoteTransaction); + updateTransactionStateAndPushEvent(transactionId, WalletTransactionState::SUCCEEDED); + } else { + assert(m_uncommitedTransactions.count(transactionId) == 0); + m_uncommitedTransactions.emplace(transactionId, std::move(cryptoNoteTransaction)); + } + + rollbackAddingUnconfirmedTransaction.cancel(); + rollbackTransactionInsertion.cancel(); + + return transactionId; +} + AccountKeys WalletGreen::makeAccountKeys(const WalletRecord& wallet) const { AccountKeys keys; keys.address.spendPublicKey = wallet.spendPublicKey; @@ -902,7 +1394,7 @@ uint64_t WalletGreen::selectTransfers( size_t outIndex = outDistribution(randomGenerator); TransactionOutputInformation out = addressOuts[outIndex]; - if (!isOutputUsed(out) && (out.amount > dustThreshold || dust)) { + if (out.amount > dustThreshold || dust) { if (out.amount <= dustThreshold) { dust = false; } @@ -923,11 +1415,9 @@ uint64_t WalletGreen::selectTransfers( } for (const auto& addressOuts : walletOuts) { - auto it = std::find_if(addressOuts.outs.begin(), addressOuts.outs.end(), - [dustThreshold, this] (const TransactionOutputInformation& out) { - return out.amount <= dustThreshold && (!this->isOutputUsed(out)); - } - ); + auto it = std::find_if(addressOuts.outs.begin(), addressOuts.outs.end(), [dustThreshold] (const TransactionOutputInformation& out) { + return out.amount <= dustThreshold; + }); if (it != addressOuts.outs.end()) { foundMoney += it->amount; @@ -971,26 +1461,44 @@ WalletGreen::WalletOuts WalletGreen::pickWallet(const std::string& address) { return outs; } -void WalletGreen::splitDestinations(const std::vector& destinations, - const CryptoNote::WalletTransfer& changeDestination, - uint64_t dustThreshold, - const CryptoNote::Currency& currency, - std::vector& decomposedOutputs) { +std::vector WalletGreen::pickWallets(const std::vector& addresses) { + std::vector wallets; + wallets.reserve(addresses.size()); - for (const auto& destination: destinations) { - ReceiverAmounts receiverAmounts; - - parseAddressString(destination.address, currency, receiverAmounts.receiver); - decomposeAmount(destination.amount, dustThreshold, receiverAmounts.amounts); - - decomposedOutputs.push_back(std::move(receiverAmounts)); + for (const auto& address: addresses) { + WalletOuts wallet = pickWallet(address); + if (!wallet.outs.empty()) { + wallets.emplace_back(std::move(wallet)); + } } - ReceiverAmounts changeAmounts; - parseAddressString(changeDestination.address, currency, changeAmounts.receiver); - decomposeAmount(changeDestination.amount, dustThreshold, changeAmounts.amounts); + return wallets; +} - decomposedOutputs.push_back(std::move(changeAmounts)); +std::vector WalletGreen::splitDestinations(const std::vector& destinations, + uint64_t dustThreshold, + const CryptoNote::Currency& currency) { + + std::vector decomposedOutputs; + for (const auto& destination: destinations) { + AccountPublicAddress address; + parseAddressString(destination.address, currency, address); + decomposedOutputs.push_back(splitAmount(destination.amount, address, dustThreshold)); + } + + return decomposedOutputs; +} + +CryptoNote::WalletGreen::ReceiverAmounts WalletGreen::splitAmount( + uint64_t amount, + const AccountPublicAddress& destination, + uint64_t dustThreshold) { + + ReceiverAmounts receiverAmounts; + + receiverAmounts.receiver = destination; + decomposeAmount(amount, dustThreshold, receiverAmounts.amounts); + return receiverAmounts; } void WalletGreen::prepareInputs( @@ -1048,13 +1556,114 @@ void WalletGreen::prepareInputs( } } +WalletTransactionWithTransfers WalletGreen::getTransaction(const Crypto::Hash& transactionHash) const { + throwIfNotInitialized(); + throwIfStopped(); + + auto& hashIndex = m_transactions.get(); + auto it = hashIndex.find(transactionHash); + if (it == hashIndex.end()) { + throw std::system_error(make_error_code(error::OBJECT_NOT_FOUND), "Transaction not found"); + } + + WalletTransactionWithTransfers walletTransaction; + walletTransaction.transaction = *it; + walletTransaction.transfers = getTransactionTransfers(*it); + + return walletTransaction; +} + +std::vector WalletGreen::getTransactions(const Crypto::Hash& blockHash, size_t count) const { + throwIfNotInitialized(); + throwIfStopped(); + + auto& hashIndex = m_blockchain.get(); + auto it = hashIndex.find(blockHash); + if (it == hashIndex.end()) { + return std::vector(); + } + + auto heightIt = m_blockchain.project(it); + + uint32_t blockIndex = static_cast(std::distance(m_blockchain.get().begin(), heightIt)); + return getTransactionsInBlocks(blockIndex, count); +} + +std::vector WalletGreen::getTransactions(uint32_t blockIndex, size_t count) const { + throwIfNotInitialized(); + throwIfStopped(); + + return getTransactionsInBlocks(blockIndex, count); +} + +std::vector WalletGreen::getBlockHashes(uint32_t blockIndex, size_t count) const { + throwIfNotInitialized(); + throwIfStopped(); + + auto& index = m_blockchain.get(); + + if (blockIndex >= index.size()) { + return std::vector(); + } + + auto start = std::next(index.begin(), blockIndex); + auto end = std::next(index.begin(), std::min(index.size(), blockIndex + count)); + return std::vector(start, end); +} + +uint32_t WalletGreen::getBlockCount() const { + throwIfNotInitialized(); + throwIfStopped(); + + uint32_t blockCount = static_cast(m_blockchain.size()); + assert(blockCount != 0); + + return blockCount; +} + +std::vector WalletGreen::getUnconfirmedTransactions() const { + throwIfNotInitialized(); + throwIfStopped(); + + std::vector result; + auto lowerBound = m_transactions.get().lower_bound(WALLET_UNCONFIRMED_TRANSACTION_HEIGHT); + for (auto it = lowerBound; it != m_transactions.get().end(); ++it) { + if (it->state != WalletTransactionState::SUCCEEDED) { + continue; + } + + WalletTransactionWithTransfers transaction; + transaction.transaction = *it; + transaction.transfers = getTransactionTransfers(*it); + + result.push_back(transaction); + } + + return result; +} + +std::vector WalletGreen::getDelayedTransactionIds() const { + throwIfNotInitialized(); + throwIfStopped(); + throwIfTrackingMode(); + + std::vector result; + result.reserve(m_uncommitedTransactions.size()); + + for (const auto& kv: m_uncommitedTransactions) { + result.push_back(kv.first); + } + + return result; +} + void WalletGreen::start() { m_stopped = false; } void WalletGreen::stop() { m_stopped = true; - m_eventOccured.set(); + m_eventOccurred.set(); } WalletEvent WalletGreen::getEvent() { @@ -1062,8 +1671,8 @@ WalletEvent WalletGreen::getEvent() { throwIfStopped(); while(m_events.empty()) { - m_eventOccured.wait(); - m_eventOccured.clear(); + m_eventOccurred.wait(); + m_eventOccurred.clear(); throwIfStopped(); } @@ -1115,6 +1724,51 @@ void WalletGreen::onSynchronizationCompleted() { pushEvent(makeSyncCompletedEvent()); } +void WalletGreen::onBlocksAdded(const Crypto::PublicKey& viewPublicKey, const std::vector& blockHashes) { + m_dispatcher.remoteSpawn([this, blockHashes] () { blocksAdded(blockHashes); } ); +} + +void WalletGreen::blocksAdded(const std::vector& blockHashes) { + System::EventLock lk(m_readyEvent); + + if (m_state == WalletState::NOT_INITIALIZED) { + return; + } + + m_blockchain.insert(m_blockchain.end(), blockHashes.begin(), blockHashes.end()); +} + +void WalletGreen::onBlockchainDetach(const Crypto::PublicKey& viewPublicKey, uint32_t blockIndex) { + m_dispatcher.remoteSpawn([this, blockIndex] () { blocksRollback(blockIndex); } ); +} + +void WalletGreen::blocksRollback(uint32_t blockIndex) { + System::EventLock lk(m_readyEvent); + + if (m_state == WalletState::NOT_INITIALIZED) { + return; + } + + auto& blockHeightIndex = m_blockchain.get(); + blockHeightIndex.erase(std::next(blockHeightIndex.begin(), blockIndex), blockHeightIndex.end()); +} + +void WalletGreen::onTransactionDeleteBegin(const Crypto::PublicKey& viewPublicKey, Crypto::Hash transactionHash) { + m_dispatcher.remoteSpawn([=]() { transactionDeleteBegin(transactionHash); }); +} + +// TODO remove +void WalletGreen::transactionDeleteBegin(Crypto::Hash /*transactionHash*/) { +} + +void WalletGreen::onTransactionDeleteEnd(const Crypto::PublicKey& viewPublicKey, Crypto::Hash transactionHash) { + m_dispatcher.remoteSpawn([=]() { transactionDeleteEnd(transactionHash); }); +} + +// TODO remove +void WalletGreen::transactionDeleteEnd(Crypto::Hash transactionHash) { +} + void WalletGreen::unlockBalances(uint32_t height) { auto& index = m_unlockTransactionsJob.get(); auto upper = index.upper_bound(height); @@ -1129,66 +1783,95 @@ void WalletGreen::unlockBalances(uint32_t height) { } } -void WalletGreen::onTransactionUpdated(ITransfersSubscription* object, const Hash& transactionHash) { - m_dispatcher.remoteSpawn([object, transactionHash, this] () { this->transactionUpdated(object, transactionHash); } ); +void WalletGreen::onTransactionUpdated(ITransfersSubscription* /*object*/, const Crypto::Hash& /*transactionHash*/) { + // Deprecated, ignore it. New event handler is onTransactionUpdated(const Crypto::PublicKey&, const Crypto::Hash&, const std::vector&) } -void WalletGreen::transactionUpdated(ITransfersSubscription* object, const Hash& transactionHash) { +void WalletGreen::onTransactionUpdated(const Crypto::PublicKey&, const Crypto::Hash& transactionHash, const std::vector& containers) { + assert(!containers.empty()); + + TransactionInformation info; + std::vector containerAmountsList; + containerAmountsList.reserve(containers.size()); + for (auto container : containers) { + uint64_t inputsAmount; + // Don't move this code to the following remote spawn, because it guarantees that the container has the transaction + uint64_t outputsAmount; + bool found = container->getTransactionInformation(transactionHash, info, &inputsAmount, &outputsAmount); + assert(found); + + ContainerAmounts containerAmounts; + containerAmounts.container = container; + containerAmounts.amounts.input = -static_cast(inputsAmount); + containerAmounts.amounts.output = static_cast(outputsAmount); + containerAmountsList.emplace_back(std::move(containerAmounts)); + } + + m_dispatcher.remoteSpawn([this, info, containerAmountsList] { + this->transactionUpdated(info, containerAmountsList); + }); +} + +void WalletGreen::transactionUpdated(const TransactionInformation& transactionInfo, const std::vector& containerAmountsList) { System::EventLock lk(m_readyEvent); if (m_state == WalletState::NOT_INITIALIZED) { return; } - CryptoNote::ITransfersContainer* container = &object->getContainer(); + bool updated = false; + bool isNew = false; - deleteSpentOutputs(transactionHash); + int64_t totalAmount = std::accumulate(containerAmountsList.begin(), containerAmountsList.end(), static_cast(0), + [](int64_t sum, const ContainerAmounts& containerAmounts) { return sum + containerAmounts.amounts.input + containerAmounts.amounts.output; }); - CryptoNote::TransactionInformation info; - int64_t txBalance; - bool found = container->getTransactionInformation(transactionHash, info, txBalance); - assert(found); - - if (transactionExists(info.transactionHash)) { - bool updated = updateWalletTransactionInfo(info.transactionHash, info); - - auto id = getTransactionId(info.transactionHash); - - if (updated) { - pushEvent(makeTransactionUpdatedEvent(id)); - } + size_t transactionId; + auto& hashIndex = m_transactions.get(); + auto it = hashIndex.find(transactionInfo.transactionHash); + if (it != hashIndex.end()) { + transactionId = std::distance(m_transactions.get().begin(), m_transactions.project(it)); + updated |= updateWalletTransactionInfo(transactionId, transactionInfo, totalAmount); } else { - auto id = insertBlockchainTransaction(info, txBalance); - if (txBalance > 0) { - AccountPublicAddress walletAddress{ getWalletRecord(container).spendPublicKey, m_viewPublicKey }; - insertIncomingTransfer(id, m_currency.accountAddressAsString(walletAddress), txBalance); + isNew = true; + transactionId = insertBlockchainTransaction(transactionInfo, totalAmount); + m_fusionTxsCache.emplace(transactionId, isFusionTransaction(*it)); + } + + if (transactionInfo.blockHeight != CryptoNote::WALLET_UNCONFIRMED_TRANSACTION_HEIGHT) { + // In some cases a transaction can be included to a block but not removed from m_uncommitedTransactions. Fix it + m_uncommitedTransactions.erase(transactionId); + } + + // Update cached balance + for (auto containerAmounts : containerAmountsList) { + updateBalance(containerAmounts.container); + + if (transactionInfo.blockHeight != CryptoNote::WALLET_UNCONFIRMED_TRANSACTION_HEIGHT) { + uint32_t unlockHeight = std::max(transactionInfo.blockHeight + m_transactionSoftLockTime, static_cast(transactionInfo.unlockTime)); + insertUnlockTransactionJob(transactionInfo.transactionHash, unlockHeight, containerAmounts.container); } - - m_fusionTxsCache.emplace(id, isFusionTransaction(m_transactions.get()[id])); - - pushEvent(makeTransactionCreatedEvent(id)); } - m_change.erase(transactionHash); + updated |= updateTransactionTransfers(transactionId, containerAmountsList, -static_cast(transactionInfo.totalAmountIn), + static_cast(transactionInfo.totalAmountOut)); - if (info.blockHeight != CryptoNote::WALLET_UNCONFIRMED_TRANSACTION_HEIGHT) { - uint32_t unlockHeight = std::max(info.blockHeight + m_transactionSoftLockTime, static_cast(info.unlockTime)); - insertUnlockTransactionJob(transactionHash, unlockHeight, container); + if (isNew) { + pushEvent(makeTransactionCreatedEvent(transactionId)); + } else if (updated) { + pushEvent(makeTransactionUpdatedEvent(transactionId)); } - - updateBalance(container); } void WalletGreen::pushEvent(const WalletEvent& event) { m_events.push(event); - m_eventOccured.set(); + m_eventOccurred.set(); } size_t WalletGreen::getTransactionId(const Hash& transactionHash) const { auto it = m_transactions.get().find(transactionHash); if (it == m_transactions.get().end()) { - throw std::system_error(std::make_error_code(std::errc::invalid_argument)); + throw std::system_error(make_error_code(std::errc::invalid_argument)); } auto rndIt = m_transactions.project(it); @@ -1215,20 +1898,26 @@ void WalletGreen::transactionDeleted(ITransfersSubscription* object, const Hash& } CryptoNote::ITransfersContainer* container = &object->getContainer(); + updateBalance(container); deleteUnlockTransactionJob(transactionHash); - m_change.erase(transactionHash); - deleteSpentOutputs(transactionHash); - m_transactions.get().modify(it, [] (CryptoNote::WalletTransaction& tx) { - tx.state = WalletTransactionState::CANCELLED; - tx.blockHeight = WALLET_UNCONFIRMED_TRANSACTION_HEIGHT; + bool updated = false; + m_transactions.get().modify(it, [&updated](CryptoNote::WalletTransaction& tx) { + if (tx.state == WalletTransactionState::CREATED || tx.state == WalletTransactionState::SUCCEEDED) { + tx.state = WalletTransactionState::CANCELLED; + updated = true; + } + + if (tx.blockHeight != WALLET_UNCONFIRMED_TRANSACTION_HEIGHT) { + tx.blockHeight = WALLET_UNCONFIRMED_TRANSACTION_HEIGHT; + updated = true; + } }); - auto rndIt = m_transactions.project(it); - auto id = std::distance(m_transactions.get().begin(), rndIt); - - updateBalance(container); - pushEvent(makeTransactionUpdatedEvent(id)); + if (updated) { + auto transactionId = getTransactionId(transactionHash); + pushEvent(makeTransactionUpdatedEvent(transactionId)); + } } void WalletGreen::insertUnlockTransactionJob(const Hash& transactionHash, uint32_t blockHeight, CryptoNote::ITransfersContainer* container) { @@ -1241,6 +1930,39 @@ void WalletGreen::deleteUnlockTransactionJob(const Hash& transactionHash) { index.erase(transactionHash); } +void WalletGreen::startBlockchainSynchronizer() { + if (!m_walletsContainer.empty() && !m_blockchainSynchronizerStarted) { + m_blockchainSynchronizer.start(); + m_blockchainSynchronizerStarted = true; + } +} + +void WalletGreen::stopBlockchainSynchronizer() { + if (m_blockchainSynchronizerStarted) { + m_blockchainSynchronizer.stop(); + m_blockchainSynchronizerStarted = false; + } +} + +void WalletGreen::addUnconfirmedTransaction(const ITransactionReader& transaction) { + System::RemoteContext context(m_dispatcher, [this, &transaction] { + return m_blockchainSynchronizer.addUnconfirmedTransaction(transaction).get(); + }); + + auto ec = context.get(); + if (ec) { + throw std::system_error(ec, "Failed to add unconfirmed transaction"); + } +} + +void WalletGreen::removeUnconfirmedTransaction(const Crypto::Hash& transactionHash) { + System::RemoteContext context(m_dispatcher, [this, &transactionHash] { + m_blockchainSynchronizer.removeUnconfirmedTransaction(transactionHash).get(); + }); + + context.get(); +} + void WalletGreen::updateBalance(CryptoNote::ITransfersContainer* container) { auto it = m_walletsContainer.get().find(container); @@ -1251,17 +1973,6 @@ void WalletGreen::updateBalance(CryptoNote::ITransfersContainer* container) { uint64_t actual = container->balance(ITransfersContainer::IncludeAllUnlocked); uint64_t pending = container->balance(ITransfersContainer::IncludeAllLocked); - uint64_t unconfirmedBalance = countSpentBalance(&(*it)); - - actual -= unconfirmedBalance; - - //xxx: i don't like this special case. Decompose this function - if (container == m_walletsContainer.get()[0].container) { - uint64_t change = 0; - std::for_each(m_change.begin(), m_change.end(), [&change] (const TransactionChanges::value_type& item) { change += item.second; }); - pending += change; - } - if (it->actualBalance < actual) { m_actualBalance += actual - it->actualBalance; } else { @@ -1283,7 +1994,7 @@ void WalletGreen::updateBalance(CryptoNote::ITransfersContainer* container) { const WalletRecord& WalletGreen::getWalletRecord(const PublicKey& key) const { auto it = m_walletsContainer.get().find(key); if (it == m_walletsContainer.get().end()) { - throw std::system_error(std::make_error_code(std::errc::invalid_argument)); + throw std::system_error(make_error_code(error::WALLET_NOT_FOUND)); } return *it; @@ -1297,7 +2008,7 @@ const WalletRecord& WalletGreen::getWalletRecord(const std::string& address) con const WalletRecord& WalletGreen::getWalletRecord(CryptoNote::ITransfersContainer* container) const { auto it = m_walletsContainer.get().find(container); if (it == m_walletsContainer.get().end()) { - throw std::system_error(std::make_error_code(std::errc::invalid_argument)); + throw std::system_error(make_error_code(error::WALLET_NOT_FOUND)); } return *it; @@ -1307,54 +2018,12 @@ CryptoNote::AccountPublicAddress WalletGreen::parseAddress(const std::string& ad CryptoNote::AccountPublicAddress pubAddr; if (!m_currency.parseAccountAddressString(address, pubAddr)) { - throw std::system_error(std::make_error_code(std::errc::invalid_argument)); + throw std::system_error(make_error_code(error::BAD_ADDRESS)); } return pubAddr; } -bool WalletGreen::isOutputUsed(const TransactionOutputInformation& out) const { - return m_spentOutputs.get().find(boost::make_tuple(out.transactionHash, out.outputInTransaction)) - != - m_spentOutputs.get().end(); -} - -void WalletGreen::markOutputsSpent(const Hash& transactionHash,const std::vector& selectedTransfers) { - auto& index = m_spentOutputs.get(); - - for (const auto& output: selectedTransfers) { - index.insert( {output.out.amount, output.out.transactionHash, output.out.outputInTransaction, output.wallet, transactionHash} ); - } -} - -void WalletGreen::deleteSpentOutputs(const Hash& transactionHash) { - auto& index = m_spentOutputs.get(); - index.erase(transactionHash); -} - -uint64_t WalletGreen::countSpentBalance(const WalletRecord* wallet) { - uint64_t amount = 0; - - auto bounds = m_spentOutputs.get().equal_range(wallet); - for (auto it = bounds.first; it != bounds.second; ++it) { - amount += it->amount; - } - - return amount; -} - -void WalletGreen::updateUsedWalletsBalances(const std::vector& selectedTransfers) { - std::set wallets; - - // wallet #0 recieves change, so we have to update it after transfer - wallets.insert(const_cast(&m_walletsContainer.get()[0])); - - std::for_each(selectedTransfers.begin(), selectedTransfers.end(), [&wallets] (const OutputToTransfer& output) { wallets.insert(output.wallet); } ); - std::for_each(wallets.begin(), wallets.end(), [this] (WalletRecord* wallet) { - this->updateBalance(wallet->container); - }); -} - void WalletGreen::throwIfStopped() const { if (m_stopped) { throw std::system_error(make_error_code(error::OPERATION_CANCELLED)); @@ -1377,12 +2046,16 @@ WalletGreen::WalletTrackingMode WalletGreen::getTrackingMode() const { } size_t WalletGreen::createFusionTransaction(uint64_t threshold, uint64_t mixin) { + Tools::ScopeExit releaseContext([this] { + m_dispatcher.yield(); + }); + System::EventLock lk(m_readyEvent); throwIfNotInitialized(); + throwIfTrackingMode(); throwIfStopped(); - //TODO: check if wallet is not in tracking mode const size_t MAX_FUSION_OUTPUT_COUNT = 4; if (threshold <= m_currency.defaultDustThreshold()) { @@ -1435,6 +2108,7 @@ size_t WalletGreen::createFusionTransaction(uint64_t threshold, uint64_t mixin) fusionTransaction = makeTransaction(std::vector{decomposedOutputs}, keysInfo, "", 0); transactionSize = getTransactionSize(*fusionTransaction); + ++round; } while (transactionSize > m_currency.fusionTxMaxSize() && fusionInputs.size() >= m_currency.fusionTxMinInputCount()); @@ -1442,35 +2116,7 @@ size_t WalletGreen::createFusionTransaction(uint64_t threshold, uint64_t mixin) throw std::runtime_error("Unable to create fusion transaction"); } - size_t transactionId = insertOutgoingTransaction(fusionTransaction->getTransactionHash(), 0, 0, fusionTransaction->getExtra(), 0); - m_fusionTxsCache.emplace(transactionId, true); - - WalletTransfer destination = {m_currency.accountAddressAsString({m_walletsContainer.get().begin()->spendPublicKey, - m_viewPublicKey }), 0}; - pushBackOutgoingTransfers(transactionId, std::vector {destination}); - - markOutputsSpent(fusionTransaction->getTransactionHash(), fusionInputs); - - try { - sendTransaction(fusionTransaction.get()); - } catch (std::exception&) { - deleteSpentOutputs(fusionTransaction->getTransactionHash()); - pushEvent(makeTransactionCreatedEvent(transactionId)); - throw; - } - - auto txIt = m_transactions.get().begin(); - std::advance(txIt, transactionId); - m_transactions.get().modify(txIt, - [] (WalletTransaction& tx) { tx.state = WalletTransactionState::SUCCEEDED; }); - - m_change[fusionTransaction->getTransactionHash()] = transactionAmount; - - updateUsedWalletsBalances(fusionInputs); - - pushEvent(makeTransactionCreatedEvent(transactionId)); - - return transactionId; + return validateSaveAndSendTransaction(*fusionTransaction, {}, true, true); } WalletGreen::ReceiverAmounts WalletGreen::decomposeFusionOutputs(uint64_t inputsAmount) { @@ -1533,8 +2179,7 @@ bool WalletGreen::isFusionTransaction(const WalletTransaction& walletTx) const { } if (!gotTx) { - int64_t ignore; - gotTx = wallet.container->getTransactionInformation(walletTx.hash, txInfo, ignore); + gotTx = wallet.container->getTransactionInformation(walletTx.hash, txInfo); } } @@ -1560,7 +2205,7 @@ IFusionManager::EstimateResult WalletGreen::estimate(uint64_t threshold) const { for (size_t walletIndex = 0; walletIndex < walletOuts.size(); ++walletIndex) { for (auto& out : walletOuts[walletIndex].outs) { uint8_t powerOfTen = 0; - if (m_currency.isAmountApplicableInFusionTransactionInput(out.amount, threshold, powerOfTen) && !isOutputUsed(out)) { + if (m_currency.isAmountApplicableInFusionTransactionInput(out.amount, threshold, powerOfTen)) { assert(powerOfTen < std::numeric_limits::digits10 + 1); bucketSizes[powerOfTen]++; } @@ -1586,7 +2231,7 @@ std::vector WalletGreen::pickRandomFusionInputs(u for (size_t walletIndex = 0; walletIndex < walletOuts.size(); ++walletIndex) { for (auto& out : walletOuts[walletIndex].outs) { uint8_t powerOfTen = 0; - if (m_currency.isAmountApplicableInFusionTransactionInput(out.amount, threshold, powerOfTen) && !isOutputUsed(out)) { + if (m_currency.isAmountApplicableInFusionTransactionInput(out.amount, threshold, powerOfTen)) { allFusionReadyOuts.push_back({std::move(out), walletOuts[walletIndex].wallet}); assert(powerOfTen < std::numeric_limits::digits10 + 1); bucketSizes[powerOfTen]++; @@ -1645,4 +2290,201 @@ std::vector WalletGreen::pickRandomFusionInputs(u return trimmedSelectedOuts; } +std::vector WalletGreen::getTransactionsInBlocks(uint32_t blockIndex, size_t count) const { + if (count == 0) { + throw std::system_error(make_error_code(error::WRONG_PARAMETERS), "blocks count must be greater than zero"); + } + + std::vector result; + + if (blockIndex >= m_blockchain.size()) { + return result; + } + + auto& blockHeightIndex = m_transactions.get(); + uint32_t stopIndex = static_cast(std::min(m_blockchain.size(), blockIndex + count)); + + for (uint32_t height = blockIndex; height < stopIndex; ++height) { + TransactionsInBlockInfo info; + info.blockHash = m_blockchain[height]; + + auto lowerBound = blockHeightIndex.lower_bound(height); + auto upperBound = blockHeightIndex.upper_bound(height); + for (auto it = lowerBound; it != upperBound; ++it) { + if (it->state != WalletTransactionState::SUCCEEDED) { + continue; + } + + WalletTransactionWithTransfers transaction; + transaction.transaction = *it; + + transaction.transfers = getTransactionTransfers(*it); + + info.transactions.emplace_back(std::move(transaction)); + } + + result.emplace_back(std::move(info)); + } + + return result; +} + +Crypto::Hash WalletGreen::getBlockHashByIndex(uint32_t blockIndex) const { + assert(blockIndex < m_blockchain.size()); + return m_blockchain.get()[blockIndex]; +} + +std::vector WalletGreen::getTransactionTransfers(const WalletTransaction& transaction) const { + auto& transactionIdIndex = m_transactions.get(); + + auto it = transactionIdIndex.iterator_to(transaction); + assert(it != transactionIdIndex.end()); + + size_t transactionId = std::distance(transactionIdIndex.begin(), it); + size_t transfersCount = getTransactionTransferCount(transactionId); + + std::vector result; + result.reserve(transfersCount); + + for (size_t transferId = 0; transferId < transfersCount; ++transferId) { + result.push_back(getTransactionTransfer(transactionId, transferId)); + } + + return result; +} + +void WalletGreen::filterOutTransactions(WalletTransactions& transactions, WalletTransfers& transfers, std::function&& pred) const { + size_t cancelledTransactions = 0; + + auto& index = m_transactions.get(); + for (size_t i = 0; i < m_transactions.size(); ++i) { + const WalletTransaction& transaction = index[i]; + + if (pred(transaction)) { + ++cancelledTransactions; + continue; + } + + transactions.push_back(transaction); + std::vector transactionTransfers = getTransactionTransfers(transaction); + for (auto& transfer: transactionTransfers) { + transfers.push_back(TransactionTransferPair {i - cancelledTransactions, std::move(transfer)} ); + } + } +} + +void WalletGreen::getViewKeyKnownBlocks(const Crypto::PublicKey& viewPublicKey) { + std::vector blockchain = m_synchronizer.getViewKeyKnownBlocks(m_viewPublicKey); + m_blockchain.insert(m_blockchain.end(), blockchain.begin(), blockchain.end()); +} + +///pre: changeDestinationAddress belongs to current container +///pre: source address belongs to current container +CryptoNote::AccountPublicAddress WalletGreen::getChangeDestination(const std::string& changeDestinationAddress, const std::vector& sourceAddresses) const { + if (!changeDestinationAddress.empty()) { + return parseAccountAddressString(changeDestinationAddress, m_currency); + } + + if (m_walletsContainer.size() == 1) { + return AccountPublicAddress { m_walletsContainer.get()[0].spendPublicKey, m_viewPublicKey }; + } + + assert(sourceAddresses.size() == 1 && isMyAddress(sourceAddresses[0])); + return parseAccountAddressString(sourceAddresses[0], m_currency); +} + +bool WalletGreen::isMyAddress(const std::string& addressString) const { + CryptoNote::AccountPublicAddress address = parseAccountAddressString(addressString, m_currency); + return m_viewPublicKey == address.viewPublicKey && m_walletsContainer.get().count(address.spendPublicKey) != 0; +} + +void WalletGreen::deleteContainerFromUnlockTransactionJobs(const ITransfersContainer* container) { + for (auto it = m_unlockTransactionsJob.begin(); it != m_unlockTransactionsJob.end();) { + if (it->container == container) { + it = m_unlockTransactionsJob.erase(it); + } else { + ++it; + } + } +} + +std::vector WalletGreen::deleteTransfersForAddress(const std::string& address, std::vector& deletedTransactions) { + assert(!address.empty()); + + int64_t deletedInputs = 0; + int64_t deletedOutputs = 0; + + int64_t unknownInputs = 0; + + bool transfersLeft = false; + size_t firstTransactionTransfer = 0; + + std::vector updatedTransactions; + + for (size_t i = 0; i < m_transfers.size(); ++i) { + WalletTransfer& transfer = m_transfers[i].second; + + if (transfer.address == address) { + if (transfer.amount >= 0) { + deletedOutputs += transfer.amount; + } else { + deletedInputs += transfer.amount; + transfer.address = ""; + } + } else if (transfer.address.empty()) { + if (transfer.amount < 0) { + unknownInputs += transfer.amount; + } + } else if (isMyAddress(transfer.address)) { + transfersLeft = true; + } + + size_t transactionId = m_transfers[i].first; + if ((i == m_transfers.size() - 1) || (transactionId != m_transfers[i + 1].first)) { + //the last transfer for current transaction + + size_t transfersBeforeMerge = m_transfers.size(); + if (deletedInputs != 0) { + adjustTransfer(transactionId, firstTransactionTransfer, "", deletedInputs + unknownInputs); + } + + assert(transfersBeforeMerge >= m_transfers.size()); + i -= transfersBeforeMerge - m_transfers.size(); + + auto& randomIndex = m_transactions.get(); + + randomIndex.modify(std::next(randomIndex.begin(), transactionId), [transfersLeft, deletedInputs, deletedOutputs] (WalletTransaction& transaction) { + transaction.totalAmount -= deletedInputs + deletedOutputs; + + if (!transfersLeft) { + transaction.state = WalletTransactionState::DELETED; + } + }); + + if (!transfersLeft) { + deletedTransactions.push_back(transactionId); + } + + if (deletedInputs != 0 || deletedOutputs != 0) { + updatedTransactions.push_back(transactionId); + } + + //reset values for next transaction + deletedInputs = 0; + deletedOutputs = 0; + unknownInputs = 0; + transfersLeft = false; + firstTransactionTransfer = i + 1; + } + } + + return updatedTransactions; +} + +void WalletGreen::deleteFromUncommitedTransactions(const std::vector& deletedTransactions) { + for (auto transactionId: deletedTransactions) { + m_uncommitedTransactions.erase(transactionId); + } +} + } //namespace CryptoNote diff --git a/src/Wallet/WalletGreen.h b/src/Wallet/WalletGreen.h index ed51bd78..39a773cf 100755 --- a/src/Wallet/WalletGreen.h +++ b/src/Wallet/WalletGreen.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -7,6 +7,7 @@ #include "IWallet.h" #include +#include #include "IFusionManager.h" #include "WalletIndices.h" @@ -21,6 +22,7 @@ namespace CryptoNote { class WalletGreen : public IWallet, ITransfersObserver, IBlockchainSynchronizerObserver, + ITransfersSynchronizerObserver, IFusionManager { public: WalletGreen(System::Dispatcher& dispatcher, const Currency& currency, INode& node, uint32_t transactionSoftLockTime = 1); @@ -37,6 +39,7 @@ public: virtual size_t getAddressCount() const override; virtual std::string getAddress(size_t index) const override; virtual KeyPair getAddressSpendKey(size_t index) const override; + virtual KeyPair getAddressSpendKey(const std::string& address) const override; virtual KeyPair getViewKey() const override; virtual std::string createAddress() override; virtual std::string createAddress(const Crypto::SecretKey& spendSecretKey) override; @@ -53,10 +56,19 @@ public: virtual size_t getTransactionTransferCount(size_t transactionIndex) const override; virtual WalletTransfer getTransactionTransfer(size_t transactionIndex, size_t transferIndex) const override; - virtual size_t transfer(const WalletTransfer& destination, uint64_t fee, uint64_t mixIn = 0, const std::string& extra = "", uint64_t unlockTimestamp = 0) override; - virtual size_t transfer(const std::vector& destinations, uint64_t fee, uint64_t mixIn = 0, const std::string& extra = "", uint64_t unlockTimestamp = 0) override; - 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) override; - virtual size_t transfer(const std::string& sourceAddress, const std::vector& destinations, uint64_t fee, uint64_t mixIn = 0, const std::string& extra = "", uint64_t unlockTimestamp = 0) override; + virtual WalletTransactionWithTransfers getTransaction(const Crypto::Hash& transactionHash) const override; + virtual std::vector getTransactions(const Crypto::Hash& blockHash, size_t count) const override; + virtual std::vector getTransactions(uint32_t blockIndex, size_t count) const override; + virtual std::vector getBlockHashes(uint32_t blockIndex, size_t count) const override; + virtual uint32_t getBlockCount() const override; + virtual std::vector getUnconfirmedTransactions() const override; + virtual std::vector getDelayedTransactionIds() const override; + + virtual size_t transfer(const TransactionParameters& sendingTransaction) override; + + virtual size_t makeTransaction(const TransactionParameters& sendingTransaction) override; + virtual void commitTransaction(size_t) override; + virtual void rollbackUncommitedTransaction(size_t) override; virtual void start() override; virtual void stop() override; @@ -96,9 +108,26 @@ protected: std::vector outs; }; + typedef std::pair TransfersRange; + + struct AddressAmounts { + int64_t input = 0; + int64_t output = 0; + }; + + struct ContainerAmounts { + ITransfersContainer* container; + AddressAmounts amounts; + }; + + typedef std::unordered_map TransfersMap; + virtual void onError(ITransfersSubscription* object, uint32_t height, std::error_code ec) override; + virtual void onTransactionUpdated(ITransfersSubscription* object, const Crypto::Hash& transactionHash) override; - void transactionUpdated(ITransfersSubscription* object, const Crypto::Hash& transactionHash); + virtual void onTransactionUpdated(const Crypto::PublicKey& viewPublicKey, const Crypto::Hash& transactionHash, + const std::vector& containers) override; + void transactionUpdated(const TransactionInformation& transactionInfo, const std::vector& containerAmountsList); virtual void onTransactionDeleted(ITransfersSubscription* object, const Crypto::Hash& transactionHash) override; void transactionDeleted(ITransfersSubscription* object, const Crypto::Hash& transactionHash); @@ -109,8 +138,21 @@ protected: void onSynchronizationProgressUpdated(uint32_t processedBlockCount, uint32_t totalBlockCount); void onSynchronizationCompleted(); + virtual void onBlocksAdded(const Crypto::PublicKey& viewPublicKey, const std::vector& blockHashes) override; + void blocksAdded(const std::vector& blockHashes); + + virtual void onBlockchainDetach(const Crypto::PublicKey& viewPublicKey, uint32_t blockIndex) override; + void blocksRollback(uint32_t blockIndex); + + virtual void onTransactionDeleteBegin(const Crypto::PublicKey& viewPublicKey, Crypto::Hash transactionHash) override; + void transactionDeleteBegin(Crypto::Hash transactionHash); + + virtual void onTransactionDeleteEnd(const Crypto::PublicKey& viewPublicKey, Crypto::Hash transactionHash) override; + void transactionDeleteEnd(Crypto::Hash transactionHash); + std::vector pickWalletsWithMoney() const; WalletOuts pickWallet(const std::string& address); + std::vector pickWallets(const std::vector& addresses); void updateBalance(CryptoNote::ITransfersContainer* container); void unlockBalances(uint32_t height); @@ -120,23 +162,31 @@ 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, 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); - uint64_t countSpentBalance(const WalletRecord* wallet); - void updateUsedWalletsBalances(const std::vector& selectedTransfers); + std::string addWallet(const Crypto::PublicKey& spendPublicKey, const Crypto::SecretKey& spendSecretKey, uint64_t creationTimestamp); AccountKeys makeAccountKeys(const WalletRecord& wallet) const; size_t getTransactionId(const Crypto::Hash& transactionHash) const; void pushEvent(const WalletEvent& event); bool isFusionTransaction(const WalletTransaction& walletTx) const; - size_t doTransfer(std::vector&& wallets, - const std::vector& destinations, + struct PreparedTransaction { + std::unique_ptr transaction; + std::vector destinations; + uint64_t neededMoney; + uint64_t changeAmount; + }; + + void prepareTransaction(std::vector&& wallets, + const std::vector& orders, uint64_t fee, uint64_t mixIn, const std::string& extra, - uint64_t unlockTimestamp); + uint64_t unlockTimestamp, + const DonationSettings& donation, + const CryptoNote::AccountPublicAddress& changeDestinationAddress, + PreparedTransaction& preparedTransaction); + + void validateTransactionParameters(const TransactionParameters& transactionParameters); + size_t doTransfer(const TransactionParameters& transactionParameters); void requestMixinOuts(const std::vector& selectedTransfers, uint64_t mixIn, @@ -153,28 +203,45 @@ protected: std::vector&& wallets, std::vector& selectedTransfers); - void splitDestinations(const std::vector& destinations, const WalletTransfer& changeDestination, - uint64_t dustThreshold, const Currency& currency, std::vector& decomposedOutputs); + std::vector splitDestinations(const std::vector& destinations, + uint64_t dustThreshold, const Currency& currency); + ReceiverAmounts splitAmount(uint64_t amount, const AccountPublicAddress& destination, uint64_t dustThreshold); std::unique_ptr makeTransaction(const std::vector& decomposedOutputs, std::vector& keysInfo, const std::string& extra, uint64_t unlockTimestamp); - void sendTransaction(ITransaction* tx); + void sendTransaction(const CryptoNote::Transaction& cryptoNoteTransaction); + size_t validateSaveAndSendTransaction(const ITransactionReader& transaction, const std::vector& destinations, bool isFusion, bool send); - 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 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); + size_t insertOutgoingTransactionAndPushEvent(const Crypto::Hash& transactionHash, uint64_t fee, const BinaryArray& extra, uint64_t unlockTimestamp); + void updateTransactionStateAndPushEvent(size_t transactionId, WalletTransactionState state); + bool updateWalletTransactionInfo(size_t transactionId, const CryptoNote::TransactionInformation& info, int64_t totalAmount); + bool updateTransactionTransfers(size_t transactionId, const std::vector& containerAmountsList, + int64_t allInputsAmount, int64_t allOutputsAmount); + TransfersMap getKnownTransfersMap(size_t transactionId, size_t firstTransferIdx) const; + bool updateAddressTransfers(size_t transactionId, size_t firstTransferIdx, const std::string& address, int64_t knownAmount, int64_t targetAmount); + bool updateUnknownTransfers(size_t transactionId, size_t firstTransferIdx, const std::unordered_set& myAddresses, + int64_t knownAmount, int64_t myAmount, int64_t totalAmount, bool isOutput); + void appendTransfer(size_t transactionId, size_t firstTransferIdx, const std::string& address, int64_t amount); + bool adjustTransfer(size_t transactionId, size_t firstTransferIdx, const std::string& address, int64_t amount); + bool eraseTransfers(size_t transactionId, size_t firstTransferIdx, std::function&& predicate); + bool eraseTransfersByAddress(size_t transactionId, size_t firstTransferIdx, const std::string& address, bool eraseOutputTransfers); + bool eraseForeignTransfers(size_t transactionId, size_t firstTransferIdx, const std::unordered_set& knownAddresses, bool eraseOutputTransfers); + void pushBackOutgoingTransfers(size_t txId, const std::vector& destinations); void insertUnlockTransactionJob(const Crypto::Hash& transactionHash, uint32_t blockHeight, CryptoNote::ITransfersContainer* container); void deleteUnlockTransactionJob(const Crypto::Hash& transactionHash); + void startBlockchainSynchronizer(); + void stopBlockchainSynchronizer(); + void addUnconfirmedTransaction(const ITransactionReader& transaction); + void removeUnconfirmedTransaction(const Crypto::Hash& transactionHash); void unsafeLoad(std::istream& source, const std::string& password); void unsafeSave(std::ostream& destination, bool saveDetails, bool saveCache); std::vector pickRandomFusionInputs(uint64_t threshold, size_t minInputCount, size_t maxInputCount); ReceiverAmounts decomposeFusionOutputs(uint64_t inputsAmount); + enum class WalletState { INITIALIZED, NOT_INITIALIZED @@ -188,40 +255,54 @@ protected: WalletTrackingMode getTrackingMode() const; - std::pair getTransactionTransfers(size_t transactionIndex) const; + TransfersRange getTransactionTransfersRange(size_t transactionIndex) const; + std::vector getTransactionsInBlocks(uint32_t blockIndex, size_t count) const; + Crypto::Hash getBlockHashByIndex(uint32_t blockIndex) const; + + std::vector getTransactionTransfers(const WalletTransaction& transaction) const; + void filterOutTransactions(WalletTransactions& transactions, WalletTransfers& transfers, std::function&& pred) const; + void getViewKeyKnownBlocks(const Crypto::PublicKey& viewPublicKey); + CryptoNote::AccountPublicAddress getChangeDestination(const std::string& changeDestinationAddress, const std::vector& sourceAddresses) const; + bool isMyAddress(const std::string& address) const; + + void deleteContainerFromUnlockTransactionJobs(const ITransfersContainer* container); + std::vector deleteTransfersForAddress(const std::string& address, std::vector& deletedTransactions); + void deleteFromUncommitedTransactions(const std::vector& deletedTransactions); System::Dispatcher& m_dispatcher; const Currency& m_currency; INode& m_node; - bool m_stopped = false; + bool m_stopped; WalletsContainer m_walletsContainer; - SpentOutputs m_spentOutputs; UnlockTransactionJobs m_unlockTransactionsJob; WalletTransactions m_transactions; WalletTransfers m_transfers; //sorted - TransactionChanges m_change; mutable std::unordered_map m_fusionTxsCache; // txIndex -> isFusion + UncommitedTransactions m_uncommitedTransactions; + bool m_blockchainSynchronizerStarted; BlockchainSynchronizer m_blockchainSynchronizer; TransfersSyncronizer m_synchronizer; - System::Event m_eventOccured; + System::Event m_eventOccurred; std::queue m_events; mutable System::Event m_readyEvent; - WalletState m_state = WalletState::NOT_INITIALIZED; + WalletState m_state; std::string m_password; Crypto::PublicKey m_viewPublicKey; Crypto::SecretKey m_viewSecretKey; - uint64_t m_actualBalance = 0; - uint64_t m_pendingBalance = 0; + uint64_t m_actualBalance; + uint64_t m_pendingBalance; uint64_t m_upperTransactionSizeLimit; uint32_t m_transactionSoftLockTime; + + BlockHashesContainer m_blockchain; }; } //namespace CryptoNote diff --git a/src/Wallet/WalletIndices.h b/src/Wallet/WalletIndices.h index 583fa0b0..761f5677 100644 --- a/src/Wallet/WalletIndices.h +++ b/src/Wallet/WalletIndices.h @@ -1,9 +1,10 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #pragma once +#include #include #include "ITransfersContainer.h" @@ -30,14 +31,6 @@ struct WalletRecord { time_t creationTimestamp; }; -struct SpentOutput { - uint64_t amount; - Crypto::Hash transactionHash; - uint32_t outputInTransaction; - const WalletRecord* wallet; - Crypto::Hash spendingTransactionHash; -}; - struct RandomAccessIndex {}; struct KeysIndex {}; struct TransfersContainerIndex {}; @@ -48,6 +41,7 @@ struct BlockHeightIndex {}; struct TransactionHashIndex {}; struct TransactionIndex {}; +struct BlockHashIndex {}; typedef boost::multi_index_container < WalletRecord, @@ -60,27 +54,6 @@ typedef boost::multi_index_container < > > WalletsContainer; -struct OutputIndex: boost::multi_index::composite_key < - SpentOutput, - BOOST_MULTI_INDEX_MEMBER(SpentOutput, Crypto::Hash, transactionHash), - BOOST_MULTI_INDEX_MEMBER(SpentOutput, uint32_t, outputInTransaction) -> {}; - -typedef boost::multi_index_container < - SpentOutput, - boost::multi_index::indexed_by < - boost::multi_index::hashed_unique < boost::multi_index::tag , - OutputIndex - >, - boost::multi_index::hashed_non_unique < boost::multi_index::tag , - BOOST_MULTI_INDEX_MEMBER(SpentOutput, Crypto::Hash, spendingTransactionHash) - >, - boost::multi_index::hashed_non_unique < boost::multi_index::tag , - BOOST_MULTI_INDEX_MEMBER(SpentOutput, const WalletRecord *, wallet) - > - > -> SpentOutputs; - struct UnlockTransactionJob { uint32_t blockHeight; CryptoNote::ITransfersContainer* container; @@ -93,7 +66,7 @@ typedef boost::multi_index_container < boost::multi_index::ordered_non_unique < boost::multi_index::tag , BOOST_MULTI_INDEX_MEMBER(UnlockTransactionJob, uint32_t, blockHeight) >, - boost::multi_index::hashed_unique < boost::multi_index::tag , + boost::multi_index::hashed_non_unique < boost::multi_index::tag , BOOST_MULTI_INDEX_MEMBER(UnlockTransactionJob, Crypto::Hash, transactionHash) > > @@ -105,13 +78,28 @@ typedef boost::multi_index_container < boost::multi_index::random_access < boost::multi_index::tag >, boost::multi_index::hashed_unique < boost::multi_index::tag , boost::multi_index::member + >, + boost::multi_index::ordered_non_unique < boost::multi_index::tag , + boost::multi_index::member > > > WalletTransactions; -typedef std::unordered_map TransactionChanges; - typedef std::pair TransactionTransferPair; typedef std::vector WalletTransfers; +typedef std::map UncommitedTransactions; + +typedef boost::multi_index_container< + Crypto::Hash, + boost::multi_index::indexed_by < + boost::multi_index::random_access< + boost::multi_index::tag + >, + boost::multi_index::hashed_unique< + boost::multi_index::tag, + boost::multi_index::identity + > + > +> BlockHashesContainer; } diff --git a/src/Wallet/WalletRpcServer.cpp b/src/Wallet/WalletRpcServer.cpp index 5934aace..38bd995f 100644 --- a/src/Wallet/WalletRpcServer.cpp +++ b/src/Wallet/WalletRpcServer.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Wallet/WalletRpcServer.h b/src/Wallet/WalletRpcServer.h index a5ab5fd6..e0705022 100755 --- a/src/Wallet/WalletRpcServer.h +++ b/src/Wallet/WalletRpcServer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Wallet/WalletRpcServerCommandsDefinitions.h b/src/Wallet/WalletRpcServerCommandsDefinitions.h index 1e61b24d..adc438b4 100755 --- a/src/Wallet/WalletRpcServerCommandsDefinitions.h +++ b/src/Wallet/WalletRpcServerCommandsDefinitions.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -35,7 +35,7 @@ using CryptoNote::ISerializer; }; }; - struct trnsfer_destination + struct transfer_destination { uint64_t amount; std::string address; @@ -50,7 +50,7 @@ using CryptoNote::ISerializer; { struct request { - std::list destinations; + std::list destinations; uint64_t fee; uint64_t mixin; uint64_t unlock_time; diff --git a/src/Wallet/WalletRpcServerErrorCodes.h b/src/Wallet/WalletRpcServerErrorCodes.h index 13e24451..7f386a4e 100644 --- a/src/Wallet/WalletRpcServerErrorCodes.h +++ b/src/Wallet/WalletRpcServerErrorCodes.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/Wallet/WalletSerialization.cpp b/src/Wallet/WalletSerialization.cpp index 625b0a8e..14abe821 100644 --- a/src/Wallet/WalletSerialization.cpp +++ b/src/Wallet/WalletSerialization.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -12,6 +12,7 @@ #include "Common/StdInputStream.h" #include "Common/StdOutputStream.h" #include "CryptoNoteCore/CryptoNoteSerialization.h" +#include "CryptoNoteCore/CryptoNoteTools.h" #include "Serialization/BinaryOutputStreamSerializer.h" #include "Serialization/BinaryInputStreamSerializer.h" @@ -36,7 +37,7 @@ struct WalletRecordDto { }; //DO NOT CHANGE IT -struct SpentOutputDto { +struct ObsoleteSpentOutputDto { uint64_t amount; Hash transactionHash; uint32_t outputInTransaction; @@ -45,7 +46,7 @@ struct SpentOutputDto { }; //DO NOT CHANGE IT -struct ChangeDto { +struct ObsoleteChangeDto { Hash txHash; uint64_t amount; }; @@ -86,14 +87,18 @@ struct WalletTransactionDto { //DO NOT CHANGE IT struct WalletTransferDto { - WalletTransferDto() {} - WalletTransferDto(const CryptoNote::WalletTransfer& tr) { + WalletTransferDto(uint32_t version) : version(version) {} + WalletTransferDto(const CryptoNote::WalletTransfer& tr, uint32_t version) : WalletTransferDto(version) { address = tr.address; amount = tr.amount; + type = static_cast(tr.type); } std::string address; uint64_t amount; + uint8_t type; + + uint32_t version; }; void serialize(WalletRecordDto& value, CryptoNote::ISerializer& serializer) { @@ -104,7 +109,7 @@ void serialize(WalletRecordDto& value, CryptoNote::ISerializer& serializer) { serializer(value.creationTimestamp, "creation_timestamp"); } -void serialize(SpentOutputDto& value, CryptoNote::ISerializer& serializer) { +void serialize(ObsoleteSpentOutputDto& value, CryptoNote::ISerializer& serializer) { serializer(value.amount, "amount"); serializer(value.transactionHash, "transaction_hash"); serializer(value.outputInTransaction, "output_in_transaction"); @@ -112,7 +117,7 @@ void serialize(SpentOutputDto& value, CryptoNote::ISerializer& serializer) { serializer(value.spendingTransactionHash, "spending_transaction_hash"); } -void serialize(ChangeDto& value, CryptoNote::ISerializer& serializer) { +void serialize(ObsoleteChangeDto& value, CryptoNote::ISerializer& serializer) { serializer(value.txHash, "transaction_hash"); serializer(value.amount, "amount"); } @@ -143,8 +148,11 @@ void serialize(WalletTransactionDto& value, CryptoNote::ISerializer& serializer) void serialize(WalletTransferDto& value, CryptoNote::ISerializer& serializer) { serializer(value.address, "address"); serializer(value.amount, "amount"); -} + if (value.version > 2) { + serializer(value.type, "type"); + } +} template std::string serialize(Object& obj, const std::string& name) { @@ -253,7 +261,7 @@ CryptoNote::WalletTransfer convert(const CryptoNote::WalletLegacyTransfer& tr) { namespace CryptoNote { -const uint32_t WalletSerializer::SERIALIZATION_VERSION = 2; +const uint32_t WalletSerializer::SERIALIZATION_VERSION = 5; void CryptoContext::incIv() { uint64_t * i = reinterpret_cast(&iv.data[0]); @@ -268,12 +276,11 @@ WalletSerializer::WalletSerializer( uint64_t& pendingBalance, WalletsContainer& walletsContainer, TransfersSyncronizer& synchronizer, - SpentOutputs& spentOutputs, UnlockTransactionJobs& unlockTransactions, - TransactionChanges& change, WalletTransactions& transactions, WalletTransfers& transfers, - uint32_t transactionSoftLockTime + uint32_t transactionSoftLockTime, + UncommitedTransactions& uncommitedTransactions ) : m_transfersObserver(transfersObserver), m_viewPublicKey(viewPublicKey), @@ -282,12 +289,11 @@ WalletSerializer::WalletSerializer( m_pendingBalance(pendingBalance), m_walletsContainer(walletsContainer), m_synchronizer(synchronizer), - m_spentOutputs(spentOutputs), m_unlockTransactions(unlockTransactions), - m_change(change), m_transactions(transactions), m_transfers(transfers), - m_transactionSoftLockTime(transactionSoftLockTime) + m_transactionSoftLockTime(transactionSoftLockTime), + uncommitedTransactions(uncommitedTransactions) { } void WalletSerializer::save(const std::string& password, Common::IOutputStream& destination, bool saveDetails, bool saveCache) { @@ -311,9 +317,8 @@ void WalletSerializer::save(const std::string& password, Common::IOutputStream& if (saveCache) { saveBalances(destination, saveCache, cryptoContext); saveTransfersSynchronizer(destination, cryptoContext); - saveSpentOutputs(destination, cryptoContext); saveUnlockTransactionsJobs(destination, cryptoContext); - saveChange(destination, cryptoContext); + saveUncommitedTransactions(destination, cryptoContext); } s.endObject(); @@ -406,29 +411,6 @@ void WalletSerializer::saveTransfersSynchronizer(Common::IOutputStream& destinat cryptoContext.incIv(); } -void WalletSerializer::saveSpentOutputs(Common::IOutputStream& destination, CryptoContext& cryptoContext) { - auto& index = m_spentOutputs.get(); - - uint64_t outsCount = index.size(); - serializeEncrypted(outsCount, "spent_outputs_count", cryptoContext, destination); - cryptoContext.incIv(); - - for (const auto& o: index) { - auto it = m_walletsContainer.get().iterator_to(*o.wallet); - uint64_t walletIndex = std::distance(m_walletsContainer.get().begin(), it); - - SpentOutputDto dto; - dto.amount = o.amount; - dto.transactionHash = o.transactionHash; - dto.outputInTransaction = o.outputInTransaction; - dto.walletIndex = walletIndex; - dto.spendingTransactionHash = o.spendingTransactionHash; - - serializeEncrypted(dto, "", cryptoContext, destination); - cryptoContext.incIv(); - } -} - void WalletSerializer::saveUnlockTransactionsJobs(Common::IOutputStream& destination, CryptoContext& cryptoContext) { auto& index = m_unlockTransactions.get(); auto& wallets = m_walletsContainer.get(); @@ -456,19 +438,8 @@ void WalletSerializer::saveUnlockTransactionsJobs(Common::IOutputStream& destina } } -void WalletSerializer::saveChange(Common::IOutputStream& destination, CryptoContext& cryptoContext) { - uint64_t count = m_change.size(); - serializeEncrypted(count, "changes_count", cryptoContext, destination); - cryptoContext.incIv(); - - for (const auto& kv: m_change) { - ChangeDto dto; - dto.txHash = kv.first; - dto.amount = kv.second; - - serializeEncrypted(dto, "", cryptoContext, destination); - cryptoContext.incIv(); - } +void WalletSerializer::saveUncommitedTransactions(Common::IOutputStream& destination, CryptoContext& cryptoContext) { + serializeEncrypted(uncommitedTransactions, "uncommited_transactions", cryptoContext, destination); } void WalletSerializer::saveTransactions(Common::IOutputStream& destination, CryptoContext& cryptoContext) { @@ -490,7 +461,8 @@ void WalletSerializer::saveTransfers(Common::IOutputStream& destination, CryptoC for (const auto& kv: m_transfers) { uint64_t txId = kv.first; - WalletTransferDto tr(kv.second); + + WalletTransferDto tr(kv.second, SERIALIZATION_VERSION); serializeEncrypted(txId, "transaction_id", cryptoContext, destination); cryptoContext.incIv(); @@ -506,18 +478,18 @@ void WalletSerializer::load(const std::string& password, Common::IInputStream& s uint32_t version = loadVersion(source); - if (version == SERIALIZATION_VERSION) { - loadCurrentVersion(source, password); - } else if (version == 1) { - loadWalletV1(source, password); - } else { + if (version > SERIALIZATION_VERSION) { throw std::system_error(make_error_code(error::WRONG_VERSION)); + } else if (version != 1) { + loadWallet(source, password, version); + } else { + loadWalletV1(source, password); } s.endObject(); } -void WalletSerializer::loadCurrentVersion(Common::IInputStream& source, const std::string& password) { +void WalletSerializer::loadWallet(Common::IInputStream& source, const std::string& password, uint32_t version) { CryptoNote::CryptoContext cryptoContext; bool details = false; @@ -536,15 +508,36 @@ void WalletSerializer::loadCurrentVersion(Common::IInputStream& source, const st if (details) { loadTransactions(source, cryptoContext); - loadTransfers(source, cryptoContext); + loadTransfers(source, cryptoContext, version); + } + + if (version < 5) { + updateTransfersSign(); + cache = false; } if (cache) { loadBalances(source, cryptoContext); loadTransfersSynchronizer(source, cryptoContext); - loadSpentOutputs(source, cryptoContext); + if (version < 5) { + loadObsoleteSpentOutputs(source, cryptoContext); + } + loadUnlockTransactionsJobs(source, cryptoContext); - loadChange(source, cryptoContext); + + if (version < 5) { + loadObsoleteChange(source, cryptoContext); + } + + if (version > 3) { + loadUncommitedTransactions(source, cryptoContext); + + if (version >= 5) { + initTransactionPool(); + } + } + } else { + resetCachedBalance(); } if (details && cache) { @@ -742,30 +735,15 @@ void WalletSerializer::loadTransfersSynchronizer(Common::IInputStream& source, C m_synchronizer.load(stream); } -void WalletSerializer::loadSpentOutputs(Common::IInputStream& source, CryptoContext& cryptoContext) { - auto& index = m_spentOutputs.get(); - auto& walletsIndex = m_walletsContainer.get(); - const uint64_t walletsSize = walletsIndex.size(); - +void WalletSerializer::loadObsoleteSpentOutputs(Common::IInputStream& source, CryptoContext& cryptoContext) { uint64_t count = 0; deserializeEncrypted(count, "spent_outputs_count", cryptoContext, source); cryptoContext.incIv(); for (uint64_t i = 0; i < count; ++i) { - SpentOutputDto dto; + ObsoleteSpentOutputDto dto; deserializeEncrypted(dto, "", cryptoContext, source); cryptoContext.incIv(); - - assert(dto.walletIndex < walletsSize); - - SpentOutput output; - output.amount = dto.amount; - output.transactionHash = dto.transactionHash; - output.outputInTransaction = dto.outputInTransaction; - output.spendingTransactionHash = dto.spendingTransactionHash; - output.wallet = &walletsIndex[dto.walletIndex]; - - index.insert(std::move(output)); } } @@ -794,17 +772,37 @@ void WalletSerializer::loadUnlockTransactionsJobs(Common::IInputStream& source, } } -void WalletSerializer::loadChange(Common::IInputStream& source, CryptoContext& cryptoContext) { +void WalletSerializer::loadObsoleteChange(Common::IInputStream& source, CryptoContext& cryptoContext) { uint64_t count = 0; deserializeEncrypted(count, "changes_count", cryptoContext, source); cryptoContext.incIv(); for (uint64_t i = 0; i < count; i++) { - ChangeDto dto; + ObsoleteChangeDto dto; deserializeEncrypted(dto, "", cryptoContext, source); cryptoContext.incIv(); + } +} - m_change[dto.txHash] = dto.amount; +void WalletSerializer::loadUncommitedTransactions(Common::IInputStream& source, CryptoContext& cryptoContext) { + deserializeEncrypted(uncommitedTransactions, "uncommited_transactions", cryptoContext, source); +} + +void WalletSerializer::initTransactionPool() { + std::unordered_set uncommitedTransactionsSet; + std::transform(uncommitedTransactions.begin(), uncommitedTransactions.end(), std::inserter(uncommitedTransactionsSet, uncommitedTransactionsSet.end()), + [](const UncommitedTransactions::value_type& pair) { + return getObjectHash(pair.second); + }); + m_synchronizer.initTransactionPool(uncommitedTransactionsSet); +} + +void WalletSerializer::resetCachedBalance() { + for (auto it = m_walletsContainer.begin(); it != m_walletsContainer.end(); ++it) { + m_walletsContainer.modify(it, [](WalletRecord& wallet) { + wallet.actualBalance = 0; + wallet.pendingBalance = 0; + }); } } @@ -818,9 +816,8 @@ void WalletSerializer::updateTransactionsBaseStatus() { auto& wallets = m_walletsContainer.get(); TransactionInformation txInfo; auto it = std::find_if(std::begin(wallets), std::end(wallets), [&](const WalletRecord& rec) { - int64_t id = 0; assert(rec.container != nullptr); - return rec.container->getTransactionInformation(tx.hash, txInfo, id); + return rec.container->getTransactionInformation(tx.hash, txInfo); }); tx.isBase = it != std::end(wallets) && txInfo.totalAmountIn == 0; @@ -828,6 +825,18 @@ void WalletSerializer::updateTransactionsBaseStatus() { } } +void WalletSerializer::updateTransfersSign() { + auto it = m_transfers.begin(); + while (it != m_transfers.end()) { + if (it->second.amount < 0) { + it->second.amount = -it->second.amount; + ++it; + } else { + it = m_transfers.erase(it); + } + } +} + void WalletSerializer::loadTransactions(Common::IInputStream& source, CryptoContext& cryptoContext) { uint64_t count = 0; deserializeEncrypted(count, "transactions_count", cryptoContext, source); @@ -856,7 +865,7 @@ void WalletSerializer::loadTransactions(Common::IInputStream& source, CryptoCont } } -void WalletSerializer::loadTransfers(Common::IInputStream& source, CryptoContext& cryptoContext) { +void WalletSerializer::loadTransfers(Common::IInputStream& source, CryptoContext& cryptoContext, uint32_t version) { uint64_t count = 0; deserializeEncrypted(count, "transfers_count", cryptoContext, source); cryptoContext.incIv(); @@ -868,7 +877,7 @@ void WalletSerializer::loadTransfers(Common::IInputStream& source, CryptoContext deserializeEncrypted(txId, "transaction_id", cryptoContext, source); cryptoContext.incIv(); - WalletTransferDto dto; + WalletTransferDto dto(version); deserializeEncrypted(dto, "transfer", cryptoContext, source); cryptoContext.incIv(); @@ -876,6 +885,12 @@ void WalletSerializer::loadTransfers(Common::IInputStream& source, CryptoContext tr.address = dto.address; tr.amount = dto.amount; + if (version > 2) { + tr.type = static_cast(dto.type); + } else { + tr.type = WalletTransferType::USUAL; + } + m_transfers.push_back(std::make_pair(txId, tr)); } } diff --git a/src/Wallet/WalletSerialization.h b/src/Wallet/WalletSerialization.h index fb058d51..10d1c960 100644 --- a/src/Wallet/WalletSerialization.h +++ b/src/Wallet/WalletSerialization.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -32,12 +32,11 @@ public: uint64_t& pendingBalance, WalletsContainer& walletsContainer, TransfersSyncronizer& synchronizer, - SpentOutputs& spentOutputs, UnlockTransactionJobs& unlockTransactions, - TransactionChanges& change, WalletTransactions& transactions, WalletTransfers& transfers, - uint32_t transactionSoftLockTime + uint32_t transactionSoftLockTime, + UncommitedTransactions& uncommitedTransactions ); void save(const std::string& password, Common::IOutputStream& destination, bool saveDetails, bool saveCache); @@ -46,7 +45,7 @@ public: private: static const uint32_t SERIALIZATION_VERSION; - void loadCurrentVersion(Common::IInputStream& source, const std::string& password); + void loadWallet(Common::IInputStream& source, const std::string& password, uint32_t version); void loadWalletV1(Common::IInputStream& source, const std::string& password); CryptoContext generateCryptoContext(const std::string& password); @@ -60,9 +59,8 @@ private: void saveWallets(Common::IOutputStream& destination, bool saveCache, CryptoContext& cryptoContext); void saveBalances(Common::IOutputStream& destination, bool saveCache, CryptoContext& cryptoContext); void saveTransfersSynchronizer(Common::IOutputStream& destination, CryptoContext& cryptoContext); - void saveSpentOutputs(Common::IOutputStream& destination, CryptoContext& cryptoContext); void saveUnlockTransactionsJobs(Common::IOutputStream& destination, CryptoContext& cryptoContext); - void saveChange(Common::IOutputStream& destination, CryptoContext& cryptoContext); + void saveUncommitedTransactions(Common::IOutputStream& destination, CryptoContext& cryptoContext); void saveTransactions(Common::IOutputStream& destination, CryptoContext& cryptoContext); void saveTransfers(Common::IOutputStream& destination, CryptoContext& cryptoContext); @@ -78,16 +76,20 @@ private: void subscribeWallets(); void loadBalances(Common::IInputStream& source, CryptoContext& cryptoContext); void loadTransfersSynchronizer(Common::IInputStream& source, CryptoContext& cryptoContext); - void loadSpentOutputs(Common::IInputStream& source, CryptoContext& cryptoContext); + void loadObsoleteSpentOutputs(Common::IInputStream& source, CryptoContext& cryptoContext); void loadUnlockTransactionsJobs(Common::IInputStream& source, CryptoContext& cryptoContext); - void loadChange(Common::IInputStream& source, CryptoContext& cryptoContext); + void loadObsoleteChange(Common::IInputStream& source, CryptoContext& cryptoContext); + void loadUncommitedTransactions(Common::IInputStream& source, CryptoContext& cryptoContext); void loadTransactions(Common::IInputStream& source, CryptoContext& cryptoContext); - void loadTransfers(Common::IInputStream& source, CryptoContext& cryptoContext); + void loadTransfers(Common::IInputStream& source, CryptoContext& cryptoContext, uint32_t version); void loadWalletV1Keys(CryptoNote::BinaryInputStreamSerializer& serializer); void loadWalletV1Details(CryptoNote::BinaryInputStreamSerializer& serializer); void addWalletV1Details(const std::vector& txs, const std::vector& trs); + void initTransactionPool(); + void resetCachedBalance(); void updateTransactionsBaseStatus(); + void updateTransfersSign(); ITransfersObserver& m_transfersObserver; Crypto::PublicKey& m_viewPublicKey; @@ -96,12 +98,11 @@ private: uint64_t& m_pendingBalance; WalletsContainer& m_walletsContainer; TransfersSyncronizer& m_synchronizer; - SpentOutputs& m_spentOutputs; UnlockTransactionJobs& m_unlockTransactions; - TransactionChanges& m_change; WalletTransactions& m_transactions; WalletTransfers& m_transfers; uint32_t m_transactionSoftLockTime; + UncommitedTransactions& uncommitedTransactions; }; } //namespace CryptoNote diff --git a/src/Wallet/WalletUtils.cpp b/src/Wallet/WalletUtils.cpp new file mode 100644 index 00000000..dc987693 --- /dev/null +++ b/src/Wallet/WalletUtils.cpp @@ -0,0 +1,16 @@ +// Copyright (c) 2011-2016 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "WalletUtils.h" + +#include "CryptoNote.h" + +namespace CryptoNote { + +bool validateAddress(const std::string& address, const CryptoNote::Currency& currency) { + CryptoNote::AccountPublicAddress ignore; + return currency.parseAccountAddressString(address, ignore); +} + +} diff --git a/src/Wallet/WalletUtils.h b/src/Wallet/WalletUtils.h new file mode 100644 index 00000000..6b583353 --- /dev/null +++ b/src/Wallet/WalletUtils.h @@ -0,0 +1,15 @@ +// Copyright (c) 2011-2016 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#pragma once + +#include + +#include "CryptoNoteCore/Currency.h" + +namespace CryptoNote { + +bool validateAddress(const std::string& address, const CryptoNote::Currency& currency); + +} diff --git a/src/WalletLegacy/KeysStorage.cpp b/src/WalletLegacy/KeysStorage.cpp index dc3ce85a..e9a9ae4b 100644 --- a/src/WalletLegacy/KeysStorage.cpp +++ b/src/WalletLegacy/KeysStorage.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/WalletLegacy/KeysStorage.h b/src/WalletLegacy/KeysStorage.h index d3e7fcc4..5394f87d 100644 --- a/src/WalletLegacy/KeysStorage.h +++ b/src/WalletLegacy/KeysStorage.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/WalletLegacy/WalletHelper.cpp b/src/WalletLegacy/WalletHelper.cpp index 55f94914..39446cef 100755 --- a/src/WalletLegacy/WalletHelper.cpp +++ b/src/WalletLegacy/WalletHelper.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/WalletLegacy/WalletHelper.h b/src/WalletLegacy/WalletHelper.h index ad5cbc58..69b50fd9 100755 --- a/src/WalletLegacy/WalletHelper.h +++ b/src/WalletLegacy/WalletHelper.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/WalletLegacy/WalletLegacy.cpp b/src/WalletLegacy/WalletLegacy.cpp index 069fab6b..fa4e7bbd 100644 --- a/src/WalletLegacy/WalletLegacy.cpp +++ b/src/WalletLegacy/WalletLegacy.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -81,7 +81,7 @@ public: SyncStarter(BlockchainSynchronizer& sync) : m_sync(sync) {} virtual ~SyncStarter() {} - virtual void initCompleted(std::error_code result) { + virtual void initCompleted(std::error_code result) override { if (!result) { m_sync.start(); } @@ -523,10 +523,11 @@ void WalletLegacy::onTransactionUpdated(ITransfersSubscription* object, const Ha std::shared_ptr event; TransactionInformation txInfo; - int64_t txBalance; - if (m_transferDetails->getTransactionInformation(transactionHash, txInfo, txBalance)) { + uint64_t amountIn; + uint64_t amountOut; + if (m_transferDetails->getTransactionInformation(transactionHash, txInfo, &amountIn, &amountOut)) { std::unique_lock lock(m_cacheMutex); - event = m_transactionsCache.onTransactionUpdated(txInfo, txBalance); + event = m_transactionsCache.onTransactionUpdated(txInfo, static_cast(amountOut) - static_cast(amountIn)); } if (event.get()) { diff --git a/src/WalletLegacy/WalletLegacy.h b/src/WalletLegacy/WalletLegacy.h index 27457f22..b3fce0a7 100644 --- a/src/WalletLegacy/WalletLegacy.h +++ b/src/WalletLegacy/WalletLegacy.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -40,37 +40,37 @@ public: WalletLegacy(const CryptoNote::Currency& currency, INode& node); virtual ~WalletLegacy(); - virtual void addObserver(IWalletLegacyObserver* observer); - virtual void removeObserver(IWalletLegacyObserver* observer); + virtual void addObserver(IWalletLegacyObserver* observer) override; + virtual void removeObserver(IWalletLegacyObserver* observer) override; - virtual void initAndGenerate(const std::string& password); - virtual void initAndLoad(std::istream& source, const std::string& password); - virtual void initWithKeys(const AccountKeys& accountKeys, const std::string& password); - virtual void shutdown(); - virtual void reset(); + virtual void initAndGenerate(const std::string& password) override; + virtual void initAndLoad(std::istream& source, const std::string& password) override; + virtual void initWithKeys(const AccountKeys& accountKeys, const std::string& password) override; + virtual void shutdown() override; + virtual void reset() override; - virtual void save(std::ostream& destination, bool saveDetailed = true, bool saveCache = true); + virtual void save(std::ostream& destination, bool saveDetailed = true, bool saveCache = true) override; - virtual std::error_code changePassword(const std::string& oldPassword, const std::string& newPassword); + virtual std::error_code changePassword(const std::string& oldPassword, const std::string& newPassword) override; - virtual std::string getAddress(); + virtual std::string getAddress() override; - virtual uint64_t actualBalance(); - virtual uint64_t pendingBalance(); + virtual uint64_t actualBalance() override; + virtual uint64_t pendingBalance() override; - virtual size_t getTransactionCount(); - virtual size_t getTransferCount(); + virtual size_t getTransactionCount() override; + virtual size_t getTransferCount() override; - virtual TransactionId findTransactionByTransferId(TransferId transferId); + virtual TransactionId findTransactionByTransferId(TransferId transferId) override; - virtual bool getTransaction(TransactionId transactionId, WalletLegacyTransaction& transaction); - virtual bool getTransfer(TransferId transferId, WalletLegacyTransfer& transfer); + virtual bool getTransaction(TransactionId transactionId, WalletLegacyTransaction& transaction) override; + virtual bool getTransfer(TransferId transferId, WalletLegacyTransfer& transfer) override; - virtual TransactionId sendTransaction(const WalletLegacyTransfer& transfer, uint64_t fee, const std::string& extra = "", uint64_t mixIn = 0, uint64_t unlockTimestamp = 0); - virtual TransactionId sendTransaction(const std::vector& transfers, uint64_t fee, const std::string& extra = "", uint64_t mixIn = 0, uint64_t unlockTimestamp = 0); - virtual std::error_code cancelTransaction(size_t transactionId); + virtual TransactionId sendTransaction(const WalletLegacyTransfer& transfer, uint64_t fee, const std::string& extra = "", uint64_t mixIn = 0, uint64_t unlockTimestamp = 0) override; + virtual TransactionId sendTransaction(const std::vector& transfers, uint64_t fee, const std::string& extra = "", uint64_t mixIn = 0, uint64_t unlockTimestamp = 0) override; + virtual std::error_code cancelTransaction(size_t transactionId) override; - virtual void getAccountKeys(AccountKeys& keys); + virtual void getAccountKeys(AccountKeys& keys) override; private: diff --git a/src/WalletLegacy/WalletLegacyEvent.h b/src/WalletLegacy/WalletLegacyEvent.h index e85443f6..c266e650 100755 --- a/src/WalletLegacy/WalletLegacyEvent.h +++ b/src/WalletLegacy/WalletLegacyEvent.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -25,7 +25,7 @@ public: WalletTransactionUpdatedEvent(TransactionId transactionId) : m_id(transactionId) {}; virtual ~WalletTransactionUpdatedEvent() {}; - virtual void notify(Tools::ObserverManager& observer) + virtual void notify(Tools::ObserverManager& observer) override { observer.notify(&IWalletLegacyObserver::transactionUpdated, m_id); } @@ -40,7 +40,7 @@ public: WalletSendTransactionCompletedEvent(TransactionId transactionId, std::error_code result) : m_id(transactionId), m_error(result) {}; virtual ~WalletSendTransactionCompletedEvent() {}; - virtual void notify(Tools::ObserverManager& observer) + virtual void notify(Tools::ObserverManager& observer) override { observer.notify(&IWalletLegacyObserver::sendTransactionCompleted, m_id, m_error); } @@ -56,7 +56,7 @@ public: WalletExternalTransactionCreatedEvent(TransactionId transactionId) : m_id(transactionId) {}; virtual ~WalletExternalTransactionCreatedEvent() {}; - virtual void notify(Tools::ObserverManager& observer) + virtual void notify(Tools::ObserverManager& observer) override { observer.notify(&IWalletLegacyObserver::externalTransactionCreated, m_id); } @@ -70,7 +70,7 @@ public: WalletSynchronizationProgressUpdatedEvent(uint32_t current, uint32_t total) : m_current(current), m_total(total) {}; virtual ~WalletSynchronizationProgressUpdatedEvent() {}; - virtual void notify(Tools::ObserverManager& observer) + virtual void notify(Tools::ObserverManager& observer) override { observer.notify(&IWalletLegacyObserver::synchronizationProgressUpdated, m_current, m_total); } @@ -85,7 +85,7 @@ public: WalletSynchronizationCompletedEvent(uint32_t current, uint32_t total, std::error_code result) : m_ec(result) {}; virtual ~WalletSynchronizationCompletedEvent() {}; - virtual void notify(Tools::ObserverManager& observer) { + virtual void notify(Tools::ObserverManager& observer) override { observer.notify(&IWalletLegacyObserver::synchronizationCompleted, m_ec); } @@ -99,7 +99,7 @@ public: WalletActualBalanceUpdatedEvent(uint64_t balance) : m_balance(balance) {}; virtual ~WalletActualBalanceUpdatedEvent() {}; - virtual void notify(Tools::ObserverManager& observer) + virtual void notify(Tools::ObserverManager& observer) override { observer.notify(&IWalletLegacyObserver::actualBalanceUpdated, m_balance); } @@ -113,7 +113,7 @@ public: WalletPendingBalanceUpdatedEvent(uint64_t balance) : m_balance(balance) {}; virtual ~WalletPendingBalanceUpdatedEvent() {}; - virtual void notify(Tools::ObserverManager& observer) + virtual void notify(Tools::ObserverManager& observer) override { observer.notify(&IWalletLegacyObserver::pendingBalanceUpdated, m_balance); } diff --git a/src/WalletLegacy/WalletLegacySerialization.cpp b/src/WalletLegacy/WalletLegacySerialization.cpp index c426b57c..6dfe4f54 100644 --- a/src/WalletLegacy/WalletLegacySerialization.cpp +++ b/src/WalletLegacy/WalletLegacySerialization.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/WalletLegacy/WalletLegacySerialization.h b/src/WalletLegacy/WalletLegacySerialization.h index 111bea46..f39a42d0 100644 --- a/src/WalletLegacy/WalletLegacySerialization.h +++ b/src/WalletLegacy/WalletLegacySerialization.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/WalletLegacy/WalletLegacySerializer.cpp b/src/WalletLegacy/WalletLegacySerializer.cpp index f5ebfeb7..4e85094b 100755 --- a/src/WalletLegacy/WalletLegacySerializer.cpp +++ b/src/WalletLegacy/WalletLegacySerializer.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/WalletLegacy/WalletLegacySerializer.h b/src/WalletLegacy/WalletLegacySerializer.h index a68e3e02..05fbee1d 100644 --- a/src/WalletLegacy/WalletLegacySerializer.h +++ b/src/WalletLegacy/WalletLegacySerializer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/WalletLegacy/WalletRequest.h b/src/WalletLegacy/WalletRequest.h index 70219806..6a691233 100644 --- a/src/WalletLegacy/WalletRequest.h +++ b/src/WalletLegacy/WalletRequest.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -35,7 +35,7 @@ public: virtual ~WalletGetRandomOutsByAmountsRequest() {}; - virtual void perform(INode& node, std::function cb) + virtual void perform(INode& node, std::function cb) override { node.getRandomOutsByAmounts(std::move(m_amounts), m_outsCount, std::ref(m_context->outs), std::bind(cb, m_cb, std::placeholders::_1)); }; @@ -53,7 +53,7 @@ public: WalletRelayTransactionRequest(const CryptoNote::Transaction& tx, Callback cb) : m_tx(tx), m_cb(cb) {}; virtual ~WalletRelayTransactionRequest() {}; - virtual void perform(INode& node, std::function cb) + virtual void perform(INode& node, std::function cb) override { node.relayTransaction(m_tx, std::bind(cb, m_cb, std::placeholders::_1)); } diff --git a/src/WalletLegacy/WalletSendTransactionContext.h b/src/WalletLegacy/WalletSendTransactionContext.h index 1c2d54ff..18d5cc8c 100644 --- a/src/WalletLegacy/WalletSendTransactionContext.h +++ b/src/WalletLegacy/WalletSendTransactionContext.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/WalletLegacy/WalletTransactionSender.cpp b/src/WalletLegacy/WalletTransactionSender.cpp index 09dd7661..e88e7a0b 100644 --- a/src/WalletLegacy/WalletTransactionSender.cpp +++ b/src/WalletLegacy/WalletTransactionSender.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/WalletLegacy/WalletTransactionSender.h b/src/WalletLegacy/WalletTransactionSender.h index 3ebb13fe..7bd36875 100644 --- a/src/WalletLegacy/WalletTransactionSender.h +++ b/src/WalletLegacy/WalletTransactionSender.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/WalletLegacy/WalletUnconfirmedTransactions.cpp b/src/WalletLegacy/WalletUnconfirmedTransactions.cpp index b1c2052b..a56a7501 100644 --- a/src/WalletLegacy/WalletUnconfirmedTransactions.cpp +++ b/src/WalletLegacy/WalletUnconfirmedTransactions.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/WalletLegacy/WalletUnconfirmedTransactions.h b/src/WalletLegacy/WalletUnconfirmedTransactions.h index 8beb4e06..2a446a64 100644 --- a/src/WalletLegacy/WalletUnconfirmedTransactions.h +++ b/src/WalletLegacy/WalletUnconfirmedTransactions.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/WalletLegacy/WalletUserTransactionsCache.cpp b/src/WalletLegacy/WalletUserTransactionsCache.cpp index 2b01824f..02469234 100644 --- a/src/WalletLegacy/WalletUserTransactionsCache.cpp +++ b/src/WalletLegacy/WalletUserTransactionsCache.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/WalletLegacy/WalletUserTransactionsCache.h b/src/WalletLegacy/WalletUserTransactionsCache.h index ac8ec16f..d237d3a1 100644 --- a/src/WalletLegacy/WalletUserTransactionsCache.h +++ b/src/WalletLegacy/WalletUserTransactionsCache.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/WalletLegacy/WalletUtils.h b/src/WalletLegacy/WalletUtils.h index 609e0fe5..dc03e43b 100644 --- a/src/WalletLegacy/WalletUtils.h +++ b/src/WalletLegacy/WalletUtils.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/crypto/crypto-ops-data.c b/src/crypto/crypto-ops-data.c index 7fd6cd26..ed8e5fe0 100644 --- a/src/crypto/crypto-ops-data.c +++ b/src/crypto/crypto-ops-data.c @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/crypto/crypto-ops.c b/src/crypto/crypto-ops.c index beb4e302..8de36dbf 100644 --- a/src/crypto/crypto-ops.c +++ b/src/crypto/crypto-ops.c @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/crypto/crypto.cpp b/src/crypto/crypto.cpp index 6f1a5cbd..45ecd954 100644 --- a/src/crypto/crypto.cpp +++ b/src/crypto/crypto.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h index 1ccc759b..ae3b2e3f 100644 --- a/src/crypto/crypto.h +++ b/src/crypto/crypto.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/crypto/generic-ops.h b/src/crypto/generic-ops.h index ff370926..2a03e714 100644 --- a/src/crypto/generic-ops.h +++ b/src/crypto/generic-ops.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/crypto/hash-extra-blake.c b/src/crypto/hash-extra-blake.c index 775e84f4..951e81c9 100644 --- a/src/crypto/hash-extra-blake.c +++ b/src/crypto/hash-extra-blake.c @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/crypto/hash-extra-groestl.c b/src/crypto/hash-extra-groestl.c index 2d94b189..a0c522a4 100644 --- a/src/crypto/hash-extra-groestl.c +++ b/src/crypto/hash-extra-groestl.c @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/crypto/hash-extra-jh.c b/src/crypto/hash-extra-jh.c index 95c32da2..d039d4aa 100644 --- a/src/crypto/hash-extra-jh.c +++ b/src/crypto/hash-extra-jh.c @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/crypto/hash-extra-skein.c b/src/crypto/hash-extra-skein.c index 05b81d22..2e58916d 100644 --- a/src/crypto/hash-extra-skein.c +++ b/src/crypto/hash-extra-skein.c @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/crypto/hash-ops.h b/src/crypto/hash-ops.h index c0ea36ae..015f05e2 100644 --- a/src/crypto/hash-ops.h +++ b/src/crypto/hash-ops.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/crypto/hash.c b/src/crypto/hash.c index 6ae7f760..f1e3e65f 100644 --- a/src/crypto/hash.c +++ b/src/crypto/hash.c @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/crypto/hash.h b/src/crypto/hash.h index 6277299c..a64115c7 100644 --- a/src/crypto/hash.h +++ b/src/crypto/hash.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/crypto/initializer.h b/src/crypto/initializer.h index 5506e2e4..a5c38dff 100644 --- a/src/crypto/initializer.h +++ b/src/crypto/initializer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/crypto/oaes_lib.c b/src/crypto/oaes_lib.c index 76bcaeb7..f398bfa8 100644 --- a/src/crypto/oaes_lib.c +++ b/src/crypto/oaes_lib.c @@ -34,7 +34,11 @@ static const char _NR[] = { #include #include #include +#ifdef __APPLE__ +#include +#else #include +#endif #include #include #include diff --git a/src/crypto/random.c b/src/crypto/random.c index be727cf8..03d1f6d8 100644 --- a/src/crypto/random.c +++ b/src/crypto/random.c @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/crypto/random.h b/src/crypto/random.h index 34f3075b..57fd72cc 100644 --- a/src/crypto/random.h +++ b/src/crypto/random.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/crypto/slow-hash.c b/src/crypto/slow-hash.c index d7eaeb25..6c76d5b5 100644 --- a/src/crypto/slow-hash.c +++ b/src/crypto/slow-hash.c @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/crypto/slow-hash.cpp b/src/crypto/slow-hash.cpp index 96ee3d38..75713828 100644 --- a/src/crypto/slow-hash.cpp +++ b/src/crypto/slow-hash.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/crypto/slow-hash.inl b/src/crypto/slow-hash.inl index e63c4d6e..7bbe50c1 100644 --- a/src/crypto/slow-hash.inl +++ b/src/crypto/slow-hash.inl @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -11,7 +11,7 @@ cn_slow_hash_noaesni (void *restrict context, const void *restrict data, size_t length, void *restrict hash) { #define ctx ((struct cn_ctx *) context) - uint8_t ExpandedKey[256]; + ALIGNED_DECL(uint8_t ExpandedKey[256], 16); size_t i; __m128i *longoutput, *expkey, *xmminput, b_x; ALIGNED_DECL(uint64_t a[2], 16); diff --git a/src/crypto/tree-hash.c b/src/crypto/tree-hash.c index b64e0f08..50139963 100644 --- a/src/crypto/tree-hash.c +++ b/src/crypto/tree-hash.c @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -19,23 +19,23 @@ void tree_hash(const char (*hashes)[HASH_SIZE], size_t count, char *root_hash) { size_t i, j; size_t cnt = count - 1; char (*ints)[HASH_SIZE]; - for (i = 1; i < sizeof(size_t); i <<= 1) { + for (i = 1; i < 8 * sizeof(size_t); i <<= 1) { cnt |= cnt >> i; } cnt &= ~(cnt >> 1); ints = alloca(cnt * HASH_SIZE); memcpy(ints, hashes, (2 * cnt - count) * HASH_SIZE); for (i = 2 * cnt - count, j = 2 * cnt - count; j < cnt; i += 2, ++j) { - cn_fast_hash(hashes[i], 64, ints[j]); + cn_fast_hash(hashes[i], 2 * HASH_SIZE, ints[j]); } assert(i == count); while (cnt > 2) { cnt >>= 1; for (i = 0, j = 0; j < cnt; i += 2, ++j) { - cn_fast_hash(ints[i], 64, ints[j]); + cn_fast_hash(ints[i], 2 * HASH_SIZE, ints[j]); } } - cn_fast_hash(ints[0], 64, root_hash); + cn_fast_hash(ints[0], 2 * HASH_SIZE, root_hash); } } diff --git a/src/version.h.in b/src/version.h.in index 10c74e34..cf7c25d0 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -1,4 +1,4 @@ #define BUILD_COMMIT_ID "@VERSION@" -#define PROJECT_VERSION "1.1.0" +#define PROJECT_VERSION "1.1.1" #define PROJECT_VERSION_BUILD_NO "1" #define PROJECT_VERSION_LONG PROJECT_VERSION "." PROJECT_VERSION_BUILD_NO "(" BUILD_COMMIT_ID ")" diff --git a/tests/CoreTests/AccountBoostSerialization.h b/tests/CoreTests/AccountBoostSerialization.h index ed9ab6d1..18659e07 100644 --- a/tests/CoreTests/AccountBoostSerialization.h +++ b/tests/CoreTests/AccountBoostSerialization.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/CoreTests/BlockReward.cpp b/tests/CoreTests/BlockReward.cpp index 3a829727..743a7769 100644 --- a/tests/CoreTests/BlockReward.cpp +++ b/tests/CoreTests/BlockReward.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/CoreTests/BlockReward.h b/tests/CoreTests/BlockReward.h index 881d7e62..7c3cae84 100644 --- a/tests/CoreTests/BlockReward.h +++ b/tests/CoreTests/BlockReward.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/CoreTests/BlockValidation.cpp b/tests/CoreTests/BlockValidation.cpp index ce9a9d17..a18bb1a5 100644 --- a/tests/CoreTests/BlockValidation.cpp +++ b/tests/CoreTests/BlockValidation.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/CoreTests/BlockValidation.h b/tests/CoreTests/BlockValidation.h index 4797b979..c249fef6 100644 --- a/tests/CoreTests/BlockValidation.h +++ b/tests/CoreTests/BlockValidation.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/CoreTests/BoostSerializationHelper.h b/tests/CoreTests/BoostSerializationHelper.h index 837525cd..34a45f4d 100755 --- a/tests/CoreTests/BoostSerializationHelper.h +++ b/tests/CoreTests/BoostSerializationHelper.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/CoreTests/ChainSplit1.cpp b/tests/CoreTests/ChainSplit1.cpp index 67c940b3..3ec59bd7 100644 --- a/tests/CoreTests/ChainSplit1.cpp +++ b/tests/CoreTests/ChainSplit1.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/CoreTests/ChainSplit1.h b/tests/CoreTests/ChainSplit1.h index c77d85e4..2bda22c5 100644 --- a/tests/CoreTests/ChainSplit1.h +++ b/tests/CoreTests/ChainSplit1.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/CoreTests/ChainSwitch1.cpp b/tests/CoreTests/ChainSwitch1.cpp index a7544f27..7a6f622e 100644 --- a/tests/CoreTests/ChainSwitch1.cpp +++ b/tests/CoreTests/ChainSwitch1.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/CoreTests/ChainSwitch1.h b/tests/CoreTests/ChainSwitch1.h index 636ff889..5666c167 100644 --- a/tests/CoreTests/ChainSwitch1.h +++ b/tests/CoreTests/ChainSwitch1.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/CoreTests/Chaingen.cpp b/tests/CoreTests/Chaingen.cpp index 986135d8..a26e2e34 100644 --- a/tests/CoreTests/Chaingen.cpp +++ b/tests/CoreTests/Chaingen.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/CoreTests/Chaingen.h b/tests/CoreTests/Chaingen.h index 507aa306..576a38ec 100644 --- a/tests/CoreTests/Chaingen.h +++ b/tests/CoreTests/Chaingen.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/CoreTests/Chaingen001.cpp b/tests/CoreTests/Chaingen001.cpp index 035dc428..b2487c44 100644 --- a/tests/CoreTests/Chaingen001.cpp +++ b/tests/CoreTests/Chaingen001.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/CoreTests/Chaingen001.h b/tests/CoreTests/Chaingen001.h index 14cb3ab3..24489d9a 100644 --- a/tests/CoreTests/Chaingen001.h +++ b/tests/CoreTests/Chaingen001.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/CoreTests/ChaingenMain.cpp b/tests/CoreTests/ChaingenMain.cpp index b367040c..e6caab44 100644 --- a/tests/CoreTests/ChaingenMain.cpp +++ b/tests/CoreTests/ChaingenMain.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/CoreTests/CryptoNoteBoostSerialization.h b/tests/CoreTests/CryptoNoteBoostSerialization.h index 0a5e8a0f..b3c9c0e1 100755 --- a/tests/CoreTests/CryptoNoteBoostSerialization.h +++ b/tests/CoreTests/CryptoNoteBoostSerialization.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/CoreTests/DoubleSpend.cpp b/tests/CoreTests/DoubleSpend.cpp index 308fe4b1..247f4354 100644 --- a/tests/CoreTests/DoubleSpend.cpp +++ b/tests/CoreTests/DoubleSpend.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/CoreTests/DoubleSpend.h b/tests/CoreTests/DoubleSpend.h index d6accc63..2ab20389 100644 --- a/tests/CoreTests/DoubleSpend.h +++ b/tests/CoreTests/DoubleSpend.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/CoreTests/IntegerOverflow.cpp b/tests/CoreTests/IntegerOverflow.cpp index 02d38b35..9dec5b1e 100644 --- a/tests/CoreTests/IntegerOverflow.cpp +++ b/tests/CoreTests/IntegerOverflow.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/CoreTests/IntegerOverflow.h b/tests/CoreTests/IntegerOverflow.h index a366eb2d..a8804ffe 100644 --- a/tests/CoreTests/IntegerOverflow.h +++ b/tests/CoreTests/IntegerOverflow.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/CoreTests/RandomOuts.cpp b/tests/CoreTests/RandomOuts.cpp index 1ca1316f..f4196451 100644 --- a/tests/CoreTests/RandomOuts.cpp +++ b/tests/CoreTests/RandomOuts.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/CoreTests/RandomOuts.h b/tests/CoreTests/RandomOuts.h index b0bc8ca2..91f5d37a 100644 --- a/tests/CoreTests/RandomOuts.h +++ b/tests/CoreTests/RandomOuts.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/CoreTests/RingSignature.cpp b/tests/CoreTests/RingSignature.cpp index ae134d0a..58352c8a 100644 --- a/tests/CoreTests/RingSignature.cpp +++ b/tests/CoreTests/RingSignature.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/CoreTests/RingSignature.h b/tests/CoreTests/RingSignature.h index 40c807f3..ad031f28 100644 --- a/tests/CoreTests/RingSignature.h +++ b/tests/CoreTests/RingSignature.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/CoreTests/TestGenerator.h b/tests/CoreTests/TestGenerator.h index ea6534f4..62ef543b 100644 --- a/tests/CoreTests/TestGenerator.h +++ b/tests/CoreTests/TestGenerator.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/CoreTests/TransactionBuilder.cpp b/tests/CoreTests/TransactionBuilder.cpp index 90f79315..2cfd333a 100644 --- a/tests/CoreTests/TransactionBuilder.cpp +++ b/tests/CoreTests/TransactionBuilder.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/CoreTests/TransactionBuilder.h b/tests/CoreTests/TransactionBuilder.h index 51307dbd..673521b3 100644 --- a/tests/CoreTests/TransactionBuilder.h +++ b/tests/CoreTests/TransactionBuilder.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/CoreTests/TransactionTests.cpp b/tests/CoreTests/TransactionTests.cpp index a82d444a..7bcab93e 100644 --- a/tests/CoreTests/TransactionTests.cpp +++ b/tests/CoreTests/TransactionTests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/CoreTests/TransactionTests.h b/tests/CoreTests/TransactionTests.h index 9b5292ab..07f50f94 100644 --- a/tests/CoreTests/TransactionTests.h +++ b/tests/CoreTests/TransactionTests.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/CoreTests/TransactionValidation.cpp b/tests/CoreTests/TransactionValidation.cpp index f45c560d..0f241f11 100644 --- a/tests/CoreTests/TransactionValidation.cpp +++ b/tests/CoreTests/TransactionValidation.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/CoreTests/TransactionValidation.h b/tests/CoreTests/TransactionValidation.h index a08289b9..b5836dff 100644 --- a/tests/CoreTests/TransactionValidation.h +++ b/tests/CoreTests/TransactionValidation.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/CoreTests/UnorderedContainersBoostSerialization.h b/tests/CoreTests/UnorderedContainersBoostSerialization.h index 709462b6..a5b70c2d 100644 --- a/tests/CoreTests/UnorderedContainersBoostSerialization.h +++ b/tests/CoreTests/UnorderedContainersBoostSerialization.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/CoreTests/double_spend.inl b/tests/CoreTests/double_spend.inl index 43a72db5..dcb855cd 100644 --- a/tests/CoreTests/double_spend.inl +++ b/tests/CoreTests/double_spend.inl @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/Difficulty/Difficulty.cpp b/tests/Difficulty/Difficulty.cpp index ac27103b..02bb6913 100644 --- a/tests/Difficulty/Difficulty.cpp +++ b/tests/Difficulty/Difficulty.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/Hash/main.cpp b/tests/Hash/main.cpp index 96a6d24a..b1fe91d9 100644 --- a/tests/Hash/main.cpp +++ b/tests/Hash/main.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/HashTarget.cpp b/tests/HashTarget.cpp index c21c2004..562b29c0 100644 --- a/tests/HashTarget.cpp +++ b/tests/HashTarget.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/IntegrationTestLib/BaseFunctionalTests.cpp b/tests/IntegrationTestLib/BaseFunctionalTests.cpp index 693e1fd8..1fbbc2f3 100755 --- a/tests/IntegrationTestLib/BaseFunctionalTests.cpp +++ b/tests/IntegrationTestLib/BaseFunctionalTests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/IntegrationTestLib/BaseFunctionalTests.h b/tests/IntegrationTestLib/BaseFunctionalTests.h index 08c97f0c..80f49f93 100644 --- a/tests/IntegrationTestLib/BaseFunctionalTests.h +++ b/tests/IntegrationTestLib/BaseFunctionalTests.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/IntegrationTestLib/InProcTestNode.cpp b/tests/IntegrationTestLib/InProcTestNode.cpp index 2107f6a7..10cdb609 100644 --- a/tests/IntegrationTestLib/InProcTestNode.cpp +++ b/tests/IntegrationTestLib/InProcTestNode.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/IntegrationTestLib/InProcTestNode.h b/tests/IntegrationTestLib/InProcTestNode.h index 8a9c57d6..5db3552f 100644 --- a/tests/IntegrationTestLib/InProcTestNode.h +++ b/tests/IntegrationTestLib/InProcTestNode.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/IntegrationTestLib/Logger.cpp b/tests/IntegrationTestLib/Logger.cpp index 23c2192d..4b54acf3 100644 --- a/tests/IntegrationTestLib/Logger.cpp +++ b/tests/IntegrationTestLib/Logger.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/IntegrationTestLib/Logger.h b/tests/IntegrationTestLib/Logger.h index 28921c74..e396d372 100644 --- a/tests/IntegrationTestLib/Logger.h +++ b/tests/IntegrationTestLib/Logger.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/IntegrationTestLib/NetworkConfiguration.h b/tests/IntegrationTestLib/NetworkConfiguration.h index 12309ea3..79f2d017 100644 --- a/tests/IntegrationTestLib/NetworkConfiguration.h +++ b/tests/IntegrationTestLib/NetworkConfiguration.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/IntegrationTestLib/NodeCallback.h b/tests/IntegrationTestLib/NodeCallback.h index 99776502..3a7a619e 100644 --- a/tests/IntegrationTestLib/NodeCallback.h +++ b/tests/IntegrationTestLib/NodeCallback.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/IntegrationTestLib/NodeObserver.h b/tests/IntegrationTestLib/NodeObserver.h index 9162a4f3..ce05a79f 100644 --- a/tests/IntegrationTestLib/NodeObserver.h +++ b/tests/IntegrationTestLib/NodeObserver.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/IntegrationTestLib/ObservableValue.h b/tests/IntegrationTestLib/ObservableValue.h index ef09f5b8..140e348c 100644 --- a/tests/IntegrationTestLib/ObservableValue.h +++ b/tests/IntegrationTestLib/ObservableValue.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/IntegrationTestLib/Process.cpp b/tests/IntegrationTestLib/Process.cpp index f26a47b7..8c3e4b31 100644 --- a/tests/IntegrationTestLib/Process.cpp +++ b/tests/IntegrationTestLib/Process.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/IntegrationTestLib/Process.h b/tests/IntegrationTestLib/Process.h index 4a48dc65..c1a09333 100644 --- a/tests/IntegrationTestLib/Process.h +++ b/tests/IntegrationTestLib/Process.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/IntegrationTestLib/RPCTestNode.cpp b/tests/IntegrationTestLib/RPCTestNode.cpp index 301e456e..45f2cc89 100755 --- a/tests/IntegrationTestLib/RPCTestNode.cpp +++ b/tests/IntegrationTestLib/RPCTestNode.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/IntegrationTestLib/RPCTestNode.h b/tests/IntegrationTestLib/RPCTestNode.h index 36709a92..d943ded3 100644 --- a/tests/IntegrationTestLib/RPCTestNode.h +++ b/tests/IntegrationTestLib/RPCTestNode.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/IntegrationTestLib/TestNetwork.cpp b/tests/IntegrationTestLib/TestNetwork.cpp index d8427ae3..29a8f6a3 100644 --- a/tests/IntegrationTestLib/TestNetwork.cpp +++ b/tests/IntegrationTestLib/TestNetwork.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/IntegrationTestLib/TestNetwork.h b/tests/IntegrationTestLib/TestNetwork.h index 9b1ceeaa..0e239fb2 100644 --- a/tests/IntegrationTestLib/TestNetwork.h +++ b/tests/IntegrationTestLib/TestNetwork.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/IntegrationTestLib/TestNode.h b/tests/IntegrationTestLib/TestNode.h index e29813f2..7f178125 100755 --- a/tests/IntegrationTestLib/TestNode.h +++ b/tests/IntegrationTestLib/TestNode.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/IntegrationTestLib/TestWalletLegacy.cpp b/tests/IntegrationTestLib/TestWalletLegacy.cpp index d129d3b1..aefb5490 100644 --- a/tests/IntegrationTestLib/TestWalletLegacy.cpp +++ b/tests/IntegrationTestLib/TestWalletLegacy.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -57,7 +57,7 @@ namespace { m_waiting = false; } - virtual void sendTransactionCompleted(TransactionId transactionId, std::error_code result) { + virtual void sendTransactionCompleted(TransactionId transactionId, std::error_code result) override { m_dispatcher.remoteSpawn([this, transactionId, result]() { if (m_waiting && m_expectedTxId == transactionId) { m_result = result; diff --git a/tests/IntegrationTestLib/TestWalletLegacy.h b/tests/IntegrationTestLib/TestWalletLegacy.h index 5bd192b2..8c8c3db6 100644 --- a/tests/IntegrationTestLib/TestWalletLegacy.h +++ b/tests/IntegrationTestLib/TestWalletLegacy.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/IntegrationTests/BaseTests.h b/tests/IntegrationTests/BaseTests.h index b2845372..c4629a44 100644 --- a/tests/IntegrationTests/BaseTests.h +++ b/tests/IntegrationTests/BaseTests.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/IntegrationTests/IntegrationTests.cpp b/tests/IntegrationTests/IntegrationTests.cpp index 4238e9be..18dec417 100644 --- a/tests/IntegrationTests/IntegrationTests.cpp +++ b/tests/IntegrationTests/IntegrationTests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/IntegrationTests/MultiVersion.cpp b/tests/IntegrationTests/MultiVersion.cpp index 6d6c930b..a02ed7ce 100644 --- a/tests/IntegrationTests/MultiVersion.cpp +++ b/tests/IntegrationTests/MultiVersion.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/IntegrationTests/Node.cpp b/tests/IntegrationTests/Node.cpp index f78adeee..8a942ffc 100644 --- a/tests/IntegrationTests/Node.cpp +++ b/tests/IntegrationTests/Node.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/IntegrationTests/WalletLegacyObserver.h b/tests/IntegrationTests/WalletLegacyObserver.h index d6c3836b..7ccf9c77 100644 --- a/tests/IntegrationTests/WalletLegacyObserver.h +++ b/tests/IntegrationTests/WalletLegacyObserver.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/IntegrationTests/WalletLegacyTests.cpp b/tests/IntegrationTests/WalletLegacyTests.cpp index 811f5e61..272415c3 100644 --- a/tests/IntegrationTests/WalletLegacyTests.cpp +++ b/tests/IntegrationTests/WalletLegacyTests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/IntegrationTests/main.cpp b/tests/IntegrationTests/main.cpp index 6edca56d..4e84488e 100644 --- a/tests/IntegrationTests/main.cpp +++ b/tests/IntegrationTests/main.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -107,7 +107,7 @@ public: public: WaitForActualGrowObserver(Tests::Common::Semaphore& GotActual, uint64_t lastFunds) : m_GotActual(GotActual), m_lastFunds(lastFunds) { } - virtual void actualBalanceUpdated(uint64_t actualBalance) { + virtual void actualBalanceUpdated(uint64_t actualBalance) override { if (m_lastFunds < actualBalance) { m_GotActual.notify(); } @@ -123,7 +123,7 @@ public: public: WaitForActualDwindleObserver(Tests::Common::Semaphore& GotActual, uint64_t lastFunds) : m_GotActual(GotActual), m_lastFunds(lastFunds) { } - virtual void actualBalanceUpdated(uint64_t actualBalance) { + virtual void actualBalanceUpdated(uint64_t actualBalance) override { if (m_lastFunds > actualBalance) { m_GotActual.notify(); } @@ -139,7 +139,7 @@ public: public: WaitForPendingGrowObserver(Tests::Common::Semaphore& GotActual, uint64_t lastFunds) : m_GotActual(GotActual), m_lastFunds(lastFunds) { } - virtual void pendingBalanceUpdated(uint64_t pendingBalance) { + virtual void pendingBalanceUpdated(uint64_t pendingBalance) override { if (m_lastFunds < pendingBalance) { m_GotActual.notify(); } diff --git a/tests/Io.h b/tests/Io.h index d7c3fc56..c56b2ee2 100644 --- a/tests/Io.h +++ b/tests/Io.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/NodeRpcProxyTests/NodeRpcProxyTests.cpp b/tests/NodeRpcProxyTests/NodeRpcProxyTests.cpp index 646b4460..00135f1c 100755 --- a/tests/NodeRpcProxyTests/NodeRpcProxyTests.cpp +++ b/tests/NodeRpcProxyTests/NodeRpcProxyTests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -26,7 +26,7 @@ public: virtual ~NodeObserver() { } - virtual void peerCountUpdated(size_t count) { + virtual void peerCountUpdated(size_t count) override { logger(INFO) << '[' << m_name << "] peerCountUpdated " << count << " = " << m_nodeProxy.getPeerCount(); } diff --git a/tests/PerformanceTests/CheckRingSignature.h b/tests/PerformanceTests/CheckRingSignature.h index 6f3d3e8d..b0d93a53 100644 --- a/tests/PerformanceTests/CheckRingSignature.h +++ b/tests/PerformanceTests/CheckRingSignature.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/PerformanceTests/ConstructTransaction.h b/tests/PerformanceTests/ConstructTransaction.h index b2071787..99479678 100644 --- a/tests/PerformanceTests/ConstructTransaction.h +++ b/tests/PerformanceTests/ConstructTransaction.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/PerformanceTests/CryptoNoteSlowHash.h b/tests/PerformanceTests/CryptoNoteSlowHash.h index 3885ba26..f0a765b6 100644 --- a/tests/PerformanceTests/CryptoNoteSlowHash.h +++ b/tests/PerformanceTests/CryptoNoteSlowHash.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/PerformanceTests/DerivePublicKey.h b/tests/PerformanceTests/DerivePublicKey.h index f36d6d96..6d84e0e8 100644 --- a/tests/PerformanceTests/DerivePublicKey.h +++ b/tests/PerformanceTests/DerivePublicKey.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/PerformanceTests/DeriveSecretKey.h b/tests/PerformanceTests/DeriveSecretKey.h index 5cfa92c1..748a4d5f 100644 --- a/tests/PerformanceTests/DeriveSecretKey.h +++ b/tests/PerformanceTests/DeriveSecretKey.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/PerformanceTests/GenerateKeyDerivation.h b/tests/PerformanceTests/GenerateKeyDerivation.h index d76154a4..ffd63c9e 100644 --- a/tests/PerformanceTests/GenerateKeyDerivation.h +++ b/tests/PerformanceTests/GenerateKeyDerivation.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/PerformanceTests/GenerateKeyImage.h b/tests/PerformanceTests/GenerateKeyImage.h index 425f6f3b..a6291780 100644 --- a/tests/PerformanceTests/GenerateKeyImage.h +++ b/tests/PerformanceTests/GenerateKeyImage.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/PerformanceTests/GenerateKeyImageHelper.h b/tests/PerformanceTests/GenerateKeyImageHelper.h index 8c2fc92d..e07e47f7 100644 --- a/tests/PerformanceTests/GenerateKeyImageHelper.h +++ b/tests/PerformanceTests/GenerateKeyImageHelper.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/PerformanceTests/IsOutToAccount.h b/tests/PerformanceTests/IsOutToAccount.h index 26ecc0cf..32b64608 100644 --- a/tests/PerformanceTests/IsOutToAccount.h +++ b/tests/PerformanceTests/IsOutToAccount.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/PerformanceTests/MultiTransactionTestBase.h b/tests/PerformanceTests/MultiTransactionTestBase.h index d1b037ce..a50b1efd 100644 --- a/tests/PerformanceTests/MultiTransactionTestBase.h +++ b/tests/PerformanceTests/MultiTransactionTestBase.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/PerformanceTests/PerformanceTests.h b/tests/PerformanceTests/PerformanceTests.h index d5060d08..33e5b34c 100644 --- a/tests/PerformanceTests/PerformanceTests.h +++ b/tests/PerformanceTests/PerformanceTests.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/PerformanceTests/PerformanceUtils.h b/tests/PerformanceTests/PerformanceUtils.h index 4f5bff84..d22f625e 100644 --- a/tests/PerformanceTests/PerformanceUtils.h +++ b/tests/PerformanceTests/PerformanceUtils.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/PerformanceTests/SingleTransactionTestBase.h b/tests/PerformanceTests/SingleTransactionTestBase.h index 7f6c9541..bdc0b0a8 100644 --- a/tests/PerformanceTests/SingleTransactionTestBase.h +++ b/tests/PerformanceTests/SingleTransactionTestBase.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/PerformanceTests/main.cpp b/tests/PerformanceTests/main.cpp index 47264125..7d3e1543 100644 --- a/tests/PerformanceTests/main.cpp +++ b/tests/PerformanceTests/main.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/System/ContextGroupTests.cpp b/tests/System/ContextGroupTests.cpp index f9b751fc..3814fabb 100755 --- a/tests/System/ContextGroupTests.cpp +++ b/tests/System/ContextGroupTests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/System/ContextGroupTimeoutTests.cpp b/tests/System/ContextGroupTimeoutTests.cpp index b1a7ba78..6e02dd60 100644 --- a/tests/System/ContextGroupTimeoutTests.cpp +++ b/tests/System/ContextGroupTimeoutTests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/System/ContextTests.cpp b/tests/System/ContextTests.cpp index 7e694a8e..36538ac0 100755 --- a/tests/System/ContextTests.cpp +++ b/tests/System/ContextTests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/System/DispatcherTests.cpp b/tests/System/DispatcherTests.cpp index 5daaf09e..ba53fd11 100755 --- a/tests/System/DispatcherTests.cpp +++ b/tests/System/DispatcherTests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/System/ErrorMessageTests.cpp b/tests/System/ErrorMessageTests.cpp index de48509b..eb21aa49 100644 --- a/tests/System/ErrorMessageTests.cpp +++ b/tests/System/ErrorMessageTests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/System/EventLockTests.cpp b/tests/System/EventLockTests.cpp index 739e4902..db1969cc 100755 --- a/tests/System/EventLockTests.cpp +++ b/tests/System/EventLockTests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/System/EventTests.cpp b/tests/System/EventTests.cpp index 83dfc534..5dc1c9be 100755 --- a/tests/System/EventTests.cpp +++ b/tests/System/EventTests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -29,7 +29,7 @@ TEST(EventTests, eventIsWorking) { TEST(EventTests, movedEventIsWorking) { Dispatcher dispatcher; - Event event(std::move(Event(dispatcher))); + Event event{Event(dispatcher)}; Context<> context(dispatcher, [&]() { event.set(); }); diff --git a/tests/System/Ipv4AddressTests.cpp b/tests/System/Ipv4AddressTests.cpp index 1868c5fb..17cfc6ec 100755 --- a/tests/System/Ipv4AddressTests.cpp +++ b/tests/System/Ipv4AddressTests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/System/Ipv4ResolverTests.cpp b/tests/System/Ipv4ResolverTests.cpp index 602ef763..4ad27bdf 100755 --- a/tests/System/Ipv4ResolverTests.cpp +++ b/tests/System/Ipv4ResolverTests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/System/OperationTimeoutTests.cpp b/tests/System/OperationTimeoutTests.cpp index b7ca015d..1fe5d309 100644 --- a/tests/System/OperationTimeoutTests.cpp +++ b/tests/System/OperationTimeoutTests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/System/RemoteContextTests.cpp b/tests/System/RemoteContextTests.cpp index 29dc63dc..12d49b44 100644 --- a/tests/System/RemoteContextTests.cpp +++ b/tests/System/RemoteContextTests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/System/TcpConnectionTests.cpp b/tests/System/TcpConnectionTests.cpp index 3483ed55..2bbcd024 100755 --- a/tests/System/TcpConnectionTests.cpp +++ b/tests/System/TcpConnectionTests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/System/TcpConnectorTests.cpp b/tests/System/TcpConnectorTests.cpp index 620fbbf1..10c91aaf 100755 --- a/tests/System/TcpConnectorTests.cpp +++ b/tests/System/TcpConnectorTests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/System/TcpListenerTests.cpp b/tests/System/TcpListenerTests.cpp index cf19c8a8..07ea2345 100755 --- a/tests/System/TcpListenerTests.cpp +++ b/tests/System/TcpListenerTests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/System/TimerTests.cpp b/tests/System/TimerTests.cpp index b6405be9..0b2a5601 100755 --- a/tests/System/TimerTests.cpp +++ b/tests/System/TimerTests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -34,7 +34,7 @@ TEST_F(TimerTests, timerIsWorking) { } TEST_F(TimerTests, movedTimerIsWorking) { - Timer t(std::move(Timer(dispatcher))); + Timer t{Timer{dispatcher}}; bool done = false; contextGroup.spawn([&]() { done = true; @@ -130,7 +130,7 @@ TEST_F(TimerTests, movedTimerIsWorking2) { bool done = false; contextGroup.spawn([&] { Timer t(dispatcher); - t = std::move(Timer(dispatcher)); + t = Timer{dispatcher}; //contextGroup.spawn([&]() { done = true; }); ASSERT_FALSE(done); diff --git a/tests/System/main.cpp b/tests/System/main.cpp index 996749f9..5bbbe9c1 100755 --- a/tests/System/main.cpp +++ b/tests/System/main.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/TestGenerator/TestGenerator.cpp b/tests/TestGenerator/TestGenerator.cpp index c26d36d5..14611327 100644 --- a/tests/TestGenerator/TestGenerator.cpp +++ b/tests/TestGenerator/TestGenerator.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/TestGenerator/TestGenerator.h b/tests/TestGenerator/TestGenerator.h index 088acac0..2eb49126 100644 --- a/tests/TestGenerator/TestGenerator.h +++ b/tests/TestGenerator/TestGenerator.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/TransfersTests/Globals.h b/tests/TransfersTests/Globals.h index d42fc747..4a8b7776 100644 --- a/tests/TransfersTests/Globals.h +++ b/tests/TransfersTests/Globals.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/TransfersTests/TestNodeRpcProxy.cpp b/tests/TransfersTests/TestNodeRpcProxy.cpp index 2f05d67e..3273cae5 100755 --- a/tests/TransfersTests/TestNodeRpcProxy.cpp +++ b/tests/TransfersTests/TestNodeRpcProxy.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -34,7 +34,7 @@ namespace { class PoolChangedObserver : public INodeObserver { public: - virtual void poolChanged() { + virtual void poolChanged() override { std::unique_lock lk(mutex); ready = true; cv.notify_all(); diff --git a/tests/TransfersTests/TestTxPoolSync.cpp b/tests/TransfersTests/TestTxPoolSync.cpp index ccedad9d..18a8d2ba 100755 --- a/tests/TransfersTests/TestTxPoolSync.cpp +++ b/tests/TransfersTests/TestTxPoolSync.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/TransfersTests/Tests.cpp b/tests/TransfersTests/Tests.cpp index 8ce91e27..8d23da60 100644 --- a/tests/TransfersTests/Tests.cpp +++ b/tests/TransfersTests/Tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -30,13 +30,13 @@ public: class WalletLegacyObserver : public IWalletLegacyObserver { public: - virtual void actualBalanceUpdated(uint64_t actualBalance) { + virtual void actualBalanceUpdated(uint64_t actualBalance) override { std::cout << "Actual balance updated = " << currency.formatAmount(actualBalance) << std::endl; m_actualBalance = actualBalance; m_sem.notify(); } - virtual void sendTransactionCompleted(TransactionId transactionId, std::error_code result) { + virtual void sendTransactionCompleted(TransactionId transactionId, std::error_code result) override { std::cout << "Transaction sent, result = " << result << std::endl; } @@ -86,7 +86,25 @@ public: return std::error_code(); } - void getKnownPoolTxIds(std::vector& ids) override { + const std::unordered_set& getKnownPoolTxIds() const override { + //stub + static std::unordered_set empty; + return empty; + } + + std::error_code addUnconfirmedTransaction(const ITransactionReader& /*transaction*/) override { + throw std::runtime_error("Not implemented"); + } + + void removeUnconfirmedTransaction(const Crypto::Hash& /*transactionHash*/) override { + throw std::runtime_error("Not implemented"); + } + + virtual void addObserver(IBlockchainConsumerObserver* observer) override { + //stub + } + + virtual void removeObserver(IBlockchainConsumerObserver* observer) override { //stub } diff --git a/tests/TransfersTests/main.cpp b/tests/TransfersTests/main.cpp index a243fcdb..c85d7b43 100644 --- a/tests/TransfersTests/main.cpp +++ b/tests/TransfersTests/main.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/ArrayRefTests.cpp b/tests/UnitTests/ArrayRefTests.cpp index 44903311..a15468d9 100755 --- a/tests/UnitTests/ArrayRefTests.cpp +++ b/tests/UnitTests/ArrayRefTests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/ArrayViewTests.cpp b/tests/UnitTests/ArrayViewTests.cpp index 5aef1a1d..0a1d8776 100755 --- a/tests/UnitTests/ArrayViewTests.cpp +++ b/tests/UnitTests/ArrayViewTests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/Base58.cpp b/tests/UnitTests/Base58.cpp index b962e6d5..8b010c29 100644 --- a/tests/UnitTests/Base58.cpp +++ b/tests/UnitTests/Base58.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/BlockReward.cpp b/tests/UnitTests/BlockReward.cpp index 34d6dc79..cfe09034 100644 --- a/tests/UnitTests/BlockReward.cpp +++ b/tests/UnitTests/BlockReward.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -80,7 +80,7 @@ namespace protected: static const uint64_t alreadyGeneratedCoins = 0; - virtual void SetUp() { + virtual void SetUp() override { m_blockTooBig = !m_currency.getBlockReward(0, 0, alreadyGeneratedCoins, 0, m_standardBlockReward, m_emissionChange); ASSERT_FALSE(m_blockTooBig); @@ -177,7 +177,7 @@ namespace static const size_t testMedian = 7 * TEST_GRANTED_FULL_REWARD_ZONE; static const uint64_t alreadyGeneratedCoins = 0; - virtual void SetUp() { + virtual void SetUp() override { m_blockTooBig = !m_currency.getBlockReward(testMedian, 0, alreadyGeneratedCoins, 0, m_standardBlockReward, m_emissionChange); @@ -280,7 +280,7 @@ namespace } protected: - virtual void SetUp() { + virtual void SetUp() override { uint64_t blockReward; int64_t emissionChange; diff --git a/tests/UnitTests/BlockingQueue.cpp b/tests/UnitTests/BlockingQueue.cpp index 2ff39e0e..b0e47d9d 100644 --- a/tests/UnitTests/BlockingQueue.cpp +++ b/tests/UnitTests/BlockingQueue.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/Chacha8.cpp b/tests/UnitTests/Chacha8.cpp index f1d2fa38..01d0e844 100644 --- a/tests/UnitTests/Chacha8.cpp +++ b/tests/UnitTests/Chacha8.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/Checkpoints.cpp b/tests/UnitTests/Checkpoints.cpp index 1ccf5a97..bd41c968 100644 --- a/tests/UnitTests/Checkpoints.cpp +++ b/tests/UnitTests/Checkpoints.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/DecomposeAmountIntoDigits.cpp b/tests/UnitTests/DecomposeAmountIntoDigits.cpp index 3cbdf9c2..22e0de60 100644 --- a/tests/UnitTests/DecomposeAmountIntoDigits.cpp +++ b/tests/UnitTests/DecomposeAmountIntoDigits.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/EventWaiter.cpp b/tests/UnitTests/EventWaiter.cpp index a58288af..e01238eb 100644 --- a/tests/UnitTests/EventWaiter.cpp +++ b/tests/UnitTests/EventWaiter.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/EventWaiter.h b/tests/UnitTests/EventWaiter.h index a54d94c1..f0ab434d 100644 --- a/tests/UnitTests/EventWaiter.h +++ b/tests/UnitTests/EventWaiter.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/ICoreStub.cpp b/tests/UnitTests/ICoreStub.cpp index c5e89b56..8829cbab 100755 --- a/tests/UnitTests/ICoreStub.cpp +++ b/tests/UnitTests/ICoreStub.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/ICoreStub.h b/tests/UnitTests/ICoreStub.h index d95cba37..a52da725 100644 --- a/tests/UnitTests/ICoreStub.h +++ b/tests/UnitTests/ICoreStub.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -18,16 +18,16 @@ public: ICoreStub(); ICoreStub(const CryptoNote::Block& genesisBlock); - virtual bool addObserver(CryptoNote::ICoreObserver* observer); - virtual bool removeObserver(CryptoNote::ICoreObserver* observer); - virtual void get_blockchain_top(uint32_t& height, Crypto::Hash& top_id); + virtual bool addObserver(CryptoNote::ICoreObserver* observer) override; + virtual bool removeObserver(CryptoNote::ICoreObserver* observer) override; + virtual void get_blockchain_top(uint32_t& height, Crypto::Hash& top_id) override; virtual std::vector findBlockchainSupplement(const std::vector& remoteBlockIds, size_t maxCount, uint32_t& totalBlockCount, uint32_t& startBlockIndex) override; virtual bool get_random_outs_for_amounts(const CryptoNote::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_request& req, - CryptoNote::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_response& res); - virtual bool get_tx_outputs_gindexs(const Crypto::Hash& tx_id, std::vector& indexs); - virtual CryptoNote::i_cryptonote_protocol* get_protocol(); - virtual bool handle_incoming_tx(CryptoNote::BinaryArray const& tx_blob, CryptoNote::tx_verification_context& tvc, bool keeped_by_block); + CryptoNote::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_response& res) override; + virtual bool get_tx_outputs_gindexs(const Crypto::Hash& tx_id, std::vector& indexs) override; + virtual CryptoNote::i_cryptonote_protocol* get_protocol() override; + virtual bool handle_incoming_tx(CryptoNote::BinaryArray const& tx_blob, CryptoNote::tx_verification_context& tvc, bool keeped_by_block) override; virtual std::vector getPoolTransactions() override; virtual bool getPoolChanges(const Crypto::Hash& tailBlockId, const std::vector& knownTxsIds, std::vector& addedTxs, std::vector& deletedTxsIds) override; @@ -50,7 +50,6 @@ public: virtual bool handle_incoming_block_blob(const CryptoNote::BinaryArray& block_blob, CryptoNote::block_verification_context& bvc, bool control_miner, bool relay_block) override { return false; } virtual bool handle_get_objects(CryptoNote::NOTIFY_REQUEST_GET_OBJECTS::request& arg, CryptoNote::NOTIFY_RESPONSE_GET_OBJECTS::request& rsp) override { return false; } virtual void on_synchronized() override {} - virtual bool is_ready() override { return true; } virtual bool getOutByMSigGIndex(uint64_t amount, uint64_t gindex, CryptoNote::MultisignatureOutput& out) override { return true; } virtual size_t addChain(const std::vector& chain) override; diff --git a/tests/UnitTests/ICryptoNoteProtocolQueryStub.cpp b/tests/UnitTests/ICryptoNoteProtocolQueryStub.cpp index 899d44eb..6f535432 100644 --- a/tests/UnitTests/ICryptoNoteProtocolQueryStub.cpp +++ b/tests/UnitTests/ICryptoNoteProtocolQueryStub.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/ICryptoNoteProtocolQueryStub.h b/tests/UnitTests/ICryptoNoteProtocolQueryStub.h index 19df18d9..1e0d3d96 100644 --- a/tests/UnitTests/ICryptoNoteProtocolQueryStub.h +++ b/tests/UnitTests/ICryptoNoteProtocolQueryStub.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -13,11 +13,11 @@ class ICryptoNoteProtocolQueryStub: public CryptoNote::ICryptoNoteProtocolQuery public: ICryptoNoteProtocolQueryStub() : peers(0), observedHeight(0), synchronized(false) {} - virtual bool addObserver(CryptoNote::ICryptoNoteProtocolObserver* observer); - virtual bool removeObserver(CryptoNote::ICryptoNoteProtocolObserver* observer); - virtual uint32_t getObservedHeight() const; - virtual size_t getPeerCount() const; - virtual bool isSynchronized() const; + virtual bool addObserver(CryptoNote::ICryptoNoteProtocolObserver* observer) override; + virtual bool removeObserver(CryptoNote::ICryptoNoteProtocolObserver* observer) override; + virtual uint32_t getObservedHeight() const override; + virtual size_t getPeerCount() const override; + virtual bool isSynchronized() const override; void setPeerCount(uint32_t count); void setObservedHeight(uint32_t height); diff --git a/tests/UnitTests/INodeStubs.cpp b/tests/UnitTests/INodeStubs.cpp index 05baa367..a2adcb0d 100644 --- a/tests/UnitTests/INodeStubs.cpp +++ b/tests/UnitTests/INodeStubs.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/INodeStubs.h b/tests/UnitTests/INodeStubs.h index 7bbb1a9a..3ed5e378 100644 --- a/tests/UnitTests/INodeStubs.h +++ b/tests/UnitTests/INodeStubs.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -21,10 +21,10 @@ public: virtual bool addObserver(CryptoNote::INodeObserver* observer) override; virtual bool removeObserver(CryptoNote::INodeObserver* observer) override; - virtual void init(const CryptoNote::INode::Callback& callback) {callback(std::error_code());}; - virtual bool shutdown() { return true; }; + virtual void init(const CryptoNote::INode::Callback& callback) override {callback(std::error_code());}; + virtual bool shutdown() override { return true; }; - virtual size_t getPeerCount() const { return 0; }; + virtual size_t getPeerCount() const override { return 0; }; virtual uint32_t getLastLocalBlockHeight() const override { return 0; }; virtual uint32_t getLastKnownBlockHeight() const override { return 0; }; virtual uint32_t getLocalBlockCount() const override { return 0; }; @@ -43,13 +43,13 @@ public: virtual void queryBlocks(std::vector&& knownBlockIds, uint64_t timestamp, std::vector& newBlocks, uint32_t& startHeight, const Callback& callback) override { callback(std::error_code()); }; - virtual void getBlocks(const std::vector& blockHeights, std::vector>& blocks, const Callback& callback) { callback(std::error_code()); }; - virtual void getBlocks(const std::vector& blockHashes, std::vector& blocks, const Callback& callback) { callback(std::error_code()); }; - virtual void getBlocks(uint64_t timestampBegin, uint64_t timestampEnd, uint32_t blocksNumberLimit, std::vector& blocks, uint32_t& blocksNumberWithinTimestamps, const Callback& callback) { callback(std::error_code()); }; - virtual void getTransactions(const std::vector& transactionHashes, std::vector& transactions, const Callback& callback) { callback(std::error_code()); }; - virtual void getTransactionsByPaymentId(const Crypto::Hash& paymentId, std::vector& transactions, const Callback& callback) { callback(std::error_code()); }; - virtual void getPoolTransactions(uint64_t timestampBegin, uint64_t timestampEnd, uint32_t transactionsNumberLimit, std::vector& transactions, uint64_t& transactionsNumberWithinTimestamps, const Callback& callback) { callback(std::error_code()); }; - virtual void isSynchronized(bool& syncStatus, const Callback& callback) { callback(std::error_code()); }; + virtual void getBlocks(const std::vector& blockHeights, std::vector>& blocks, const Callback& callback) override { callback(std::error_code()); }; + virtual void getBlocks(const std::vector& blockHashes, std::vector& blocks, const Callback& callback) override { callback(std::error_code()); }; + virtual void getBlocks(uint64_t timestampBegin, uint64_t timestampEnd, uint32_t blocksNumberLimit, std::vector& blocks, uint32_t& blocksNumberWithinTimestamps, const Callback& callback) override { callback(std::error_code()); }; + virtual void getTransactions(const std::vector& transactionHashes, std::vector& transactions, const Callback& callback) override { callback(std::error_code()); }; + virtual void getTransactionsByPaymentId(const Crypto::Hash& paymentId, std::vector& transactions, const Callback& callback) override { callback(std::error_code()); }; + virtual void getPoolTransactions(uint64_t timestampBegin, uint64_t timestampEnd, uint32_t transactionsNumberLimit, std::vector& transactions, uint64_t& transactionsNumberWithinTimestamps, const Callback& callback) override { callback(std::error_code()); }; + virtual void isSynchronized(bool& syncStatus, const Callback& callback) override { callback(std::error_code()); }; virtual void getMultisignatureOutputByGlobalIndex(uint64_t amount, uint32_t gindex, CryptoNote::MultisignatureOutput& out, const Callback& callback) override { callback(std::error_code()); } void updateObservers(); @@ -66,16 +66,16 @@ public: void setGetNewBlocksLimit(size_t maxBlocks) { m_getMaxBlocks = maxBlocks; } - virtual uint32_t getLastLocalBlockHeight() const { return static_cast(m_blockchainGenerator.getBlockchain().size() - 1); } - virtual uint32_t getLastKnownBlockHeight() const { return static_cast(m_blockchainGenerator.getBlockchain().size() - 1); } + virtual uint32_t getLastLocalBlockHeight() const override { return static_cast(m_blockchainGenerator.getBlockchain().size() - 1); } + virtual uint32_t getLastKnownBlockHeight() const override { return static_cast(m_blockchainGenerator.getBlockchain().size() - 1); } virtual uint32_t getLocalBlockCount() const override { return static_cast(m_blockchainGenerator.getBlockchain().size()); } virtual uint32_t getKnownBlockCount() const override { return static_cast(m_blockchainGenerator.getBlockchain().size()); } - virtual void getNewBlocks(std::vector&& knownBlockIds, std::vector& newBlocks, uint32_t& startHeight, const Callback& callback); + virtual void getNewBlocks(std::vector&& knownBlockIds, std::vector& newBlocks, uint32_t& startHeight, const Callback& callback) override; - virtual void relayTransaction(const CryptoNote::Transaction& transaction, const Callback& callback); - virtual void getRandomOutsByAmounts(std::vector&& amounts, uint64_t outsCount, std::vector& result, const Callback& callback); + virtual void relayTransaction(const CryptoNote::Transaction& transaction, const Callback& callback) override; + virtual void getRandomOutsByAmounts(std::vector&& amounts, uint64_t outsCount, std::vector& result, const Callback& callback) override; 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; virtual void getPoolSymmetricDifference(std::vector&& known_pool_tx_ids, Crypto::Hash known_block_id, bool& is_bc_actual, diff --git a/tests/UnitTests/MulDiv.cpp b/tests/UnitTests/MulDiv.cpp index 85b00741..57c0d9a0 100644 --- a/tests/UnitTests/MulDiv.cpp +++ b/tests/UnitTests/MulDiv.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/ParseAmount.cpp b/tests/UnitTests/ParseAmount.cpp index 446cf734..511d5c3b 100644 --- a/tests/UnitTests/ParseAmount.cpp +++ b/tests/UnitTests/ParseAmount.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/PaymentGateTests.cpp b/tests/UnitTests/PaymentGateTests.cpp index 554347fd..e3b11633 100644 --- a/tests/UnitTests/PaymentGateTests.cpp +++ b/tests/UnitTests/PaymentGateTests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -10,6 +10,7 @@ #include #include "PaymentGate/WalletService.h" +#include "PaymentGate/WalletFactory.h" // test helpers #include "INodeStubs.h" @@ -32,7 +33,8 @@ public: } std::unique_ptr createWalletService(const WalletConfiguration& cfg) { - std::unique_ptr service(new WalletService(currency, dispatcher, nodeStub, cfg, logger)); + wallet.reset(WalletFactory::createWallet(currency, nodeStub, dispatcher)); + std::unique_ptr service(new WalletService(currency, dispatcher, nodeStub, *wallet, cfg, logger)); service->init(); return service; } @@ -48,6 +50,8 @@ protected: TestBlockchainGenerator generator; INodeTrivialRefreshStub nodeStub; System::Dispatcher dispatcher; + + std::unique_ptr wallet; }; @@ -77,15 +81,9 @@ TEST_F(PaymentGateTest, addTransaction) { System::Timer(dispatcher).sleep(std::chrono::seconds(2)); - uint64_t txCount = 0; - - ASSERT_TRUE(!service->getTransactionsCount(txCount)); - ASSERT_EQ(3, txCount); - uint64_t pending = 0, actual = 0; - ASSERT_TRUE(!service->getPendingBalance(pending)); - ASSERT_TRUE(!service->getActualBalance(actual)); + service->getBalance(actual, pending); ASSERT_NE(0, pending); ASSERT_NE(0, actual); @@ -93,6 +91,7 @@ TEST_F(PaymentGateTest, addTransaction) { ASSERT_EQ(pending * 2, actual); } +/* TEST_F(PaymentGateTest, DISABLED_sendTransaction) { auto cfg = createWalletConfiguration(); @@ -129,16 +128,16 @@ TEST_F(PaymentGateTest, DISABLED_sendTransaction) { uint64_t txId = 0; { - SendTransactionRequest req; - SendTransactionResponse res; + SendTransaction::Request req; + SendTransaction::Response res; - req.destinations.push_back(TransferDestination{ TEST_AMOUNT, recvAddress }); + req.transfers.push_back(WalletRpcOrder{ TEST_AMOUNT, recvAddress }); req.fee = currency.minimumFee(); - req.mixin = 1; + req.anonymity = 1; req.unlockTime = 0; req.paymentId = paymentIdStr; - ASSERT_TRUE(!service->sendTransaction(req, res)); + ASSERT_TRUE(!service->sendTransaction(req, res.transactionHash)); txId = res.transactionId; } @@ -250,4 +249,4 @@ TEST_F(PaymentGateTest, DISABLED_sendTransaction) { ASSERT_EQ(1, recvPayment.size()); ASSERT_EQ(TEST_AMOUNT / 2, recvPayment[0].amount); } -} +} */ diff --git a/tests/UnitTests/Serialization.cpp b/tests/UnitTests/Serialization.cpp index 95198d40..4f1355f1 100755 --- a/tests/UnitTests/Serialization.cpp +++ b/tests/UnitTests/Serialization.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/SerializationKV.cpp b/tests/UnitTests/SerializationKV.cpp index c8999195..1fd8613f 100755 --- a/tests/UnitTests/SerializationKV.cpp +++ b/tests/UnitTests/SerializationKV.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/Shuffle.cpp b/tests/UnitTests/Shuffle.cpp index 4c83025e..a63cb131 100644 --- a/tests/UnitTests/Shuffle.cpp +++ b/tests/UnitTests/Shuffle.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/StringBufferTests.cpp b/tests/UnitTests/StringBufferTests.cpp index cea76ead..a7f94c2c 100755 --- a/tests/UnitTests/StringBufferTests.cpp +++ b/tests/UnitTests/StringBufferTests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/StringViewTests.cpp b/tests/UnitTests/StringViewTests.cpp index 7fcb6f34..6e902eb7 100755 --- a/tests/UnitTests/StringViewTests.cpp +++ b/tests/UnitTests/StringViewTests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/TestBcS.cpp b/tests/UnitTests/TestBcS.cpp index 7607678a..ccd6d0cf 100644 --- a/tests/UnitTests/TestBcS.cpp +++ b/tests/UnitTests/TestBcS.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -7,6 +7,7 @@ #include "Transfers/BlockchainSynchronizer.h" #include "Transfers/TransfersConsumer.h" +#include "crypto/hash.h" #include "CryptoNoteCore/TransactionApi.h" #include "CryptoNoteCore/CryptoNoteFormatUtils.h" #include "CryptoNoteCore/CryptoNoteTools.h" @@ -109,11 +110,21 @@ public: m_blockchain.push_back(genesisBlockHash); } + void addPoolTransaction(const Crypto::Hash& hash) { + m_pool.emplace(hash); + } + virtual SynchronizationStart getSyncStart() override { SynchronizationStart start = { 0, 0 }; return start; } + virtual void addObserver(IBlockchainConsumerObserver* observer) override { + } + + virtual void removeObserver(IBlockchainConsumerObserver* observer) override { + } + virtual void onBlockchainDetach(uint32_t height) override { assert(height < m_blockchain.size()); m_blockchain.resize(height); @@ -132,28 +143,32 @@ public: return m_blockchain; } - virtual void getKnownPoolTxIds(std::vector& ids) override { - ids.assign(m_pool.begin(), m_pool.end()); + virtual const std::unordered_set& getKnownPoolTxIds() const override { + return m_pool; } virtual std::error_code onPoolUpdated(const std::vector>& addedTransactions, const std::vector& deletedTransactions) override { for (const auto& tx: addedTransactions) { - Hash hash = tx->getTransactionHash(); - m_pool.push_back(reinterpret_cast(hash)); + m_pool.emplace(tx->getTransactionHash()); } for (auto& hash : deletedTransactions) { - auto pos = std::find(m_pool.begin(), m_pool.end(), hash); - if (pos != m_pool.end()) { - m_pool.erase(pos); - } + m_pool.erase(hash); } return std::error_code(); } + std::error_code addUnconfirmedTransaction(const ITransactionReader& /*transaction*/) override { + throw std::runtime_error("Not implemented"); + } + + void removeUnconfirmedTransaction(const Crypto::Hash& /*transactionHash*/) override { + throw std::runtime_error("Not implemented"); + } + private: - std::vector m_pool; + std::unordered_set m_pool; std::vector m_blockchain; }; @@ -362,10 +377,10 @@ TEST_F(BcSTest, stopIsWaiting) { bool flag = false; - o1.updFunc = std::move([&e, &flag](uint32_t, uint32_t) { + o1.updFunc = [&e, &flag](uint32_t, uint32_t) { e.notify(); std::this_thread::sleep_for(std::chrono::milliseconds(1000)); flag = true; - }); + }; m_sync.addObserver(&o1); m_sync.start(); @@ -385,9 +400,9 @@ TEST_F(BcSTest, syncCompletedError) { IBlockchainSynchronizerFunctorialObserver o1; EventWaiter e; - o1.updFunc = std::move([&e](uint32_t curr, uint32_t total) { + o1.updFunc = [&e](uint32_t curr, uint32_t total) { e.notify(); std::this_thread::sleep_for(std::chrono::milliseconds(200)); - }); + }; m_sync.addObserver(&o); m_sync.addObserver(&o1); @@ -406,9 +421,9 @@ TEST_F(BcSTest, onLastKnownBlockHeightUpdated) { generator.generateEmptyBlocks(20); IBlockchainSynchronizerFunctorialObserver o1; EventWaiter e; - o1.syncFunc = std::move([&e](std::error_code) { + o1.syncFunc = [&e](std::error_code) { e.notify(); - }); + }; m_sync.addObserver(&o1); m_sync.start(); @@ -432,9 +447,9 @@ TEST_F(BcSTest, onPoolChanged) { generator.generateEmptyBlocks(20); IBlockchainSynchronizerFunctorialObserver o1; EventWaiter e; - o1.syncFunc = std::move([&e](std::error_code) { + o1.syncFunc = [&e](std::error_code) { e.notify(); - }); + }; m_sync.addObserver(&o1); m_sync.start(); @@ -470,18 +485,12 @@ TEST_F(BcSTest, serializationCheck) { class FunctorialPoolConsumerStub : public ConsumerStub { public: - FunctorialPoolConsumerStub(const Hash& genesisBlockHash) : ConsumerStub(genesisBlockHash) {} - virtual void getKnownPoolTxIds(std::vector& ids) override { - getKnownPoolTxIdsFunctor(ids); - } - virtual std::error_code onPoolUpdated(const std::vector>& addedTransactions, const std::vector& deletedTransactions) override { return onPoolUpdatedFunctor(addedTransactions, deletedTransactions); } - std::function&)> getKnownPoolTxIdsFunctor; std::function>&, const std::vector&)> onPoolUpdatedFunctor; }; @@ -498,8 +507,6 @@ TEST_F(BcSTest, firstPoolSynchronizationCheck) { auto tx2hash = getObjectHash(tx2); auto tx3hash = getObjectHash(tx3); - std::vector consumer1Pool = { tx1hash, tx2hash }; - std::vector consumer2Pool = { tx2hash, tx3hash }; std::unordered_set firstExpectedPool = { tx1hash, tx2hash, tx3hash }; std::unordered_set secondExpectedPool = { tx2hash }; @@ -510,8 +517,11 @@ TEST_F(BcSTest, firstPoolSynchronizationCheck) { FunctorialPoolConsumerStub c1(m_currency.genesisBlockHash()); FunctorialPoolConsumerStub c2(m_currency.genesisBlockHash()); - c1.getKnownPoolTxIdsFunctor = [&](std::vector& ids) { ids.assign(consumer1Pool.begin(), consumer1Pool.end()); }; - c2.getKnownPoolTxIdsFunctor = [&](std::vector& ids) { ids.assign(consumer2Pool.begin(), consumer2Pool.end()); }; + c1.addPoolTransaction(tx1hash); + c1.addPoolTransaction(tx2hash); + + c2.addPoolTransaction(tx2hash); + c2.addPoolTransaction(tx3hash); std::vector c1ResponseDeletedPool; std::vector c2ResponseDeletedPool; @@ -571,9 +581,9 @@ TEST_F(BcSTest, firstPoolSynchronizationCheck) { IBlockchainSynchronizerFunctorialObserver o1; EventWaiter e; - o1.syncFunc = std::move([&e](std::error_code) { + o1.syncFunc = [&e](std::error_code) { e.notify(); - }); + }; m_sync.addObserver(&o1); m_sync.start(); @@ -593,6 +603,7 @@ TEST_F(BcSTest, firstPoolSynchronizationCheck) { TEST_F(BcSTest, firstPoolSynchronizationCheckNonActual) { addConsumers(2); + m_consumers.front()->addPoolTransaction(Crypto::rand()); int requestsCount = 0; @@ -611,9 +622,9 @@ TEST_F(BcSTest, firstPoolSynchronizationCheckNonActual) { IBlockchainSynchronizerFunctorialObserver o1; EventWaiter e; - o1.syncFunc = std::move([&e](std::error_code) { + o1.syncFunc = [&e](std::error_code) { e.notify(); - }); + }; m_sync.addObserver(&o1); m_sync.start(); @@ -622,12 +633,12 @@ TEST_F(BcSTest, firstPoolSynchronizationCheckNonActual) { m_sync.removeObserver(&o1); o1.syncFunc = [](std::error_code) {}; - EXPECT_EQ(4, requestsCount); } TEST_F(BcSTest, firstPoolSynchronizationCheckGetPoolErr) { addConsumers(2); + m_consumers.front()->addPoolTransaction(Crypto::rand()); int requestsCount = 0; @@ -647,9 +658,9 @@ TEST_F(BcSTest, firstPoolSynchronizationCheckGetPoolErr) { IBlockchainSynchronizerFunctorialObserver o1; EventWaiter e; - o1.syncFunc = std::move([&e](std::error_code) { + o1.syncFunc = [&e](std::error_code) { e.notify(); - }); + }; m_sync.addObserver(&o1); m_sync.start(); @@ -668,9 +679,9 @@ TEST_F(BcSTest, poolSynchronizationCheckActual) { IBlockchainSynchronizerFunctorialObserver o1; EventWaiter e; - o1.syncFunc = std::move([&e](std::error_code) { + o1.syncFunc = [&e](std::error_code) { e.notify(); - }); + }; m_sync.addObserver(&o1); m_sync.start(); @@ -706,10 +717,10 @@ TEST_F(BcSTest, poolSynchronizationCheckError) { IBlockchainSynchronizerFunctorialObserver o1; EventWaiter e; std::error_code errc; - o1.syncFunc = std::move([&](std::error_code ec) { + o1.syncFunc = [&](std::error_code ec) { e.notify(); errc = ec; - }); + }; m_sync.addObserver(&o1); m_sync.start(); @@ -754,9 +765,9 @@ TEST_F(BcSTest, poolSynchronizationCheckTxAdded) { IBlockchainSynchronizerFunctorialObserver o1; EventWaiter e; - o1.syncFunc = std::move([&e](std::error_code) { + o1.syncFunc = [&e](std::error_code) { e.notify(); - }); + }; m_sync.addObserver(&o1); m_sync.start(); @@ -812,9 +823,9 @@ TEST_F(BcSTest, poolSynchronizationCheckTxDeleted) { IBlockchainSynchronizerFunctorialObserver o1; EventWaiter e; - o1.syncFunc = std::move([&e](std::error_code) { + o1.syncFunc = [&e](std::error_code) { e.notify(); - }); + }; m_sync.addObserver(&o1); m_sync.start(); @@ -868,9 +879,9 @@ TEST_F(BcSTest, poolSynchronizationCheckNotification) { IBlockchainSynchronizerFunctorialObserver o1; EventWaiter e; - o1.syncFunc = std::move([&e](std::error_code) { + o1.syncFunc = [&e](std::error_code) { e.notify(); - }); + }; m_sync.addObserver(&o1); m_sync.start(); @@ -882,9 +893,6 @@ TEST_F(BcSTest, poolSynchronizationCheckConsumersNotififcation) { FunctorialPoolConsumerStub c1(m_currency.genesisBlockHash()); FunctorialPoolConsumerStub c2(m_currency.genesisBlockHash()); - c1.getKnownPoolTxIdsFunctor = [&](std::vector& ids) {}; - c2.getKnownPoolTxIdsFunctor = [&](std::vector& ids) {}; - bool c1Notified = false; bool c2Notified = false; c1.onPoolUpdatedFunctor = [&](const std::vector>& new_txs, const std::vector& deleted)->std::error_code { @@ -899,9 +907,9 @@ TEST_F(BcSTest, poolSynchronizationCheckConsumersNotififcation) { IBlockchainSynchronizerFunctorialObserver o1; EventWaiter e; - o1.syncFunc = std::move([&e](std::error_code) { + o1.syncFunc = [&e](std::error_code) { e.notify(); - }); + }; m_sync.addObserver(&o1); m_sync.addConsumer(&c1); @@ -920,9 +928,6 @@ TEST_F(BcSTest, poolSynchronizationCheckConsumerReturnError) { FunctorialPoolConsumerStub c1(m_currency.genesisBlockHash()); FunctorialPoolConsumerStub c2(m_currency.genesisBlockHash()); - c1.getKnownPoolTxIdsFunctor = [&](std::vector& ids) {}; - c2.getKnownPoolTxIdsFunctor = [&](std::vector& ids) {}; - bool c1Notified = false; bool c2Notified = false; c1.onPoolUpdatedFunctor = [&](const std::vector>& new_txs, const std::vector& deleted)->std::error_code { @@ -938,10 +943,10 @@ TEST_F(BcSTest, poolSynchronizationCheckConsumerReturnError) { IBlockchainSynchronizerFunctorialObserver o1; EventWaiter e; std::error_code errc; - o1.syncFunc = std::move([&](std::error_code ec) { + o1.syncFunc = [&](std::error_code ec) { e.notify(); errc = ec; - }); + }; m_sync.addObserver(&o1); m_sync.addConsumer(&c1); @@ -978,10 +983,10 @@ TEST_F(BcSTest, checkINodeError) { IBlockchainSynchronizerFunctorialObserver o1; EventWaiter e; std::error_code errc; - o1.syncFunc = std::move([&](std::error_code ec) { + o1.syncFunc = [&](std::error_code ec) { e.notify(); errc = ec; - }); + }; m_node.queryBlocksFunctor = [](const std::vector& knownBlockIds, uint64_t timestamp, std::vector& newBlocks, uint32_t& startHeight, const INode::Callback& callback) -> bool { callback(std::make_error_code(std::errc::invalid_argument)); @@ -1003,10 +1008,10 @@ TEST_F(BcSTest, checkConsumerError) { IBlockchainSynchronizerFunctorialObserver o1; EventWaiter e; std::error_code errc; - o1.syncFunc = std::move([&](std::error_code ec) { + o1.syncFunc = [&](std::error_code ec) { e.notify(); errc = ec; - }); + }; generator.generateEmptyBlocks(10); @@ -1030,13 +1035,13 @@ TEST_F(BcSTest, checkBlocksRequesting) { IBlockchainSynchronizerFunctorialObserver o1; EventWaiter e; std::error_code errc; - o1.syncFunc = std::move([&](std::error_code ec) { + o1.syncFunc = [&](std::error_code ec) { e.notify(); errc = ec; - }); + }; - uint32_t blocksExpected = 20; + size_t blocksExpected = 20; generator.generateEmptyBlocks(blocksExpected - 1); //-1 for genesis m_node.setGetNewBlocksLimit(3); @@ -1064,15 +1069,15 @@ TEST_F(BcSTest, checkConsumerHeightReceived) { IBlockchainSynchronizerFunctorialObserver o1; EventWaiter e; std::error_code errc; - o1.syncFunc = std::move([&](std::error_code ec) { + o1.syncFunc = [&](std::error_code ec) { e.notify(); errc = ec; - }); + }; uint32_t firstlySnchronizedHeight = 20; - generator.generateEmptyBlocks(firstlySnchronizedHeight - 1);//-1 for genesis + generator.generateEmptyBlocks(static_cast(firstlySnchronizedHeight - 1));//-1 for genesis m_node.setGetNewBlocksLimit(50); c.onNewBlocksFunctor = [&](const CompleteBlock*, uint32_t startHeight, size_t) -> bool { @@ -1109,10 +1114,10 @@ TEST_F(BcSTest, checkConsumerOldBlocksNotIvoked) { IBlockchainSynchronizerFunctorialObserver o1; EventWaiter e; std::error_code errc; - o1.syncFunc = std::move([&](std::error_code ec) { + o1.syncFunc = [&](std::error_code ec) { e.notify(); errc = ec; - }); + }; generator.generateEmptyBlocks(20); m_node.setGetNewBlocksLimit(50); @@ -1151,10 +1156,10 @@ TEST_F(BcSTest, checkConsumerHeightReceivedOnDetach) { IBlockchainSynchronizerFunctorialObserver o1; EventWaiter e; std::error_code errc; - o1.syncFunc = std::move([&](std::error_code ec) { + o1.syncFunc = [&](std::error_code ec) { e.notify(); errc = ec; - }); + }; generator.generateEmptyBlocks(20); m_node.setGetNewBlocksLimit(50); @@ -1200,10 +1205,10 @@ TEST_F(BcSTest, checkStatePreservingBetweenSynchronizations) { IBlockchainSynchronizerFunctorialObserver o1; EventWaiter e; std::error_code errc; - o1.syncFunc = std::move([&](std::error_code ec) { + o1.syncFunc = [&](std::error_code ec) { e.notify(); errc = ec; - }); + }; generator.generateEmptyBlocks(20); @@ -1237,10 +1242,10 @@ TEST_F(BcSTest, checkBlocksRerequestingOnError) { IBlockchainSynchronizerFunctorialObserver o1; EventWaiter e; std::error_code errc; - o1.syncFunc = std::move([&](std::error_code ec) { + o1.syncFunc = [&](std::error_code ec) { e.notify(); errc = ec; - }); + }; generator.generateEmptyBlocks(20); m_node.setGetNewBlocksLimit(10); @@ -1307,10 +1312,10 @@ TEST_F(BcSTest, checkTxOrder) { IBlockchainSynchronizerFunctorialObserver o1; EventWaiter e; std::error_code errc; - o1.syncFunc = std::move([&](std::error_code ec) { + o1.syncFunc = [&](std::error_code ec) { e.notify(); errc = ec; - }); + }; auto tx1ptr = createTransaction(); auto tx2ptr = createTransaction(); diff --git a/tests/UnitTests/TestBlockchainExplorer.cpp b/tests/UnitTests/TestBlockchainExplorer.cpp index 076fb66c..17708fb4 100755 --- a/tests/UnitTests/TestBlockchainExplorer.cpp +++ b/tests/UnitTests/TestBlockchainExplorer.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -91,8 +91,8 @@ public: nodeStub(generator), blockchainExplorer(nodeStub, logger) { } - void SetUp(); - void TearDown(); + void SetUp() override; + void TearDown() override; protected: Currency currency; @@ -1090,7 +1090,7 @@ TEST_F(BlockchainExplorerTests, getBlocksByTimestampNotInited) { } TEST_F(BlockchainExplorerTests, generatedTransactions) { - const uint32_t NUMBER_OF_BLOCKS = 10; + const size_t NUMBER_OF_BLOCKS = 10; const size_t POOL_TX_NUMBER = 10; std::vector blockHeights; for (uint32_t i = 0; i < NUMBER_OF_BLOCKS + 3; ++i) { diff --git a/tests/UnitTests/TestBlockchainGenerator.cpp b/tests/UnitTests/TestBlockchainGenerator.cpp index 64ce627d..2e1f25a3 100644 --- a/tests/UnitTests/TestBlockchainGenerator.cpp +++ b/tests/UnitTests/TestBlockchainGenerator.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -121,11 +121,11 @@ void TestBlockchainGenerator::addMiningBlock() { m_generatedTransactionsIndex.add(block); } -void TestBlockchainGenerator::generateEmptyBlocks(uint32_t count) +void TestBlockchainGenerator::generateEmptyBlocks(size_t count) { std::unique_lock lock(m_mutex); - for (uint32_t i = 0; i < count; ++i) + for (size_t i = 0; i < count; ++i) { CryptoNote::Block& prev_block = m_blockchain.back(); CryptoNote::Block block; @@ -197,6 +197,10 @@ void TestBlockchainGenerator::addToBlockchain(const CryptoNote::Transaction& tx) } void TestBlockchainGenerator::addToBlockchain(const std::vector& txs) { + addToBlockchain(txs, miner_acc); +} + +void TestBlockchainGenerator::addToBlockchain(const std::vector& txs, const CryptoNote::AccountBase& minerAddress) { std::list txsToBlock; for (const auto& tx: txs) { @@ -209,7 +213,7 @@ void TestBlockchainGenerator::addToBlockchain(const std::vector(keyOutsContainer.size())); keyOutsContainer.push_back({ txHash, outIndex }); } else if (out.target.type() == typeid(MultisignatureOutput)) { auto& msigOutsContainer = multisignatureOutsIndex[out.amount]; - globalIndexes.push_back(msigOutsContainer.size()); + globalIndexes.push_back(static_cast(msigOutsContainer.size())); msigOutsContainer.push_back({ txHash, outIndex }); } } @@ -383,3 +387,9 @@ bool TestBlockchainGenerator::getMultisignatureOutputByGlobalIndex(uint64_t amou out = boost::get(tx.outputs[entry.indexOut].target); return true; } + +bool TestBlockchainGenerator::generateFromBaseTx(const CryptoNote::AccountBase& address) { + std::unique_lock lock(m_mutex); + addToBlockchain({}, address); + return true; +} diff --git a/tests/UnitTests/TestBlockchainGenerator.h b/tests/UnitTests/TestBlockchainGenerator.h index b48df733..ca8469c7 100644 --- a/tests/UnitTests/TestBlockchainGenerator.h +++ b/tests/UnitTests/TestBlockchainGenerator.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -23,13 +23,14 @@ public: //TODO: get rid of this method std::vector& getBlockchain(); std::vector getBlockchainCopy(); - void generateEmptyBlocks(uint32_t count); + void generateEmptyBlocks(size_t count); bool getBlockRewardForAddress(const CryptoNote::AccountPublicAddress& address); bool generateTransactionsInOneBlock(const CryptoNote::AccountPublicAddress& address, size_t n); bool getSingleOutputTransaction(const CryptoNote::AccountPublicAddress& address, uint64_t amount); void addTxToBlockchain(const CryptoNote::Transaction& transaction); bool getTransactionByHash(const Crypto::Hash& hash, CryptoNote::Transaction& tx, bool checkTxPool = false); const CryptoNote::AccountBase& getMinerAccount() const; + bool generateFromBaseTx(const CryptoNote::AccountBase& address); void putTxToPool(const CryptoNote::Transaction& tx); void getPoolSymmetricDifference(std::vector&& known_pool_tx_ids, Crypto::Hash known_block_id, bool& is_bc_actual, @@ -83,6 +84,7 @@ private: void addToBlockchain(const CryptoNote::Transaction& tx); void addToBlockchain(const std::vector& txs); + void addToBlockchain(const std::vector& txs, const CryptoNote::AccountBase& minerAddress); void addTx(const CryptoNote::Transaction& tx); bool doGenerateTransactionsInOneBlock(CryptoNote::AccountPublicAddress const &address, size_t n); diff --git a/tests/UnitTests/TestCurrency.cpp b/tests/UnitTests/TestCurrency.cpp index c81077c6..30fa69f2 100644 --- a/tests/UnitTests/TestCurrency.cpp +++ b/tests/UnitTests/TestCurrency.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/TestFormatUtils.cpp b/tests/UnitTests/TestFormatUtils.cpp index 73c4dc2d..6b4f500b 100755 --- a/tests/UnitTests/TestFormatUtils.cpp +++ b/tests/UnitTests/TestFormatUtils.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/TestInprocessNode.cpp b/tests/UnitTests/TestInprocessNode.cpp index 2279c0ae..ea1cfe8d 100644 --- a/tests/UnitTests/TestInprocessNode.cpp +++ b/tests/UnitTests/TestInprocessNode.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -49,7 +49,7 @@ public: node(coreStub, protocolQueryStub), currency(CryptoNote::CurrencyBuilder(logger).currency()), generator(currency) {} - void SetUp(); + void SetUp() override; protected: void initNode(); @@ -254,7 +254,7 @@ TEST_F(InProcessNodeTests, getBlocksByHeightEmpty) { } TEST_F(InProcessNodeTests, getBlocksByHeightMany) { - const uint32_t NUMBER_OF_BLOCKS = 10; + const size_t NUMBER_OF_BLOCKS = 10; std::vector blockHeights; std::vector> actualBlocks; @@ -298,7 +298,7 @@ TEST_F(InProcessNodeTests, getBlocksByHeightMany) { } TEST_F(InProcessNodeTests, getBlocksByHeightFail) { - const uint32_t NUMBER_OF_BLOCKS = 10; + const size_t NUMBER_OF_BLOCKS = 10; std::vector blockHeights; std::vector> actualBlocks; @@ -353,7 +353,7 @@ TEST_F(InProcessNodeTests, getBlocksByHashEmpty) { } TEST_F(InProcessNodeTests, getBlocksByHashMany) { - const uint32_t NUMBER_OF_BLOCKS = 10; + const size_t NUMBER_OF_BLOCKS = 10; std::vector blockHashes; std::vector actualBlocks; @@ -394,7 +394,7 @@ TEST_F(InProcessNodeTests, getBlocksByHashMany) { } TEST_F(InProcessNodeTests, getBlocksByHashFail) { - const uint32_t NUMBER_OF_BLOCKS = 10; + const size_t NUMBER_OF_BLOCKS = 10; std::vector blockHashes; std::vector actualBlocks; diff --git a/tests/UnitTests/TestJsonValue.cpp b/tests/UnitTests/TestJsonValue.cpp index 6d45fc6b..8f0d2fa1 100755 --- a/tests/UnitTests/TestJsonValue.cpp +++ b/tests/UnitTests/TestJsonValue.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/TestMessageQueue.cpp b/tests/UnitTests/TestMessageQueue.cpp index c19a1a01..9da94f00 100644 --- a/tests/UnitTests/TestMessageQueue.cpp +++ b/tests/UnitTests/TestMessageQueue.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -28,8 +28,8 @@ public: void sendBlockchainMessage(const BlockchainMessage& message); void interruptBlockchainMessageWaiting(); - void SetUp(); - void TearDown(); + void SetUp() override; + void TearDown() override; protected: System::Dispatcher dispatcher; @@ -84,7 +84,7 @@ TEST_F(MessageQueueTest, singleNewBlockMessage) { ASSERT_NO_THROW(queue.pop()); }); - ASSERT_NO_THROW(sendBlockchainMessage(BlockchainMessage(std::move(NewBlockMessage(randomHash))))); + ASSERT_NO_THROW(sendBlockchainMessage(BlockchainMessage(NewBlockMessage(randomHash)))); contextGroup.wait(); } @@ -107,7 +107,7 @@ TEST_F(MessageQueueTest, singleNewAlternativeBlockMessage) { ASSERT_NO_THROW(queue.pop()); }); - ASSERT_NO_THROW(sendBlockchainMessage(BlockchainMessage(std::move(NewAlternativeBlockMessage(randomHash))))); + ASSERT_NO_THROW(sendBlockchainMessage(BlockchainMessage(NewAlternativeBlockMessage(randomHash)))); contextGroup.wait(); } @@ -137,7 +137,7 @@ TEST_F(MessageQueueTest, singleChainSwitchMessage) { std::vector copy = randomHashes; - ASSERT_NO_THROW(sendBlockchainMessage(BlockchainMessage(std::move(ChainSwitchMessage(std::move(copy)))))); + ASSERT_NO_THROW(sendBlockchainMessage(BlockchainMessage(ChainSwitchMessage(std::move(copy))))); contextGroup.wait(); } @@ -168,7 +168,7 @@ TEST_F(MessageQueueTest, manyMessagesOneListener) { }); for (auto h : randomHashes) { - ASSERT_NO_THROW(sendBlockchainMessage(BlockchainMessage(std::move(NewBlockMessage(h))))); + ASSERT_NO_THROW(sendBlockchainMessage(BlockchainMessage(NewBlockMessage(h)))); } contextGroup.wait(); @@ -180,8 +180,8 @@ TEST_F(MessageQueueTest, manyMessagesManyListeners) { std::array>, NUMBER_OF_LISTENERS> quards; for (size_t i = 0; i < NUMBER_OF_LISTENERS; ++i) { - queues[i] = std::move(std::unique_ptr>(new MessageQueue(dispatcher))); - quards[i] = std::move(std::unique_ptr>(new MesageQueueGuard(*this, *queues[i]))); + queues[i] = std::unique_ptr>(new MessageQueue(dispatcher)); + quards[i] = std::unique_ptr>(new MesageQueueGuard(*this, *queues[i])); } const size_t NUMBER_OF_BLOCKS = 10; @@ -209,7 +209,7 @@ TEST_F(MessageQueueTest, manyMessagesManyListeners) { for (auto h : randomHashes) { - ASSERT_NO_THROW(sendBlockchainMessage(BlockchainMessage(std::move(NewBlockMessage(h))))); + ASSERT_NO_THROW(sendBlockchainMessage(BlockchainMessage(NewBlockMessage(h)))); } contextGroup.wait(); @@ -221,8 +221,8 @@ TEST_F(MessageQueueTest, interruptWaiting) { std::array>, NUMBER_OF_LISTENERS> quards; for (size_t i = 0; i < NUMBER_OF_LISTENERS; ++i) { - queues[i] = std::move(std::unique_ptr>(new MessageQueue(dispatcher))); - quards[i] = std::move(std::unique_ptr>(new MesageQueueGuard(*this, *queues[i]))); + queues[i] = std::unique_ptr>(new MessageQueue(dispatcher)); + quards[i] = std::unique_ptr>(new MesageQueueGuard(*this, *queues[i])); } const size_t NUMBER_OF_BLOCKS = 10; @@ -259,7 +259,7 @@ TEST_F(MessageQueueTest, interruptWaiting) { }); for (auto h : randomHashes) { - ASSERT_NO_THROW(sendBlockchainMessage(BlockchainMessage(std::move(NewBlockMessage(h))))); + ASSERT_NO_THROW(sendBlockchainMessage(BlockchainMessage(NewBlockMessage(h)))); } interruptBlockchainMessageWaiting(); diff --git a/tests/UnitTests/TestPath.cpp b/tests/UnitTests/TestPath.cpp index 813d1330..6d7148e9 100755 --- a/tests/UnitTests/TestPath.cpp +++ b/tests/UnitTests/TestPath.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/TestPeerlist.cpp b/tests/UnitTests/TestPeerlist.cpp index 990e16eb..f7122f57 100644 --- a/tests/UnitTests/TestPeerlist.cpp +++ b/tests/UnitTests/TestPeerlist.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/TestProtocolPack.cpp b/tests/UnitTests/TestProtocolPack.cpp index daa9c00c..efe15a3b 100644 --- a/tests/UnitTests/TestProtocolPack.cpp +++ b/tests/UnitTests/TestProtocolPack.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/TestTransactionPoolDetach.cpp b/tests/UnitTests/TestTransactionPoolDetach.cpp index 665f1c0c..5683e2a5 100644 --- a/tests/UnitTests/TestTransactionPoolDetach.cpp +++ b/tests/UnitTests/TestTransactionPoolDetach.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/TestTransfers.cpp b/tests/UnitTests/TestTransfers.cpp index 842a80b2..59a42999 100644 --- a/tests/UnitTests/TestTransfers.cpp +++ b/tests/UnitTests/TestTransfers.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/TestTransfersConsumer.cpp b/tests/UnitTests/TestTransfersConsumer.cpp index ad90ce9e..ad096c5e 100644 --- a/tests/UnitTests/TestTransfersConsumer.cpp +++ b/tests/UnitTests/TestTransfersConsumer.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -424,7 +424,7 @@ TEST_F(TransfersConsumerTest, onNewBlocks_getTransactionOutsGlobalIndicesError) block.transactions.push_back(tx); consumer.addSubscription(subscription); - ASSERT_FALSE(consumer.onNewBlocks(&block, subscription.syncStart.height, 1)); + ASSERT_FALSE(consumer.onNewBlocks(&block, static_cast(subscription.syncStart.height), 1)); } TEST_F(TransfersConsumerTest, onNewBlocks_updateHeight) { @@ -444,7 +444,7 @@ TEST_F(TransfersConsumerTest, onNewBlocks_updateHeight) { block.block->timestamp = subscription.syncStart.timestamp; block.transactions.push_back(tx); - ASSERT_TRUE(m_consumer.onNewBlocks(&block, subscription.syncStart.height, 1)); + ASSERT_TRUE(m_consumer.onNewBlocks(&block, static_cast(subscription.syncStart.height), 1)); ASSERT_EQ(900, container.balance(ITransfersContainer::IncludeAllLocked)); std::unique_ptr blocks(new CompleteBlock[subscription.transactionSpendableAge]); @@ -455,7 +455,7 @@ TEST_F(TransfersConsumerTest, onNewBlocks_updateHeight) { addTestKeyOutput(*tr, 100, i + 1, generateAccountKeys()); } - ASSERT_TRUE(m_consumer.onNewBlocks(blocks.get(), subscription.syncStart.height + 1, subscription.transactionSpendableAge)); + ASSERT_TRUE(m_consumer.onNewBlocks(blocks.get(), static_cast(subscription.syncStart.height + 1), static_cast(subscription.transactionSpendableAge))); ASSERT_EQ(0, container.balance(ITransfersContainer::IncludeAllLocked)); ASSERT_EQ(900, container.balance(ITransfersContainer::IncludeAllUnlocked)); } @@ -729,8 +729,7 @@ TEST_F(TransfersConsumerTest, onNewBlocks_checkTransactionInformation) { ASSERT_TRUE(m_consumer.onNewBlocks(&blocks[0], 0, 2)); TransactionInformation info; - int64_t balance; - ASSERT_TRUE(container.getTransactionInformation(tx->getTransactionHash(), info, balance)); + ASSERT_TRUE(container.getTransactionInformation(tx->getTransactionHash(), info)); ASSERT_EQ(tx->getTransactionHash(), info.transactionHash); ASSERT_EQ(tx->getTransactionPublicKey(), info.publicKey); @@ -779,7 +778,7 @@ TEST_F(TransfersConsumerTest, onNewBlocks_manyBlocks) { } } - ASSERT_TRUE(m_consumer.onNewBlocks(&blocks[0], 0, blocks.size())); + ASSERT_TRUE(m_consumer.onNewBlocks(&blocks[0], 0, static_cast(blocks.size()))); ASSERT_EQ(expectedTransactions, container.transactionsCount()); ASSERT_EQ(expectedAmount, container.balance(ITransfersContainer::IncludeAll)); @@ -862,7 +861,7 @@ TEST_F(TransfersConsumerTest, onPoolUpdated_addTransactionDoesNotGetsGlobalIndic ASSERT_TRUE(m_node.calls_getTransactionOutsGlobalIndices.empty()); } -TEST_F(TransfersConsumerTest, onPoolUpdated_deleteTransaction) { +TEST_F(TransfersConsumerTest, onPoolUpdated_deleteTransactionNotDeleted) { auto& sub = addSubscription(); TransfersObserver observer; sub.addObserver(&observer); @@ -874,15 +873,42 @@ TEST_F(TransfersConsumerTest, onPoolUpdated_deleteTransaction) { m_consumer.onPoolUpdated({}, deleted); + ASSERT_EQ(0, observer.deleted.size()); +} + +TEST_F(TransfersConsumerTest, onPoolUpdated_deleteTransaction) { + const uint8_t TX_COUNT = 2; + auto& sub = addSubscription(); + TransfersObserver observer; + sub.addObserver(&observer); + + std::vector> added; + std::vector deleted; + + for (uint8_t i = 0; i < TX_COUNT; ++i) { + // construct tx + TestTransactionBuilder b1; + auto unknownSender = generateAccountKeys(); + b1.addTestInput(10000, unknownSender); + auto out = b1.addTestKeyOutput(10000, UNCONFIRMED_TRANSACTION_GLOBAL_OUTPUT_INDEX, m_accountKeys); + + auto tx = std::shared_ptr(b1.build().release()); + + std::unique_ptr prefix = createTransactionPrefix(convertTx(*tx)); + added.push_back(std::move(prefix)); + deleted.push_back(added.back()->getTransactionHash()); + } + + m_consumer.onPoolUpdated(added, {}); + m_consumer.onPoolUpdated({}, deleted); + ASSERT_EQ(deleted.size(), observer.deleted.size()); - ASSERT_EQ(reinterpret_cast(deleted[0]), observer.deleted[0]); - ASSERT_EQ(reinterpret_cast(deleted[1]), observer.deleted[1]); + ASSERT_EQ(deleted, observer.deleted); } TEST_F(TransfersConsumerTest, getKnownPoolTxIds_empty) { addSubscription(); - std::vector ids; - m_consumer.getKnownPoolTxIds(ids); + const std::unordered_set& ids = m_consumer.getKnownPoolTxIds(); ASSERT_TRUE(ids.empty()); } @@ -913,14 +939,13 @@ TEST_F(TransfersConsumerTest, getKnownPoolTxIds_returnsUnconfirmed) { v.push_back(createTransactionPrefix(convertTx(*txs[2]))); m_consumer.onPoolUpdated(v, {}); - std::vector ids; - m_consumer.getKnownPoolTxIds(ids); + const std::unordered_set& ids = m_consumer.getKnownPoolTxIds(); ASSERT_EQ(3, ids.size()); for (int i = 0; i < 3; ++i) { auto txhash = txs[i]->getTransactionHash(); - ASSERT_TRUE(std::find(ids.begin(), ids.end(), reinterpret_cast(txhash)) != ids.end()); + ASSERT_EQ(1, ids.count(txhash)); } } @@ -1018,7 +1043,7 @@ TEST_F(TransfersConsumerPerformanceTest, DISABLED_memory) { { AutoPrintTimer t; - ASSERT_TRUE(m_consumer.onNewBlocks(&blocks[0], 0, blocks.size())); + ASSERT_TRUE(m_consumer.onNewBlocks(&blocks[0], 0, static_cast(blocks.size()))); } blocks.clear(); @@ -1043,7 +1068,7 @@ TEST_F(TransfersConsumerPerformanceTest, DISABLED_performanceTest) { std::cout << "Calling onNewBlocks" << std::endl; - ASSERT_TRUE(m_consumer.onNewBlocks(&blocks[0], 0, blocks.size())); + ASSERT_TRUE(m_consumer.onNewBlocks(&blocks[0], 0, static_cast(blocks.size()))); auto end = std::chrono::steady_clock::now(); std::chrono::duration dur = end - start; diff --git a/tests/UnitTests/TestTransfersContainer.cpp b/tests/UnitTests/TestTransfersContainer.cpp index d30e0d91..6755a132 100644 --- a/tests/UnitTests/TestTransfersContainer.cpp +++ b/tests/UnitTests/TestTransfersContainer.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -282,10 +282,12 @@ TEST_F(TransfersContainer_addTransaction, handlesAddingUnconfirmedOutputToKey) { ASSERT_TRUE(transfers.empty()); TransactionInformation txInfo; - int64_t txBalance; - ASSERT_TRUE(container.getTransactionInformation(tx->getTransactionHash(), txInfo, txBalance)); + uint64_t amountIn; + uint64_t amountOut; + ASSERT_TRUE(container.getTransactionInformation(tx->getTransactionHash(), txInfo, &amountIn, &amountOut)); ASSERT_EQ(blockInfo.height, txInfo.blockHeight); - ASSERT_EQ(TEST_OUTPUT_AMOUNT, txBalance); + ASSERT_EQ(0, amountIn); + ASSERT_EQ(TEST_OUTPUT_AMOUNT, amountOut); std::vector unconfirmedTransactions; container.getUnconfirmedTransactions(unconfirmedTransactions); @@ -326,10 +328,12 @@ TEST_F(TransfersContainer_addTransaction, handlesAddingConfirmedOutputToKey) { ASSERT_EQ(1, transfers.size()); TransactionInformation txInfo; - int64_t txBalance; - ASSERT_TRUE(container.getTransactionInformation(tx->getTransactionHash(), txInfo, txBalance)); + uint64_t amountIn; + uint64_t amountOut; + ASSERT_TRUE(container.getTransactionInformation(tx->getTransactionHash(), txInfo, &amountIn, &amountOut)); ASSERT_EQ(blockInfo.height, txInfo.blockHeight); - ASSERT_EQ(TEST_OUTPUT_AMOUNT, txBalance); + ASSERT_EQ(0, amountIn); + ASSERT_EQ(TEST_OUTPUT_AMOUNT, amountOut); std::vector unconfirmedTransactions; container.getUnconfirmedTransactions(unconfirmedTransactions); @@ -366,8 +370,7 @@ TEST_F(TransfersContainer_addTransaction, addingEmptyTransactionOuptutsDoesNotCh ASSERT_TRUE(transfers.empty()); TransactionInformation txInfo; - int64_t txBalance; - ASSERT_FALSE(container.getTransactionInformation(tx->getTransactionHash(), txInfo, txBalance)); + ASSERT_FALSE(container.getTransactionInformation(tx->getTransactionHash(), txInfo)); std::vector unconfirmedTransactions; container.getUnconfirmedTransactions(unconfirmedTransactions); diff --git a/tests/UnitTests/TestTransfersContainerKeyImage.cpp b/tests/UnitTests/TestTransfersContainerKeyImage.cpp index 4a14ee40..533a3827 100644 --- a/tests/UnitTests/TestTransfersContainerKeyImage.cpp +++ b/tests/UnitTests/TestTransfersContainerKeyImage.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/TestTransfersSubscription.cpp b/tests/UnitTests/TestTransfersSubscription.cpp index e18b3279..b532e9bd 100644 --- a/tests/UnitTests/TestTransfersSubscription.cpp +++ b/tests/UnitTests/TestTransfersSubscription.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/TestWallet.cpp b/tests/UnitTests/TestWallet.cpp index 9ffc0e8a..31e47cb1 100755 --- a/tests/UnitTests/TestWallet.cpp +++ b/tests/UnitTests/TestWallet.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -7,6 +7,7 @@ #include #include #include +#include #include "Common/StringTools.h" #include "CryptoNoteCore/Currency.h" @@ -16,6 +17,7 @@ #include "TestBlockchainGenerator.h" #include "TransactionApiHelpers.h" #include +#include "Wallet/WalletErrors.h" #include "Wallet/WalletGreen.h" #include "WalletLegacy/WalletUserTransactionsCache.h" #include "WalletLegacy/WalletLegacySerializer.h" @@ -41,9 +43,16 @@ namespace CryptoNote { case WalletTransactionState::SUCCEEDED: o << "SUCCEEDED"; break; + case WalletTransactionState::CREATED: + o << "CREATED"; + break; + case WalletTransactionState::DELETED: + o << "DELETED"; + break; } return o; } + std::ostream& operator<<(std::ostream& o, const WalletTransaction& tx) { o << "WalletTransaction{state=" << tx.state << ", timestamp=" << tx.timestamp << ", blockHeight=" << tx.blockHeight << ", hash=" << tx.hash @@ -110,6 +119,10 @@ namespace CryptoNote { return false; } + if (lhs.type != rhs.type) { + return false; + } + return true; } @@ -120,6 +133,10 @@ namespace CryptoNote { bool operator==(const IFusionManager::EstimateResult& lhs, const IFusionManager::EstimateResult& rhs) { return lhs.fusionReadyCount == rhs.fusionReadyCount && lhs.totalOutputCount == rhs.totalOutputCount; } + + bool operator<(const WalletTransfer& lhs, const WalletTransfer& rhs) { + return std::make_tuple(lhs.amount, lhs.address) < std::make_tuple(rhs.amount, rhs.address); + } } class WalletApi: public ::testing::Test { @@ -169,11 +186,18 @@ protected: void waitForActualBalance(uint64_t expected); void waitForActualBalance(CryptoNote::WalletGreen& wallet, uint64_t expected); - size_t sendMoneyToRandomAddressFrom(const std::string& address, uint64_t amount, uint64_t fee); - size_t sendMoneyToRandomAddressFrom(const std::string& address); + size_t sendMoneyToRandomAddressFrom(const std::string& address, uint64_t amount, uint64_t fee, const std::string& changeDestination); + size_t sendMoneyToRandomAddressFrom(const std::string& address, const std::string& changeDestination); - size_t sendMoney(CryptoNote::WalletGreen& wallet, const std::string& to, int64_t amount, uint64_t fee, uint64_t mixIn = 0, const std::string& extra = "", uint64_t unlockTimestamp = 0); - size_t sendMoney(const std::string& to, int64_t amount, uint64_t fee, uint64_t mixIn = 0, const std::string& extra = "", uint64_t unlockTimestamp = 0); + size_t sendMoney(CryptoNote::WalletGreen& wallet, const std::string& to, uint64_t amount, uint64_t fee, uint64_t mixIn = 0, const std::string& extra = "", uint64_t unlockTimestamp = 0); + size_t sendMoney(const std::string& to, uint64_t amount, uint64_t fee, uint64_t mixIn = 0, const std::string& extra = "", uint64_t unlockTimestamp = 0); + size_t sendMoneyWithDonation(const std::string& to, uint64_t amount, uint64_t fee, + const std::string& donationAddress, uint64_t donationAmount, uint64_t mixIn = 0, const std::string& extra = "", uint64_t unlockTimestamp = 0); + + size_t makeTransaction(const std::vector& sourceAdresses, const std::string& to, uint64_t amount, uint64_t fee, uint64_t mixIn = 0, const std::string& extra = "", uint64_t unlockTimestamp = 0); + size_t makeTransaction(CryptoNote::WalletGreen& wallet, const std::vector& sourceAdresses, const std::string& to, uint64_t amount, uint64_t fee, uint64_t mixIn = 0, const std::string& extra = "", uint64_t unlockTimestamp = 0); + size_t makeTransaction(const std::vector& sourceAdresses, const std::vector& orders, uint64_t fee, uint64_t mixIn = 0, const std::string& extra = "", uint64_t unlockTimestamp = 0); + size_t makeTransaction(CryptoNote::WalletGreen& wallet, const std::vector& sourceAdresses, const std::vector& orders, uint64_t fee, uint64_t mixIn = 0, const std::string& extra = "", uint64_t unlockTimestamp = 0); void fillWalletWithDetailsCache(); @@ -387,16 +411,21 @@ void WalletApi::generateAddressesWithPendingMoney(size_t count) { } } -size_t WalletApi::sendMoneyToRandomAddressFrom(const std::string& address, uint64_t amount, uint64_t fee) { - CryptoNote::WalletTransfer transfer; - transfer.address = RANDOM_ADDRESS; - transfer.amount = amount; +size_t WalletApi::sendMoneyToRandomAddressFrom(const std::string& address, uint64_t amount, uint64_t fee, const std::string& changeDestination) { + CryptoNote::WalletOrder order; + order.address = RANDOM_ADDRESS; + order.amount = amount; - return alice.transfer(address, transfer, fee, 0); + CryptoNote::TransactionParameters params; + params.sourceAddresses = {address}; + params.destinations = {order}; + params.fee = fee; + params.changeDestination = changeDestination; + return alice.transfer(params); } -size_t WalletApi::sendMoneyToRandomAddressFrom(const std::string& address) { - return sendMoneyToRandomAddressFrom(address, SENT, FEE); +size_t WalletApi::sendMoneyToRandomAddressFrom(const std::string& address, const std::string& changeDestination) { + return sendMoneyToRandomAddressFrom(address, SENT, FEE, changeDestination); } void WalletApi::fillWalletWithDetailsCache() { @@ -405,34 +434,156 @@ void WalletApi::fillWalletWithDetailsCache() { auto alicePrev = alice.getActualBalance(); for (size_t i = 1; i < 5; ++i) { - sendMoneyToRandomAddressFrom(alice.getAddress(i)); + sendMoneyToRandomAddressFrom(alice.getAddress(i), alice.getAddress(0)); } node.updateObservers(); waitActualBalanceUpdated(alicePrev); for (size_t i = 5; i < 10; ++i) { - sendMoneyToRandomAddressFrom(alice.getAddress(i)); + sendMoneyToRandomAddressFrom(alice.getAddress(i), alice.getAddress(0)); } } -size_t WalletApi::sendMoney(CryptoNote::WalletGreen& wallet, const std::string& to, int64_t amount, uint64_t fee, uint64_t mixIn, const std::string& extra, uint64_t unlockTimestamp) { - CryptoNote::WalletTransfer transfer; - transfer.address = to; - transfer.amount = amount; +size_t WalletApi::sendMoney(CryptoNote::WalletGreen& wallet, const std::string& to, uint64_t amount, uint64_t fee, uint64_t mixIn, const std::string& extra, uint64_t unlockTimestamp) { + CryptoNote::WalletOrder order; + order.address = to; + order.amount = amount; - return wallet.transfer(transfer, fee, mixIn, extra, unlockTimestamp); + CryptoNote::TransactionParameters params; + params.destinations = {order}; + params.fee = fee; + params.mixIn = mixIn; + params.extra = extra; + params.unlockTimestamp = unlockTimestamp; + params.changeDestination = wallet.getAddress(0); + + return wallet.transfer(params); } -size_t WalletApi::sendMoney(const std::string& to, int64_t amount, uint64_t fee, uint64_t mixIn, const std::string& extra, uint64_t unlockTimestamp) { +size_t WalletApi::sendMoney(const std::string& to, uint64_t amount, uint64_t fee, uint64_t mixIn, const std::string& extra, uint64_t unlockTimestamp) { return sendMoney(alice, to, amount, fee, mixIn, extra, unlockTimestamp); } +size_t WalletApi::sendMoneyWithDonation(const std::string& to, uint64_t amount, uint64_t fee, + const std::string& donationAddress, uint64_t donationAmount, uint64_t mixIn, const std::string& extra, uint64_t unlockTimestamp) { + + TransactionParameters params; + params.destinations.push_back({to, amount}); + params.fee = fee; + params.donation.address = donationAddress; + params.donation.threshold = donationAmount; + params.mixIn = mixIn; + params.extra = extra; + params.unlockTimestamp = unlockTimestamp; + + return alice.transfer(params); +} + +size_t WalletApi::makeTransaction( + const std::vector& sourceAdresses, + const std::string& to, + uint64_t amount, + uint64_t fee, + uint64_t mixIn, + const std::string& extra, + uint64_t unlockTimestamp) { + + return makeTransaction(alice, sourceAdresses, to, amount, fee, mixIn, extra, unlockTimestamp); +} + +size_t WalletApi::makeTransaction( + CryptoNote::WalletGreen& wallet, + const std::vector& sourceAdresses, + const std::string& to, + uint64_t amount, + uint64_t fee, + uint64_t mixIn, + const std::string& extra, + uint64_t unlockTimestamp) { + + CryptoNote::TransactionParameters params; + params.destinations = { {to, amount} }; + params.sourceAddresses = sourceAdresses; + params.fee = fee; + params.mixIn = mixIn; + params.extra = extra; + params.unlockTimestamp = unlockTimestamp; + + return wallet.makeTransaction(params); +} + +size_t WalletApi::makeTransaction( + const std::vector& sourceAdresses, + const std::vector& orders, + uint64_t fee, + uint64_t mixIn, + const std::string& extra, + uint64_t unlockTimestamp) { + + return makeTransaction(alice, sourceAdresses, orders, fee, mixIn, extra, unlockTimestamp); +} + +size_t WalletApi::makeTransaction( + CryptoNote::WalletGreen& wallet, + const std::vector& sourceAdresses, + const std::vector& orders, + uint64_t fee, + uint64_t mixIn, + const std::string& extra, + uint64_t unlockTimestamp) { + + CryptoNote::TransactionParameters params; + params.destinations = orders; + params.sourceAddresses = sourceAdresses; + params.fee = fee; + params.mixIn = mixIn; + params.extra = extra; + params.unlockTimestamp = unlockTimestamp; + + return wallet.makeTransaction(params); +} + void WalletApi::wait(uint64_t milliseconds) { System::Timer timer(dispatcher); timer.sleep(std::chrono::nanoseconds(milliseconds * 1000000)); } +auto transfersAmountSortingFunction = [] (const CryptoNote::WalletTransfer& lhs, const CryptoNote::WalletTransfer& rhs) { + return lhs.amount < rhs.amount; +}; + +std::vector getTransfersFromTransaction(CryptoNote::WalletGreen& wallet, size_t transactionId, bool isPositiveAmount) { + std::vector transfers; + size_t transfersCount = wallet.getTransactionTransferCount(transactionId); + + for (size_t i = 0; i < transfersCount; ++i) { + WalletTransfer transfer = wallet.getTransactionTransfer(transactionId, i); + + if (isPositiveAmount == (transfer.amount >= 0)) { + transfers.push_back(std::move(transfer)); + } + } + + return transfers; +} + +void sortTransfersByAmount(std::vector& transfers) { + std::sort(transfers.begin(), transfers.end(), transfersAmountSortingFunction); //sort by amount +} + +//returns sorted transfers by amount +std::vector getTransfersFromTransaction(CryptoNote::WalletGreen& wallet, size_t transactionId) { + auto result = getTransfersFromTransaction(wallet, transactionId, true); + auto neg = getTransfersFromTransaction(wallet, transactionId, false); + + result.insert(result.end(), neg.begin(), neg.end()); + + sortTransfersByAmount(result); + + return result; +} + static const uint64_t TEST_BLOCK_REWARD = 70368744177663; TEST_F(WalletApi, emptyBalance) { @@ -497,7 +648,7 @@ TEST_F(WalletApi, pendingBalanceUpdatedAfterTransactionGotInBlock) { auto prevPending = alice.getPendingBalance(); - generator.generateEmptyBlocks(TRANSACTION_SOFTLOCK_TIME); + generator.generateEmptyBlocks(static_cast(TRANSACTION_SOFTLOCK_TIME)); node.updateObservers(); waitPendingBalanceUpdated(prevPending); @@ -511,7 +662,7 @@ TEST_F(WalletApi, moneyLockedIfTransactionIsSoftLocked) { bob.initialize("pass2"); sendMoney(bob.createAddress(), SENT, FEE); - generator.generateEmptyBlocks(TRANSACTION_SOFTLOCK_TIME - 1); + generator.generateEmptyBlocks(static_cast(TRANSACTION_SOFTLOCK_TIME - 1)); node.updateObservers(); waitPendingBalanceUpdated(bob, 0); @@ -604,19 +755,24 @@ TEST_F(WalletApi, transferTooBigTransaction) { n.updateObservers(); waitActualBalanceUpdated(wallet, prev); - std::vector destinations; + CryptoNote::TransactionParameters params; for (size_t i = 0; i < bigTxOutputCount; ++i) { - destinations.push_back({ RANDOM_ADDRESS, 1 }); + params.destinations.push_back({ RANDOM_ADDRESS, 1 }); } - ASSERT_ANY_THROW(wallet.transfer(destinations, FEE)); + params.fee = FEE; + + ASSERT_ANY_THROW(wallet.transfer(params)); } TEST_F(WalletApi, balanceAfterTransfer) { generateAndUnlockMoney(); + auto prev = alice.getActualBalance(); sendMoney(RANDOM_ADDRESS, SENT, FEE); + waitActualBalanceUpdated(alice, prev); + ASSERT_EQ(TEST_BLOCK_REWARD - SENT - FEE, alice.getActualBalance() + alice.getPendingBalance()); } @@ -650,7 +806,8 @@ TEST_F(WalletApi, transferFromSpecificAddress) { auto prevActual = alice.getActualBalance(); auto prevPending = alice.getPendingBalance(); - sendMoneyToRandomAddressFrom(secondAddress); + //send change to aliceAddress + sendMoneyToRandomAddressFrom(secondAddress, aliceAddress); node.updateObservers(); waitActualBalanceUpdated(prevActual); @@ -658,8 +815,6 @@ TEST_F(WalletApi, transferFromSpecificAddress) { ASSERT_EQ(TEST_BLOCK_REWARD, alice.getActualBalance(aliceAddress)); - //NOTE: do not expect the rule 'actual + pending == previous - sent - fee' to work, - //because change is sent to address #0. ASSERT_NE(TEST_BLOCK_REWARD, alice.getActualBalance(secondAddress)); ASSERT_NE(0, alice.getPendingBalance(aliceAddress)); ASSERT_EQ(2 * TEST_BLOCK_REWARD - SENT - FEE, alice.getActualBalance() + alice.getPendingBalance()); @@ -1071,7 +1226,7 @@ TEST_F(WalletApi, uninitializedObject) { ASSERT_ANY_THROW(bob.getTransaction(0)); ASSERT_ANY_THROW(bob.getTransactionTransferCount(0)); ASSERT_ANY_THROW(bob.getTransactionTransfer(0, 0)); - ASSERT_ANY_THROW(sendMoneyToRandomAddressFrom(aliceAddress)); + ASSERT_ANY_THROW(sendMoneyToRandomAddressFrom(aliceAddress, aliceAddress)); ASSERT_ANY_THROW(bob.shutdown()); wait(100); } @@ -1080,8 +1235,12 @@ const size_t TX_PUB_KEY_EXTRA_SIZE = 33; TEST_F(WalletApi, checkSentTransaction) { generateAndUnlockMoney(); + + auto prev = alice.getActualBalance(); size_t txId = sendMoney(RANDOM_ADDRESS, SENT, FEE); + waitActualBalanceUpdated(alice, prev); + CryptoNote::WalletTransaction tx = alice.getTransaction(txId); ASSERT_EQ(CryptoNote::WalletTransactionState::SUCCEEDED, tx.state); ASSERT_EQ(0, tx.timestamp); @@ -1114,8 +1273,12 @@ TEST_F(WalletApi, checkSentTransactionWithExtra) { const std::string extra = createExtraNonce("\x01\x23\x45\x67\x89\xab\xcd\xef"); generateAndUnlockMoney(); + + auto prev = alice.getActualBalance(); size_t txId = sendMoney(RANDOM_ADDRESS, SENT, FEE, 0, extra); + waitActualBalanceUpdated(alice, prev); + CryptoNote::WalletTransaction tx = alice.getTransaction(txId); ASSERT_EQ(CryptoNote::WalletTransactionState::SUCCEEDED, tx.state); ASSERT_EQ(0, tx.timestamp); @@ -1236,7 +1399,7 @@ TEST_F(WalletApi, deleteAddresses) { EXPECT_EQ(0, alice.getPendingBalance()); } -TEST_F(WalletApi, incomingTxTransfer) { +TEST_F(WalletApi, incomingTxTransferWithChange) { generateAndUnlockMoney(); CryptoNote::WalletGreen bob(dispatcher, currency, node, TRANSACTION_SOFTLOCK_TIME); @@ -1249,8 +1412,8 @@ TEST_F(WalletApi, incomingTxTransfer) { node.updateObservers(); waitForTransactionCount(bob, 2); - EXPECT_EQ(1, bob.getTransactionTransferCount(0)); - ASSERT_EQ(1, bob.getTransactionTransferCount(1)); + EXPECT_EQ(3, bob.getTransactionTransferCount(0)); //sent from alice + received on bob + alice change + ASSERT_EQ(3, bob.getTransactionTransferCount(1)); auto tr1 = bob.getTransactionTransfer(0, 0); EXPECT_EQ(tr1.address, bob.getAddress(0)); @@ -1264,26 +1427,136 @@ TEST_F(WalletApi, incomingTxTransfer) { wait(100); } +TEST_F(WalletApi, incomingTxTransferWithoutChange) { + generator.getSingleOutputTransaction(parseAddress(aliceAddress), SENT + FEE); + unlockMoney(); + + CryptoNote::WalletGreen bob(dispatcher, currency, node, TRANSACTION_SOFTLOCK_TIME); + bob.initialize("pass2"); + bob.createAddress(); + + sendMoney(bob.getAddress(0), SENT, FEE); + + node.updateObservers(); + waitForTransactionCount(bob, 1); + + ASSERT_EQ(2, bob.getTransactionTransferCount(0)); + bob.shutdown(); + wait(100); +} + +TEST_F(WalletApi, walletSendsTransactionUpdatedEventAfterAddingTransfer) { + generateAndUnlockMoney(); + + CryptoNote::WalletGreen bob(dispatcher, currency, node, TRANSACTION_SOFTLOCK_TIME); + bob.initialize("pass2"); + bob.createAddress(); + bob.createAddress(); + bob.createAddress(); + + CryptoNote::TransactionParameters params; + params.destinations.emplace_back(CryptoNote::WalletOrder{ bob.getAddress(0), SENT }); + params.destinations.emplace_back(CryptoNote::WalletOrder{ bob.getAddress(1), SENT }); + params.destinations.emplace_back(CryptoNote::WalletOrder{ bob.getAddress(2), SENT }); + params.fee = FEE; + alice.transfer(params); + + node.updateObservers(); + ASSERT_TRUE(waitForWalletEvent(bob, CryptoNote::WalletEventType::TRANSACTION_CREATED, std::chrono::seconds(5))); + + bob.shutdown(); + wait(100); +} + +TEST_F(WalletApi, walletCreatesTransferForEachTransactionFunding) { + generateAndUnlockMoney(); + + CryptoNote::WalletGreen bob(dispatcher, currency, node, TRANSACTION_SOFTLOCK_TIME); + bob.initialize("pass2"); + bob.createAddress(); + bob.createAddress(); + + CryptoNote::TransactionParameters params; + params.destinations.emplace_back(CryptoNote::WalletOrder{ bob.getAddress(0), SENT }); + params.destinations.emplace_back(CryptoNote::WalletOrder{ bob.getAddress(1), 2 * SENT }); + + params.fee = FEE; + alice.transfer(params); + + node.updateObservers(); + ASSERT_TRUE(waitForWalletEvent(bob, CryptoNote::WalletEventType::TRANSACTION_CREATED, std::chrono::seconds(5))); + + //2 incoming transfers to bob's addresses(0, 1) and one outgoing for alice(0) + change to alice(0) + ASSERT_EQ(4, bob.getTransactionTransferCount(0)); + auto tr1 = bob.getTransactionTransfer(0, 0); + auto tr2 = bob.getTransactionTransfer(0, 1); + ASSERT_TRUE(tr1.address == bob.getAddress(0) || tr1.address == bob.getAddress(1)); + ASSERT_TRUE(tr2.address == bob.getAddress(0) || tr2.address == bob.getAddress(1)); + ASSERT_NE(tr1.address, tr2.address); + + bob.shutdown(); + wait(100); +} + +size_t getTransactionUsualTransferCount(WalletGreen& wallet, size_t transactionIndex) { + size_t transfersCount = wallet.getTransactionTransferCount(transactionIndex); + size_t usualTransfersCount = 0; + for (size_t i = 0; i < transfersCount; ++i) { + if (wallet.getTransactionTransfer(transactionIndex, i).type == WalletTransferType::USUAL) { + ++usualTransfersCount; + } + } + + return usualTransfersCount; +} + TEST_F(WalletApi, hybridTxTransfer) { generateAndUnlockMoney(); alice.createAddress(); alice.createAddress(); - CryptoNote::WalletTransfer tr1 { alice.getAddress(1), static_cast(SENT) }; - CryptoNote::WalletTransfer tr2 { alice.getAddress(2), static_cast(2 * SENT) }; + CryptoNote::WalletOrder tr1 { alice.getAddress(1), SENT }; + CryptoNote::WalletOrder tr2 { alice.getAddress(2), 2 * SENT }; - alice.transfer({tr1, tr2}, FEE); + CryptoNote::TransactionParameters params; + params.destinations = {tr1, tr2}; + params.fee = FEE; + params.changeDestination = alice.getAddress(0); + alice.transfer(params); node.updateObservers(); dispatcher.yield(); - ASSERT_EQ(2, alice.getTransactionTransferCount(1)); + //2 incoming transfers to alice's addresses(1, 2) and one outgoing for alice(0) + ASSERT_EQ(3, getTransactionUsualTransferCount(alice, 1)); - EXPECT_EQ(tr1.address, alice.getTransactionTransfer(1, 0).address); - EXPECT_EQ(-tr1.amount, alice.getTransactionTransfer(1, 0).amount); + WalletTransactionWithTransfers transfersWithTx; + ASSERT_NO_THROW({ + transfersWithTx = alice.getTransaction(alice.getTransaction(1).hash); + }); + //2 incoming transfers to alice's addresses(1, 2) and one outgoing for alice(0) + change to alice(0) + ASSERT_EQ(4, transfersWithTx.transfers.size()); - EXPECT_EQ(tr2.address, alice.getTransactionTransfer(1, 1).address); - EXPECT_EQ(-tr2.amount, alice.getTransactionTransfer(1, 1).amount); + auto iter = std::find_if(transfersWithTx.transfers.begin(), transfersWithTx.transfers.end(), [&tr1](const WalletTransfer& transfer) { + return tr1.address == transfer.address && tr1.amount == transfer.amount && WalletTransferType::USUAL == transfer.type; + }); + EXPECT_NE(transfersWithTx.transfers.end(), iter); + + iter = std::find_if(transfersWithTx.transfers.begin(), transfersWithTx.transfers.end(), [&tr2](const WalletTransfer& transfer) { + return tr2.address == transfer.address && tr2.amount == transfer.amount && WalletTransferType::USUAL == transfer.type; + }); + EXPECT_NE(transfersWithTx.transfers.end(), iter); + + iter = std::find_if(transfersWithTx.transfers.begin(), transfersWithTx.transfers.end(), [this](const WalletTransfer& transfer) { + return alice.getAddress(0) == transfer.address && WalletTransferType::CHANGE == transfer.type; + }); + EXPECT_NE(transfersWithTx.transfers.end(), iter); + WalletTransfer changeTransfer = *iter; + + iter = std::find_if(transfersWithTx.transfers.begin(), transfersWithTx.transfers.end(), [this, &tr1, &tr2, &changeTransfer](const WalletTransfer& transfer) { + return alice.getAddress(0) == transfer.address && -static_cast(tr1.amount + tr2.amount + FEE + changeTransfer.amount) == transfer.amount && WalletTransferType::USUAL == transfer.type; + }); + EXPECT_NE(transfersWithTx.transfers.end(), iter); } TEST_F(WalletApi, doubleSpendJustSentOut) { @@ -1313,7 +1586,7 @@ class INodeNoRelay : public INodeTrivialRefreshStub { public: INodeNoRelay(TestBlockchainGenerator& generator) : INodeTrivialRefreshStub(generator) {} - virtual void relayTransaction(const CryptoNote::Transaction& transaction, const Callback& callback) { + virtual void relayTransaction(const CryptoNote::Transaction& transaction, const Callback& callback) override { m_asyncCounter.addAsyncContext(); std::thread task(&INodeNoRelay::doNoRelayTransaction, this, transaction, callback); task.detach(); @@ -1376,10 +1649,7 @@ TEST_F(WalletApi, DISABLED_loadTest) { steady_clock::time_point transferStart = steady_clock::now(); for (size_t i = 0; i < TRANSACTIONS_COUNT; ++i) { - CryptoNote::WalletTransfer tr; - tr.amount = SENT; - tr.address = RANDOM_ADDRESS; - wallet.transfer(tr, FEE); + sendMoney(wallet, RANDOM_ADDRESS, SENT, FEE); } steady_clock::time_point transferEnd = steady_clock::now(); std::cout << "transfers took: " << duration_cast(transferEnd - transferStart).count() << " ms" << std::endl; @@ -1391,7 +1661,7 @@ TEST_F(WalletApi, DISABLED_loadTest) { TEST_F(WalletApi, transferSmallFeeTransactionThrows) { generateAndUnlockMoney(); - ASSERT_ANY_THROW(sendMoneyToRandomAddressFrom(alice.getAddress(0), SENT, currency.minimumFee() - 1)); + ASSERT_ANY_THROW(sendMoneyToRandomAddressFrom(alice.getAddress(0), SENT, currency.minimumFee() - 1, alice.getAddress(0))); } TEST_F(WalletApi, initializeWithKeysSucceded) { @@ -1826,20 +2096,1453 @@ TEST_F(WalletApi, fusionManagerIsFusionTransactionSpent) { wallet.createAddress(); generateFusionOutputsAndUnlock(alice, node, currency, FUSION_THRESHOLD); + auto initialBalance = alice.getActualBalance(); auto id = alice.createFusionTransaction(FUSION_THRESHOLD, 0); ASSERT_NE(WALLET_INVALID_TRANSACTION_ID, id); unlockMoney(); - CryptoNote::WalletTransfer transfer; - transfer.address = wallet.getAddress(0); - transfer.amount = alice.getActualBalance() - currency.minimumFee(); - alice.transfer(aliceAddress, transfer, currency.minimumFee(), 0); + waitForActualBalance(initialBalance); auto pending = wallet.getPendingBalance(); + ASSERT_NE(0, alice.getActualBalance()); + sendMoney(wallet.getAddress(0), alice.getActualBalance() - currency.minimumFee(), currency.minimumFee()); + node.updateObservers(); waitPendingBalanceUpdated(wallet, pending); ASSERT_TRUE(alice.isFusionTransaction(id)); } +size_t findDonationTransferId(const WalletGreen& wallet, size_t transactionId) { + for (size_t i = 0; i < wallet.getTransactionTransferCount(transactionId); ++i) { + if (wallet.getTransactionTransfer(transactionId, i).type == WalletTransferType::DONATION) { + return i; + } + } + + return WALLET_INVALID_TRANSFER_ID; +} + +TEST_F(WalletApi, donationTransferPresents) { + const uint64_t DONATION_THRESHOLD = 1000000; + + generator.getSingleOutputTransaction(parseAddress(aliceAddress), SENT + FEE + DONATION_THRESHOLD); + unlockMoney(); + + auto transactionId = sendMoneyWithDonation(RANDOM_ADDRESS, SENT, FEE, RANDOM_ADDRESS, DONATION_THRESHOLD); + + ASSERT_NE(WALLET_INVALID_TRANSACTION_ID, transactionId); + + auto donationTransferId = findDonationTransferId(alice, transactionId); + ASSERT_NE(WALLET_INVALID_TRANSFER_ID, donationTransferId); + + auto donationTransfer = alice.getTransactionTransfer(transactionId, donationTransferId); + ASSERT_EQ(WalletTransferType::DONATION, donationTransfer.type); + ASSERT_EQ(DONATION_THRESHOLD, donationTransfer.amount); + ASSERT_EQ(RANDOM_ADDRESS, donationTransfer.address); +} + +TEST_F(WalletApi, donationDidntHappenIfNotEnoughMoney) { + const uint64_t DONATION_THRESHOLD = 1000000; + + generator.getSingleOutputTransaction(parseAddress(aliceAddress), SENT + FEE); + unlockMoney(); + + auto transactionId = sendMoneyWithDonation(RANDOM_ADDRESS, SENT, FEE, RANDOM_ADDRESS, DONATION_THRESHOLD); + ASSERT_NE(WALLET_INVALID_TRANSACTION_ID, transactionId); + ASSERT_EQ(WALLET_INVALID_TRANSFER_ID, findDonationTransferId(alice, transactionId)); +} + +TEST_F(WalletApi, donationThrowsIfAddressEmpty) { + const uint64_t DONATION_THRESHOLD = 1000000; + + generator.getSingleOutputTransaction(parseAddress(aliceAddress), SENT + FEE + DONATION_THRESHOLD); + unlockMoney(); + + TransactionParameters params; + params.destinations.push_back({RANDOM_ADDRESS, SENT}); + params.fee = FEE; + params.donation.threshold = DONATION_THRESHOLD; + + ASSERT_ANY_THROW(alice.transfer(params)); +} + +TEST_F(WalletApi, donationThrowsIfThresholdZero) { + const uint64_t DONATION_THRESHOLD = 1000000; + + generator.getSingleOutputTransaction(parseAddress(aliceAddress), SENT + FEE + DONATION_THRESHOLD); + unlockMoney(); + + TransactionParameters params; + params.destinations.push_back({RANDOM_ADDRESS, SENT}); + params.fee = FEE; + params.donation.address = RANDOM_ADDRESS; + params.donation.threshold = 0; + + ASSERT_ANY_THROW(alice.transfer(params)); +} + +TEST_F(WalletApi, donationTransactionHaveCorrectFee) { + CatchTransactionNodeStub catchNode(generator); + CryptoNote::WalletGreen wallet(dispatcher, currency, catchNode); + wallet.initialize("pass"); + wallet.createAddress(); + + const uint64_t DONATION_THRESHOLD = 1000000; + + generator.getSingleOutputTransaction(parseAddress(wallet.getAddress(0)), SENT + FEE + DONATION_THRESHOLD); + unlockMoney(wallet, catchNode); + + TransactionParameters params; + params.destinations.push_back({RANDOM_ADDRESS, SENT}); + params.fee = FEE; + params.donation.address = RANDOM_ADDRESS; + params.donation.threshold = DONATION_THRESHOLD; + + wallet.transfer(params); + + ASSERT_TRUE(catchNode.caught); + ASSERT_EQ(FEE, getInputAmount(catchNode.transaction) - getOutputAmount(catchNode.transaction)); + + wallet.shutdown(); +} + +TEST_F(WalletApi, donationSerialization) { + const uint64_t DONATION_THRESHOLD = 1000000; + + generator.getSingleOutputTransaction(parseAddress(aliceAddress), SENT + FEE + DONATION_THRESHOLD); + unlockMoney(); + + sendMoneyWithDonation(RANDOM_ADDRESS, SENT, FEE, RANDOM_ADDRESS, DONATION_THRESHOLD); + + std::stringstream data; + alice.save(data, true, true); + + WalletGreen bob(dispatcher, currency, node, TRANSACTION_SOFTLOCK_TIME); + bob.load(data, "pass"); + + compareWalletsTransactionTransfers(alice, bob); + bob.shutdown(); +} + +TEST_F(WalletApi, transferThrowsIfDonationThresholdTooBig) { + const uint64_t DONATION_THRESHOLD = static_cast(std::numeric_limits::max()) + 1; + + generator.getSingleOutputTransaction(parseAddress(aliceAddress), SENT + FEE); + unlockMoney(); + + ASSERT_ANY_THROW(sendMoneyWithDonation(RANDOM_ADDRESS, SENT, FEE, RANDOM_ADDRESS, DONATION_THRESHOLD)); +} + +namespace { + +class WalletApi_makeTransaction : public WalletApi { +public: + WalletApi_makeTransaction() : + WalletApi() { + } + +protected: + int makeAliceTransactionAndReturnErrorCode(const std::string& sourceAddress, const std::vector& destinations, + uint64_t fee, uint64_t mixIn, const std::string& extra = "") { + + try { + makeTransaction({sourceAddress}, destinations, fee, mixIn, extra); + } catch (std::system_error& e) { + return e.code().value(); + } + + return 0; + } + + std::string getExtraForBigTransaction() const { + size_t extraSize = 2 * currency.blockGrantedFullRewardZone(); + return std::string(extraSize, static_cast(0)); + } +}; + +} + +TEST_F(WalletApi_makeTransaction, throwsIfStopped) { + alice.stop(); + ASSERT_ANY_THROW(makeTransaction({}, RANDOM_ADDRESS, SENT, FEE, 0)); +} + +TEST_F(WalletApi_makeTransaction, throwsIfSourceAddressIsInvalid) { + generateAndUnlockMoney(); + ASSERT_ANY_THROW(makeTransaction({"not an address"}, RANDOM_ADDRESS, SENT, FEE, 0)); +} + +TEST_F(WalletApi_makeTransaction, throwsIfDestinationsIsEmpty) { + generateAndUnlockMoney(); + int error = makeAliceTransactionAndReturnErrorCode(alice.getAddress(0), {}, FEE, 0); + ASSERT_EQ(static_cast(error::WalletErrorCodes::ZERO_DESTINATION), error); +} + +TEST_F(WalletApi_makeTransaction, throwsIfDestinationsHasInvalidAddress) { + generateAndUnlockMoney(); + int error = makeAliceTransactionAndReturnErrorCode({alice.getAddress(0)}, { CryptoNote::WalletOrder{ "not an address", SENT } }, FEE, 0); + ASSERT_EQ(static_cast(error::WalletErrorCodes::BAD_ADDRESS), error); +} + +TEST_F(WalletApi_makeTransaction, throwsIfDestinationHasZeroAmount) { + generateAndUnlockMoney(); + int error = makeAliceTransactionAndReturnErrorCode({alice.getAddress(0)}, { CryptoNote::WalletOrder{ RANDOM_ADDRESS, 0 } }, FEE, 0); + ASSERT_EQ(static_cast(error::WalletErrorCodes::ZERO_DESTINATION), error); +} + +TEST_F(WalletApi_makeTransaction, throwsIfDestinationHasTooBigAmount) { + generateAndUnlockMoney(); + CryptoNote::WalletOrder order; + order.address = RANDOM_ADDRESS; + order.amount = static_cast(std::numeric_limits::max()) + 1; + int error = makeAliceTransactionAndReturnErrorCode({alice.getAddress(0)}, { order }, FEE, 0); + ASSERT_EQ(static_cast(CryptoNote::error::WalletErrorCodes::WRONG_AMOUNT), error); +} + +TEST_F(WalletApi_makeTransaction, throwsIfSumOfDestinationsAmountsOverflows) { + generateAndUnlockMoney(); + std::vector destinations; + destinations.push_back({ RANDOM_ADDRESS, SENT }); + destinations.push_back({ RANDOM_ADDRESS, std::numeric_limits::max() }); + int error = makeAliceTransactionAndReturnErrorCode({alice.getAddress(0)}, destinations, FEE, 0); + ASSERT_EQ(static_cast(error::WalletErrorCodes::WRONG_AMOUNT), error); +} + +TEST_F(WalletApi_makeTransaction, throwsIfFeeIsLessThanMinimumFee) { + if (currency.minimumFee() > 0) { + generateAndUnlockMoney(); + int error = makeAliceTransactionAndReturnErrorCode({alice.getAddress(0)}, { CryptoNote::WalletOrder{ RANDOM_ADDRESS, SENT } }, currency.minimumFee() - 1, 0); + ASSERT_EQ(static_cast(error::WalletErrorCodes::FEE_TOO_SMALL), error); + } +} + +TEST_F(WalletApi_makeTransaction, throwsIfWalletHasNotEnoughMoney) { + generateAndUnlockMoney(); + uint64_t available = alice.getActualBalance(); + ASSERT_GT(available, FEE); + uint64_t amount = available - FEE + 1; + int error = makeAliceTransactionAndReturnErrorCode({alice.getAddress(0)}, { CryptoNote::WalletOrder{ RANDOM_ADDRESS, amount } }, FEE, 0); + ASSERT_EQ(static_cast(error::WalletErrorCodes::WRONG_AMOUNT), error); +} + +TEST_F(WalletApi_makeTransaction, throwsIfMixInIsTooBig) { + generateAndUnlockMoney(); + uint64_t mixin = 10; + node.setMaxMixinCount(mixin - 1); + int error = makeAliceTransactionAndReturnErrorCode({alice.getAddress(0)}, { CryptoNote::WalletOrder{ RANDOM_ADDRESS, SENT } }, FEE, mixin); + ASSERT_EQ(static_cast(error::WalletErrorCodes::MIXIN_COUNT_TOO_BIG), error); +} + +TEST_F(WalletApi_makeTransaction, throwsIfTransactionIsTooBig) { + generateAndUnlockMoney(); + std::string extra = getExtraForBigTransaction(); + int error = makeAliceTransactionAndReturnErrorCode({alice.getAddress(0)}, { CryptoNote::WalletOrder{ RANDOM_ADDRESS, SENT } }, FEE, 0, extra); + ASSERT_EQ(static_cast(error::WalletErrorCodes::TRANSACTION_SIZE_TOO_BIG), error); +} + +TEST_F(WalletApi_makeTransaction, createdTransactionCanBeReceivedByGetTransactionAndHasCorrectFieldValues) { + const uint64_t MONEY = SENT + FEE + 1; + generator.getSingleOutputTransaction(parseAddress(aliceAddress), MONEY); + unlockMoney(); + + std::string extra = "some extra"; + uint64_t unlockTimestamp = 7823673; + + auto txId = makeTransaction({alice.getAddress(0)}, { CryptoNote::WalletOrder{ RANDOM_ADDRESS, SENT } }, FEE, 0, extra, unlockTimestamp); + + waitForTransactionUpdated(alice, txId); + + CryptoNote::WalletTransaction tx; + ASSERT_NO_THROW(tx = alice.getTransaction(txId)); + ASSERT_EQ(WalletTransactionState::CREATED, tx.state); + ASSERT_EQ(0, tx.timestamp); + ASSERT_EQ(WALLET_UNCONFIRMED_TRANSACTION_HEIGHT, tx.blockHeight); + ASSERT_EQ(-static_cast(SENT + FEE), tx.totalAmount); + ASSERT_EQ(FEE, tx.fee); + ASSERT_NE(0, tx.creationTime); + ASSERT_EQ(unlockTimestamp, tx.unlockTime); + ASSERT_NE(std::string::npos, tx.extra.find(extra)); + ASSERT_FALSE(tx.isBase); + + auto transfers = getTransfersFromTransaction(alice, txId); + ASSERT_EQ(3, transfers.size()); //one transfer for source address, one transfer for destination, one transfer for change + + //source + EXPECT_EQ(aliceAddress, transfers[0].address); + EXPECT_EQ(-static_cast(MONEY), transfers[0].amount); + + //change + EXPECT_EQ(aliceAddress, transfers[1].address); + EXPECT_EQ(MONEY - SENT - FEE, transfers[1].amount); + + //destination + EXPECT_EQ(RANDOM_ADDRESS, transfers[2].address); + EXPECT_EQ(SENT, transfers[2].amount); +} + +TEST_F(WalletApi_makeTransaction, methodLocksMoneyUsedInTransaction) { + generateAndUnlockMoney(); + + std::string sourceAddress = alice.getAddress(0); + uint64_t actualBefore = alice.getActualBalance(sourceAddress); + uint64_t pendingBefore = alice.getPendingBalance(sourceAddress); + auto txId = makeTransaction({sourceAddress}, { CryptoNote::WalletOrder{ RANDOM_ADDRESS, SENT } }, FEE, 0); + + waitForTransactionUpdated(alice, txId); + + ASSERT_GE(actualBefore - SENT - FEE, alice.getActualBalance(sourceAddress)); + ASSERT_LE(pendingBefore, alice.getPendingBalance(sourceAddress)); +} + +TEST_F(WalletApi_makeTransaction, ifFailedMoneyDoesNotLocked) { + generateAndUnlockMoney(); + + std::string sourceAddress = alice.getAddress(0); + uint64_t actualBefore = alice.getActualBalance(sourceAddress); + uint64_t pendingBefore = alice.getPendingBalance(sourceAddress); + ASSERT_ANY_THROW(makeTransaction({sourceAddress}, { CryptoNote::WalletOrder{ RANDOM_ADDRESS, SENT } }, FEE, 0, getExtraForBigTransaction())); + + ASSERT_EQ(actualBefore, alice.getActualBalance(sourceAddress)); + ASSERT_EQ(pendingBefore, alice.getPendingBalance(sourceAddress)); +} + +TEST_F(WalletApi_makeTransaction, sendsTransactionCreatedEvent) { + generateAndUnlockMoney(); + makeTransaction({alice.getAddress(0)}, { CryptoNote::WalletOrder{ RANDOM_ADDRESS, SENT } }, FEE, 0); + ASSERT_TRUE(waitForWalletEvent(alice, WalletEventType::TRANSACTION_CREATED, std::chrono::seconds(5))); +} + +TEST_F(WalletApi_makeTransaction, ifFailedDoesNotSendTransactionCreatedEvent) { + generateAndUnlockMoney(); + + System::Context eventContext(dispatcher, [this]() { + bool res; + + for (;;) { + try { + CryptoNote::WalletEvent event = alice.getEvent(); + if (event.type == WalletEventType::TRANSACTION_CREATED) { + res = true; + break; + } + } catch (System::InterruptedException&) { + res = false; + break; + } + } + + return res; + }); + + ASSERT_ANY_THROW(makeTransaction({alice.getAddress(0)}, { CryptoNote::WalletOrder{ RANDOM_ADDRESS, SENT } }, FEE, 0, getExtraForBigTransaction())); + + dispatcher.yield(); + eventContext.interrupt(); + ASSERT_FALSE(eventContext.get()); +} + +namespace { + +class WalletApi_commitTransaction : public WalletApi { +public: + WalletApi_commitTransaction() : + WalletApi() { + } + +protected: + size_t generateMoneyAndMakeAliceTransaction() { + generateAndUnlockMoney(); + return makeTransaction({alice.getAddress(0)}, { CryptoNote::WalletOrder{ RANDOM_ADDRESS, SENT } }, FEE, 0); + } + + int commitAliceTransactionAndReturnErrorCode(size_t transactionId) { + try { + alice.commitTransaction(transactionId); + } catch (std::system_error& e) { + return e.code().value(); + } + + return 0; + } +}; + +} + +TEST_F(WalletApi_commitTransaction, throwsIfStopped) { + auto txId = generateMoneyAndMakeAliceTransaction(); + alice.stop(); + ASSERT_ANY_THROW(alice.commitTransaction(txId)); +} + +TEST_F(WalletApi_commitTransaction, throwsIfTransactionIdIsInvalid) { + auto txId = generateMoneyAndMakeAliceTransaction(); + int error = commitAliceTransactionAndReturnErrorCode(txId + 1); + ASSERT_EQ(static_cast(error::WalletErrorCodes::INDEX_OUT_OF_RANGE), error); +} + +TEST_F(WalletApi_commitTransaction, throwsIfTransactionIsInSucceededState) { + auto txId = generateMoneyAndMakeAliceTransaction(); + alice.commitTransaction(txId); + + int error = commitAliceTransactionAndReturnErrorCode(txId); + ASSERT_EQ(static_cast(error::WalletErrorCodes::TX_TRANSFER_IMPOSSIBLE), error); +} + +TEST_F(WalletApi_commitTransaction, canSendTransactionAfterFail) { + auto txId = generateMoneyAndMakeAliceTransaction(); + node.setNextTransactionError(); + ASSERT_ANY_THROW(alice.commitTransaction(txId)); + + ASSERT_NO_THROW(alice.commitTransaction(txId)); +} + +TEST_F(WalletApi_commitTransaction, throwsIfTransactionIsInCancelledState) { + auto txId = generateMoneyAndMakeAliceTransaction(); + alice.rollbackUncommitedTransaction(txId); + + int error = commitAliceTransactionAndReturnErrorCode(txId); + ASSERT_EQ(static_cast(error::WalletErrorCodes::TX_TRANSFER_IMPOSSIBLE), error); +} + +TEST_F(WalletApi_commitTransaction, changesTransactionStateToSucceededIfTransactionSent) { + auto txId = generateMoneyAndMakeAliceTransaction(); + alice.commitTransaction(txId); + auto tx = alice.getTransaction(txId); + ASSERT_EQ(WalletTransactionState::SUCCEEDED, tx.state); +} + +TEST_F(WalletApi_commitTransaction, remainsTransactionStateCreatedIfTransactionSendFailed) { + auto txId = generateMoneyAndMakeAliceTransaction(); + node.setNextTransactionError(); + ASSERT_ANY_THROW(alice.commitTransaction(txId)); + auto tx = alice.getTransaction(txId); + ASSERT_EQ(WalletTransactionState::CREATED, tx.state); +} + +TEST_F(WalletApi_commitTransaction, doesNotUnlockMoneyIfTransactionCommitFailed) { + generateAndUnlockMoney(); + + std::string sourceAddress = alice.getAddress(0); + auto txId = makeTransaction({alice.getAddress(0)}, { CryptoNote::WalletOrder{ RANDOM_ADDRESS, SENT } }, FEE, 0); + + uint64_t actualBefore = alice.getActualBalance(sourceAddress); + uint64_t pendingBefore = alice.getPendingBalance(sourceAddress); + + node.setNextTransactionError(); + ASSERT_ANY_THROW(alice.commitTransaction(txId)); + + ASSERT_EQ(actualBefore, alice.getActualBalance(sourceAddress)); + ASSERT_EQ(pendingBefore, alice.getPendingBalance(sourceAddress)); +} + +TEST_F(WalletApi_commitTransaction, doesNotChangeBalanceIfTransactionSent) { + generateAndUnlockMoney(); + + std::string sourceAddress = alice.getAddress(0); + auto txId = makeTransaction({alice.getAddress(0)}, { CryptoNote::WalletOrder{ RANDOM_ADDRESS, SENT } }, FEE, 0); + waitForTransactionUpdated(alice, txId); + + uint64_t actualBefore = alice.getActualBalance(sourceAddress); + uint64_t pendingBefore = alice.getPendingBalance(sourceAddress); + + alice.commitTransaction(txId); + + waitForTransactionUpdated(alice, txId); + + EXPECT_EQ(actualBefore, alice.getActualBalance(sourceAddress)); + EXPECT_EQ(pendingBefore, alice.getPendingBalance(sourceAddress)); +} + +TEST_F(WalletApi_commitTransaction, sendsTransactionUpdatedEventIfTransactionSent) { + auto txId = generateMoneyAndMakeAliceTransaction(); + alice.commitTransaction(txId); + + ASSERT_TRUE(waitForWalletEvent(alice, WalletEventType::TRANSACTION_UPDATED, std::chrono::seconds(5))); +} + +namespace { + +class WalletApi_rollbackUncommitedTransaction : public WalletApi { +public: + WalletApi_rollbackUncommitedTransaction() : + WalletApi() { + } + +protected: + size_t generateMoneyAndMakeAliceTransaction() { + generateAndUnlockMoney(); + auto txId = makeTransaction({alice.getAddress(0)}, { CryptoNote::WalletOrder{ RANDOM_ADDRESS, SENT } }, FEE, 0); + + waitForTransactionUpdated(alice, txId); + return txId; + } + + int rollbackAliceTransactionAndReturnErrorCode(size_t transactionId) { + try { + alice.rollbackUncommitedTransaction(transactionId); + } catch (std::system_error& e) { + return e.code().value(); + } + + return 0; + } +}; + +} + +TEST_F(WalletApi_rollbackUncommitedTransaction, throwsIfStopped) { + auto txId = generateMoneyAndMakeAliceTransaction(); + alice.stop(); + ASSERT_ANY_THROW(alice.rollbackUncommitedTransaction(txId)); +} + +TEST_F(WalletApi_rollbackUncommitedTransaction, throwsIfTransactionIdIsInvalid) { + auto txId = generateMoneyAndMakeAliceTransaction(); + int error = rollbackAliceTransactionAndReturnErrorCode(txId + 1); + ASSERT_EQ(static_cast(error::WalletErrorCodes::INDEX_OUT_OF_RANGE), error); +} + +TEST_F(WalletApi_rollbackUncommitedTransaction, throwsIfTransactionIsInSucceededState) { + auto txId = generateMoneyAndMakeAliceTransaction(); + alice.commitTransaction(txId); + + int error = rollbackAliceTransactionAndReturnErrorCode(txId); + ASSERT_EQ(static_cast(error::WalletErrorCodes::TX_CANCEL_IMPOSSIBLE), error); +} + +TEST_F(WalletApi_rollbackUncommitedTransaction, rollsBackTransactionAfterFail) { + auto txId = generateMoneyAndMakeAliceTransaction(); + node.setNextTransactionError(); + ASSERT_ANY_THROW(alice.commitTransaction(txId)); + + int error = rollbackAliceTransactionAndReturnErrorCode(txId); + ASSERT_EQ(0, error); +} + +TEST_F(WalletApi_rollbackUncommitedTransaction, throwsIfTransactionIsInCancelledState) { + auto txId = generateMoneyAndMakeAliceTransaction(); + alice.rollbackUncommitedTransaction(txId); + + int error = rollbackAliceTransactionAndReturnErrorCode(txId); + ASSERT_EQ(static_cast(error::WalletErrorCodes::TX_CANCEL_IMPOSSIBLE), error); +} + +TEST_F(WalletApi_rollbackUncommitedTransaction, changesTransactionStateToCancelledIfTransactionRolledback) { + auto txId = generateMoneyAndMakeAliceTransaction(); + alice.rollbackUncommitedTransaction(txId); + auto tx = alice.getTransaction(txId); + ASSERT_EQ(WalletTransactionState::CANCELLED, tx.state); +} + +TEST_F(WalletApi_rollbackUncommitedTransaction, doesNotChangeTransactionStateToCancelledIfTransactionRolledbackFailed) { + auto txId = generateMoneyAndMakeAliceTransaction(); + alice.commitTransaction(txId); + ASSERT_ANY_THROW(alice.rollbackUncommitedTransaction(txId)); + auto tx = alice.getTransaction(txId); + ASSERT_NE(WalletTransactionState::CANCELLED, tx.state); +} + +TEST_F(WalletApi_rollbackUncommitedTransaction, unlocksMoneyIfTransactionRolledback) { + generateAndUnlockMoney(); + + std::string sourceAddress = alice.getAddress(0); + uint64_t actualBefore = alice.getActualBalance(sourceAddress); + uint64_t pendingBefore = alice.getPendingBalance(sourceAddress); + + auto txId = makeTransaction({alice.getAddress(0)}, { CryptoNote::WalletOrder{ RANDOM_ADDRESS, SENT } }, FEE, 0); + alice.rollbackUncommitedTransaction(txId); + + ASSERT_EQ(actualBefore, alice.getActualBalance(sourceAddress)); + ASSERT_EQ(pendingBefore, alice.getPendingBalance(sourceAddress)); +} + +TEST_F(WalletApi_rollbackUncommitedTransaction, doesNotChangeBalanceIfTransactionRollbackFailed) { + generateAndUnlockMoney(); + + std::string sourceAddress = alice.getAddress(0); + auto txId = makeTransaction({sourceAddress}, { CryptoNote::WalletOrder{ RANDOM_ADDRESS, SENT } }, FEE, 0); + alice.rollbackUncommitedTransaction(txId); + + uint64_t actualBefore = alice.getActualBalance(sourceAddress); + uint64_t pendingBefore = alice.getPendingBalance(sourceAddress); + ASSERT_ANY_THROW(alice.rollbackUncommitedTransaction(txId)); + + ASSERT_EQ(actualBefore, alice.getActualBalance(sourceAddress)); + ASSERT_EQ(pendingBefore, alice.getPendingBalance(sourceAddress)); +} + +TEST_F(WalletApi_rollbackUncommitedTransaction, sendsTransactionUpdatedEventIfTransactionRolledback) { + auto txId = generateMoneyAndMakeAliceTransaction(); + alice.rollbackUncommitedTransaction(txId); + + ASSERT_TRUE(waitForWalletEvent(alice, WalletEventType::TRANSACTION_UPDATED, std::chrono::seconds(5))); +} + +TEST_F(WalletApi_rollbackUncommitedTransaction, doesNotSendTransactionUpdatedEventIfTransactionRollbackFailed) { + auto txId = generateMoneyAndMakeAliceTransaction(); + alice.commitTransaction(txId); + ASSERT_TRUE(waitForWalletEvent(alice, WalletEventType::TRANSACTION_UPDATED, std::chrono::seconds(5))); + + System::Context eventContext(dispatcher, [this]() { + bool res; + + for (;;) { + try { + CryptoNote::WalletEvent event = alice.getEvent(); + if (event.type == WalletEventType::TRANSACTION_UPDATED) { + res = true; + break; + } + } catch (System::InterruptedException&) { + res = false; + break; + } + } + + return res; + }); + + ASSERT_ANY_THROW(alice.rollbackUncommitedTransaction(txId)); + + dispatcher.yield(); + eventContext.interrupt(); + ASSERT_FALSE(eventContext.get()); +} + +TEST_F(WalletApi, getTransactionThrowsIfTransactionNotFound) { + Crypto::Hash hash; + std::generate(std::begin(hash.data), std::end(hash.data), std::rand); + + ASSERT_ANY_THROW(alice.getTransaction(hash)); +} + +TEST_F(WalletApi, getTransactionThrowsIfStopped) { + alice.stop(); + + Crypto::Hash hash; + std::generate(std::begin(hash.data), std::end(hash.data), std::rand); + + ASSERT_ANY_THROW(alice.getTransaction(hash)); +} + +TEST_F(WalletApi, getTransactionThrowsIfNotInitialized) { + WalletGreen wallet(dispatcher, currency, node); + + Crypto::Hash hash; + std::generate(std::begin(hash.data), std::end(hash.data), std::rand); + + ASSERT_ANY_THROW(wallet.getTransaction(hash)); +} + +TEST_F(WalletApi, getTransactionReturnsCorrectTransaction) { + const uint64_t MONEY = 2 * SENT + 2 * FEE + 1; + + generator.getSingleOutputTransaction(parseAddress(aliceAddress), MONEY); + unlockMoney(); + + CryptoNote::TransactionParameters params; + params.destinations = { CryptoNote::WalletOrder {RANDOM_ADDRESS, SENT}, CryptoNote::WalletOrder {RANDOM_ADDRESS, SENT + FEE} }; + params.fee = FEE; + + auto txId = alice.transfer(params); + + waitForTransactionUpdated(alice, txId); //first notification comes right after inserting transaction. totalAmount at the moment is 0 + waitForTransactionUpdated(alice, txId); //second notification comes after processing the transaction by TransfersContainer + + Crypto::Hash hash = alice.getTransaction(txId).hash; + + CryptoNote::WalletTransactionWithTransfers tx = alice.getTransaction(hash); + CryptoNote::WalletTransaction transaction = tx.transaction; + + EXPECT_EQ(CryptoNote::WalletTransactionState::SUCCEEDED, transaction.state); + EXPECT_EQ(CryptoNote::WALLET_UNCONFIRMED_TRANSACTION_HEIGHT, transaction.blockHeight); + EXPECT_EQ(FEE, transaction.fee); + EXPECT_FALSE(transaction.isBase); + EXPECT_EQ(0, transaction.unlockTime); + + ASSERT_EQ(-static_cast(SENT * 2 + FEE * 2), tx.transaction.totalAmount); + + ASSERT_EQ(4, tx.transfers.size()); //2 transfers for user's orders, 1 transfer for change, 1 transfer for source + sortTransfersByAmount(tx.transfers); + + //source + EXPECT_EQ(aliceAddress, tx.transfers[0].address); + EXPECT_EQ(-static_cast(MONEY), tx.transfers[0].amount); + + //change + EXPECT_EQ(aliceAddress, tx.transfers[1].address); + EXPECT_EQ(static_cast(MONEY - 2 * SENT - 2 * FEE), tx.transfers[1].amount); + + //destinations + EXPECT_EQ(RANDOM_ADDRESS, tx.transfers[2].address); + EXPECT_EQ(static_cast(SENT), tx.transfers[2].amount); + + EXPECT_EQ(RANDOM_ADDRESS, tx.transfers[3].address); + EXPECT_EQ(static_cast(SENT + FEE), tx.transfers[3].amount); +} + +TEST_F(WalletApi, getTransactionsThrowsIfStopped) { + alice.stop(); + ASSERT_ANY_THROW(alice.getTransactions(0, 10)); + alice.start(); +} + +TEST_F(WalletApi, getTransactionsThrowsIfNotInitialized) { + WalletGreen wallet(dispatcher, currency, node); + ASSERT_ANY_THROW(wallet.getTransactions(0, 10)); +} + +TEST_F(WalletApi, getTransactionsThrowsCountZero) { + ASSERT_ANY_THROW(alice.getTransactions(0, 0)); +} + +TEST_F(WalletApi, getTransactionsReturnsEmptyArrayIfBlockIndexTooBig) { + auto transactions = alice.getTransactions(1, 1); + ASSERT_TRUE(transactions.empty()); +} + +TEST_F(WalletApi, transferDoesntAppearTwiceAfterIncludingToBlockchain) { + //we generate single output transaction to make sure we'll have change transfer in transaction + generator.getSingleOutputTransaction(parseAddress(aliceAddress), 2 * SENT + FEE); + unlockMoney(); + + CryptoNote::WalletGreen bob(dispatcher, currency, node, 1); + bob.initialize("p"); + + node.setNextTransactionToPool(); + sendMoney(bob.createAddress(), SENT, FEE); + + node.sendPoolChanged(); + + waitForTransactionCount(bob, 1); + waitForWalletEvent(bob, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + ASSERT_EQ(3, bob.getTransactionTransferCount(0)); + + node.includeTransactionsFromPoolToBlock(); + generator.generateEmptyBlocks(1); + node.updateObservers(); + waitForWalletEvent(bob, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + ASSERT_EQ(3, bob.getTransactionTransferCount(0)); +} + +TEST_F(WalletApi, incomingTransactionToTwoAddressesContainsTransfersForEachAddress) { + //we don't want to produce change + generator.getSingleOutputTransaction(parseAddress(aliceAddress), 2 * SENT + 2 * FEE); + unlockMoney(); + + CryptoNote::WalletGreen bob(dispatcher, currency, node, 1); + bob.initialize("p"); + + CryptoNote::TransactionParameters params; + params.destinations = {{bob.createAddress(), SENT}, {bob.createAddress(), SENT + FEE}}; + params.fee = FEE; + + waitForWalletEvent(bob, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + alice.transfer(params); + node.updateObservers(); + + waitForTransactionCount(bob, 1); + waitForWalletEvent(bob, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + //2 outcoming transfers to bob's addresses and one incoming for alice + ASSERT_EQ(3, bob.getTransactionTransferCount(0)); + + std::vector receivedTransfers = getTransfersFromTransaction(bob, 0, true); + std::sort(receivedTransfers.begin(), receivedTransfers.end()); + + //we expect to have exactly 2 positive transfers - one for each bob's address + ASSERT_EQ(2, receivedTransfers.size()); + + ASSERT_EQ(bob.getAddress(0), receivedTransfers[0].address); + ASSERT_EQ(SENT, receivedTransfers[0].amount); + + ASSERT_EQ(bob.getAddress(1), receivedTransfers[1].address); + ASSERT_EQ(SENT + FEE, receivedTransfers[1].amount); +} + +TEST_F(WalletApi, getTransactionsReturnsEmptyArrayIfBlockHashDoesntExist) { + Crypto::Hash hash; + std::generate(std::begin(hash.data), std::end(hash.data), std::rand); + + auto transactions = alice.getTransactions(hash, 1); + ASSERT_TRUE(transactions.empty()); +} + +TEST_F(WalletApi, getTransactionsReturnsEmptyArrayWhenNoTransactions) { + auto transactions = alice.getTransactions(0, 1); + + ASSERT_FALSE(transactions.empty()); + ASSERT_TRUE(transactions[0].transactions.empty()); +} + +bool compareTransactionsWithTransfers(CryptoNote::WalletTransactionWithTransfers& leftTransaction, CryptoNote::WalletTransactionWithTransfers& rightTransaction) { + std::sort(leftTransaction.transfers.begin(), leftTransaction.transfers.end()); + std::sort(rightTransaction.transfers.begin(), rightTransaction.transfers.end()); + + if (leftTransaction.transaction != rightTransaction.transaction) { + return false; + } + + return leftTransaction.transfers == rightTransaction.transfers; +} + +CryptoNote::WalletTransactionWithTransfers makeTransactionWithTransfers(CryptoNote::WalletGreen& wallet, size_t transactionId) { + CryptoNote::WalletTransactionWithTransfers transactionWithTransfers; + transactionWithTransfers.transaction = wallet.getTransaction(transactionId); + + for (size_t i = 0; i < wallet.getTransactionTransferCount(transactionId); ++i ) { + transactionWithTransfers.transfers.push_back(wallet.getTransactionTransfer(transactionId, i)); + } + + return transactionWithTransfers; +} + +bool transactionWithTransfersFound(CryptoNote::WalletGreen& wallet, const std::vector& transactions, size_t transactionId) { + CryptoNote::WalletTransactionWithTransfers walletTransaction = makeTransactionWithTransfers(wallet, transactionId); + + for (auto& block: transactions) { + for (auto& transaction: block.transactions) { + auto transactionCopy = transaction; + if (compareTransactionsWithTransfers(walletTransaction, transactionCopy)) { + return true; + } + } + } + + return false; +} + +size_t getTransactionsCount(const std::vector& transactions) { + size_t count = 0; + + for (auto& block: transactions) { + count += block.transactions.size(); + } + + return count; +} + +TEST_F(WalletApi, getTransactionsDoesntReturnUnconfirmedTransactions) { + generateAndUnlockMoney(); + + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + size_t transactionId = sendMoney(RANDOM_ADDRESS, SENT, FEE); + auto transactions = alice.getTransactions(0, generator.getBlockchain().size()); + + ASSERT_FALSE(transactionWithTransfersFound(alice, transactions, transactionId)); +} + +TEST_F(WalletApi, getTransactionsReturnsCorrectTransactionsFromOneBlock) { + generateAndUnlockMoney(); + const uint32_t MIXIN_1 = 1; + const uint32_t MIXIN_2 = 0; + + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + node.setNextTransactionToPool(); + size_t transactionId1 = sendMoney(RANDOM_ADDRESS, SENT, FEE, MIXIN_1); + + node.setNextTransactionToPool(); + size_t transactionId2 = sendMoney(RANDOM_ADDRESS, SENT + FEE, FEE, MIXIN_2); + + node.includeTransactionsFromPoolToBlock(); + node.updateObservers(); + + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + auto transactions = alice.getTransactions(generator.getBlockchain().size() - 1, 1); + + size_t transactionsCount = getTransactionsCount(transactions); + ASSERT_EQ(2, transactionsCount); + + ASSERT_TRUE(transactionWithTransfersFound(alice, transactions, transactionId1)); + ASSERT_TRUE(transactionWithTransfersFound(alice, transactions, transactionId2)); +} + +TEST_F(WalletApi, getTransactionsReturnsBlockWithCorrectHash) { + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + generator.generateEmptyBlocks(1); + node.updateObservers(); + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + Crypto::Hash lastBlockHash = get_block_hash(generator.getBlockchain().back()); + auto transactions = alice.getTransactions(lastBlockHash, 1); + + ASSERT_EQ(1, transactions.size()); + ASSERT_EQ(lastBlockHash, transactions[0].blockHash); +} + +TEST_F(WalletApi, getTransactionsReturnsCorrectTransactionByBlockHash) { + generateAndUnlockMoney(); + + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + size_t transactionId = sendMoney(RANDOM_ADDRESS, SENT, FEE); + + node.updateObservers(); + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + Crypto::Hash lastBlockHash = get_block_hash(generator.getBlockchain().back()); + auto transactions = alice.getTransactions(lastBlockHash, 1); + + ASSERT_TRUE(transactionWithTransfersFound(alice, transactions, transactionId)); +} + +TEST_F(WalletApi, getTransactionsDoesntReturnUnconfirmedIncomingTransactions) { + CryptoNote::WalletGreen bob(dispatcher, currency, node, TRANSACTION_SOFTLOCK_TIME); + bob.initialize("pass2"); + + generateAndUnlockMoney(); + + node.setNextTransactionToPool(); + sendMoney(bob.createAddress(), SENT, FEE); + node.updateObservers(); + + waitForTransactionCount(bob, 1); + + auto transactions = bob.getTransactions(0, generator.getBlockchain().size()); + ASSERT_EQ(0, getTransactionsCount(transactions)); + + bob.shutdown(); +} + +TEST_F(WalletApi, getTransactionsReturnsConfirmedIncomingTransactions) { + CryptoNote::WalletGreen bob(dispatcher, currency, node, TRANSACTION_SOFTLOCK_TIME); + bob.initialize("pass2"); + + generateAndUnlockMoney(); + + sendMoney(bob.createAddress(), SENT, FEE); + node.updateObservers(); + + waitForTransactionCount(bob, 1); + waitForWalletEvent(bob, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + auto transactions = bob.getTransactions(generator.getBlockchain().size() - 1, 1); + ASSERT_EQ(1, getTransactionsCount(transactions)); + ASSERT_TRUE(transactionWithTransfersFound(bob, transactions, 0)); + + bob.shutdown(); +} + +TEST_F(WalletApi, getTransactionsDoesntReturnFailedTransactions) { + generateAndUnlockMoney(); + + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + node.setNextTransactionError(); + try { + sendMoney(RANDOM_ADDRESS, SENT + FEE, FEE); + } catch (std::exception&) { + } + + node.updateObservers(); + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + auto transactions = alice.getTransactions(0, generator.getBlockchain().size()); + ASSERT_FALSE(transactionWithTransfersFound(alice, transactions, alice.getTransactionCount() - 1)); +} + +TEST_F(WalletApi, getTransactionsDoesntReturnDelayedTransactions) { + generateAndUnlockMoney(); + + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + size_t id = makeTransaction({}, RANDOM_ADDRESS, SENT, FEE); + + generator.generateEmptyBlocks(1); + node.updateObservers(); + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + auto transactions = alice.getTransactions(0, generator.getBlockchain().size()); + ASSERT_FALSE(transactionWithTransfersFound(alice, transactions, id)); +} + +TEST_F(WalletApi, getTransactionsReturnsDelayedTransactionsAfterSend) { + generateAndUnlockMoney(); + + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + size_t id = makeTransaction({}, RANDOM_ADDRESS, SENT, FEE); + alice.commitTransaction(id); + + node.updateObservers(); + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + auto transactions = alice.getTransactions(generator.getBlockchain().size() - 1, 1); + ASSERT_TRUE(transactionWithTransfersFound(alice, transactions, id)); +} + +TEST_F(WalletApi, getTransactionsDoesntReturnDeletedTransactions) { + generateAndUnlockMoney(); + + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + size_t detachHeight = generator.getBlockchain().size() - 1; + size_t id = sendMoney(RANDOM_ADDRESS, SENT + FEE, FEE); + + node.updateObservers(); + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + node.startAlternativeChain(detachHeight); + generator.generateEmptyBlocks(1); + node.updateObservers(); + + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + auto transactions = alice.getTransactions(generator.getBlockchain().size() - 1, 1); + ASSERT_FALSE(transactionWithTransfersFound(alice, transactions, id)); +} + +TEST_F(WalletApi, getTransactionsByBlockHashThrowsIfNotInitialized) { + CryptoNote::WalletGreen bob(dispatcher, currency, node, TRANSACTION_SOFTLOCK_TIME); + auto hash = get_block_hash(generator.getBlockchain().back()); + ASSERT_ANY_THROW(bob.getTransactions(hash, 1)); +} + +TEST_F(WalletApi, getTransactionsByBlockHashThrowsIfStopped) { + alice.stop(); + auto hash = get_block_hash(generator.getBlockchain().back()); + ASSERT_ANY_THROW(alice.getTransactions(hash, 1)); + alice.start(); +} + +TEST_F(WalletApi, getBlockHashesThrowsIfNotInitialized) { + CryptoNote::WalletGreen bob(dispatcher, currency, node, TRANSACTION_SOFTLOCK_TIME); + ASSERT_ANY_THROW(bob.getBlockHashes(0, 1)); +} + +TEST_F(WalletApi, getBlockHashesThrowsIfStopped) { + alice.stop(); + ASSERT_ANY_THROW(alice.getBlockHashes(0, 1)); + alice.start(); +} + +TEST_F(WalletApi, getBlockHashesReturnsEmptyVectorIfBlockIndexGreaterThanBlockhainSize) { + auto hashes = alice.getBlockHashes(1, 1); + ASSERT_TRUE(hashes.empty()); +} + +TEST_F(WalletApi, getBlockHashesReturnsNewBlocks) { + generator.generateEmptyBlocks(1); + + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + auto hash = get_block_hash(generator.getBlockchain().back()); + auto hashes = alice.getBlockHashes(0, generator.getBlockchain().size()); + + ASSERT_EQ(generator.getBlockchain().size(), hashes.size()); + ASSERT_EQ(hash, hashes.back()); +} + +TEST_F(WalletApi, getBlockHashesReturnsCorrectBlockHashesAfterDetach) { + generator.generateEmptyBlocks(1); + + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + node.startAlternativeChain(1); + generator.generateEmptyBlocks(1); + node.updateObservers(); + + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + auto hash = get_block_hash(generator.getBlockchain()[1]); + auto hashes = alice.getBlockHashes(0, 2); + + ASSERT_EQ(2, hashes.size()); + ASSERT_EQ(hash, hashes.back()); +} + +TEST_F(WalletApi, getBlockHashesReturnsOnlyGenesisBlockHashForWalletWithoutAddresses) { + CryptoNote::WalletGreen bob(dispatcher, currency, node, TRANSACTION_SOFTLOCK_TIME); + bob.initialize("pass"); + + auto hashes = bob.getBlockHashes(0, 100); + auto hash = hashes[0]; + + ASSERT_EQ(1, hashes.size()); + ASSERT_EQ(currency.genesisBlockHash(), hash); + bob.shutdown(); +} + +TEST_F(WalletApi, getBlockHashesReturnsOnlyGenesisBlockHashAfterDeletingAddresses) { + generator.generateEmptyBlocks(1); + + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + alice.deleteAddress(alice.getAddress(0)); + + auto hashes = alice.getBlockHashes(0, 100); + auto hash = hashes[0]; + + ASSERT_EQ(1, hashes.size()); + ASSERT_EQ(currency.genesisBlockHash(), hash); +} + +TEST_F(WalletApi, getBlockHashesReturnsCorrectHashesAfterLoad) { + generator.generateEmptyBlocks(1); + + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + auto hashesBefore = alice.getBlockHashes(0, generator.getBlockchain().size()); + + std::stringstream data; + alice.save(data, false, true); + + CryptoNote::WalletGreen bob(dispatcher, currency, node, TRANSACTION_SOFTLOCK_TIME); + bob.load(data, "pass"); + + auto hashesAfter = bob.getBlockHashes(0, generator.getBlockchain().size()); + ASSERT_EQ(hashesBefore, hashesAfter); + bob.shutdown(); +} + +TEST_F(WalletApi, getBlockCountThrowIfNotInitialized) { + CryptoNote::WalletGreen bob(dispatcher, currency, node, TRANSACTION_SOFTLOCK_TIME); + ASSERT_ANY_THROW(bob.getBlockCount()); +} + +TEST_F(WalletApi, getBlockCountThrowIfNotStopped) { + alice.stop(); + ASSERT_ANY_THROW(alice.getBlockCount()); + alice.start(); +} + +TEST_F(WalletApi, getBlockCountForWalletWithoutAddressesReturnsOne) { + CryptoNote::WalletGreen bob(dispatcher, currency, node, TRANSACTION_SOFTLOCK_TIME); + bob.initialize("pass"); + ASSERT_EQ(1, bob.getBlockCount()); + bob.shutdown(); +} + +TEST_F(WalletApi, getBlockCountReturnsCorrectBlockCount) { + generator.generateEmptyBlocks(1); + node.updateObservers(); + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + ASSERT_EQ(generator.getBlockchain().size(), alice.getBlockCount()); +} + +TEST_F(WalletApi, getBlockCountReturnsPlusOneAfterBlockAdded) { + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + auto prevBlockCount = alice.getBlockCount(); + + generator.generateEmptyBlocks(1); + node.updateObservers(); + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + ASSERT_EQ(prevBlockCount + 1, alice.getBlockCount()); +} + +TEST_F(WalletApi, getBlockCountReturnsCorrectBlockCountAfterDetach) { + generator.generateEmptyBlocks(2); + node.updateObservers(); + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + auto prevBlockCount = alice.getBlockCount(); + + auto detachBlockIndex = generator.getBlockchain().size() - 2; + node.startAlternativeChain(detachBlockIndex); + generator.generateEmptyBlocks(1); + node.updateObservers(); + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + ASSERT_EQ(prevBlockCount - 1, alice.getBlockCount()); +} + +TEST_F(WalletApi, getBlockCountReturnsOneAfterAddressesRemoving) { + generator.generateEmptyBlocks(1); + node.updateObservers(); + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + alice.deleteAddress(alice.getAddress(0)); + ASSERT_EQ(1, alice.getBlockCount()); +} + +TEST_F(WalletApi, getBlockCountReturnsCorrectBlockCountAfterLoad) { + generator.generateEmptyBlocks(1); + node.updateObservers(); + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + auto aliceBlockCount = alice.getBlockCount(); + + std::stringstream data; + alice.save(data, false, true); + + CryptoNote::WalletGreen bob(dispatcher, currency, node, TRANSACTION_SOFTLOCK_TIME); + ASSERT_NO_THROW(bob.load(data, "pass")); + + ASSERT_EQ(aliceBlockCount, bob.getBlockCount()); + bob.shutdown(); +} + +TEST_F(WalletApi, getUnconfirmedTransactionsThrowsIfNotInitialized) { + CryptoNote::WalletGreen bob(dispatcher, currency, node, TRANSACTION_SOFTLOCK_TIME); + ASSERT_ANY_THROW(bob.getUnconfirmedTransactions()); +} + +TEST_F(WalletApi, getUnconfirmedTransactionsThrowsIfStopped) { + alice.stop(); + ASSERT_ANY_THROW(alice.getUnconfirmedTransactions()); + alice.start(); +} + +TEST_F(WalletApi, getUnconfirmedTransactionsReturnsOneTransaction) { + generateAndUnlockMoney(); + node.updateObservers(); + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + CryptoNote::TransactionParameters params; + params.destinations = {{RANDOM_ADDRESS, SENT}, {RANDOM_ADDRESS, SENT + FEE}}; + params.fee = FEE; + + node.setNextTransactionToPool(); + auto transaction = makeTransactionWithTransfers(alice, alice.transfer(params)); + + auto unconfirmed = alice.getUnconfirmedTransactions(); + ASSERT_EQ(1, unconfirmed.size()); + ASSERT_TRUE(compareTransactionsWithTransfers(transaction, unconfirmed[0])); +} + +TEST_F(WalletApi, getUnconfirmedTransactionsReturnsTwoTransactions) { + generateAndUnlockMoney(); + node.updateObservers(); + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + node.setNextTransactionToPool(); + auto transaction1 = makeTransactionWithTransfers(alice, sendMoney(RANDOM_ADDRESS, SENT, FEE)); + + node.setNextTransactionToPool(); + auto transaction2 = makeTransactionWithTransfers(alice, sendMoney(RANDOM_ADDRESS, SENT + FEE, FEE)); + + auto unconfirmed = alice.getUnconfirmedTransactions(); + ASSERT_EQ(2, unconfirmed.size()); + + auto found1 = std::find_if(unconfirmed.begin(), unconfirmed.end(), [&transaction1] (CryptoNote::WalletTransactionWithTransfers& tr) { + return compareTransactionsWithTransfers(transaction1, tr); + }); + + ASSERT_NE(unconfirmed.end(), found1); + + auto found2 = std::find_if(unconfirmed.begin(), unconfirmed.end(), [&transaction2] (CryptoNote::WalletTransactionWithTransfers& tr) { + return compareTransactionsWithTransfers(transaction2, tr); + }); + + ASSERT_NE(unconfirmed.end(), found2); +} + +TEST_F(WalletApi, getUnconfirmedTransactionsDoesntReturnFailedTransactions) { + generateAndUnlockMoney(); + node.updateObservers(); + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + node.setNextTransactionError(); + try { + sendMoney(RANDOM_ADDRESS, SENT, FEE); + } catch (std::exception&) { + } + + auto unconfirmed = alice.getUnconfirmedTransactions(); + ASSERT_TRUE(unconfirmed.empty()); +} + +TEST_F(WalletApi, getUnconfirmedTransactionsDoesntReturnConfirmedTransactions) { + generateAndUnlockMoney(); + node.updateObservers(); + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + sendMoney(RANDOM_ADDRESS, SENT, FEE); + node.updateObservers(); + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + auto unconfirmed = alice.getUnconfirmedTransactions(); + ASSERT_TRUE(unconfirmed.empty()); +} + +TEST_F(WalletApi, getDelayedTransactionIdsThrowsIfNotInitialized) { + CryptoNote::WalletGreen bob(dispatcher, currency, node, TRANSACTION_SOFTLOCK_TIME); + ASSERT_ANY_THROW(bob.getDelayedTransactionIds()); +} + +TEST_F(WalletApi, getDelayedTransactionIdsThrowsIfStopped) { + alice.stop(); + ASSERT_ANY_THROW(alice.getDelayedTransactionIds()); + alice.start(); +} + +TEST_F(WalletApi, getDelayedTransactionIdsThrowsIfInTrackingMode) { + CryptoNote::WalletGreen bob(dispatcher, currency, node, TRANSACTION_SOFTLOCK_TIME); + bob.initialize("p"); + + Crypto::PublicKey pub; + Crypto::SecretKey sec; + Crypto::generate_keys(pub, sec); + + bob.createAddress(pub); + ASSERT_ANY_THROW(bob.getDelayedTransactionIds()); +} + +TEST_F(WalletApi, getDelayedTransactionIdsReturnsDelayedTransaction) { + generateAndUnlockMoney(); + node.updateObservers(); + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + auto id = makeTransaction({}, RANDOM_ADDRESS, SENT, FEE); + + auto delayed = alice.getDelayedTransactionIds(); + + ASSERT_EQ(1, delayed.size()); + ASSERT_EQ(id, delayed[0]); +} + +TEST_F(WalletApi, getDelayedTransactionIdsDoesntReturnSentTransactions) { + generateAndUnlockMoney(); + node.updateObservers(); + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + auto id = makeTransaction({}, RANDOM_ADDRESS, SENT, FEE); + alice.commitTransaction(id); + + auto delayed = alice.getDelayedTransactionIds(); + ASSERT_TRUE(delayed.empty()); +} + +TEST_F(WalletApi, getDelayedTransactionIdsDoesntReturnFailedTransactions) { + generateAndUnlockMoney(); + node.updateObservers(); + waitForWalletEvent(alice, CryptoNote::WalletEventType::SYNC_COMPLETED, std::chrono::seconds(3)); + + node.setNextTransactionError(); + try { + sendMoney(RANDOM_ADDRESS, SENT, FEE); + } catch (std::exception&){ + } + + auto delayed = alice.getDelayedTransactionIds(); + ASSERT_TRUE(delayed.empty()); +} + +TEST_F(WalletApi, transferFailsIfWrongChangeAddress) { + CryptoNote::TransactionParameters params; + params.destinations = {{RANDOM_ADDRESS, SENT}}; + params.fee = FEE; + params.changeDestination = "Wrong address"; + + ASSERT_ANY_THROW(alice.transfer(params)); +} + +TEST_F(WalletApi, transferFailsIfChangeAddressDoesntExist) { + auto changeAddress = alice.createAddress(); + + CryptoNote::TransactionParameters params; + params.destinations = {{RANDOM_ADDRESS, SENT}}; + params.fee = FEE; + params.changeDestination = changeAddress; + alice.deleteAddress(changeAddress); + + ASSERT_ANY_THROW(alice.transfer(params)); +} + +TEST_F(WalletApi, transferFailsIfChangeAddressIsNotMine) { + CryptoNote::TransactionParameters params; + params.destinations = {{RANDOM_ADDRESS, SENT}}; + params.fee = FEE; + params.changeDestination = RANDOM_ADDRESS; + + ASSERT_ANY_THROW(alice.transfer(params)); +} + +TEST_F(WalletApi, transferFailsIfWalletHasManyAddressesSourceAddressesNotSetAndNoChangeDestination) { + alice.createAddress(); + CryptoNote::TransactionParameters params; + params.destinations = {{RANDOM_ADDRESS, SENT}}; + params.fee = FEE; + + ASSERT_ANY_THROW(alice.transfer(params)); +} + +TEST_F(WalletApi, transferSendsChangeToSingleSpecifiedSourceAddress) { + const uint64_t MONEY = SENT + FEE + 1; + + alice.createAddress(); + + generator.getSingleOutputTransaction(parseAddress(alice.getAddress(1)), MONEY); + unlockMoney(); + + CryptoNote::TransactionParameters params; + params.destinations = {{RANDOM_ADDRESS, SENT}}; + params.fee = FEE; + params.sourceAddresses = {alice.getAddress(1)}; + + alice.transfer(params); + waitForActualBalance(alice, 0); + + EXPECT_EQ(MONEY - SENT - FEE, alice.getPendingBalance()); + EXPECT_EQ(MONEY - SENT - FEE, alice.getPendingBalance(alice.getAddress(1))); +} + +TEST_F(WalletApi, transferFailsIfNoChangeDestinationAndMultipleSourceAddressesSet) { + generateAndUnlockMoney(); + alice.createAddress(); + + CryptoNote::TransactionParameters params; + params.destinations = {{RANDOM_ADDRESS, SENT}}; + params.fee = FEE; + params.sourceAddresses = {aliceAddress, alice.getAddress(1)}; + + ASSERT_ANY_THROW(alice.transfer(params)); +} + +TEST_F(WalletApi, transferSendsChangeToAddress) { + const uint64_t MONEY = SENT * 3; + + generator.getSingleOutputTransaction(parseAddress(aliceAddress), MONEY); + unlockMoney(); + + CryptoNote::TransactionParameters params; + params.destinations = {{RANDOM_ADDRESS, SENT}}; + params.fee = FEE; + params.changeDestination = alice.createAddress(); + + alice.transfer(params); + node.updateObservers(); + + waitActualBalanceUpdated(MONEY); + + EXPECT_EQ(MONEY - SENT - FEE, alice.getPendingBalance()); + EXPECT_EQ(0, alice.getActualBalance()); + EXPECT_EQ(0, alice.getActualBalance(aliceAddress)); + EXPECT_EQ(0, alice.getPendingBalance(aliceAddress)); + EXPECT_EQ(0, alice.getActualBalance(alice.getAddress(1))); + EXPECT_EQ(MONEY - SENT - FEE, alice.getPendingBalance(alice.getAddress(1))); +} + +TEST_F(WalletApi, checkBaseTransaction) { + CryptoNote::AccountKeys keys{ parseAddress(alice.getAddress(0)), alice.getAddressSpendKey(0).secretKey, alice.getViewKey().secretKey }; + CryptoNote::AccountBase acc; + acc.setAccountKeys(keys); + acc.set_createtime(0); + generator.generateFromBaseTx(acc); + + node.updateObservers(); + waitForTransactionCount(alice, 1); + + ASSERT_EQ(1, alice.getTransactionCount()); + WalletTransaction tx = alice.getTransaction(0); + EXPECT_TRUE(tx.isBase); + EXPECT_EQ(0, tx.fee); + EXPECT_EQ(CryptoNote::WalletTransactionState::SUCCEEDED, tx.state); + + ASSERT_EQ(1, alice.getTransactionTransferCount(0)); + WalletTransfer transfer = alice.getTransactionTransfer(0, 0); + EXPECT_LT(0, transfer.amount); + EXPECT_EQ(tx.totalAmount, transfer.amount); +} diff --git a/tests/UnitTests/TestWalletLegacy.cpp b/tests/UnitTests/TestWalletLegacy.cpp index 1f0062b2..849fb6dd 100644 --- a/tests/UnitTests/TestWalletLegacy.cpp +++ b/tests/UnitTests/TestWalletLegacy.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -145,7 +145,7 @@ public: WalletLegacyApi() : m_currency(CryptoNote::CurrencyBuilder(m_logger).currency()), generator(m_currency) { } - void SetUp(); + void SetUp() override; protected: void prepareAliceWallet(); @@ -1379,7 +1379,7 @@ TEST_F(WalletLegacyApi, outcommingExternalTransactionTotalAmount) { wallet.initAndLoad(walletData, "pass"); WaitWalletSync(&walletObserver); - ASSERT_EQ(-(sent + fee), externalTransactionObserver.totalAmount); + ASSERT_EQ(-static_cast(sent + fee), externalTransactionObserver.totalAmount); wallet.shutdown(); } diff --git a/tests/UnitTests/TestWalletService.cpp b/tests/UnitTests/TestWalletService.cpp new file mode 100644 index 00000000..f9f150bd --- /dev/null +++ b/tests/UnitTests/TestWalletService.cpp @@ -0,0 +1,988 @@ +// Copyright (c) 2011-2016 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "gtest/gtest.h" + +#include +#include +#include + +#include + +#include "CryptoNoteCore/Currency.h" +#include "Logging/LoggerGroup.h" +#include "Logging/ConsoleLogger.h" +#include +#include "PaymentGate/WalletService.h" +#include "PaymentGate/WalletServiceErrorCategory.h" +#include "INodeStubs.h" +#include "Wallet/WalletErrors.h" + +using namespace CryptoNote; +using namespace PaymentService; + +namespace CryptoNote { + +bool operator== (const WalletOrder& lhs, const WalletOrder& rhs) { + return std::make_tuple(lhs.address, lhs.amount) == std::make_tuple(rhs.address, rhs.amount); +} + +bool operator== (const DonationSettings& lhs, const DonationSettings& rhs) { + return std::make_tuple(lhs.address, lhs.threshold) == std::make_tuple(rhs.address, rhs.threshold); +} + +} //namespace CryptoNote + +struct IWalletBaseStub : public CryptoNote::IWallet { + IWalletBaseStub(System::Dispatcher& dispatcher) : m_eventOccurred(dispatcher) {} + virtual ~IWalletBaseStub() {} + + virtual void initialize(const std::string& password) override { } + virtual void initializeWithViewKey(const Crypto::SecretKey& viewSecretKey, const std::string& password) override { } + virtual void load(std::istream& source, const std::string& password) override { } + virtual void shutdown() override { } + + virtual void changePassword(const std::string& oldPassword, const std::string& newPassword) override { } + virtual void save(std::ostream& destination, bool saveDetails = true, bool saveCache = true) override { } + + virtual size_t getAddressCount() const override { return 0; } + virtual std::string getAddress(size_t index) const override { return ""; } + virtual KeyPair getAddressSpendKey(size_t index) const override { return KeyPair(); } + virtual KeyPair getAddressSpendKey(const std::string& address) const override { return KeyPair(); } + virtual KeyPair getViewKey() const override { return KeyPair(); } + virtual std::string createAddress() override { return ""; } + virtual std::string createAddress(const Crypto::SecretKey& spendSecretKey) override { return ""; } + virtual std::string createAddress(const Crypto::PublicKey& spendPublicKey) override { return ""; } + virtual void deleteAddress(const std::string& address) override { } + + virtual uint64_t getActualBalance() const override { return 0; } + virtual uint64_t getActualBalance(const std::string& address) const override { return 0; } + virtual uint64_t getPendingBalance() const override { return 0; } + virtual uint64_t getPendingBalance(const std::string& address) const override { return 0; } + + virtual size_t getTransactionCount() const override { return 0; } + virtual WalletTransaction getTransaction(size_t transactionIndex) const override { return WalletTransaction(); } + virtual size_t getTransactionTransferCount(size_t transactionIndex) const override { return 0; } + virtual WalletTransfer getTransactionTransfer(size_t transactionIndex, size_t transferIndex) const override { return WalletTransfer(); } + + virtual WalletTransactionWithTransfers getTransaction(const Crypto::Hash& transactionHash) const override { return WalletTransactionWithTransfers(); } + virtual std::vector getTransactions(const Crypto::Hash& blockHash, size_t count) const override { return {}; } + virtual std::vector getTransactions(uint32_t blockIndex, size_t count) const override { return {}; } + virtual std::vector getBlockHashes(uint32_t blockIndex, size_t count) const override { return {}; } + virtual uint32_t getBlockCount() const override { return 0; } + virtual std::vector getUnconfirmedTransactions() const override { return {}; } + virtual std::vector getDelayedTransactionIds() const override { return {}; } + + virtual size_t transfer(const TransactionParameters& sendingTransaction) override { return 0; } + + virtual size_t makeTransaction(const TransactionParameters& sendingTransaction) override { return 0; } + virtual void commitTransaction(size_t transactionId) override { } + virtual void rollbackUncommitedTransaction(size_t transactionId) override { } + + virtual void start() override { m_stopped = false; } + virtual void stop() override { m_stopped = true; m_eventOccurred.set(); } + + //blocks until an event occurred + virtual WalletEvent getEvent() override { + throwIfStopped(); + + while(m_events.empty()) { + m_eventOccurred.wait(); + m_eventOccurred.clear(); + throwIfStopped(); + } + + WalletEvent event = std::move(m_events.front()); + m_events.pop(); + + return event; + } + + void pushEvent(const WalletEvent& event) { + m_events.push(event); + m_eventOccurred.set(); + } + +protected: + void throwIfStopped() { + if (m_stopped) { + throw std::system_error(make_error_code(std::errc::operation_canceled)); + } + } + + bool m_stopped = false; + System::Event m_eventOccurred; + std::queue m_events; +}; + +class WalletServiceTest: public ::testing::Test { +public: + WalletServiceTest() : + currency(CryptoNote::CurrencyBuilder(logger).currency()), + generator(currency), + nodeStub(generator), + walletBase(dispatcher) + {} + + virtual void SetUp() override; +protected: + Logging::ConsoleLogger logger; + Currency currency; + TestBlockchainGenerator generator; + INodeTrivialRefreshStub nodeStub; + WalletConfiguration walletConfig; + System::Dispatcher dispatcher; + IWalletBaseStub walletBase; + + std::unique_ptr createWalletService(CryptoNote::IWallet& wallet); + std::unique_ptr createWalletService(); + Crypto::Hash generateRandomHash(); +}; + +void WalletServiceTest::SetUp() { + logger.setMaxLevel(Logging::DEBUGGING); + + walletConfig.walletFile = "test"; + walletConfig.walletPassword = "test"; +} + +std::unique_ptr WalletServiceTest::createWalletService(CryptoNote::IWallet& wallet) { + return std::unique_ptr (new WalletService(currency, dispatcher, nodeStub, wallet, walletConfig, logger)); +} + +std::unique_ptr WalletServiceTest::createWalletService() { + return createWalletService(walletBase); +} + +Crypto::Hash WalletServiceTest::generateRandomHash() { + Crypto::Hash hash; + std::generate(std::begin(hash.data), std::end(hash.data), std::rand); + return hash; +} + +class WalletServiceTest_createAddress : public WalletServiceTest { +}; + +struct WalletCreateAddressStub: public IWalletBaseStub { + WalletCreateAddressStub(System::Dispatcher& d) : IWalletBaseStub(d) {} + + virtual std::string createAddress() override { return address; } + virtual std::string createAddress(const Crypto::SecretKey& spendSecretKey) override { return address; } + virtual std::string createAddress(const Crypto::PublicKey& spendPublicKey) override { return address; } + + std::string address = "correctAddress"; +}; + +TEST_F(WalletServiceTest_createAddress, returnsCorrectAddress) { + WalletCreateAddressStub wallet(dispatcher); + + std::unique_ptr service = createWalletService(wallet); + std::string address; + std::error_code ec = service->createAddress(address); + + ASSERT_FALSE(ec); + ASSERT_EQ(wallet.address, address); +} + +TEST_F(WalletServiceTest_createAddress, invalidSecretKey) { + std::unique_ptr service = createWalletService(); + + std::string address; + std::error_code ec = service->createAddress("wrong key", address); + ASSERT_EQ(make_error_code(CryptoNote::error::WalletServiceErrorCode::WRONG_KEY_FORMAT), ec); +} + +TEST_F(WalletServiceTest_createAddress, invalidPublicKey) { + std::unique_ptr service = createWalletService(); + + std::string address; + std::error_code ec = service->createTrackingAddress("wrong key", address); + ASSERT_EQ(make_error_code(CryptoNote::error::WalletServiceErrorCode::WRONG_KEY_FORMAT), ec); +} + +TEST_F(WalletServiceTest_createAddress, correctSecretKey) { + Crypto::PublicKey pub; + Crypto::SecretKey sec; + Crypto::generate_keys(pub, sec); + + WalletCreateAddressStub wallet(dispatcher); + std::unique_ptr service = createWalletService(wallet); + + std::string address; + std::error_code ec = service->createAddress(Common::podToHex(sec), address); + + ASSERT_FALSE(ec); + ASSERT_EQ(wallet.address, address); +} + +TEST_F(WalletServiceTest_createAddress, correctPublicKey) { + Crypto::PublicKey pub; + Crypto::SecretKey sec; + Crypto::generate_keys(pub, sec); + + WalletCreateAddressStub wallet(dispatcher); + std::unique_ptr service = createWalletService(wallet); + + std::string address; + std::error_code ec = service->createTrackingAddress(Common::podToHex(pub), address); + + ASSERT_FALSE(ec); + ASSERT_EQ(wallet.address, address); +} + +class WalletServiceTest_getSpendKeys : public WalletServiceTest { +}; + +struct WalletgetSpendKeysStub: public IWalletBaseStub { + WalletgetSpendKeysStub(System::Dispatcher& d) : IWalletBaseStub(d) { + Crypto::generate_keys(keyPair.publicKey, keyPair.secretKey); + } + + virtual KeyPair getAddressSpendKey(const std::string& address) const override { + return keyPair; + } + + KeyPair keyPair; +}; + +TEST_F(WalletServiceTest_getSpendKeys, returnsKeysCorrectly) { + WalletgetSpendKeysStub wallet(dispatcher); + std::unique_ptr service = createWalletService(wallet); + + std::string publicSpendKey; + std::string secretSpendKey; + auto ec = service->getSpendkeys("address", publicSpendKey, secretSpendKey); + ASSERT_FALSE(ec); + ASSERT_EQ(Common::podToHex(wallet.keyPair.publicKey), publicSpendKey); + ASSERT_EQ(Common::podToHex(wallet.keyPair.secretKey), secretSpendKey); +} + +class WalletServiceTest_getBalance : public WalletServiceTest { +}; + +struct WalletGetBalanceStub: public IWalletBaseStub { + WalletGetBalanceStub(System::Dispatcher& d, bool byAddress) : IWalletBaseStub(d), byAddress(byAddress) { + } + + virtual uint64_t getActualBalance() const override { + if (byAddress) { + throw std::runtime_error("wrong overload"); + } + + return actualBalance; + } + + virtual uint64_t getPendingBalance() const override { + if (byAddress) { + throw std::runtime_error("wrong overload"); + } + + return pendingBalance; + } + + virtual uint64_t getActualBalance(const std::string& address) const override { + if (!byAddress) { + throw std::runtime_error("wrong overload"); + } + + return actualBalance; + } + + virtual uint64_t getPendingBalance(const std::string& address) const override { + if (!byAddress) { + throw std::runtime_error("wrong overload"); + } + + return pendingBalance; + } + + bool byAddress; + uint64_t actualBalance = 345466; + uint64_t pendingBalance = 12121; +}; + +TEST_F(WalletServiceTest_getBalance, returnsCorrectBalance) { + WalletGetBalanceStub wallet(dispatcher, false); + std::unique_ptr service = createWalletService(wallet); + + uint64_t actual; + uint64_t pending; + auto ec = service->getBalance(actual, pending); + + ASSERT_FALSE(ec); + ASSERT_EQ(wallet.actualBalance, actual); + ASSERT_EQ(wallet.pendingBalance, pending); +} + +TEST_F(WalletServiceTest_getBalance, returnsCorrectBalanceByAddress) { + WalletGetBalanceStub wallet(dispatcher, true); + std::unique_ptr service = createWalletService(wallet); + + uint64_t actual; + uint64_t pending; + auto ec = service->getBalance("address", actual, pending); + + ASSERT_FALSE(ec); + ASSERT_EQ(wallet.actualBalance, actual); + ASSERT_EQ(wallet.pendingBalance, pending); +} + +class WalletServiceTest_getBlockHashes : public WalletServiceTest { +protected: + std::vector convertBlockHashes(const std::vector& hashes) { + std::vector result; + result.reserve(hashes.size()); + + std::for_each(hashes.begin(), hashes.end(), [&result] (const std::string& str) { + Crypto::Hash hash; + Common::podFromHex(str, hash); + result.push_back(hash); + }); + + return result; + } +}; + +struct WalletGetBlockHashesStub: public IWalletBaseStub { + WalletGetBlockHashesStub(System::Dispatcher& d) : IWalletBaseStub(d) { + } + + virtual std::vector getBlockHashes(uint32_t blockIndex, size_t count) const override { + return blockHashes; + } + + std::vector blockHashes; +}; + +TEST_F(WalletServiceTest_getBlockHashes, returnsEmptyBlockHashes) { + WalletGetBlockHashesStub wallet(dispatcher); + auto service = createWalletService(wallet); + + std::vector blockHashes; + ASSERT_FALSE(service->getBlockHashes(0, 1, blockHashes)); + ASSERT_EQ(wallet.blockHashes, convertBlockHashes(blockHashes)); +} + +TEST_F(WalletServiceTest_getBlockHashes, returnsBlockHashes) { + WalletGetBlockHashesStub wallet(dispatcher); + std::generate_n(std::back_inserter(wallet.blockHashes), 10, [this] () { return generateRandomHash(); }); + auto service = createWalletService(wallet); + + std::vector blockHashes; + ASSERT_FALSE(service->getBlockHashes(0, 10, blockHashes)); + ASSERT_EQ(wallet.blockHashes, convertBlockHashes(blockHashes)); +} + +class WalletServiceTest_getViewKey : public WalletServiceTest { +}; + +struct WalletGetViewKeyStub: public IWalletBaseStub { + WalletGetViewKeyStub(System::Dispatcher& d) : IWalletBaseStub(d) { + Crypto::generate_keys(keyPair.publicKey, keyPair.secretKey); + } + + virtual KeyPair getViewKey() const override { + return keyPair; + } + + KeyPair keyPair; +}; + +TEST_F(WalletServiceTest_getViewKey, returnsCorrectValue) { + WalletGetViewKeyStub wallet(dispatcher); + auto service = createWalletService(wallet); + + std::string viewSecretKey; + ASSERT_FALSE(service->getViewKey(viewSecretKey)); + ASSERT_EQ(Common::podToHex(wallet.keyPair.secretKey), viewSecretKey); +} + +class WalletTransactionBuilder { +public: + WalletTransactionBuilder& hash(const Crypto::Hash& hash) { + transaction.hash = hash; + return *this; + } + + WalletTransactionBuilder& extra(const std::string& extra) { + transaction.extra = Common::asString(Common::fromHex(extra)); + return *this; + } + + WalletTransactionBuilder& state(WalletTransactionState state) { + transaction.state = state; + return *this; + } + + WalletTransaction build() const { + return transaction; + } + + WalletTransactionBuilder& timestamp(uint64_t t) { + transaction.timestamp = t; + return *this; + } + + WalletTransactionBuilder& blockHeight(uint32_t height) { + transaction.blockHeight = height; + return *this; + } + + WalletTransactionBuilder& totalAmount(int64_t amount) { + transaction.totalAmount = amount; + return *this; + } + + WalletTransactionBuilder& fee(uint64_t fee) { + transaction.fee = fee; + return *this; + } + + WalletTransactionBuilder& creationTime(uint64_t t) { + transaction.creationTime = t; + return *this; + } + + WalletTransactionBuilder& unlockTime(uint64_t unlock) { + transaction.unlockTime = unlock; + return *this; + } + + WalletTransactionBuilder& isBase(bool base) { + transaction.isBase = base; + return *this; + } + +private: + WalletTransaction transaction; +}; + +class WalletTransactionWithTransfersBuilder { +public: + WalletTransactionWithTransfersBuilder& transaction(const WalletTransaction& transaction) { + tx.transaction = transaction; + return *this; + } + + WalletTransactionWithTransfersBuilder& addTransfer(const std::string& address, int64_t amount) { + tx.transfers.push_back(WalletTransfer{WalletTransferType::USUAL, address, amount}); + return *this; + } + + WalletTransactionWithTransfers build() const { + return tx; + } + +private: + WalletTransactionWithTransfers tx; +}; + +class WalletServiceTest_getTransactions : public WalletServiceTest { + virtual void SetUp() override; +protected: + std::vector testTransactions; + const std::string RANDOM_ADDRESS1 = "288DiQfYSxDNQoWpR6cy94i2AWyGnxo1L1MF2ZiXg58h9P52o576CSDcJp7ZceSXSUQ7u8aTF1MigQXzAtqRZ3Uq58Sne8x"; + const std::string RANDOM_ADDRESS2 = "29PQ8VbzPi163kG59w5V8PR9A6watydfYAvwFcDS74KhDEyU9CGgqsDH719oeLbpAa4xtPsgfQ6Bv9RmKs1XZWudV6q6cmU"; + const std::string RANDOM_ADDRESS3 = "23E4CVgzJok9zXnrKzvHgbKvMXZnAgsB9FA1pkAppR6d42dWMEuJjsfcJp7ZceSXSUQ7u8aTF1MigQXzAtqRZ3Uq5AHHbzZ"; + const std::string TRANSACTION_EXTRA = "022100dededededededededededededededededededededededededededededededede"; + const std::string PAYMENT_ID = "dededededededededededededededededededededededededededededededede"; +}; + +void WalletServiceTest_getTransactions::SetUp() { + TransactionsInBlockInfo block; + block.blockHash = generateRandomHash(); + block.transactions.push_back( + WalletTransactionWithTransfersBuilder().addTransfer(RANDOM_ADDRESS1, 222).addTransfer(RANDOM_ADDRESS2, 33333).transaction( + WalletTransactionBuilder().hash(generateRandomHash()).extra(TRANSACTION_EXTRA).build() + ).build() + ); + + testTransactions.push_back(block); +} + +class WalletGetTransactionsStub : public IWalletBaseStub { +public: + WalletGetTransactionsStub(System::Dispatcher& d) : IWalletBaseStub(d) {} + virtual std::vector getTransactions(const Crypto::Hash& blockHash, size_t count) const override { + return transactions; + } + + virtual std::vector getTransactions(uint32_t blockIndex, size_t count) const override { + return transactions; + } + + std::vector transactions; +}; + +TEST_F(WalletServiceTest_getTransactions, addressesFilter_emptyReturnsTransaction) { + WalletGetTransactionsStub wallet(dispatcher); + wallet.transactions = testTransactions; + + auto service = createWalletService(wallet); + + std::vector transactions; + auto ec = service->getTransactions({}, 0, 1, "", transactions); + + ASSERT_FALSE(ec); + + ASSERT_EQ(1, transactions.size()); + ASSERT_EQ(Common::podToHex(testTransactions[0].transactions[0].transaction.hash), transactions[0].transactions[0].transactionHash); +} + +TEST_F(WalletServiceTest_getTransactions, addressesFilter_existentReturnsTransaction) { + WalletGetTransactionsStub wallet(dispatcher); + wallet.transactions = testTransactions; + + auto service = createWalletService(wallet); + + std::vector transactions; + auto ec = service->getTransactions({RANDOM_ADDRESS1}, 0, 1, "", transactions); + + ASSERT_FALSE(ec); + + ASSERT_EQ(1, transactions.size()); + ASSERT_EQ(Common::podToHex(testTransactions[0].transactions[0].transaction.hash), transactions[0].transactions[0].transactionHash); +} + +TEST_F(WalletServiceTest_getTransactions, addressesFilter_nonExistentReturnsNoTransactions) { + WalletGetTransactionsStub wallet(dispatcher); + wallet.transactions = testTransactions; + + auto service = createWalletService(wallet); + + std::vector transactions; + auto ec = service->getTransactions({RANDOM_ADDRESS3}, 0, 1, "", transactions); + + ASSERT_FALSE(ec); + + ASSERT_EQ(1, transactions.size()); + ASSERT_TRUE(transactions[0].transactions.empty()); +} + +TEST_F(WalletServiceTest_getTransactions, addressesFilter_existentAndNonExistentReturnsTransaction) { + WalletGetTransactionsStub wallet(dispatcher); + wallet.transactions = testTransactions; + + auto service = createWalletService(wallet); + + std::vector transactions; + auto ec = service->getTransactions({RANDOM_ADDRESS1, RANDOM_ADDRESS3}, 0, 1, "", transactions); + + ASSERT_FALSE(ec); + + ASSERT_EQ(1, transactions.size()); + ASSERT_EQ(Common::podToHex(testTransactions[0].transactions[0].transaction.hash), transactions[0].transactions[0].transactionHash); +} + +TEST_F(WalletServiceTest_getTransactions, paymentIdFilter_existentReturnsTransaction) { + WalletGetTransactionsStub wallet(dispatcher); + wallet.transactions = testTransactions; + + auto service = createWalletService(wallet); + + std::vector transactions; + auto ec = service->getTransactions({}, 0, 1, PAYMENT_ID, transactions); + + ASSERT_FALSE(ec); + + ASSERT_EQ(1, transactions.size()); + ASSERT_EQ(Common::podToHex(testTransactions[0].transactions[0].transaction.hash), transactions[0].transactions[0].transactionHash); + ASSERT_EQ(PAYMENT_ID, transactions[0].transactions[0].paymentId); +} + +TEST_F(WalletServiceTest_getTransactions, paymentIdFilter_nonExistentReturnsNoTransaction) { + WalletGetTransactionsStub wallet(dispatcher); + wallet.transactions = testTransactions; + + auto service = createWalletService(wallet); + + std::vector transactions; + auto ec = service->getTransactions({}, 0, 1, "dfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdf", transactions); + + ASSERT_FALSE(ec); + + ASSERT_EQ(1, transactions.size()); + ASSERT_TRUE(transactions[0].transactions.empty()); +} + +TEST_F(WalletServiceTest_getTransactions, invalidAddress) { + WalletGetTransactionsStub wallet(dispatcher); + wallet.transactions = testTransactions; + + auto service = createWalletService(wallet); + + std::vector transactions; + auto ec = service->getTransactions({"invalid address"}, 0, 1, "", transactions); + ASSERT_EQ(make_error_code(CryptoNote::error::BAD_ADDRESS), ec); +} + +TEST_F(WalletServiceTest_getTransactions, invalidPaymentId) { + WalletGetTransactionsStub wallet(dispatcher); + wallet.transactions = testTransactions; + + auto service = createWalletService(wallet); + + std::vector transactions; + auto ec = service->getTransactions({}, 0, 1, "invalid payment id", transactions); + ASSERT_EQ(make_error_code(CryptoNote::error::WalletServiceErrorCode::WRONG_PAYMENT_ID_FORMAT), ec); +} + +TEST_F(WalletServiceTest_getTransactions, blockNotFound) { + WalletGetTransactionsStub wallet(dispatcher); + auto service = createWalletService(wallet); + std::vector transactions; + + auto ec = service->getTransactions({}, 0, 1, "", transactions); + ASSERT_EQ(make_error_code(CryptoNote::error::WalletServiceErrorCode::OBJECT_NOT_FOUND), ec); +} + +class WalletServiceTest_getTransaction : public WalletServiceTest_getTransactions { +}; + +struct WalletGetTransactionStub : public IWalletBaseStub { + WalletGetTransactionStub (System::Dispatcher& dispatcher) : IWalletBaseStub(dispatcher) { + } + + virtual WalletTransactionWithTransfers getTransaction(const Crypto::Hash& transactionHash) const override { + return transaction; + } + + WalletTransactionWithTransfers transaction; +}; + +TEST_F(WalletServiceTest_getTransaction, wrongHash) { + auto service = createWalletService(); + + TransactionRpcInfo transaction; + auto ec = service->getTransaction("wrong hash", transaction); + ASSERT_EQ(make_error_code(CryptoNote::error::WalletServiceErrorCode::WRONG_HASH_FORMAT), ec); +} + +TEST_F(WalletServiceTest_getTransaction, returnsCorrectFields) { + WalletGetTransactionStub wallet(dispatcher); + wallet.transaction = WalletTransactionWithTransfersBuilder().transaction( + WalletTransactionBuilder() + .state(WalletTransactionState::FAILED) + .hash(generateRandomHash()) + .creationTime(789123) + .extra(TRANSACTION_EXTRA) + .fee(293945) + .isBase(false) + .timestamp(929293847) + .totalAmount(-200000) + .unlockTime(23456) + .build() + ).addTransfer("address1", 231).addTransfer("address2", 883).build(); + + auto service = createWalletService(wallet); + + TransactionRpcInfo transaction; + auto ec = service->getTransaction(Common::podToHex(Crypto::Hash()), transaction); + + ASSERT_FALSE(ec); + ASSERT_EQ(static_cast(wallet.transaction.transaction.state), transaction.state); + ASSERT_EQ(wallet.transaction.transaction.blockHeight, transaction.blockIndex); + ASSERT_EQ(Common::toHex(Common::asBinaryArray(wallet.transaction.transaction.extra)), transaction.extra); + ASSERT_EQ(PAYMENT_ID, transaction.paymentId); + ASSERT_EQ(wallet.transaction.transaction.fee, transaction.fee); + ASSERT_EQ(wallet.transaction.transaction.isBase, transaction.isBase); + ASSERT_EQ(wallet.transaction.transaction.timestamp, transaction.timestamp); + ASSERT_EQ(Common::podToHex(wallet.transaction.transaction.hash), transaction.transactionHash); + ASSERT_EQ(wallet.transaction.transaction.unlockTime, transaction.unlockTime); + + ASSERT_EQ(wallet.transaction.transfers.size(), transaction.transfers.size()); + + ASSERT_EQ(wallet.transaction.transfers[0].address, transaction.transfers[0].address); + ASSERT_EQ(wallet.transaction.transfers[0].amount, transaction.transfers[0].amount); + + ASSERT_EQ(wallet.transaction.transfers[1].address, transaction.transfers[1].address); + ASSERT_EQ(wallet.transaction.transfers[1].amount, transaction.transfers[1].amount); + +} + +struct WalletGetTransactionThrowStub : public IWalletBaseStub { + WalletGetTransactionThrowStub (System::Dispatcher& dispatcher) : IWalletBaseStub(dispatcher) { + } + + virtual WalletTransactionWithTransfers getTransaction(const Crypto::Hash& transactionHash) const override { + throw std::system_error(make_error_code(error::OBJECT_NOT_FOUND)); + } +}; + +TEST_F(WalletServiceTest_getTransaction, transactionNotFound) { + WalletGetTransactionThrowStub wallet(dispatcher); + auto service = createWalletService(wallet); + + TransactionRpcInfo transaction; + auto ec = service->getTransaction(Common::podToHex(Crypto::Hash()), transaction); + + ASSERT_EQ(make_error_code(error::OBJECT_NOT_FOUND), ec); +} + +class WalletServiceTest_sendTransaction : public WalletServiceTest_getTransactions { + virtual void SetUp() override; +protected: + SendTransaction::Request request; +}; + +void WalletServiceTest_sendTransaction::SetUp() { + request.sourceAddresses.insert(request.sourceAddresses.end(), {RANDOM_ADDRESS1, RANDOM_ADDRESS2}); + request.transfers.push_back(WalletRpcOrder {RANDOM_ADDRESS3, 11111}); + request.fee = 2021; + request.anonymity = 4; + request.unlockTime = 848309; +} + +struct WalletTransferStub : public IWalletBaseStub { + WalletTransferStub(System::Dispatcher& dispatcher, const Crypto::Hash& hash) : IWalletBaseStub(dispatcher), hash(hash) { + } + + virtual size_t transfer(const TransactionParameters& sendingTransaction) override { + params = sendingTransaction; + return 0; + } + + virtual WalletTransaction getTransaction(size_t transactionIndex) const override { + return WalletTransactionBuilder().hash(hash).build(); + } + + Crypto::Hash hash; + TransactionParameters params; +}; + +bool isEquivalent(const SendTransaction::Request& request, const TransactionParameters& params) { + std::string extra; + if (!request.paymentId.empty()) { + extra = "022100" + request.paymentId; + } else { + extra = request.extra; + } + + std::vector orders; + std::for_each(request.transfers.begin(), request.transfers.end(), [&orders] (const WalletRpcOrder& order) { + orders.push_back( WalletOrder{order.address, order.amount}); + }); + + return std::make_tuple(request.sourceAddresses, orders, request.fee, request.anonymity, extra, request.unlockTime) + == + std::make_tuple(params.sourceAddresses, params.destinations, params.fee, params.mixIn, Common::toHex(Common::asBinaryArray(params.extra)), params.unlockTimestamp); +} + +TEST_F(WalletServiceTest_sendTransaction, passesCorrectParameters) { + WalletTransferStub wallet(dispatcher, generateRandomHash()); + auto service = createWalletService(wallet); + + std::string hash; + auto ec = service->sendTransaction(request, hash); + + ASSERT_FALSE(ec); + ASSERT_EQ(Common::podToHex(wallet.hash), hash); + ASSERT_TRUE(isEquivalent(request, wallet.params)); +} + +TEST_F(WalletServiceTest_sendTransaction, incorrectSourceAddress) { + auto service = createWalletService(); + request.sourceAddresses.push_back("wrong address"); + + std::string hash; + auto ec = service->sendTransaction(request, hash); + ASSERT_EQ(make_error_code(CryptoNote::error::BAD_ADDRESS), ec); +} + +TEST_F(WalletServiceTest_sendTransaction, incorrectTransferAddress) { + auto service = createWalletService(); + request.transfers.push_back(WalletRpcOrder{"wrong address", 12131}); + + std::string hash; + auto ec = service->sendTransaction(request, hash); + ASSERT_EQ(make_error_code(CryptoNote::error::BAD_ADDRESS), ec); +} + +class WalletServiceTest_createDelayedTransaction : public WalletServiceTest_getTransactions { + virtual void SetUp() override; +protected: + CreateDelayedTransaction::Request request; +}; + +void WalletServiceTest_createDelayedTransaction::SetUp() { + request.addresses.insert(request.addresses.end(), {RANDOM_ADDRESS1, RANDOM_ADDRESS2}); + request.transfers.push_back(WalletRpcOrder {RANDOM_ADDRESS3, 11111}); + request.fee = 2021; + request.anonymity = 4; + request.unlockTime = 848309; +} + +struct WalletMakeTransactionStub : public IWalletBaseStub { + WalletMakeTransactionStub(System::Dispatcher& dispatcher, const Crypto::Hash& hash) : IWalletBaseStub(dispatcher), hash(hash) { + } + + virtual size_t makeTransaction(const TransactionParameters& sendingTransaction) override { + params = sendingTransaction; + return 0; + } + + virtual WalletTransaction getTransaction(size_t transactionIndex) const override { + return WalletTransactionBuilder().hash(hash).build(); + } + + Crypto::Hash hash; + TransactionParameters params; +}; + +bool isEquivalent(const CreateDelayedTransaction::Request& request, const TransactionParameters& params) { + std::string extra; + if (!request.paymentId.empty()) { + extra = "022100" + request.paymentId; + } else { + extra = request.extra; + } + + std::vector orders; + std::for_each(request.transfers.begin(), request.transfers.end(), [&orders] (const WalletRpcOrder& order) { + orders.push_back( WalletOrder{order.address, order.amount}); + }); + + return std::make_tuple(request.addresses, orders, request.fee, request.anonymity, extra, request.unlockTime) + == + std::make_tuple(params.sourceAddresses, params.destinations, params.fee, params.mixIn, Common::toHex(Common::asBinaryArray(params.extra)), params.unlockTimestamp); +} + +TEST_F(WalletServiceTest_createDelayedTransaction, passesCorrectParameters) { + WalletMakeTransactionStub wallet(dispatcher, generateRandomHash()); + auto service = createWalletService(wallet); + + std::string hash; + auto ec = service->createDelayedTransaction(request, hash); + + ASSERT_FALSE(ec); + ASSERT_EQ(Common::podToHex(wallet.hash), hash); + ASSERT_TRUE(isEquivalent(request, wallet.params)); +} + +TEST_F(WalletServiceTest_createDelayedTransaction, incorrectSourceAddress) { + auto service = createWalletService(); + request.addresses.push_back("wrong address"); + + std::string hash; + auto ec = service->createDelayedTransaction(request, hash); + ASSERT_EQ(make_error_code(CryptoNote::error::BAD_ADDRESS), ec); +} + +TEST_F(WalletServiceTest_createDelayedTransaction, incorrectTransferAddress) { + auto service = createWalletService(); + request.transfers.push_back(WalletRpcOrder{"wrong address", 12131}); + + std::string hash; + auto ec = service->createDelayedTransaction(request, hash); + ASSERT_EQ(make_error_code(CryptoNote::error::BAD_ADDRESS), ec); +} + +class WalletServiceTest_getDelayedTransactionHashes: public WalletServiceTest { +}; + +struct WalletGetDelayedTransactionIdsStub : public IWalletBaseStub { + WalletGetDelayedTransactionIdsStub(System::Dispatcher& dispatcher, const Crypto::Hash& hash) : IWalletBaseStub(dispatcher), hash(hash) { + } + + virtual std::vector getDelayedTransactionIds() const override { + return {0}; + } + + virtual WalletTransaction getTransaction(size_t transactionIndex) const override { + return WalletTransactionBuilder().hash(hash).build(); + } + + const Crypto::Hash hash; +}; + +TEST_F(WalletServiceTest_getDelayedTransactionHashes, returnsCorrectResult) { + WalletGetDelayedTransactionIdsStub wallet(dispatcher, generateRandomHash()); + auto service = createWalletService(wallet); + + std::vector hashes; + auto ec = service->getDelayedTransactionHashes(hashes); + + ASSERT_FALSE(ec); + ASSERT_EQ(1, hashes.size()); + ASSERT_EQ(Common::podToHex(wallet.hash), hashes[0]); +} + +class WalletServiceTest_getUnconfirmedTransactionHashes: public WalletServiceTest_getTransactions { +public: + virtual void SetUp() override; +protected: + std::vector transactions; +}; + +void WalletServiceTest_getUnconfirmedTransactionHashes::SetUp() { + transactions = { WalletTransactionWithTransfersBuilder().transaction( + WalletTransactionBuilder().hash(generateRandomHash()).build() + ).addTransfer(RANDOM_ADDRESS1, 100).addTransfer(RANDOM_ADDRESS2, 333).build() + , + WalletTransactionWithTransfersBuilder().transaction( + WalletTransactionBuilder().hash(generateRandomHash()).build() + ).addTransfer(RANDOM_ADDRESS3, 123).addTransfer(RANDOM_ADDRESS2, 4252).build() + }; +} + +struct WalletGetUnconfirmedTransactionsStub : public IWalletBaseStub { + WalletGetUnconfirmedTransactionsStub(System::Dispatcher& dispatcher) : IWalletBaseStub(dispatcher) { + } + + virtual std::vector getUnconfirmedTransactions() const override { + return transactions; + } + + std::vector transactions; +}; + +TEST_F(WalletServiceTest_getUnconfirmedTransactionHashes, returnsAllHashesWithoutAddresses) { + WalletGetUnconfirmedTransactionsStub wallet(dispatcher); + wallet.transactions = transactions; + auto service = createWalletService(wallet); + + std::vector hashes; + auto ec = service->getUnconfirmedTransactionHashes({}, hashes); + + ASSERT_FALSE(ec); + ASSERT_EQ(2, hashes.size()); + ASSERT_EQ(hashes[0], Common::podToHex(transactions[0].transaction.hash)); + ASSERT_EQ(hashes[1], Common::podToHex(transactions[1].transaction.hash)); +} + +TEST_F(WalletServiceTest_getUnconfirmedTransactionHashes, returnsOneTransactionWithAddressFilter) { + WalletGetUnconfirmedTransactionsStub wallet(dispatcher); + wallet.transactions = transactions; + auto service = createWalletService(wallet); + + std::vector hashes; + auto ec = service->getUnconfirmedTransactionHashes({RANDOM_ADDRESS1}, hashes); + + ASSERT_FALSE(ec); + ASSERT_EQ(1, hashes.size()); + ASSERT_EQ(hashes[0], Common::podToHex(transactions[0].transaction.hash)); +} + +TEST_F(WalletServiceTest_getUnconfirmedTransactionHashes, returnsTwoTransactionsWithAddressFilter) { + WalletGetUnconfirmedTransactionsStub wallet(dispatcher); + wallet.transactions = transactions; + auto service = createWalletService(wallet); + + std::vector hashes; + auto ec = service->getUnconfirmedTransactionHashes({RANDOM_ADDRESS2}, hashes); + + ASSERT_FALSE(ec); + ASSERT_EQ(2, hashes.size()); + ASSERT_EQ(hashes[0], Common::podToHex(transactions[0].transaction.hash)); + ASSERT_EQ(hashes[1], Common::podToHex(transactions[1].transaction.hash)); +} + +TEST_F(WalletServiceTest_getUnconfirmedTransactionHashes, wrongAddressFilter) { + auto service = createWalletService(); + + std::vector hashes; + auto ec = service->getUnconfirmedTransactionHashes({"wrong address"}, hashes); + + ASSERT_EQ(make_error_code(CryptoNote::error::BAD_ADDRESS), ec); +} diff --git a/tests/UnitTests/TransactionApi.cpp b/tests/UnitTests/TransactionApi.cpp index 0f532827..5ea708f9 100644 --- a/tests/UnitTests/TransactionApi.cpp +++ b/tests/UnitTests/TransactionApi.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/TransactionApiHelpers.cpp b/tests/UnitTests/TransactionApiHelpers.cpp index 1790ae01..e8cc7053 100755 --- a/tests/UnitTests/TransactionApiHelpers.cpp +++ b/tests/UnitTests/TransactionApiHelpers.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/TransactionApiHelpers.h b/tests/UnitTests/TransactionApiHelpers.h index 30bb283e..562bb178 100644 --- a/tests/UnitTests/TransactionApiHelpers.h +++ b/tests/UnitTests/TransactionApiHelpers.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/TransactionPool.cpp b/tests/UnitTests/TransactionPool.cpp index f70747ef..eba96d74 100755 --- a/tests/UnitTests/TransactionPool.cpp +++ b/tests/UnitTests/TransactionPool.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -47,7 +47,7 @@ public: : timeNow(currentTime) {} time_t timeNow; - virtual time_t now() { return timeNow; } + virtual time_t now() override { return timeNow; } }; diff --git a/tests/UnitTests/TransfersObserver.h b/tests/UnitTests/TransfersObserver.h index 8d78e5ee..44152e7b 100644 --- a/tests/UnitTests/TransfersObserver.h +++ b/tests/UnitTests/TransfersObserver.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/UnitTestsUtils.h b/tests/UnitTests/UnitTestsUtils.h index 42ec69a2..55c45183 100644 --- a/tests/UnitTests/UnitTestsUtils.h +++ b/tests/UnitTests/UnitTestsUtils.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/UnitTests/main.cpp b/tests/UnitTests/main.cpp index 26209268..fe6626d1 100644 --- a/tests/UnitTests/main.cpp +++ b/tests/UnitTests/main.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/crypto/crypto-ops-data.c b/tests/crypto/crypto-ops-data.c index 0f59369b..edf1af5a 100644 --- a/tests/crypto/crypto-ops-data.c +++ b/tests/crypto/crypto-ops-data.c @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/crypto/crypto-ops.c b/tests/crypto/crypto-ops.c index a0b73716..eb1c5616 100644 --- a/tests/crypto/crypto-ops.c +++ b/tests/crypto/crypto-ops.c @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/crypto/crypto-tests.h b/tests/crypto/crypto-tests.h index 6692d47d..37753cae 100644 --- a/tests/crypto/crypto-tests.h +++ b/tests/crypto/crypto-tests.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/crypto/crypto.cpp b/tests/crypto/crypto.cpp index f0142bc4..672e3916 100644 --- a/tests/crypto/crypto.cpp +++ b/tests/crypto/crypto.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/crypto/hash.c b/tests/crypto/hash.c index 260cfda9..128cbe4b 100644 --- a/tests/crypto/hash.c +++ b/tests/crypto/hash.c @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/crypto/main.cpp b/tests/crypto/main.cpp index 7291dcaa..26f182ea 100644 --- a/tests/crypto/main.cpp +++ b/tests/crypto/main.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/tests/crypto/random.c b/tests/crypto/random.c index 2c2e8459..c3fe9d30 100644 --- a/tests/crypto/random.c +++ b/tests/crypto/random.c @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2015 The Cryptonote developers +// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php.