def _compute_merkle_root(self, previous_block_hash): """Computes the merkle root of this block based on the sorted transactions. :param previous_block_hash: Hash of the previous block. :type previous_block_hash: str :return: Th merkle root hash. """ sorted_tx = sorted(self.transactions) all_hashes = ((previous_block_hash, ) + tuple(crypto.get_hash(tx.to_json()) for tx in sorted_tx)) return crypto.get_hash(''.join(all_hashes))
def __init__(self, sender_id, recipient_id, amount, tx_type=TYPE_TX, tx_time=None, tx_id=None): self.tx_id = tx_id or crypto.get_hash() self.type = tx_type self.sender_id = sender_id self.recipient_id = recipient_id self.amount = amount self.emission_time = tx_time or datetime.utcnow().timestamp()
def __init__(self, context, nodes_folder): """Creates a new Node. :param context: The running context that is required to interact with the node network. :type context: Context :param nodes_folder: Root folder for nodes of this type. :type nodes_folder: str """ super().__init__(crypto.get_hash()) self.node_folder = os.path.join(nodes_folder, self.id) self.context = context keys = crypto.generate_encryption_keys(self.id) self.private_key = keys.private_key context.register_node(self, keys.public_key) os.makedirs(self.node_folder)
def __init__(self, keystore_path, masternodes_folder, cashingnodes_folder, consumernodes_folder, block_time, fees_rate, retribute_rate): """Initialises a new Context. :param: keystore_path: Path to the folder on this machine to store the keys. It will be created if missing. :type keystore_path: str :param masternodes_folder: Folder path on this machine where created master nodes should save their data. :type masternodes_folder: str :param cashingnodes_folder: Folder path on this machine where created cashing nodes should save their data. :type cashingnodes_folder: str :param consumernodes_folder: Folder path on this machine where created consumer nodes should save their data. :type consumernodes_folder: str :param block_time: Seconds between each block creation. :type block_time: int :param fees_rate: Percentage of each transaction amount taken out as a fee. :type fees_rate: float :param retribute_rate: Percentage of each transaction fee that the master node closing a block can keep for itself. """ self._keystore = KeyStore(keystore_path) self.masternodes_folder = masternodes_folder self.cashingnodes_folder = cashingnodes_folder self.consumernodes_folder = consumernodes_folder self.fees_rate = fees_rate self.retribute_rate = retribute_rate self._pou_algo = ProofOfUsageAlgorithm(1 - retribute_rate) self._create_block_timer = lambda: threading.Timer( block_time, self._block_timer_tick ) self._block_timer = self._create_block_timer() self.next_block_seed = crypto.get_hash('0') self.started = False self.masternodes = {} self.consumernodes = {} self.cashingnodes = {}
def _generate_satoshis(self, transactions, salt): """From a set of transaction and a salt, generates Satoshis to be used to poll winning tickets that which should get cashback. :param transactions: The list of transactions to generate Satoshis. One Satoshi will be generated per transaction. :type transactions: list[Transaction] :param salt: A salt to ensure the same transaction never gives the same Satoshi. :type salt: str :return: The list of generated Satoshis, one per transaction. :rtype: list[str] """ # The seeds are based on senders ids and the provided salt. # Both should be stable and pretty unique seeds = (crypto.get_hash(salt + tx.content.sender_id) for tx in transactions) # Satoshis destination set is [0, total_amount] total_amount = sum(tx.content.amount for tx in transactions) return [self._satoshi(seed, total_amount) for seed in seeds]
def test_get_hash_for_payload_always_same(self): self.assertEqual(crypto.get_hash('12345'), crypto.get_hash('12345'))
def test_get_random_hash_not_twice_the_same(self): self.assertNotEqual(crypto.get_hash(), crypto.get_hash())