Example #1
0
    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
Example #6
0
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