def test_merkle_happy_path():
    w1 = Wallet(test=True)
    w2 = Wallet(test=True)
    transactions = [
        SignedRawTransaction(
            details=Details(
                sender=w1.address,
                recipient=w2.address,
                amount=4.5,
                nonce=0,
                timestamp=datetime.utcnow(),
                public_key=w1.public_key.hex(),
            ),
            signature="sig",
        ),
        SignedRawTransaction(
            details=Details(
                sender=w2.address,
                recipient=w1.address,
                amount=1.87,
                nonce=0,
                timestamp=datetime.utcnow(),
                public_key=w2.public_key.hex(),
            ),
            signature="sig",
        ),
    ]

    m = convert_to_merkle(transactions)
    assert m.is_ready
    print(m.get_merkle_root())
    print(m.get_proof(0))
    SignedRawTransaction.ParseFromHex(m.get_proof(0)[0]["right"])
    print(m.get_proof(1))
    SignedRawTransaction.ParseFromHex(m.get_proof(1)[0]["left"])
def test_transaction_fails_validation():
    w = Wallet(test=True)
    w2 = Wallet(test=True)

    timestamp = datetime.utcfromtimestamp(0)

    d = Details(
        sender=w.address,
        recipient=w2.address,
        amount=4.5,
        nonce=0,
        timestamp=timestamp,
        public_key=w.public_key.hex(),
    )

    t = w.sign_transaction(d)

    t_hex = t.SerializeToHex()

    parsed_t = SignedRawTransaction.ParseFromHex(t_hex)

    assert parsed_t == t
    assert w.verify_transaction(t, return_test_nonce)

    t.details.amount = 2.5
    try:
        assert w.verify_transaction(t, return_test_nonce)
        raise Exception("Expected to fail but did not")
    except ecdsa.keys.BadSignatureError:
        assert True
    def broadcast_transaction():  # pylint: disable=unused-variable
        """
        Broadcasts a new transaction to all the nodes
        Returns a status message

        Methods
        -----
        POST

        Parameters
        -----
        transaction : SignedRawTransaction as hex

        Returns application/json
        -----
        Return code : 201, 400, 500
        Response :
        message : str
        transaction : optional Transaction as Dict
        """
        values = request.get_json()
        if not values:
            response = {"message": "No data found."}
            return jsonify(response), 400
        required = ["transaction", "type"]
        if not all(key in values for key in required):
            response = {"message": "Some data is missing."}
            return jsonify(response), 400
        t = SignedRawTransaction.ParseFromHex(values["transaction"])
        try:
            if values["type"] == "mining" or values["type"] == "confirmed":
                tx = FinalTransaction(
                    transaction_hash=Verification.hash_transaction(t),
                    transaction_id=Verification.hash_transaction(t),
                    signed_transaction=t,
                )
                FinalTransaction.SaveTransaction(blockchain.data_location, tx,
                                                 values["type"])
                response = {
                    "message":
                    f"Successfully saved {values['type']} transaction.",
                    "transaction": values["transaction"],
                }
                return jsonify(response), 201
            block_index = blockchain.add_transaction(t, is_receiving=True)
            response = {
                "message": "Successfully added transaction.",
                "transaction": values["transaction"],
                "block": block_index,
            }
            return jsonify(response), 201
        except ValueError as e:
            response = {
                "message": "Creating a transaction failed.",
                "error": str(e)
            }
        return jsonify(response), 500
def test_transaction_with_signature_to_protobuf_and_back():
    w = Wallet(test=True)
    w2 = Wallet(test=True)

    timestamp = datetime.utcfromtimestamp(0)

    d = Details(
        sender=w.address,
        recipient=w2.address,
        amount=4.5,
        nonce=0,
        timestamp=timestamp,
        public_key=w.public_key.hex(),
    )

    t = w.sign_transaction(d)

    t_hex = t.SerializeToHex()

    parsed_t = SignedRawTransaction.ParseFromHex(t_hex)

    assert parsed_t == t

    assert w.verify_transaction(t, return_test_nonce)
def test_transaction_to_protobuf_and_back():
    timestamp = datetime.utcfromtimestamp(0)

    t = SignedRawTransaction(
        details=Details(
            sender="test",
            recipient="test2",
            amount=4.5,
            nonce=0,
            timestamp=timestamp,
            public_key="pub_key",
        ),
        signature="sig",
    )
    t_hex = t.SerializeToHex()

    assert (
        t_hex
        == "0a230a04746573741205746573743219000000000000124020002a0032077075625f6b65791203736967"
    )

    parsed_t = SignedRawTransaction.ParseFromHex(t_hex)

    assert parsed_t == t