Simplewallet improvements
This commit is contained in:
parent
ad291f5285
commit
6d45be9ec0
|
@ -35,7 +35,10 @@ namespace {
|
|||
|
||||
void handleSignal() {
|
||||
static std::mutex m_mutex;
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
std::unique_lock<std::mutex> lock(m_mutex, std::try_to_lock);
|
||||
if (!lock.owns_lock()) {
|
||||
return;
|
||||
}
|
||||
m_handler();
|
||||
}
|
||||
|
||||
|
@ -75,6 +78,7 @@ namespace tools {
|
|||
#else
|
||||
signal(SIGINT, posixHandler);
|
||||
signal(SIGTERM, posixHandler);
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
m_handler = t;
|
||||
return true;
|
||||
#endif
|
||||
|
|
|
@ -237,10 +237,6 @@ std::pair<Ipv4Address, uint16_t> TcpConnection::getPeerAddressAndPort() {
|
|||
}
|
||||
|
||||
TcpConnection::TcpConnection(Dispatcher& dispatcher, int socket) : dispatcher(&dispatcher), connection(socket), stopped(false), readContext(nullptr), writeContext(nullptr) {
|
||||
int val = 1;
|
||||
if (setsockopt(connection, SOL_SOCKET, SO_NOSIGPIPE, (void*)&val, sizeof val) == -1) {
|
||||
throw std::runtime_error("TcpConnection::TcpConnection, setsockopt failed, result=" + std::to_string(errno));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -150,7 +150,8 @@ const CheckpointData CHECKPOINTS[] = {
|
|||
{667000, "a020c8fcaa567845d04b520bb7ebe721e097a9bed2bdb8971081f933b5b42995"},
|
||||
{689000, "212ec2698c5ebd15d6242d59f36c2d186d11bb47c58054f476dd8e6b1c7f0008"},
|
||||
{713000, "a03f836c4a19f907cd6cac095eb6f56f5279ca2d1303fb7f826750dcb9025495"},
|
||||
{750300, "5117631dbeb5c14748a91127a515ecbf13f6849e14fda7ee03cd55da41f1710c"}
|
||||
{750300, "5117631dbeb5c14748a91127a515ecbf13f6849e14fda7ee03cd55da41f1710c"},
|
||||
{780000, "8dd55a9bae429e3685b90317281e633917023d3512eb7f37372209d1a5fc1070"}
|
||||
};
|
||||
} // CryptoNote
|
||||
|
||||
|
|
|
@ -435,7 +435,11 @@ namespace CryptoNote
|
|||
m_idleTimer.stop();
|
||||
m_timedSyncTimer.stop();
|
||||
|
||||
logger(INFO) << "Stopping " << m_connections.size() << " connections";
|
||||
logger(INFO) << "Stopping " << m_connections.size() + m_raw_connections.size() << " connections";
|
||||
|
||||
for (auto& conn : m_raw_connections) {
|
||||
conn.second.connection.stop();
|
||||
}
|
||||
|
||||
for (auto& conn : m_connections) {
|
||||
conn.second.connection.stop();
|
||||
|
@ -671,32 +675,44 @@ namespace CryptoNote
|
|||
ctx.m_is_income = false;
|
||||
ctx.m_started = time(nullptr);
|
||||
|
||||
CryptoNote::LevinProtocol proto(ctx.connection);
|
||||
auto raw = m_raw_connections.emplace(ctx.m_connection_id, std::move(ctx)).first;
|
||||
try {
|
||||
CryptoNote::LevinProtocol proto(raw->second.connection);
|
||||
|
||||
if (!handshake(proto, ctx, just_take_peerlist)) {
|
||||
logger(WARNING) << "Failed to HANDSHAKE with peer " << na;
|
||||
return false;
|
||||
if (!handshake(proto, raw->second, just_take_peerlist)) {
|
||||
logger(WARNING) << "Failed to HANDSHAKE with peer " << na;
|
||||
m_raw_connections.erase(raw);
|
||||
return false;
|
||||
}
|
||||
} catch (...) {
|
||||
m_raw_connections.erase(raw);
|
||||
throw;
|
||||
}
|
||||
|
||||
if (just_take_peerlist) {
|
||||
logger(Logging::DEBUGGING, Logging::BRIGHT_GREEN) << ctx << "CONNECTION HANDSHAKED OK AND CLOSED.";
|
||||
logger(Logging::DEBUGGING, Logging::BRIGHT_GREEN) << raw->second << "CONNECTION HANDSHAKED OK AND CLOSED.";
|
||||
m_raw_connections.erase(raw);
|
||||
return true;
|
||||
}
|
||||
|
||||
peerlist_entry pe_local = AUTO_VAL_INIT(pe_local);
|
||||
pe_local.adr = na;
|
||||
pe_local.id = ctx.peer_id;
|
||||
pe_local.id = raw->second.peer_id;
|
||||
time(&pe_local.last_seen);
|
||||
m_peerlist.append_with_peer_white(pe_local);
|
||||
|
||||
if (m_stop) {
|
||||
m_raw_connections.erase(raw);
|
||||
throw System::InterruptedException();
|
||||
}
|
||||
|
||||
auto iter = m_connections.emplace(ctx.m_connection_id, std::move(ctx)).first;
|
||||
auto iter = m_connections.emplace(raw->first, std::move(raw->second)).first;
|
||||
m_raw_connections.erase(raw);
|
||||
const boost::uuids::uuid& connectionId = iter->first;
|
||||
p2p_connection_context& connectionContext = iter->second;
|
||||
|
||||
++m_spawnCount;
|
||||
m_dispatcher.spawn(std::bind(&node_server::connectionHandler, this, iter));
|
||||
m_dispatcher.spawn(std::bind(&node_server::connectionHandler, this, std::cref(connectionId), std::ref(connectionContext)));
|
||||
|
||||
return true;
|
||||
} catch (System::InterruptedException&) {
|
||||
|
@ -1219,9 +1235,11 @@ namespace CryptoNote
|
|||
ctx.m_remote_port = addressAndPort.second;
|
||||
|
||||
auto iter = m_connections.emplace(ctx.m_connection_id, std::move(ctx)).first;
|
||||
const boost::uuids::uuid& connectionId = iter->first;
|
||||
p2p_connection_context& connection = iter->second;
|
||||
|
||||
++m_spawnCount;
|
||||
m_dispatcher.spawn(std::bind(&node_server::connectionHandler, this, iter));
|
||||
m_dispatcher.spawn(std::bind(&node_server::connectionHandler, this, std::cref(connectionId), std::ref(connection)));
|
||||
}
|
||||
} catch (System::InterruptedException&) {
|
||||
} catch (const std::exception& e) {
|
||||
|
@ -1274,10 +1292,9 @@ namespace CryptoNote
|
|||
}
|
||||
}
|
||||
|
||||
void node_server::connectionHandler(ConnectionIterator connIter) {
|
||||
void node_server::connectionHandler(const boost::uuids::uuid& connectionId, p2p_connection_context& ctx) {
|
||||
|
||||
try {
|
||||
auto& ctx = connIter->second;
|
||||
on_connection_new(ctx);
|
||||
|
||||
LevinProtocol proto(ctx.connection);
|
||||
|
@ -1320,10 +1337,10 @@ namespace CryptoNote
|
|||
logger(WARNING) << "Exception in connectionHandler: " << e.what();
|
||||
}
|
||||
|
||||
connIter->second.writeLatch.wait();
|
||||
ctx.writeLatch.wait();
|
||||
|
||||
on_connection_close(connIter->second);
|
||||
m_connections.erase(connIter);
|
||||
on_connection_close(ctx);
|
||||
m_connections.erase(connectionId);
|
||||
|
||||
if (--m_spawnCount == 0) {
|
||||
m_shutdownCompleteEvent.set();
|
||||
|
|
|
@ -171,10 +171,11 @@ namespace CryptoNote
|
|||
|
||||
typedef std::unordered_map<boost::uuids::uuid, p2p_connection_context, boost::hash<boost::uuids::uuid>> ConnectionContainer;
|
||||
typedef ConnectionContainer::iterator ConnectionIterator;
|
||||
ConnectionContainer m_raw_connections;
|
||||
ConnectionContainer m_connections;
|
||||
|
||||
void acceptLoop();
|
||||
void connectionHandler(ConnectionIterator connIter);
|
||||
void connectionHandler(const boost::uuids::uuid& connectionId, p2p_connection_context& connection);
|
||||
void onIdle();
|
||||
void timedSyncLoop();
|
||||
|
||||
|
|
|
@ -791,7 +791,7 @@ bool simple_wallet::listTransfers(const std::vector<std::string>& args) {
|
|||
for (size_t trantransactionNumber = 0; trantransactionNumber < transactionsCount; ++trantransactionNumber) {
|
||||
TransactionInfo txInfo;
|
||||
m_wallet->getTransaction(trantransactionNumber, txInfo);
|
||||
if (txInfo.state != TransactionState::Active) {
|
||||
if (txInfo.state != TransactionState::Active || txInfo.blockHeight == UNCONFIRMED_TRANSACTION_HEIGHT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -125,7 +125,6 @@ private:
|
|||
INode& m_node;
|
||||
const crypto::hash m_genesisBlockHash;
|
||||
|
||||
std::vector<crypto::hash> knownTxIds;
|
||||
crypto::hash lastBlockId;
|
||||
|
||||
State m_currentState;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#define BUILD_COMMIT_ID "@VERSION@"
|
||||
#define PROJECT_VERSION "1.0.4"
|
||||
#define PROJECT_VERSION_BUILD_NO "461"
|
||||
#define PROJECT_VERSION "1.0.4.1"
|
||||
#define PROJECT_VERSION_BUILD_NO "466"
|
||||
#define PROJECT_VERSION_LONG PROJECT_VERSION "." PROJECT_VERSION_BUILD_NO "(" BUILD_COMMIT_ID ")"
|
||||
|
|
|
@ -16,14 +16,15 @@
|
|||
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "Wallet.h"
|
||||
#include "serialization/binary_utils.h"
|
||||
#include "WalletUtils.h"
|
||||
#include "WalletSerializer.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "serialization/binary_utils.h"
|
||||
#include "WalletHelper.h"
|
||||
#include "WalletSerialization.h"
|
||||
#include "WalletSerializer.h"
|
||||
#include "WalletUtils.h"
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -93,6 +94,7 @@ private:
|
|||
std::promise<std::error_code> promise;
|
||||
std::future<std::error_code> future;
|
||||
};
|
||||
|
||||
} //namespace
|
||||
|
||||
namespace CryptoNote {
|
||||
|
@ -125,7 +127,6 @@ Wallet::Wallet(const CryptoNote::Currency& currency, INode& node) :
|
|||
m_onInitSyncStarter(new SyncStarter(m_blockchainSync))
|
||||
{
|
||||
addObserver(m_onInitSyncStarter.get());
|
||||
m_blockchainSync.addObserver(this);
|
||||
}
|
||||
|
||||
Wallet::~Wallet() {
|
||||
|
@ -139,10 +140,10 @@ Wallet::~Wallet() {
|
|||
}
|
||||
}
|
||||
|
||||
m_blockchainSync.removeObserver(this);
|
||||
m_blockchainSync.stop();
|
||||
m_asyncContextCounter.waitAsyncContextsFinish();
|
||||
m_sender.release();
|
||||
m_blockchainSync.removeObserver(this);
|
||||
m_blockchainSync.stop();
|
||||
m_asyncContextCounter.waitAsyncContextsFinish();
|
||||
m_sender.release();
|
||||
}
|
||||
|
||||
void Wallet::addObserver(IWalletObserver* observer) {
|
||||
|
@ -215,7 +216,7 @@ void Wallet::initAndLoad(std::istream& source, const std::string& password) {
|
|||
|
||||
m_password = password;
|
||||
m_state = LOADING;
|
||||
|
||||
|
||||
m_asyncContextCounter.addAsyncContext();
|
||||
std::thread loader(&Wallet::doLoad, this, std::ref(source));
|
||||
loader.detach();
|
||||
|
@ -234,6 +235,8 @@ void Wallet::initSync() {
|
|||
|
||||
m_sender.reset(new WalletTransactionSender(m_currency, m_transactionsCache, m_account.get_keys(), *m_transferDetails));
|
||||
m_state = INITIALIZED;
|
||||
|
||||
m_blockchainSync.addObserver(this);
|
||||
}
|
||||
|
||||
void Wallet::doLoad(std::istream& source) {
|
||||
|
@ -248,20 +251,18 @@ void Wallet::doLoad(std::istream& source) {
|
|||
initSync();
|
||||
|
||||
try {
|
||||
if (!cache.empty()) {
|
||||
std::stringstream stream(cache);
|
||||
m_transfersSync.load(stream);
|
||||
}
|
||||
if (!cache.empty()) {
|
||||
std::stringstream stream(cache);
|
||||
m_transfersSync.load(stream);
|
||||
}
|
||||
} catch (const std::exception&) {
|
||||
// ignore cache loading errors
|
||||
}
|
||||
}
|
||||
catch (std::system_error& e) {
|
||||
}
|
||||
} catch (std::system_error& e) {
|
||||
runAtomic(m_cacheMutex, [this] () {this->m_state = Wallet::NOT_INITIALIZED;} );
|
||||
m_observerManager.notify(&IWalletObserver::initCompleted, e.code());
|
||||
return;
|
||||
}
|
||||
catch (std::exception&) {
|
||||
} catch (std::exception&) {
|
||||
runAtomic(m_cacheMutex, [this] () {this->m_state = Wallet::NOT_INITIALIZED;} );
|
||||
m_observerManager.notify(&IWalletObserver::initCompleted, make_error_code(CryptoNote::error::INTERNAL_WALLET_ERROR));
|
||||
return;
|
||||
|
@ -295,31 +296,39 @@ void Wallet::shutdown() {
|
|||
std::unique_lock<std::mutex> lock(m_cacheMutex);
|
||||
m_isStopping = false;
|
||||
m_state = NOT_INITIALIZED;
|
||||
|
||||
const AccountAddress& accountAddress = reinterpret_cast<const AccountAddress&>(m_account.get_keys().m_account_address);
|
||||
auto subObject = m_transfersSync.getSubscription(accountAddress);
|
||||
assert(subObject != nullptr);
|
||||
subObject->removeObserver(this);
|
||||
m_transfersSync.removeSubscription(accountAddress);
|
||||
m_transferDetails = nullptr;
|
||||
|
||||
m_transactionsCache.reset();
|
||||
m_lastNotifiedActualBalance = 0;
|
||||
m_lastNotifiedPendingBalance = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Wallet::reset() {
|
||||
InitWaiter initWaiter;
|
||||
SaveWaiter saveWaiter;
|
||||
|
||||
addObserver(&initWaiter);
|
||||
addObserver(&saveWaiter);
|
||||
WalletHelper::IWalletRemoveObserverGuard initGuarantee(*this, initWaiter);
|
||||
WalletHelper::IWalletRemoveObserverGuard saveGuarantee(*this, saveWaiter);
|
||||
|
||||
std::stringstream ss;
|
||||
try {
|
||||
save(ss, false, false);
|
||||
save(ss, false, false);
|
||||
|
||||
auto saveError = saveWaiter.waitSave();
|
||||
if (!saveError) {
|
||||
shutdown();
|
||||
initAndLoad(ss, m_password);
|
||||
if (!saveError) {
|
||||
shutdown();
|
||||
initAndLoad(ss, m_password);
|
||||
initWaiter.waitInit();
|
||||
}
|
||||
} catch (std::exception& e) {
|
||||
std::cout << "exception in reset: " << e.what() << std::endl;
|
||||
}
|
||||
} catch (std::exception&) {
|
||||
}
|
||||
|
||||
removeObserver(&saveWaiter);
|
||||
removeObserver(&initWaiter);
|
||||
}
|
||||
|
||||
void Wallet::save(std::ostream& destination, bool saveDetailed, bool saveCache) {
|
||||
|
|
|
@ -123,5 +123,9 @@ void WalletUnconfirmedTransactions::collectUsedOutputs() {
|
|||
m_usedOutputs = std::move(used);
|
||||
}
|
||||
|
||||
void WalletUnconfirmedTransactions::reset() {
|
||||
m_unconfirmedTxs.clear();
|
||||
m_usedOutputs.clear();
|
||||
}
|
||||
|
||||
} /* namespace CryptoNote */
|
||||
|
|
|
@ -64,6 +64,7 @@ public:
|
|||
uint64_t countUnconfirmedOutsAmount() const;
|
||||
uint64_t countUnconfirmedTransactionsAmount() const;
|
||||
bool isUsed(const TransactionOutputInformation& out) const;
|
||||
void reset();
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -293,5 +293,11 @@ void WalletUserTransactionsCache::updateUnconfirmedTransactions() {
|
|||
Transfer& WalletUserTransactionsCache::getTransfer(TransferId transferId) {
|
||||
return m_transfers.at(transferId);
|
||||
}
|
||||
|
||||
void WalletUserTransactionsCache::reset() {
|
||||
m_transactions.clear();
|
||||
m_transfers.clear();
|
||||
m_unconfirmedTransactions.reset();
|
||||
}
|
||||
|
||||
} //namespace CryptoNote
|
||||
|
|
|
@ -57,6 +57,7 @@ public:
|
|||
Transfer& getTransfer(TransferId transferId);
|
||||
|
||||
bool isUsed(const TransactionOutputInformation& out) const;
|
||||
void reset();
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "EventWaiter.h"
|
||||
#include "INode.h"
|
||||
#include "wallet/Wallet.h"
|
||||
#include "wallet/WalletHelper.h"
|
||||
#include "cryptonote_core/account.h"
|
||||
#include "cryptonote_core/Currency.h"
|
||||
|
||||
|
@ -285,7 +286,7 @@ void WalletApi::TestSendMoney(int64_t transferAmount, uint64_t fee, uint64_t mix
|
|||
bob->initAndGenerate("pass2");
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(bobWalletObserver.get()));
|
||||
ASSERT_NO_FATAL_FAILURE(TransferMoney(*alice, *bob, transferAmount, fee, 0, ""));
|
||||
ASSERT_NO_FATAL_FAILURE(TransferMoney(*alice, *bob, transferAmount, fee, mixIn, ""));
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSend(aliceWalletObserver.get()));
|
||||
|
||||
generator.generateEmptyBlocks(10);
|
||||
|
@ -1327,3 +1328,344 @@ TEST_F(WalletApi, DISABLED_loadingBrokenCache) {
|
|||
ASSERT_NO_FATAL_FAILURE(WaitWalletLoad(aliceWalletObserver.get(), result));
|
||||
ASSERT_EQ(result.value(), 0);
|
||||
}
|
||||
|
||||
TEST_F(WalletApi, shutdownAllowsInitializeWalletWithTheSameKeys) {
|
||||
alice->initAndGenerate("pass");
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
GetOneBlockReward(*alice);
|
||||
aliceNode->updateObservers();
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
CryptoNote::WalletAccountKeys accountKeys;
|
||||
alice->getAccountKeys(accountKeys);
|
||||
|
||||
alice->shutdown();
|
||||
alice->initWithKeys(accountKeys, "pass");
|
||||
|
||||
aliceNode->updateObservers();
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
ASSERT_EQ(1, alice->getTransactionCount());
|
||||
|
||||
alice->shutdown();
|
||||
}
|
||||
|
||||
TEST_F(WalletApi, shutdownAllowsInitializeWalletWithDifferentKeys) {
|
||||
alice->initAndGenerate("pass");
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
GetOneBlockReward(*alice);
|
||||
aliceNode->updateObservers();
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
alice->shutdown();
|
||||
alice->initAndGenerate("pass");
|
||||
|
||||
aliceNode->updateObservers();
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
ASSERT_EQ(0, alice->getTransactionCount());
|
||||
|
||||
alice->shutdown();
|
||||
}
|
||||
|
||||
namespace {
|
||||
class WalletSynchronizationProgressUpdatedObserver : public CryptoNote::IWalletObserver {
|
||||
public:
|
||||
virtual void synchronizationProgressUpdated(uint64_t current, uint64_t /*total*/) override {
|
||||
m_current = current;
|
||||
}
|
||||
|
||||
uint64_t m_current = 0;
|
||||
};
|
||||
}
|
||||
|
||||
TEST_F(WalletApi, shutdownDoesNotRemoveObservers) {
|
||||
alice->initAndGenerate("pass");
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
WalletSynchronizationProgressUpdatedObserver observer;
|
||||
CryptoNote::WalletHelper::IWalletRemoveObserverGuard observerGuard(*alice, observer);
|
||||
|
||||
alice->shutdown();
|
||||
observer.m_current = 0;
|
||||
alice->initAndGenerate("pass");
|
||||
|
||||
aliceNode->updateObservers();
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
ASSERT_EQ(5, observer.m_current);
|
||||
|
||||
observerGuard.removeObserver();
|
||||
alice->shutdown();
|
||||
}
|
||||
|
||||
namespace {
|
||||
class WalletTransactionEventCounter : public CryptoNote::IWalletObserver {
|
||||
public:
|
||||
virtual void externalTransactionCreated(CryptoNote::TransactionId /*transactionId*/) override {
|
||||
++m_count;
|
||||
}
|
||||
|
||||
virtual void transactionUpdated(CryptoNote::TransactionId /*transactionId*/) override {
|
||||
++m_count;
|
||||
}
|
||||
|
||||
size_t m_count = 0;
|
||||
};
|
||||
}
|
||||
|
||||
TEST_F(WalletApi, afterShutdownAndInitWalletDoesNotSendNotificationsRelatedToOldAddress) {
|
||||
alice->initAndGenerate("pass");
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
std::string aliceAddress1 = alice->getAddress();
|
||||
CryptoNote::WalletAccountKeys accountKeys1;
|
||||
alice->getAccountKeys(accountKeys1);
|
||||
|
||||
alice->shutdown();
|
||||
alice->initAndGenerate("pass");
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
std::string aliceAddress2 = alice->getAddress();
|
||||
|
||||
alice->shutdown();
|
||||
alice->initWithKeys(accountKeys1, "pass");
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
WalletTransactionEventCounter observer;
|
||||
CryptoNote::WalletHelper::IWalletRemoveObserverGuard observerGuard(*alice, observer);
|
||||
|
||||
prepareBobWallet();
|
||||
bob->initAndGenerate("pass");
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(bobWalletObserver.get()));
|
||||
GetOneBlockReward(*bob);
|
||||
generator.generateEmptyBlocks(10);
|
||||
bobNode->updateObservers();
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(bobWalletObserver.get()));
|
||||
|
||||
std::vector<CryptoNote::Transfer> transfers;
|
||||
transfers.push_back({ aliceAddress1, TEST_BLOCK_REWARD / 10 });
|
||||
transfers.push_back({ aliceAddress2, TEST_BLOCK_REWARD / 5 });
|
||||
bob->sendTransaction(transfers, m_currency.minimumFee());
|
||||
std::error_code sendResult;
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSend(bobWalletObserver.get(), sendResult));
|
||||
|
||||
generator.generateEmptyBlocks(1);
|
||||
bobNode->updateObservers();
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(bobWalletObserver.get()));
|
||||
|
||||
aliceNode->updateObservers();
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
ASSERT_EQ(1, observer.m_count);
|
||||
|
||||
observerGuard.removeObserver();
|
||||
bob->shutdown();
|
||||
alice->shutdown();
|
||||
}
|
||||
|
||||
TEST_F(WalletApi, resetDoesNotChangeAddress) {
|
||||
alice->initAndGenerate("pass");
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
auto expectedAddress = alice->getAddress();
|
||||
alice->reset();
|
||||
ASSERT_EQ(expectedAddress, alice->getAddress());
|
||||
|
||||
alice->shutdown();
|
||||
}
|
||||
|
||||
TEST_F(WalletApi, resetDoesNotChangeAccountKeys) {
|
||||
alice->initAndGenerate("pass");
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
CryptoNote::WalletAccountKeys expectedAccountKeys;
|
||||
alice->getAccountKeys(expectedAccountKeys);
|
||||
|
||||
alice->reset();
|
||||
|
||||
CryptoNote::WalletAccountKeys actualAccountKeys;
|
||||
alice->getAccountKeys(actualAccountKeys);
|
||||
|
||||
ASSERT_EQ(expectedAccountKeys.spendPublicKey, actualAccountKeys.spendPublicKey);
|
||||
ASSERT_EQ(expectedAccountKeys.spendSecretKey, actualAccountKeys.spendSecretKey);
|
||||
ASSERT_EQ(expectedAccountKeys.viewPublicKey, actualAccountKeys.viewPublicKey);
|
||||
ASSERT_EQ(expectedAccountKeys.viewSecretKey, actualAccountKeys.viewSecretKey);
|
||||
|
||||
alice->shutdown();
|
||||
}
|
||||
|
||||
TEST_F(WalletApi, resetDoesNotRemoveObservers) {
|
||||
alice->initAndGenerate("pass");
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
WalletSynchronizationProgressUpdatedObserver observer;
|
||||
CryptoNote::WalletHelper::IWalletRemoveObserverGuard observerGuard(*alice, observer);
|
||||
|
||||
alice->reset();
|
||||
observer.m_current = 0;
|
||||
|
||||
aliceNode->updateObservers();
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
ASSERT_EQ(5, observer.m_current);
|
||||
|
||||
observerGuard.removeObserver();
|
||||
alice->shutdown();
|
||||
}
|
||||
|
||||
TEST_F(WalletApi, resetDoesNotChangePassword) {
|
||||
std::string password = "password";
|
||||
std::string newPassword = "new_password";
|
||||
|
||||
alice->initAndGenerate(password);
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
alice->reset();
|
||||
ASSERT_TRUE(static_cast<bool>(alice->changePassword(newPassword, password)));
|
||||
ASSERT_FALSE(static_cast<bool>(alice->changePassword(password, newPassword)));
|
||||
|
||||
alice->shutdown();
|
||||
}
|
||||
|
||||
TEST_F(WalletApi, resetClearsPendingBalance) {
|
||||
alice->initAndGenerate("pass");
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
GetOneBlockReward(*alice);
|
||||
aliceNode->updateObservers();
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
ASSERT_EQ(TEST_BLOCK_REWARD, alice->pendingBalance());
|
||||
alice->reset();
|
||||
ASSERT_EQ(0, alice->pendingBalance());
|
||||
|
||||
alice->shutdown();
|
||||
}
|
||||
|
||||
TEST_F(WalletApi, resetClearsActualBalance) {
|
||||
alice->initAndGenerate("pass");
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
GetOneBlockReward(*alice);
|
||||
generator.generateEmptyBlocks(10);
|
||||
aliceNode->updateObservers();
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
ASSERT_EQ(TEST_BLOCK_REWARD, alice->actualBalance());
|
||||
alice->reset();
|
||||
ASSERT_EQ(0, alice->actualBalance());
|
||||
|
||||
alice->shutdown();
|
||||
}
|
||||
|
||||
TEST_F(WalletApi, resetClearsTransactionHistory) {
|
||||
alice->initAndGenerate("pass");
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
GetOneBlockReward(*alice);
|
||||
generator.generateEmptyBlocks(10);
|
||||
aliceNode->updateObservers();
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
ASSERT_EQ(1, alice->getTransactionCount());
|
||||
alice->reset();
|
||||
ASSERT_EQ(0, alice->getTransactionCount());
|
||||
|
||||
alice->shutdown();
|
||||
}
|
||||
|
||||
TEST_F(WalletApi, resetClearsTransfersHistory) {
|
||||
alice->initAndGenerate("pass");
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
GetOneBlockReward(*alice);
|
||||
generator.generateEmptyBlocks(10);
|
||||
aliceNode->updateObservers();
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
alice->sendTransaction({ alice->getAddress(), 100 }, m_currency.minimumFee());
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSend(aliceWalletObserver.get()));
|
||||
|
||||
ASSERT_EQ(1, alice->getTransferCount());
|
||||
alice->reset();
|
||||
ASSERT_EQ(0, alice->getTransferCount());
|
||||
|
||||
alice->shutdown();
|
||||
}
|
||||
|
||||
TEST_F(WalletApi, resetAndSyncRestorePendingBalance) {
|
||||
alice->initAndGenerate("pass");
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
GetOneBlockReward(*alice);
|
||||
aliceNode->updateObservers();
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
alice->reset();
|
||||
aliceNode->updateObservers();
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
ASSERT_EQ(TEST_BLOCK_REWARD, alice->pendingBalance());
|
||||
|
||||
alice->shutdown();
|
||||
}
|
||||
|
||||
TEST_F(WalletApi, resetAndSyncRestoreActualBalance) {
|
||||
alice->initAndGenerate("pass");
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
GetOneBlockReward(*alice);
|
||||
generator.generateEmptyBlocks(10);
|
||||
aliceNode->updateObservers();
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
alice->reset();
|
||||
aliceNode->updateObservers();
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
ASSERT_EQ(TEST_BLOCK_REWARD, alice->actualBalance());
|
||||
|
||||
alice->shutdown();
|
||||
}
|
||||
|
||||
TEST_F(WalletApi, resetAndSyncRestoreTransactions) {
|
||||
alice->initAndGenerate("pass");
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
GetOneBlockReward(*alice);
|
||||
generator.generateEmptyBlocks(10);
|
||||
aliceNode->updateObservers();
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
alice->reset();
|
||||
aliceNode->updateObservers();
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
ASSERT_EQ(1, alice->getTransactionCount());
|
||||
|
||||
alice->shutdown();
|
||||
}
|
||||
|
||||
TEST_F(WalletApi, resetAndSyncDoNotRestoreTransfers) {
|
||||
alice->initAndGenerate("pass");
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
GetOneBlockReward(*alice);
|
||||
generator.generateEmptyBlocks(10);
|
||||
aliceNode->updateObservers();
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
alice->sendTransaction({ alice->getAddress(), 100 }, m_currency.minimumFee());
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSend(aliceWalletObserver.get()));
|
||||
|
||||
alice->reset();
|
||||
aliceNode->updateObservers();
|
||||
ASSERT_NO_FATAL_FAILURE(WaitWalletSync(aliceWalletObserver.get()));
|
||||
|
||||
ASSERT_EQ(0, alice->getTransferCount());
|
||||
|
||||
alice->shutdown();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue