6868from chia .protocols .full_node_protocol import RequestBlocks , RespondBlock , RespondBlocks , RespondSignagePoint
6969from chia .protocols .outbound_message import Message , NodeType , make_msg
7070from chia .protocols .protocol_message_types import ProtocolMessageTypes
71+ from chia .protocols .protocol_timing import CONSENSUS_ERROR_BAN_SECONDS
7172from chia .protocols .shared_protocol import Capability
7273from chia .protocols .wallet_protocol import CoinStateUpdate , RemovedMempoolItem
7374from chia .rpc .rpc_server import StateChangedProtocol
@@ -502,11 +503,16 @@ async def _handle_one_transaction(self, entry: TransactionQueueEntry) -> None:
502503 except asyncio .CancelledError :
503504 error_stack = traceback .format_exc ()
504505 self .log .debug (f"Cancelling _handle_one_transaction, closing: { error_stack } " )
506+ except ValidationError as e :
507+ self .log .exception ("ValidationError in _handle_one_transaction, closing" )
508+ if peer is not None :
509+ await peer .close (CONSENSUS_ERROR_BAN_SECONDS )
510+ entry .done .set ((MempoolInclusionStatus .FAILED , e .code ))
505511 except Exception :
506- error_stack = traceback .format_exc ()
507- self .log .error (f"Error in _handle_one_transaction, closing: { error_stack } " )
512+ self .log .exception ("Error in _handle_one_transaction, closing" )
508513 if peer is not None :
509- await peer .close ()
514+ await peer .close (CONSENSUS_ERROR_BAN_SECONDS )
515+ entry .done .set ((MempoolInclusionStatus .FAILED , Err .UNKNOWN ))
510516 finally :
511517 self .add_transaction_semaphore .release ()
512518
@@ -1092,13 +1098,13 @@ async def request_validate_wp(
10921098 response = await weight_proof_peer .call_api (FullNodeAPI .request_proof_of_weight , request , timeout = wp_timeout )
10931099 # Disconnect from this peer, because they have not behaved properly
10941100 if response is None or not isinstance (response , full_node_protocol .RespondProofOfWeight ):
1095- await weight_proof_peer .close (600 )
1101+ await weight_proof_peer .close (CONSENSUS_ERROR_BAN_SECONDS )
10961102 raise RuntimeError (f"Weight proof did not arrive in time from peer: { weight_proof_peer .peer_info .host } " )
10971103 if response .wp .recent_chain_data [- 1 ].reward_chain_block .height != peak_height :
1098- await weight_proof_peer .close (600 )
1104+ await weight_proof_peer .close (CONSENSUS_ERROR_BAN_SECONDS )
10991105 raise RuntimeError (f"Weight proof had the wrong height: { weight_proof_peer .peer_info .host } " )
11001106 if response .wp .recent_chain_data [- 1 ].reward_chain_block .weight != peak_weight :
1101- await weight_proof_peer .close (600 )
1107+ await weight_proof_peer .close (CONSENSUS_ERROR_BAN_SECONDS )
11021108 raise RuntimeError (f"Weight proof had the wrong weight: { weight_proof_peer .peer_info .host } " )
11031109 if self .in_bad_peak_cache (response .wp ):
11041110 raise ValueError ("Weight proof failed bad peak cache validation" )
@@ -1113,10 +1119,10 @@ async def request_validate_wp(
11131119 try :
11141120 validated , fork_point , summaries = await self .weight_proof_handler .validate_weight_proof (response .wp )
11151121 except Exception as e :
1116- await weight_proof_peer .close (600 )
1122+ await weight_proof_peer .close (CONSENSUS_ERROR_BAN_SECONDS )
11171123 raise ValueError (f"Weight proof validation threw an error { e } " )
11181124 if not validated :
1119- await weight_proof_peer .close (600 )
1125+ await weight_proof_peer .close (CONSENSUS_ERROR_BAN_SECONDS )
11201126 raise ValueError ("Weight proof validation failed" )
11211127 self .log .info (f"Re-checked peers: total of { len (peers_with_peak )} peers with peak { peak_height } " )
11221128 self .sync_store .set_sync_mode (True )
@@ -1378,7 +1384,7 @@ async def ingest_blocks(
13781384 vs ,
13791385 )
13801386 if err is not None :
1381- await peer .close (600 )
1387+ await peer .close (CONSENSUS_ERROR_BAN_SECONDS )
13821388 raise ValueError (f"Failed to validate block batch { start_height } to { end_height } : { err } " )
13831389 if end_height - block_rate_height > 100 :
13841390 now = time .monotonic ()
@@ -2767,66 +2773,56 @@ async def add_transaction(
27672773 return MempoolInclusionStatus .SUCCESS , None
27682774 if self .mempool_manager .seen (spend_name ):
27692775 return MempoolInclusionStatus .FAILED , Err .ALREADY_INCLUDING_TRANSACTION
2770- self .mempool_manager .add_and_maybe_pop_seen (spend_name )
27712776 self .log .debug (f"Processing transaction: { spend_name } " )
27722777 # Ignore if syncing or if we have not yet received a block
27732778 # the mempool must have a peak to validate transactions
27742779 if self .sync_store .get_sync_mode () or self .mempool_manager .peak is None :
2775- status = MempoolInclusionStatus .FAILED
2776- error : Optional [Err ] = Err .NO_TRANSACTIONS_WHILE_SYNCING
2777- self .mempool_manager .remove_seen (spend_name )
2778- else :
2780+ return MempoolInclusionStatus .FAILED , Err .NO_TRANSACTIONS_WHILE_SYNCING
2781+
2782+ cost_result = await self .mempool_manager .pre_validate_spendbundle (transaction , spend_name , self ._bls_cache )
2783+
2784+ self .mempool_manager .add_and_maybe_pop_seen (spend_name )
2785+
2786+ if self .config .get ("log_mempool" , False ): # pragma: no cover
27792787 try :
2780- cost_result = await self .mempool_manager .pre_validate_spendbundle (
2781- transaction , spend_name , self ._bls_cache
2782- )
2783- except ValidationError as e :
2784- self .mempool_manager .remove_seen (spend_name )
2785- return MempoolInclusionStatus .FAILED , e .code
2788+ mempool_dir = path_from_root (self .root_path , "mempool-log" ) / f"{ self .blockchain .get_peak_height ()} "
2789+ mempool_dir .mkdir (parents = True , exist_ok = True )
2790+ with open (mempool_dir / f"{ spend_name } .bundle" , "wb+" ) as f :
2791+ f .write (bytes (transaction ))
27862792 except Exception :
2787- self .mempool_manager .remove_seen (spend_name )
2788- raise
2793+ self .log .exception (f"Failed to log mempool item: { spend_name } " )
27892794
2790- if self .config .get ("log_mempool" , False ): # pragma: no cover
2791- try :
2792- mempool_dir = path_from_root (self .root_path , "mempool-log" ) / f"{ self .blockchain .get_peak_height ()} "
2793- mempool_dir .mkdir (parents = True , exist_ok = True )
2794- with open (mempool_dir / f"{ spend_name } .bundle" , "wb+" ) as f :
2795- f .write (bytes (transaction ))
2796- except Exception :
2797- self .log .exception (f"Failed to log mempool item: { spend_name } " )
2798-
2799- async with self .blockchain .priority_mutex .acquire (priority = BlockchainMutexPriority .low ):
2800- if self .mempool_manager .get_spendbundle (spend_name ) is not None :
2801- self .mempool_manager .remove_seen (spend_name )
2802- return MempoolInclusionStatus .SUCCESS , None
2803- if self .mempool_manager .peak is None :
2804- return MempoolInclusionStatus .FAILED , Err .MEMPOOL_NOT_INITIALIZED
2805- info = await self .mempool_manager .add_spend_bundle (
2806- transaction , cost_result , spend_name , self .mempool_manager .peak .height
2807- )
2808- status = info .status
2809- error = info .error
2810- if status == MempoolInclusionStatus .SUCCESS :
2811- self .log .debug (
2812- f"Added transaction to mempool: { spend_name } mempool size: "
2813- f"{ self .mempool_manager .mempool .total_mempool_cost ()} normalized "
2814- f"{ self .mempool_manager .mempool .total_mempool_cost () / 5000000 } "
2815- )
2795+ async with self .blockchain .priority_mutex .acquire (priority = BlockchainMutexPriority .low ):
2796+ if self .mempool_manager .get_spendbundle (spend_name ) is not None :
2797+ self .mempool_manager .remove_seen (spend_name )
2798+ return MempoolInclusionStatus .SUCCESS , None
2799+ if self .mempool_manager .peak is None :
2800+ return MempoolInclusionStatus .FAILED , Err .MEMPOOL_NOT_INITIALIZED
2801+ info = await self .mempool_manager .add_spend_bundle (
2802+ transaction , cost_result , spend_name , self .mempool_manager .peak .height
2803+ )
2804+ status = info .status
2805+ error = info .error
2806+ if status == MempoolInclusionStatus .SUCCESS :
2807+ self .log .debug (
2808+ f"Added transaction to mempool: { spend_name } mempool size: "
2809+ f"{ self .mempool_manager .mempool .total_mempool_cost ()} normalized "
2810+ f"{ self .mempool_manager .mempool .total_mempool_cost () / 5000000 } "
2811+ )
28162812
2817- # Only broadcast successful transactions, not pending ones. Otherwise it's a DOS
2818- # vector.
2819- mempool_item = self .mempool_manager .get_mempool_item (spend_name )
2820- assert mempool_item is not None
2821- await self .broadcast_removed_tx (info .removals )
2822- await self .broadcast_added_tx (mempool_item , current_peer = peer )
2813+ # Only broadcast successful transactions, not pending ones. Otherwise it's a DOS
2814+ # vector.
2815+ mempool_item = self .mempool_manager .get_mempool_item (spend_name )
2816+ assert mempool_item is not None
2817+ await self .broadcast_removed_tx (info .removals )
2818+ await self .broadcast_added_tx (mempool_item , current_peer = peer )
28232819
2824- if self .simulator_transaction_callback is not None : # callback
2825- await self .simulator_transaction_callback (spend_name )
2820+ if self .simulator_transaction_callback is not None : # callback
2821+ await self .simulator_transaction_callback (spend_name )
28262822
2827- else :
2828- self .mempool_manager .remove_seen (spend_name )
2829- self .log .debug (f"Wasn't able to add transaction with id { spend_name } , status { status } error: { error } " )
2823+ else :
2824+ self .mempool_manager .remove_seen (spend_name )
2825+ self .log .debug (f"Wasn't able to add transaction with id { spend_name } , status { status } error: { error } " )
28302826 return status , error
28312827
28322828 async def broadcast_added_tx (
0 commit comments