2021-05-27 18:40:58 +02:00
/*
* This file is part of the Flowee project
2024-05-28 10:20:42 +02:00
* Copyright (C) 2021-2024 Tom Zander <tom@flowee.org>
2021-05-27 18:40:58 +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 "test_blockchain.h"
# include <p2p/Blockchain.h>
# include <p2p/DownloadManager.h>
# include <streaming/BufferPool.h>
# include <streaming/P2PBuilder.h>
# include <utiltime.h>
constexpr const char * genesisHash = " 0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f " ;
void TestP2PBlockchain : : init ( )
{
2022-01-12 19:45:51 +01:00
m_tmpPath = QDir : : tempPath ( ) + QString ( " /flowee-test-%1 " ) . arg ( getpid ( ) ) ;
2021-05-27 18:40:58 +02:00
}
void TestP2PBlockchain : : cleanup ( )
{
// delete tmp dir.
if ( ! m_tmpPath . isEmpty ( ) )
QDir ( m_tmpPath ) . removeRecursively ( ) ;
m_tmpPath . clear ( ) ;
2022-01-12 19:45:51 +01:00
Blockchain : : setStaticChain ( nullptr , 0 , " " ) ;
2021-05-27 18:40:58 +02:00
SetMockTime ( 0 ) ;
}
void TestP2PBlockchain : : basics ( )
{
2025-02-08 19:05:26 +01:00
boost : : asio : : io_context ioContext ;
2021-05-27 18:40:58 +02:00
boost : : filesystem : : path basedir ( m_tmpPath . toStdString ( ) ) ;
2025-02-08 19:05:26 +01:00
DownloadManager dlm ( ioContext , basedir , P2PNet : : MainChain ) ;
2021-05-27 18:40:58 +02:00
Blockchain blockchain ( & dlm , basedir , P2PNet : : MainChain ) ;
// empty, no blocks other than genesis
QCOMPARE ( blockchain . height ( ) , 0 ) ;
const auto genesis = uint256S ( genesisHash ) ;
QCOMPARE ( blockchain . block ( 0 ) . createHash ( ) , genesis ) ;
QVERIFY ( blockchain . isKnown ( genesis ) ) ;
QCOMPARE ( blockchain . blockHeightFor ( genesis ) , 0 ) ;
}
void TestP2PBlockchain : : staticChain ( )
{
2021-08-09 21:26:07 +02:00
QByteArray bytes ;
prepareStaticFile ( bytes ) ;
2021-05-27 18:40:58 +02:00
// support
SetMockTime ( 1232000000 ) ;
2025-02-08 19:05:26 +01:00
boost : : asio : : io_context ioContext ;
2021-05-27 18:40:58 +02:00
boost : : filesystem : : path basedir ( m_tmpPath . toStdString ( ) ) ;
2025-02-08 19:05:26 +01:00
DownloadManager dlm ( ioContext , basedir , P2PNet : : MainChain ) ;
2021-05-27 18:40:58 +02:00
// First just load only the static stuff.
{
Blockchain blockchain ( & dlm , basedir , P2PNet : : MainChain ) ;
QCOMPARE ( blockchain . height ( ) , 99 ) ;
QCOMPARE ( blockchain . block ( 99 ) . createHash ( ) , uint256S ( " 00000000cd9b12643e6854cb25939b39cd7a1ad0af31a9bd8b2efe67854b1995 " ) ) ; // block at height 99 on mainchain
2021-05-28 14:52:27 +02:00
QCOMPARE ( blockchain . blockHeightFor ( uint256S ( " 00000000cd9b12643e6854cb25939b39cd7a1ad0af31a9bd8b2efe67854b1995 " ) ) , 99 ) ;
2021-05-27 18:40:58 +02:00
QCOMPARE ( blockchain . expectedBlockHeight ( ) , 665 ) ;
2024-05-28 10:20:42 +02:00
auto dat = blockchain . dataSources ( ) ;
QCOMPARE ( dat . size ( ) , 1 ) ;
auto source = dat . at ( 0 ) ;
QCOMPARE ( source . source , Blockchain : : StaticHeadersSource ) ;
QCOMPARE ( source . startBlock , 0 ) ;
QCOMPARE ( source . endBlock , 99 ) ;
2021-05-27 18:40:58 +02:00
}
const QString dest ( m_tmpPath + " /blockchain " ) ;
QFile : : remove ( dest ) ;
2022-11-13 15:53:51 +01:00
// The static chain and the blockchain have the same blocks, make sure
// we are not seeing any confusion.
2021-05-27 18:40:58 +02:00
QVERIFY ( QFile : : copy ( QString ( " %1/headers0-99 " ) . arg ( SRCDIR ) , dest ) ) ;
{
Blockchain blockchain ( & dlm , basedir , P2PNet : : MainChain ) ;
QCOMPARE ( blockchain . height ( ) , 99 ) ;
QCOMPARE ( blockchain . block ( 99 ) . createHash ( ) , uint256S ( " 00000000cd9b12643e6854cb25939b39cd7a1ad0af31a9bd8b2efe67854b1995 " ) ) ; // block at height 99 on mainchain
2021-05-28 14:52:27 +02:00
QCOMPARE ( blockchain . blockHeightFor ( uint256S ( " 00000000cd9b12643e6854cb25939b39cd7a1ad0af31a9bd8b2efe67854b1995 " ) ) , 99 ) ;
2021-05-27 18:40:58 +02:00
QCOMPARE ( blockchain . expectedBlockHeight ( ) , 665 ) ;
2024-05-28 10:20:42 +02:00
auto dat = blockchain . dataSources ( ) ;
QCOMPARE ( dat . size ( ) , 1 ) ;
auto source = dat . at ( 0 ) ;
QCOMPARE ( source . source , Blockchain : : StaticHeadersSource ) ;
QCOMPARE ( source . startBlock , 0 ) ;
QCOMPARE ( source . endBlock , 99 ) ;
2021-05-27 18:40:58 +02:00
}
// Now follow the static load with a nicely fitting one
QFile : : remove ( dest ) ;
2023-10-04 19:22:17 +02:00
QFile : : remove ( dest + " .info " ) ;
2021-05-27 18:40:58 +02:00
QVERIFY ( QFile : : copy ( QString ( " %1/headers100-111 " ) . arg ( SRCDIR ) , dest ) ) ;
{
Blockchain blockchain ( & dlm , basedir , P2PNet : : MainChain ) ;
QCOMPARE ( blockchain . height ( ) , 111 ) ;
QCOMPARE ( blockchain . block ( 99 ) . createHash ( ) , uint256S ( " 00000000cd9b12643e6854cb25939b39cd7a1ad0af31a9bd8b2efe67854b1995 " ) ) ;
2021-05-28 14:52:27 +02:00
QCOMPARE ( blockchain . blockHeightFor ( uint256S ( " 00000000cd9b12643e6854cb25939b39cd7a1ad0af31a9bd8b2efe67854b1995 " ) ) , 99 ) ;
2021-05-27 18:40:58 +02:00
QCOMPARE ( blockchain . block ( 111 ) . createHash ( ) , uint256S ( " 000000004d6a6dd8b882deec7b54421949dddd2c166bd51ee7f62a52091a6c35 " ) ) ;
2021-05-28 14:52:27 +02:00
QCOMPARE ( blockchain . blockHeightFor ( uint256S ( " 000000004d6a6dd8b882deec7b54421949dddd2c166bd51ee7f62a52091a6c35 " ) ) , 111 ) ;
2021-05-27 18:40:58 +02:00
QCOMPARE ( blockchain . expectedBlockHeight ( ) , 662 ) ;
2024-05-28 10:20:42 +02:00
auto dat = blockchain . dataSources ( ) ;
QCOMPARE ( dat . size ( ) , 2 ) ;
auto source = dat . at ( 0 ) ;
QCOMPARE ( source . source , Blockchain : : StaticHeadersSource ) ;
QCOMPARE ( source . startBlock , 0 ) ;
QCOMPARE ( source . endBlock , 99 ) ;
source = dat . at ( 1 ) ;
QCOMPARE ( source . source , Blockchain : : DataFileSource ) ;
QCOMPARE ( source . startBlock , 100 ) ;
QCOMPARE ( source . endBlock , 111 ) ;
2021-05-27 18:40:58 +02:00
}
2022-11-13 15:53:51 +01:00
// ensure that we didn't save anything.
QVERIFY ( ! QFile : : exists ( dest + " 1 " ) ) ;
2021-05-27 18:40:58 +02:00
// Now follow the static load with one that slightly overlaps
QFile : : remove ( dest ) ;
2023-10-04 19:22:17 +02:00
QFile : : remove ( dest + " .info " ) ;
2021-05-27 18:40:58 +02:00
QVERIFY ( QFile : : copy ( QString ( " %1/headers91-104 " ) . arg ( SRCDIR ) , dest ) ) ;
{
Blockchain blockchain ( & dlm , basedir , P2PNet : : MainChain ) ;
QCOMPARE ( blockchain . height ( ) , 104 ) ;
QCOMPARE ( blockchain . block ( 99 ) . createHash ( ) , uint256S ( " 00000000cd9b12643e6854cb25939b39cd7a1ad0af31a9bd8b2efe67854b1995 " ) ) ;
2021-05-28 14:52:27 +02:00
QCOMPARE ( blockchain . blockHeightFor ( uint256S ( " 00000000cd9b12643e6854cb25939b39cd7a1ad0af31a9bd8b2efe67854b1995 " ) ) , 99 ) ;
2021-05-27 18:40:58 +02:00
QCOMPARE ( blockchain . block ( 104 ) . createHash ( ) , uint256S ( " 00000000fb11ef25014e02b315285a22f80c8f97689d7e36d723317defaabe5b " ) ) ;
2021-05-28 14:52:27 +02:00
QCOMPARE ( blockchain . blockHeightFor ( uint256S ( " 00000000fb11ef25014e02b315285a22f80c8f97689d7e36d723317defaabe5b " ) ) , 104 ) ;
2021-05-27 18:40:58 +02:00
QCOMPARE ( blockchain . expectedBlockHeight ( ) , 664 ) ;
2024-05-28 10:20:42 +02:00
auto dat = blockchain . dataSources ( ) ;
QCOMPARE ( dat . size ( ) , 2 ) ;
auto source = dat . at ( 0 ) ;
QCOMPARE ( source . source , Blockchain : : StaticHeadersSource ) ;
QCOMPARE ( source . startBlock , 0 ) ;
QCOMPARE ( source . endBlock , 99 ) ;
source = dat . at ( 1 ) ;
QCOMPARE ( source . source , Blockchain : : DataFileSource ) ;
QCOMPARE ( source . startBlock , 100 ) ;
QCOMPARE ( source . endBlock , 104 ) ;
2021-05-27 18:40:58 +02:00
}
2022-11-13 15:53:51 +01:00
// ensure that we didn't save anything.
QVERIFY ( ! QFile : : exists ( dest + " 1 " ) ) ;
2021-05-27 18:40:58 +02:00
#if 0
{
QFile out("headers0-99");
if (!out.open(QIODevice::WriteOnly))
logFatal() << "failed to write file";
for (int i = 0; i <= 99; ++i) {
BlockHeader bh = blockchain.block(i);
out.write(reinterpret_cast<const char*>(&bh), 80);
}
}
#endif
}
2022-11-13 15:53:51 +01:00
void TestP2PBlockchain : : staticChain2 ( )
{
QByteArray bytes ;
prepareStaticFile ( bytes ) ;
// support
SetMockTime ( 1232000000 ) ;
2025-02-08 19:05:26 +01:00
boost : : asio : : io_context ioContext ;
2022-11-13 15:53:51 +01:00
boost : : filesystem : : path basedir ( m_tmpPath . toStdString ( ) ) ;
2025-02-08 19:05:26 +01:00
DownloadManager dlm ( ioContext , basedir , P2PNet : : MainChain ) ;
2022-11-13 15:53:51 +01:00
auto moreHeaders = QFile ( QString ( " %1/headers100-111 " ) . arg ( SRCDIR ) ) ;
QVERIFY ( moreHeaders . open ( QIODevice : : ReadOnly ) ) ;
Streaming : : BufferPool pool ;
for ( int i = 100 ; i < = 111 ; + + i ) {
2023-10-16 12:29:45 +02:00
pool . reserve ( 82 ) ;
2022-11-13 15:53:51 +01:00
pool . data ( ) [ 0 ] = 1 ;
pool . markUsed ( 1 ) ;
auto readSize = moreHeaders . read ( pool . data ( ) , 80 ) ;
QVERIFY ( readSize = = 80 ) ;
2023-10-16 12:29:45 +02:00
pool . markUsed ( readSize ) ;
pool . data ( ) [ 81 ] = 0 ;
2022-11-13 15:53:51 +01:00
Blockchain blockchain ( & dlm , basedir , P2PNet : : MainChain ) ;
QCOMPARE ( blockchain . height ( ) , i - 1 ) ;
QCOMPARE ( blockchain . block ( 99 ) . createHash ( ) , uint256S ( " 00000000cd9b12643e6854cb25939b39cd7a1ad0af31a9bd8b2efe67854b1995 " ) ) ; // block at height 99 on mainchain
QCOMPARE ( blockchain . blockHeightFor ( uint256S ( " 00000000cd9b12643e6854cb25939b39cd7a1ad0af31a9bd8b2efe67854b1995 " ) ) , 99 ) ;
// add one header.
2023-10-16 12:29:45 +02:00
blockchain . processBlockHeaders ( Message ( pool . commit ( 1 ) , 1 ) , 1 ) ;
2022-11-13 15:53:51 +01:00
QCOMPARE ( blockchain . height ( ) , i ) ;
if ( i > = 104 ) {
QCOMPARE ( blockchain . block ( 104 ) . createHash ( ) , uint256S ( " 00000000fb11ef25014e02b315285a22f80c8f97689d7e36d723317defaabe5b " ) ) ;
QCOMPARE ( blockchain . blockHeightFor ( uint256S ( " 00000000fb11ef25014e02b315285a22f80c8f97689d7e36d723317defaabe5b " ) ) , 104 ) ;
}
blockchain . save ( ) ;
2024-05-28 10:20:42 +02:00
auto dat = blockchain . dataSources ( ) ;
QCOMPARE ( dat . size ( ) , 2 ) ;
auto source = dat . at ( 0 ) ;
QCOMPARE ( source . source , Blockchain : : StaticHeadersSource ) ;
QCOMPARE ( source . startBlock , 0 ) ;
QCOMPARE ( source . endBlock , 99 ) ;
source = dat . at ( 1 ) ;
QCOMPARE ( source . source , Blockchain : : DataFileSource ) ;
QCOMPARE ( source . startBlock , 100 ) ;
QCOMPARE ( source . endBlock , i ) ;
2022-11-13 15:53:51 +01:00
}
}
2021-05-28 14:52:27 +02:00
void TestP2PBlockchain : : blockHeightAtTime ( )
{
2025-02-08 19:05:26 +01:00
boost : : asio : : io_context ioContext ;
2021-05-28 14:52:27 +02:00
boost : : filesystem : : path basedir ( m_tmpPath . toStdString ( ) ) ;
2025-02-08 19:05:26 +01:00
DownloadManager dlm ( ioContext , basedir , P2PNet : : MainChain ) ;
2021-08-09 21:26:07 +02:00
QByteArray bytes ;
prepareStaticFile ( bytes ) ;
2021-05-28 14:52:27 +02:00
2023-06-14 16:51:23 +02:00
// block at height 80 is mined at: 1231646077
// asking for all timestamps until block 81 is mined (nearly 6 minutes later)
// should return blockheight 80.
2021-05-28 14:52:27 +02:00
{
Blockchain blockchain ( & dlm , basedir , P2PNet : : MainChain ) ;
2023-06-14 16:51:23 +02:00
QCOMPARE ( blockchain . blockHeightAtTime ( 1231646077 ) , 80 ) ;
QCOMPARE ( blockchain . blockHeightAtTime ( 1231646078 ) , 80 ) ;
QCOMPARE ( blockchain . blockHeightAtTime ( 1231646400 ) , 80 ) ;
2021-05-28 14:52:27 +02:00
}
// block 101 is mined at 1231661741
// block 102 is mined at 1231662670
QVERIFY ( QFile : : copy ( QString ( " %1/headers100-111 " ) . arg ( SRCDIR ) , m_tmpPath + " /blockchain " ) ) ;
{
Blockchain blockchain ( & dlm , basedir , P2PNet : : MainChain ) ;
QCOMPARE ( blockchain . height ( ) , 111 ) ;
2023-06-14 16:51:23 +02:00
QCOMPARE ( blockchain . blockHeightAtTime ( 1231646080 ) , 80 ) ;
QCOMPARE ( blockchain . blockHeightAtTime ( 1231662000 ) , 101 ) ;
QCOMPARE ( blockchain . blockHeightAtTime ( 1800000000 ) , 111 ) ;
2021-05-28 14:52:27 +02:00
}
}
2023-10-09 11:32:00 +02:00
void TestP2PBlockchain : : startAtCheckpoint ( )
{
QByteArray bytes ;
2024-07-06 21:50:48 +02:00
prepareStaticFile ( bytes , " headers-295000-295020 " ) ;
2025-02-08 19:05:26 +01:00
boost : : asio : : io_context ioContext ;
2023-10-09 11:32:00 +02:00
boost : : filesystem : : path basedir ( m_tmpPath . toStdString ( ) ) ;
2025-02-08 19:05:26 +01:00
DownloadManager dlm ( ioContext , basedir , P2PNet : : MainChain ) ;
2023-10-09 11:32:00 +02:00
{
Blockchain blockchain ( & dlm , basedir , P2PNet : : MainChain ) ;
2024-07-06 21:50:48 +02:00
QCOMPARE ( blockchain . height ( ) , 295020 ) ;
logFatal ( ) < < blockchain . block ( 295000 ) . createHash ( ) ;
logFatal ( ) < < blockchain . block ( 295010 ) . createHash ( ) ;
logFatal ( ) < < blockchain . block ( 295020 ) . createHash ( ) ;
QCOMPARE ( blockchain . block ( 295000 ) . createHash ( ) , uint256S ( " 4d9b4ef50f0f9d686fd69db2e03af35a100370c64632a983 " ) ) ;
QCOMPARE ( blockchain . blockHeightFor ( uint256S ( " 4d9b4ef50f0f9d686fd69db2e03af35a100370c64632a983 " ) ) , 295000 ) ;
QCOMPARE ( blockchain . block ( 295010 ) . createHash ( ) , uint256S ( " a6b67d5c5bd85bf8d3fe11212211e1d8c8b43961ac04c01 " ) ) ;
QCOMPARE ( blockchain . blockHeightFor ( uint256S ( " a6b67d5c5bd85bf8d3fe11212211e1d8c8b43961ac04c01 " ) ) , 295010 ) ;
QCOMPARE ( blockchain . block ( 295020 ) . createHash ( ) , uint256S ( " ca07ade2023489b5de067b1262f1d5fd738de28dcda1af0 " ) ) ;
QCOMPARE ( blockchain . blockHeightFor ( uint256S ( " ca07ade2023489b5de067b1262f1d5fd738de28dcda1af0 " ) ) , 295020 ) ;
2023-10-09 11:32:00 +02:00
auto g = blockchain . block ( 0 ) ;
2023-10-16 12:29:45 +02:00
Q_UNUSED ( g ) ;
2023-10-09 11:32:00 +02:00
try {
auto b = blockchain . block ( 10 ) ;
2023-10-16 12:29:45 +02:00
Q_UNUSED ( b ) ;
2023-10-09 11:32:00 +02:00
QFAIL ( " Expected exception on fetch non existing block " ) ;
} catch ( . . . ) { }
2024-05-28 10:20:42 +02:00
auto dat = blockchain . dataSources ( ) ;
QCOMPARE ( dat . size ( ) , 1 ) ;
auto source = dat . at ( 0 ) ;
QCOMPARE ( source . source , Blockchain : : StaticHeadersSource ) ;
2024-07-06 21:50:48 +02:00
QCOMPARE ( source . startBlock , 295000 ) ;
QCOMPARE ( source . endBlock , 295020 ) ;
2023-10-09 11:32:00 +02:00
}
// split our static headers. Making sure there is some overlap between them.
QCOMPARE ( bytes . size ( ) , 1680 ) ; // 21 blocks.
QFile blks ( m_tmpPath + " /blockchain " ) ;
QVERIFY ( blks . open ( QIODevice : : WriteOnly ) ) ;
blks . write ( bytes . mid ( 800 ) ) ; // last 11 blocks
blks . close ( ) ;
QFile staticHeaders ( m_tmpPath + " /staticHeaders " ) ;
QVERIFY ( staticHeaders . open ( QIODevice : : WriteOnly ) ) ;
bytes = bytes . mid ( 0 , 1200 ) ; // first 15 blocks
staticHeaders . write ( bytes ) ;
staticHeaders . close ( ) ;
// create info file for new staticHeaders
QFile : : remove ( m_tmpPath + " /staticHeaders.info " ) ;
std : : string info = staticHeaders . fileName ( ) . toStdString ( ) + " .info " ;
Blockchain : : createStaticHeaders ( staticHeaders . fileName ( ) . toStdString ( ) , info ) ;
Blockchain : : setStaticChain ( reinterpret_cast < const uint8_t * > ( bytes . constData ( ) ) , bytes . size ( ) , info ) ;
{
2023-10-16 12:29:45 +02:00
// loading now should load the staticHeaders file which extends
// a checkpoint at 279000. The static file covers 15 blocks (279000-279014 inc).
2023-10-09 11:32:00 +02:00
// Then it should load the blockchain file which overlaps the
2023-10-16 12:29:45 +02:00
// static one and has 6 additional blocks (15 - 20 inc).
2023-10-09 11:32:00 +02:00
Blockchain blockchain ( & dlm , basedir , P2PNet : : MainChain ) ;
2024-07-06 21:50:48 +02:00
QCOMPARE ( blockchain . height ( ) , 295020 ) ;
QCOMPARE ( blockchain . block ( 295000 ) . createHash ( ) , uint256S ( " 4d9b4ef50f0f9d686fd69db2e03af35a100370c64632a983 " ) ) ;
QCOMPARE ( blockchain . blockHeightFor ( uint256S ( " 4d9b4ef50f0f9d686fd69db2e03af35a100370c64632a983 " ) ) , 295000 ) ;
QCOMPARE ( blockchain . block ( 295010 ) . createHash ( ) , uint256S ( " a6b67d5c5bd85bf8d3fe11212211e1d8c8b43961ac04c01 " ) ) ;
QCOMPARE ( blockchain . blockHeightFor ( uint256S ( " a6b67d5c5bd85bf8d3fe11212211e1d8c8b43961ac04c01 " ) ) , 295010 ) ;
QCOMPARE ( blockchain . block ( 295020 ) . createHash ( ) , uint256S ( " ca07ade2023489b5de067b1262f1d5fd738de28dcda1af0 " ) ) ;
QCOMPARE ( blockchain . blockHeightFor ( uint256S ( " ca07ade2023489b5de067b1262f1d5fd738de28dcda1af0 " ) ) , 295020 ) ;
2023-10-09 11:32:00 +02:00
auto g = blockchain . block ( 0 ) ;
2023-10-16 12:29:45 +02:00
Q_UNUSED ( g ) ;
2023-10-09 11:32:00 +02:00
try {
auto b = blockchain . block ( 10 ) ;
2023-10-16 12:29:45 +02:00
Q_UNUSED ( b ) ;
2023-10-09 11:32:00 +02:00
QFAIL ( " Expected exception on fetch non existing block " ) ;
} catch ( . . . ) { }
2024-05-28 10:20:42 +02:00
auto dat = blockchain . dataSources ( ) ;
QCOMPARE ( dat . size ( ) , 2 ) ;
auto source = dat . at ( 0 ) ;
QCOMPARE ( source . source , Blockchain : : StaticHeadersSource ) ;
2024-07-06 21:50:48 +02:00
QCOMPARE ( source . startBlock , 295000 ) ;
QCOMPARE ( source . endBlock , 295014 ) ;
2024-05-28 10:20:42 +02:00
source = dat . at ( 1 ) ;
QCOMPARE ( source . source , Blockchain : : DataFileSource ) ;
2024-07-06 21:50:48 +02:00
QCOMPARE ( source . startBlock , 295015 ) ;
QCOMPARE ( source . endBlock , 295020 ) ;
2023-10-09 11:32:00 +02:00
}
// and one more time, now after the .info file has been created for the save file.
{
Blockchain blockchain ( & dlm , basedir , P2PNet : : MainChain ) ;
2024-07-06 21:50:48 +02:00
QCOMPARE ( blockchain . height ( ) , 295020 ) ;
QCOMPARE ( blockchain . block ( 295000 ) . createHash ( ) , uint256S ( " 4d9b4ef50f0f9d686fd69db2e03af35a100370c64632a983 " ) ) ;
QCOMPARE ( blockchain . blockHeightFor ( uint256S ( " 4d9b4ef50f0f9d686fd69db2e03af35a100370c64632a983 " ) ) , 295000 ) ;
QCOMPARE ( blockchain . block ( 295010 ) . createHash ( ) , uint256S ( " a6b67d5c5bd85bf8d3fe11212211e1d8c8b43961ac04c01 " ) ) ;
QCOMPARE ( blockchain . blockHeightFor ( uint256S ( " a6b67d5c5bd85bf8d3fe11212211e1d8c8b43961ac04c01 " ) ) , 295010 ) ;
QCOMPARE ( blockchain . block ( 295020 ) . createHash ( ) , uint256S ( " ca07ade2023489b5de067b1262f1d5fd738de28dcda1af0 " ) ) ;
QCOMPARE ( blockchain . blockHeightFor ( uint256S ( " ca07ade2023489b5de067b1262f1d5fd738de28dcda1af0 " ) ) , 295020 ) ;
2023-10-09 11:32:00 +02:00
auto g = blockchain . block ( 0 ) ;
2023-10-16 12:29:45 +02:00
Q_UNUSED ( g ) ;
2023-10-09 11:32:00 +02:00
try {
auto b = blockchain . block ( 10 ) ;
2023-10-16 12:29:45 +02:00
Q_UNUSED ( b ) ;
2023-10-09 11:32:00 +02:00
QFAIL ( " Expected exception on fetch non existing block " ) ;
} catch ( . . . ) { }
}
// avoid loading the file in the constructor.
QFile : : remove ( blks . fileName ( ) + " .info " ) ;
blks . rename ( m_tmpPath + " /blocks " ) ;
{
Blockchain blockchain ( & dlm , basedir , P2PNet : : MainChain ) ;
2024-07-06 21:50:48 +02:00
QCOMPARE ( blockchain . height ( ) , 295014 ) ;
2023-10-09 11:32:00 +02:00
}
QVERIFY ( blks . open ( QIODevice : : ReadOnly ) ) ;
Streaming : : BufferPool pool ;
for ( int i = 0 ; i < 11 ; + + i ) {
2023-10-16 12:29:45 +02:00
pool . reserve ( 82 ) ;
2023-10-09 11:32:00 +02:00
pool . data ( ) [ 0 ] = 1 ;
pool . markUsed ( 1 ) ;
auto readSize = blks . read ( pool . data ( ) , 80 ) ;
QVERIFY ( readSize = = 80 ) ;
2023-10-16 12:29:45 +02:00
pool . markUsed ( readSize ) ;
pool . data ( ) [ 81 ] = 0 ;
2023-10-09 11:32:00 +02:00
Blockchain blockchain ( & dlm , basedir , P2PNet : : MainChain ) ;
2024-07-06 21:50:48 +02:00
QCOMPARE ( blockchain . height ( ) , 295014 + ( std : : max ( 0 , i - 5 ) ) ) ;
2023-10-09 11:32:00 +02:00
// add one header.
2023-10-16 12:29:45 +02:00
blockchain . processBlockHeaders ( Message ( pool . commit ( 1 ) , 1 ) , 1 ) ;
2024-07-06 21:50:48 +02:00
QCOMPARE ( blockchain . height ( ) , 295014 + ( std : : max ( 0 , i - 4 ) ) ) ;
QCOMPARE ( blockchain . block ( 295000 ) . createHash ( ) , uint256S ( " 4d9b4ef50f0f9d686fd69db2e03af35a100370c64632a983 " ) ) ;
2023-10-09 11:32:00 +02:00
blockchain . save ( ) ;
2024-05-28 10:20:42 +02:00
auto dat = blockchain . dataSources ( ) ;
QCOMPARE ( dat . size ( ) , i < = 4 ? 1 : 2 ) ;
auto source = dat . at ( 0 ) ;
QCOMPARE ( source . source , Blockchain : : StaticHeadersSource ) ;
2024-07-06 21:50:48 +02:00
QCOMPARE ( source . startBlock , 295000 ) ;
QCOMPARE ( source . endBlock , 295014 ) ;
2024-05-28 10:20:42 +02:00
if ( i > 4 ) {
source = dat . at ( 1 ) ;
QCOMPARE ( source . source , Blockchain : : DataFileSource ) ;
2024-07-06 21:50:48 +02:00
QCOMPARE ( source . startBlock , 295015 ) ;
2024-05-28 10:20:42 +02:00
QCOMPARE ( source . endBlock , blockchain . height ( ) ) ;
}
2023-10-09 11:32:00 +02:00
}
}
void TestP2PBlockchain : : prepareStaticFile ( QByteArray & bytes , const char * filename )
2021-05-28 14:52:27 +02:00
{
// we copy our static data from a file, more flexible.
// Suggestion for real apps is to use something like QResource.
2023-10-09 11:32:00 +02:00
static const char * first100headers = " headers0-99 " ;
if ( filename = = nullptr )
filename = first100headers ;
QFile staticHeaders ( QString ( " %1/%2 " ) . arg ( SRCDIR , filename ) ) ;
2023-09-13 12:02:51 +02:00
std : : string info = ( m_tmpPath + " /staticHeaders.info " ) . toStdString ( ) ;
2022-01-12 19:45:51 +01:00
boost : : system : : error_code error ;
boost : : filesystem : : create_directories ( m_tmpPath . toStdString ( ) , error ) ;
Blockchain : : createStaticHeaders ( staticHeaders . fileName ( ) . toStdString ( ) , info ) ;
2021-08-09 21:26:07 +02:00
bool readOk = staticHeaders . open ( QIODevice : : ReadOnly ) ;
assert ( readOk ) ;
bytes = staticHeaders . readAll ( ) ;
2022-01-12 19:45:51 +01:00
Blockchain : : setStaticChain ( reinterpret_cast < const uint8_t * > ( bytes . constData ( ) ) , bytes . size ( ) , info ) ;
2021-05-28 14:52:27 +02:00
}
2021-05-27 18:40:58 +02:00
QTEST_MAIN ( TestP2PBlockchain )