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