Skip to content

Commit 5c260b9

Browse files
committed
feat(harvesters): add base harvester abstract class
- BaseHarvester ABC with collect() interface - HarvestResult dataclass for standardized output - safe_collect() wrapper for exception handling
1 parent 4d19ed2 commit 5c260b9

2 files changed

Lines changed: 176 additions & 0 deletions

File tree

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# =============================================================================
2+
# TrueEntropy - Harvesters Package
3+
# =============================================================================
4+
#
5+
# Harvesters are the entropy collectors - they gather randomness from various
6+
# real-world sources and feed it into the entropy pool.
7+
#
8+
# Available Harvesters:
9+
# - TimingHarvester: CPU jitter and scheduling randomness
10+
# - NetworkHarvester: Network latency measurements
11+
# - SystemHarvester: System state (RAM, processes, etc.)
12+
# - ExternalHarvester: External APIs (earthquakes, crypto prices)
13+
#
14+
# =============================================================================
15+
16+
"""
17+
Entropy harvesters - collectors of real-world randomness.
18+
19+
This package contains various harvester classes that collect entropy
20+
from different sources and feed it into the entropy pool.
21+
"""
22+
23+
from trueentropy.harvesters.base import BaseHarvester
24+
from trueentropy.harvesters.timing import TimingHarvester
25+
from trueentropy.harvesters.network import NetworkHarvester
26+
from trueentropy.harvesters.system import SystemHarvester
27+
from trueentropy.harvesters.external import ExternalHarvester
28+
29+
__all__ = [
30+
"BaseHarvester",
31+
"TimingHarvester",
32+
"NetworkHarvester",
33+
"SystemHarvester",
34+
"ExternalHarvester",
35+
]

src/trueentropy/harvesters/base.py

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
# =============================================================================
2+
# TrueEntropy - Base Harvester Class
3+
# =============================================================================
4+
#
5+
# This module defines the abstract base class for all entropy harvesters.
6+
# All harvester implementations must inherit from BaseHarvester and implement
7+
# the collect() method.
8+
#
9+
# Design Philosophy:
10+
# - Harvesters are independent and can fail gracefully
11+
# - Each harvester provides an entropy estimate for its data
12+
# - Harvesters should be lightweight and non-blocking when possible
13+
#
14+
# =============================================================================
15+
16+
"""
17+
Abstract base class for entropy harvesters.
18+
19+
All harvester implementations must inherit from BaseHarvester and
20+
implement the collect() method.
21+
"""
22+
23+
from __future__ import annotations
24+
25+
from abc import ABC, abstractmethod
26+
from dataclasses import dataclass
27+
from typing import Optional
28+
29+
30+
@dataclass
31+
class HarvestResult:
32+
"""
33+
Result of an entropy harvest operation.
34+
35+
Attributes:
36+
data: Raw bytes collected from the source
37+
entropy_bits: Conservative estimate of entropy bits in the data
38+
source: Name of the source that provided the data
39+
success: Whether the harvest was successful
40+
error: Error message if harvest failed, None otherwise
41+
"""
42+
data: bytes
43+
entropy_bits: int
44+
source: str
45+
success: bool
46+
error: Optional[str] = None
47+
48+
49+
class BaseHarvester(ABC):
50+
"""
51+
Abstract base class for entropy harvesters.
52+
53+
Harvesters are responsible for collecting entropy from various sources
54+
and packaging it for the entropy pool. Each harvester should:
55+
56+
1. Collect data from its source (timing, network, system, etc.)
57+
2. Convert the data to bytes
58+
3. Estimate the entropy content
59+
4. Return a HarvestResult
60+
61+
Subclasses MUST implement:
62+
- name property: Returns the harvester's name
63+
- collect() method: Performs the actual collection
64+
65+
Example:
66+
>>> class MyHarvester(BaseHarvester):
67+
... @property
68+
... def name(self) -> str:
69+
... return "my_harvester"
70+
...
71+
... def collect(self) -> HarvestResult:
72+
... data = b"some entropy"
73+
... return HarvestResult(
74+
... data=data,
75+
... entropy_bits=8,
76+
... source=self.name,
77+
... success=True
78+
... )
79+
"""
80+
81+
@property
82+
@abstractmethod
83+
def name(self) -> str:
84+
"""
85+
Return the name of this harvester.
86+
87+
This is used for logging and identification.
88+
Names should be lowercase with underscores.
89+
90+
Returns:
91+
The harvester's name (e.g., "timing", "network")
92+
"""
93+
...
94+
95+
@abstractmethod
96+
def collect(self) -> HarvestResult:
97+
"""
98+
Collect entropy from this source.
99+
100+
This method should:
101+
1. Gather data from the entropy source
102+
2. Convert it to a bytes object
103+
3. Estimate the entropy content
104+
4. Return a HarvestResult
105+
106+
If collection fails, return a HarvestResult with:
107+
- success=False
108+
- error="description of what went wrong"
109+
- data=b"" (empty bytes)
110+
- entropy_bits=0
111+
112+
Returns:
113+
HarvestResult containing the collected entropy
114+
"""
115+
...
116+
117+
def safe_collect(self) -> HarvestResult:
118+
"""
119+
Safely collect entropy, catching any exceptions.
120+
121+
This wrapper ensures that harvester failures don't crash
122+
the entropy collection system. Any exception is caught
123+
and converted to a failed HarvestResult.
124+
125+
Returns:
126+
HarvestResult (always succeeds, but may indicate failure)
127+
"""
128+
try:
129+
return self.collect()
130+
except Exception as e:
131+
return HarvestResult(
132+
data=b"",
133+
entropy_bits=0,
134+
source=self.name,
135+
success=False,
136+
error=str(e)
137+
)
138+
139+
def __repr__(self) -> str:
140+
"""Return string representation."""
141+
return f"{self.__class__.__name__}(name={self.name!r})"

0 commit comments

Comments
 (0)