def init_blockchain(self, birthdate, my_key_pair, ref_key_pair): """Created a validated Blockchain and initialize some control attributes """ self.bc = UserBlockchain(my_key_pair["pub"]) birth_tx = self.bc.make_birth_tx(birthdate) random_sign(birth_tx, my_key_pair["pub"], my_key_pair["priv"]) self.bc._add_transaction(birth_tx) tx_guzis = self.bc.make_daily_guzis_tx(birthdate) random_sign(tx_guzis, my_key_pair["pub"], my_key_pair["priv"]) self.bc._add_transaction(tx_guzis) tx_guziboxes = self.bc.make_daily_guziboxes_tx(birthdate) random_sign(tx_guziboxes, my_key_pair["pub"], my_key_pair["priv"]) self.bc._add_transaction(tx_guziboxes) init_block = self.bc.fill_init_block(birthdate) random_sign(init_block, ref_key_pair["pub"], ref_key_pair["priv"]) self.bc.new_block() self.guzis = 1 self.current_date = birthdate self.guzis_made_today = True self.key_pair = my_key_pair
def test_base_case(self): bc = UserBlockchain(NEW_USER_PUB_KEY) bc.new_block() bc.last_block().total = 4**3 bc._add_transaction(random_sign(bc.make_daily_guzis_tx())) result = bc._get_available_guzis() expected = [ ("2011-12-13", 0), ("2011-12-13", 1), ("2011-12-13", 2), ("2011-12-13", 3), ("2011-12-13", 4), ] assert expected == result
def test_birth_only_ok(self): bc = UserBlockchain(NEW_USER_PUB_KEY) birth_tx = bc.make_birth_tx() random_sign(birth_tx, REF_PUB_KEY, REF_PRIV_KEY) bc._add_transaction(birth_tx) result = bc.is_valid() assert result is True
def test_birth_false_signature_ko(self): bc = UserBlockchain(NEW_USER_PUB_KEY) birth_tx = bc.make_birth_tx() # Fails because REF_PRIV_KEY should be NEW_USER_PRIV_KEY random_sign(birth_tx, NEW_USER_PUB_KEY, REF_PRIV_KEY) bc._add_transaction(birth_tx) result = bc.is_valid() assert result is False
def test_create_base_block(self): bc = UserBlockchain(NEW_USER_PUB_KEY) birth_tx = bc.make_birth_tx(date(1998, 12, 21).isoformat()) random_sign(birth_tx, NEW_USER_PUB_KEY, NEW_USER_PRIV_KEY) bc._add_transaction(birth_tx) init_block = bc.last_block() assert init_block.version == VERSION assert init_block.close_date is None assert init_block.previous_block_signature is None assert init_block.merkle_root is None assert init_block.signer is None assert len(init_block.transactions) == 1 assert len(init_block.engagements) == 0 assert init_block.is_signed() is False assert init_block.is_valid() is True
class UserBlockchainStateMachine(RuleBasedStateMachine): """This class runs tests to simulate random usages of Blockchain. It relies on hypothesis which allows to create rules. Each rule simulates one behavious of the Blockchain (creating guzis, making a payment, etc) At the end of the simulation, checks all methods having the @invariant() decorator """ bc = None @initialize( birthdate=st.dates(), my_key_pair=st.sampled_from(KEY_POOL), ref_key_pair=st.sampled_from(KEY_POOL), ) def init_blockchain(self, birthdate, my_key_pair, ref_key_pair): """Created a validated Blockchain and initialize some control attributes """ self.bc = UserBlockchain(my_key_pair["pub"]) birth_tx = self.bc.make_birth_tx(birthdate) random_sign(birth_tx, my_key_pair["pub"], my_key_pair["priv"]) self.bc._add_transaction(birth_tx) tx_guzis = self.bc.make_daily_guzis_tx(birthdate) random_sign(tx_guzis, my_key_pair["pub"], my_key_pair["priv"]) self.bc._add_transaction(tx_guzis) tx_guziboxes = self.bc.make_daily_guziboxes_tx(birthdate) random_sign(tx_guziboxes, my_key_pair["pub"], my_key_pair["priv"]) self.bc._add_transaction(tx_guziboxes) init_block = self.bc.fill_init_block(birthdate) random_sign(init_block, ref_key_pair["pub"], ref_key_pair["priv"]) self.bc.new_block() self.guzis = 1 self.current_date = birthdate self.guzis_made_today = True self.key_pair = my_key_pair @rule() def new_day(self): """ Simulate a date change, which has strong impact in Guzis""" self.current_date += timedelta(days=1) self.guzis_made_today = False @rule() def make_daily_guzis(self): """Simulates the creation of daily Guzis for the blockchain. Note that if it was already made today, it shouldn't create those again. """ try: tx = self.bc.make_daily_guzis_tx(self.current_date) random_sign(tx, self.key_pair["pub"], self.key_pair["priv"]) self.bc._add_transaction(tx) if not self.guzis_made_today: self.guzis += self.bc._get_guzis_amount() self.guzis_made_today = True except GuziError: pass @rule(target_user=st.sampled_from(KEY_POOL), amount=st.integers()) def pay_to(self, target_user, amount): """Simulates a payment to another user.""" try: note("paying amount {}".format(amount)) tx = self.bc.make_pay_tx(target_user, amount) random_sign(tx, self.key_pair["pub"], self.key_pair["priv"]) self.bc._add_transaction(tx) self.guzis -= amount except (InsufficientFundsError, NegativeAmountError): pass @precondition(lambda self: self.bc is not None) @invariant() def check_guzis(self): """Check that blockchain guzis amount is correct""" assert self.guzis >= 0 note(self.bc._get_available_guzis()) assert self.guzis == self.bc._get_available_guzis_amount()
def make_blockchain( start=date(2000, 1, 1), days=0, tx_per_block=1, total=0, end_with_empty_block=False, close_last_block=True, ): """Make a Blockchain with given informations :start: The starting date (and birthdate) of the blockchain :days: Number of days that occurs :tx_per_block: Number of transactions created per block. :total: Accumulated total of the blockchain after init :end_with_empty_block: Append an empty block to the end of the blockchain if set to True. :returns: Blockchain Note: This method makes always one day per block """ with freeze_time(start) as frozen_date: bc = UserBlockchain(NEW_USER_PUB_KEY) birth_tx = bc.make_birth_tx(frozen_date.time_to_freeze.date()) tx_guzis = bc.make_daily_guzis_tx(frozen_date.time_to_freeze.date()) tx_guziboxes = bc.make_daily_guziboxes_tx( frozen_date.time_to_freeze.date()) random_sign(birth_tx, NEW_USER_PUB_KEY, NEW_USER_PRIV_KEY) random_sign(tx_guzis, NEW_USER_PUB_KEY, NEW_USER_PRIV_KEY) random_sign(tx_guziboxes, NEW_USER_PUB_KEY, NEW_USER_PRIV_KEY) bc._add_transaction(birth_tx) bc._add_transaction(tx_guzis) bc._add_transaction(tx_guziboxes) init_block = bc.fill_init_block() random_sign(init_block) for i in range(days): frozen_date.tick(60 * 60 * 24) # +1 day bc.new_block() if tx_per_block > 0: tx = bc.make_daily_guzis_tx(frozen_date.time_to_freeze.date()) random_sign(tx, NEW_USER_PUB_KEY, NEW_USER_PRIV_KEY) bc._add_transaction(tx) for _ in range(1, tx_per_block): tx = bc.make_pay_tx(REF_PUB_KEY, bc._get_available_guzis_amount()) random_sign(tx, NEW_USER_PUB_KEY, NEW_USER_PRIV_KEY) bc._add_transaction(tx) if i < days - 1 or (i == days - 1 and close_last_block is True): bc.close_last_block() random_sign(bc.last_block()) if end_with_empty_block: bc.new_block() if total > 0: bc[0].total = total return bc
def test_create_GUZIBOX_CREATE_transaction(self): bc = UserBlockchain(NEW_USER_PUB_KEY) tx = bc.make_daily_guziboxes_tx() assert tx.tx_type == Transaction.GUZIBOX_CREATE
def test_return_evolving_total(self): # Arrange bc = UserBlockchain(NEW_USER_PUB_KEY) bc.new_block() bc.last_block().total = 4**3 bc._add_transaction(random_sign(bc.make_daily_guzis_tx())) bc.last_block().total = 5**3 bc._add_transaction(random_sign(bc.make_daily_guzis_tx())) bc.last_block().total = 6**3 bc._add_transaction(random_sign(bc.make_daily_guzis_tx())) # Act result = bc._get_available_guzis() expected = [ ("2011-12-13", 0), ("2011-12-13", 1), ("2011-12-13", 2), ("2011-12-13", 3), ("2011-12-13", 4), ("2011-12-14", 0), ("2011-12-14", 1), ("2011-12-14", 2), ("2011-12-14", 3), ("2011-12-14", 4), ("2011-12-14", 5), ("2011-12-15", 0), ("2011-12-15", 1), ("2011-12-15", 2), ("2011-12-15", 3), ("2011-12-15", 4), ("2011-12-15", 5), ("2011-12-15", 6), ] # Assert assert expected == result