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
4 changes: 2 additions & 2 deletions hathor/builder/resources_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ def create_resources(self) -> server.Site:
# mining
(b'mining', MiningResource(self.manager), root),
(b'getmininginfo', MiningInfoResource(self.manager), root),
(b'get_block_template', GetBlockTemplateResource(self.manager), root),
(b'get_block_template', GetBlockTemplateResource(self.manager, settings), root),
(b'submit_block', SubmitBlockResource(self.manager), root),
(b'tx_parents', TxParentsResource(self.manager), root),
# /thin_wallet
Expand Down Expand Up @@ -281,7 +281,7 @@ def create_resources(self) -> server.Site:
(b'balance', BalanceResource(self.manager), wallet_resource),
(b'history', HistoryResource(self.manager), wallet_resource),
(b'address', AddressResource(self.manager), wallet_resource),
(b'send_tokens', SendTokensResource(self.manager), wallet_resource),
(b'send_tokens', SendTokensResource(self.manager, settings), wallet_resource),
(b'sign_tx', SignTxResource(self.manager), wallet_resource),
(b'unlock', UnlockWalletResource(self.manager), wallet_resource),
(b'lock', LockWalletResource(self.manager), wallet_resource),
Expand Down
1 change: 1 addition & 0 deletions hathor/consensus/poa/poa_block_producer.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ def _produce_block(self, previous_block: PoaBlock) -> None:
from hathor.transaction.poa import PoaBlock
block_templates = self.manager.get_block_templates(parent_block_hash=previous_block.hash)
block = block_templates.generate_mining_block(self.manager.rng, cls=PoaBlock)
block.init_static_metadata_from_storage(self._settings, self.manager.tx_storage)
assert isinstance(block, PoaBlock)

if block.get_height() <= self.manager.tx_storage.get_height_best_block():
Expand Down
21 changes: 11 additions & 10 deletions hathor/feature_activation/feature_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ def is_signaling_mandatory_features(self, block: 'Block') -> BlockSignalingState
Return whether a block is signaling features that are mandatory, that is, any feature currently in the
MUST_SIGNAL phase.
"""
bit_counts = block.get_feature_activation_bit_counts()
height = block.get_height()
bit_counts = block.static_metadata.feature_activation_bit_counts
height = block.static_metadata.height
offset_to_boundary = height % self._feature_settings.evaluation_interval
remaining_blocks = self._feature_settings.evaluation_interval - offset_to_boundary - 1
descriptions = self.get_bits_description(block=block)
Expand Down Expand Up @@ -95,7 +95,7 @@ def get_state(self, *, block: 'Block', feature: Feature) -> FeatureState:
# All blocks within the same evaluation interval have the same state, that is, the state is only defined for
# the block in each interval boundary. Therefore, we get the state of the previous boundary block or calculate
# a new state if this block is a boundary block.
height = block.get_height()
height = block.static_metadata.height
offset_to_boundary = height % self._feature_settings.evaluation_interval
offset_to_previous_boundary = offset_to_boundary or self._feature_settings.evaluation_interval
previous_boundary_height = height - offset_to_previous_boundary
Expand Down Expand Up @@ -139,7 +139,7 @@ def _calculate_new_state(
an AssertionError. Non-boundary blocks never calculate their own state, they get it from their parent block
instead.
"""
height = boundary_block.get_height()
height = boundary_block.static_metadata.height
criteria = self._feature_settings.features.get(feature)
evaluation_interval = self._feature_settings.evaluation_interval

Expand All @@ -162,7 +162,7 @@ def _calculate_new_state(
# Get the count for this block's parent. Since this is a boundary block, its parent count represents the
# previous evaluation interval count.
parent_block = boundary_block.get_block_parent()
counts = parent_block.get_feature_activation_bit_counts()
counts = parent_block.static_metadata.feature_activation_bit_counts
count = counts[criteria.bit]
threshold = criteria.get_threshold(self._feature_settings)

Expand Down Expand Up @@ -209,8 +209,9 @@ def _get_ancestor_at_height(self, *, block: 'Block', ancestor_height: int) -> 'B
Given a block, return its ancestor at a specific height.
Uses the height index if the block is in the best blockchain, or search iteratively otherwise.
"""
assert ancestor_height < block.get_height(), (
f"ancestor height must be lower than the block's height: {ancestor_height} >= {block.get_height()}"
assert ancestor_height < block.static_metadata.height, (
f"ancestor height must be lower than the block's height: "
f"{ancestor_height} >= {block.static_metadata.height}"
)

# It's possible that this method is called before the consensus runs for this block, therefore we do not know
Expand All @@ -219,7 +220,7 @@ def _get_ancestor_at_height(self, *, block: 'Block', ancestor_height: int) -> 'B
parent_metadata = parent_block.get_metadata()
assert parent_metadata.validation.is_fully_connected(), 'The parent should always be fully validated.'

if parent_block.get_height() == ancestor_height:
if parent_block.static_metadata.height == ancestor_height:
return parent_block

if not parent_metadata.voided_by and (ancestor := self._tx_storage.get_block_by_height(ancestor_height)):
Expand All @@ -237,11 +238,11 @@ def _get_ancestor_iteratively(self, *, block: 'Block', ancestor_height: int) ->
# TODO: there are further optimizations to be done here, the latest common block height could be persisted in
# metadata, so we could still use the height index if the requested height is before that height.
assert ancestor_height >= 0
assert block.get_height() - ancestor_height <= self._feature_settings.evaluation_interval, (
assert block.static_metadata.height - ancestor_height <= self._feature_settings.evaluation_interval, (
'requested ancestor is deeper than the maximum allowed'
)
ancestor = block
while ancestor.get_height() > ancestor_height:
while ancestor.static_metadata.height > ancestor_height:
ancestor = ancestor.get_block_parent()

return ancestor
2 changes: 1 addition & 1 deletion hathor/feature_activation/resources/feature.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def get_block_features(self, request: Request) -> bytes:

def get_features(self) -> bytes:
best_block = self.tx_storage.get_best_block()
bit_counts = best_block.get_feature_activation_bit_counts()
bit_counts = best_block.static_metadata.feature_activation_bit_counts
features = []

for feature, criteria in self._feature_settings.features.items():
Expand Down
27 changes: 13 additions & 14 deletions hathor/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ def _initialize_components_full_verification(self) -> None:
dt = LogDuration(t2 - t1)
dcnt = cnt - cnt2
tx_rate = '?' if dt == 0 else dcnt / dt
h = max(h, tx_meta.height or 0)
h = max(h, (tx.static_metadata.height if isinstance(tx, Block) else 0))
if dt > 30:
ts_date = datetime.datetime.fromtimestamp(self.tx_storage.latest_timestamp)
if h == 0:
Expand All @@ -469,12 +469,10 @@ def _initialize_components_full_verification(self) -> None:

try:
# TODO: deal with invalid tx
tx.calculate_height()
tx._update_parents_children_metadata()

if tx.can_validate_full():
tx.update_initial_metadata()
tx.calculate_min_height()
if tx.is_genesis:
assert tx.validate_checkpoint(self.checkpoints)
assert self.verification_service.validate_full(
Expand Down Expand Up @@ -661,31 +659,32 @@ def _verify_checkpoints(self) -> None:
for checkpoint in expected_checkpoints:
# XXX: query the database from checkpoint.hash and verify what comes out
try:
tx = self.tx_storage.get_transaction(checkpoint.hash)
block = self.tx_storage.get_block(checkpoint.hash)
except TransactionDoesNotExist as e:
raise InitializationError(f'Expected checkpoint does not exist in database: {checkpoint}') from e
tx_meta = tx.get_metadata()
if tx_meta.height != checkpoint.height:
meta = block.get_metadata()
height = block.static_metadata.height
if height != checkpoint.height:
raise InitializationError(
f'Expected checkpoint of hash {tx.hash_hex} to have height {checkpoint.height}, but instead it has'
f'height {tx_meta.height}'
f'Expected checkpoint of hash {block.hash_hex} to have height {checkpoint.height},'
f'but instead it has height {height}'
)
if tx_meta.voided_by:
pretty_voided_by = list(i.hex() for i in tx_meta.voided_by)
if meta.voided_by:
pretty_voided_by = list(i.hex() for i in meta.voided_by)
raise InitializationError(
f'Expected checkpoint {checkpoint} to *NOT* be voided, but it is being voided by: '
f'{pretty_voided_by}'
)
# XXX: query the height index from checkpoint.height and check that the hash matches
tx_hash = self.tx_storage.indexes.height.get(checkpoint.height)
if tx_hash is None:
block_hash = self.tx_storage.indexes.height.get(checkpoint.height)
if block_hash is None:
raise InitializationError(
f'Expected checkpoint {checkpoint} to be found in the height index, but it was not found'
)
if tx_hash != tx.hash:
if block_hash != block.hash:
raise InitializationError(
f'Expected checkpoint {checkpoint} to be found in the height index, but it instead the block with '
f'hash {tx_hash.hex()} was found'
f'hash {block_hash.hex()} was found'
)

def get_new_tx_parents(self, timestamp: Optional[float] = None) -> list[VertexId]:
Expand Down
2 changes: 1 addition & 1 deletion hathor/mining/block_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def generate_mining_block(
block = cls(outputs=tx_outputs, parents=parents, timestamp=block_timestamp,
data=data or b'', storage=storage, weight=self.weight, signal_bits=self.signal_bits)
if include_metadata:
block._metadata = TransactionMetadata(height=self.height, score=self.score)
block._metadata = TransactionMetadata(score=self.score)
block.get_metadata(use_storage=False)
return block

Expand Down
3 changes: 2 additions & 1 deletion hathor/p2p/resources/mining_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,9 @@ def render_GET(self, request):
self._settings.P2PKH_VERSION_BYTE.hex() + 'acbfb94571417423c1ed66f706730c4aea516ac5762cccb8'
)
block = self.manager.generate_mining_block(address=burn_address)
block.init_static_metadata_from_storage(self._settings, self.manager.tx_storage)

height = block.calculate_height() - 1
height = block.static_metadata.height - 1
difficulty = max(int(Weight(block.weight).to_pdiff()), 1)

parent = block.get_block_parent()
Expand Down
7 changes: 3 additions & 4 deletions hathor/p2p/resources/status.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,8 @@ def render_GET(self, request):

best_block_tips = []
for tip in self.manager.tx_storage.get_best_block_tips():
tx = self.manager.tx_storage.get_transaction(tip)
meta = tx.get_metadata()
best_block_tips.append({'hash': tx.hash_hex, 'height': meta.height})
block = self.manager.tx_storage.get_block(tip)
best_block_tips.append({'hash': block.hash_hex, 'height': block.static_metadata.height})

best_block = self.manager.tx_storage.get_best_block()
raw_best_blockchain = self.manager.tx_storage.get_n_height_tips(self._settings.DEFAULT_BEST_BLOCKCHAIN_BLOCKS)
Expand Down Expand Up @@ -122,7 +121,7 @@ def render_GET(self, request):
'best_block_tips': best_block_tips,
'best_block': {
'hash': best_block.hash_hex,
'height': best_block.get_metadata().height,
'height': best_block.static_metadata.height,
},
'best_blockchain': best_blockchain,
}
Expand Down
4 changes: 2 additions & 2 deletions hathor/p2p/sync_v2/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
from hathor.transaction.storage.exceptions import TransactionDoesNotExist
from hathor.transaction.vertex_parser import VertexParser
from hathor.types import VertexId
from hathor.util import collect_n, not_none
from hathor.util import collect_n

if TYPE_CHECKING:
from hathor.p2p.protocol import HathorProtocol
Expand Down Expand Up @@ -846,7 +846,7 @@ def handle_get_best_block(self, _payload: str) -> None:
assert meta.validation.is_fully_connected()
payload = BestBlockPayload(
block=best_block.hash,
height=not_none(meta.height),
height=best_block.static_metadata.height,
)
self.send_message(ProtocolMessages.BEST_BLOCK, payload.json())

Expand Down
4 changes: 2 additions & 2 deletions hathor/p2p/sync_v2/streamers.py
Original file line number Diff line number Diff line change
Expand Up @@ -296,8 +296,8 @@ def send_next(self) -> None:
# Check if tx is confirmed by the `self.current_block` or any next block.
assert cur_metadata.first_block is not None
assert self.current_block is not None
first_block = self.tx_storage.get_transaction(cur_metadata.first_block)
if not_none(first_block.get_metadata().height) < not_none(self.current_block.get_metadata().height):
first_block = self.tx_storage.get_block(cur_metadata.first_block)
if not_none(first_block.static_metadata.height) < not_none(self.current_block.static_metadata.height):
self.log.debug('skipping tx: out of current block')
self.bfs.skip_neighbors(cur)
return
Expand Down
1 change: 1 addition & 0 deletions hathor/stratum/stratum.py
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,7 @@ def create_job_tx(self, jobid: UUID) -> BaseTransaction:
data = data[:self._settings.BLOCK_DATA_MAX_SIZE]
block = self.manager.generate_mining_block(data=data, address=self.miner_address,
merge_mined=self.merged_mining)
block.init_static_metadata_from_storage(self._settings, self.manager.tx_storage)
self.log.debug('prepared block for mining', block=block)
return block

Expand Down
Loading