diff --git a/CMakeLists.txt b/CMakeLists.txt index 75a3a2fdb..a44ecc6ec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.15) set(_CLIENT_VERSION_MAJOR 0) set(_CLIENT_VERSION_MINOR 20) -set(_CLIENT_VERSION_REVISION 22) +set(_CLIENT_VERSION_REVISION 23) set(_CLIENT_VERSION_BUILD 0) set(_CLIENT_VERSION_IS_RELEASE false) set(_COPYRIGHT_YEAR 2022) diff --git a/build_msvc/libpocketcoin_server/libpocketcoin_server.vcxproj b/build_msvc/libpocketcoin_server/libpocketcoin_server.vcxproj index f2a27db1a..5453ed9df 100644 --- a/build_msvc/libpocketcoin_server/libpocketcoin_server.vcxproj +++ b/build_msvc/libpocketcoin_server/libpocketcoin_server.vcxproj @@ -244,7 +244,7 @@ - + diff --git a/build_msvc/pocketcoin_config.h b/build_msvc/pocketcoin_config.h index 597ed381a..1b0823177 100644 --- a/build_msvc/pocketcoin_config.h +++ b/build_msvc/pocketcoin_config.h @@ -14,7 +14,7 @@ #define CLIENT_VERSION_MINOR 20 /* Build revision */ -#define CLIENT_VERSION_REVISION 22 +#define CLIENT_VERSION_REVISION 23 /* Version Build */ #define CLIENT_VERSION_BUILD 0 @@ -346,7 +346,7 @@ #define PACKAGE_NAME "Pocketnet Core" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "Pocketnet Core 0.20.22" +#define PACKAGE_STRING "Pocketnet Core 0.20.23" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "pocketcoin" @@ -355,7 +355,7 @@ #define PACKAGE_URL "https://github.com/pocketnetteam" /* Define to the version of this package. */ -#define PACKAGE_VERSION "0.20.22" +#define PACKAGE_VERSION "0.20.23" /* Define to necessary symbol if this constant uses a non-standard name on your system. */ diff --git a/configure.ac b/configure.ac index b886a326d..0998a2516 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 0) define(_CLIENT_VERSION_MINOR, 20) -define(_CLIENT_VERSION_REVISION, 22) +define(_CLIENT_VERSION_REVISION, 23) define(_CLIENT_VERSION_BUILD, 0) define(_CLIENT_VERSION_IS_RELEASE, true) define(_COPYRIGHT_YEAR, 2022) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 37194e52b..13af94c58 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -362,7 +362,7 @@ add_library(${POCKETDB} pocketdb/models/base/TransactionOutput.h pocketdb/models/base/SocialTransaction.h pocketdb/models/base/Rating.h - pocketdb/models/base/ReturnDtoModels.h + pocketdb/models/base/DtoModels.h pocketdb/models/dto/Default.h pocketdb/models/dto/Coinbase.h pocketdb/models/dto/Coinstake.h @@ -785,6 +785,8 @@ add_library(${POCKETCOIN_SERVER} pocketdb/repositories/CheckpointRepository.cpp pocketdb/repositories/SystemRepository.h pocketdb/repositories/SystemRepository.cpp + pocketdb/repositories/MigrationRepository.h + pocketdb/repositories/MigrationRepository.cpp pocketdb/repositories/web/NotifierRepository.h pocketdb/repositories/web/NotifierRepository.cpp pocketdb/repositories/web/WebRepository.h diff --git a/src/Makefile.am b/src/Makefile.am index 027d3ad6d..c81918992 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -127,6 +127,7 @@ POCKETDB_H = \ pocketdb/repositories/RatingsRepository.h \ pocketdb/repositories/CheckpointRepository.h \ pocketdb/repositories/SystemRepository.h \ + pocketdb/repositories/MigrationRepository.h \ pocketdb/repositories/web/WebRepository.h \ pocketdb/repositories/web/WebRpcRepository.h \ pocketdb/repositories/web/NotifierRepository.h \ @@ -175,7 +176,7 @@ POCKETDB_H = \ pocketdb/models/base/SocialTransaction.h \ pocketdb/models/base/Rating.h \ pocketdb/models/base/Payload.h \ - pocketdb/models/base/ReturnDtoModels.h \ + pocketdb/models/base/DtoModels.h \ \ pocketdb/models/dto/Default.h \ pocketdb/models/dto/Coinbase.h \ @@ -228,6 +229,7 @@ POCKETDB_CPP = \ pocketdb/repositories/RatingsRepository.cpp \ pocketdb/repositories/CheckpointRepository.cpp \ pocketdb/repositories/SystemRepository.cpp \ + pocketdb/repositories/MigrationRepository.cpp \ pocketdb/repositories/web/WebRepository.cpp \ pocketdb/repositories/web/WebRpcRepository.cpp \ pocketdb/repositories/web/NotifierRepository.cpp \ diff --git a/src/init.cpp b/src/init.cpp index 1b7ce929c..fde8d8ceb 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -173,6 +173,7 @@ void ShutdownPocketServices() PocketDb::RatingsRepoInst.Destroy(); PocketDb::ConsensusRepoInst.Destroy(); PocketDb::NotifierRepoInst.Destroy(); + PocketDb::MigrationRepoInst.Destroy(); PocketDb::SQLiteDbInst.DetachDatabase("web"); PocketDb::SQLiteDbInst.Close(); @@ -849,7 +850,10 @@ static void ThreadImport(std::vector vImportFiles) int i = (int)gArgs.GetArg("-reindex-start", 0); LogPrintf("Start indexing pocketnet part at height %d\n", i); - PocketServices::ChainPostProcessing::Rollback(i); + if (i == 0) + PocketDb::ChainRepoInst.ClearDatabase(); + else + PocketServices::ChainPostProcessing::Rollback(i); while (i <= chainActive.Height() && !ShutdownRequested()) { @@ -1714,6 +1718,12 @@ bool AppInitMain() if (!gArgs.GetBoolArg("-withoutweb", false)) PocketServices::WebPostProcessorInst.Start(threadGroup); + if (ShutdownRequested()) + { + LogPrintf("Shutdown requested. Exiting.\n"); + return false; + } + // ********************************************************* Step 4b: Additional settings if (gArgs.GetArg("-reindex", 0) == 4) diff --git a/src/pocketdb/SQLiteConnection.cpp b/src/pocketdb/SQLiteConnection.cpp index b451adda6..d7a0fcbee 100644 --- a/src/pocketdb/SQLiteConnection.cpp +++ b/src/pocketdb/SQLiteConnection.cpp @@ -18,6 +18,7 @@ namespace PocketDb ExplorerRepoInst = make_shared(*SQLiteDbInst); SearchRepoInst = make_shared(*SQLiteDbInst); TransactionRepoInst = make_shared(*SQLiteDbInst); + ConsensusRepoInst = make_shared(*SQLiteDbInst); } SQLiteConnection::~SQLiteConnection() @@ -28,6 +29,7 @@ namespace PocketDb ExplorerRepoInst->Destroy(); SearchRepoInst->Destroy(); TransactionRepoInst->Destroy(); + ConsensusRepoInst->Destroy(); SQLiteDbInst->DetachDatabase("web"); SQLiteDbInst->Close(); diff --git a/src/pocketdb/SQLiteConnection.h b/src/pocketdb/SQLiteConnection.h index 70739c1e6..3b717a6f4 100644 --- a/src/pocketdb/SQLiteConnection.h +++ b/src/pocketdb/SQLiteConnection.h @@ -10,6 +10,7 @@ #include "pocketdb/repositories/web/WebRpcRepository.h" #include "pocketdb/repositories/web/ExplorerRepository.h" #include "pocketdb/repositories/web/SearchRepository.h" +#include "pocketdb/repositories/ConsensusRepository.h" #include "pocketdb/repositories/TransactionRepository.h" #include "pocketdb/web/PocketFrontend.h" @@ -34,6 +35,7 @@ namespace PocketDb ExplorerRepositoryRef ExplorerRepoInst; SearchRepositoryRef SearchRepoInst; TransactionRepositoryRef TransactionRepoInst; + ConsensusRepositoryRef ConsensusRepoInst; }; diff --git a/src/pocketdb/SQLiteDatabase.cpp b/src/pocketdb/SQLiteDatabase.cpp index 1afa9c56c..9d48b051d 100644 --- a/src/pocketdb/SQLiteDatabase.cpp +++ b/src/pocketdb/SQLiteDatabase.cpp @@ -59,6 +59,25 @@ namespace PocketDb ConsensusRepoInst.Init(); NotifierRepoInst.Init(); SystemRepoInst.Init(); + MigrationRepoInst.Init(); + + // Execute migration scripts + if (gArgs.GetArg("-reindex", 0) == 0) + { + if (!MigrationRepoInst.SplitLikers()) + { + LogPrintf("SQLDB Migration: SplitLikers completed.\n"); + StartShutdown(); + return; + } + + if (!MigrationRepoInst.AccumulateLikers()) + { + LogPrintf("SQLDB Migration: AccumulateLikers completed.\n"); + StartShutdown(); + return; + } + } // Open, create structure and close `web` db PocketDbMigrationRef webDbMigration = std::make_shared(); diff --git a/src/pocketdb/consensus/Base.h b/src/pocketdb/consensus/Base.h index 271b3862c..aa4e522d5 100644 --- a/src/pocketdb/consensus/Base.h +++ b/src/pocketdb/consensus/Base.h @@ -166,6 +166,8 @@ namespace PocketConsensus enum ConsensusLimit { + ConsensusLimit_depth, + ConsensusLimit_threshold_reputation, ConsensusLimit_threshold_reputation_score, ConsensusLimit_threshold_balance, @@ -173,7 +175,20 @@ namespace PocketConsensus ConsensusLimit_threshold_likers_count, ConsensusLimit_threshold_low_likers_count, ConsensusLimit_threshold_low_likers_depth, - ConsensusLimit_depth, + + // Thresholds for obtaining badges - SHARK + threshold_shark_reg_depth, + threshold_shark_likers_all, + threshold_shark_likers_content, + threshold_shark_likers_comment, + threshold_shark_likers_comment_answer, + + // Thresholds for obtaining badges - WHALE + threshold_whale_reg_depth, + threshold_whale_likers_all, + threshold_whale_likers_content, + threshold_whale_likers_comment, + threshold_whale_likers_comment_answer, ConsensusLimit_trial_post, ConsensusLimit_trial_video, @@ -235,104 +250,26 @@ namespace PocketConsensus typedef map>> ConsensusLimits; static inline ConsensusLimits m_consensus_limits = { - // ConsensusLimit_bad_reputation - { - ConsensusLimit_bad_reputation, - { - { - NetworkMain, - { - {0, -500} - } - }, - { - NetworkTest, - { - {0, -50} - } - } - } - }, - // ConsensusLimit_threshold_reputation - { - ConsensusLimit_threshold_reputation, - { - { - NetworkMain, - { - {0, 500}, - {292800, 1000} - } - }, - { - NetworkTest, - { - {0, 100}, - {761000, 10} - } - } - } - }, - // ConsensusLimit_threshold_reputation_score - { - ConsensusLimit_threshold_reputation_score, - { - { - NetworkMain, - { - {0, -10000}, - {108300, 500}, - {292800, 1000} - } - }, - { - NetworkTest, - { - {0, 0}, - {100000, 100} - } - } - } - }, - // ConsensusLimit_threshold_balance - { - ConsensusLimit_threshold_balance, - { - { - NetworkMain, - { - {0, 50 * COIN} - } - }, - { - NetworkTest, - { - {0, 5 * COIN} - } - } - } - }, - // ConsensusLimit_threshold_balance_pro - { - ConsensusLimit_threshold_balance_pro, - { - { - NetworkMain, - { - {0, INT64_MAX}, - {65000, 250 * COIN} - } - }, - { - NetworkTest, - { - {0, INT64_MAX}, - {65000, 25 * COIN} - } - } - } - }, - // ConsensusLimit_threshold_likers_count + { ConsensusLimit_bad_reputation, { + { NetworkMain, { {0, -500} } }, + { NetworkTest, { {0, -50} } } + } }, + { ConsensusLimit_threshold_reputation, { + { NetworkMain, { {0, 500}, {292800, 1000} } }, + { NetworkTest, { {0, 100}, {761000, 10} } } + } }, + { ConsensusLimit_threshold_reputation_score, { + { NetworkMain, { {0, -10000}, {108300, 500}, {292800, 1000} } }, + { NetworkTest, { {0, 0}, {100000, 100} } } + } }, + { ConsensusLimit_threshold_balance, { + { NetworkMain, { {0, 50 * COIN} } }, + { NetworkTest, { {0, 5 * COIN} } } + } }, + { ConsensusLimit_threshold_balance_pro, { + { NetworkMain, { {0, INT64_MAX}, {65000, 250 * COIN} } }, + { NetworkTest, { {0, INT64_MAX}, {65000, 25 * COIN} } } + } }, { ConsensusLimit_threshold_likers_count, { { NetworkMain, { {0, 0}, {1124000, 100} }}, { NetworkTest, { {0, 0}, {100000, 10} }}, @@ -342,737 +279,224 @@ namespace PocketConsensus { NetworkMain, { {0, 30} }}, { NetworkTest, { {0, 30}, {761000, 0} }} }}, - // ConsensusLimit_threshold_low_likers_depth - { - ConsensusLimit_threshold_low_likers_depth, - { - { - NetworkMain, - { - {1180000, 250'000}, - } - }, - { - NetworkTest, - { - {0, 250'000}, - } - } - } - }, - // ConsensusLimit_depth - { - ConsensusLimit_depth, - { - { - NetworkMain, - { - {0, 86400}, - {1180000, 1440} - } - }, - { - NetworkTest, - { - {0, 1440} - } - } - } - }, - - // ConsensusLimit_trial_post - { - ConsensusLimit_trial_post, - { - { - NetworkMain, - { - {0, 15}, - {1324655, 5} - } - }, - { - NetworkTest, - { - {0, 15} - } - } - } - }, - // ConsensusLimit_trial_video - { - ConsensusLimit_trial_video, - { - { - NetworkMain, - { - {0, 15}, - {1324655, 5} - } - }, - { - NetworkTest, - { - {0, 15} - } - } - } - }, - // ConsensusLimit_trial_article - { - ConsensusLimit_trial_article, - { - { - NetworkMain, - { - {0, 1} - } - }, - { - NetworkTest, - { - {0, 10} - } - } - } - }, - // ConsensusLimit_trial_score - { - ConsensusLimit_trial_score, - { - { - NetworkMain, - { - {0, 45}, - {175600, 100}, - {1324655, 15} - } - }, - { - NetworkTest, - { - {0, 100} - } - } - } - }, - // ConsensusLimit_trial_complain - { - ConsensusLimit_trial_complain, - { - { - NetworkMain, - { - {0, 6} - } - }, - { - NetworkTest, - { - {0, 6} - } - } - } - }, - // ConsensusLimit_full_post - { - ConsensusLimit_full_post, - { - { - NetworkMain, - { - {0, 30} - } - }, - { - NetworkTest, - { - {0, 30} - } - } - } - }, - // ConsensusLimit_full_video - { - ConsensusLimit_full_video, - { - { - NetworkMain, - { - {0, 30} - } - }, - { - NetworkTest, - { - {0, 30} - } - } - } - }, - // ConsensusLimit_full_article - { - ConsensusLimit_full_article, - { - { - NetworkMain, - { - {0, 3} - } - }, - { - NetworkTest, - { - {0, 30} - } - } - } - }, - // ConsensusLimit_full_score - { - ConsensusLimit_full_score, - { - { - NetworkMain, - { - {0, 90}, - {175600, 200} - } - }, - { - NetworkTest, - { - {0, 200} - } - } - } - }, - // ConsensusLimit_full_complain - { - ConsensusLimit_full_complain, - { - { - NetworkMain, - { - {0, 12} - } - }, - { - NetworkTest, - { - {0, 12} - } - } - } - }, - // ConsensusLimit_pro_video - { - ConsensusLimit_pro_video, - { - { - NetworkMain, - { - {0, 0}, - {1324655, 100} - } - }, - { - NetworkTest, - { - {0, 100} - } - } - } - }, - - // ConsensusLimit_post_edit_count - { - ConsensusLimit_post_edit_count, - { - { - NetworkMain, - { - {0, 5} - } - }, - { - NetworkTest, - { - {0, 5} - } - } - } - }, - // ConsensusLimit_video_edit_count - { - ConsensusLimit_video_edit_count, - { - { - NetworkMain, - { - {0, 5} - } - }, - { - NetworkTest, - { - {0, 5} - } - } - } - }, - // ConsensusLimit_article_edit_count - { - ConsensusLimit_article_edit_count, - { - { - NetworkMain, - { - {0, 10} - } - }, - { - NetworkTest, - { - {0, 10} - } - } - } - }, - // ConsensusLimit_comment_edit_count - { - ConsensusLimit_comment_edit_count, - { - { - NetworkMain, - { - {0, 4} - } - }, - { - NetworkTest, - { - {0, 4} - } - } - } - }, - - // ConsensusLimit_edit_user_depth - { - ConsensusLimit_edit_user_depth, - { - { - NetworkMain, - { - {0, 3600}, - {1180000, 60} - } - }, - { - NetworkTest, - { - {0, 30} - } - } - } - }, - // ConsensusLimit_edit_user_daily_count - { - ConsensusLimit_edit_user_daily_count, - { - { - NetworkMain, - { - {0, 10} - } - }, - { - NetworkTest, - { - {0, 10} - } - } - } - }, - // ConsensusLimit_edit_post_depth - { - ConsensusLimit_edit_post_depth, - { - { - NetworkMain, - { - {0, 86400}, - {1180000, 1440} - } - }, - { - NetworkTest, - { - {0, 1440} - } - } - } - }, - // ConsensusLimit_edit_video_depth - { - ConsensusLimit_edit_video_depth, - { - { - NetworkMain, - { - {0, 1440} - } - }, - { - NetworkTest, - { - {0, 1440} - } - } - } - }, - // ConsensusLimit_edit_article_depth - { - ConsensusLimit_edit_article_depth, - { - { - NetworkMain, - { - {0, 4320} - } - }, - { - NetworkTest, - { - {0, 4320} - } - } - } - }, - // ConsensusLimit_edit_comment_depth - { - ConsensusLimit_edit_comment_depth, - { - { - NetworkMain, - { - {0, 86400}, - {1180000, 1440} - } - }, - { - NetworkTest, - { - {0, 1440} - } - } - } - }, - - // ConsensusLimit_max_user_size - { - ConsensusLimit_max_user_size, - { - { - NetworkMain, - { - {0, 2000} - } - }, - { - NetworkTest, - { - {0, 2000} - } - } - } - }, - // ConsensusLimit_max_post_size - { - ConsensusLimit_max_post_size, - { - { - NetworkMain, - { - {0, 60000} - } - }, - { - NetworkTest, - { - {0, 60000} - } - } - } - }, - // ConsensusLimit_max_video_size - { - ConsensusLimit_max_video_size, - { - { - NetworkMain, - { - {0, 60000} - } - }, - { - NetworkTest, - { - {0, 60000} - } - } - } - }, - // ConsensusLimit_max_article_size - { - ConsensusLimit_max_article_size, - { - { - NetworkMain, - { - {0, 120000} - } - }, - { - NetworkTest, - { - {0, 60000} - } - } - } - }, - // ConsensusLimit_scores_one_to_one - { - ConsensusLimit_scores_one_to_one, - { - { - NetworkMain, - { - {0, 99999}, - {225000, 2} - } - }, - { - NetworkTest, - { - {0, 2} - } - } - } - }, - // ConsensusLimit_scores_one_to_one_over_comment - { - ConsensusLimit_scores_one_to_one_over_comment, - { - { - NetworkMain, - { - {0, 20} - } - }, - { - NetworkTest, - { - {0, 20} - } - } - } - }, - // ConsensusLimit_scores_one_to_one_depth - { - ConsensusLimit_scores_one_to_one_depth, - { - { - NetworkMain, - { - {0, 336 * 24 * 3600}, - {225000, 1 * 24 * 3600}, - {292800, 7 * 24 * 3600}, - {322700, 2 * 24 * 3600} - } - }, - { - NetworkTest, - { - {0, 2 * 24 * 3600} - } - } - } - }, - // ConsensusLimit_trial_comment - { - ConsensusLimit_trial_comment, - { - { - NetworkMain, - { - {0, 150} - } - }, - { - NetworkTest, - { - {0, 150} - } - } - } - }, - // ConsensusLimit_trial_comment_score - { - ConsensusLimit_trial_comment_score, - { - { - NetworkMain, - { - {0, 300} - } - }, - { - NetworkTest, - { - {0, 300} - } - } - } - }, - // ConsensusLimit_full_comment - { - ConsensusLimit_full_comment, - { - { - NetworkMain, - { - {0, 300} - } - }, - { - NetworkTest, - { - {0, 300} - } - } - } - }, - // ConsensusLimit_full_comment_score - { - ConsensusLimit_full_comment_score, - { - { - NetworkMain, - { - {0, 600} - } - }, - { - NetworkTest, - { - {0, 600} - } - } - } - }, - // ConsensusLimit_max_comment_size - { - ConsensusLimit_max_comment_size, - { - { - NetworkMain, - { - {0, 2000} - } - }, - { - NetworkTest, - { - {0, 2000} - } - } - } - }, - // ConsensusLimit_scores_depth_modify_reputation - { - ConsensusLimit_scores_depth_modify_reputation, - { - { - NetworkMain, - { - {0, 336 * 24 * 3600}, - {322700, 30 * 24 * 3600} - } - }, - { - NetworkTest, - { - {0, 30 * 24 * 3600} - } - } - } - }, + { ConsensusLimit_threshold_low_likers_depth, { + { NetworkMain, { {1180000, 250'000}, } }, + { NetworkTest, { {0, 250'000}, + } + } + } }, + { ConsensusLimit_depth, { + { NetworkMain, { {0, 86400}, {1180000, 1440} } }, + { NetworkTest, { {0, 1440} } } + } }, + + // Thresholds for obtaining badges - SHARK + { threshold_shark_reg_depth, { + { NetworkMain, { {0, 129600} } }, + { NetworkTest, { {0, 1} } } + } }, + { threshold_shark_likers_all, { + { NetworkMain, { {0, 100} } }, + { NetworkTest, { {0, 1} } } + } }, + { threshold_shark_likers_content, { + { NetworkMain, { {0, 0} } }, + { NetworkTest, { {0, 0} } } + } }, + { threshold_shark_likers_comment, { + { NetworkMain, { {0, 15} } }, + { NetworkTest, { {0, 1} } } + } }, + { threshold_shark_likers_comment_answer, { + { NetworkMain, { {0, 0} } }, + { NetworkTest, { {0, 0} } } + } }, + + // Thresholds for obtaining badges - WHALE + { threshold_shark_reg_depth, { + { NetworkMain, { {0, 207360} } }, + { NetworkTest, { {0, 1} } } + } }, + { threshold_whale_likers_all, { + { NetworkMain, { {0, 1000} } }, + { NetworkTest, { {0, 10} } } + } }, + { threshold_whale_likers_content, { + { NetworkMain, { {0, 100} } }, + { NetworkTest, { {0, 10} } } + } }, + { threshold_whale_likers_comment, { + { NetworkMain, { {0, 100} } }, + { NetworkTest, { {0, 10} } } + } }, + { threshold_whale_likers_comment_answer, { + { NetworkMain, { {0, 100} } }, + { NetworkTest, { {0, 10} } } + } }, + + // Other + { ConsensusLimit_edit_user_depth, { + { NetworkMain, { {0, 3600}, {1180000, 60} } }, + { NetworkTest, { {0, 30} } } + } }, + { ConsensusLimit_edit_user_daily_count, { + { NetworkMain, { {0, 10} } }, + { NetworkTest, { {0, 10} } } + } }, + { ConsensusLimit_edit_post_depth, { + { NetworkMain, { {0, 86400}, {1180000, 1440} } }, + { NetworkTest, { {0, 1440} } } + } }, + { ConsensusLimit_edit_video_depth, { + { NetworkMain, { {0, 1440} } }, + { NetworkTest, { {0, 1440} } } + } }, + { ConsensusLimit_edit_article_depth, { + { NetworkMain, { {0, 4320} } }, + { NetworkTest, { {0, 4320} } } + } }, + { ConsensusLimit_edit_comment_depth, { + { NetworkMain, { {0, 86400}, {1180000, 1440} } }, + { NetworkTest, { {0, 1440} } } + } }, + { ConsensusLimit_scores_one_to_one, { + { NetworkMain, { {0, 99999}, {225000, 2} } }, + { NetworkTest, { {0, 2} } } + } }, + { ConsensusLimit_scores_one_to_one_over_comment, { + { NetworkMain, { {0, 20} } }, + { NetworkTest, { {0, 20} } } + } }, + { ConsensusLimit_scores_one_to_one_depth, { + { NetworkMain, { {0, 336 * 24 * 3600}, {225000, 1 * 24 * 3600}, {292800, 7 * 24 * 3600}, {322700, 2 * 24 * 3600} } }, + { NetworkTest, { {0, 2 * 24 * 3600} } } + } }, + { ConsensusLimit_scores_depth_modify_reputation, { + { NetworkMain, { {0, 336 * 24 * 3600}, {322700, 30 * 24 * 3600} } }, + { NetworkTest, { {0, 30 * 24 * 3600} } } + } }, // TODO (brangr) (v0.21.0): change GetLotteryReferralDepth Time to Height - // ConsensusLimit_lottery_referral_depth - { - ConsensusLimit_lottery_referral_depth, - { - { - NetworkMain, - { - {0, 30 * 24 * 3600} - } - }, - { - NetworkTest, - { - {0, 30 * 24 * 3600} - } - } - } - }, - // ConsensusLimit_max_account_setting_size - { - ConsensusLimit_max_account_setting_size, - { - { - NetworkMain, - { - {0, 2048} - } - }, - { - NetworkTest, - { - {0, 2048} - } - } - } - }, - // ConsensusLimit_account_settings_daily_count - { - ConsensusLimit_account_settings_daily_count, - { - { - NetworkMain, - { - {0, 5} - } - }, - { - NetworkTest, - { - {0, 5} - } - } - } - }, - - // - // MODERATION - // - + { ConsensusLimit_lottery_referral_depth, { + { NetworkMain, { {0, 30 * 24 * 3600} } }, + { NetworkTest, { {0, 30 * 24 * 3600} } } + } }, + + // Limits + { ConsensusLimit_trial_post, { + { NetworkMain, { {0, 15}, {1324655, 5} } }, + { NetworkTest, { {0, 15} } } + } }, + { ConsensusLimit_trial_video, { + { NetworkMain, { {0, 15}, {1324655, 5} } }, + { NetworkTest, { {0, 15} } } + } }, + { ConsensusLimit_trial_article, { + { NetworkMain, { {0, 1} } }, + { NetworkTest, { {0, 10} } } + } }, + { ConsensusLimit_trial_score, { + { NetworkMain, { {0, 45}, {175600, 100}, {1324655, 15} } }, + { NetworkTest, { {0, 100} } } + } }, + { ConsensusLimit_trial_complain, { + { NetworkMain, { {0, 6} } }, + { NetworkTest, { {0, 6} } } + } }, + { ConsensusLimit_trial_comment, { + { NetworkMain, { {0, 150}, {1757000, 50} } }, + { NetworkTest, { {0, 150} } } + } }, + { ConsensusLimit_trial_comment_score, { + { NetworkMain, { {0, 300}, {1757000, 100} } }, + { NetworkTest, { {0, 300} } } + } }, + + { ConsensusLimit_full_post, { + { NetworkMain, { {0, 30}, {1757000, 10} } }, + { NetworkTest, { {0, 30} } } + } }, + { ConsensusLimit_full_video, { + { NetworkMain, { {0, 30}, {1757000, 10} } }, + { NetworkTest, { {0, 30} } } + } }, + { ConsensusLimit_full_article, { + { NetworkMain, { {0, 3} } }, + { NetworkTest, { {0, 30} } } + } }, + { ConsensusLimit_full_score, { + { NetworkMain, { {0, 90}, {175600, 200}, {1757000, 60} } }, + { NetworkTest, { {0, 200} } } + } }, + { ConsensusLimit_full_complain, { + { NetworkMain, { {0, 12} } }, + { NetworkTest, { {0, 12} } } + } }, + { ConsensusLimit_full_comment, { + { NetworkMain, { {0, 300}, {1757000, 100} } }, + { NetworkTest, { {0, 300} } } + } }, + { ConsensusLimit_full_comment_score, { + { NetworkMain, { {0, 600}, {1757000, 200} } }, + { NetworkTest, { {0, 600} } } + } }, + + { ConsensusLimit_pro_video, { + { NetworkMain, { {0, 0}, {1324655, 100} } }, + { NetworkTest, { {0, 100} } } + } }, + { ConsensusLimit_moderation_flag_count, { { NetworkMain, { {0, 30} }}, { NetworkTest, { {0, 100} }} }}, + + { ConsensusLimit_post_edit_count, { + { NetworkMain, { {0, 5} } }, + { NetworkTest, { {0, 5} } } + } }, + { ConsensusLimit_video_edit_count, { + { NetworkMain, { {0, 5} } }, + { NetworkTest, { {0, 5} } } + } }, + { ConsensusLimit_article_edit_count, { + { NetworkMain, { {0, 10} } }, + { NetworkTest, { {0, 10} } } + } }, + { ConsensusLimit_comment_edit_count, { + { NetworkMain, { {0, 4} } }, + { NetworkTest, { {0, 4} } } + } }, + + { ConsensusLimit_account_settings_daily_count, { + { NetworkMain, { {0, 5} } }, + { NetworkTest, { {0, 5} } } + } }, + + // Size + { ConsensusLimit_max_user_size, { + { NetworkMain, { {0, 2000} } }, + { NetworkTest, { {0, 2000} } } + } }, + { ConsensusLimit_max_post_size, { + { NetworkMain, { {0, 60000} } }, + { NetworkTest, { {0, 60000} } } + } }, + { ConsensusLimit_max_video_size, { + { NetworkMain, { {0, 60000} } }, + { NetworkTest, { {0, 60000} } } + } }, + { ConsensusLimit_max_article_size, { + { NetworkMain, { {0, 120000} } }, + { NetworkTest, { {0, 60000} } } + } }, + { ConsensusLimit_max_comment_size, { + { NetworkMain, { {0, 2000} } }, + { NetworkTest, { {0, 2000} } } + } }, + { ConsensusLimit_max_account_setting_size, { + { NetworkMain, { {0, 2048} } }, + { NetworkTest, { {0, 2048} } } + } }, }; diff --git a/src/pocketdb/consensus/Reputation.h b/src/pocketdb/consensus/Reputation.h index 9683d1313..c22d825de 100644 --- a/src/pocketdb/consensus/Reputation.h +++ b/src/pocketdb/consensus/Reputation.h @@ -20,7 +20,7 @@ namespace PocketConsensus return GetConsensusLimit(ConsensusLimit_threshold_likers_count); } - virtual string SelectAddressScoreContent(shared_ptr& scoreData, bool lottery) + virtual string SelectAddressScoreContent(ScoreDataDtoRef& scoreData, bool lottery) { if (lottery) return scoreData->ScoreAddressHash; @@ -28,10 +28,10 @@ namespace PocketConsensus return scoreData->ContentAddressHash; } - virtual bool AllowModifyReputationOverPost(shared_ptr& scoreData, bool lottery) + virtual bool AllowModifyReputationOverPost(ScoreDataDtoRef& scoreData, bool lottery) { // Check user reputation - if (!IsShark(SelectAddressScoreContent(scoreData, lottery), ConsensusLimit_threshold_reputation_score)) + if (!GetBadges(SelectAddressScoreContent(scoreData, lottery), ConsensusLimit_threshold_reputation_score).Shark) return false; // Disable reputation increment if from one address to one address > 2 scores over day @@ -63,10 +63,10 @@ namespace PocketConsensus return true; } - virtual bool AllowModifyReputationOverComment(shared_ptr& scoreData, bool lottery) + virtual bool AllowModifyReputationOverComment(ScoreDataDtoRef& scoreData, bool lottery) { // Check user reputation - if (!IsShark(scoreData->ScoreAddressHash, ConsensusLimit_threshold_reputation_score)) + if (!GetBadges(scoreData->ScoreAddressHash, ConsensusLimit_threshold_reputation_score).Shark) return false; // Disable reputation increment if from one address to one address > Limit::scores_one_to_one scores over Limit::scores_one_to_one_depth @@ -94,21 +94,60 @@ namespace PocketConsensus return true; } + virtual void ExtendLikersList(vector& lkrs, int likerId) + { + lkrs.clear(); + lkrs.emplace_back(likerId); + } + + virtual void ExtendLikersList(map>>& likersValues, map>& ratingValues, const ScoreDataDtoRef& scoreData) + { + for (const auto& type : likersValues) + if (type.first != RatingType::ACCOUNT_LIKERS) + likersValues[type.first][scoreData->ContentAddressId].clear(); + + likersValues[scoreData->LikerType(false)][scoreData->ContentAddressId].emplace_back(scoreData->ScoreAddressId); + + ratingValues[RatingType::ACCOUNT_LIKERS_POST_LAST][scoreData->ContentAddressId] = 0; + ratingValues[RatingType::ACCOUNT_LIKERS_COMMENT_ROOT_LAST][scoreData->ContentAddressId] = 0; + ratingValues[RatingType::ACCOUNT_LIKERS_COMMENT_ANSWER_LAST][scoreData->ContentAddressId] = 0; + } + + virtual bool ValidateScoreValue(const ScoreDataDtoRef& scoreData) + { + // For scores to posts allowed only 4 and 5 values + if (scoreData->ScoreType == ACTION_SCORE_CONTENT) + if (scoreData->ScoreValue == 4 || scoreData->ScoreValue == 5) + return true; + + // For scores to comments allowed only 1 value + if (scoreData->ScoreType == ACTION_SCORE_COMMENT) + if (scoreData->ScoreValue == 1) + return true; + + // Another types not allowed + return false; + } + public: explicit ReputationConsensus(int height) : BaseConsensus(height) {} - virtual bool IsShark(const AccountData& accountData, ConsensusLimit limit = ConsensusLimit_threshold_reputation) + virtual BadgeSet GetBadges(const AccountData& data, ConsensusLimit limit = ConsensusLimit_threshold_reputation) { - auto minReputation = GetConsensusLimit(limit); - auto minLikersCount = GetMinLikers(accountData.RegistrationHeight); + BadgeSet badgeSet; - return accountData.Reputation >= minReputation && accountData.LikersCount >= minLikersCount; + badgeSet.Developer = IsDeveloper(data.AddressHash); + badgeSet.Shark = data.Reputation >= GetConsensusLimit(limit) && data.LikersAll() >= GetMinLikers(data.RegistrationHeight); + badgeSet.Whale = false; + badgeSet.Moderator = false; + + return badgeSet; } - virtual bool IsShark(const string& address, ConsensusLimit limit = ConsensusLimit_threshold_reputation) + virtual BadgeSet GetBadges(const string& address, ConsensusLimit limit = ConsensusLimit_threshold_reputation) { auto accountData = ConsensusRepoInst.GetAccountData(address); - return IsShark(accountData, limit); + return GetBadges(accountData, limit); } virtual AccountMode GetAccountMode(int reputation, int64_t balance) @@ -128,7 +167,7 @@ namespace PocketConsensus return {GetAccountMode(reputation, balance), reputation, balance}; } - virtual bool AllowModifyReputation(shared_ptr& scoreData, bool lottery) + virtual bool AllowModifyReputation(ScoreDataDtoRef& scoreData, bool lottery) { if (scoreData->ScoreType == TxType::ACTION_SCORE_CONTENT) return AllowModifyReputationOverPost(scoreData, lottery); @@ -151,21 +190,6 @@ namespace PocketConsensus return true; } } - - virtual void PrepareAccountLikers(map>& accountLikersSrc, map>& accountLikers) - { - for (const auto& account : accountLikersSrc) - { - for (const auto& likerId : account.second) - { - if (!PocketDb::RatingsRepoInst.ExistsLiker(account.first, likerId, Height)) - { - accountLikers[account.first].clear(); - accountLikers[account.first].emplace_back(likerId); - } - } - } - } virtual int GetScoreContentAuthorValue(int scoreValue) { @@ -176,6 +200,74 @@ namespace PocketConsensus { return scoreValue; } + + virtual void DistinctScores(const ScoreDataDtoRef& scoreData, vector& distinctScores) + { + if (!ValidateScoreValue(scoreData)) + return; + + auto it = find_if( + distinctScores.begin(), + distinctScores.end(), + [&scoreData](const ScoreDataDtoRef& _scoreData) + { + return _scoreData->ContentAddressId == scoreData->ContentAddressId && + _scoreData->ScoreAddressId == scoreData->ScoreAddressId; + }); + + if (it == distinctScores.end()) + distinctScores.push_back(scoreData); + } + + virtual void ValidateAccountLiker(const ScoreDataDtoRef& scoreData, map>>& likersValues, map>& ratingValues) + { + // Check already added to list and exists in DB + auto& lkrs = likersValues[ACCOUNT_LIKERS][scoreData->ContentAddressId]; + if (find(lkrs.begin(), lkrs.end(), scoreData->ScoreAddressId) == lkrs.end()) + { + if (!PocketDb::RatingsRepoInst.ExistsLiker( + scoreData->ContentAddressId, + scoreData->ScoreAddressId, + { ACCOUNT_LIKERS } + )) + { + ExtendLikersList( + lkrs, + scoreData->ScoreAddressId + ); + } + } + + // + // Split likers types + // + auto& lkrs_post = likersValues[ACCOUNT_LIKERS_POST][scoreData->ContentAddressId]; + if ((find(lkrs_post.begin(), lkrs_post.end(), scoreData->ScoreAddressId) != lkrs_post.end())) + return; + + auto& lkrs_cmnt_root = likersValues[ACCOUNT_LIKERS_COMMENT_ROOT][scoreData->ContentAddressId]; + if ((find(lkrs_cmnt_root.begin(), lkrs_cmnt_root.end(), scoreData->ScoreAddressId) != lkrs_cmnt_root.end())) + return; + + auto& lkrs_cmnt_answer = likersValues[ACCOUNT_LIKERS_COMMENT_ANSWER][scoreData->ContentAddressId]; + if ((find(lkrs_cmnt_answer.begin(), lkrs_cmnt_answer.end(), scoreData->ScoreAddressId) != lkrs_cmnt_answer.end())) + return; + + if (!PocketDb::RatingsRepoInst.ExistsLiker( + scoreData->ContentAddressId, + scoreData->ScoreAddressId, + { ACCOUNT_LIKERS_POST, ACCOUNT_LIKERS_COMMENT_ROOT, ACCOUNT_LIKERS_COMMENT_ANSWER } + )) + { + ExtendLikersList( + likersValues, + ratingValues, + scoreData + ); + + ratingValues[scoreData->LikerType(true)][scoreData->ContentAddressId] += 1; + } + } }; // Consensus checkpoint at 151600 block @@ -184,7 +276,7 @@ namespace PocketConsensus public: explicit ReputationConsensus_checkpoint_151600(int height) : ReputationConsensus(height) {} protected: - string SelectAddressScoreContent(shared_ptr& scoreData, bool lottery) override + string SelectAddressScoreContent(ScoreDataDtoRef& scoreData, bool lottery) override { return scoreData->ScoreAddressHash; } @@ -205,9 +297,17 @@ namespace PocketConsensus } }; - // Consensus checkpoint at 1324655 block class ReputationConsensus_checkpoint_1324655 : public ReputationConsensus_checkpoint_1180000 { + protected: + void ExtendLikersList(vector& lkrs, int likerId) override + { + lkrs.emplace_back(likerId); + } + void ExtendLikersList(map>>& lkrs, map>& ratingValues, const ScoreDataDtoRef& scoreData) override + { + lkrs[scoreData->LikerType(false)][scoreData->ContentAddressId].emplace_back(scoreData->ScoreAddressId); + } public: explicit ReputationConsensus_checkpoint_1324655(int height) : ReputationConsensus_checkpoint_1180000(height) {} AccountMode GetAccountMode(int reputation, int64_t balance) override @@ -227,25 +327,11 @@ namespace PocketConsensus } }; - // Consensus checkpoint at 1324655_2 block - class ReputationConsensus_checkpoint_1324655_2 : public ReputationConsensus_checkpoint_1324655 - { - public: - explicit ReputationConsensus_checkpoint_1324655_2(int height) : ReputationConsensus_checkpoint_1324655(height) {} - void PrepareAccountLikers(map>& accountLikersSrc, map>& accountLikers) override - { - for (const auto& account : accountLikersSrc) - for (const auto& likerId : account.second) - if (!PocketDb::RatingsRepoInst.ExistsLiker(account.first, likerId, Height)) - accountLikers[account.first].emplace_back(likerId); - } - }; - // Consensus checkpoint: reducing the impact on the reputation of scores 1,2 for content - class ReputationConsensus_checkpoint_scores_content_author_reducing_impact : public ReputationConsensus_checkpoint_1324655_2 + class ReputationConsensus_checkpoint_scores_content_author_reducing_impact : public ReputationConsensus_checkpoint_1324655 { public: - explicit ReputationConsensus_checkpoint_scores_content_author_reducing_impact(int height) : ReputationConsensus_checkpoint_1324655_2(height) {} + explicit ReputationConsensus_checkpoint_scores_content_author_reducing_impact(int height) : ReputationConsensus_checkpoint_1324655(height) {} int GetScoreContentAuthorValue(int scoreValue) override { int multiplier = 10; @@ -254,13 +340,6 @@ namespace PocketConsensus return (scoreValue - 3) * multiplier; } - }; - - // Consensus checkpoint: disable the impact on the reputation of scores -1 for comment - class ReputationConsensus_checkpoint_scores_comment_author_disable_impact : public ReputationConsensus_checkpoint_scores_content_author_reducing_impact - { - public: - explicit ReputationConsensus_checkpoint_scores_comment_author_disable_impact(int height) : ReputationConsensus_checkpoint_scores_content_author_reducing_impact(height) {} int GetScoreCommentAuthorValue(int scoreValue) override { if (scoreValue == -1) @@ -270,6 +349,35 @@ namespace PocketConsensus } }; + // Consensus checkpoint: reducing the impact on the reputation of scores 1,2 for content + class ReputationConsensus_checkpoint_badges : public ReputationConsensus_checkpoint_scores_content_author_reducing_impact + { + public: + explicit ReputationConsensus_checkpoint_badges(int height) : ReputationConsensus_checkpoint_scores_content_author_reducing_impact(height) {} + BadgeSet GetBadges(const AccountData& data, ConsensusLimit limit = ConsensusLimit_threshold_reputation) override + { + BadgeSet badgeSet; + + badgeSet.Developer = IsDeveloper(data.AddressHash); + + badgeSet.Shark = data.LikersAll() >= GetConsensusLimit(threshold_shark_likers_all) + && data.LikersContent >= GetConsensusLimit(threshold_shark_likers_content) + && data.LikersComment >= GetConsensusLimit(threshold_shark_likers_comment) + && data.LikersCommentAnswer >= GetConsensusLimit(threshold_shark_likers_comment_answer) + && Height - data.RegistrationHeight >= GetConsensusLimit(threshold_shark_reg_depth); + + badgeSet.Whale = data.LikersAll() >= GetConsensusLimit(threshold_whale_likers_all) + && data.LikersContent >= GetConsensusLimit(threshold_whale_likers_content) + && data.LikersComment >= GetConsensusLimit(threshold_whale_likers_comment) + && data.LikersCommentAnswer >= GetConsensusLimit(threshold_whale_likers_comment_answer) + && Height - data.RegistrationHeight >= GetConsensusLimit(threshold_whale_reg_depth); + + // badgeSet.Moderator = TODO (brangr): implement for future + + return badgeSet; + } + }; + // Factory for select actual rules version class ReputationConsensusFactory @@ -280,9 +388,8 @@ namespace PocketConsensus { 151600, -1, [](int height) { return make_shared(height); }}, { 1180000, 0, [](int height) { return make_shared(height); }}, { 1324655, 65000, [](int height) { return make_shared(height); }}, - { 1324655, 75000, [](int height) { return make_shared(height); }}, { 1700000, 761000, [](int height) { return make_shared(height); }}, - { 1700000, 772000, [](int height) { return make_shared(height); }}, + { 1757000, 947500, [](int height) { return make_shared(height); }}, }; public: shared_ptr Instance(int height) diff --git a/src/pocketdb/consensus/moderation/Flag.hpp b/src/pocketdb/consensus/moderation/Flag.hpp index a36a1f5c0..04cf1c117 100644 --- a/src/pocketdb/consensus/moderation/Flag.hpp +++ b/src/pocketdb/consensus/moderation/Flag.hpp @@ -32,7 +32,7 @@ namespace PocketConsensus // Only `Shark` account can flag content auto reputationConsensus = ReputationConsensusFactoryInst.Instance(Height); - if (!reputationConsensus->IsShark(*ptx->GetAddress())) + if (!reputationConsensus->GetBadges(*ptx->GetAddress()).Shark) return {false, SocialConsensusResult_LowReputation}; // Target transaction must be a exists and is a content and author should be equals ptx->GetContentAddressHash() diff --git a/src/pocketdb/consensus/social/BoostContent.hpp b/src/pocketdb/consensus/social/BoostContent.hpp index 59ef17d21..ab490ec75 100644 --- a/src/pocketdb/consensus/social/BoostContent.hpp +++ b/src/pocketdb/consensus/social/BoostContent.hpp @@ -35,6 +35,10 @@ namespace PocketConsensus if (*contentTx->GetType() == CONTENT_DELETE) return {false, SocialConsensusResult_CommentDeletedContent}; + // Check Blocking + if (auto[ok, result] = ValidateBlocking(*contentTx->GetString1(), ptx); !ok) + return {false, result}; + return Success; } ConsensusValidateResult Check(const CTransactionRef& tx, const BoostContentRef& ptx) override @@ -66,6 +70,10 @@ namespace PocketConsensus { return {*ptx->GetAddress()}; } + virtual ConsensusValidateResult ValidateBlocking(const string& contentAddress, const BoostContentRef& ptx) + { + return Success; + } }; /******************************************************************************************************************* @@ -82,12 +90,29 @@ namespace PocketConsensus } }; + // Disable scores for blocked accounts + class BoostContentConsensus_checkpoint_disable_for_blocked : public BoostContentConsensus_checkpoint_accept + { + public: + BoostContentConsensus_checkpoint_disable_for_blocked(int height) : BoostContentConsensus_checkpoint_accept(height) {} + protected: + ConsensusValidateResult ValidateBlocking(const string& contentAddress, const BoostContentRef& ptx) override + { + if (auto[existsBlocking, blockingType] = PocketDb::ConsensusRepoInst.GetLastBlockingType( + contentAddress, *ptx->GetAddress()); existsBlocking && blockingType == ACTION_BLOCKING) + return {false, SocialConsensusResult_Blocking}; + + return Success; + } + }; + class BoostContentConsensusFactory { private: const vector> m_rules = { { 0, 0, [](int height) { return make_shared(height); }}, { 1586000, 528100, [](int height) { return make_shared(height); }}, + { 1757000, 953000, [](int height) { return make_shared(height); }}, }; public: shared_ptr Instance(int height) diff --git a/src/pocketdb/consensus/social/Post.hpp b/src/pocketdb/consensus/social/Post.hpp index 37f3fa28e..12ec0e0fe 100644 --- a/src/pocketdb/consensus/social/Post.hpp +++ b/src/pocketdb/consensus/social/Post.hpp @@ -41,8 +41,16 @@ namespace PocketConsensus if (!relayOk && !CheckpointRepoInst.IsSocialCheckpoint(*ptx->GetHash(), *ptx->GetType(), SocialConsensusResult_RelayContentNotFound)) return {false, SocialConsensusResult_RelayContentNotFound}; - if (relayOk && *relayTx->GetType() == CONTENT_DELETE) - return {false, SocialConsensusResult_RepostDeletedContent}; + if (relayOk) + { + // Repost deleted content not allowed + if (*relayTx->GetType() == CONTENT_DELETE) + return {false, SocialConsensusResult_RepostDeletedContent}; + + // Check Blocking + if (auto[ok, result] = ValidateBlocking(*relayTx->GetString1(), ptx); !ok) + return {false, result}; + } } // Check payload size @@ -257,6 +265,10 @@ namespace PocketConsensus return Success; } + virtual ConsensusValidateResult ValidateBlocking(const string& contentAddress, const PostRef& ptx) + { + return Success; + } }; /******************************************************************************************************************* @@ -298,6 +310,26 @@ namespace PocketConsensus } }; + // Disable scores for blocked accounts + class PostConsensus_checkpoint_disable_for_blocked : public PostConsensus_checkpoint_1180000 + { + public: + PostConsensus_checkpoint_disable_for_blocked(int height) : PostConsensus_checkpoint_1180000(height) {} + protected: + ConsensusValidateResult ValidateBlocking(const string& contentAddress, const PostRef& ptx) override + { + auto[existsBlocking, blockingType] = PocketDb::ConsensusRepoInst.GetLastBlockingType( + contentAddress, + *ptx->GetAddress() + ); + + if (existsBlocking && blockingType == ACTION_BLOCKING) + return {false, SocialConsensusResult_Blocking}; + + return Success; + } + }; + /******************************************************************************************************************* * Factory for select actual rules version *******************************************************************************************************************/ @@ -305,9 +337,10 @@ namespace PocketConsensus { protected: const vector> m_rules = { - { 0, -1, [](int height) { return make_shared(height); }}, - { 1124000, -1, [](int height) { return make_shared(height); }}, - { 1180000, -1, [](int height) { return make_shared(height); }}, + { 0, -1, [](int height) { return make_shared(height); }}, + { 1124000, -1, [](int height) { return make_shared(height); }}, + { 1180000, -1, [](int height) { return make_shared(height); }}, + { 1757000, 953000, [](int height) { return make_shared(height); }}, }; public: shared_ptr Instance(int height) diff --git a/src/pocketdb/consensus/social/ScoreComment.hpp b/src/pocketdb/consensus/social/ScoreComment.hpp index 2c37f5776..891cc4301 100644 --- a/src/pocketdb/consensus/social/ScoreComment.hpp +++ b/src/pocketdb/consensus/social/ScoreComment.hpp @@ -238,9 +238,6 @@ namespace PocketConsensus } }; - /******************************************************************************************************************* - * Start checkpoint at 1180000 block - *******************************************************************************************************************/ class ScoreCommentConsensus_checkpoint_1180000 : public ScoreCommentConsensus_checkpoint_1124000 { public: @@ -256,6 +253,26 @@ namespace PocketConsensus } }; + class ScoreCommentConsensus_checkpoint_disable_for_blocked : public ScoreCommentConsensus_checkpoint_1180000 + { + public: + explicit ScoreCommentConsensus_checkpoint_disable_for_blocked(int height) : ScoreCommentConsensus_checkpoint_1180000(height) {} + protected: + ConsensusValidateResult ValidateBlocking(const string& commentAddress, const ScoreCommentRef& ptx) override + { + + auto[existsBlocking, blockingType] = PocketDb::ConsensusRepoInst.GetLastBlockingType( + commentAddress, + *ptx->GetAddress() + ); + + if (existsBlocking && blockingType == ACTION_BLOCKING) + return {false, SocialConsensusResult_Blocking}; + + return Success; + } + }; + /******************************************************************************************************************* * Factory for select actual rules version *******************************************************************************************************************/ @@ -268,6 +285,7 @@ namespace PocketConsensus { 514184, -1, [](int height) { return make_shared(height); }}, { 1124000, -1, [](int height) { return make_shared(height); }}, { 1180000, 0, [](int height) { return make_shared(height); }}, + { 1757000, 953000, [](int height) { return make_shared(height); }}, }; public: shared_ptr Instance(int height) diff --git a/src/pocketdb/consensus/social/ScoreContent.hpp b/src/pocketdb/consensus/social/ScoreContent.hpp index 5b51516fc..f1e6cdab0 100644 --- a/src/pocketdb/consensus/social/ScoreContent.hpp +++ b/src/pocketdb/consensus/social/ScoreContent.hpp @@ -270,6 +270,26 @@ namespace PocketConsensus } }; + // Disable scores for blocked accounts + class ScoreContentConsensus_checkpoint_disable_for_blocked : public ScoreContentConsensus_checkpoint_1324655 + { + public: + ScoreContentConsensus_checkpoint_disable_for_blocked(int height) : ScoreContentConsensus_checkpoint_1324655(height) {} + protected: + ConsensusValidateResult ValidateBlocking(const string& contentAddress, const ScoreContentRef& ptx) override + { + auto[existsBlocking, blockingType] = PocketDb::ConsensusRepoInst.GetLastBlockingType( + contentAddress, + *ptx->GetAddress() + ); + + if (existsBlocking && blockingType == ACTION_BLOCKING) + return {false, SocialConsensusResult_Blocking}; + + return Success; + } + }; + /******************************************************************************************************************* * Factory for select actual rules version *******************************************************************************************************************/ @@ -277,12 +297,13 @@ namespace PocketConsensus { private: const vector> m_rules = { - { 0, -1, [](int height) { return make_shared(height); }}, - { 430000, -1, [](int height) { return make_shared(height); }}, - { 514184, -1, [](int height) { return make_shared(height); }}, - { 1124000, -1, [](int height) { return make_shared(height); }}, - { 1180000, 0, [](int height) { return make_shared(height); }}, - { 1324655, 65000, [](int height) { return make_shared(height); }}, + { 0, -1, [](int height) { return make_shared(height); }}, + { 430000, -1, [](int height) { return make_shared(height); }}, + { 514184, -1, [](int height) { return make_shared(height); }}, + { 1124000, -1, [](int height) { return make_shared(height); }}, + { 1180000, 0, [](int height) { return make_shared(height); }}, + { 1324655, 65000, [](int height) { return make_shared(height); }}, + { 1757000, 953000, [](int height) { return make_shared(height); }}, }; public: shared_ptr Instance(int height) diff --git a/src/pocketdb/consensus/social/Subscribe.hpp b/src/pocketdb/consensus/social/Subscribe.hpp index f3a9cabe3..8178179c6 100644 --- a/src/pocketdb/consensus/social/Subscribe.hpp +++ b/src/pocketdb/consensus/social/Subscribe.hpp @@ -37,6 +37,10 @@ namespace PocketConsensus return {false, SocialConsensusResult_DoubleSubscribe}; } + // Check Blocking + if (auto[ok, result] = ValidateBlocking(ptx); !ok) + return {false, result}; + return Success; } ConsensusValidateResult Check(const CTransactionRef& tx, const SubscribeRef& ptx) override @@ -94,6 +98,26 @@ namespace PocketConsensus { return {*ptx->GetAddress(), *ptx->GetAddressTo()}; } + virtual ConsensusValidateResult ValidateBlocking(const SubscribeRef& ptx) + { + return Success; + } + }; + + // Disable scores for blocked accounts + class SubscribeConsensus_checkpoint_disable_for_blocked : public SubscribeConsensus + { + public: + SubscribeConsensus_checkpoint_disable_for_blocked(int height) : SubscribeConsensus(height) {} + protected: + ConsensusValidateResult ValidateBlocking(const SubscribeRef& ptx) override + { + if (auto[existsBlocking, blockingType] = PocketDb::ConsensusRepoInst.GetLastBlockingType( + *ptx->GetAddressTo(), *ptx->GetAddress()); existsBlocking && blockingType == ACTION_BLOCKING) + return {false, SocialConsensusResult_Blocking}; + + return Success; + } }; /******************************************************************************************************************* @@ -103,7 +127,8 @@ namespace PocketConsensus { private: const vector> m_rules = { - { 0, 0, [](int height) { return make_shared(height); }}, + { 0, 0, [](int height) { return make_shared(height); }}, + { 1757000, 953000, [](int height) { return make_shared(height); }}, }; public: shared_ptr Instance(int height) diff --git a/src/pocketdb/consensus/social/SubscribePrivate.hpp b/src/pocketdb/consensus/social/SubscribePrivate.hpp index eef03ae32..28c2148a1 100644 --- a/src/pocketdb/consensus/social/SubscribePrivate.hpp +++ b/src/pocketdb/consensus/social/SubscribePrivate.hpp @@ -37,6 +37,10 @@ namespace PocketConsensus return {false, SocialConsensusResult_DoubleSubscribe}; } + // Check Blocking + if (auto[ok, result] = ValidateBlocking(ptx); !ok) + return {false, result}; + return Success; } ConsensusValidateResult Check(const CTransactionRef& tx, const SubscribePrivateRef& ptx) override @@ -94,6 +98,26 @@ namespace PocketConsensus { return {*ptx->GetAddress(), *ptx->GetAddressTo()}; } + virtual ConsensusValidateResult ValidateBlocking(const SubscribePrivateRef& ptx) + { + return Success; + } + }; + + // Disable scores for blocked accounts + class SubscribePrivateConsensus_checkpoint_disable_for_blocked : public SubscribePrivateConsensus + { + public: + SubscribePrivateConsensus_checkpoint_disable_for_blocked(int height) : SubscribePrivateConsensus(height) {} + protected: + ConsensusValidateResult ValidateBlocking(const SubscribePrivateRef& ptx) override + { + if (auto[existsBlocking, blockingType] = PocketDb::ConsensusRepoInst.GetLastBlockingType( + *ptx->GetAddressTo(), *ptx->GetAddress()); existsBlocking && blockingType == ACTION_BLOCKING) + return {false, SocialConsensusResult_Blocking}; + + return Success; + } }; /******************************************************************************************************************* @@ -103,7 +127,8 @@ namespace PocketConsensus { private: const vector> m_rules = { - { 0, 0, [](int height) { return make_shared(height); }}, + { 0, 0, [](int height) { return make_shared(height); }}, + { 1757000, 953000, [](int height) { return make_shared(height); }}, }; public: shared_ptr Instance(int height) diff --git a/src/pocketdb/helpers/TransactionHelper.h b/src/pocketdb/helpers/TransactionHelper.h index e7c743e44..3ec89b51a 100644 --- a/src/pocketdb/helpers/TransactionHelper.h +++ b/src/pocketdb/helpers/TransactionHelper.h @@ -13,7 +13,7 @@ #include "primitives/transaction.h" #include "utilstrencodings.h" -#include "pocketdb/models/base/ReturnDtoModels.h" +#include "pocketdb/models/base/DtoModels.h" #include "pocketdb/models/base/PocketTypes.h" #include "pocketdb/models/dto/Blocking.h" diff --git a/src/pocketdb/migrations/main.cpp b/src/pocketdb/migrations/main.cpp index 105a3ead3..24848c6d7 100644 --- a/src/pocketdb/migrations/main.cpp +++ b/src/pocketdb/migrations/main.cpp @@ -182,8 +182,8 @@ namespace PocketDb primary key (Db) ); )sql"); - - + + _preProcessing = R"sql( insert or ignore into System (Db, Version) values ('main', 0); )sql"; diff --git a/src/pocketdb/models/base/ReturnDtoModels.h b/src/pocketdb/models/base/DtoModels.h similarity index 82% rename from src/pocketdb/models/base/ReturnDtoModels.h rename to src/pocketdb/models/base/DtoModels.h index 1c7a00a41..abd319e69 100644 --- a/src/pocketdb/models/base/ReturnDtoModels.h +++ b/src/pocketdb/models/base/DtoModels.h @@ -85,6 +85,8 @@ namespace PocketTx string ContentAddressHash; int64_t ContentTime; + string String5; + shared_ptr Serialize() override { UniValue ret(UniValue::VOBJ); @@ -102,6 +104,21 @@ namespace PocketTx ret.pushKV("ContentTime", ContentTime); return make_shared(ret); } + + RatingType LikerType(bool last) + { + if (ScoreType == ACTION_SCORE_CONTENT) + return last ? ACCOUNT_LIKERS_POST_LAST : ACCOUNT_LIKERS_POST; + + if (ScoreType == ACTION_SCORE_COMMENT && String5.empty()) + return last ? ACCOUNT_LIKERS_COMMENT_ROOT_LAST : ACCOUNT_LIKERS_COMMENT_ROOT; + + if (ScoreType == ACTION_SCORE_COMMENT && !String5.empty()) + return last ? ACCOUNT_LIKERS_COMMENT_ANSWER_LAST : ACCOUNT_LIKERS_COMMENT_ANSWER; + + // You don't have to get to here + return ACCOUNT_LIKERS; + } }; typedef shared_ptr ScoreDataDtoRef; diff --git a/src/pocketdb/models/base/PocketTypes.h b/src/pocketdb/models/base/PocketTypes.h index 0b6b96077..fe4d9ebdd 100644 --- a/src/pocketdb/models/base/PocketTypes.h +++ b/src/pocketdb/models/base/PocketTypes.h @@ -97,9 +97,20 @@ namespace PocketTx enum RatingType { RATING_ACCOUNT = 0, - RATING_ACCOUNT_LIKERS = 1, RATING_CONTENT = 2, RATING_COMMENT = 3, + + ACCOUNT_LIKERS = 1, + + ACCOUNT_LIKERS_POST = 101, + ACCOUNT_LIKERS_COMMENT_ROOT = 102, + ACCOUNT_LIKERS_COMMENT_ANSWER = 103, + ACCOUNT_DISLIKERS_COMMENT_ANSWER = 104, + + ACCOUNT_LIKERS_POST_LAST = 111, + ACCOUNT_LIKERS_COMMENT_ROOT_LAST = 112, + ACCOUNT_LIKERS_COMMENT_ANSWER_LAST = 113, + ACCOUNT_DISLIKERS_COMMENT_ANSWER_LAST = 114, }; // Content field types diff --git a/src/pocketdb/pocketnet.cpp b/src/pocketdb/pocketnet.cpp index 40c7bcd5a..0cb98e073 100644 --- a/src/pocketdb/pocketnet.cpp +++ b/src/pocketdb/pocketnet.cpp @@ -14,6 +14,7 @@ namespace PocketDb NotifierRepository NotifierRepoInst(SQLiteDbInst); ExplorerRepository ExplorerRepoInst(SQLiteDbInst); SystemRepository SystemRepoInst(SQLiteDbInst); + MigrationRepository MigrationRepoInst(SQLiteDbInst); SQLiteDatabase SQLiteDbCheckpointInst(true); CheckpointRepository CheckpointRepoInst(SQLiteDbCheckpointInst); diff --git a/src/pocketdb/pocketnet.h b/src/pocketdb/pocketnet.h index 942028a82..d263b0ae6 100644 --- a/src/pocketdb/pocketnet.h +++ b/src/pocketdb/pocketnet.h @@ -19,6 +19,7 @@ #include "pocketdb/repositories/ConsensusRepository.h" #include "pocketdb/repositories/SystemRepository.h" #include "pocketdb/repositories/CheckpointRepository.h" +#include "pocketdb/repositories/MigrationRepository.h" #include "pocketdb/repositories/web/WebRpcRepository.h" #include "pocketdb/repositories/web/ExplorerRepository.h" @@ -37,6 +38,7 @@ namespace PocketDb extern NotifierRepository NotifierRepoInst; extern ExplorerRepository ExplorerRepoInst; extern SystemRepository SystemRepoInst; + extern MigrationRepository MigrationRepoInst; extern SQLiteDatabase SQLiteDbCheckpointInst; extern CheckpointRepository CheckpointRepoInst; diff --git a/src/pocketdb/repositories/BaseRepository.h b/src/pocketdb/repositories/BaseRepository.h index bb83841ac..16871db0f 100644 --- a/src/pocketdb/repositories/BaseRepository.h +++ b/src/pocketdb/repositories/BaseRepository.h @@ -125,6 +125,18 @@ namespace PocketDb throw std::runtime_error(strprintf("%s: Failed execute SQL statement\n", __func__)); } + void TryTransactionBulk(const string& func, const vector>& stmts) + { + if (!m_database.BeginTransaction()) + throw std::runtime_error(strprintf("%s: can't begin transaction\n", func)); + + for (auto stmt : stmts) + TryStepStatement(stmt); + + if (!m_database.CommitTransaction()) + throw std::runtime_error(strprintf("%s: can't commit transaction\n", func)); + } + shared_ptr SetupSqlStatement(const std::string& sql) const { sqlite3_stmt* stmt; diff --git a/src/pocketdb/repositories/ChainRepository.cpp b/src/pocketdb/repositories/ChainRepository.cpp index db0512457..a03142fb8 100644 --- a/src/pocketdb/repositories/ChainRepository.cpp +++ b/src/pocketdb/repositories/ChainRepository.cpp @@ -202,6 +202,7 @@ namespace PocketDb ) saldo left join Balances b indexed by Balances_AddressHash_Last on b.AddressHash = saldo.AddressHash and b.Last = 1 + where saldo.AddressHash != '' group by saldo.AddressHash )sql"); TryBindStatementInt(stmt, 1, height); @@ -455,10 +456,11 @@ namespace PocketDb void ChainRepository::RestoreOldLast(int height) { - int64_t nTime1 = GetTimeMicros(); + int64_t nTime0 = GetTimeMicros(); + // ---------------------------------------- // Restore old Last transactions - auto stmt = SetupSqlStatement(R"sql( + auto stmt1 = SetupSqlStatement(R"sql( update Transactions indexed by Transactions_Height_Id set Last=1 from ( @@ -471,13 +473,14 @@ namespace PocketDb )t where Transactions.Id = t.Id and Transactions.Height = t.Height )sql"); - TryBindStatementInt(stmt, 1, height); - TryBindStatementInt(stmt, 2, height); - TryStepStatement(stmt); + TryBindStatementInt(stmt1, 1, height); + TryBindStatementInt(stmt1, 2, height); + TryStepStatement(stmt1); - int64_t nTime2 = GetTimeMicros(); - LogPrint(BCLog::BENCH, " - RestoreOldLast (Transactions:Last = 1): %.2fms\n", 0.001 * (nTime2 - nTime1)); + int64_t nTime1 = GetTimeMicros(); + LogPrint(BCLog::BENCH, " - RestoreOldLast (Transactions): %.2fms\n", 0.001 * (nTime1 - nTime0)); + // ---------------------------------------- // Restore Last for deleting ratings auto stmt2 = SetupSqlStatement(R"sql( update Ratings indexed by Ratings_Type_Id_Height_Value @@ -485,7 +488,7 @@ namespace PocketDb from ( select r1.Type, r1.Id, max(r2.Height)Height from Ratings r1 indexed by Ratings_Type_Id_Last_Height - join Ratings r2 indexed by Ratings_Last_Id_Height on r2.Last = 0 and r2.Id = r1.Id and r2.Height < ? + join Ratings r2 indexed by Ratings_Type_Id_Last_Height on r2.Type = r1.Type and r2.Id = r1.Id and r2.Last = 0 and r2.Height < ? where r1.Height >= ? and r1.Last = 1 group by r1.Type, r1.Id @@ -498,35 +501,54 @@ namespace PocketDb TryBindStatementInt(stmt2, 2, height); TryStepStatement(stmt2); - int64_t nTime3 = GetTimeMicros(); - LogPrint(BCLog::BENCH, " - RestoreOldLast (Ratings:Last = 1): %.2fms\n", 0.001 * (nTime3 - nTime2)); + int64_t nTime2 = GetTimeMicros(); + LogPrint(BCLog::BENCH, " - RestoreOldLast (Ratings): %.2fms\n", 0.001 * (nTime2 - nTime1)); + // ---------------------------------------- // Restore Last for deleting balances auto stmt3 = SetupSqlStatement(R"sql( - update Balances set Last=1 + update Balances set + + Last = 1 + from ( - select b1.AddressHash, max(b2.Height)Height - from Balances b1 indexed by Balances_AddressHash_Last_Height - join Balances b2 indexed by Balances_AddressHash_Last_Height on b2.Last = 0 and b2.AddressHash = b1.AddressHash and b2.Height < ? + select + + b1.AddressHash + ,( + select max(b2.Height) + from Balances b2 indexed by Balances_AddressHash_Last_Height + where b2.AddressHash = b1.AddressHash + and b2.Last = 0 + and b2.Height < ? + limit 1 + )Height + + from Balances b1 indexed by Balances_Height + where b1.Height >= ? and b1.Last = 1 + and b1.AddressHash != '' + group by b1.AddressHash )b - where Balances.AddressHash = b.AddressHash + where b.Height is not null + and Balances.AddressHash = b.AddressHash and Balances.Height = b.Height )sql"); TryBindStatementInt(stmt3, 1, height); TryBindStatementInt(stmt3, 2, height); TryStepStatement(stmt3); - int64_t nTime4 = GetTimeMicros(); - LogPrint(BCLog::BENCH, " - RestoreOldLast (Balances:Last = 1): %.2fms\n", 0.001 * (nTime4 - nTime3)); + int64_t nTime3 = GetTimeMicros(); + LogPrint(BCLog::BENCH, " - RestoreOldLast (Balances): %.2fms\n", 0.001 * (nTime3 - nTime2)); } void ChainRepository::RollbackHeight(int height) { - int64_t nTime1 = GetTimeMicros(); + int64_t nTime0 = GetTimeMicros(); + // ---------------------------------------- // Rollback general transaction information auto stmt0 = SetupSqlStatement(R"sql( UPDATE Transactions SET @@ -540,61 +562,59 @@ namespace PocketDb TryBindStatementInt(stmt0, 1, height); TryStepStatement(stmt0); - int64_t nTime2 = GetTimeMicros(); - LogPrint(BCLog::BENCH, " - RollbackHeight (Transactions:Height = null): %.2fms\n", 0.001 * (nTime2 - nTime1)); + int64_t nTime1 = GetTimeMicros(); + LogPrint(BCLog::BENCH, " - RollbackHeight (Transactions:Height = null): %.2fms\n", 0.001 * (nTime1 - nTime0)); // ---------------------------------------- - // Rollback spent transaction outputs - auto stmt1 = SetupSqlStatement(R"sql( + auto stmt2 = SetupSqlStatement(R"sql( UPDATE TxOutputs SET SpentHeight = null, SpentTxHash = null WHERE SpentHeight >= ? )sql"); - TryBindStatementInt(stmt1, 1, height); - TryStepStatement(stmt1); + TryBindStatementInt(stmt2, 1, height); + TryStepStatement(stmt2); - int64_t nTime3 = GetTimeMicros(); - LogPrint(BCLog::BENCH, " - RollbackHeight (TxOutputs:SpentHeight = null): %.2fms\n", 0.001 * (nTime3 - nTime2)); + int64_t nTime2 = GetTimeMicros(); + LogPrint(BCLog::BENCH, " - RollbackHeight (TxOutputs:SpentHeight = null): %.2fms\n", 0.001 * (nTime2 - nTime1)); + // ---------------------------------------- // Rollback transaction outputs height - auto stmt11 = SetupSqlStatement(R"sql( + auto stmt3 = SetupSqlStatement(R"sql( UPDATE TxOutputs SET TxHeight = null WHERE TxHeight >= ? )sql"); - TryBindStatementInt(stmt11, 1, height); - TryStepStatement(stmt11); + TryBindStatementInt(stmt3, 1, height); + TryStepStatement(stmt3); - int64_t nTime4 = GetTimeMicros(); - LogPrint(BCLog::BENCH, " - RollbackHeight (TxOutputs:TxHeight = null): %.2fms\n", 0.001 * (nTime4 - nTime3)); + int64_t nTime3 = GetTimeMicros(); + LogPrint(BCLog::BENCH, " - RollbackHeight (TxOutputs:TxHeight = null): %.2fms\n", 0.001 * (nTime3 - nTime2)); // ---------------------------------------- - // Remove ratings - auto stmt21 = SetupSqlStatement(R"sql( + auto stmt4 = SetupSqlStatement(R"sql( delete from Ratings where Height >= ? )sql"); - TryBindStatementInt(stmt21, 1, height); - TryStepStatement(stmt21); + TryBindStatementInt(stmt4, 1, height); + TryStepStatement(stmt4); - int64_t nTime5 = GetTimeMicros(); - LogPrint(BCLog::BENCH, " - RollbackHeight (Ratings delete): %.2fms\n", 0.001 * (nTime5 - nTime4)); + int64_t nTime4 = GetTimeMicros(); + LogPrint(BCLog::BENCH, " - RollbackHeight (Ratings delete): %.2fms\n", 0.001 * (nTime4 - nTime3)); // ---------------------------------------- - // Remove balances - auto stmt31 = SetupSqlStatement(R"sql( + auto stmt5 = SetupSqlStatement(R"sql( delete from Balances where Height >= ? )sql"); - TryBindStatementInt(stmt31, 1, height); - TryStepStatement(stmt31); + TryBindStatementInt(stmt5, 1, height); + TryStepStatement(stmt5); - int64_t nTime6 = GetTimeMicros(); - LogPrint(BCLog::BENCH, " - RollbackHeight (Balances delete): %.2fms\n", 0.001 * (nTime6 - nTime5)); + int64_t nTime5 = GetTimeMicros(); + LogPrint(BCLog::BENCH, " - RollbackHeight (Balances delete): %.2fms\n", 0.001 * (nTime5 - nTime4)); } diff --git a/src/pocketdb/repositories/ChainRepository.h b/src/pocketdb/repositories/ChainRepository.h index 082ee7b3a..c29e839c1 100644 --- a/src/pocketdb/repositories/ChainRepository.h +++ b/src/pocketdb/repositories/ChainRepository.h @@ -11,7 +11,7 @@ #include "pocketdb/repositories/BaseRepository.h" #include "pocketdb/models/base/Rating.h" #include "pocketdb/models/base/PocketTypes.h" -#include "pocketdb/models/base/ReturnDtoModels.h" +#include "pocketdb/models/base/DtoModels.h" #include #include diff --git a/src/pocketdb/repositories/ConsensusRepository.cpp b/src/pocketdb/repositories/ConsensusRepository.cpp index 8f874ee35..e7e94cfac 100644 --- a/src/pocketdb/repositories/ConsensusRepository.cpp +++ b/src/pocketdb/repositories/ConsensusRepository.cpp @@ -434,7 +434,7 @@ namespace PocketDb auto sql = R"sql( select r.Value from Ratings r - where r.Type = ? + where r.Type = 0 and r.Id = (SELECT u.Id FROM Transactions u WHERE u.Type in (100, 101, 102) and u.Height is not null and u.Last = 1 and u.String1 = ? LIMIT 1) and r.Last = 1 )sql"; @@ -442,8 +442,7 @@ namespace PocketDb TryTransactionStep(__func__, [&]() { auto stmt = SetupSqlStatement(sql); - TryBindStatementInt(stmt, 1, (int) RatingType::RATING_ACCOUNT); - TryBindStatementText(stmt, 2, address); + TryBindStatementText(stmt, 1, address); if (sqlite3_step(*stmt) == SQLITE_ROW) if (auto[ok, value] = TryGetColumnInt(*stmt, 0); ok) @@ -462,7 +461,7 @@ namespace PocketDb string sql = R"sql( select r.Value from Ratings r - where r.Type = ? + where r.Type = 0 and r.Id = ? and r.Last = 1 )sql"; @@ -470,8 +469,7 @@ namespace PocketDb TryTransactionStep(__func__, [&]() { auto stmt = SetupSqlStatement(sql); - TryBindStatementInt(stmt, 1, (int) RatingType::RATING_ACCOUNT); - TryBindStatementInt(stmt, 2, addressId); + TryBindStatementInt(stmt, 1, addressId); if (sqlite3_step(*stmt) == SQLITE_ROW) if (auto[ok, value] = TryGetColumnInt(*stmt, 0); ok) @@ -540,31 +538,51 @@ namespace PocketDb AccountData ConsensusRepository::GetAccountData(const string& address) { - AccountData result = {-1, 0, 0, 0}; + AccountData result = {address,-1,0,0,0,0,0}; TryTransactionStep(__func__, [&]() { auto stmt = SetupSqlStatement(R"sql( - select (u.Id)AddressId, - ifnull(r.Value, 0)Reputation, - (select min(uf.Height) from Transactions uf where uf.Id = u.Id)RegistrationBlock, - (select count() from Ratings l where l.Type = 1 and l.Id = u.Id)LikersCount + select + + (u.Id)AddressId, + reg.Time as RegistrationDate, + reg.Height as RegistrationHeight, + ifnull(b.Value,0)Balance, + ifnull(r.Value,0)Reputation, + ifnull(lp.Value,0)LikersContent, + ifnull(lc.Value,0)LikersComment, + ifnull(lca.Value,0)LikersCommentAnswer + from Transactions u indexed by Transactions_Type_Last_String1_Height_Id + cross join Transactions reg indexed by Transactions_Id + on reg.Id = u.Id and reg.Height = (select min(reg1.Height) from Transactions reg1 indexed by Transactions_Id where reg1.Id = reg.Id) + left join Balances b indexed by Balances_AddressHash_Last on b.AddressHash = u.String1 and b.Last = 1 left join Ratings r indexed by Ratings_Type_Id_Last_Value on r.Type = 0 and r.Id = u.Id and r.Last = 1 + left join Ratings lp indexed by Ratings_Type_Id_Last_Value on lp.Type = 111 and lp.Id = u.Id and lp.Last = 1 + left join Ratings lc indexed by Ratings_Type_Id_Last_Value on lc.Type = 112 and lc.Id = u.Id and lc.Last = 1 + left join Ratings lca indexed by Ratings_Type_Id_Last_Value on lca.Type = 113 and lca.Id = u.Id and lca.Last = 1 + where u.Type in (100) and u.Last = 1 and u.String1 = ? and u.Height > 0 + limit 1 )sql"); TryBindStatementText(stmt, 1, address); if (sqlite3_step(*stmt) == SQLITE_ROW) { - if (auto[ok, value] = TryGetColumnInt64(*stmt, 0); ok) result.AddressId = value; - if (auto[ok, value] = TryGetColumnInt64(*stmt, 1); ok) result.Reputation = value; - if (auto[ok, value] = TryGetColumnInt64(*stmt, 2); ok) result.RegistrationHeight = value; - if (auto[ok, value] = TryGetColumnInt64(*stmt, 3); ok) result.LikersCount = value; + int i = 0; + if (auto[ok, value] = TryGetColumnInt64(*stmt, i++); ok) result.AddressId = value; + if (auto[ok, value] = TryGetColumnInt64(*stmt, i++); ok) result.RegistrationTime = value; + if (auto[ok, value] = TryGetColumnInt64(*stmt, i++); ok) result.RegistrationHeight = value; + if (auto[ok, value] = TryGetColumnInt64(*stmt, i++); ok) result.Balance = value; + if (auto[ok, value] = TryGetColumnInt64(*stmt, i++); ok) result.Reputation = value; + if (auto[ok, value] = TryGetColumnInt64(*stmt, i++); ok) result.LikersContent = value; + if (auto[ok, value] = TryGetColumnInt64(*stmt, i++); ok) result.LikersComment = value; + if (auto[ok, value] = TryGetColumnInt64(*stmt, i++); ok) result.LikersCommentAnswer = value; } FinalizeSqlStatement(*stmt); @@ -592,7 +610,9 @@ namespace PocketDb c.Time cTime, c.Id cId, ca.Id caId, - ca.String1 caHash + ca.String1 caHash, + + c.String5 from Transactions s indexed by Transactions_Hash_Height @@ -633,6 +653,8 @@ namespace PocketDb if (auto[ok, value] = TryGetColumnInt(*stmt, 9); ok) data.ContentId = value; if (auto[ok, value] = TryGetColumnInt(*stmt, 10); ok) data.ContentAddressId = value; if (auto[ok, value] = TryGetColumnString(*stmt, 11); ok) data.ContentAddressHash = value; + + if (auto[ok, value] = TryGetColumnString(*stmt, 12); ok) data.String5 = value; result = make_shared(data); } @@ -724,33 +746,6 @@ namespace PocketDb return {result, referrer}; } - int ConsensusRepository::GetUserLikersCount(int addressId) - { - int result = 0; - - string sql = R"sql( - select count(1) - from Ratings r - where r.Type = ? - and r.Id = ? - )sql"; - - TryTransactionStep(__func__, [&]() - { - auto stmt = SetupSqlStatement(sql); - TryBindStatementInt(stmt, 1, (int) RatingType::RATING_ACCOUNT_LIKERS); - TryBindStatementInt(stmt, 2, addressId); - - if (sqlite3_step(*stmt) == SQLITE_ROW) - if (auto[ok, value] = TryGetColumnInt(*stmt, 0); ok) - result = value; - - FinalizeSqlStatement(*stmt); - }); - - return result; - } - int ConsensusRepository::GetScoreContentCount( int height, const shared_ptr& scoreData, diff --git a/src/pocketdb/repositories/ConsensusRepository.h b/src/pocketdb/repositories/ConsensusRepository.h index 849cf4646..a73a6fbac 100644 --- a/src/pocketdb/repositories/ConsensusRepository.h +++ b/src/pocketdb/repositories/ConsensusRepository.h @@ -26,10 +26,41 @@ namespace PocketDb struct AccountData { + string AddressHash; int64_t AddressId; int64_t Reputation; + int64_t RegistrationTime; int64_t RegistrationHeight; - int64_t LikersCount; + int64_t Balance; + + int64_t LikersContent; + int64_t LikersComment; + int64_t LikersCommentAnswer; + + int64_t LikersAll() const + { + return LikersContent + LikersComment + LikersCommentAnswer; + } + }; + + struct BadgeSet + { + bool Shark = false; + bool Whale = false; + bool Moderator = false; + bool Developer = false; + + UniValue ToJson() + { + UniValue ret(UniValue::VARR); + + if (Shark) ret.push_back("shark"); + if (Whale) ret.push_back("whale"); + if (Moderator) ret.push_back("moderator"); + if (Developer) ret.push_back("developer"); + + return ret; + } }; class ConsensusRepository : public TransactionRepository @@ -62,7 +93,6 @@ namespace PocketDb ScoreDataDtoRef GetScoreData(const string& txHash); shared_ptr> GetReferrers(const vector& addresses, int minHeight); tuple GetReferrer(const string& address); - int GetUserLikersCount(int addressId); int GetScoreContentCount( int height, @@ -141,6 +171,8 @@ namespace PocketDb }; + typedef shared_ptr ConsensusRepositoryRef; + } // namespace PocketDb #endif // POCKETDB_CONSENSUSREPOSITORY_H diff --git a/src/pocketdb/repositories/MigrationRepository.cpp b/src/pocketdb/repositories/MigrationRepository.cpp new file mode 100644 index 000000000..f674d8812 --- /dev/null +++ b/src/pocketdb/repositories/MigrationRepository.cpp @@ -0,0 +1,274 @@ +// Copyright (c) 2018-2022 The Pocketnet developers +// Distributed under the Apache 2.0 software license, see the accompanying +// https://www.apache.org/licenses/LICENSE-2.0 + +#include "pocketdb/repositories/MigrationRepository.h" +#include + +namespace PocketDb +{ + bool MigrationRepository::SplitLikers() + { + if (!CheckNeedSplitLikers()) + return true; + + uiInterface.InitMessage(_("SQLDB Migration: SplitLikers...")); + + TryTransactionStep(__func__, [&]() + { + // delete exists data before insert splitted data + auto stmtDelete = SetupSqlStatement(R"sql( + delete from Ratings where Type in (101,102,103) + )sql"); + TryStepStatement(stmtDelete); + + // Insert new splitted types of likers + auto stmtSelect = SetupSqlStatement(R"sql( + select + + ( + + select + case sc.Type + when 300 then 101 + when 301 then ( + case + when c.String5 isnull then 102 + else 103 + end + ) + end + + from Transactions sc indexed by Transactions_Height_Type + join Transactions ul indexed by Transactions_Type_Last_String1_Height_Id + on ul.Type = 100 and ul.Last = 1 and ul.Height > 0 and ul.String1 = sc.String1 + join Transactions c + on c.Hash = sc.String2 + and ( + (sc.Type in (300) and (sc.Time-c.Time) < ((case when sc.height < 322700 then 336 else 30 end) * 24 * 3600)) + or + (sc.Type in (301)) + ) + join Transactions ua indexed by Transactions_Type_Last_String1_Height_Id + on ua.Type = 100 and ua.Last = 1 and ua.Height > 0 and ua.String1 = c.String1 + + where sc.Type in (300,301) + and sc.Height = r.Height + and ((sc.Int1 in (4,5) and sc.Type = 300) or (sc.Int1 = 1 and sc.Type = 301)) + and ua.Id = r.Id + and ul.Id = r.Value + + and (( + sc.Type = 300 + and ( + select count() + + from Transactions s indexed by Transactions_Type_String1_Height_Time_Int1 + join Transactions c + on c.Hash = s.String2 + and c.String1 = ua.String1 + and c.Type in (200,201,202,207) + + where s.Type = sc.Type + and s.Height <= sc.Height + and s.String1 = sc.String1 + and s.Hash != sc.Hash + + and s.Time < sc.Time + and s.Time >= sc.Time - (( + case + when sc.Height >= 322700 then 2 + when sc.Height >= 292800 then 7 + when sc.Height >= 225000 then 1 + else 336 + end + ) * 24 * 3600) + + and s.Int1 in (4,5) + ) < (case when sc.Height >= 225000 then 2 else 99999 end) + ) + or + ( + sc.Type = 301 + and ( + select count() + + from Transactions s indexed by Transactions_Type_String1_Height_Time_Int1 + join Transactions c + on c.Hash = s.String2 + and c.String1 = ua.String1 + and c.Type in (204,205,206) + + where s.Type = sc.Type + and s.String1 = sc.String1 + and s.Height <= sc.Height + and s.Hash != sc.Hash + + and s.Time < sc.Time + and s.Time >= sc.Time - (( + case + when sc.Height >= 322700 then 2 + when sc.Height >= 292800 then 7 + when sc.Height >= 225000 then 1 + else 336 + end + ) * 24 * 3600) + + and s.Int1 = 1 + ) < 20 + ) + ) + + order by sc.BlockNum + limit 1 + + ) lkrType + + , 1 + , r.Height + , r.Id + , r.Value + + from Ratings r + where r.Type in (1) + )sql"); + + while (sqlite3_step(*stmtSelect) == SQLITE_ROW) + { + auto[okType, Type] = TryGetColumnInt(*stmtSelect, 0); + auto[okLast, Last] = TryGetColumnInt(*stmtSelect, 1); + auto[okHeight, Height] = TryGetColumnInt64(*stmtSelect, 2); + auto[okId, Id] = TryGetColumnInt64(*stmtSelect, 3); + auto[okValue, Value] = TryGetColumnInt64(*stmtSelect, 4); + + auto stmtInsert = SetupSqlStatement(R"sql( + insert into Ratings (type, last, height, id, value) + values (?,?,?,?,?) + )sql"); + + TryBindStatementInt(stmtInsert, 1, Type); + TryBindStatementInt(stmtInsert, 2, Last); + TryBindStatementInt64(stmtInsert, 3, Height); + TryBindStatementInt64(stmtInsert, 4, Id); + TryBindStatementInt64(stmtInsert, 5, Value); + TryStepStatement(stmtInsert); + } + + FinalizeSqlStatement(*stmtSelect); + }); + + return !CheckNeedSplitLikers(); + } + + bool MigrationRepository::CheckNeedSplitLikers() + { + bool result = false; + + uiInterface.InitMessage(_("Checking SQLDB Migration: SplitLikers...")); + + TryTransactionStep(__func__, [&]() + { + auto stmt = SetupSqlStatement(R"sql( + select 'All', ifnull(sum(rAll.Id),0)sAllId, ifnull(sum(rAll.Value),0)sAllValue, count()cnt + from Ratings rAll + where rAll.Type in (1) + + union + + select 'Split', ifnull(sum(r.Id),0)sId, ifnull(sum(r.Value),0)sValue, count()cnt + from Ratings r + where r.Type in (101,102,103) + )sql"); + + if (sqlite3_step(*stmt) == SQLITE_ROW) + { + auto[sumAllIdOk, sumAllId] = TryGetColumnInt64(*stmt, 1); + auto[sumAllValueOk, sumAllValue] = TryGetColumnInt64(*stmt, 2); + auto[cntAllOk, cntAll] = TryGetColumnInt64(*stmt, 3); + + if (sqlite3_step(*stmt) == SQLITE_ROW) + { + auto[sumSpltIdOk, sumSpltId] = TryGetColumnInt64(*stmt, 1); + auto[sumSpltValueOk, sumSpltValue] = TryGetColumnInt64(*stmt, 2); + auto[cntSpltOk, cntSplt] = TryGetColumnInt64(*stmt, 3); + + result = (sumAllId != sumSpltId || sumAllValue != sumSpltValue || cntAll != cntSplt); + + } + } + + FinalizeSqlStatement(*stmt); + }); + + return result; + } + + bool MigrationRepository::AccumulateLikers() + { + bool result = false; + + if (!CheckNeedAccumulateLikers()) + return true; + + uiInterface.InitMessage(_("SQLDB Migration: AccumulateLikers...")); + + TryTransactionBulk(__func__, { + + // Clear old data - this first init simple migration + SetupSqlStatement(R"sql( + delete from Ratings + where Type in (111,112,113) + )sql"), + + // Insert new last values + SetupSqlStatement(R"sql( + insert into Ratings (Type, Last, Height, Id, Value) + select + (case r.Type when 101 then 111 when 102 then 112 when 103 then 113 end), + ifnull((select 0 from Ratings ll indexed by Ratings_Type_Id_Height_Value where ll.Type = r.Type and ll.Id = r.Id and ll.Height > r.Height limit 1),1), + r.Height, + r.Id, + (select count() from Ratings l indexed by Ratings_Type_Id_Height_Value where l.Type = r.Type and l.Id = r.Id and l.Height <= r.Height) + from Ratings r + where r.Type in (101,102,103) + group by r.Type, r.Id, r.Height + )sql") + + }); + + return !CheckNeedAccumulateLikers(); + } + + bool MigrationRepository::CheckNeedAccumulateLikers() + { + bool result = false; + + uiInterface.InitMessage(_("Checking SQLDB Migration: AccumulateLikers...")); + + TryTransactionStep(__func__, [&]() + { + auto stmt = SetupSqlStatement(R"sql( + select 1 + from Ratings r indexed by Ratings_Type_Id_Height_Value + left join Ratings ll indexed by Ratings_Type_Id_Height_Value + on ll.Id = r.Id and ll.Type = (case r.Type when 101 then 111 when 102 then 112 when 103 then 113 end) and ll.Height = r.Height + where r.Type in (101,102,103) + and ( + (select count() from Ratings l where l.Id = r.Id and l.Height <= r.Height and l.Type = r.Type) != ll.Value + or + ll.Value isnull + ) + limit 1 + )sql"); + + result = (sqlite3_step(*stmt) == SQLITE_ROW); + + FinalizeSqlStatement(*stmt); + }); + + return result; + } + + +} // namespace PocketDb + diff --git a/src/pocketdb/repositories/MigrationRepository.h b/src/pocketdb/repositories/MigrationRepository.h new file mode 100644 index 000000000..92cd586c8 --- /dev/null +++ b/src/pocketdb/repositories/MigrationRepository.h @@ -0,0 +1,45 @@ +// Copyright (c) 2018-2022 The Pocketnet developers +// Distributed under the Apache 2.0 software license, see the accompanying +// https://www.apache.org/licenses/LICENSE-2.0 + +#ifndef POCKETDB_MIGRATIONREPOSITORY_H +#define POCKETDB_MIGRATIONREPOSITORY_H + +#include "pocketdb/repositories/BaseRepository.h" + +#include +#include + +namespace PocketDb +{ + using std::runtime_error; + using boost::algorithm::join; + using boost::adaptors::transformed; + + using namespace std; + + class MigrationRepository : public BaseRepository + { + public: + explicit MigrationRepository(SQLiteDatabase& db) : BaseRepository(db) {} + void Init() override {} + void Destroy() override {} + + bool SplitLikers(); + + // Calculate last values group by AccountID & Type + bool AccumulateLikers(); + + protected: + + bool CheckNeedSplitLikers(); + bool CheckNeedAccumulateLikers(); + + }; + + typedef std::shared_ptr MigrationRepositoryRef; + +} // namespace PocketDb + +#endif // POCKETDB_MIGRATIONREPOSITORY_H + diff --git a/src/pocketdb/repositories/RatingsRepository.cpp b/src/pocketdb/repositories/RatingsRepository.cpp index 663ad3c1e..e0eab91f8 100644 --- a/src/pocketdb/repositories/RatingsRepository.cpp +++ b/src/pocketdb/repositories/RatingsRepository.cpp @@ -10,34 +10,46 @@ namespace PocketDb { for (const auto& rating: *ratings) { - if (*rating.GetType() == RatingType::RATING_ACCOUNT_LIKERS) + switch (*rating.GetType()) + { + case RatingType::ACCOUNT_LIKERS: + case RatingType::ACCOUNT_LIKERS_POST: + case RatingType::ACCOUNT_LIKERS_COMMENT_ROOT: + case RatingType::ACCOUNT_LIKERS_COMMENT_ANSWER: + case RatingType::ACCOUNT_DISLIKERS_COMMENT_ANSWER: InsertLiker(rating); - else + break; + default: InsertRating(rating); + break; + } } } - bool RatingsRepository::ExistsLiker(int addressId, int likerId, int height) + bool RatingsRepository::ExistsLiker(int addressId, int likerId, const vector& types) { bool result = false; + + string sql = R"sql( + select 1 + from Ratings indexed by Ratings_Type_Id_Value + where Type in ( )sql" + join(vector(types.size(), "?"), ",") + R"sql( ) + and Id = ? + and Value = ? + )sql"; TryTransactionStep(__func__, [&]() { - auto stmt = SetupSqlStatement(R"sql( - select count(*) - from Ratings indexed by Ratings_Type_Id_Value - where Type = ? - and Id = ? - and Value = ? - )sql"); + auto stmt = SetupSqlStatement(sql); - TryBindStatementInt(stmt, 1, RatingType::RATING_ACCOUNT_LIKERS); - TryBindStatementInt(stmt, 2, addressId); - TryBindStatementInt(stmt, 3, likerId); + int i = 1; + for (const auto& type: types) + TryBindStatementInt(stmt, i++, type); + TryBindStatementInt(stmt, i++, addressId); + TryBindStatementInt(stmt, i++, likerId); if (sqlite3_step(*stmt) == SQLITE_ROW) - if (auto[ok, value] = TryGetColumnInt(*stmt, 0); ok) - result = (value > 0); + result = true; FinalizeSqlStatement(*stmt); }); @@ -97,32 +109,20 @@ namespace PocketDb { TryTransactionStep(__func__, [&]() { - auto stmt = SetupSqlStatement(R"sql( - INSERT OR FAIL INTO Ratings ( + auto stmtInsert = SetupSqlStatement(R"sql( + insert or fail into Ratings ( Type, Last, Height, Id, Value - ) SELECT ?,1,?,?,? - WHERE NOT EXISTS ( - select 1 - from Ratings r indexed by Ratings_Type_Id_Value - where r.Type=? - and r.Id=? - and r.Value=? - ) + ) values ( ?,1,?,?,? ) )sql"); - - TryBindStatementInt(stmt, 1, (int)*rating.GetType()); - TryBindStatementInt(stmt, 2, rating.GetHeight()); - TryBindStatementInt64(stmt, 3, rating.GetId()); - TryBindStatementInt64(stmt, 4, rating.GetValue()); - TryBindStatementInt(stmt, 5, (int)*rating.GetType()); - TryBindStatementInt64(stmt, 6, rating.GetId()); - TryBindStatementInt64(stmt, 7, rating.GetValue()); - - TryStepStatement(stmt); + TryBindStatementInt(stmtInsert, 1, *rating.GetType()); + TryBindStatementInt(stmtInsert, 2, rating.GetHeight()); + TryBindStatementInt64(stmtInsert, 3, rating.GetId()); + TryBindStatementInt64(stmtInsert, 4, rating.GetValue()); + TryStepStatement(stmtInsert); }); } } diff --git a/src/pocketdb/repositories/RatingsRepository.h b/src/pocketdb/repositories/RatingsRepository.h index d80e18bce..df04651cf 100644 --- a/src/pocketdb/repositories/RatingsRepository.h +++ b/src/pocketdb/repositories/RatingsRepository.h @@ -6,14 +6,19 @@ #define SRC_RATINGSREPOSITORY_H #include +#include +#include #include "pocketdb/repositories/BaseRepository.h" #include "pocketdb/models/base/Rating.h" -#include "pocketdb/models/base/ReturnDtoModels.h" +#include "pocketdb/models/base/DtoModels.h" namespace PocketDb { using std::runtime_error; + using boost::algorithm::join; + using boost::adaptors::transformed; + using namespace PocketTx; class RatingsRepository : public BaseRepository @@ -27,8 +32,8 @@ namespace PocketDb // Accumulate new rating records void InsertRatings(shared_ptr> ratings); - - bool ExistsLiker(int addressId, int likerId, int height); + bool ExistsLiker(int addressId, int likerId); + bool ExistsLiker(int addressId, int likerId, const vector& types); private: diff --git a/src/pocketdb/repositories/TransactionRepository.h b/src/pocketdb/repositories/TransactionRepository.h index 88ad52847..b9fad462b 100644 --- a/src/pocketdb/repositories/TransactionRepository.h +++ b/src/pocketdb/repositories/TransactionRepository.h @@ -8,12 +8,12 @@ #include #include -#include "pocketdb/helpers/TransactionHelper.h" #include "pocketdb/repositories/BaseRepository.h" +#include "pocketdb/helpers/TransactionHelper.h" #include "pocketdb/models/base/Transaction.h" #include "pocketdb/models/base/TransactionOutput.h" #include "pocketdb/models/base/Rating.h" -#include "pocketdb/models/base/ReturnDtoModels.h" +#include "pocketdb/models/base/DtoModels.h" #include "pocketdb/models/dto/User.h" #include "pocketdb/models/dto/ScoreContent.h" #include "pocketdb/models/dto/ScoreComment.h" diff --git a/src/pocketdb/repositories/web/WebRpcRepository.cpp b/src/pocketdb/repositories/web/WebRpcRepository.cpp index 65d8ea085..56557afb0 100644 --- a/src/pocketdb/repositories/web/WebRpcRepository.cpp +++ b/src/pocketdb/repositories/web/WebRpcRepository.cpp @@ -193,18 +193,6 @@ namespace PocketDb u.Id as AddressId, u.String1 as Address, - reg.Time as RegistrationDate, - reg.Height as RegistrationHeight, - - ifnull((select r.Value from Ratings r indexed by Ratings_Type_Id_Last_Height - where r.Type=0 and r.Id=u.Id and r.Last=1),0) as Reputation, - - ifnull((select b.Value from Balances b indexed by Balances_AddressHash_Last - where b.AddressHash=u.String1 and b.Last=1),0) as Balance, - - (select count() from Ratings r indexed by Ratings_Type_Id_Last_Height - where r.Type=1 and r.Id=u.Id) as Likers, - (select count() from Transactions p indexed by Transactions_Type_String1_Height_Time_Int1 where p.Type in (200) and p.Hash=p.String2 and p.String1=u.String1 and (p.Height>=? or p.Height isnull)) as PostSpent, @@ -231,9 +219,6 @@ namespace PocketDb from Transactions u indexed by Transactions_Type_Last_String1_Height_Id - cross join Transactions reg indexed by Transactions_Id - on reg.Id = u.Id and reg.Height = (select min(reg1.Height) from Transactions reg1 indexed by Transactions_Id where reg1.Id = reg.Id) - where u.Type in (100, 101, 102) and u.Height is not null and u.String1 = ? @@ -256,23 +241,19 @@ namespace PocketDb if (sqlite3_step(*stmt) == SQLITE_ROW) { - if (auto[ok, value] = TryGetColumnInt64(*stmt, 0); ok) result.pushKV("address_id", value); - if (auto[ok, value] = TryGetColumnString(*stmt, 1); ok) result.pushKV("address", value); - if (auto[ok, value] = TryGetColumnInt64(*stmt, 2); ok) result.pushKV("user_reg_date", value); - if (auto[ok, value] = TryGetColumnInt64(*stmt, 3); ok) result.pushKV("user_reg_height", value); - if (auto[ok, value] = TryGetColumnInt64(*stmt, 4); ok) result.pushKV("reputation", value); - if (auto[ok, value] = TryGetColumnInt64(*stmt, 5); ok) result.pushKV("balance", value); - if (auto[ok, value] = TryGetColumnInt64(*stmt, 6); ok) result.pushKV("likers", value); - - if (auto[ok, value] = TryGetColumnInt64(*stmt, 7); ok) result.pushKV("post_spent", value); - if (auto[ok, value] = TryGetColumnInt64(*stmt, 8); ok) result.pushKV("video_spent", value); - if (auto[ok, value] = TryGetColumnInt64(*stmt, 9); ok) result.pushKV("article_spent", value); - if (auto[ok, value] = TryGetColumnInt64(*stmt, 10); ok) result.pushKV("comment_spent", value); - if (auto[ok, value] = TryGetColumnInt64(*stmt, 11); ok) result.pushKV("score_spent", value); - if (auto[ok, value] = TryGetColumnInt64(*stmt, 12); ok) result.pushKV("comment_score_spent", value); - if (auto[ok, value] = TryGetColumnInt64(*stmt, 13); ok) result.pushKV("complain_spent", value); + int i = 0; + if (auto[ok, value] = TryGetColumnInt64(*stmt, i++); ok) result.pushKV("address_id", value); + if (auto[ok, value] = TryGetColumnString(*stmt, i++); ok) result.pushKV("address", value); + + if (auto[ok, value] = TryGetColumnInt64(*stmt, i++); ok) result.pushKV("post_spent", value); + if (auto[ok, value] = TryGetColumnInt64(*stmt, i++); ok) result.pushKV("video_spent", value); + if (auto[ok, value] = TryGetColumnInt64(*stmt, i++); ok) result.pushKV("article_spent", value); + if (auto[ok, value] = TryGetColumnInt64(*stmt, i++); ok) result.pushKV("comment_spent", value); + if (auto[ok, value] = TryGetColumnInt64(*stmt, i++); ok) result.pushKV("score_spent", value); + if (auto[ok, value] = TryGetColumnInt64(*stmt, i++); ok) result.pushKV("comment_score_spent", value); + if (auto[ok, value] = TryGetColumnInt64(*stmt, i++); ok) result.pushKV("complain_spent", value); - if (auto[ok, value] = TryGetColumnInt64(*stmt, 14); ok) result.pushKV("mod_flag_spent", value); + if (auto[ok, value] = TryGetColumnInt64(*stmt, i++); ok) result.pushKV("mod_flag_spent", value); } FinalizeSqlStatement(*stmt); @@ -341,13 +322,45 @@ namespace PocketDb where ru1.Id = ru.Id limit 1 ) - ),0) as ReferralsCountHist + ),0) as ReferralsCountHist, + + ( + select count() + from Transactions p indexed by Transactions_String1_Last_Height + join Transactions c indexed by Transactions_Type_Last_String3_Height + on c.Type in (204) + and c.Last in (0,1) + and c.String3 = p.String2 + and c.Height <= ? + and c.Height > ? + and c.Hash = c.String2 + where p.Type in (200,201,202) + and p.Last = 1 + and p.String1 = u.String1 + and p.Height > 0 + )Comments, + + ( + select count(distinct c.String1) + from Transactions p indexed by Transactions_String1_Last_Height + join Transactions c indexed by Transactions_Type_Last_String3_Height + on c.Type in (204) + and c.Last in (0,1) + and c.String3 = p.String2 + and c.Height <= ? + and c.Height > ? + and c.Hash = c.String2 + where p.Type in (200,201,202) + and p.Last = 1 + and p.String1 = u.String1 + and p.Height > 0 + )Commentators from Transactions u indexed by Transactions_Type_Last_String1_Height_Id where u.Type in (100) - and u.Height is not null - and u.String1 in ( )sql" + addressesWhere + R"sql( ) - and u.Last = 1 + and u.Last = 1 + and u.String1 in ( )sql" + addressesWhere + R"sql( ) + and u.Height is not null )sql"; TryTransactionStep(__func__, [&]() @@ -355,8 +368,16 @@ namespace PocketDb auto stmt = SetupSqlStatement(sql); int i = 1; + // Referrals + TryBindStatementInt(stmt, i++, nHeight); + TryBindStatementInt(stmt, i++, nHeight - depth); + // Comments TryBindStatementInt(stmt, i++, nHeight); TryBindStatementInt(stmt, i++, nHeight - depth); + // Commentators + TryBindStatementInt(stmt, i++, nHeight); + TryBindStatementInt(stmt, i++, nHeight - depth); + // Addresses for (const auto& address: addresses) TryBindStatementText(stmt, i++, address); @@ -377,8 +398,11 @@ namespace PocketDb return result; } - vector> WebRpcRepository::GetAccountProfiles(const vector& addresses, - const vector& ids, bool shortForm) + vector> WebRpcRepository::GetAccountProfiles( + const vector& addresses, + const vector& ids, + bool shortForm, + int firstFlagsDepth) { vector> result{}; @@ -419,8 +443,8 @@ namespace PocketDb from Transactions ru indexed by Transactions_Type_Last_String2_Height where ru.Type in (100) and ru.Last in (0,1) - and ru.Height > 0 and ru.String2 = u.String1 + and ru.Height > 0 and ru.ROWID = ( select min(ru1.ROWID) from Transactions ru1 indexed by Transactions_Id @@ -429,14 +453,13 @@ namespace PocketDb ) ),0) as ReferralsCount - , u.Hash as AccountHash - )sql"; } string sql = R"sql( select - u.String1 as Address + u.Hash as AccountHash + , u.String1 as Address , u.Id , p.String2 as Name , p.String3 as Avatar @@ -462,28 +485,28 @@ namespace PocketDb ,0) as Reputation , ( - select count(*) + select count() from Transactions subs indexed by Transactions_Type_Last_String1_Height_Id where subs.Type in (302,303) and subs.Height > 0 and subs.Last = 1 and subs.String1 = u.String1 ) as SubscribesCount , ( - select count(*) + select count() from Transactions subs indexed by Transactions_Type_Last_String2_Height where subs.Type in (302,303) and subs.Height > 0 and subs.Last = 1 and subs.String2 = u.String1 ) as SubscribersCount , ( - select count(*) + select count() from Transactions subs indexed by Transactions_Type_Last_String1_Height_Id where subs.Type in (305) and subs.Height > 0 and subs.Last = 1 and subs.String1 = u.String1 ) as BlockingsCount - , ( - select count(*) + , ifnull(( + select sum(lkr.Value) from Ratings lkr indexed by Ratings_Type_Id_Last_Height - where lkr.Type = 1 and lkr.Id = u.Id - ) as Likers + where lkr.Type in (111,112,113) and lkr.Id = u.Id and lkr.Last = 1 + ),0) as Likers , p.String6 as Pubkey , p.String4 as About @@ -510,13 +533,36 @@ namespace PocketDb )gr ) as FlagsJson + , ( + select json_group_object(gr.Type, gr.Cnt) + from ( + select (f.Int1)Type, (count())Cnt + from Transactions f indexed by Transactions_Type_Last_String3_Height + cross join ( + select min(fp.Height)minHeight + from Transactions fp + where fp.Type in (200,201,202) + and fp.String1 = u.String1 + and fp.Hash = fp.String2 + and fp.Last in (0, 1) + and fp.Height > 0 + )fp + where f.Type in (410) + and f.Last = 0 + and f.String3 = u.String1 + and f.Height >= fp.minHeight + and f.Height <= (fp.minHeight + ?) + group by f.Int1 + )gr + ) as FirstFlagsCount + )sql" + fullProfileSql + R"sql( from Transactions u indexed by Transactions_Type_Last_String1_Height_Id cross join Payload p on p.TxHash=u.Hash where u.Type in (100,101,102) - and u.Last=1 + and u.Last = 1 and u.Height is not null )sql" + where + R"sql( )sql"; @@ -527,6 +573,7 @@ namespace PocketDb // Bind parameters int i = 1; + TryBindStatementInt(stmt, i++, firstFlagsDepth * 1440); for (const string& address : addresses) TryBindStatementText(stmt, i++, address); for (int64_t id : ids) @@ -535,12 +582,14 @@ namespace PocketDb // Fetch data while (sqlite3_step(*stmt) == SQLITE_ROW) { + UniValue record(UniValue::VOBJ); + int i = 0; - auto[ok0, address] = TryGetColumnString(*stmt, i++); + auto[ok0, hash] = TryGetColumnString(*stmt, i++); + auto[ok1, address] = TryGetColumnString(*stmt, i++); auto[ok2, id] = TryGetColumnInt64(*stmt, i++); - UniValue record(UniValue::VOBJ); - + record.pushKV("hash", hash); record.pushKV("address", address); record.pushKV("id", id); if (IsDeveloper(address)) record.pushKV("dev", true); @@ -570,6 +619,13 @@ namespace PocketDb record.pushKV("flags", flags); } + if (auto[ok, value] = TryGetColumnString(*stmt, i++); ok) + { + UniValue flags(UniValue::VOBJ); + flags.read(value); + record.pushKV("firstFlags", flags); + } + if (!shortForm) { @@ -595,7 +651,6 @@ namespace PocketDb } if (auto[ok, value] = TryGetColumnInt(*stmt, i++); ok) record.pushKV("rc", value); - if (auto[ok, value] = TryGetColumnString(*stmt, i++); ok) record.pushKV("hash", value); } result.emplace_back(address, id, record); @@ -607,22 +662,22 @@ namespace PocketDb return result; } - map WebRpcRepository::GetAccountProfiles(const vector& addresses, bool shortForm) + map WebRpcRepository::GetAccountProfiles(const vector& addresses, bool shortForm, int firstFlagsDepth) { map result{}; - auto _result = GetAccountProfiles(addresses, {}, shortForm); + auto _result = GetAccountProfiles(addresses, {}, shortForm, firstFlagsDepth); for (const auto[address, id, record] : _result) result.insert_or_assign(address, record); return result; } - map WebRpcRepository::GetAccountProfiles(const vector& ids, bool shortForm) + map WebRpcRepository::GetAccountProfiles(const vector& ids, bool shortForm, int firstFlagsDepth) { map result{}; - auto _result = GetAccountProfiles({}, ids, shortForm); + auto _result = GetAccountProfiles({}, ids, shortForm, firstFlagsDepth); for (const auto[address, id, record] : _result) result.insert_or_assign(id, record); @@ -1467,11 +1522,62 @@ namespace PocketDb return UniValue(UniValue::VARR); } - UniValue WebRpcRepository::GetBlockingToAddresses(const string& address) + UniValue WebRpcRepository::GetBlockings(const string& address) { - // TODO (brangr) (v0.21): implement - // Should return pagination list of account profiles - return UniValue(UniValue::VARR); + UniValue result(UniValue::VARR); + + TryTransactionStep(__func__, [&]() + { + auto stmt = SetupSqlStatement(R"sql( + select + u.Id + from Transactions b indexed by Transactions_Type_Last_String1_Height_Id + join Transactions u indexed by Transactions_Type_Last_String1_Height_Id + on u.Type in (100) and u.Last = 1 and u.String1 = b.String2 and u.Height > 0 + where b.Type in (305) + and b.Last = 1 + and b.String1 = ? + and b.Height > 0 + )sql"); + TryBindStatementText(stmt, 1, address); + + while (sqlite3_step(*stmt) == SQLITE_ROW) + if (auto[ok, value] = TryGetColumnInt64(*stmt, 0); ok) + result.push_back(value); + + FinalizeSqlStatement(*stmt); + }); + + return result; + } + + UniValue WebRpcRepository::GetBlockers(const string& address) + { + UniValue result(UniValue::VARR); + + TryTransactionStep(__func__, [&]() + { + auto stmt = SetupSqlStatement(R"sql( + select + u.Id + from Transactions b indexed by Transactions_Type_Last_String2_Height + cross join Transactions u indexed by Transactions_Type_Last_String1_Height_Id + on u.Type in (100) and u.Last = 1 and u.String1 = b.String1 and u.Height > 0 + where b.Type in (305) + and b.Last = 1 + and b.String2 = ? + and b.Height > 0 + )sql"); + TryBindStatementText(stmt, 1, address); + + while (sqlite3_step(*stmt) == SQLITE_ROW) + if (auto[ok, value] = TryGetColumnInt64(*stmt, 0); ok) + result.push_back(value); + + FinalizeSqlStatement(*stmt); + }); + + return result; } vector WebRpcRepository::GetTopAccounts(int topHeight, int countOut, const string& lang, @@ -2803,7 +2909,7 @@ namespace PocketDb // --------------------------------------------- // Get profiles for posts - auto profiles = GetAccountProfiles(authors, true); + auto profiles = GetAccountProfiles(authors); for (auto& record : tmpResult) record.second.pushKV("userprofile", profiles[record.second["address"].get_str()]); @@ -4183,5 +4289,4 @@ namespace PocketDb return result; } - } \ No newline at end of file diff --git a/src/pocketdb/repositories/web/WebRpcRepository.h b/src/pocketdb/repositories/web/WebRpcRepository.h index a1dcce09d..4bd2db009 100644 --- a/src/pocketdb/repositories/web/WebRpcRepository.h +++ b/src/pocketdb/repositories/web/WebRpcRepository.h @@ -78,12 +78,14 @@ namespace PocketDb UniValue GetAddressScores(const vector& postHashes, const string& address); - map GetAccountProfiles(const vector& addresses, bool shortForm = true); - map GetAccountProfiles(const vector& ids, bool shortForm = true); + map GetAccountProfiles(const vector& addresses, bool shortForm = true, int firstFlagsDepth = 14); + map GetAccountProfiles(const vector& ids, bool shortForm = true, int firstFlagsDepth = 14); UniValue GetSubscribesAddresses(const string& address, const vector& types = {ACTION_SUBSCRIBE, ACTION_SUBSCRIBE_PRIVATE }); UniValue GetSubscribersAddresses(const string& address, const vector& types = {ACTION_SUBSCRIBE, ACTION_SUBSCRIBE_PRIVATE }); - UniValue GetBlockingToAddresses(const string& address); + UniValue GetBlockings(const string& address); + UniValue GetBlockers(const string& address); + vector GetTopAccounts(int topHeight, int countOut, const string& lang, const vector& tags, const vector& contentTypes, const vector& adrsExcluded, const vector& tagsExcluded, int depth, @@ -161,7 +163,7 @@ namespace PocketDb double dekayVideo = 0.99; double dekayContent = 0.96; - vector> GetAccountProfiles(const vector& addresses, const vector& ids, bool shortForm); + vector> GetAccountProfiles(const vector& addresses, const vector& ids, bool shortForm, int firstFlagsDepth); }; typedef shared_ptr WebRpcRepositoryRef; diff --git a/src/pocketdb/services/ChainPostProcessing.cpp b/src/pocketdb/services/ChainPostProcessing.cpp index 72c557693..61a4c21e3 100644 --- a/src/pocketdb/services/ChainPostProcessing.cpp +++ b/src/pocketdb/services/ChainPostProcessing.cpp @@ -64,8 +64,10 @@ namespace PocketServices void ChainPostProcessing::IndexRatings(int height, vector& txs) { - map > ratingValues; - map> accountLikersSrc; + map> ratingValues; + vector distinctScores; + map>> likersValues; + // map> accountLikersSrc; // Actual consensus checker instance by current height auto reputationConsensus = PocketConsensus::ReputationConsensusFactoryInst.Instance(height); @@ -113,9 +115,6 @@ namespace PocketServices ratingValues[RatingType::RATING_CONTENT][scoreData->ContentId] += scoreData->ScoreValue - 3; - if (scoreData->ScoreValue == 4 || scoreData->ScoreValue == 5) - BuildAccountLikers(scoreData, accountLikersSrc); - break; case PocketTx::ACTION_SCORE_COMMENT: @@ -125,19 +124,25 @@ namespace PocketServices ratingValues[RatingType::RATING_COMMENT][scoreData->ContentId] += scoreData->ScoreValue; - if (scoreData->ScoreValue == 1) - BuildAccountLikers(scoreData, accountLikersSrc); - break; - // Not supported score type + // Not supported score type default: break; } + + // Extend list of ratings with likers values + reputationConsensus->DistinctScores(scoreData, distinctScores); } - // Prepare all ratings model records for increase Rating - shared_ptr > ratings = make_shared < vector < Rating >> (); + // Filter all distinct records + for (const auto& _scoreData : distinctScores) + { + reputationConsensus->ValidateAccountLiker(_scoreData, likersValues, ratingValues); + } + + // Prepare all ratings model records for increase ratings + shared_ptr> ratings = make_shared>(); for (const auto& tp : ratingValues) { for (const auto& itm : tp.second) @@ -156,22 +161,30 @@ namespace PocketServices } } - // Prepare all ratings model records for Liker type - map> accountLikers; - reputationConsensus->PrepareAccountLikers(accountLikersSrc, accountLikers); - - // Save likers in db - for (const auto& acc : accountLikers) + // Prepare likers models + for (const auto& tp : likersValues) { - for (const auto& lkrId : acc.second) + for (const auto& cnt : tp.second) { - Rating rtg; - rtg.SetType(RatingType::RATING_ACCOUNT_LIKERS); - rtg.SetHeight(height); - rtg.SetId(acc.first); - rtg.SetValue(lkrId); - - ratings->push_back(rtg); + for (const auto& lkr : cnt.second) + { + // Skip not changed likers count + if (lkr == 0 && ( + tp.first == RatingType::ACCOUNT_LIKERS_POST_LAST || + tp.first == RatingType::ACCOUNT_LIKERS_COMMENT_ROOT_LAST || + tp.first == RatingType::ACCOUNT_LIKERS_COMMENT_ANSWER_LAST || + tp.first == RatingType::ACCOUNT_DISLIKERS_COMMENT_ANSWER_LAST + )) + continue; + + Rating rtg; + rtg.SetType(tp.first); + rtg.SetHeight(height); + rtg.SetId(cnt.first); + rtg.SetValue(lkr); + + ratings->push_back(rtg); + } } } @@ -182,16 +195,4 @@ namespace PocketServices PocketDb::RatingsRepoInst.InsertRatings(ratings); } - void ChainPostProcessing::BuildAccountLikers(const shared_ptr & scoreData, map>& accountLikers) - { - auto found = find( - accountLikers[scoreData->ContentAddressId].begin(), - accountLikers[scoreData->ContentAddressId].end(), - scoreData->ScoreAddressId - ); - - if (found == accountLikers[scoreData->ContentAddressId].end()) - accountLikers[scoreData->ContentAddressId].push_back(scoreData->ScoreAddressId); - } - } // namespace PocketServices \ No newline at end of file diff --git a/src/pocketdb/services/ChainPostProcessing.h b/src/pocketdb/services/ChainPostProcessing.h index 291187a80..cb5a73df2 100644 --- a/src/pocketdb/services/ChainPostProcessing.h +++ b/src/pocketdb/services/ChainPostProcessing.h @@ -33,8 +33,6 @@ namespace PocketServices static void PrepareTransactions(const CBlock& block, vector& txs); static void IndexChain(const string& blockHash, int height, vector& txs); static void IndexRatings(int height, vector& txs); - private: - static void BuildAccountLikers(const shared_ptr& scoreData, map>& accountLikers); }; } // namespace PocketServices diff --git a/src/pocketdb/web/PocketAccountRpc.cpp b/src/pocketdb/web/PocketAccountRpc.cpp index ac5430dab..bef9c8319 100644 --- a/src/pocketdb/web/PocketAccountRpc.cpp +++ b/src/pocketdb/web/PocketAccountRpc.cpp @@ -54,8 +54,13 @@ namespace PocketWeb::PocketWebRpc if (request.params.size() > 1) shortForm = request.params[1].get_str() == "1"; + // Count of days for first flags after first content publish + int firstFlagsDepth = 7; + if (request.params.size() > 2 && request.params[2].isNum() && request.params[2].get_int() > 0) + firstFlagsDepth = request.params[2].get_int(); + // Get data - map profiles = request.DbConnection()->WebRpcRepoInst->GetAccountProfiles(addresses, shortForm); + map profiles = request.DbConnection()->WebRpcRepoInst->GetAccountProfiles(addresses, shortForm, firstFlagsDepth); for (auto& p : profiles) result.push_back(p.second); @@ -148,15 +153,26 @@ namespace PocketWeb::PocketWebRpc if (result["address"].isNull()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pocketcoin address not found : " + address); - // Cechk account permissions - AccountData accountData = { result["address_id"].get_int64(), result["reputation"].get_int64(), result["user_reg_height"].get_int64(), result["likers"].get_int64() }; - auto accountMode = reputationConsensus->GetAccountMode(result["reputation"].get_int(), result["balance"].get_int64()); - auto accountIsShark = reputationConsensus->IsShark(accountData); - + // Check account permissions + const AccountData accountData = request.DbConnection()->ConsensusRepoInst->GetAccountData(address); + + auto accountMode = reputationConsensus->GetAccountMode(accountData.Reputation, accountData.Balance); result.pushKV("mode", accountMode); result.pushKV("trial", accountMode == AccountMode_Trial); - result.pushKV("reputation", result["reputation"].get_int() / 10.0); + result.pushKV("reputation", accountData.Reputation / 10.0); + + // Extend result data with badges array + auto badgeSet = reputationConsensus->GetBadges(accountData); + UniValue badges = badgeSet.ToJson(); + result.pushKV("badges", badges); + + result.pushKV("user_reg_date", accountData.RegistrationTime); + result.pushKV("user_reg_height", accountData.RegistrationHeight); + result.pushKV("reputation", accountData.Reputation); + result.pushKV("balance", accountData.Balance); + result.pushKV("likers", accountData.LikersAll()); + // Spent/Unspent limits int64_t postLimit; int64_t videoLimit; int64_t articleLimit; @@ -219,13 +235,6 @@ namespace PocketWeb::PocketWebRpc if (!result["mod_flag_spent"].isNull()) result.pushKV("mod_flag_unspent", reputationConsensus->GetConsensusLimit(ConsensusLimit_moderation_flag_count) - result["mod_flag_spent"].get_int()); - if (accountIsShark) - { - UniValue badges(UniValue::VARR); - badges.push_back("shark"); - result.pushKV("badges", badges); - } - return result; } @@ -429,13 +438,26 @@ namespace PocketWeb::PocketWebRpc if (request.fHelp) throw std::runtime_error( "GetAccountBlockings \"address\"\n" - "\nReturn blocked accounts list with pagination - NOT IMPLEMENTED\n"); + "\nReturn blocked accounts list\n"); RPCTypeCheck(request.params, {UniValue::VSTR}); string address = request.params[0].get_str(); - return request.DbConnection()->WebRpcRepoInst->GetBlockingToAddresses(address); + return request.DbConnection()->WebRpcRepoInst->GetBlockings(address); + } + + UniValue GetAccountBlockers(const JSONRPCRequest& request) + { + if (request.fHelp) + throw std::runtime_error( + "GetAccountBlockers \"address\"\n" + "\nReturns a list of accounts that have blocked the specified address\n"); + + RPCTypeCheck(request.params, {UniValue::VSTR}); + + string address = request.params[0].get_str(); + return request.DbConnection()->WebRpcRepoInst->GetBlockers(address); } UniValue GetTopAccounts(const JSONRPCRequest& request) @@ -506,7 +528,7 @@ namespace PocketWeb::PocketWebRpc adrsExcluded, tagsExcluded, depth, badReputationLimit); if (!ids.empty()) { - auto profiles = request.DbConnection()->WebRpcRepoInst->GetAccountProfiles(ids, true); + auto profiles = request.DbConnection()->WebRpcRepoInst->GetAccountProfiles(ids); for (const auto[id, record] : profiles) result.push_back(record); } diff --git a/src/pocketdb/web/PocketAccountRpc.h b/src/pocketdb/web/PocketAccountRpc.h index 73899ee4c..a360878d9 100644 --- a/src/pocketdb/web/PocketAccountRpc.h +++ b/src/pocketdb/web/PocketAccountRpc.h @@ -26,6 +26,7 @@ namespace PocketWeb::PocketWebRpc UniValue GetAccountSubscribes(const JSONRPCRequest& request); UniValue GetAccountSubscribers(const JSONRPCRequest& request); UniValue GetAccountBlockings(const JSONRPCRequest& request); + UniValue GetAccountBlockers(const JSONRPCRequest& request); UniValue GetTopAccounts(const JSONRPCRequest& request); } diff --git a/src/pocketdb/web/PocketRpc.cpp b/src/pocketdb/web/PocketRpc.cpp index 8d83e00f1..5211cfecf 100644 --- a/src/pocketdb/web/PocketRpc.cpp +++ b/src/pocketdb/web/PocketRpc.cpp @@ -75,7 +75,8 @@ static const CRPCCommand commands[] = {"accounts", "getuserstatistic", &GetAccountStatistic, {"address", "height", "depth"}}, {"accounts", "getusersubscribes", &GetAccountSubscribes, {"address", "height", "depth"}}, {"accounts", "getusersubscribers", &GetAccountSubscribers, {"address", "height", "depth"}}, - {"accounts", "getuserblockings", &GetAccountBlockings, {"address", "height", "depth"}}, + {"accounts", "getuserblockings", &GetAccountBlockings, {"address"}}, + {"accounts", "getuserblockers", &GetAccountBlockers, {"address"}}, {"accounts", "gettopaccounts", &GetTopAccounts, {"topHeight","countOut","lang","tags","contentTypes","adrsExcluded","tagsExcluded","depth"}}, // Scores diff --git a/src/pocketdb/web/SearchRpc.cpp b/src/pocketdb/web/SearchRpc.cpp index 4702cc18c..03f952e4f 100644 --- a/src/pocketdb/web/SearchRpc.cpp +++ b/src/pocketdb/web/SearchRpc.cpp @@ -144,7 +144,7 @@ namespace PocketWeb::PocketWebRpc auto ids = request.DbConnection()->SearchRepoInst->SearchUsersOld(searchRequest); // Get accounts data - auto accounts = request.DbConnection()->WebRpcRepoInst->GetAccountProfiles(ids, true); + auto accounts = request.DbConnection()->WebRpcRepoInst->GetAccountProfiles(ids); UniValue data(UniValue::VARR); for (const auto& account : accounts) @@ -440,7 +440,7 @@ namespace PocketWeb::PocketWebRpc auto ids = request.DbConnection()->SearchRepoInst->GetRecommendedAccountByAddressSubscriptions(address, addressExclude, contentTypes, lang, cntOut, nHeight, depth); if (!ids.empty()) { - auto profiles = request.DbConnection()->WebRpcRepoInst->GetAccountProfiles(ids, true); + auto profiles = request.DbConnection()->WebRpcRepoInst->GetAccountProfiles(ids); for (const auto[id, record] : profiles) result.push_back(record); } diff --git a/src/rest.cpp b/src/rest.cpp index cbcac8da2..e0f2eca13 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -753,6 +753,16 @@ static double getEmission(int height) return emission; } +static bool rest_emission(HTTPRequest* req, const std::string& strURIPart) +{ + if (!CheckWarmup(req)) + return false; + + req->WriteHeader("Content-Type", "text/plain"); + req->WriteReply(HTTP_OK, std::to_string(getEmission(chainActive.Height()))); + return true; +} + static bool get_static_status(HTTPRequest* req, const std::string& strURIPart) { if (!CheckWarmup(req)) @@ -863,6 +873,7 @@ static const struct {"/rest/headers/", rest_headers}, {"/rest/getutxos", rest_getutxos}, {"/rest/blockhash", rest_blockhash}, + {"/rest/emission", rest_emission}, }; void StartREST()