Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions hathor/builder/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ def build(self) -> BuildArtifacts:
event_manager = self._get_or_create_event_manager()
indexes = self._get_or_create_indexes_manager()
tx_storage = self._get_or_create_tx_storage(indexes)
feature_service = self._get_or_create_feature_service(tx_storage)
bit_signaling_service = self._get_or_create_bit_signaling_service(tx_storage)

if self._enable_address_index:
Expand Down Expand Up @@ -188,6 +189,7 @@ def build(self) -> BuildArtifacts:
checkpoints=self._checkpoints,
capabilities=self._capabilities,
environment_info=get_environment_info(self._cmdline, peer_id.id),
feature_service=feature_service,
bit_signaling_service=bit_signaling_service,
**kwargs
)
Expand Down
1 change: 1 addition & 0 deletions hathor/builder/cli_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ def create_manager(self, reactor: PosixReactorBase) -> HathorManager:
environment_info=get_environment_info(args=str(self._args), peer_id=peer_id.id),
full_verification=full_verification,
enable_event_queue=self._args.x_enable_event_queue,
feature_service=self.feature_service,
bit_signaling_service=bit_signaling_service
)

Expand Down
5 changes: 5 additions & 0 deletions hathor/conf/testnet.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

from hathor.checkpoint import Checkpoint as cp
from hathor.conf.settings import HathorSettings
from hathor.feature_activation.settings import Settings as FeatureActivationSettings

SETTINGS = HathorSettings(
P2PKH_VERSION_BYTE=b'\x49',
Expand Down Expand Up @@ -51,4 +52,8 @@
cp(1_500_000, bytes.fromhex('000000000c3591805f4748480b59ac1788f754fc004930985a487580e2b5de8f')),
cp(1_600_000, bytes.fromhex('00000000060adfdfd7d488d4d510b5779cf35a3c50df7bcff941fbb6957be4d2')),
],
FEATURE_ACTIVATION=FeatureActivationSettings(
enable_usage=True,
default_threshold=30240
)
)
6 changes: 3 additions & 3 deletions hathor/conf/testnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,6 @@ CHECKPOINTS:
1_500_000: 000000000c3591805f4748480b59ac1788f754fc004930985a487580e2b5de8f
1_600_000: 00000000060adfdfd7d488d4d510b5779cf35a3c50df7bcff941fbb6957be4d2

# TODO: Enable this config when settings via python modules are no longer used
# FEATURE_ACTIVATION:
# default_threshold: 30240 # 30240 = 75% of evaluation_interval (40320)
FEATURE_ACTIVATION:
enable_usage: true
default_threshold: 30240 # 30240 = 75% of evaluation_interval (40320)
3 changes: 3 additions & 0 deletions hathor/feature_activation/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ class Settings(BaseModel, validate_all=True):
# neither their values changed, to preserve history.
features: dict[Feature, Criteria] = {}

# Boolean indicating whether feature activation can be used.
enable_usage: bool = False

@validator('default_threshold')
def _validate_default_threshold(cls, default_threshold: int, values: dict[str, Any]) -> int:
"""Validates that the default_threshold is not greater than the evaluation_interval."""
Expand Down
31 changes: 31 additions & 0 deletions hathor/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
SpendingVoidedError,
)
from hathor.feature_activation.bit_signaling_service import BitSignalingService
from hathor.feature_activation.feature import Feature
from hathor.feature_activation.feature_service import FeatureService
from hathor.mining import BlockTemplate, BlockTemplates
from hathor.p2p.manager import ConnectionsManager
from hathor.p2p.peer_discovery import PeerDiscovery
Expand Down Expand Up @@ -98,6 +100,7 @@ def __init__(self,
tx_storage: TransactionStorage,
p2p_manager: ConnectionsManager,
event_manager: EventManager,
feature_service: FeatureService,
bit_signaling_service: BitSignalingService,
network: str,
hostname: Optional[str] = None,
Expand Down Expand Up @@ -172,6 +175,7 @@ def __init__(self,
self._event_manager.save_event_queue_state(enable_event_queue)
self._enable_event_queue = enable_event_queue

self._feature_service = feature_service
self._bit_signaling_service = bit_signaling_service

self.consensus_algorithm = consensus_algorithm
Expand Down Expand Up @@ -1096,6 +1100,33 @@ def tx_fully_validated(self, tx: BaseTransaction, *, quiet: bool) -> None:
self.wallet.on_new_tx(tx)

self.log_new_object(tx, 'new {}', quiet=quiet)
self._log_feature_states(tx)

def _log_feature_states(self, vertex: BaseTransaction) -> None:
"""Log features states for a block. Used as part of the Feature Activation Phased Testing."""
if not settings.FEATURE_ACTIVATION.enable_usage or not isinstance(vertex, Block):
return

feature_descriptions = self._feature_service.get_bits_description(block=vertex)
state_by_feature = {
feature.value: description.state.value
for feature, description in feature_descriptions.items()
}

self.log.info(
'New block accepted with feature activation states',
block_height=vertex.get_height(),
features_states=state_by_feature
)

features = [Feature.NOP_FEATURE_1, Feature.NOP_FEATURE_2, Feature.NOP_FEATURE_3]
for feature in features:
self._log_if_feature_is_active(vertex, feature)

def _log_if_feature_is_active(self, block: Block, feature: Feature) -> None:
"""Log if a feature is ACTIVE for a block. Used as part of the Feature Activation Phased Testing."""
if self._feature_service.is_feature_active(block=block, feature=feature):
self.log.info('Feature is ACTIVE for block', feature=feature.value, block_height=block.get_height())

def listen(self, description: str, use_ssl: Optional[bool] = None) -> None:
endpoint = self.connections.listen(description, use_ssl)
Expand Down