Пример #1
0
 def test_risky_spend(self):
     self.chain_id = self.minter
     spend_value = Decimal(10.00, self.con)
     spend_dot = Dot((1, "11111"))
     self.state.apply_spend(
         self.chain_id,
         GENESIS_LINK,
         GENESIS_LINK,
         spend_dot,
         self.spender,
         self.receiver,
         spend_value,
     )
     assert float(self.state.get_balance(self.spender)) == -10
     # Next spend - tries to pretend as if hasn't happen
     self.new_spend_value = Decimal(6.00, self.con)
     self.new_spend_dot = Dot((2, "22222"))
     self.state.apply_spend(
         self.chain_id,
         Links((spend_dot,)),
         Links((spend_dot,)),
         self.new_spend_dot,
         self.spender,
         self.receiver,
         self.new_spend_value,
     )
     # As the value is less -> the balance will not change until confirmed, or rejected
     assert float(self.state.get_balance(self.spender)) == -10
Пример #2
0
    def add_block(self, block_blob: bytes, block: "PlexusBlock") -> None:

        block_hash = block.hash
        block_tx = block.transaction

        # 1. Add block blob and transaction blob to the block storage
        self.block_store.add_block(block_hash, block_blob)
        self.block_store.add_tx(block_hash, block_tx)
        self.block_store.add_extra(block_hash,
                                   encode_raw({b"type": block.type}))

        # 2. There are two chains: personal and community chain
        pers = block.public_key
        com = block.com_id

        if pers == com:
            pers = block.com_prefix + pers
            com = block.com_prefix + com
        else:
            com = block.com_prefix + com

        # 2.1: Process the block wrt personal chain
        if pers not in self.chains:
            self.chains[pers] = self.chain_factory.create_chain()

        pers_block_dot = Dot((block.sequence_number, block.short_hash))
        pers_dots_list = self.chains[pers].add_block(block.previous,
                                                     block.sequence_number,
                                                     block_hash)
        full_dot_id = pers + encode_raw(pers_block_dot)
        self.block_store.add_dot(full_dot_id, block_hash)
        # TODO: add more chain topic

        # Notify subs of the personal chain
        self.notify(ChainTopic.ALL, chain_id=pers, dots=pers_dots_list)
        self.notify(ChainTopic.PERSONAL, chain_id=pers, dots=pers_dots_list)
        self.notify(pers, chain_id=pers, dots=pers_dots_list)

        # 2.2: add block to the community chain

        if com != EMPTY_PK:
            if com == pers:
                # Chain was processed already, notify rest
                self.notify(ChainTopic.GROUP,
                            chain_id=com,
                            dots=pers_dots_list)
            else:
                if com not in self.chains:
                    self.chains[com] = self.chain_factory.create_chain()
                com_block_dot = Dot((block.com_seq_num, block.short_hash))
                com_dots_list = self.chains[com].add_block(
                    block.links, block.com_seq_num, block_hash)
                full_dot_id = com + encode_raw(com_block_dot)
                self.block_store.add_dot(full_dot_id, block_hash)

                self.notify(ChainTopic.ALL, chain_id=com, dots=com_dots_list)
                self.notify(ChainTopic.GROUP, chain_id=com, dots=com_dots_list)
                self.notify(com, chain_id=com, dots=com_dots_list)
Пример #3
0
    def test_add_mint(self):
        chain_id = self.minter
        value = Decimal(12.00, self.con)
        dot = Dot((1, "123123"))

        self.state.apply_mint(chain_id, dot, GENESIS_LINK, self.minter, value)
        assert self.state.get_balance(self.minter) == value
Пример #4
0
    def test_spend_fork(self):
        value = Decimal(1, self.con)
        dot = Dot((1, b"123123"))
        chain_id = self.spender

        self.state.apply_spend(
            chain_id,
            GENESIS_LINK,
            GENESIS_LINK,
            dot,
            self.spender,
            self.receiver,
            value,
        )
        assert float(self.state.get_balance(self.spender)) == -1
        new_dot = Dot((1, b"5464646"))
        self.state.apply_spend(
            chain_id,
            GENESIS_LINK,
            GENESIS_LINK,
            new_dot,
            self.spender,
            self.receiver,
            value,
        )
        assert float(self.state.get_balance(self.spender)) == -2

        assert self.state.is_chain_forked(chain_id, self.spender)
        assert self.state.was_chain_forked(chain_id, self.spender)

        # Fix the fork:
        f_dot = Dot((2, b"000000"))
        value = Decimal(3, self.con)
        self.state.apply_spend(
            chain_id,
            Links((dot, new_dot)),
            Links((dot, new_dot)),
            f_dot,
            self.spender,
            self.receiver,
            value,
        )
        assert float(self.state.get_balance(self.spender)) == -3

        assert not self.state.is_chain_forked(chain_id, self.spender)
        assert self.state.was_chain_forked(chain_id, self.spender)
Пример #5
0
 def _find_first_conflicting_point(self, conf_dict: Dict,
                                   chain: BaseChain) -> Set[Dot]:
     to_request = set()
     for sn, hash_vals in conf_dict.items():
         local_val = chain.get_all_short_hash_by_seq_num(sn)
         if not local_val:
             # Don't know this value => request from peer
             to_request.update(Dot((sn, k) for k in hash_vals))
             continue
         diff_val = local_val - set(hash_vals)
         sim_diff = set(hash_vals) - local_val
         if sim_diff:
             to_request.update(Dot((sn, k)) for k in sim_diff)
         # If there is a hash that is known
         if diff_val:
             # First inconsistency point met
             return {Dot((sn, k)) for k in diff_val}, to_request
     return set(), to_request
Пример #6
0
    def test_mint_and_spend_fork(self):
        chain_id = self.minter
        value = Decimal(12.00, self.con)
        dot = Dot((1, "123123"))

        self.state.apply_mint(chain_id, dot, GENESIS_LINK, self.minter, value)
        assert self.state.get_balance(self.minter) == value

        spend_value = Decimal(12.00, self.con)
        spend_dot = Dot((1, "323123"))
        self.state.apply_spend(
            chain_id,
            GENESIS_LINK,
            GENESIS_LINK,
            spend_dot,
            self.spender,
            self.receiver,
            spend_value,
        )
        assert float(self.state.get_balance(self.spender)) == 0
        assert self.state.is_chain_forked(chain_id, self.spender)
Пример #7
0
    def std_vals(self):
        self.chain_id = b"chain_id"
        self.block_dot = Dot((3, ShortKey("808080")))
        self.block_dot_encoded = encode_raw(self.block_dot)
        self.dot_id = self.chain_id + self.block_dot_encoded

        self.test_hash = b"test_hash"
        self.tx_blob = b"tx_blob"
        self.block_blob = b"block_blob"

        self.test_block = FakeBlock()
        self.pers = self.test_block.public_key
        self.com_id = self.test_block.com_id
Пример #8
0
    def test_add_claim(self):
        value = Decimal(12.11, self.con)
        dot = Dot((1, "123123"))
        chain_id = self.spender

        self.state.apply_spend(
            chain_id,
            GENESIS_LINK,
            GENESIS_LINK,
            dot,
            self.spender,
            self.receiver,
            value,
        )
        assert self.state.last_spend_values[self.spender][self.receiver][dot] == value
        assert float(self.state.get_balance(self.spender)) == -12.11

        claim_dot = Dot((1, "2323"))

        self.state.apply_confirm(
            chain_id, self.receiver, Links((dot,)), claim_dot, self.spender, dot, value
        )
        assert self.state.last_spend_values[self.spender][self.receiver][dot] == value
        assert float(self.state.get_balance(self.receiver)) == 12.11
Пример #9
0
    def test_mint_and_spend(self):
        chain_id = self.minter
        value = Decimal(15.00, self.con)
        dot = Dot((1, "123123"))

        self.state.apply_mint(chain_id, dot, GENESIS_LINK, self.minter, value)
        assert self.state.get_balance(self.minter) == value
        assert not self.state.is_chain_forked(chain_id, self.minter)

        spend_value = Decimal(12.00, self.con)
        spend_dot = Dot((2, "23123"))
        self.state.apply_spend(
            chain_id,
            GENESIS_LINK,
            Links((dot,)),
            spend_dot,
            self.spender,
            self.receiver,
            spend_value,
        )
        assert float(self.state.get_balance(self.spender)) == 3
        assert not self.state.is_chain_forked(chain_id, self.spender)
        assert not self.state.was_chain_forked(chain_id, self.spender)
        return chain_id, spend_value, spend_dot
Пример #10
0
 def test_mint_value_unbound_value(self, set_vals):
     mint_tx = {b"value": 10**7 - 1}
     chain_id = set_vals.community_id
     minter = set_vals.nodes[0].overlay.my_pub_key_bin
     set_vals.nodes[0].overlay.state_db.apply_mint(
         chain_id,
         Dot((1, "123123")),
         GENESIS_LINK,
         minter,
         Decimal(mint_tx.get(b"value"), set_vals.context),
         True,
     )
     next_mint = {b"value": 1}
     with pytest.raises(UnboundedMintException):
         set_vals.nodes[0].overlay.verify_mint(chain_id, minter, next_mint)
Пример #11
0
    def test_valid_spend_with_reject(self):
        chain_id, value, spend_dot = self.test_mint_and_spend()

        reject_dot = Dot((3, "33333"))
        # Add confirmation from the counter-party
        self.state.apply_reject(
            chain_id,
            self.receiver,
            Links((spend_dot,)),
            reject_dot,
            self.spender,
            spend_dot,
        )
        # As the transaction is confirmed, inconsistency is resolved
        assert float(self.state.get_balance(self.spender)) == 3 + value
        assert float(self.state.get_balance(self.receiver)) == 0
Пример #12
0
    def test_risky_spend_with_reject(self):
        self.test_risky_spend()

        reject_dot = Dot((3, "33333"))
        # Add confirmation from the counter-party
        self.state.apply_reject(
            self.chain_id,
            self.receiver,
            Links((self.new_spend_dot,)),
            reject_dot,
            self.spender,
            self.new_spend_dot,
        )
        # As the transaction is rejected - the effect of it is reverted to the previous stable state - zero.
        assert float(self.state.get_balance(self.spender)) == 0
        assert float(self.state.get_balance(self.receiver)) == 0
        assert self.state.was_balance_negative(self.spender)
Пример #13
0
    def test_risky_spend_with_confirm(self):
        self.test_risky_spend()

        confirm_dot = Dot((3, "33333"))
        # Add confirmation from the counter-party
        self.state.apply_confirm(
            self.chain_id,
            self.receiver,
            Links((self.new_spend_dot,)),
            confirm_dot,
            self.spender,
            self.new_spend_dot,
            self.new_spend_value,
        )
        # As the transaction is confirmed, inconsistency is resolved
        assert float(self.state.get_balance(self.spender)) == -6
        assert float(self.state.get_balance(self.receiver)) == 6
        assert self.state.was_balance_negative(self.spender)
Пример #14
0
    def test_state_updates(self):
        chain_id = self.minter
        value = Decimal(12.00, self.con)
        dot = Dot((1, b"123123"))

        self.state.apply_mint(
            chain_id, dot, GENESIS_LINK, self.minter, value, store_update=True
        )
        assert self.state.get_balance(self.minter) == value
        assert not self.state.is_chain_forked(chain_id, self.minter)
        spend_value = Decimal(12.00, self.con)
        spend_dot = Dot((2, b"23123"))
        self.state.apply_spend(
            chain_id,
            GENESIS_LINK,
            Links((dot,)),
            spend_dot,
            self.spender,
            self.receiver,
            spend_value,
            store_status_update=True,
        )
        assert float(self.state.get_balance(self.spender)) == 0
        assert not self.state.is_chain_forked(chain_id, self.spender)

        claim_dot = Dot((3, b"23323"))

        self.state.apply_confirm(
            chain_id,
            self.receiver,
            Links((spend_dot,)),
            claim_dot,
            self.spender,
            spend_dot,
            spend_value,
            store_update=True,
        )

        v = self.state.get_closest_peers_status(chain_id, 1)
        assert v is not None
        assert v[0] == 1
        assert len(v[1]) == 1
        assert v[1].get(shorten(self.spender)) == (True, True)

        v = self.state.get_closest_peers_status(chain_id, 2)
        assert v is not None
        assert (
            (v[0] == 2)
            and (len(v[1]) == 1)
            and (v[1].get(shorten(self.spender)) == (True, True))
        )

        v = self.state.get_closest_peers_status(chain_id, 3)
        assert v is not None
        assert (
            v[0] == 3
            and len(v[1]) == 2
            and (v[1].get(shorten(self.spender)) == (True, True))
            and (v[1].get(shorten(self.receiver)) == (True, True))
        )

        assert v[1] == self.state.get_last_peer_status(chain_id)
Пример #15
0
 def com_dot(self) -> Dot:
     return Dot((self.com_seq_num, self.short_hash))
Пример #16
0
 def pers_dot(self) -> Dot:
     return Dot((self.sequence_number, self.short_hash))
Пример #17
0
    def test_add_invalid_claim(self):
        value = Decimal(1, self.con)
        dot = Dot((1, "123123"))
        chain_id = self.spender

        self.state.apply_spend(
            chain_id,
            GENESIS_LINK,
            GENESIS_LINK,
            dot,
            self.spender,
            self.receiver,
            value,
        )
        assert self.state.last_spend_values[self.spender][self.receiver][dot] == value
        assert float(self.state.get_balance(self.spender)) == -1

        new_dot = Dot((1, "223123"))
        self.state.apply_spend(
            chain_id,
            GENESIS_LINK,
            GENESIS_LINK,
            new_dot,
            self.spender,
            self.receiver,
            value,
        )
        assert self.state.last_spend_values[self.spender][self.receiver][dot] == value
        assert float(self.state.get_balance(self.spender)) == -2
        assert self.state.was_chain_forked(chain_id, self.spender)

        claim_dot = Dot((2, "33323"))
        with pytest.raises(InvalidClaimException):
            # Should raise exception as the claim links are not correct
            self.state.apply_confirm(
                chain_id,
                self.receiver,
                GENESIS_LINK,
                claim_dot,
                self.spender,
                dot,
                value,
            )
        self.state.apply_confirm(
            chain_id, self.receiver, Links((dot,)), claim_dot, self.spender, dot, value
        )

        assert self.state.last_spend_values[self.spender][self.receiver][dot] == value
        assert float(self.state.get_balance(self.receiver)) == 1
        with pytest.raises(InvalidClaimException):
            # Double claim - should raise exception
            self.state.apply_confirm(
                chain_id,
                self.receiver,
                Links((claim_dot,)),
                claim_dot,
                self.spender,
                dot,
                value,
            )
        assert float(self.state.get_balance(self.receiver)) == 1
        assert not self.state.was_chain_forked(chain_id, self.receiver)

        # Add inconsistent claim
        inconsistent_value = Decimal(100, self.con)
        with pytest.raises(InconsistentClaimException):
            self.state.apply_confirm(
                chain_id,
                self.receiver,
                Links((claim_dot,)),
                claim_dot,
                self.spender,
                new_dot,
                inconsistent_value,
            )
        assert float(self.state.get_balance(self.receiver)) == 1
        assert not self.state.was_chain_forked(chain_id, self.receiver)