@@ -576,17 +576,32 @@ void NodeImpl::load_persisted_shares()
576576 if (!m_storage || !m_storage->is_available ())
577577 return ;
578578
579- // load_sharechain iterates the height index and loads each share
580- auto hashes = m_storage->get_shares_by_height_range (0 , UINT64_MAX );
581- if (hashes.empty ())
579+ // load_sharechain iterates the height index and loads each share.
580+ // Limit to keep_per_head shares to avoid loading unbounded history
581+ // into memory (LevelDB is never pruned, so it accumulates forever).
582+ auto all_hashes = m_storage->get_shares_by_height_range (0 , UINT64_MAX );
583+ if (all_hashes.empty ())
582584 {
583585 LOG_INFO << " No persisted shares found in LevelDB" ;
584586 return ;
585587 }
586588
589+ const size_t keep_per_head = PoolConfig::chain_length () * 2 + 10 ;
590+ const size_t total_in_db = all_hashes.size ();
591+
592+ // Only load the most recent shares (highest height = end of vector)
593+ size_t skip = 0 ;
594+ if (total_in_db > keep_per_head)
595+ {
596+ skip = total_in_db - keep_per_head;
597+ LOG_INFO << " [Pool] LevelDB has " << total_in_db << " shares, loading only newest "
598+ << keep_per_head << " (skipping " << skip << " old shares)" ;
599+ }
600+
587601 int loaded = 0 ;
588- for (const auto & hash : hashes )
602+ for (size_t i = skip; i < total_in_db; ++i )
589603 {
604+ const auto & hash = all_hashes[i];
590605 std::vector<uint8_t > data;
591606 uint256 prev; uint64_t height, ts; uint256 work, target; bool orphan;
592607 if (!m_storage->load_share (hash, data, prev, height, ts, work, target, orphan))
@@ -612,12 +627,25 @@ void NodeImpl::load_persisted_shares()
612627 }
613628 catch (const std::exception& e)
614629 {
615- LOG_WARNING << " Failed to load share " << hash.ToString (). substr ( 0 , 16 )
616- << " ... from LevelDB: " << e.what ();
630+ LOG_WARNING << " Failed to load share " << hash.ToString ()
631+ << " from LevelDB: " << e.what ();
617632 }
618633 }
619634
620- LOG_INFO << " [Pool] Loaded " << loaded << " shares from LevelDB storage" ;
635+ LOG_INFO << " [Pool] Loaded " << loaded << " shares from LevelDB storage"
636+ << " (DB total: " << total_in_db << " , limit: " << keep_per_head << " )" ;
637+
638+ // Prune old shares from LevelDB that we skipped
639+ if (skip > 0 )
640+ {
641+ size_t pruned = 0 ;
642+ for (size_t i = 0 ; i < skip; ++i)
643+ {
644+ if (m_storage->remove_share (all_hashes[i]))
645+ ++pruned;
646+ }
647+ LOG_INFO << " [Pool] Pruned " << pruned << " old shares from LevelDB" ;
648+ }
621649}
622650
623651void NodeImpl::start_outbound_connections ()
@@ -676,7 +704,8 @@ void NodeImpl::run_think()
676704
677705 LOG_INFO << " [Pool] run_think(): chain=" << m_tracker.chain .size ()
678706 << " verified=" << m_tracker.verified .size ()
679- << " heads=" << m_tracker.chain .get_heads ().size ();
707+ << " heads=" << m_tracker.chain .get_heads ().size ()
708+ << " rss=" << get_rss_mb () << " MB" ;
680709
681710 // Capture block_rel_height fn by value for thread safety
682711 auto block_rel_height = m_block_rel_height_fn
@@ -701,21 +730,36 @@ void NodeImpl::run_think()
701730 {
702731 // Trim stale shares (on ioc thread — safe with phase2)
703732 const size_t keep_per_head = PoolConfig::chain_length () * 2 + 10 ;
704- auto trim_chain = [&](auto & sc, const char * label, bool owns_data = true ) {
733+ std::vector<uint256> evicted_from_chain;
734+ auto trim_chain = [&](auto & sc, const char * label, bool owns_data = true ,
735+ std::vector<uint256>* evicted = nullptr ) {
705736 if (sc.size () <= keep_per_head)
706737 return ;
707738 auto heads_copy = sc.get_heads ();
708739 size_t total_removed = 0 ;
709740 for (auto & [head_hash, tail_hash] : heads_copy) {
710- auto removed = sc.trim (head_hash, keep_per_head, owns_data);
741+ auto removed = sc.trim (head_hash, keep_per_head, owns_data, evicted );
711742 total_removed += removed;
712743 }
713744 if (total_removed > 0 )
714745 LOG_INFO << " [Pool] Trimmed " << total_removed << " old shares from " << label
715746 << " (now " << sc.size () << " )" ;
716747 };
717748 trim_chain (m_tracker.verified , " verified" , /* owns_data=*/ false );
718- trim_chain (m_tracker.chain , " chain" );
749+ trim_chain (m_tracker.chain , " chain" , /* owns_data=*/ true , &evicted_from_chain);
750+
751+ // Prune evicted shares from LevelDB
752+ if (!evicted_from_chain.empty () && m_storage && m_storage->is_available ())
753+ {
754+ size_t pruned = 0 ;
755+ for (const auto & h : evicted_from_chain)
756+ {
757+ if (m_storage->remove_share (h))
758+ ++pruned;
759+ }
760+ if (pruned > 0 )
761+ LOG_INFO << " [Pool] Pruned " << pruned << " evicted shares from LevelDB" ;
762+ }
719763
720764 // Ban peers that provided invalid/unverifiable shares.
721765 // Skip localhost:0 — that's our own locally created shares
0 commit comments