Files

221 lines
9.4 KiB
C++
Raw Permalink Normal View History

2020-05-19 17:39:21 +02:00
/*
* This file is part of the Flowee project
2021-06-20 22:44:44 +02:00
* Copyright (C) 2019-2020 Tom Zander <tom@flowee.org>
2020-05-19 17:39:21 +02:00
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "TestTxIdMonitor.h"
2021-03-17 21:07:25 +01:00
#include "TestData.h"
2020-05-19 17:39:21 +02:00
#include <uint256.h>
#include <streaming/BufferPool.h>
#include <streaming/MessageBuilder.h>
#include <streaming/MessageParser.h>
#include <primitives/Tx.h>
2020-05-19 17:39:21 +02:00
void TestTxIdMonitor::testBasic()
{
startHubs();
2023-12-21 15:13:56 +01:00
auto pool = std::make_shared<Streaming::BufferPool>();
pool->reserve(50);
2020-05-19 17:39:21 +02:00
Streaming::MessageBuilder builder(pool);
// (coinbase @ 5)
builder.add(Api::TransactionMonitor::TxId, uint256S("29bae599098880a9e609418ea5dee1da154b214c3cad6f99d96596badfadefc1"));
// (last tx in block 111)
builder.add(Api::TransactionMonitor::TxId, uint256S("a3132383a40424c1ac9644be637c3bb471dffdfa4bf05139b9a0ce3b8d45db88"));
auto m = waitForReply(0, builder.message(Api::TransactionMonitorService,
Api::TransactionMonitor::Subscribe), Api::TransactionMonitor::SubscribeReply);
QVERIFY(m.messageId() == Api::TransactionMonitor::SubscribeReply);
feedDefaultBlocksToHub(0);
int total = 0;
for (auto message : m_hubs[0].messages) {
if (message.serviceId() == Api::TransactionMonitorService) {
QVERIFY(message.messageId() == Api::TransactionMonitor::SubscribeReply
|| message.messageId() == Api::TransactionMonitor::TransactionFound);
if (message.messageId() != Api::TransactionMonitor::TransactionFound)
continue;
++total;
bool seenBlockHeight = false, seenOffsetInBlock = false;
int seenTransactions = 0;
Streaming::MessageParser p(message.body());
QCOMPARE(p.next(), Streaming::FoundTag);
while (true) {
if (p.tag() == Api::TransactionMonitor::TxId) {
seenTransactions++;
QCOMPARE(p.isByteArray(), true);
QCOMPARE(p.dataLength(), 32);
}
else if (p.tag() == Api::TransactionMonitor::OffsetInBlock) {
seenOffsetInBlock = true;
QCOMPARE(p.isInt(), true);
QVERIFY(p.intData() > 80);
}
else if (p.tag() == Api::TransactionMonitor::BlockHeight) {
seenBlockHeight = true;
QCOMPARE(p.isInt(), true);
QVERIFY(p.intData() > 0);
}
auto type = p.next();
QVERIFY(type != Streaming::Error);
if (type != Streaming::FoundTag)
break;
}
QVERIFY(seenTransactions > 0);
QVERIFY(seenTransactions <= 2);
QVERIFY(seenOffsetInBlock);
QVERIFY(seenBlockHeight);
}
}
QCOMPARE(total, 2);
}
void TestTxIdMonitor::testMempool()
{
startHubs(2);
feedDefaultBlocksToHub(0);
QVERIFY(waitForHeight(115)); // make sure all nodes are at the same tip.
2023-12-21 15:13:56 +01:00
auto pool = std::make_shared<Streaming::BufferPool>();
auto txs = TestData::createDoubleSpend(pool);
2021-03-17 21:07:25 +01:00
Tx tx1 = txs.first;
2023-12-21 15:13:56 +01:00
pool->reserve(50);
2020-05-19 17:39:21 +02:00
Streaming::MessageBuilder builder(pool);
builder.add(Api::TransactionMonitor::TxId, tx1.createHash());
auto m = waitForReply(0, builder.message(Api::TransactionMonitorService,
Api::TransactionMonitor::Subscribe), Api::TransactionMonitor::SubscribeReply);
QVERIFY(m.messageId() == Api::TransactionMonitor::SubscribeReply);
logDebug() << "Sending tx1 to hub0" << tx1.createHash();
2020-09-02 13:52:36 +02:00
Streaming::MessageBuilder builder2(pool);
builder2.add(Api::LiveTransactions::GenericByteData, tx1.data());
2020-05-19 17:39:21 +02:00
m = waitForReply(0, builder.message(Api::LiveTransactionService, Api::LiveTransactions::SendTransaction),
Api::TransactionMonitorService, Api::TransactionMonitor::TransactionFound);
QVERIFY(m.messageId() == Api::TransactionMonitor::TransactionFound);
bool seenBlockHeight = false, seenOffsetInBlock = false, seenTxId = false;
Streaming::MessageParser p(m.body());
while (p.next() == Streaming::FoundTag) {
if (p.tag() == Api::TransactionMonitor::TxId) {
QVERIFY(p.uint256Data() == tx1.createHash());
seenTxId = true;
}
else if (p.tag() == Api::TransactionMonitor::BlockHeight)
seenBlockHeight = true;
else if (p.tag() == Api::TransactionMonitor::OffsetInBlock)
seenOffsetInBlock = true;
else
QVERIFY(false);
}
QCOMPARE(seenTxId, true);
QCOMPARE(seenBlockHeight, false);
QCOMPARE(seenOffsetInBlock, false);
// second part; to connect to a peer that already has it in the mempool.
2020-09-02 13:52:36 +02:00
builder2.add(Api::TransactionMonitor::TxId, tx1.createHash());
m = waitForReply(1, builder2.message(Api::TransactionMonitorService, Api::TransactionMonitor::Subscribe),
2020-05-19 17:39:21 +02:00
Api::TransactionMonitorService, Api::TransactionMonitor::TransactionFound);
QVERIFY(m.messageId() == Api::TransactionMonitor::TransactionFound);
seenTxId = false;
p = Streaming::MessageParser(m.body());
while (p.next() == Streaming::FoundTag) {
if (p.tag() == Api::TransactionMonitor::TxId) {
QVERIFY(p.uint256Data() == tx1.createHash());
seenTxId = true;
}
else if (p.tag() == Api::TransactionMonitor::BlockHeight)
seenBlockHeight = true;
else if (p.tag() == Api::TransactionMonitor::OffsetInBlock)
seenOffsetInBlock = true;
else
QVERIFY(false);
}
QCOMPARE(seenTxId, true);
QCOMPARE(seenBlockHeight, false);
QCOMPARE(seenOffsetInBlock, false);
}
void TestTxIdMonitor::testDoubleSpend()
{
startHubs(2);
feedDefaultBlocksToHub(0);
QVERIFY(waitForHeight(115)); // make sure all nodes are at the same tip.
2023-12-21 15:13:56 +01:00
auto pool = std::make_shared<Streaming::BufferPool>();
auto txs = TestData::createDoubleSpend(pool);
2021-03-17 21:07:25 +01:00
Tx tx1 = txs.first;
Tx tx2 = txs.second;
2020-05-19 17:39:21 +02:00
// subscribing
Streaming::MessageBuilder builder(pool);
builder.add(Api::TransactionMonitor::TxId, tx1.createHash());
auto subScribeMessage = builder.message(Api::TransactionMonitorService, Api::TransactionMonitor::Subscribe);
auto m = waitForReply(0, subScribeMessage, Api::TransactionMonitor::SubscribeReply);
QCOMPARE(m.messageId(), (int) Api::TransactionMonitor::SubscribeReply);
m = waitForReply(1, subScribeMessage, Api::TransactionMonitor::SubscribeReply);
QCOMPARE(m.messageId(), (int) Api::TransactionMonitor::SubscribeReply);
// I wills end the txs to peer zero, lets catch the double spend proof on peer 1
m_hubs[1].m_waitForMessageId = Api::TransactionMonitor::DoubleSpendFound;
m_hubs[1].m_waitForServiceId = Api::TransactionMonitorService;
m_hubs[1].m_waitForMessageId2 = -1;
2022-08-20 19:18:34 +02:00
m_hubs[1].m_foundMessage.storeRelaxed(nullptr);
2020-05-19 17:39:21 +02:00
logDebug() << "Sending tx1 to hub0" << tx1.createHash();
2020-09-02 13:52:36 +02:00
Streaming::MessageBuilder builder2(pool);
builder2.add(Api::LiveTransactions::GenericByteData, tx1.data());
m = waitForReply(0, builder2.message(Api::LiveTransactionService, Api::LiveTransactions::SendTransaction),
2020-05-19 17:39:21 +02:00
Api::TransactionMonitorService, Api::TransactionMonitor::TransactionFound);
QCOMPARE(m.messageId(), (int) Api::TransactionMonitor::TransactionFound);
logDebug() << "Sending tx2 to hub0" << tx2.createHash();
2020-09-02 13:52:36 +02:00
Streaming::MessageBuilder builder3(pool);
builder3.add(Api::LiveTransactions::GenericByteData, tx2.data());
m = waitForReply(0, builder3.message(Api::LiveTransactionService, Api::LiveTransactions::SendTransaction),
2020-05-19 17:39:21 +02:00
Api::TransactionMonitorService, Api::TransactionMonitor::DoubleSpendFound);
QCOMPARE(m.messageId(), (int) Api::TransactionMonitor::DoubleSpendFound);
// we should get a notification about the double spend attempt of the transaction I am interested in (tx1).
// Lets take a look at the message.
Streaming::MessageParser p(m);
p.next();
QCOMPARE(p.tag(), (uint32_t) Api::TransactionMonitor::TxId);
QCOMPARE(p.dataLength(), 32);
QVERIFY((p.uint256Data() == tx1.createHash()));
p.next();
QCOMPARE(p.tag(), (uint32_t) Api::TransactionMonitor::TransactionData); // the transaction.
QCOMPARE(p.dataLength(), tx2.size());
2020-06-01 19:58:38 +02:00
QTRY_VERIFY_WITH_TIMEOUT(m_hubs[1].m_foundMessage != nullptr, 30000); // this waits until its arrived.
2022-08-20 19:18:34 +02:00
Message *m2 = m_hubs[1].m_foundMessage.loadRelaxed();
2020-05-19 17:39:21 +02:00
assert(m2); // the qtry should have failed.
p = Streaming::MessageParser(*m2);
p.next();
QCOMPARE(p.tag(), (uint32_t) Api::TransactionMonitor::TxId);
QCOMPARE(p.dataLength(), 32);
QVERIFY((p.uint256Data() == tx1.createHash()));
p.next();
2020-07-05 16:31:49 +02:00
QVERIFY(p.tag() == Api::TransactionMonitor::DoubleSpendProofData
|| p.tag() == Api::TransactionMonitor::TransactionData);
2020-05-19 17:39:21 +02:00
}
QTEST_MAIN(TestTxIdMonitor)