diff --git a/configure.ac b/configure.ac index 1e531f6d78..3ce06c4584 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ AC_PREREQ([2.69]) define(_CLIENT_VERSION_MAJOR, 28) define(_CLIENT_VERSION_MINOR, 0) define(_CLIENT_VERSION_BUILD, 0) -define(_CLIENT_VERSION_RC, 1) +define(_CLIENT_VERSION_RC, 2) define(_CLIENT_VERSION_IS_RELEASE, true) define(_COPYRIGHT_YEAR, 2024) define(_COPYRIGHT_HOLDERS,[The %s developers]) diff --git a/doc/man/namecoin-cli.1 b/doc/man/namecoin-cli.1 index 1eb479c25b..f4e346223b 100644 --- a/doc/man/namecoin-cli.1 +++ b/doc/man/namecoin-cli.1 @@ -1,7 +1,7 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.1. -.TH NAMECOIN-CLI "1" "September 2024" "namecoin-cli v28.0.0rc1" "User Commands" +.TH NAMECOIN-CLI "1" "September 2024" "namecoin-cli v28.0.0rc2" "User Commands" .SH NAME -namecoin-cli \- manual page for namecoin-cli v28.0.0rc1 +namecoin-cli \- manual page for namecoin-cli v28.0.0rc2 .SH SYNOPSIS .B namecoin-cli [\fI\,options\/\fR] \fI\, \/\fR[\fI\,params\/\fR] \fI\,Send command to Namecoin Core\/\fR @@ -15,7 +15,7 @@ namecoin-cli \- manual page for namecoin-cli v28.0.0rc1 .B namecoin-cli [\fI\,options\/\fR] \fI\,help Get help for a command\/\fR .SH DESCRIPTION -Namecoin Core RPC client version v28.0.0rc1 +Namecoin Core RPC client version v28.0.0rc2 .SH OPTIONS .HP \-? diff --git a/doc/man/namecoin-qt.1 b/doc/man/namecoin-qt.1 index f3151f466b..255bb0ff53 100644 --- a/doc/man/namecoin-qt.1 +++ b/doc/man/namecoin-qt.1 @@ -1,12 +1,12 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.1. -.TH NAMECOIN-QT "1" "September 2024" "namecoin-qt v28.0.0rc1" "User Commands" +.TH NAMECOIN-QT "1" "September 2024" "namecoin-qt v28.0.0rc2" "User Commands" .SH NAME -namecoin-qt \- manual page for namecoin-qt v28.0.0rc1 +namecoin-qt \- manual page for namecoin-qt v28.0.0rc2 .SH SYNOPSIS .B namecoin-qt [\fI\,command-line options\/\fR] [\fI\,URI\/\fR] .SH DESCRIPTION -Namecoin Core version v28.0.0rc1 +Namecoin Core version v28.0.0rc2 .PP Optional URI is a Namecoin address in BIP21 URI format. .SH OPTIONS diff --git a/doc/man/namecoin-tx.1 b/doc/man/namecoin-tx.1 index 20f2cc0cd2..cccfb3e399 100644 --- a/doc/man/namecoin-tx.1 +++ b/doc/man/namecoin-tx.1 @@ -1,7 +1,7 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.1. -.TH NAMECOIN-TX "1" "September 2024" "namecoin-tx v28.0.0rc1" "User Commands" +.TH NAMECOIN-TX "1" "September 2024" "namecoin-tx v28.0.0rc2" "User Commands" .SH NAME -namecoin-tx \- manual page for namecoin-tx v28.0.0rc1 +namecoin-tx \- manual page for namecoin-tx v28.0.0rc2 .SH SYNOPSIS .B namecoin-tx [\fI\,options\/\fR] \fI\, \/\fR[\fI\,commands\/\fR] \fI\,Update hex-encoded transaction\/\fR @@ -9,7 +9,7 @@ namecoin-tx \- manual page for namecoin-tx v28.0.0rc1 .B namecoin-tx [\fI\,options\/\fR] \fI\,-create \/\fR[\fI\,commands\/\fR] \fI\,Create hex-encoded transaction\/\fR .SH DESCRIPTION -Namecoin Core namecoin\-tx utility version v28.0.0rc1 +Namecoin Core namecoin\-tx utility version v28.0.0rc2 .SH OPTIONS .HP \-? diff --git a/doc/man/namecoin-util.1 b/doc/man/namecoin-util.1 index 9cb710082f..b633e84588 100644 --- a/doc/man/namecoin-util.1 +++ b/doc/man/namecoin-util.1 @@ -1,12 +1,12 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.1. -.TH NAMECOIN-UTIL "1" "September 2024" "namecoin-util v28.0.0rc1" "User Commands" +.TH NAMECOIN-UTIL "1" "September 2024" "namecoin-util v28.0.0rc2" "User Commands" .SH NAME -namecoin-util \- manual page for namecoin-util v28.0.0rc1 +namecoin-util \- manual page for namecoin-util v28.0.0rc2 .SH SYNOPSIS .B bitcoin-util [\fI\,options\/\fR] [\fI\,commands\/\fR] \fI\,Do stuff\/\fR .SH DESCRIPTION -Namecoin Core bitcoin\-util utility version v28.0.0rc1 +Namecoin Core bitcoin\-util utility version v28.0.0rc2 .SH OPTIONS .HP \-? diff --git a/doc/man/namecoin-wallet.1 b/doc/man/namecoin-wallet.1 index 68f00d8f88..7857743f6c 100644 --- a/doc/man/namecoin-wallet.1 +++ b/doc/man/namecoin-wallet.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.1. -.TH NAMECOIN-WALLET "1" "September 2024" "namecoin-wallet v28.0.0rc1" "User Commands" +.TH NAMECOIN-WALLET "1" "September 2024" "namecoin-wallet v28.0.0rc2" "User Commands" .SH NAME -namecoin-wallet \- manual page for namecoin-wallet v28.0.0rc1 +namecoin-wallet \- manual page for namecoin-wallet v28.0.0rc2 .SH DESCRIPTION -Namecoin Core namecoin\-wallet version v28.0.0rc1 +Namecoin Core namecoin\-wallet version v28.0.0rc2 .PP namecoin\-wallet is an offline tool for creating and interacting with Namecoin Core wallet files. By default namecoin\-wallet will act on wallets in the default mainnet wallet directory in the datadir. diff --git a/doc/man/namecoind.1 b/doc/man/namecoind.1 index 0651aa4394..baea5c896b 100644 --- a/doc/man/namecoind.1 +++ b/doc/man/namecoind.1 @@ -1,12 +1,12 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.1. -.TH NAMECOIND "1" "September 2024" "namecoind v28.0.0rc1" "User Commands" +.TH NAMECOIND "1" "September 2024" "namecoind v28.0.0rc2" "User Commands" .SH NAME -namecoind \- manual page for namecoind v28.0.0rc1 +namecoind \- manual page for namecoind v28.0.0rc2 .SH SYNOPSIS .B namecoind [\fI\,options\/\fR] \fI\,Start Namecoin Core\/\fR .SH DESCRIPTION -Namecoin Core version v28.0.0rc1 +Namecoin Core version v28.0.0rc2 .SH OPTIONS .HP \-? diff --git a/src/addrdb.cpp b/src/addrdb.cpp index e9838d7222..b89141c88e 100644 --- a/src/addrdb.cpp +++ b/src/addrdb.cpp @@ -73,7 +73,7 @@ bool SerializeFileDB(const std::string& prefix, const fs::path& path, const Data remove(pathTmp); return false; } - if (!FileCommit(fileout.Get())) { + if (!fileout.Commit()) { fileout.fclose(); remove(pathTmp); LogError("%s: Failed to flush file %s\n", __func__, fs::PathToString(pathTmp)); diff --git a/src/bench/streams_findbyte.cpp b/src/bench/streams_findbyte.cpp index 5098262e9a..004bf8ffc9 100644 --- a/src/bench/streams_findbyte.cpp +++ b/src/bench/streams_findbyte.cpp @@ -19,7 +19,7 @@ static void FindByte(benchmark::Bench& bench) uint8_t data[file_size] = {0}; data[file_size-1] = 1; file << data; - std::rewind(file.Get()); + file.seek(0, SEEK_SET); BufferedFile bf{file, /*nBufSize=*/file_size + 1, /*nRewindIn=*/file_size}; bench.run([&] { diff --git a/src/index/blockfilterindex.cpp b/src/index/blockfilterindex.cpp index 41bdca9df5..26de7eee32 100644 --- a/src/index/blockfilterindex.cpp +++ b/src/index/blockfilterindex.cpp @@ -151,7 +151,7 @@ bool BlockFilterIndex::CustomCommit(CDBBatch& batch) LogError("%s: Failed to open filter file %d\n", __func__, pos.nFile); return false; } - if (!FileCommit(file.Get())) { + if (!file.Commit()) { LogError("%s: Failed to commit filter file %d\n", __func__, pos.nFile); return false; } @@ -201,11 +201,11 @@ size_t BlockFilterIndex::WriteFilterToDisk(FlatFilePos& pos, const BlockFilter& LogPrintf("%s: Failed to open filter file %d\n", __func__, pos.nFile); return 0; } - if (!TruncateFile(last_file.Get(), pos.nPos)) { + if (!last_file.Truncate(pos.nPos)) { LogPrintf("%s: Failed to truncate filter file %d\n", __func__, pos.nFile); return 0; } - if (!FileCommit(last_file.Get())) { + if (!last_file.Commit()) { LogPrintf("%s: Failed to commit filter file %d\n", __func__, pos.nFile); return 0; } diff --git a/src/index/txindex.cpp b/src/index/txindex.cpp index 80f615ed0e..425a7f00a0 100644 --- a/src/index/txindex.cpp +++ b/src/index/txindex.cpp @@ -87,10 +87,7 @@ bool TxIndex::FindTx(const uint256& tx_hash, uint256& block_hash, CTransactionRe CBlockHeader header; try { file >> header; - if (fseek(file.Get(), postx.nTxOffset, SEEK_CUR)) { - LogError("%s: fseek(...) failed\n", __func__); - return false; - } + file.seek(postx.nTxOffset, SEEK_CUR); file >> TX_WITH_WITNESS(tx); } catch (const std::exception& e) { LogError("%s: Deserialize or I/O error - %s\n", __func__, e.what()); diff --git a/src/init.cpp b/src/init.cpp index c392a963b1..5b0e42cd9e 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1582,7 +1582,12 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) // This is defined and set here instead of inline in validation.h to avoid a hard // dependency between validation and index/base, since the latter is not in // libbitcoinkernel. - chainman.restart_indexes = [&node]() { + chainman.snapshot_download_completed = [&node]() { + if (!node.chainman->m_blockman.IsPruneMode()) { + LogPrintf("[snapshot] re-enabling NODE_NETWORK services\n"); + node.connman->AddLocalServices(NODE_NETWORK); + } + LogPrintf("[snapshot] restarting indexes\n"); // Drain the validation interface queue to ensure that the old indexes @@ -1725,8 +1730,13 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) } } } else { - LogPrintf("Setting NODE_NETWORK on non-prune mode\n"); - nLocalServices = ServiceFlags(nLocalServices | NODE_NETWORK); + // Prior to setting NODE_NETWORK, check if we can provide historical blocks. + if (!WITH_LOCK(chainman.GetMutex(), return chainman.BackgroundSyncInProgress())) { + LogPrintf("Setting NODE_NETWORK on non-prune mode\n"); + nLocalServices = ServiceFlags(nLocalServices | NODE_NETWORK); + } else { + LogPrintf("Running node in NODE_NETWORK_LIMITED mode until snapshot background sync completes\n"); + } } // ********************************************************* Step 11: import blocks diff --git a/src/net.cpp b/src/net.cpp index e1206745a4..05b98d1029 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1789,7 +1789,8 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr&& sock, const bool inbound_onion = std::find(m_onion_binds.begin(), m_onion_binds.end(), addr_bind) != m_onion_binds.end(); // The V2Transport transparently falls back to V1 behavior when an incoming V1 connection is // detected, so use it whenever we signal NODE_P2P_V2. - const bool use_v2transport(nLocalServices & NODE_P2P_V2); + ServiceFlags local_services = GetLocalServices(); + const bool use_v2transport(local_services & NODE_P2P_V2); CNode* pnode = new CNode(id, std::move(sock), @@ -1807,7 +1808,7 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr&& sock, .use_v2transport = use_v2transport, }); pnode->AddRef(); - m_msgproc->InitializeNode(*pnode, nLocalServices); + m_msgproc->InitializeNode(*pnode, local_services); { LOCK(m_nodes_mutex); m_nodes.push_back(pnode); diff --git a/src/net.h b/src/net.h index d086c91d98..3be2d42409 100644 --- a/src/net.h +++ b/src/net.h @@ -1227,6 +1227,11 @@ class CConnman //! that peer during `net_processing.cpp:PushNodeVersion()`. ServiceFlags GetLocalServices() const; + //! Updates the local services that this node advertises to other peers + //! during connection handshake. + void AddLocalServices(ServiceFlags services) { nLocalServices = ServiceFlags(nLocalServices | services); }; + void RemoveLocalServices(ServiceFlags services) { nLocalServices = ServiceFlags(nLocalServices & ~services); } + uint64_t GetMaxOutboundTarget() const EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex); std::chrono::seconds GetMaxOutboundTimeframe() const; @@ -1466,11 +1471,12 @@ class CConnman * This data is replicated in each Peer instance we create. * * This data is not marked const, but after being set it should not - * change. + * change. Unless AssumeUTXO is started, in which case, the peer + * will be limited until the background chain sync finishes. * * \sa Peer::our_services */ - ServiceFlags nLocalServices; + std::atomic nLocalServices; std::unique_ptr semOutbound; std::unique_ptr semAddnode; diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp index f1749f0455..7e73f297d3 100644 --- a/src/node/blockstorage.cpp +++ b/src/node/blockstorage.cpp @@ -683,7 +683,7 @@ bool BlockManager::UndoWriteToDisk(const CBlockUndo& blockundo, FlatFilePos& pos fileout << GetParams().MessageStart() << nSize; // Write undo data - long fileOutPos = ftell(fileout.Get()); + long fileOutPos = fileout.tell(); if (fileOutPos < 0) { LogError("%s: ftell failed\n", __func__); return false; @@ -981,7 +981,7 @@ bool BlockManager::WriteBlockToDisk(const CBlock& block, FlatFilePos& pos) const fileout << GetParams().MessageStart() << nSize; // Write block - long fileOutPos = ftell(fileout.Get()); + long fileOutPos = fileout.tell(); if (fileOutPos < 0) { LogError("%s: ftell failed\n", __func__); return false; diff --git a/src/node/mempool_persist.cpp b/src/node/mempool_persist.cpp index a265c2e12d..ff7de8c64a 100644 --- a/src/node/mempool_persist.cpp +++ b/src/node/mempool_persist.cpp @@ -199,8 +199,8 @@ bool DumpMempool(const CTxMemPool& pool, const fs::path& dump_path, FopenFn mock LogInfo("Writing %d unbroadcast transactions to file.\n", unbroadcast_txids.size()); file << unbroadcast_txids; - if (!skip_file_commit && !FileCommit(file.Get())) - throw std::runtime_error("FileCommit failed"); + if (!skip_file_commit && !file.Commit()) + throw std::runtime_error("Commit failed"); file.fclose(); if (!RenameOver(dump_path + ".new", dump_path)) { throw std::runtime_error("Rename failed"); diff --git a/src/node/utxo_snapshot.cpp b/src/node/utxo_snapshot.cpp index 976421e455..7d589c886b 100644 --- a/src/node/utxo_snapshot.cpp +++ b/src/node/utxo_snapshot.cpp @@ -73,9 +73,11 @@ std::optional ReadSnapshotBaseBlockhash(fs::path chaindir) } afile >> base_blockhash; - if (std::fgetc(afile.Get()) != EOF) { + int64_t position = afile.tell(); + afile.seek(0, SEEK_END); + if (position != afile.tell()) { LogPrintf("[snapshot] warning: unexpected trailing data in %s\n", read_from_str); - } else if (std::ferror(afile.Get())) { + } else if (afile.IsError()) { LogPrintf("[snapshot] warning: i/o error reading %s\n", read_from_str); } return base_blockhash; diff --git a/src/qt/locale/bitcoin_am.ts b/src/qt/locale/bitcoin_am.ts index 2fcf7a1e63..c02049b984 100644 --- a/src/qt/locale/bitcoin_am.ts +++ b/src/qt/locale/bitcoin_am.ts @@ -175,6 +175,10 @@ Signing is only possible with addresses of the type 'legacy'. Wallet encrypted ቦርሳዎ ምስጢር ተደርጓል + + Back + ተመለስ + Wallet to be encrypted ለመመስጠር የተዘጋጀ ዋሌት @@ -253,6 +257,18 @@ Signing is only possible with addresses of the type 'legacy'. Error: %1 ስህተት፥ %1 + + Embedded "%1" + የተከተተ "%1" + + + Default system font "%1" + ነባሪ የስርዓት ቅርጸ-ቁምፊ "%1 + + + Custom… + ብጁ… + Amount መጠን @@ -362,6 +378,14 @@ Signing is only possible with addresses of the type 'legacy'. &Receive &ተቀበል + + &Change Passphrase… + &የይለፍ ቃል ቀይር… + + + Sign messages with your Bitcoin addresses to prove you own them + በእርሶ የተያዙ መሆኑን ለማረጋገጥ በBitcoin አድራሻዎችዎ መልዕክቶችን ይፈርሙ + &File &ፋይል @@ -405,6 +429,14 @@ Signing is only possible with addresses of the type 'legacy'. Close wallet ዋሌት ዝጋ + + Migrate Wallet + ዋሌትዎን ያዛውሩ + + + Migrate a wallet + ዋሌትዎን ያዛውሩ + Wallet Name Label of the input field where the name of the wallet is entered. @@ -422,6 +454,14 @@ Signing is only possible with addresses of the type 'legacy'. %n active connection(s) to Bitcoin network. + + Error creating wallet + ዋሌትዎን ለፍጠር ተሳስተዋል + + + Cannot create new wallet, the software was compiled without sqlite support (required for descriptor wallets) + አዲስ ዋሌት መፍጠር አልተቻለም፣ ሶፍትዌሩ የተቀናበረው ያለ ስኩላይት ድጋፍ ነው (ለገላጭ ዋሌቶች ያስፈልጋል) + Error: %1 ስህተት፥ %1 @@ -484,6 +524,49 @@ Signing is only possible with addresses of the type 'legacy'. (መለያ ስም የለም) + + MigrateWalletActivity + + Migrate wallet + ዋሌት ያዛውሩ + + + Migrating the wallet will convert this wallet to one or more descriptor wallets. A new wallet backup will need to be made. +If this wallet contains any watchonly scripts, a new wallet will be created which contains those watchonly scripts. +If this wallet contains any solvable but not watched scripts, a different and new wallet will be created which contains those scripts. + +The migration process will create a backup of the wallet before migrating. This backup file will be named <wallet name>-<timestamp>.legacy.bak and can be found in the directory for this wallet. In the event of an incorrect migration, the backup can be restored with the "Restore Wallet" functionality. + ዋሌትን ማዛወር ይህንን ዋሌት አንድ ወይም ከዚያ በላይ ወደሆነ ገላጭ ዋሌቶች ይቀይረዋል።አዲስ ዋሌት ማዘጋጀት ያስፈልጋል ።ይህ ዋሌት ምንም ዓይነት የመመልከት ብቻ ስክሪፕቶችን የያዘ ከሆነ፣እነዚያን የመመልከት ብቻ ስክሪፕቶችን የያዘ አዲስ ዋሌት ይፈጠራል።ይህ ዋሌት ሊፈቱ የሚችሉ ነገር ግን የመመልከት ብቻ ያልሆኑ ስክሪፕቶችን የያዘ ከሆነ ፣ እነዚህን የያዘ አዲስ እና ልዩ የሆነ ዋሌት ይፈጠራል ።የማዛወር ሂደቱ ማዘዋወር ከመፈጸሙ በፊት የነዚህን ዋሌቶች መጠባበቂያ ቅጂ ይይዛል።ይህ መጠባበቂያ ቅጂ 1-2 legacy.bak ተብሎ ተሰይሞ በዋሌቱ ማውጫ ውስጥ ይገኛል።የተሳሳተ ዝውውር በሚከሰትበት ጊዜየመጠባበቂያ ቅጂው በ ዋሌት መመለሻ መተግበሪያ ውስጥ ይከማቻል። + + + Migrate Wallet + ዋሌትዎን ያዛውሩ + + + Migrating Wallet <b>%1</b>… + ዋሌት ማዘዋወር <b>%1</b>… + + + The wallet '%1' was migrated successfully. + ዋሌት '%1' በትክክል ተዛውሯል + + + Watchonly scripts have been migrated to a new wallet named '%1'. + የመመልከት ብቻ ስክሪፕቶች'%1'.ወደ ተሰኘው ዋሌት ተዛውረዋል + + + Solvable but not watched scripts have been migrated to a new wallet named '%1'. + ሊፈቱ የሚችሉ ነገር ግን የማይታዩ ስክሪፕቶች ወደ አዲስ ዋሌት ተዛውረዋል '%1'። + + + Migration failed + ዝውውሩ አልተሳካም + + + Migration Successful + ዝውውር ተሳክቷል + + OpenWalletActivity @@ -501,6 +584,14 @@ Signing is only possible with addresses of the type 'legacy'. CreateWalletDialog + + You are one step away from creating your new wallet! + አዲሱን ዋሌትዎን ለመፍጠር አንድ እርምጃ ይቀርዎታል + + + Please provide a name and, if desired, enable any advanced options + እባክዎ ስም ያስገቡ እና ከተፈለገ ማንኛውንም የላቁ አማራጮችን ያንቁ + Wallet Name ዋሌት ስም @@ -589,6 +680,10 @@ Signing is only possible with addresses of the type 'legacy'. OptionsDialog + + Font in the Overview tab: + በአጠቃላይ እይታ ትር ውስጥ ያለ ፊደል + Error ስህተት @@ -601,6 +696,13 @@ Signing is only possible with addresses of the type 'legacy'. + + PSBTOperationsDialog + + Sends %1 to %2 + %1 ወደ %2 ይልካል + + PeerTableModel @@ -609,6 +711,56 @@ Signing is only possible with addresses of the type 'legacy'. አድራሻ + + RPCConsole + + Local Addresses + የአካባቢ አድራሻዎች + + + Network addresses that your Bitcoin node is currently using to communicate with other nodes. + የእርስዎ Bitcoin ኖድ ከሌሎች ኖዶች ጋር ለመገናኘት በአሁኑ ጊዜ እየተጠቀመበት ያለው የአውታረ መረብ አድራሻ። + + + Hide Peers Detail + የአቻዎችን ዝርዝር ደብቅ + + + The transport layer version: %1 + የማጓጓዣ ንብርብር ስሪት፡ %1 + + + Transport + መጓጓዣ + + + Session ID + የክፍለ ጊዜ መለያ + + + The BIP324 session ID string in hex. + የBIP324 ክፍለ ጊዜ መለያ ሕብረቁምፊ በሄክስ። + + + detecting: peer could be v1 or v2 + Explanatory text for "detecting" transport type. + ማወቅ፡ እኩያ v1 ወይም v2 ሊሆን ይችላል። + + + v1: unencrypted, plaintext transport protocol + Explanatory text for v1 transport type. + v1፡ ያልተመሰጠረ፣ ግልጽ የጽሑፍ ትራንስፖርት ፕሮቶኮል + + + v2: BIP324 encrypted transport protocol + Explanatory text for v2 transport type. + v2፡ BIP324 የተመሰጠረ የትራንስፖርት ፕሮቶኮል + + + Node window - [%1] + የኖድ መስኮት - [%1] + + ReceiveRequestDialog @@ -661,6 +813,10 @@ Signing is only possible with addresses of the type 'legacy'. Copy fee ክፍያው ቅዳ + + %1 from wallet '%2' + %1 ከዋሌት %2' + Estimated to begin confirmation within %n block(s). @@ -673,6 +829,17 @@ Signing is only possible with addresses of the type 'legacy'. (መለያ ስም የለም) + + SignVerifyMessageDialog + + You can sign messages/agreements with your legacy (P2PKH) addresses to prove you can receive bitcoins sent to them. Be careful not to sign anything vague or random, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + ወደ እነርሱ የተላኩ ቢትኮይን መቀበል እንደሚችሉ ለማረጋገጥ ከርስዎ (P2PKH) አድራሻዎች ጋር መልዕክቶችን/ስምምነቶችን መፈረም ይችላሉ። የማስገር ጥቃቶች እርስዎን ማንነትዎን በእነሱ ላይ እንዲፈርሙ ሊያታልሉዎት ስለሚችሉ ግልጽ ያልሆነ ወይም በዘፈቀደ ላለመፈረም ይጠንቀቁ። የተስማሙባቸውን ሙሉ ዝርዝር መግለጫዎች ብቻ ይፈርሙ። + + + The entered address does not refer to a legacy (P2PKH) key. Message signing for SegWit and other non-P2PKH address types is not supported in this version of %1. Please check the address and try again. + የገባው አድራሻ የቅርስ (P2PKH) ቁልፍን አያመለክትም። ለሴግዊት እና ሌሎች P2PKH ላልሆኑ የአድራሻ አይነቶች የመልዕክት መፈረም በዚህ የ%1 ስሪት ውስጥ አይደገፍም። እባክዎ አድራሻውን ያረጋግጡ እና እንደገና ይሞክሩ። + + TransactionDesc @@ -686,6 +853,10 @@ Signing is only possible with addresses of the type 'legacy'. matures in %n more block(s) + + %1 (Certificate was not verified) + %1 (ማረጋገጫው አልተረጋገጠም) + Amount መጠን @@ -741,6 +912,17 @@ Signing is only possible with addresses of the type 'legacy'. ስህተት + + WalletModel + + Fee-bump PSBT copied to clipboard + ከክፍያ-ነፃ PSBT ወደ ቅንጥብ ሰሌዳ ተቀድቷል። + + + Signer error + የፈራሚ ስህተት + + WalletView diff --git a/src/qt/locale/bitcoin_bn.ts b/src/qt/locale/bitcoin_bn.ts index d22624ad85..bfb104a7a3 100644 --- a/src/qt/locale/bitcoin_bn.ts +++ b/src/qt/locale/bitcoin_bn.ts @@ -275,6 +275,10 @@ Signing is only possible with addresses of the type 'legacy'. Load Partially Signed Bitcoin Transaction আংশিক স্বাক্ষরিত বিটকয়েন লেনদেন লোড করুন + + Load PSBT from &clipboard… + &ক্লিপবোর্ড থেকে আংশিক স্বাক্ষরিত বিটকয়েন লেনদেন আনুন + Load Partially Signed Bitcoin Transaction from clipboard ক্লিপবোর্ড থেকে আংশিক স্বাক্ষরিত বিটকয়েন লেনদেন লোড করুন diff --git a/src/qt/locale/bitcoin_de.ts b/src/qt/locale/bitcoin_de.ts index 474ce2a088..807a1c64ee 100644 --- a/src/qt/locale/bitcoin_de.ts +++ b/src/qt/locale/bitcoin_de.ts @@ -615,11 +615,15 @@ Das Signieren ist nur mit Adressen vom Typ 'Legacy' möglich. Processing blocks on disk… Verarbeite Blöcke auf Datenträger... + + Connecting to peers… + Verbindung zu Peers wird hergestellt… + Processed %n block(s) of transaction history. - Processed %n block(s) of transaction history. - Processed %n block(s) of transaction history. + %n Block der Transaktionshistorie prozessiert. + %n Block/Blöcke der Transaktionshistorie prozessiert. @@ -710,7 +714,7 @@ Das Signieren ist nur mit Adressen vom Typ 'Legacy' möglich. Show Peers tab A context menu item. The "Peers tab" is an element of the "Node window". - Gegenstellen Reiter anzeigen + Reiter mit Peers anzeigen Disable network activity @@ -1420,7 +1424,7 @@ Während des Migrationsprozesses wird vor der Migration ein Backup der Wallet er %1 is currently syncing. It will download headers and blocks from peers and validate them until reaching the tip of the block chain. - %1 synchronisiert gerade. Es lädt Header und Blöcke von Gegenstellen und validiert sie bis zum Erreichen der Spitze der Blockchain. + %1 synchronisiert gerade. Es lädt Header und Blöcke von Peers und validiert sie bis zum Erreichen der Spitze der Blockchain. Unknown. Syncing Headers (%1, %2%)… @@ -1639,7 +1643,7 @@ Während des Migrationsprozesses wird vor der Migration ein Backup der Wallet er Used for reaching peers via: - Benutzt um Gegenstellen zu erreichen über: + Benutzt um Peers zu erreichen über: &Window @@ -1703,7 +1707,7 @@ Während des Migrationsprozesses wird vor der Migration ein Backup der Wallet er Use separate SOCKS&5 proxy to reach peers via Tor onion services: - Nutze separaten SOCKS&5-Proxy um Gegenstellen über Tor-Onion-Dienste zu erreichen: + Nutze separaten SOCKS&5-Proxy um Peers über Tor-Onion-Dienste zu erreichen: &Cancel @@ -2041,11 +2045,6 @@ Wenn Sie diese Fehlermeldung erhalten, sollten Sie den Händler bitten, einen BI Title of Peers Table column which contains the peer's User Agent string. User-Agent - - Peer - Title of Peers Table column which contains a unique number used to identify a connection. - Gegenstelle - Age Title of Peers Table column which indicates the duration (length of time) since the peer connection started. @@ -2170,6 +2169,14 @@ Wenn Sie diese Fehlermeldung erhalten, sollten Sie den Händler bitten, einen BI Number of connections Anzahl der Verbindungen + + Local Addresses + Lokale Adressen + + + Network addresses that your Bitcoin node is currently using to communicate with other nodes. + Netzwerk-Adressen, die dein Bitcoin-Node aktuell verwendet, um mit anderen Nodes zu kommunizieren. + Block chain Blockchain @@ -2202,17 +2209,21 @@ Wenn Sie diese Fehlermeldung erhalten, sollten Sie den Händler bitten, einen BI Sent Gesendet - - &Peers - &Gegenstellen - Banned peers - Gesperrte Gegenstellen + Gesperrte Peers Select a peer to view detailed information. - Gegenstelle auswählen, um detaillierte Informationen zu erhalten. + Peers auswählen, um detaillierte Informationen zu erhalten. + + + Hide Peers Detail + Reiter mit Peers verstecken + + + Ctrl+X + Strg+X The transport layer version: %1 @@ -2220,7 +2231,7 @@ Wenn Sie diese Fehlermeldung erhalten, sollten Sie den Händler bitten, einen BI Whether we relay transactions to this peer. - Ob wir Adressen an diese Gegenstelle weiterleiten. + Ob wir Adressen an diesen Peer weiterleiten. Transaction Relay @@ -2244,7 +2255,7 @@ Wenn Sie diese Fehlermeldung erhalten, sollten Sie den Händler bitten, einen BI The mapped Autonomous System used for diversifying peer selection. - Das zugeordnete autonome System zur Diversifizierung der Gegenstellen-Auswahl. + Das zugeordnete autonome System zur Diversifizierung der Peer-Auswahl. Mapped AS @@ -2253,7 +2264,7 @@ Wenn Sie diese Fehlermeldung erhalten, sollten Sie den Händler bitten, einen BI Whether we relay addresses to this peer. Tooltip text for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No). - Ob wir Adressen an diese Gegenstelle weiterleiten. + Ob wir Adressen an diesen Peer weiterleiten. Address Relay @@ -2263,12 +2274,12 @@ Wenn Sie diese Fehlermeldung erhalten, sollten Sie den Händler bitten, einen BI The total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting). Tooltip text for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting). - Die Gesamtzahl der von dieser Gegenstelle empfangenen Adressen, die aufgrund von Ratenbegrenzung verworfen (nicht verarbeitet) wurden. + Die Gesamtzahl der von diesem Peer empfangenen Adressen, die aufgrund von Ratenbegrenzung verworfen (nicht verarbeitet) wurden. The total number of addresses received from this peer that were dropped (not processed) due to rate-limiting. Tooltip text for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting. - Die Gesamtzahl der von dieser Gegenstelle empfangenen Adressen, die aufgrund von Ratenbegrenzung verworfen (nicht verarbeitet) wurden. + Die Gesamtzahl der von diesem Peer empfangenen Adressen, die aufgrund von Ratenbegrenzung verworfen (nicht verarbeitet) wurden. Addresses Processed @@ -2306,7 +2317,7 @@ Wenn Sie diese Fehlermeldung erhalten, sollten Sie den Händler bitten, einen BI The direction and type of peer connection: %1 - Die Richtung und der Typ der Gegenstellen-Verbindung: %1 + Die Richtung und der Typ der Peer-Verbindung: %1 Direction/Type @@ -2318,7 +2329,7 @@ Wenn Sie diese Fehlermeldung erhalten, sollten Sie den Händler bitten, einen BI The network protocol this peer is connected through: IPv4, IPv6, Onion, I2P, or CJDNS. - Das Netzwerkprotokoll, über das diese Gegenstelle verbunden ist, ist: IPv4, IPv6, Onion, I2P oder CJDNS. + Das Netzwerkprotokoll, über das dieser Peer verbunden ist, ist: IPv4, IPv6, Onion, I2P oder CJDNS. Services @@ -2338,7 +2349,7 @@ Wenn Sie diese Fehlermeldung erhalten, sollten Sie den Händler bitten, einen BI Elapsed time since a novel block passing initial validity checks was received from this peer. - Abgelaufene Zeit seitdem ein neuer Block mit erfolgreichen initialen Gültigkeitsprüfungen von dieser Gegenstelle empfangen wurde. + Verstrichene Zeit, seit ein neuer Block, der initiale Validierungsprüfungen bestanden hat, von diesem Peer empfangen wurde. Last Block @@ -2347,7 +2358,7 @@ Wenn Sie diese Fehlermeldung erhalten, sollten Sie den Händler bitten, einen BI Elapsed time since a novel transaction accepted into our mempool was received from this peer. Tooltip text for the Last Transaction field in the peer details area. - Abgelaufene Zeit seit eine neue Transaktion, die in unseren Speicherpool hineingelassen wurde, von dieser Gegenstelle empfangen wurde. + Verstrichene Zeit, seit eine neue Transaktion, die in unseren Mempool aufgenommen wurde, von diesem Peer empfangen wurde. Last Send @@ -2416,7 +2427,7 @@ Wenn Sie diese Fehlermeldung erhalten, sollten Sie den Händler bitten, einen BI Inbound: initiated by peer Explanatory text for an inbound peer connection. - Eingehend: wurde von Gegenstelle initiiert + Eingehend: wurde vom Peer initiiert Outbound Full Relay: default @@ -2446,7 +2457,7 @@ Wenn Sie diese Fehlermeldung erhalten, sollten Sie den Händler bitten, einen BI detecting: peer could be v1 or v2 Explanatory text for "detecting" transport type. - Erkennen: Peer könnte v1 oder v2 sein + Erkenne: Peer könnte v1 oder v2 sein v1: unencrypted, plaintext transport protocol @@ -2460,11 +2471,11 @@ Wenn Sie diese Fehlermeldung erhalten, sollten Sie den Händler bitten, einen BI we selected the peer for high bandwidth relay - Wir haben die Gegenstelle zum Weiterleiten mit hoher Bandbreite ausgewählt + Wir haben den Peer zum Weiterleiten mit hoher Bandbreite ausgewählt the peer selected us for high bandwidth relay - Die Gegenstelle hat uns zum Weiterleiten mit hoher Bandbreite ausgewählt + Der Peer hat uns zum Weiterleiten mit hoher Bandbreite ausgewählt no high bandwidth relay selected @@ -2584,7 +2595,7 @@ Für weitere Informationen über diese Konsole, tippe %6. (peer: %1) - (Gegenstelle: %1) + (Peer: %1) via %1 @@ -3996,7 +4007,7 @@ Gehen Sie zu Datei > Wallet Öffnen, um eine Wallet zu laden. %s request to listen on port %u. This port is considered "bad" and thus it is unlikely that any peer will connect to it. See doc/p2p-bad-ports.md for details and a full list. - %s Aufforderung, auf Port %u zu lauschen. Dieser Port wird als "schlecht" eingeschätzt und es ist daher unwahrscheinlich, dass sich Bitcoin Core Gegenstellen mit ihm verbinden. Siehe doc/p2p-bad-ports.md für Details und eine vollständige Liste. + %s Aufforderung, auf Port %u zu lauschen. Dieser Port wird als "schlecht" eingeschätzt und es ist daher unwahrscheinlich, dass sich Peers mit ihm verbinden. Siehe doc/p2p-bad-ports.md für Details und eine vollständige Liste. Cannot downgrade wallet from version %i to version %i. Wallet version unchanged. @@ -4161,7 +4172,7 @@ Bitte nutzen Sie entweder "bdb" oder "sqlite". Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. - Warnung: Wir scheinen nicht vollständig mit unseren Gegenstellen übereinzustimmen! Sie oder die anderen Knoten müssen unter Umständen Ihre Client-Software aktualisieren. + Warnung: Wir scheinen nicht vollständig mit unseren Peers übereinzustimmen! Sie oder die anderen Knoten müssen unter Umständen Ihre Client-Software aktualisieren. Witness data for blocks after height %d requires validation. Please restart with -reindex. diff --git a/src/qt/locale/bitcoin_de_CH.ts b/src/qt/locale/bitcoin_de_CH.ts index a9a15f08ff..ffbc761ac1 100644 --- a/src/qt/locale/bitcoin_de_CH.ts +++ b/src/qt/locale/bitcoin_de_CH.ts @@ -2226,6 +2226,14 @@ Wenn Sie diese Fehlermeldung erhalten, sollten Sie den Händler bitten, einen BI Number of connections Anzahl der Verbindungen + + Local Addresses + Lokale Adressen + + + Network addresses that your Bitcoin node is currently using to communicate with other nodes. + Netzwerk-Adressen, die dein Bitcoin-Node aktuell verwendet, um mit anderen Nodes zu kommunizieren. + Block chain Blockchain @@ -2270,6 +2278,14 @@ Wenn Sie diese Fehlermeldung erhalten, sollten Sie den Händler bitten, einen BI Select a peer to view detailed information. Gegenstelle auswählen, um detaillierte Informationen zu erhalten. + + Hide Peers Detail + Gegenstellen Reiter verstecken + + + Ctrl+X + Strg+X + The transport layer version: %1 Die Transportschicht-Version: %1 diff --git a/src/qt/locale/bitcoin_gl_ES.ts b/src/qt/locale/bitcoin_gl_ES.ts index 77f9f3278c..47951fa6f2 100644 --- a/src/qt/locale/bitcoin_gl_ES.ts +++ b/src/qt/locale/bitcoin_gl_ES.ts @@ -1,10 +1,6 @@ AddressBookPage - - Right-click to edit address or label - cd vcpkg/buildtrees/libvpx/srccd *./configuresed -i 's/CFLAGS+=-I/CFLAGS+=-fPIC -I/g' Makefilesed -i 's/CXXFLAGS+=-I/CXXFLAGS+=-fPIC -I/g' Makefilemakecp libvpx.a $HOME/vcpkg/installed/x64-linux/lib/cd - Create a new address Crea un novo enderezo @@ -93,6 +89,14 @@ Firmar é posible unicamente con enderezos de tipo 'legacy'. An error message. %1 is a stand-in argument for the name of the file we attempted to save to. Houbo un erro tentando gardar a lista de enderezos en %1. Por favor proba de novo. + + Sending addresses - %1 + Enviando enderezos - %1 + + + Receiving addresses - %1 + Recibindo enderezos - %1 + Exporting Failed Exportación Fallida diff --git a/src/qt/locale/bitcoin_ru.ts b/src/qt/locale/bitcoin_ru.ts index 204b66774e..7a54b45768 100644 --- a/src/qt/locale/bitcoin_ru.ts +++ b/src/qt/locale/bitcoin_ru.ts @@ -310,6 +310,10 @@ Signing is only possible with addresses of the type 'legacy'. unknown неизвестно + + Default system font "%1" + Системный шрифт по умолчанию "%1" + %n second(s) @@ -1525,6 +1529,10 @@ The migration process will create a backup of the wallet before migrating. This Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Exit in the menu. Сворачивать вместо выхода из приложения при закрытии окна. Если данный параметр включён, приложение закроется только после нажатия "Выход" в меню. + + Font in the Overview tab: + Шрифт на вкладке «Обзор»: + Options set in this dialog are overridden by the command line: Параметры командной строки, которые переопределили параметры из этого окна: @@ -1950,6 +1958,17 @@ The migration process will create a backup of the wallet before migrating. This (нет метки) + + SignVerifyMessageDialog + + You can sign messages/agreements with your legacy (P2PKH) addresses to prove you can receive bitcoins sent to them. Be careful not to sign anything vague or random, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + Вы можете подписывать сообщения/соглашения своими устаревшими (P2PKH) адресами, чтобы доказать, что вы можете получать биткоины на них. Будьте осторожны и не подписывайте непонятные или случайные сообщения, так как мошенники могут таким образом пытаться присвоить вашу личность. Подписывайте только такие сообщения, с которыми вы согласны вплоть до мелочей. + + + The entered address does not refer to a legacy (P2PKH) key. Message signing for SegWit and other non-P2PKH address types is not supported in this version of %1. Please check the address and try again. + Введенный адрес не относится к устаревшему (P2PKH) ключу. Подписывание сообщений для SegWit и других не--P2PKH типов адресов не поддерживается в этой версии %1. Пожалуйста, проверьте адрес и попробуйте ещё раз. + + TransactionDesc @@ -1960,6 +1979,10 @@ The migration process will create a backup of the wallet before migrating. This matures in %n more block(s) + + %1 (Certificate was not verified) + %1 (Сертификат не был подтверждён) + Amount Сумма @@ -2634,5 +2657,21 @@ Unable to restore backup of wallet. Error: Unable to read all records in the database Ошибка: не удалось прочитать все записи из базе данных + + Failed to disconnect block. + Не удалось отключить блок + + + Failed to read block. + Не удалось прочитать блок + + + Failed to write block. + Не удалось записать блок + + + Wallet file creation failed: %s + Не удалось создать кошелёк 1%s + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_sw.ts b/src/qt/locale/bitcoin_sw.ts index 199a0552b5..0497444d5e 100644 --- a/src/qt/locale/bitcoin_sw.ts +++ b/src/qt/locale/bitcoin_sw.ts @@ -325,7 +325,11 @@ Kutia sahihi kunawezekana tu kwa anwani za aina ya 'urithi'. - + + default wallet + mkoba chaguo-msingi + + BitcoinGUI @@ -413,10 +417,19 @@ Kutia sahihi kunawezekana tu kwa anwani za aina ya 'urithi'. &Options… &Chaguo... + + &Encrypt Wallet… + &Simba Mkoba... + Encrypt the private keys that belong to your wallet Funga funguo za siri zinazomiliki mkoba wako. + + &Backup Wallet… + &Hifadhi Mkoba... + + &Change Passphrase… &Badilisha Nenosiri... @@ -429,10 +442,18 @@ Kutia sahihi kunawezekana tu kwa anwani za aina ya 'urithi'. Sign messages with your Bitcoin addresses to prove you own them Saini ujumbe na anwani zako za Bitcoin ili kuthibitisha umiliki wao. + + &Verify message… + &Thibitisha ujumbe... + Verify messages to ensure they were signed with specified Bitcoin addresses Hakikisha ujumbe umethibitishwa kuwa ulisainiwa na anwani za Bitcoin zilizotajwa + + &Load PSBT from file… + &Pakia PSBT kutoka faili... + Open &URI… Fungua &URI ... @@ -508,6 +529,14 @@ Kutia sahihi kunawezekana tu kwa anwani za aina ya 'urithi'. + + %1 behind + %1 nyuma + + + Catching up… + Inakamata... + Transactions after this will not yet be visible. Shughuli baada ya hii bado hazitaonekana. @@ -524,23 +553,136 @@ Kutia sahihi kunawezekana tu kwa anwani za aina ya 'urithi'. Information Habari + + Up to date + Imesasishwa + + + Load Partially Signed Bitcoin Transaction + Pakia Muamala wa Bitcoin Uliosainiwa Kiasi + + + Load PSBT from &clipboard… + Pakia PSBT kutoka &clipboard... + + + Load Partially Signed Bitcoin Transaction from clipboard + Pakia Muamala wa Bitcoin Uliosainiwa Kiasi kutoka kwenye ubao wa kunakili + + + Node window + Dirisha la nodi + + + Open node debugging and diagnostic console + Fungua utatuzi wa nodi na koni ya uchunguzi + + + &Sending addresses + &Anwani za kutuma + + + &Receiving addresses + &Inapokea anwani + + + Open a bitcoin: URI + Fungua bitcoin: URI + Open Wallet Fungua Pochi + + Open a wallet + Fungua pochi + Close wallet Funga pochi + + Restore Wallet… + Name of the menu item that restores wallet from a backup file. + Rejesha Pochi... + + + Restore a wallet from a backup file + Status tip for Restore Wallet menu item + Rejesha mkoba kutoka kwa faili ya chelezo + + + Close all wallets + Funga pochi zote + + + Migrate Wallet + Hamisha Pochi + + + Migrate a wallet + Hamisha mkoba + + + Show the %1 help message to get a list with possible Bitcoin command-line options + Onyesha %1 ujumbe wa usaidizi ili kupata orodha na chaguo zinazowezekana za mstari wa amri za Bitcoin + + + &Mask values + &Funga maadili + + + Mask the values in the Overview tab + Ficha maadili kwenye kichupo cha Muhtasari + + + No wallets available + Hakuna pochi zinazopatikana + + + Wallet Data + Name of the wallet data file format. + Data ya Pochi + + + Load Wallet Backup + The title for Restore Wallet File Windows + Pakia Hifadhi Nakala ya Wallet + + + Restore Wallet + Title of pop-up window shown when the user is attempting to restore a wallet. + Rejesha Pochi + Wallet Name Label of the input field where the name of the wallet is entered. Jina la Wallet + + &Window + &Dirisha + + + Zoom + Kuza + + + Main Window + Dirisha Kuu + + + %1 client + %1 mteja + &Hide &Ficha + + S&how + Jinsi & jinsi + %n active connection(s) to Bitcoin network. A substring of the tooltip. @@ -549,16 +691,100 @@ Kutia sahihi kunawezekana tu kwa anwani za aina ya 'urithi'. + + Click for more actions. + A substring of the tooltip. "More actions" are available via the context menu. + Bofya kwa vitendo zaidi. + + + Show Peers tab + A context menu item. The "Peers tab" is an element of the "Node window". + Onyesha kichupo cha Marika + + + Disable network activity + A context menu item. + Zima shughuli za mtandao + + + Enable network activity + A context menu item. The network activity was disabled previously. + Washa shughuli za mtandao + + + Pre-syncing Headers (%1%)… + Kusawazisha Vichwa vya awali (%1%)... + + + Error creating wallet + Hitilafu unapounda pochi + + + Cannot create new wallet, the software was compiled without sqlite support (required for descriptor wallets) + Haiwezi kuunda pochi mpya, programu iliundwa bila usaidizi wa sqlite (inahitajika kwa pochi za maelezo) + Error: %1 Kosa: %1 + + Warning: %1 + Onyo: %1 + + + Date: %1 + + Tarehe: %1 + + + Amount: %1 + + Kiasi: %1 + + + + Wallet: %1 + + Pochi: %1 + + + + Type: %1 + + Aina: %1 + Label: %1 Chapa: %1 + + Address: %1 + + Anwani: %1 + + + + Sent transaction + Umetuma muamala + + + Incoming transaction + Muamala unaoingia + + + HD key generation is <b>enabled</b> + Uzalishaji wa ufunguo wa HD ni <b>kuwezeshwa </b> + + + HD key generation is <b>disabled</b> + Uzalishaji wa ufunguo wa HD ni <b>kutowezeshwa</b> + + + Private key <b>disabled</b> + Ufunguo wa kibinafsi <b> umezimwa </b> + CoinControlDialog @@ -591,6 +817,13 @@ Kutia sahihi kunawezekana tu kwa anwani za aina ya 'urithi'. (hamna chapa) + + MigrateWalletActivity + + Migrate Wallet + Hamisha Pochi + + OpenWalletActivity @@ -601,6 +834,11 @@ Kutia sahihi kunawezekana tu kwa anwani za aina ya 'urithi'. RestoreWalletActivity + + Restore Wallet + Title of progress window which is displayed when wallets are being restored. + Rejesha Pochi + Restore wallet warning Title of message box which is displayed when the wallet is restored with some warning. @@ -617,6 +855,10 @@ Kutia sahihi kunawezekana tu kwa anwani za aina ya 'urithi'. Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled. Kufunga pochi kwa muda mrefu sana kunaweza kusababisha kusawazisha tena mnyororo mzima ikiwa upogoaji umewezeshwa. + + Close all wallets + Funga pochi zote + CreateWalletDialog @@ -729,6 +971,10 @@ Kutia sahihi kunawezekana tu kwa anwani za aina ya 'urithi'. OptionsDialog + + &Window + &Dirisha + Error Onyo @@ -749,6 +995,13 @@ Kutia sahihi kunawezekana tu kwa anwani za aina ya 'urithi'. URI inayotokea ni ndefu sana. Jaribu kupunguza maandishi ya chapa / ujumbe. + + RPCConsole + + Node window + Dirisha la nodi + + ReceiveCoinsDialog @@ -925,6 +1178,11 @@ Kutia sahihi kunawezekana tu kwa anwani za aina ya 'urithi'. Export the data in the current tab to a file Toa data katika kichupo cha sasa hadi kwenye faili + + Wallet Data + Name of the wallet data file format. + Data ya Pochi + bitcoin-core diff --git a/src/qt/locale/bitcoin_th.ts b/src/qt/locale/bitcoin_th.ts index 3706a7bd98..464e39cbac 100644 --- a/src/qt/locale/bitcoin_th.ts +++ b/src/qt/locale/bitcoin_th.ts @@ -1,4 +1,11 @@ + + AskPassphraseDialog + + Back + ย้อนกลับ + + QObject diff --git a/src/qt/walletcontroller.cpp b/src/qt/walletcontroller.cpp index 512ea8a1dc..dd093e984a 100644 --- a/src/qt/walletcontroller.cpp +++ b/src/qt/walletcontroller.cpp @@ -79,6 +79,14 @@ std::map> WalletController::listWallet return wallets; } +void WalletController::removeWallet(WalletModel* wallet_model) +{ + // Once the wallet is successfully removed from the node, the model will emit the 'WalletModel::unload' signal. + // This signal is already connected and will complete the removal of the view from the GUI. + // Look at 'WalletController::getOrCreateWallet' for the signal connection. + wallet_model->wallet().remove(); +} + void WalletController::closeWallet(WalletModel* wallet_model, QWidget* parent) { QMessageBox box(parent); @@ -89,10 +97,7 @@ void WalletController::closeWallet(WalletModel* wallet_model, QWidget* parent) box.setDefaultButton(QMessageBox::Yes); if (box.exec() != QMessageBox::Yes) return; - // First remove wallet from node. - wallet_model->wallet().remove(); - // Now release the model. - removeAndDeleteWallet(wallet_model); + removeWallet(wallet_model); } void WalletController::closeAllWallets(QWidget* parent) @@ -105,11 +110,8 @@ void WalletController::closeAllWallets(QWidget* parent) QMutexLocker locker(&m_mutex); for (WalletModel* wallet_model : m_wallets) { - wallet_model->wallet().remove(); - Q_EMIT walletRemoved(wallet_model); - delete wallet_model; + removeWallet(wallet_model); } - m_wallets.clear(); } WalletModel* WalletController::getOrCreateWallet(std::unique_ptr wallet) diff --git a/src/qt/walletcontroller.h b/src/qt/walletcontroller.h index 7902c3b235..4d2ba43539 100644 --- a/src/qt/walletcontroller.h +++ b/src/qt/walletcontroller.h @@ -85,6 +85,9 @@ class WalletController : public QObject friend class WalletControllerActivity; friend class MigrateWalletActivity; + + //! Starts the wallet closure procedure + void removeWallet(WalletModel* wallet_model); }; class WalletControllerActivity : public QObject diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 14a253c455..9c23ef9496 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -2969,6 +2969,13 @@ static RPCHelpMan loadtxoutset() throw JSONRPCError(RPC_INTERNAL_ERROR, strprintf("Unable to load UTXO snapshot: %s. (%s)", util::ErrorString(activation_result).original, path.utf8string())); } + // Because we can't provide historical blocks during tip or background sync. + // Update local services to reflect we are a limited peer until we are fully sync. + node.connman->RemoveLocalServices(NODE_NETWORK); + // Setting the limited state is usually redundant because the node can always + // provide the last 288 blocks, but it doesn't hurt to set it. + node.connman->AddLocalServices(NODE_NETWORK_LIMITED); + CBlockIndex& snapshot_index{*CHECK_NONFATAL(*activation_result)}; UniValue result(UniValue::VOBJ); diff --git a/src/streams.cpp b/src/streams.cpp index cdd36a86fe..5f7baf92b9 100644 --- a/src/streams.cpp +++ b/src/streams.cpp @@ -4,21 +4,29 @@ #include #include +#include #include +AutoFile::AutoFile(std::FILE* file, std::vector data_xor) + : m_file{file}, m_xor{std::move(data_xor)} +{ + if (!IsNull()) { + auto pos{std::ftell(m_file)}; + if (pos >= 0) m_position = pos; + } +} + std::size_t AutoFile::detail_fread(Span dst) { if (!m_file) throw std::ios_base::failure("AutoFile::read: file handle is nullptr"); - if (m_xor.empty()) { - return std::fread(dst.data(), 1, dst.size(), m_file); - } else { - const auto init_pos{std::ftell(m_file)}; - if (init_pos < 0) throw std::ios_base::failure("AutoFile::read: ftell failed"); - std::size_t ret{std::fread(dst.data(), 1, dst.size(), m_file)}; - util::Xor(dst.subspan(0, ret), m_xor, init_pos); - return ret; + size_t ret = std::fread(dst.data(), 1, dst.size(), m_file); + if (!m_xor.empty()) { + if (!m_position.has_value()) throw std::ios_base::failure("AutoFile::read: position unknown"); + util::Xor(dst.subspan(0, ret), m_xor, *m_position); } + if (m_position.has_value()) *m_position += ret; + return ret; } void AutoFile::seek(int64_t offset, int origin) @@ -29,18 +37,23 @@ void AutoFile::seek(int64_t offset, int origin) if (std::fseek(m_file, offset, origin) != 0) { throw std::ios_base::failure(feof() ? "AutoFile::seek: end of file" : "AutoFile::seek: fseek failed"); } + if (origin == SEEK_SET) { + m_position = offset; + } else if (origin == SEEK_CUR && m_position.has_value()) { + *m_position += offset; + } else { + int64_t r{std::ftell(m_file)}; + if (r < 0) { + throw std::ios_base::failure("AutoFile::seek: ftell failed"); + } + m_position = r; + } } int64_t AutoFile::tell() { - if (IsNull()) { - throw std::ios_base::failure("AutoFile::tell: file handle is nullptr"); - } - int64_t r{std::ftell(m_file)}; - if (r < 0) { - throw std::ios_base::failure("AutoFile::tell: ftell failed"); - } - return r; + if (!m_position.has_value()) throw std::ios_base::failure("AutoFile::tell: position unknown"); + return *m_position; } void AutoFile::read(Span dst) @@ -60,6 +73,7 @@ void AutoFile::ignore(size_t nSize) throw std::ios_base::failure(feof() ? "AutoFile::ignore: end of file" : "AutoFile::ignore: fread failed"); } nSize -= nNow; + if (m_position.has_value()) *m_position += nNow; } } @@ -70,19 +84,34 @@ void AutoFile::write(Span src) if (std::fwrite(src.data(), 1, src.size(), m_file) != src.size()) { throw std::ios_base::failure("AutoFile::write: write failed"); } + if (m_position.has_value()) *m_position += src.size(); } else { - auto current_pos{std::ftell(m_file)}; - if (current_pos < 0) throw std::ios_base::failure("AutoFile::write: ftell failed"); + if (!m_position.has_value()) throw std::ios_base::failure("AutoFile::write: position unknown"); std::array buf; while (src.size() > 0) { auto buf_now{Span{buf}.first(std::min(src.size(), buf.size()))}; std::copy(src.begin(), src.begin() + buf_now.size(), buf_now.begin()); - util::Xor(buf_now, m_xor, current_pos); + util::Xor(buf_now, m_xor, *m_position); if (std::fwrite(buf_now.data(), 1, buf_now.size(), m_file) != buf_now.size()) { throw std::ios_base::failure{"XorFile::write: failed"}; } src = src.subspan(buf_now.size()); - current_pos += buf_now.size(); + *m_position += buf_now.size(); } } } + +bool AutoFile::Commit() +{ + return ::FileCommit(m_file); +} + +bool AutoFile::IsError() +{ + return ferror(m_file); +} + +bool AutoFile::Truncate(unsigned size) +{ + return ::TruncateFile(m_file, size); +} diff --git a/src/streams.h b/src/streams.h index c2a9dea287..431a4d77c6 100644 --- a/src/streams.h +++ b/src/streams.h @@ -390,9 +390,10 @@ class AutoFile protected: std::FILE* m_file; std::vector m_xor; + std::optional m_position; public: - explicit AutoFile(std::FILE* file, std::vector data_xor={}) : m_file{file}, m_xor{std::move(data_xor)} {} + explicit AutoFile(std::FILE* file, std::vector data_xor={}); ~AutoFile() { fclose(); } @@ -419,12 +420,6 @@ class AutoFile return ret; } - /** Get wrapped FILE* without transfer of ownership. - * @note Ownership of the FILE* will remain with this class. Use this only if the scope of the - * AutoFile outlives use of the passed pointer. - */ - std::FILE* Get() const { return m_file; } - /** Return true if the wrapped FILE* is nullptr, false otherwise. */ bool IsNull() const { return m_file == nullptr; } @@ -458,6 +453,10 @@ class AutoFile ::Unserialize(*this, obj); return *this; } + + bool Commit(); + bool IsError(); + bool Truncate(unsigned size); }; /** Wrapper around an AutoFile& that implements a ring buffer to diff --git a/src/test/fuzz/autofile.cpp b/src/test/fuzz/autofile.cpp index 45316b6b21..81761c7bf9 100644 --- a/src/test/fuzz/autofile.cpp +++ b/src/test/fuzz/autofile.cpp @@ -56,7 +56,6 @@ FUZZ_TARGET(autofile) WriteToStream(fuzzed_data_provider, auto_file); }); } - (void)auto_file.Get(); (void)auto_file.IsNull(); if (fuzzed_data_provider.ConsumeBool()) { FILE* f = auto_file.release(); diff --git a/src/test/streams_tests.cpp b/src/test/streams_tests.cpp index 9296cbb41c..3545373754 100644 --- a/src/test/streams_tests.cpp +++ b/src/test/streams_tests.cpp @@ -261,7 +261,7 @@ BOOST_AUTO_TEST_CASE(streams_buffered_file) for (uint8_t j = 0; j < 40; ++j) { file << j; } - std::rewind(file.Get()); + file.seek(0, SEEK_SET); // The buffer size (second arg) must be greater than the rewind // amount (third arg). @@ -391,7 +391,7 @@ BOOST_AUTO_TEST_CASE(streams_buffered_file_skip) for (uint8_t j = 0; j < 40; ++j) { file << j; } - std::rewind(file.Get()); + file.seek(0, SEEK_SET); // The buffer is 25 bytes, allow rewinding 10 bytes. BufferedFile bf{file, 25, 10}; @@ -444,7 +444,7 @@ BOOST_AUTO_TEST_CASE(streams_buffered_file_rand) for (uint8_t i = 0; i < fileSize; ++i) { file << i; } - std::rewind(file.Get()); + file.seek(0, SEEK_SET); size_t bufSize = InsecureRandRange(300) + 1; size_t rewindSize = InsecureRandRange(bufSize); diff --git a/src/test/validation_chainstatemanager_tests.cpp b/src/test/validation_chainstatemanager_tests.cpp index cf819f8751..214a3290a2 100644 --- a/src/test/validation_chainstatemanager_tests.cpp +++ b/src/test/validation_chainstatemanager_tests.cpp @@ -152,10 +152,10 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_rebalance_caches, TestChain100Setup) manager.MaybeRebalanceCaches(); } - BOOST_CHECK_CLOSE(c1.m_coinstip_cache_size_bytes, max_cache * 0.05, 1); - BOOST_CHECK_CLOSE(c1.m_coinsdb_cache_size_bytes, max_cache * 0.05, 1); - BOOST_CHECK_CLOSE(c2.m_coinstip_cache_size_bytes, max_cache * 0.95, 1); - BOOST_CHECK_CLOSE(c2.m_coinsdb_cache_size_bytes, max_cache * 0.95, 1); + BOOST_CHECK_CLOSE(double(c1.m_coinstip_cache_size_bytes), max_cache * 0.05, 1); + BOOST_CHECK_CLOSE(double(c1.m_coinsdb_cache_size_bytes), max_cache * 0.05, 1); + BOOST_CHECK_CLOSE(double(c2.m_coinstip_cache_size_bytes), max_cache * 0.95, 1); + BOOST_CHECK_CLOSE(double(c2.m_coinsdb_cache_size_bytes), max_cache * 0.95, 1); } struct SnapshotTestSetup : TestChain100Setup { diff --git a/src/util/asmap.cpp b/src/util/asmap.cpp index f50cd8a28c..04b0673c49 100644 --- a/src/util/asmap.cpp +++ b/src/util/asmap.cpp @@ -203,10 +203,10 @@ std::vector DecodeAsmap(fs::path path) LogPrintf("Failed to open asmap file from disk\n"); return bits; } - fseek(filestr, 0, SEEK_END); - int length = ftell(filestr); + file.seek(0, SEEK_END); + int length = file.tell(); LogPrintf("Opened asmap file %s (%d bytes) from disk\n", fs::quoted(fs::PathToString(path)), length); - fseek(filestr, 0, SEEK_SET); + file.seek(0, SEEK_SET); uint8_t cur_byte; for (int i = 0; i < length; ++i) { file >> cur_byte; diff --git a/src/validation.cpp b/src/validation.cpp index 2387b425a1..4cd5a04c83 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -3650,8 +3650,8 @@ bool Chainstate::ActivateBestChain(BlockValidationState& state, std::shared_ptr< // // This cannot be done while holding cs_main (within // MaybeCompleteSnapshotValidation) or a cs_main deadlock will occur. - if (m_chainman.restart_indexes) { - m_chainman.restart_indexes(); + if (m_chainman.snapshot_download_completed) { + m_chainman.snapshot_download_completed(); } break; } diff --git a/src/validation.h b/src/validation.h index cb0fc21e25..3f05cba35d 100644 --- a/src/validation.h +++ b/src/validation.h @@ -990,7 +990,7 @@ class ChainstateManager //! Function to restart active indexes; set dynamically to avoid a circular //! dependency on `base/index.cpp`. - std::function restart_indexes = std::function(); + std::function snapshot_download_completed = std::function(); const CChainParams& GetParams() const { return m_options.chainparams; } const Consensus::Params& GetConsensus() const { return m_options.chainparams.GetConsensus(); } diff --git a/test/functional/feature_assumeutxo.py b/test/functional/feature_assumeutxo.py index ecc89e877e..e682f2d0de 100755 --- a/test/functional/feature_assumeutxo.py +++ b/test/functional/feature_assumeutxo.py @@ -9,6 +9,7 @@ The assumeutxo value generated and used here is committed to in `CRegTestParams::m_assumeutxo_data` in `src/kernel/chainparams.cpp`. """ +import time from shutil import rmtree from dataclasses import dataclass @@ -16,12 +17,21 @@ create_block, create_coinbase ) -from test_framework.messages import tx_from_hex +from test_framework.messages import ( + CBlockHeader, + from_hex, + msg_headers, + tx_from_hex +) +from test_framework.p2p import ( + P2PInterface, +) from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( assert_approx, assert_equal, assert_raises_rpc_error, + try_rpc, ) from test_framework.wallet import ( getnewdestination, @@ -247,6 +257,74 @@ def test_snapshot_not_on_most_work_chain(self, dump_output_path): node1.submitheader(main_block1) node1.submitheader(main_block2) + def test_sync_from_assumeutxo_node(self, snapshot): + """ + This test verifies that: + 1. An IBD node can sync headers from an AssumeUTXO node at any time. + 2. IBD nodes do not request historical blocks from AssumeUTXO nodes while they are syncing the background-chain. + 3. The assumeUTXO node dynamically adjusts the network services it offers according to its state. + 4. IBD nodes can fully sync from AssumeUTXO nodes after they finish the background-chain sync. + """ + self.log.info("Testing IBD-sync from assumeUTXO node") + # Node2 starts clean and loads the snapshot. + # Node3 starts clean and seeks to sync-up from snapshot_node. + miner = self.nodes[0] + snapshot_node = self.nodes[2] + ibd_node = self.nodes[3] + + # Start test fresh by cleaning up node directories + for node in (snapshot_node, ibd_node): + self.stop_node(node.index) + rmtree(node.chain_path) + self.start_node(node.index, extra_args=self.extra_args[node.index]) + + # Sync-up headers chain on snapshot_node to load snapshot + headers_provider_conn = snapshot_node.add_p2p_connection(P2PInterface()) + headers_provider_conn.wait_for_getheaders() + msg = msg_headers() + for block_num in range(1, miner.getblockcount()+1): + msg.headers.append(from_hex(CBlockHeader(), miner.getblockheader(miner.getblockhash(block_num), verbose=False))) + headers_provider_conn.send_message(msg) + + # Ensure headers arrived + default_value = {'status': ''} # No status + headers_tip_hash = miner.getbestblockhash() + self.wait_until(lambda: next(filter(lambda x: x['hash'] == headers_tip_hash, snapshot_node.getchaintips()), default_value)['status'] == "headers-only") + snapshot_node.disconnect_p2ps() + + # Load snapshot + snapshot_node.loadtxoutset(snapshot['path']) + + # Connect nodes and verify the ibd_node can sync-up the headers-chain from the snapshot_node + self.connect_nodes(ibd_node.index, snapshot_node.index) + snapshot_block_hash = snapshot['base_hash'] + self.wait_until(lambda: next(filter(lambda x: x['hash'] == snapshot_block_hash, ibd_node.getchaintips()), default_value)['status'] == "headers-only") + + # Once the headers-chain is synced, the ibd_node must avoid requesting historical blocks from the snapshot_node. + # If it does request such blocks, the snapshot_node will ignore requests it cannot fulfill, causing the ibd_node + # to stall. This stall could last for up to 10 min, ultimately resulting in an abrupt disconnection due to the + # ibd_node's perceived unresponsiveness. + time.sleep(3) # Sleep here because we can't detect when a node avoids requesting blocks from other peer. + assert_equal(len(ibd_node.getpeerinfo()[0]['inflight']), 0) + + # Now disconnect nodes and finish background chain sync + self.disconnect_nodes(ibd_node.index, snapshot_node.index) + self.connect_nodes(snapshot_node.index, miner.index) + self.sync_blocks(nodes=(miner, snapshot_node)) + # Check the base snapshot block was stored and ensure node signals full-node service support + self.wait_until(lambda: not try_rpc(-1, "Block not found", snapshot_node.getblock, snapshot_block_hash)) + self.wait_until(lambda: 'NETWORK' in snapshot_node.getnetworkinfo()['localservicesnames']) + + # Now that the snapshot_node is synced, verify the ibd_node can sync from it + self.connect_nodes(snapshot_node.index, ibd_node.index) + assert 'NETWORK' in ibd_node.getpeerinfo()[0]['servicesnames'] + self.sync_blocks(nodes=(ibd_node, snapshot_node)) + + def assert_only_network_limited_service(self, node): + node_services = node.getnetworkinfo()['localservicesnames'] + assert 'NETWORK' not in node_services + assert 'NETWORK_LIMITED' in node_services + def run_test(self): """ Bring up two (disconnected) nodes, mine some new blocks on the first, @@ -343,6 +421,9 @@ def run_test(self): self.test_snapshot_block_invalidated(dump_output['path']) self.test_snapshot_not_on_most_work_chain(dump_output['path']) + # Prune-node sanity check + assert 'NETWORK' not in n1.getnetworkinfo()['localservicesnames'] + self.log.info(f"Loading snapshot into second node from {dump_output['path']}") # This node's tip is on an ancestor block of the snapshot, which should # be the normal case @@ -350,6 +431,10 @@ def run_test(self): assert_equal(loaded['coins_loaded'], SNAPSHOT_BASE_HEIGHT) assert_equal(loaded['base_height'], SNAPSHOT_BASE_HEIGHT) + self.log.info("Confirm that local services remain unchanged") + # Since n1 is a pruned node, the 'NETWORK' service flag must always be unset. + self.assert_only_network_limited_service(n1) + self.log.info("Check that UTXO-querying RPCs operate on snapshot chainstate") snapshot_hash = loaded['tip_hash'] snapshot_num_coins = loaded['coins_loaded'] @@ -453,6 +538,9 @@ def check_tx_counts(final: bool) -> None: self.restart_node(1, extra_args=[ f"-stopatheight={PAUSE_HEIGHT}", *self.extra_args[1]]) + # Upon restart during snapshot tip sync, the node must remain in 'limited' mode. + self.assert_only_network_limited_service(n1) + # Finally connect the nodes and let them sync. # # Set `wait_for_connect=False` to avoid a race between performing connection @@ -470,6 +558,9 @@ def check_tx_counts(final: bool) -> None: self.log.info("Restarted node before snapshot validation completed, reloading...") self.restart_node(1, extra_args=self.extra_args[1]) + # Upon restart, the node must remain in 'limited' mode + self.assert_only_network_limited_service(n1) + # Send snapshot block to n1 out of order. This makes the test less # realistic because normally the snapshot block is one of the last # blocks downloaded, but its useful to test because it triggers more @@ -488,6 +579,10 @@ def check_tx_counts(final: bool) -> None: self.log.info("Ensuring background validation completes") self.wait_until(lambda: len(n1.getchainstates()['chainstates']) == 1) + # Since n1 is a pruned node, it will not signal NODE_NETWORK after + # completing the background sync. + self.assert_only_network_limited_service(n1) + # Ensure indexes have synced. completed_idx_state = { 'basic block filter index': COMPLETE_IDX, @@ -518,12 +613,18 @@ def check_tx_counts(final: bool) -> None: self.log.info("-- Testing all indexes + reindex") assert_equal(n2.getblockcount(), START_HEIGHT) + assert 'NETWORK' in n2.getnetworkinfo()['localservicesnames'] # sanity check self.log.info(f"Loading snapshot into third node from {dump_output['path']}") loaded = n2.loadtxoutset(dump_output['path']) assert_equal(loaded['coins_loaded'], SNAPSHOT_BASE_HEIGHT) assert_equal(loaded['base_height'], SNAPSHOT_BASE_HEIGHT) + # Even though n2 is a full node, it will unset the 'NETWORK' service flag during snapshot loading. + # This indicates other peers that the node will temporarily not provide historical blocks. + self.log.info("Check node2 updated the local services during snapshot load") + self.assert_only_network_limited_service(n2) + for reindex_arg in ['-reindex=1', '-reindex-chainstate=1']: self.log.info(f"Check that restarting with {reindex_arg} will delete the snapshot chainstate") self.restart_node(2, extra_args=[reindex_arg, *self.extra_args[2]]) @@ -547,6 +648,11 @@ def check_tx_counts(final: bool) -> None: msg = "Unable to load UTXO snapshot: Can't activate a snapshot-based chainstate more than once" assert_raises_rpc_error(-32603, msg, n2.loadtxoutset, dump_output['path']) + # Upon restart, the node must stay in 'limited' mode until the background + # chain sync completes. + self.restart_node(2, extra_args=self.extra_args[2]) + self.assert_only_network_limited_service(n2) + self.connect_nodes(0, 2) self.wait_until(lambda: n2.getchainstates()['chainstates'][-1]['blocks'] == FINAL_HEIGHT) self.sync_blocks(nodes=(n0, n2)) @@ -554,6 +660,9 @@ def check_tx_counts(final: bool) -> None: self.log.info("Ensuring background validation completes") self.wait_until(lambda: len(n2.getchainstates()['chainstates']) == 1) + # Once background chain sync completes, the full node must start offering historical blocks again. + self.wait_until(lambda: {'NETWORK', 'NETWORK_LIMITED'}.issubset(n2.getnetworkinfo()['localservicesnames'])) + completed_idx_state = { 'basic block filter index': COMPLETE_IDX, 'coinstatsindex': COMPLETE_IDX, @@ -588,6 +697,9 @@ def check_tx_counts(final: bool) -> None: self.test_snapshot_in_a_divergent_chain(dump_output['path']) + # The following test cleans node2 and node3 chain directories. + #self.test_sync_from_assumeutxo_node(snapshot=dump_output) + @dataclass class Block: hash: str