diff --git a/hathor/consensus/block_consensus.py b/hathor/consensus/block_consensus.py index 18a6da20d..a6c5267cc 100644 --- a/hathor/consensus/block_consensus.py +++ b/hathor/consensus/block_consensus.py @@ -19,7 +19,7 @@ from hathor.conf.get_settings import get_settings from hathor.profiler import get_cpu_profiler -from hathor.transaction import BaseTransaction, Block, Transaction, sum_weights +from hathor.transaction import BaseTransaction, Block, Transaction from hathor.util import classproperty, not_none if TYPE_CHECKING: @@ -120,7 +120,7 @@ def update_voided_info(self, block: Block) -> None: for h in voided_by: tx = storage.get_transaction(h) tx_meta = tx.get_metadata() - tx_meta.accumulated_weight = sum_weights(tx_meta.accumulated_weight, block.weight) + tx_meta.accumulated_weight += int(2**block.weight) self.context.save(tx) # Check conflicts of the transactions voiding us. @@ -159,10 +159,10 @@ def update_voided_info(self, block: Block) -> None: is_connected_to_the_best_chain=is_connected_to_the_best_chain) # First, void this block. + # We need to void this block first, because otherwise it would always be one of the heads. self.mark_as_voided(block, skip_remove_first_block_markers=True) # Get the score of the best chains. - # We need to void this block first, because otherwise it would always be one of the heads. heads = [cast(Block, storage.get_transaction(h)) for h in storage.get_best_block_tips()] best_score = None for head in heads: @@ -171,15 +171,16 @@ def update_voided_info(self, block: Block) -> None: best_score = head_meta.score else: # All heads must have the same score. - assert abs(best_score - head_meta.score) < 1e-10 - assert isinstance(best_score, (int, float)) + assert best_score == head_meta.score + assert isinstance(best_score, int) + assert best_score > 0 # Calculate the score. # We cannot calculate score before getting the heads. score = self.calculate_score(block) # Finally, check who the winner is. - if score <= best_score - self._settings.WEIGHT_TOL: + if score < best_score: # Just update voided_by from parents. self.update_voided_by_from_parents(block) @@ -200,7 +201,7 @@ def update_voided_info(self, block: Block) -> None: common_block = self._find_first_parent_in_best_chain(block) self.add_voided_by_to_multiple_chains(block, heads, common_block) - if score >= best_score + self._settings.WEIGHT_TOL: + if score > best_score: # We have a new winner candidate. self.update_score_and_mark_as_the_best_chain_if_possible(block) # As `update_score_and_mark_as_the_best_chain_if_possible` may affect `voided_by`, @@ -287,28 +288,30 @@ def update_score_and_mark_as_the_best_chain_if_possible(self, block: Block) -> N self.update_score_and_mark_as_the_best_chain(block) self.remove_voided_by_from_chain(block) + best_score: int if self.update_voided_by_from_parents(block): storage = block.storage heads = [cast(Block, storage.get_transaction(h)) for h in storage.get_best_block_tips()] - best_score = 0.0 + best_score = 0 best_heads: list[Block] for head in heads: head_meta = head.get_metadata(force_reload=True) - if head_meta.score <= best_score - self._settings.WEIGHT_TOL: + if head_meta.score < best_score: continue - if head_meta.score >= best_score + self._settings.WEIGHT_TOL: + if head_meta.score > best_score: best_heads = [head] best_score = head_meta.score else: - assert abs(best_score - head_meta.score) < 1e-10 + assert best_score == head_meta.score best_heads.append(head) - assert isinstance(best_score, (int, float)) and best_score > 0 + assert isinstance(best_score, int) and best_score > 0 assert len(best_heads) > 0 first_block = self._find_first_parent_in_best_chain(best_heads[0]) self.add_voided_by_to_multiple_chains(best_heads[0], [block], first_block) if len(best_heads) == 1: + assert best_heads[0].hash != block.hash self.update_score_and_mark_as_the_best_chain_if_possible(best_heads[0]) def update_score_and_mark_as_the_best_chain(self, block: Block) -> None: @@ -448,7 +451,7 @@ def remove_first_block_markers(self, block: Block) -> None: self.context.save(tx) def _score_block_dfs(self, block: BaseTransaction, used: set[bytes], - mark_as_best_chain: bool, newest_timestamp: int) -> float: + mark_as_best_chain: bool, newest_timestamp: int) -> int: """ Internal method to run a DFS. It is used by `calculate_score()`. """ assert block.storage is not None @@ -458,7 +461,7 @@ def _score_block_dfs(self, block: BaseTransaction, used: set[bytes], storage = block.storage from hathor.transaction import Block - score = block.weight + score = int(2**block.weight) for parent in block.get_parents(): if parent.is_block: assert isinstance(parent, Block) @@ -467,7 +470,7 @@ def _score_block_dfs(self, block: BaseTransaction, used: set[bytes], x = meta.score else: x = self._score_block_dfs(parent, used, mark_as_best_chain, newest_timestamp) - score = sum_weights(score, x) + score += x else: from hathor.transaction.storage.traversal import BFSTimestampWalk @@ -493,7 +496,7 @@ def _score_block_dfs(self, block: BaseTransaction, used: set[bytes], meta.first_block = block.hash self.context.save(tx) - score = sum_weights(score, tx.weight) + score += int(2**tx.weight) # Always save the score when it is calculated. meta = block.get_metadata() @@ -505,12 +508,12 @@ def _score_block_dfs(self, block: BaseTransaction, used: set[bytes], # Thus, if we have already calculated it, we just check the consistency of the calculation. # Unfortunately we may have to calculate it more than once when a new block arrives in a side # side because the `first_block` points only to the best chain. - assert abs(meta.score - score) < 1e-10, \ + assert meta.score == score, \ 'hash={} meta.score={} score={}'.format(block.hash.hex(), meta.score, score) return score - def calculate_score(self, block: Block, *, mark_as_best_chain: bool = False) -> float: + def calculate_score(self, block: Block, *, mark_as_best_chain: bool = False) -> int: """ Calculate block's score, which is the accumulated work of the verified transactions and blocks. :param: mark_as_best_chain: If `True`, the transactions' will point `meta.first_block` to @@ -520,9 +523,9 @@ def calculate_score(self, block: Block, *, mark_as_best_chain: bool = False) -> if block.is_genesis: if mark_as_best_chain: meta = block.get_metadata() - meta.score = block.weight + meta.score = int(2**block.weight) self.context.save(block) - return block.weight + return int(2**block.weight) parent = self._find_first_parent_in_best_chain(block) newest_timestamp = parent.timestamp diff --git a/hathor/consensus/transaction_consensus.py b/hathor/consensus/transaction_consensus.py index 0747c1753..d39f175cd 100644 --- a/hathor/consensus/transaction_consensus.py +++ b/hathor/consensus/transaction_consensus.py @@ -18,7 +18,7 @@ from hathor.conf.get_settings import get_settings from hathor.profiler import get_cpu_profiler -from hathor.transaction import BaseTransaction, Block, Transaction, TxInput, sum_weights +from hathor.transaction import BaseTransaction, Block, Transaction, TxInput from hathor.util import classproperty if TYPE_CHECKING: @@ -199,13 +199,13 @@ def update_voided_info(self, tx: Transaction) -> None: continue tx2 = tx.storage.get_transaction(h) tx2_meta = tx2.get_metadata() - tx2_meta.accumulated_weight = sum_weights(tx2_meta.accumulated_weight, tx.weight) + tx2_meta.accumulated_weight += int(2**tx.weight) self.context.save(tx2) # Then, we add ourselves. meta = tx.get_metadata() assert not meta.voided_by or meta.voided_by == {tx.hash} - assert meta.accumulated_weight == tx.weight + assert meta.accumulated_weight == int(2**tx.weight) if tx.hash in self.context.consensus.soft_voided_tx_ids: voided_by.add(self._settings.SOFT_VOIDED_ID) voided_by.add(tx.hash) @@ -300,7 +300,7 @@ def check_conflicts(self, tx: Transaction) -> None: candidate.update_accumulated_weight(stop_value=meta.accumulated_weight) tx_meta = candidate.get_metadata() d = tx_meta.accumulated_weight - meta.accumulated_weight - if abs(d) < self._settings.WEIGHT_TOL: + if d == 0: tie_list.append(candidate) elif d > 0: is_highest = False diff --git a/hathor/event/model/event_data.py b/hathor/event/model/event_data.py index f3003d0cd..def601a6a 100644 --- a/hathor/event/model/event_data.py +++ b/hathor/event/model/event_data.py @@ -52,8 +52,8 @@ class TxMetadata(BaseModel, extra=Extra.ignore): received_by: list[int] children: list[str] twins: list[str] - accumulated_weight: float - score: float + accumulated_weight: int + score: int first_block: Optional[str] height: int validation: str diff --git a/hathor/manager.py b/hathor/manager.py index eae92da9e..4e6d76f44 100644 --- a/hathor/manager.py +++ b/hathor/manager.py @@ -51,13 +51,13 @@ from hathor.profiler import get_cpu_profiler from hathor.pubsub import HathorEvents, PubSubManager from hathor.stratum import StratumFactory -from hathor.transaction import BaseTransaction, Block, MergeMinedBlock, Transaction, TxVersion, sum_weights +from hathor.transaction import BaseTransaction, Block, MergeMinedBlock, Transaction, TxVersion from hathor.transaction.exceptions import TxValidationError from hathor.transaction.storage import TransactionStorage from hathor.transaction.storage.exceptions import TransactionDoesNotExist from hathor.transaction.storage.tx_allow_scope import TxAllowScope from hathor.types import Address, VertexId -from hathor.util import EnvironmentInfo, LogDuration, Random, Reactor, calculate_min_significant_weight, not_none +from hathor.util import EnvironmentInfo, LogDuration, Random, Reactor, not_none from hathor.verification.verification_service import VerificationService from hathor.wallet import BaseWallet @@ -794,14 +794,7 @@ def _make_block_template(self, parent_block: Block, parent_txs: 'ParentTxs', cur ) timestamp = min(max(current_timestamp, timestamp_min), timestamp_max) parent_block_metadata = parent_block.get_metadata() - # this is the min weight to cause an increase of twice the WEIGHT_TOL, we make sure to generate a template with - # at least this weight (note that the user of the API can set its own weight, the block sumit API will also - # protect agains a weight that is too small but using WEIGHT_TOL instead of 2*WEIGHT_TOL) - min_significant_weight = calculate_min_significant_weight( - parent_block_metadata.score, - 2 * self._settings.WEIGHT_TOL - ) - weight = max(self.daa.calculate_next_weight(parent_block, timestamp), min_significant_weight) + weight = self.daa.calculate_next_weight(parent_block, timestamp) height = parent_block.get_height() + 1 parents = [parent_block.hash] + parent_txs.must_include parents_any = parent_txs.can_include @@ -813,6 +806,7 @@ def _make_block_template(self, parent_block: Block, parent_txs: 'ParentTxs', cur assert 1 <= len(parents) <= 3, 'Impossible number of parents' if __debug__ and len(parents) == 3: assert len(parents_any) == 0, 'Extra parents to choose from that cannot be chosen' + score = parent_block_metadata.score + int(2**weight) return BlockTemplate( versions={TxVersion.REGULAR_BLOCK.value, TxVersion.MERGE_MINED_BLOCK.value}, reward=self.daa.get_tokens_issued_per_block(height), @@ -823,7 +817,7 @@ def _make_block_template(self, parent_block: Block, parent_txs: 'ParentTxs', cur parents=parents, parents_any=parents_any, height=height, - score=sum_weights(parent_block_metadata.score, weight), + score=score, signal_bits=self._bit_signaling_service.generate_signal_bits(block=parent_block) ) @@ -862,15 +856,7 @@ def submit_block(self, blk: Block, fails_silently: bool = True) -> bool: if parent_hash not in tips: self.log.warn('submit_block(): Ignoring block: parent not a tip', blk=blk.hash_hex) return False - parent_block = self.tx_storage.get_transaction(parent_hash) - parent_block_metadata = parent_block.get_metadata() # this is the smallest weight that won't cause the score to increase, anything equal or smaller is bad - min_insignificant_weight = calculate_min_significant_weight( - parent_block_metadata.score, - self._settings.WEIGHT_TOL - ) - if blk.weight <= min_insignificant_weight: - self.log.warn('submit_block(): insignificant weight? accepted anyway', blk=blk.hash_hex, weight=blk.weight) return self.propagate_tx(blk, fails_silently=fails_silently) def push_tx(self, tx: Transaction, allow_non_standard_script: bool = False, diff --git a/hathor/mining/block_template.py b/hathor/mining/block_template.py index 54e690d95..fc48aba5a 100644 --- a/hathor/mining/block_template.py +++ b/hathor/mining/block_template.py @@ -33,7 +33,7 @@ class BlockTemplate(NamedTuple): parents: list[bytes] # required parents, will always have a block and at most 2 txs parents_any: list[bytes] # list of extra parents to choose from when there are more options height: int # metadata - score: float # metadata + score: int # metadata signal_bits: int # signal bits for blocks generated from this template def generate_minimally_valid_block(self) -> BaseTransaction: diff --git a/hathor/transaction/base_transaction.py b/hathor/transaction/base_transaction.py index 5e606b460..c9c3c2acc 100644 --- a/hathor/transaction/base_transaction.py +++ b/hathor/transaction/base_transaction.py @@ -614,11 +614,12 @@ def get_metadata(self, *, force_reload: bool = False, use_storage: bool = True) # which requires the use of a storage, this is a workaround that should be fixed, places where this # happens include generating new mining blocks and some tests height = self.calculate_height() if self.storage else None - score = self.weight if self.is_genesis else 0 + score = int(2**self.weight) if self.is_genesis else 1 + accumulated_weight = int(2**self.weight) metadata = TransactionMetadata( hash=self.hash, - accumulated_weight=self.weight, + accumulated_weight=accumulated_weight, height=height, score=score, min_height=0, @@ -635,10 +636,11 @@ def reset_metadata(self) -> None: """ from hathor.transaction.transaction_metadata import ValidationState assert self.storage is not None - score = self.weight if self.is_genesis else 0 + score = int(2**self.weight) if self.is_genesis else 0 + accumulated_weight = int(2**self.weight) self._metadata = TransactionMetadata(hash=self.hash, score=score, - accumulated_weight=self.weight) + accumulated_weight=accumulated_weight) if self.is_genesis: self._metadata.validation = ValidationState.CHECKPOINT_FULL self._metadata.voided_by = set() @@ -672,7 +674,7 @@ def update_accumulated_weight(self, *, stop_value: float = inf, save_file: bool if metadata.accumulated_weight > stop_value: return metadata - accumulated_weight = self.weight + accumulated_weight = int(2**self.weight) # TODO Another optimization is that, when we calculate the acc weight of a transaction, we # also partially calculate the acc weight of its descendants. If it were a DFS, when returning @@ -687,7 +689,7 @@ def update_accumulated_weight(self, *, stop_value: float = inf, save_file: bool from hathor.transaction.storage.traversal import BFSTimestampWalk bfs_walk = BFSTimestampWalk(self.storage, is_dag_funds=True, is_dag_verifications=True, is_left_to_right=True) for tx in bfs_walk.run(self, skip_root=True): - accumulated_weight = sum_weights(accumulated_weight, tx.weight) + accumulated_weight += int(2**tx.weight) if accumulated_weight > stop_value: break diff --git a/hathor/transaction/resources/decode_tx.py b/hathor/transaction/resources/decode_tx.py index 64274040c..a46b25e5b 100644 --- a/hathor/transaction/resources/decode_tx.py +++ b/hathor/transaction/resources/decode_tx.py @@ -147,8 +147,8 @@ def render_GET(self, request): 'conflict_with': [], 'voided_by': [], 'twins': [], - 'accumulated_weight': 10, - 'score': 12, + 'accumulated_weight': 1024, + 'score': 4096, 'first_block': None }, 'spent_outputs': { diff --git a/hathor/transaction/resources/transaction.py b/hathor/transaction/resources/transaction.py index 1646e06e5..3150e1ba0 100644 --- a/hathor/transaction/resources/transaction.py +++ b/hathor/transaction/resources/transaction.py @@ -405,8 +405,8 @@ def get_list_tx(self, request): 'conflict_with': [], 'voided_by': [], 'twins': [], - 'accumulated_weight': 10, - 'score': 12, + 'accumulated_weight': 1024, + 'score': 4096, 'first_block': None }, 'spent_outputs': { diff --git a/hathor/transaction/resources/transaction_confirmation.py b/hathor/transaction/resources/transaction_confirmation.py index d60526491..153d2b8f8 100644 --- a/hathor/transaction/resources/transaction_confirmation.py +++ b/hathor/transaction/resources/transaction_confirmation.py @@ -125,7 +125,7 @@ def render_GET(self, request): 'success': { 'summary': 'Success', 'value': { - 'accumulated_weight': 15.4, + 'accumulated_weight': 43237, 'confirmation_level': 0.88, 'stop_value': 14.5, 'accumulated_bigger': True, diff --git a/hathor/transaction/storage/migrations/change_score_acc_weight_metadata.py b/hathor/transaction/storage/migrations/change_score_acc_weight_metadata.py new file mode 100644 index 000000000..4c1128a14 --- /dev/null +++ b/hathor/transaction/storage/migrations/change_score_acc_weight_metadata.py @@ -0,0 +1,31 @@ +# Copyright 2021 Hathor Labs +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from typing import TYPE_CHECKING + +from hathor.transaction.storage.migrations import BaseMigration + +if TYPE_CHECKING: + from hathor.transaction.storage import TransactionStorage + + +class Migration(BaseMigration): + def skip_empty_db(self) -> bool: + return True + + def get_db_name(self) -> str: + return 'change_score_acc_weight_metadata' + + def run(self, storage: 'TransactionStorage') -> None: + raise Exception('Cannot migrate your database. Please, delete your data folder and sync again.') diff --git a/hathor/transaction/storage/transaction_storage.py b/hathor/transaction/storage/transaction_storage.py index 3a9df6be7..67cf01b0f 100644 --- a/hathor/transaction/storage/transaction_storage.py +++ b/hathor/transaction/storage/transaction_storage.py @@ -40,6 +40,7 @@ MigrationState, add_feature_activation_bit_counts_metadata, add_min_height_metadata, + change_score_acc_weight_metadata, ) from hathor.transaction.storage.tx_allow_scope import TxAllowScope, tx_allow_context from hathor.transaction.transaction import Transaction @@ -87,6 +88,7 @@ class TransactionStorage(ABC): _migration_factories: list[type[BaseMigration]] = [ add_min_height_metadata.Migration, add_feature_activation_bit_counts_metadata.Migration, + change_score_acc_weight_metadata.Migration, ] _migrations: list[BaseMigration] @@ -644,7 +646,7 @@ def get_best_block_tips(self, timestamp: Optional[float] = None, *, skip_cache: if timestamp is None and not skip_cache and self._best_block_tips_cache is not None: return self._best_block_tips_cache[:] - best_score = 0.0 + best_score: int = 0 best_tip_blocks: list[bytes] = [] for block_hash in (x.data for x in self.get_block_tips(timestamp)): @@ -653,7 +655,7 @@ def get_best_block_tips(self, timestamp: Optional[float] = None, *, skip_cache: if meta.voided_by and meta.voided_by != set([block_hash]): # If anyone but the block itself is voiding this block, then it must be skipped. continue - if abs(meta.score - best_score) < 1e-10: + if meta.score == best_score: best_tip_blocks.append(block_hash) elif meta.score > best_score: best_score = meta.score diff --git a/hathor/transaction/transaction_metadata.py b/hathor/transaction/transaction_metadata.py index c223d928f..e691ece20 100644 --- a/hathor/transaction/transaction_metadata.py +++ b/hathor/transaction/transaction_metadata.py @@ -37,8 +37,8 @@ class TransactionMetadata: received_by: list[int] children: list[bytes] twins: list[bytes] - accumulated_weight: float - score: float + accumulated_weight: int + score: int first_block: Optional[bytes] height: Optional[int] validation: ValidationState @@ -67,8 +67,8 @@ def __init__( self, spent_outputs: Optional[dict[int, list[bytes]]] = None, hash: Optional[bytes] = None, - accumulated_weight: float = 0, - score: float = 0, + accumulated_weight: int = 0, + score: int = 0, height: Optional[int] = None, min_height: Optional[int] = None, feature_activation_bit_counts: Optional[list[int]] = None diff --git a/hathor/util.py b/hathor/util.py index 3e1b910db..48828e2c3 100644 --- a/hathor/util.py +++ b/hathor/util.py @@ -807,9 +807,3 @@ def get_environment_info(args: str, peer_id: Optional[str]) -> EnvironmentInfo: def get_hathor_core_version(): return hathor.__version__ - - -def calculate_min_significant_weight(score: float, tol: float) -> float: - """ This function will return the min significant weight to increase score by tol. - """ - return score + math.log2(2 ** tol - 1) diff --git a/hathor/wallet/resources/send_tokens.py b/hathor/wallet/resources/send_tokens.py index 16bd97355..a055431e3 100644 --- a/hathor/wallet/resources/send_tokens.py +++ b/hathor/wallet/resources/send_tokens.py @@ -304,7 +304,7 @@ def render_OPTIONS(self, request): 'inputs': [], 'outputs': [], 'tokens': [], - 'accumulated_weight': 14 + 'accumulated_weight': 16384 } } } diff --git a/hathor/wallet/resources/thin_wallet/send_tokens.py b/hathor/wallet/resources/thin_wallet/send_tokens.py index 65136c1b6..919328e0a 100644 --- a/hathor/wallet/resources/thin_wallet/send_tokens.py +++ b/hathor/wallet/resources/thin_wallet/send_tokens.py @@ -461,7 +461,7 @@ def render_OPTIONS(self, request): 'inputs': [], 'outputs': [], 'tokens': [], - 'accumulated_weight': 14 + 'accumulated_weight': 16384 } } }, diff --git a/tests/event/websocket/test_protocol.py b/tests/event/websocket/test_protocol.py index 2f3a4dcfe..0da284c45 100644 --- a/tests/event/websocket/test_protocol.py +++ b/tests/event/websocket/test_protocol.py @@ -102,7 +102,7 @@ def test_send_event_response(): b'"timestamp":456,"version":1,"weight":10.0,"inputs":[],"outputs":[],"parents":[],' b'"tokens":[],"token_name":null,"token_symbol":null,"metadata":{"hash":"abc",' b'"spent_outputs":[],"conflict_with":[],"voided_by":[],"received_by":[],"children":[],' - b'"twins":[],"accumulated_weight":10.0,"score":20.0,"first_block":null,"height":100,' + b'"twins":[],"accumulated_weight":1024,"score":1048576,"first_block":null,"height":100,' b'"validation":"validation"},"aux_pow":null},"group_id":null},"latest_event_id":10,' b'"stream_id":"stream_id"}') diff --git a/tests/resources/transaction/test_mining.py b/tests/resources/transaction/test_mining.py index af97d8682..555f5b343 100644 --- a/tests/resources/transaction/test_mining.py +++ b/tests/resources/transaction/test_mining.py @@ -35,7 +35,7 @@ def test_get_block_template_with_address(self): 'voided_by': [], 'twins': [], 'validation': 'initial', - 'accumulated_weight': 1.0, + 'accumulated_weight': 2, 'score': 0, 'height': 1, 'min_height': 0, @@ -68,7 +68,7 @@ def test_get_block_template_without_address(self): 'voided_by': [], 'twins': [], 'validation': 'initial', # FIXME: change to 'full' when validations are enabled - 'accumulated_weight': 1.0, + 'accumulated_weight': 2, 'score': 0, 'height': 1, 'min_height': 0, diff --git a/tests/resources/transaction/test_transaction_confirmation.py b/tests/resources/transaction/test_transaction_confirmation.py index a04eeb641..efba94f9f 100644 --- a/tests/resources/transaction/test_transaction_confirmation.py +++ b/tests/resources/transaction/test_transaction_confirmation.py @@ -24,7 +24,7 @@ def test_get_data(self): ) data_success = response_success.json_value() self.assertTrue(data_success['success']) - self.assertEqual(data_success['accumulated_weight'], genesis_tx.weight) + self.assertEqual(data_success['accumulated_weight'], int(2**genesis_tx.weight)) self.assertEqual(data_success['confirmation_level'], 0) # Adding blocks to have funds @@ -38,7 +38,7 @@ def test_get_data(self): {b'id': bytes(tx.hash.hex(), 'utf-8')} ) data_success2 = response_success2.json_value() - self.assertGreater(data_success2['accumulated_weight'], tx.weight) + self.assertGreater(data_success2['accumulated_weight'], int(2**tx.weight)) self.assertEqual(data_success2['confirmation_level'], 1) # Test sending hash that does not exist diff --git a/tests/tx/test_accumulated_weight.py b/tests/tx/test_accumulated_weight.py index 8f19e00ff..d48bdef2c 100644 --- a/tests/tx/test_accumulated_weight.py +++ b/tests/tx/test_accumulated_weight.py @@ -1,5 +1,4 @@ from hathor.simulator.utils import add_new_blocks -from hathor.transaction import sum_weights from hathor.transaction.storage import TransactionMemoryStorage from tests import unittest from tests.utils import add_blocks_unlock_reward, add_new_transactions @@ -39,9 +38,9 @@ def test_accumulated_weight_indirect_block(self): # indirectly. expected = 0 for tx in tx_list: - expected = sum_weights(expected, tx.weight) + expected += int(2**tx.weight) for block in blocks: - expected = sum_weights(expected, block.weight) + expected += int(2**block.weight) meta = tx0.update_accumulated_weight() self.assertAlmostEqual(meta.accumulated_weight, expected) diff --git a/tests/tx/test_blockchain.py b/tests/tx/test_blockchain.py index 02ec4cd07..baf29c701 100644 --- a/tests/tx/test_blockchain.py +++ b/tests/tx/test_blockchain.py @@ -3,7 +3,6 @@ from hathor.conf import HathorSettings from hathor.daa import DifficultyAdjustmentAlgorithm, TestMode from hathor.simulator.utils import add_new_blocks -from hathor.transaction import sum_weights from hathor.transaction.storage import TransactionMemoryStorage from tests import unittest from tests.utils import add_new_transactions @@ -40,27 +39,27 @@ def test_single_chain(self): manager = self.create_peer('testnet', tx_storage=self.tx_storage) # The initial score is the sum of the genesis - score = self.genesis_blocks[0].weight + score = int(2**self.genesis_blocks[0].weight) for tx in self.genesis_txs: - score = sum_weights(score, tx.weight) + score += int(2**tx.weight) # Mine 100 blocks in a row with no transaction but the genesis blocks = add_new_blocks(manager, 100, advance_clock=15) for i, block in enumerate(blocks): meta = block.get_metadata(force_reload=True) - score = sum_weights(score, block.weight) + score += int(2**block.weight) self.assertAlmostEqual(score, meta.score) # Add some transactions between blocks txs = add_new_transactions(manager, 30, advance_clock=15) for tx in txs: - score = sum_weights(score, tx.weight) + score += int(2**tx.weight) # Mine 50 more blocks in a row with no transactions between them blocks = add_new_blocks(manager, 50) for i, block in enumerate(blocks): meta = block.get_metadata() - score = sum_weights(score, block.weight) + score += int(2**block.weight) self.assertAlmostEqual(score, meta.score) consensus_context = manager.consensus_algorithm.create_context() self.assertAlmostEqual(consensus_context.block_algorithm.calculate_score(block), meta.score) @@ -69,12 +68,12 @@ def test_single_chain(self): for _ in range(15): txs = add_new_transactions(manager, 10, advance_clock=15) for tx in txs: - score = sum_weights(score, tx.weight) + score += int(2**tx.weight) blocks = add_new_blocks(manager, 1) for i, block in enumerate(blocks): meta = block.get_metadata() - score = sum_weights(score, block.weight) + score += int(2**block.weight) self.assertAlmostEqual(score, meta.score) consensus_context = manager.consensus_algorithm.create_context() self.assertAlmostEqual(consensus_context.block_algorithm.calculate_score(block), meta.score) @@ -89,27 +88,27 @@ def test_single_fork_not_best(self): manager = self.create_peer('testnet', tx_storage=self.tx_storage) # The initial score is the sum of the genesis - score = self.genesis_blocks[0].weight + score = int(2**self.genesis_blocks[0].weight) for tx in self.genesis_txs: - score = sum_weights(score, tx.weight) + score += int(2**tx.weight) # Mine 30 blocks in a row with no transactions blocks = add_new_blocks(manager, 30, advance_clock=15) for i, block in enumerate(blocks): meta = block.get_metadata() - score = sum_weights(score, block.weight) + score += int(2**block.weight) self.assertAlmostEqual(score, meta.score) # Add some transactions between blocks txs = add_new_transactions(manager, 5, advance_clock=15) for tx in txs: - score = sum_weights(score, tx.weight) + score += int(2**tx.weight) # Mine 1 blocks blocks = add_new_blocks(manager, 1, advance_clock=15) for i, block in enumerate(blocks): meta = block.get_metadata() - score = sum_weights(score, block.weight) + score += int(2**block.weight) self.assertAlmostEqual(score, meta.score) # Generate a block which will be a fork in the middle of the chain @@ -123,7 +122,7 @@ def test_single_fork_not_best(self): blocks = add_new_blocks(manager, 8, advance_clock=15) for i, block in enumerate(blocks): meta = block.get_metadata() - score = sum_weights(score, block.weight) + score += int(2**block.weight) self.assertAlmostEqual(score, meta.score) # Fork block must have the same parents as blocks[0] as well as the same score @@ -138,20 +137,20 @@ def test_single_fork_not_best(self): # Add some transactions between blocks txs = add_new_transactions(manager, 5, advance_clock=15) for tx in txs: - score = sum_weights(score, tx.weight) + score += int(2**tx.weight) # Mine 5 blocks in a row # These blocks belong to case (i). blocks = add_new_blocks(manager, 5, advance_clock=15) for i, block in enumerate(blocks): meta = block.get_metadata() - score = sum_weights(score, block.weight) + score += int(2**block.weight) self.assertAlmostEqual(score, meta.score) # Add some transactions between blocks txs = add_new_transactions(manager, 2, advance_clock=15) for tx in txs: - score = sum_weights(score, tx.weight) + score += int(2**tx.weight) # Propagate a block connected to the voided chain # These blocks belongs to case (iii). @@ -163,7 +162,7 @@ def test_single_fork_not_best(self): # Add some transactions between blocks txs = add_new_transactions(manager, 2, advance_clock=15) for tx in txs: - score = sum_weights(score, tx.weight) + score += int(2**tx.weight) # Propagate a block connected to the voided chain # This block belongs to case (iv). @@ -181,28 +180,28 @@ def test_multiple_forks(self): manager = self.create_peer('testnet', tx_storage=self.tx_storage) # The initial score is the sum of the genesis - score = self.genesis_blocks[0].weight + score = int(2**self.genesis_blocks[0].weight) for tx in self.genesis_txs: - score = sum_weights(score, tx.weight) + score += int(2**tx.weight) # Mine 30 blocks in a row with no transactions, case (i). blocks = add_new_blocks(manager, 30, advance_clock=15) for i, block in enumerate(blocks): meta = block.get_metadata() - score = sum_weights(score, block.weight) + score += int(2**block.weight) self.assertAlmostEqual(score, meta.score) # Add some transactions between blocks txs1 = add_new_transactions(manager, 5, advance_clock=15) for tx in txs1: - score = sum_weights(score, tx.weight) + score += int(2**tx.weight) # Mine 1 blocks, case (i). blocks = add_new_blocks(manager, 1, advance_clock=15) block_before_fork = blocks[0] for i, block in enumerate(blocks): meta = block.get_metadata() - score = sum_weights(score, block.weight) + score += int(2**block.weight) self.assertAlmostEqual(score, meta.score) for tx in txs1: @@ -212,13 +211,13 @@ def test_multiple_forks(self): # Add some transactions between blocks txs2 = add_new_transactions(manager, 3, advance_clock=15) for tx in txs2: - score = sum_weights(score, tx.weight) + score += int(2**tx.weight) # Mine 5 blocks in a row, case (i). blocks = add_new_blocks(manager, 5, advance_clock=15) for i, block in enumerate(blocks): meta = block.get_metadata() - score = sum_weights(score, block.weight) + score += int(2**block.weight) self.assertAlmostEqual(score, meta.score) # Mine 4 blocks, starting a fork. diff --git a/tests/tx/test_indexes.py b/tests/tx/test_indexes.py index b26652a9a..97880e07e 100644 --- a/tests/tx/test_indexes.py +++ b/tests/tx/test_indexes.py @@ -266,7 +266,7 @@ def check_utxos(*args): address=decode_address(address)) block2.parents[1:] = [txA2.hash, txB2.hash] block2.timestamp = block1.timestamp - block2.weight = 1.2 + block2.weight = 4 self.manager.cpu_mining_service.resolve(block2) self.manager.verification_service.validate_full(block2) self.manager.propagate_tx(block2, fails_silently=False) diff --git a/tests/tx/test_mining.py b/tests/tx/test_mining.py index 3c55bc527..0515d2fc2 100644 --- a/tests/tx/test_mining.py +++ b/tests/tx/test_mining.py @@ -3,7 +3,7 @@ from hathor.conf import HathorSettings from hathor.mining import BlockTemplate from hathor.simulator.utils import add_new_blocks -from hathor.transaction import Block, sum_weights +from hathor.transaction import Block from hathor.transaction.storage import TransactionMemoryStorage from tests import unittest @@ -46,7 +46,7 @@ def test_block_template_after_genesis(self) -> None: self.assertEqual(block_templates[0], BlockTemplate( versions={0, 3}, reward=settings.INITIAL_TOKEN_UNITS_PER_BLOCK * 100, - weight=1.0, + weight=1, timestamp_now=int(manager.reactor.seconds()), timestamp_min=settings.GENESIS_BLOCK_TIMESTAMP + 3, timestamp_max=timestamp_max, # no limit for next block after genesis @@ -54,7 +54,7 @@ def test_block_template_after_genesis(self) -> None: parents=block_templates[0].parents, parents_any=[], height=1, # genesis is 0 - score=sum_weights(self.genesis_blocks[0].weight, 1.0), + score=int(2**self.genesis_blocks[0].weight) + int(2**1), signal_bits=0 )) @@ -75,7 +75,7 @@ def test_regular_block_template(self) -> None: self.assertEqual(block_templates[0], BlockTemplate( versions={0, 3}, reward=settings.INITIAL_TOKEN_UNITS_PER_BLOCK * 100, - weight=1.0, + weight=1, timestamp_now=int(manager.reactor.seconds()), timestamp_min=blocks[-1].timestamp + 1, timestamp_max=timestamp_max, @@ -83,7 +83,7 @@ def test_regular_block_template(self) -> None: parents=block_templates[0].parents, parents_any=[], height=101, # genesis is 0 - score=sum_weights(blocks[-1].get_metadata().score, 1.0), + score=blocks[-1].get_metadata().score + int(2**1), signal_bits=0 )) diff --git a/tests/tx/test_tx_storage.py b/tests/tx/test_tx_storage.py index 7d25f97bd..79a41bac3 100644 --- a/tests/tx/test_tx_storage.py +++ b/tests/tx/test_tx_storage.py @@ -487,6 +487,10 @@ def test_storage_new_blocks(self): # Block3 has the same parents as block2. block3 = self._add_new_block(parents=block2.parents) + self.assertEqual(block3.weight, block2.weight) + meta2 = block2.get_metadata() + meta3 = block3.get_metadata() + self.assertEqual(meta2.score, meta3.score) tip_blocks = [x.data for x in self.tx_storage.get_block_tips()] self.assertEqual(set(tip_blocks), {block2.hash, block3.hash}) diff --git a/tests/utils.py b/tests/utils.py index cdcbd7bb2..e267cc83c 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -553,8 +553,8 @@ class EventMocker: received_by=[], children=[], twins=[], - accumulated_weight=10, - score=20, + accumulated_weight=1024, + score=1048576, height=100, validation='validation' )