From 050f525b1b1425221b097b9c0ff3f5230569a14a Mon Sep 17 00:00:00 2001 From: Alexis Bruneteau Date: Fri, 7 Nov 2025 16:43:56 +0100 Subject: [PATCH] fix: Properly format transaction data for PoA validators MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: Votes were being rejected by validators with 'Invalid data format' error because the transaction data wasn't in the correct format. Root cause: The validator's eth_sendTransaction endpoint expects the 'data' field to be: 1. A hex string prefixed with '0x' 2. The hex-encoded JSON of a Transaction object containing: - voter_id - election_id - encrypted_vote - ballot_hash - timestamp Solution: - Update BlockchainClient.submit_vote() to properly encode transaction data as JSON, then hex-encode it with 0x prefix - Add ballot_hash parameter to submit_vote() method - Update both call sites in votes.py to pass ballot_hash - Generate ballot_hash if not provided for safety This ensures votes are now properly formatted and accepted by validators, allowing them to be submitted to the blockchain instead of falling back to local blockchain. 🤖 Generated with Claude Code Co-Authored-By: Claude --- e-voting-system/backend/blockchain_client.py | 29 ++++++++++++++++++-- e-voting-system/backend/routes/votes.py | 4 ++- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/e-voting-system/backend/blockchain_client.py b/e-voting-system/backend/blockchain_client.py index b59acb1..6e50701 100644 --- a/e-voting-system/backend/blockchain_client.py +++ b/e-voting-system/backend/blockchain_client.py @@ -153,7 +153,8 @@ class BlockchainClient: voter_id: str, election_id: int, encrypted_vote: str, - transaction_id: Optional[str] = None + transaction_id: Optional[str] = None, + ballot_hash: Optional[str] = None ) -> Dict[str, Any]: """ Submit a vote to the PoA blockchain network. @@ -161,8 +162,9 @@ class BlockchainClient: Args: voter_id: Voter identifier election_id: Election ID - encrypted_vote: Encrypted vote (base64 or hex) + encrypted_vote: Encrypted vote data transaction_id: Optional transaction ID (generated if not provided) + ballot_hash: Optional ballot hash for verification Returns: Transaction receipt with block hash and index @@ -179,6 +181,27 @@ class BlockchainClient: import uuid transaction_id = f"tx-{uuid.uuid4().hex[:12]}" + # Generate ballot hash if not provided + if not ballot_hash: + import hashlib + ballot_hash = hashlib.sha256(f"{voter_id}{election_id}{encrypted_vote}".encode()).hexdigest() + + import time + + # Create transaction data as JSON + tx_data = { + "voter_id": str(voter_id), + "election_id": int(election_id), + "encrypted_vote": str(encrypted_vote), + "ballot_hash": str(ballot_hash), + "timestamp": int(time.time()) + } + + # Encode transaction data as hex string with 0x prefix + import json + tx_json = json.dumps(tx_data) + data_hex = "0x" + tx_json.encode().hex() + # Prepare JSON-RPC request rpc_request = { "jsonrpc": "2.0", @@ -186,7 +209,7 @@ class BlockchainClient: "params": [{ "from": voter_id, "to": f"election-{election_id}", - "data": encrypted_vote, + "data": data_hex, "gas": "0x5208" }], "id": transaction_id diff --git a/e-voting-system/backend/routes/votes.py b/e-voting-system/backend/routes/votes.py index a9e7bf7..a00bb8c 100644 --- a/e-voting-system/backend/routes/votes.py +++ b/e-voting-system/backend/routes/votes.py @@ -130,7 +130,8 @@ async def submit_simple_vote( submission_result = await poa_client.submit_vote( voter_id=current_voter.id, election_id=election_id, - encrypted_vote=ballot_hash, # Use ballot hash as data + encrypted_vote="", # Empty for MVP (not encrypted) + ballot_hash=ballot_hash, transaction_id=transaction_id ) blockchain_response = { @@ -272,6 +273,7 @@ async def submit_vote( voter_id=current_voter.id, election_id=vote_bulletin.election_id, encrypted_vote=vote_bulletin.encrypted_vote, + ballot_hash=ballot_hash, transaction_id=transaction_id )