@@ -79,29 +79,19 @@ def receive_peer_block():
7979 if not block_data :
8080 return jsonify ({"success" : False , "message" : "No block data provided" }), 400
8181
82- # 1. Reconstruct block object
83- new_block = blockchain .block_model (
84- index = block_data ["index" ],
85- timestamp = block_data ["timestamp" ],
86- data = json .dumps (block_data ["data" ]),
87- merkle_root = block_data .get ("merkle_root" ),
88- previous_hash = block_data ["previous_hash" ],
89- nonce = block_data ["nonce" ],
90- hash = block_data ["hash" ],
91- signed_by = block_data .get ("signed_by" ),
92- signature = block_data .get ("signature" ),
93- )
82+ required_fields = {"index" , "timestamp" , "data" , "previous_hash" , "nonce" , "hash" }
83+ missing = [field for field in required_fields if field not in block_data ]
84+ if missing :
85+ return jsonify ({"success" : False , "message" : f"Missing required fields: { ', ' .join (missing )} " }), 400
9486
95- # 2. Simple validation against local chain
96- last_block = blockchain .get_latest_block ()
97- if last_block and block_data ["index" ] <= last_block .index :
98- return jsonify ({"success" : False , "message" : "Block already exists or is outdated" }), 409
87+ source_node = blockchain .normalize_node_ref (request .headers .get ("X-Node-Address" ) or request .headers .get ("X-Source-Node" ))
88+ origin_node = (request .headers .get ("X-Origin-Node" ) or request .headers .get ("X-Source-Node" ) or "unknown" ).strip ()
9989
100- if last_block and block_data ["previous_hash" ] != last_block .hash :
101- return jsonify ({"success" : False , "message" : "Previous hash mismatch. Sync required." }), 400
90+ # Idempotency gate: if already present, ignore safely.
91+ if blockchain .has_block (block_data ["index" ], block_data ["hash" ]):
92+ return jsonify ({"success" : True , "message" : "Duplicate block ignored" }), 200
10293
103- # 3. Cryptographic validation (simplified for the model bridge)
104- # Create a Block object for validation methods
94+ # 1. Validate block object before any persistence
10595 from core .blockchain import Block
10696
10797 v_block = Block (
@@ -110,6 +100,7 @@ def receive_peer_block():
110100 block_data ["previous_hash" ],
111101 signed_by = block_data .get ("signed_by" ),
112102 signature = block_data .get ("signature" ),
103+ proposed_by = block_data .get ("proposed_by" ),
113104 )
114105 v_block .timestamp = block_data ["timestamp" ]
115106 v_block .nonce = block_data ["nonce" ]
@@ -119,16 +110,50 @@ def receive_peer_block():
119110 if v_block .hash != v_block .calculate_hash ():
120111 return jsonify ({"success" : False , "message" : "Invalid block hash" }), 400
121112
122- if blockchain .crypto_manager and v_block .signature :
113+ if v_block .merkle_root and v_block .merkle_root != v_block .calculate_merkle_root ():
114+ return jsonify ({"success" : False , "message" : "Invalid Merkle root" }), 400
115+
116+ if v_block .index > 0 and v_block .signed_by not in blockchain .VALIDATORS :
117+ return jsonify ({"success" : False , "message" : "Unauthorized block signer" }), 403
118+
119+ if blockchain .crypto_manager :
120+ if not v_block .signature :
121+ return jsonify ({"success" : False , "message" : "Missing digital signature" }), 400
123122 if not blockchain .crypto_manager .verify_signature (v_block .hash , v_block .signature ):
124123 return jsonify ({"success" : False , "message" : "Invalid digital signature" }), 400
125124
126- # All checks passed, add to local DB and chain
125+ # 2. Validate against local chain linkage
126+ last_block = blockchain .get_latest_block ()
127+ if last_block and block_data ["index" ] <= last_block .index :
128+ return jsonify ({"success" : True , "message" : "Outdated block ignored" }), 200
129+
130+ if last_block and block_data ["previous_hash" ] != last_block .hash :
131+ return jsonify ({"success" : False , "message" : "Previous hash mismatch. Sync required." }), 400
132+
133+ # 3. Persist only after full validation
134+ new_block = blockchain .block_model (
135+ index = block_data ["index" ],
136+ timestamp = block_data ["timestamp" ],
137+ data = json .dumps (block_data ["data" ]),
138+ merkle_root = block_data .get ("merkle_root" ),
139+ previous_hash = block_data ["previous_hash" ],
140+ nonce = block_data ["nonce" ],
141+ hash = block_data ["hash" ],
142+ signed_by = block_data .get ("signed_by" ),
143+ signature = block_data .get ("signature" ),
144+ )
145+
127146 db .session .add (new_block )
128147 db .session .commit ()
129148 blockchain .chain .append (v_block )
130149
131- logging .info (f"Accepted peer block { block_data ['index' ]} from { block_data .get ('signed_by' )} " )
150+ # Controlled gossip propagation: relay accepted blocks, never back to sender.
151+ blockchain .broadcast_block (v_block , source_node = source_node , origin_node = origin_node )
152+
153+ logging .info (
154+ f"Accepted peer block { block_data ['index' ]} from signer={ block_data .get ('signed_by' )} "
155+ f"source={ source_node or 'unknown' } origin={ origin_node } "
156+ )
132157 return jsonify ({"success" : True , "message" : "Block accepted and added to chain" })
133158
134159 except Exception as e :
0 commit comments