@@ -171,6 +171,9 @@ class ScraperStatsQuorumHasher
171
171
struct HasherProxy
172
172
{
173
173
CHashWriter m_hasher; // !< Hashes the supplied data.
174
+ CHashWriter m_small_hasher; // !< Hashes small mag segment.
175
+ CHashWriter m_medium_hasher; // !< Hashes medium mag segment.
176
+ CHashWriter m_large_hasher; // !< Hashes large mag segment.
174
177
uint32_t m_zero_magnitude_count; // !< Tracks zero-magnitude CPIDs.
175
178
bool m_zero_magnitude_hashed; // !< Tracks when to hash the zeros.
176
179
@@ -180,6 +183,9 @@ class ScraperStatsQuorumHasher
180
183
// !
181
184
HasherProxy ()
182
185
: m_hasher(CHashWriter(SER_GETHASH, PROTOCOL_VERSION))
186
+ , m_small_hasher(CHashWriter(SER_GETHASH, PROTOCOL_VERSION))
187
+ , m_medium_hasher(CHashWriter(SER_GETHASH, PROTOCOL_VERSION))
188
+ , m_large_hasher(CHashWriter(SER_GETHASH, PROTOCOL_VERSION))
183
189
, m_zero_magnitude_count(0 )
184
190
, m_zero_magnitude_hashed(false )
185
191
{
@@ -192,13 +198,29 @@ class ScraperStatsQuorumHasher
192
198
// ! \param cpid The CPID value to hash.
193
199
// ! \param magnitude The magnitude value to hash.
194
200
// !
195
- void Add (Cpid cpid, uint16_t magnitude)
201
+ void Add (const Cpid cpid, const Magnitude magnitude)
196
202
{
197
- if (magnitude > 0 ) {
198
- m_hasher << cpid;
199
- WriteCompactSize (m_hasher, magnitude);
200
- } else {
201
- m_zero_magnitude_count++;
203
+ switch (magnitude.Which ()) {
204
+ case Magnitude::Kind::ZERO:
205
+ m_zero_magnitude_count++;
206
+ break ;
207
+
208
+ case Magnitude::Kind::SMALL:
209
+ m_small_hasher
210
+ << cpid
211
+ << static_cast <uint8_t >(magnitude.Compact ());
212
+ break ;
213
+
214
+ case Magnitude::Kind::MEDIUM:
215
+ m_medium_hasher
216
+ << cpid
217
+ << static_cast <uint8_t >(magnitude.Compact ());
218
+ break ;
219
+
220
+ case Magnitude::Kind::LARGE:
221
+ m_large_hasher << cpid;
222
+ WriteCompactSize (m_large_hasher, magnitude.Compact ());
223
+ break ;
202
224
}
203
225
}
204
226
@@ -211,7 +233,7 @@ class ScraperStatsQuorumHasher
211
233
// !
212
234
void RoundAndAdd (Cpid cpid, double magnitude)
213
235
{
214
- Add (cpid, std::nearbyint (magnitude));
236
+ Add (cpid, Magnitude::RoundFrom (magnitude));
215
237
}
216
238
217
239
// !
@@ -229,7 +251,14 @@ class ScraperStatsQuorumHasher
229
251
// first project:
230
252
//
231
253
if (!m_zero_magnitude_hashed) {
232
- m_hasher << VARINT (m_zero_magnitude_count);
254
+ m_hasher
255
+ << (CHashWriter (SER_GETHASH, PROTOCOL_VERSION)
256
+ << m_small_hasher.GetHash ()
257
+ << m_medium_hasher.GetHash ()
258
+ << m_large_hasher.GetHash ())
259
+ .GetHash ()
260
+ << VARINT (m_zero_magnitude_count);
261
+
233
262
m_zero_magnitude_hashed = true ;
234
263
}
235
264
@@ -1272,7 +1301,7 @@ class LegacySuperblockParser
1272
1301
const size_t binary_size = m_binary_magnitudes.size ();
1273
1302
1274
1303
for (size_t x = 0 ; x < binary_size && binary_size - x >= 18 ; x += 18 ) {
1275
- magnitudes.Add (
1304
+ magnitudes.AddLegacy (
1276
1305
*reinterpret_cast <const Cpid*>(byte_ptr + x),
1277
1306
be16toh (*reinterpret_cast <const int16_t *>(byte_ptr + x + 16 )));
1278
1307
}
@@ -1303,11 +1332,13 @@ class LegacySuperblockParser
1303
1332
continue ;
1304
1333
}
1305
1334
1306
- try {
1307
- magnitudes.Add (MiningId::Parse (parts[0 ]), std::stoi (parts[1 ]));
1308
- } catch (...) {
1309
- if (fDebug ) {
1310
- LogPrintf (" LegacySuperblock: Failed to parse magnitude." );
1335
+ if (const CpidOption cpid = MiningId::Parse (parts[0 ]).TryCpid ()) {
1336
+ try {
1337
+ magnitudes.AddLegacy (*cpid, std::stoi (parts[1 ]));
1338
+ } catch (...) {
1339
+ if (fDebug ) {
1340
+ LogPrintf (" LegacySuperblock: Failed to parse magnitude." );
1341
+ }
1311
1342
}
1312
1343
}
1313
1344
}
@@ -1496,7 +1527,7 @@ std::string Superblock::PackLegacy() const
1496
1527
out << " <ZERO>" << m_cpids.Zeros () << " </ZERO>"
1497
1528
<< " <BINARY>" ;
1498
1529
1499
- for (const auto & cpid_pair : m_cpids) {
1530
+ for (const auto & cpid_pair : m_cpids. Legacy () ) {
1500
1531
uint16_t mag = htobe16 (cpid_pair.second );
1501
1532
1502
1533
out.write (reinterpret_cast <const char *>(cpid_pair.first .Raw ().data ()), 16 );
@@ -1564,22 +1595,55 @@ Superblock::CpidIndex::CpidIndex(uint32_t zero_magnitude_count)
1564
1595
1565
1596
Superblock::CpidIndex::const_iterator Superblock::CpidIndex::begin () const
1566
1597
{
1567
- return m_magnitudes.begin ();
1598
+ if (m_legacy) {
1599
+ return const_iterator (
1600
+ NN::Magnitude::SCALE_FACTOR,
1601
+ m_legacy_magnitudes.begin (),
1602
+ m_legacy_magnitudes.end ());
1603
+ }
1604
+
1605
+ return const_iterator (
1606
+ decltype (m_small_magnitudes)::SCALE_FACTOR,
1607
+ m_small_magnitudes.begin (),
1608
+ m_small_magnitudes.end (),
1609
+ const_iterator (
1610
+ decltype (m_medium_magnitudes)::SCALE_FACTOR,
1611
+ m_medium_magnitudes.begin (),
1612
+ m_medium_magnitudes.end (),
1613
+ const_iterator (
1614
+ decltype (m_large_magnitudes)::SCALE_FACTOR,
1615
+ m_large_magnitudes.begin (),
1616
+ m_large_magnitudes.end ())));
1568
1617
}
1569
1618
1570
1619
Superblock::CpidIndex::const_iterator Superblock::CpidIndex::end () const
1571
1620
{
1572
- return m_magnitudes.end ();
1621
+ if (m_legacy) {
1622
+ return const_iterator (m_legacy_magnitudes.end ());
1623
+ }
1624
+
1625
+ return const_iterator (m_large_magnitudes.end ());
1573
1626
}
1574
1627
1575
1628
Superblock::CpidIndex::size_type Superblock::CpidIndex::size () const
1576
1629
{
1577
- return m_magnitudes.size ();
1630
+ if (m_legacy) {
1631
+ return m_legacy_magnitudes.size ();
1632
+ }
1633
+
1634
+ return m_small_magnitudes.size ()
1635
+ + m_medium_magnitudes.size ()
1636
+ + m_large_magnitudes.size ();
1578
1637
}
1579
1638
1580
1639
bool Superblock::CpidIndex::empty () const
1581
1640
{
1582
- return m_magnitudes.empty ();
1641
+ return size () == 0 ;
1642
+ }
1643
+
1644
+ const Superblock::MagnitudeStorageType& Superblock::CpidIndex::Legacy () const
1645
+ {
1646
+ return m_legacy_magnitudes;
1583
1647
}
1584
1648
1585
1649
uint32_t Superblock::CpidIndex::Zeros () const
@@ -1589,64 +1653,81 @@ uint32_t Superblock::CpidIndex::Zeros() const
1589
1653
1590
1654
size_t Superblock::CpidIndex::TotalCount () const
1591
1655
{
1592
- return m_magnitudes. size () + m_zero_magnitude_count;
1656
+ return size () + m_zero_magnitude_count;
1593
1657
}
1594
1658
1595
- uint64_t Superblock::CpidIndex::TotalMagnitude () const
1659
+ double Superblock::CpidIndex::TotalMagnitude () const
1596
1660
{
1597
- return m_total_magnitude;
1661
+ return static_cast < double >( m_total_magnitude) / NN::Magnitude::SCALE_FACTOR ;
1598
1662
}
1599
1663
1600
1664
double Superblock::CpidIndex::AverageMagnitude () const
1601
1665
{
1602
- if (m_magnitudes. empty ()) {
1666
+ if (empty ()) {
1603
1667
return 0 ;
1604
1668
}
1605
1669
1606
- return static_cast < double >(m_total_magnitude ) / m_magnitudes. size ();
1670
+ return TotalMagnitude ( ) / size ();
1607
1671
}
1608
1672
1609
- uint16_t Superblock::CpidIndex::MagnitudeOf (const Cpid& cpid) const
1673
+ Magnitude Superblock::CpidIndex::MagnitudeOf (const Cpid& cpid) const
1610
1674
{
1611
- const auto iter = m_magnitudes.find (cpid);
1675
+ if (m_legacy) {
1676
+ const auto iter = m_legacy_magnitudes.find (cpid);
1612
1677
1613
- if (iter == m_magnitudes.end ()) {
1614
- return 0 ;
1678
+ if (iter == m_legacy_magnitudes.end ()) {
1679
+ return Magnitude::Zero ();
1680
+ }
1681
+
1682
+ return Magnitude::FromScaled (iter->second * NN::Magnitude::SCALE_FACTOR);
1615
1683
}
1616
1684
1617
- return iter->second ;
1685
+ if (const auto mag_option = m_small_magnitudes.MagnitudeOf (cpid)) {
1686
+ return *mag_option;
1687
+ }
1688
+
1689
+ if (const auto mag_option = m_medium_magnitudes.MagnitudeOf (cpid)) {
1690
+ return *mag_option;
1691
+ }
1692
+
1693
+ if (const auto mag_option = m_large_magnitudes.MagnitudeOf (cpid)) {
1694
+ return *mag_option;
1695
+ }
1696
+
1697
+ return Magnitude::Zero ();
1618
1698
}
1619
1699
1620
1700
Superblock::CpidIndex::const_iterator
1621
1701
Superblock::CpidIndex::At (const size_t offset) const
1622
1702
{
1623
1703
// Not very efficient--we can optimize this if needed:
1624
- return std::next (m_magnitudes. begin (), offset);
1704
+ return std::next (begin (), offset);
1625
1705
}
1626
1706
1627
- void Superblock::CpidIndex::Add (const Cpid cpid, const uint16_t magnitude)
1707
+ void Superblock::CpidIndex::Add (const Cpid cpid, const Magnitude magnitude)
1628
1708
{
1629
- if (magnitude > 0 || m_legacy) {
1630
- // Only increment the total magnitude if the CPID does not already
1631
- // exist in the index:
1632
- if (m_magnitudes.emplace (cpid, magnitude).second == true ) {
1633
- m_total_magnitude += magnitude;
1634
- }
1635
- } else {
1636
- m_zero_magnitude_count++;
1637
- }
1638
- }
1709
+ // Only increment the total magnitude if the CPID does not already
1710
+ // exist in the index:
1711
+ switch (magnitude.Which ()) {
1712
+ case Magnitude::Kind::ZERO:
1713
+ m_zero_magnitude_count++;
1714
+ break ;
1639
1715
1640
- void Superblock::CpidIndex::Add (const MiningId id, const uint16_t magnitude)
1641
- {
1642
- if (const CpidOption cpid = id.TryCpid ()) {
1643
- Add (*cpid, magnitude);
1644
- } else if (!m_legacy) {
1645
- m_zero_magnitude_count++;
1716
+ case Magnitude::Kind::SMALL:
1717
+ m_total_magnitude += m_small_magnitudes.Add (cpid, magnitude);
1718
+ break ;
1719
+
1720
+ case Magnitude::Kind::MEDIUM:
1721
+ m_total_magnitude += m_medium_magnitudes.Add (cpid, magnitude);
1722
+ break ;
1723
+
1724
+ case Magnitude::Kind::LARGE:
1725
+ m_total_magnitude += m_large_magnitudes.Add (cpid, magnitude);
1726
+ break ;
1646
1727
}
1647
1728
}
1648
1729
1649
- void Superblock::CpidIndex::RoundAndAdd (const MiningId id , const double magnitude)
1730
+ void Superblock::CpidIndex::RoundAndAdd (const Cpid cpid , const double magnitude)
1650
1731
{
1651
1732
// The ScraperGetNeuralContract() function that these classes replace
1652
1733
// rounded magnitude values using a half-away-from-zero rounding mode
@@ -1658,13 +1739,35 @@ void Superblock::CpidIndex::RoundAndAdd(const MiningId id, const double magnitud
1658
1739
// To create legacy superblocks from scraper statistics with matching
1659
1740
// hashes, we filter magnitudes using the same rounding rules:
1660
1741
//
1661
- if (!m_legacy || std::round (magnitude) > 0 ) {
1662
- Add (id, std::nearbyint (magnitude));
1742
+ if (m_legacy) {
1743
+ if (std::round (magnitude) > 0 ) {
1744
+ AddLegacy (cpid, std::nearbyint (magnitude));
1745
+ } else {
1746
+ m_zero_magnitude_count++;
1747
+ }
1663
1748
} else {
1664
- m_zero_magnitude_count++;
1749
+ Add (cpid, Magnitude::RoundFrom (magnitude));
1750
+ }
1751
+ }
1752
+
1753
+ void Superblock::CpidIndex::AddLegacy (const Cpid cpid, const uint16_t magnitude)
1754
+ {
1755
+ if (m_legacy_magnitudes.emplace (cpid, magnitude).second == true ) {
1756
+ m_total_magnitude += magnitude * NN::Magnitude::SCALE_FACTOR;
1665
1757
}
1666
1758
}
1667
1759
1760
+ uint256 Superblock::CpidIndex::HashSegments () const
1761
+ {
1762
+ CHashWriter hasher (SER_GETHASH, PROTOCOL_VERSION);
1763
+
1764
+ hasher << SerializeHash (m_small_magnitudes);
1765
+ hasher << SerializeHash (m_medium_magnitudes);
1766
+ hasher << SerializeHash (m_large_magnitudes);
1767
+
1768
+ return hasher.GetHash ();
1769
+ }
1770
+
1668
1771
// -----------------------------------------------------------------------------
1669
1772
// Class: Superblock::ProjectStats
1670
1773
// -----------------------------------------------------------------------------
@@ -1819,7 +1922,7 @@ QuorumHash QuorumHash::Hash(const Superblock& superblock)
1819
1922
std::string input;
1820
1923
input.reserve (superblock.m_cpids .size () * (32 + 1 + 5 + 5 ));
1821
1924
1822
- for (const auto & cpid_pair : superblock.m_cpids ) {
1925
+ for (const auto & cpid_pair : superblock.m_cpids . Legacy () ) {
1823
1926
double dMagLength = RoundToString (cpid_pair.second , 0 ).length ();
1824
1927
double dExponent = pow (dMagLength, 5 );
1825
1928
0 commit comments