Skip to content

Commit

Permalink
[net processing] Sample the last 199 outbound time offsets
Browse files Browse the repository at this point in the history
  • Loading branch information
dergoegge committed Jan 2, 2024
1 parent 0adf1d0 commit d079ffc
Showing 1 changed file with 49 additions and 0 deletions.
49 changes: 49 additions & 0 deletions src/net_processing.cpp
Expand Up @@ -187,6 +187,51 @@ struct QueuedBlock {
std::unique_ptr<PartiallyDownloadedBlock> partialBlock;
};

class TimeOffsets
{
private:
// Historic maximum number of time offsets we include in our median.
static constexpr size_t N{199};

mutable Mutex m_mutex;
std::array<int64_t, N> m_offsets GUARDED_BY(m_mutex){};
size_t m_index GUARDED_BY(m_mutex){0};

public:
/** Add a new time offset sample. */
void Add(int64_t offset) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
{
LOCK(m_mutex);

// Stop sampling after N samples.
// TODO This maintains a historic bug of adjusted time and could be
// changed in the future.
if (m_index >= N) return;

m_offsets[m_index] = offset;
++m_index;
}

/** Compute and return the median of the collected time offset samples. */
int64_t Median() const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
{
LOCK(m_mutex);

// Only compute the median from 5 or more samples.
if (m_index < 4) return 0;

std::array<int64_t, N> sorted_copy = m_offsets;
std::sort(sorted_copy.begin(), sorted_copy.begin() + m_index);

if (m_index % 2 == 0) {
return (sorted_copy[m_index / 2] / 2) +
(sorted_copy[m_index / 2 - 1] / 2);
} else {
return sorted_copy[m_index / 2];
}
}
};

/**
* Data structure for an individual peer. This struct is not protected by
* cs_main since it does not contain validation-critical data.
Expand Down Expand Up @@ -729,6 +774,8 @@ class PeerManagerImpl final : public PeerManager
/** Next time to check for stale tip */
std::chrono::seconds m_stale_tip_check_time GUARDED_BY(cs_main){0s};

TimeOffsets m_outbound_time_offsets;

const Options m_opts;

bool RejectIncomingTxs(const CNode& peer) const;
Expand Down Expand Up @@ -3558,6 +3605,8 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
// Don't use timedata samples from inbound peers to make it
// harder for others to tamper with our adjusted time.
AddTimeData(pfrom.addr, peer->m_time_offset);

m_outbound_time_offsets.Add(peer->m_time_offset);
}

// If the peer is old enough to have the old alert system, send it the final alert.
Expand Down

0 comments on commit d079ffc

Please sign in to comment.