示例#1
0
    def test_transaction_v2_invalid_signature(self):
        # noinspection PyDictCreation
        tx_dumped = {
            'from':
            'hx48cd6eb32339d5c719dcc0af21e9bc3b67d733e6',
            'to':
            'hx22f72e44141bedd50d1e536455682863d3d8a484',
            'value':
            '0x186a0',
            'fee':
            '0xf4240',
            'timestamp':
            '1558679280067963',
            'nonce':
            '1',
            'tx_hash':
            '34477b3bc76fa73aad0258ba9fd36f28a3c4b26956c1e5eb92ddda7d98df4e32',  # valid hash
            'signature':
            'W/hW/PAo+ExeSsreD//yJVgNqmnkWKs+m0VUqE11O7Ek82yEINuczLRXtj1k515q8Ep4OLsRPPiPNjDM9vuhsgE='
        }
        tx_dumped['signature'] = Signature(os.urandom(
            Signature.size)).to_base64str()  # invalid signature

        tx_version, tx_type = self.tx_versioner.get_version(tx_dumped)
        ts = TransactionSerializer.new(tx_version, tx_type, self.tx_versioner)
        tx = ts.from_(tx_dumped)

        tv = TransactionVerifier.new(tx_version, tx_type, self.tx_versioner)
        self.assertRaises(TransactionInvalidSignatureError,
                          lambda: tv.verify(tx))
        self.assertRaises(TransactionInvalidSignatureError,
                          lambda: tv.pre_verify(tx))
示例#2
0
    def test_block_invalid_vote(self):
        ratio = 0.67
        block_hash = Hash32(os.urandom(Hash32.size))
        block_votes = BlockVotes(self.reps, ratio, 0, 0, block_hash)

        invalid_block_vote = BlockVote.new(self.signers[0], 0, 0, 1,
                                           block_hash)
        self.assertRaises(RuntimeError, block_votes.add_vote,
                          invalid_block_vote)

        invalid_block_vote = BlockVote.new(self.signers[0], 0, 1, 0,
                                           block_hash)
        self.assertRaises(RuntimeError, block_votes.add_vote,
                          invalid_block_vote)

        invalid_block_vote = BlockVote.new(self.signers[0], 0, 0, 0,
                                           Hash32(os.urandom(32)))
        self.assertRaises(RuntimeError, block_votes.add_vote,
                          invalid_block_vote)

        invalid_block_vote = BlockVote(rep=self.reps[0],
                                       timestamp=0,
                                       signature=Signature(os.urandom(65)),
                                       block_height=0,
                                       round_=0,
                                       block_hash=block_hash)
        self.assertRaises(RuntimeError, block_votes.add_vote,
                          invalid_block_vote)

        block_vote = BlockVote.new(self.signers[0], 0, 0, 0, block_hash)
        block_votes.add_vote(block_vote)
        duplicate_block_vote = BlockVote.new(self.signers[0], 0, 0, 0,
                                             Hash32.empty())
        self.assertRaises(votes.VoteDuplicateError, block_votes.add_vote,
                          duplicate_block_vote)
示例#3
0
    def _deserialize_header_data(self, json_data: dict):
        hash_ = Hash32.fromhex(json_data["hash"])

        prev_hash = json_data.get('prevHash')
        prev_hash = Hash32.fromhex(prev_hash) if prev_hash else None

        peer_id = json_data.get('leader')
        peer_id = ExternalAddress.fromhex(peer_id) if peer_id else None

        signature = json_data.get('signature')
        signature = Signature.from_base64str(signature) if signature else None

        next_leader = json_data.get("nextLeader")
        next_leader = ExternalAddress.fromhex(
            next_leader) if next_leader else None

        transactions_hash = json_data["transactionsHash"]
        transactions_hash = Hash32.fromhex(transactions_hash)

        receipts_hash = json_data["receiptsHash"]
        receipts_hash = Hash32.fromhex(receipts_hash)

        state_hash = json_data["stateHash"]
        state_hash = Hash32.fromhex(state_hash)

        reps_hash = json_data["repsHash"]
        reps_hash = Hash32.fromhex(reps_hash)

        next_reps_hash = json_data["nextRepsHash"]
        next_reps_hash = Hash32.fromhex(next_reps_hash)

        leader_votes_hash = json_data["leaderVotesHash"]
        leader_votes_hash = Hash32.fromhex(leader_votes_hash)

        prev_votes_hash = json_data["prevVotesHash"]
        prev_votes_hash = Hash32.fromhex(prev_votes_hash)

        height = json_data["height"]
        height = int(height, 16)

        timestamp = json_data["timestamp"]
        timestamp = int(timestamp, 16)

        return {
            "hash": hash_,
            "prev_hash": prev_hash,
            "height": height,
            "timestamp": timestamp,
            "peer_id": peer_id,
            "signature": signature,
            "next_leader": next_leader,
            "transactions_hash": transactions_hash,
            "receipts_hash": receipts_hash,
            "state_hash": state_hash,
            "reps_hash": reps_hash,
            "next_reps_hash": next_reps_hash,
            "leader_votes_hash": leader_votes_hash,
            "prev_votes_hash": prev_votes_hash,
            "logs_bloom": BloomFilter.fromhex(json_data["logsBloom"])
        }
    def from_(self, tx_data: dict) -> 'Transaction':
        tx_data_copied = dict(tx_data)

        tx_data_copied.pop('method', None)
        hash = tx_data_copied.pop('tx_hash', None)
        signature = tx_data_copied.pop('signature', None)
        timestamp = tx_data_copied.pop('timestamp', None)
        from_address = tx_data_copied.pop('from', None)
        to_address = tx_data_copied.pop('to', None)
        value = tx_data_copied.pop('value', None)
        fee = tx_data_copied.pop('fee', None)
        nonce = tx_data_copied.pop('nonce', None)
        extra = tx_data_copied

        value = int_fromhex(value)
        fee = int_fromhex(fee)

        if nonce is not None:
            nonce = int_fromstr(nonce)

        return Transaction(
            raw_data=tx_data,
            hash=Hash32.fromhex(hash, ignore_prefix=True, allow_malformed=False),
            signature=Signature.from_base64str(signature),
            timestamp=int(timestamp) if timestamp is not None else None,
            from_address=ExternalAddress.fromhex(from_address, ignore_prefix=False, allow_malformed=True),
            to_address=ExternalAddress.fromhex(to_address, ignore_prefix=False, allow_malformed=True),
            value=value,
            fee=fee,
            nonce=nonce,
            extra=extra,
        )
示例#5
0
    def sign(self):
        if self.signature is not None:
            return self.signature

        if self.hash is None:
            raise RuntimeError

        self.signature = Signature(self.signer.sign_hash(self.hash))
        return self.signature
示例#6
0
    def sign_transaction(self, tx: 'Transaction'):
        if self.signer.address != tx.signer_address.hex_hx():
            raise RuntimeError(
                f"Signer not match. {self.signer.address} != {tx.signer_address.hex_hx()}"
            )

        signature = Signature(self.signer.sign_hash(tx.hash))

        raw_data = dict(tx.raw_data)
        raw_data["signature"] = signature.to_base64str()

        return Transaction(raw_data=raw_data,
                           hash=tx.hash,
                           signature=signature,
                           timestamp=tx.timestamp,
                           from_address=tx.from_address,
                           to_address=tx.to_address,
                           value=tx.value,
                           fee=tx.fee,
                           nonce=tx.nonce)
示例#7
0
        def _header(hash_: Hash32 = Hash32.new(),
                    prev_hash: Hash32 = Hash32.new(),
                    height: int = 0,
                    timestamp: int = 0,
                    peer_id: ExternalAddress = ExternalAddress.new(),
                    signature: Signature = Signature.new(),
                    next_leader: Address = Address.new(),
                    merkle_tree_root_hash: Hash32 = Hash32.new(),
                    commit_state: dict = dict()) -> BlockHeader_v0_1a:

            return BlockHeader_v0_1a(hash_, prev_hash, height, timestamp, peer_id,
                                     signature, next_leader, merkle_tree_root_hash, commit_state)
示例#8
0
        def _header(hash_: Hash32 = Hash32.new(),
                    prev_hash: Hash32 = Hash32.new(),
                    height: int = 0,
                    timestamp: int = 0,
                    peer_id: ExternalAddress = ExternalAddress.new(),
                    signature: Signature = Signature.new(),
                    next_leader: ExternalAddress = ExternalAddress.new(),
                    logs_bloom: BloomFilter = BloomFilter.new(),
                    transactions_hash: Hash32 = Hash32.new(),
                    state_hash: Hash32 = Hash32.new(),
                    receipts_hash: Hash32 = Hash32.new(),
                    reps_hash: Hash32 = Hash32.new(),
                    next_reps_hash: Hash32 = Hash32.new(),
                    leader_votes_hash: Hash32 = Hash32.new(),
                    prev_votes_hash: Hash32 = Hash32.new()) -> BlockHeader_v0_4:

            return BlockHeader_v0_4(hash_, prev_hash, height, timestamp, peer_id, signature,
                                    next_leader, logs_bloom, transactions_hash,
                                    state_hash, receipts_hash, reps_hash,
                                    next_reps_hash, leader_votes_hash, prev_votes_hash)
示例#9
0
    def test_leader_invalid_vote(self):
        ratio = 0.67

        old_leader = self.reps[0]
        new_leader = self.reps[1]
        leader_votes = LeaderVotes(self.reps, ratio, 0, 0, old_leader)

        invalid_leader_vote = LeaderVote.new(self.signers[0], 0, 1, 0,
                                             old_leader, new_leader)
        self.assertRaises(RuntimeError, leader_votes.add_vote,
                          invalid_leader_vote)

        invalid_leader_vote = LeaderVote.new(self.signers[0], 0, 0, 1,
                                             old_leader, new_leader)
        self.assertRaises(RuntimeError, leader_votes.add_vote,
                          invalid_leader_vote)

        invalid_leader_vote = LeaderVote.new(self.signers[0], 0, 0, 0,
                                             new_leader, new_leader)
        self.assertRaises(RuntimeError, leader_votes.add_vote,
                          invalid_leader_vote)

        invalid_leader_vote = LeaderVote(rep=self.reps[0],
                                         timestamp=0,
                                         signature=Signature(os.urandom(65)),
                                         block_height=0,
                                         round_=0,
                                         new_leader=new_leader,
                                         old_leader=old_leader)
        self.assertRaises(RuntimeError, leader_votes.add_vote,
                          invalid_leader_vote)

        leader_vote = LeaderVote.new(self.signers[0], 0, 0, 0, old_leader,
                                     new_leader)
        leader_votes.add_vote(leader_vote)
        duplicate_leader_vote = LeaderVote.new(self.signers[0], 0, 0, 0,
                                               old_leader, self.reps[2])
        self.assertRaises(votes.VoteDuplicateError, leader_votes.add_vote,
                          duplicate_leader_vote)
示例#10
0
    def test_transaction_v3_invalid_signature(self):
        # noinspection PyDictCreation
        tx_dumped = {
            'version':
            '0x3',
            'from':
            'hx48cd6eb32339d5c719dcc0af21e9bc3b67d733e6',
            'to':
            'hxe0a231fa5c80e45f51d7df5f7d127954320df829',
            'stepLimit':
            '0xf4240',
            'timestamp':
            '0x5899c717f92f8',
            'nid':
            '0x3',
            'value':
            '0x186a0',
            'nonce':
            '0x64',
            'data':
            'test',
            'dataType':
            'message',
            'signature':
            'J84KdBtQR4w1bcBdBGF8g6aNoCXjsY/5T6vGV4RXeMwEvafj9xVRDVjzF+vN1JVYvXrAzjlYPCiiBXBQe6+tRAE='
        }
        tx_dumped['signature'] = Signature(os.urandom(
            Signature.size)).to_base64str()  # invalid signature

        tx_version, tx_type = self.tx_versioner.get_version(tx_dumped)
        ts = TransactionSerializer.new(tx_version, tx_type, self.tx_versioner)
        tx = ts.from_(tx_dumped)

        tv = TransactionVerifier.new(tx_version, tx_type, self.tx_versioner)
        self.assertRaises(TransactionInvalidSignatureError,
                          lambda: tv.verify(tx))
        self.assertRaises(TransactionInvalidSignatureError,
                          lambda: tv.pre_verify(tx, nid=3))
示例#11
0
    def _deserialize_header_data(self, json_data: dict):
        prev_hash = json_data.get('prev_block_hash')
        prev_hash = Hash32.fromhex(prev_hash, ignore_prefix=True) if prev_hash else None

        peer_id = json_data.get('peer_id')
        peer_id = ExternalAddress.fromhex(peer_id) if peer_id else None

        signature = json_data.get('signature')
        signature = Signature.from_base64str(signature) if signature else None

        next_leader = json_data.get("next_leader")
        next_leader = ExternalAddress.fromhex(next_leader) if next_leader else None

        return {
            "hash": Hash32.fromhex(json_data["block_hash"], ignore_prefix=True),
            "prev_hash": prev_hash,
            "height": json_data["height"],
            "timestamp": json_data["time_stamp"],
            "peer_id": peer_id,
            "signature": signature,
            "next_leader": next_leader,
            "merkle_tree_root_hash": Hash32.fromhex(json_data["merkle_tree_root_hash"], ignore_prefix=True),
            "commit_state": json_data["commit_state"]
        }
示例#12
0
文件: vote.py 项目: yakkle/loopchain
 def empty(cls, rep: ExternalAddress, block_height: int, round_: int,
           old_leader: ExternalAddress):
     return cls(rep, 0, Signature.empty(), block_height, round_, old_leader,
                ExternalAddress.empty())
示例#13
0
 def _deserialize(cls, data: dict):
     return {
         "rep": ExternalAddress.fromhex_address(data["rep"]),
         "timestamp": int(data["timestamp"], 16),
         "signature": Signature.from_base64str(data["signature"])
     }
示例#14
0
    def new(cls, signer: Signer, timestamp: int, **kwargs):
        rep_id: ExternalAddress = ExternalAddress.fromhex(signer.address)

        hash_ = cls.to_hash(rep_id, timestamp, **kwargs)
        signature = Signature(signer.sign_hash(hash_))
        return cls(rep_id, timestamp, signature, **kwargs)
示例#15
0
文件: vote.py 项目: yakkle/loopchain
 def empty(cls, rep: ExternalAddress, block_height: int):
     return cls(rep, 0, Signature.empty(), block_height, Hash32.empty())
class TestTxCache:
    target_attrs = ["hash", "signature"]

    @pytest.mark.parametrize("target_attr", target_attrs)
    def test_no_cache_attr_in_tx_if_not_verified(self, tx_version,
                                                 tx_factory: 'TxFactory',
                                                 target_attr):
        """Check that Transaction has no attribute until the verification func has been invoked"""
        tx = tx_factory(tx_version)
        if any("cache" in attr for attr in dir(tx)):
            raise AttributeError(
                "Something wrong. Transaction has cached value when initialized."
            )

        with pytest.raises(AttributeError):
            getattr(tx, f"_cache_verify_{target_attr}")

    @pytest.mark.parametrize("raise_exception", [True, False])
    @pytest.mark.parametrize("target_attr", ["hash", "signature"])
    def test_has_cache_attr_when_verified_successfully(self, tx_version,
                                                       tx_factory: 'TxFactory',
                                                       raise_exception,
                                                       target_attr):
        """Check that the verification result has been cached successfully"""
        tx = tx_factory(tx_version)
        tv = TransactionVerifier.new(tx.version,
                                     tx.type(),
                                     tx_versioner,
                                     raise_exceptions=raise_exception)

        verify_func_name = f"verify_{target_attr}"
        verify_func = getattr(tv, verify_func_name)
        verify_func(tx)

        assert getattr(tx, f"_cache_{verify_func_name}")

    @pytest.mark.parametrize("raise_exception", [True, False])
    @pytest.mark.parametrize("expected_exc, target_attr, fake_value", [
        (TransactionInvalidHashError, "hash", Hash32.new()),
        (TransactionInvalidSignatureError, "signature", Signature.new()),
    ])
    def test_exception_cached_when_raised_exception_while_verification(
            self, tx_version, tx_factory: 'TxFactory', raise_exception,
            expected_exc, target_attr, fake_value, monkeypatch):
        """Check that the exception successfully cached when raised any exception while verification step"""
        tx = tx_factory(tx_version)
        tv = TransactionVerifier.new(tx.version,
                                     tx.type(),
                                     tx_versioner,
                                     raise_exceptions=raise_exception)
        verify_func = getattr(tv, f"verify_{target_attr}")

        orig_value = getattr(tx, target_attr)
        test_values = (fake_value, orig_value)

        for test_value in test_values:
            # Monkeypatch
            object.__setattr__(tx, target_attr, test_value)
            assert getattr(tx, target_attr) == test_value

            # Verification test
            if raise_exception:
                with pytest.raises(expected_exc):
                    verify_func(tx)
            else:
                tv.exceptions.clear()
                assert not tv.exceptions
                verify_func(tx)
                assert isinstance(tv.exceptions[0], expected_exc)

    @pytest.mark.parametrize("raise_exception", [True, False])
    @pytest.mark.parametrize("expected_exc, target_attr, fake_value", [
        (TransactionInvalidHashError, "hash", Hash32.new()),
        (TransactionInvalidSignatureError, "signature", Signature.new()),
    ])
    def test_verify_success_and_no_exc_with_fake_value_at_second(
            self, tx_version, tx_factory: 'TxFactory', raise_exception,
            expected_exc, target_attr, fake_value, monkeypatch):
        """Check that the result is successfully cached and bypasses further verifications which could raise exceptions.

        Do not apply this usecase in code!
        This test aims the reliablity of cache logic, not for the usefulness of this case.
        """
        tx = tx_factory(tx_version)
        tv = TransactionVerifier.new(tx.version,
                                     tx.type(),
                                     tx_versioner,
                                     raise_exceptions=raise_exception)
        verify_func = getattr(tv, f"verify_{target_attr}")

        # First verification
        verify_func(tx)

        # Monkeypatch with fake value
        object.__setattr__(tx, target_attr, fake_value)
        assert getattr(tx, target_attr) == fake_value

        # Verify again with fake value and ensure no exceptions raised
        if raise_exception:
            verify_func(tx)
        else:
            tv.exceptions.clear()
            assert not tv.exceptions
            verify_func(tx)
            assert not tv.exceptions

    @pytest.mark.parametrize("tag", ["before_cache", "after_cache"])
    @pytest.mark.parametrize("target_attr", ["hash", "signature"])
    def test_benchmark_verify(self, benchmark, tx_version,
                              tx_factory: 'TxFactory', target_attr, tag):
        """Benchmark the elapsed time of verification func in various cases."""
        tx = tx_factory(tx_version)
        tv = TransactionVerifier.new(tx.version, tx.type(), tx_versioner)
        verify_func = getattr(tv, f"verify_{target_attr}")

        if tag == "first":
            benchmark(verify_func, tx)
        else:
            verify_func(tx)
            benchmark(verify_func, tx)
示例#17
0
    def sign(self):
        if self.hash is None:
            self.build_hash()

        self.signature = Signature(self.signer.sign_hash(self.hash))
        return self.signature