@@ -23,6 +23,7 @@ use ckb_light_client_lib::{
2323} ;
2424
2525use ckb_chain_spec:: consensus:: Consensus ;
26+ use ckb_constant:: hardfork:: { mainnet, testnet} ;
2627use ckb_jsonrpc_types:: {
2728 BlockView , EstimateCycles , HeaderView , JsonBytes , NodeAddress , RemoteNodeProtocol , Transaction ,
2829 Uint32 ,
@@ -804,13 +805,32 @@ impl NetRpc for NetRpcImpl {
804805
805806impl TransactionRpc for TransactionRpcImpl {
806807 fn send_transaction ( & self , tx : Transaction ) -> Result < H256 > {
808+ // Check sync status: reject if local tip hasn't passed the latest hardfork activation epoch
809+ let local_tip_header = self . swc . storage ( ) . get_last_state ( ) . 1 . into_view ( ) ;
810+ let local_tip_epoch = local_tip_header. epoch ( ) . number ( ) ;
811+
812+ // Determine the required hardfork epoch based on network
813+ let required_hardfork_epoch = match self . consensus . id . as_str ( ) {
814+ mainnet:: CHAIN_SPEC_NAME => mainnet:: CKB2023_START_EPOCH ,
815+ testnet:: CHAIN_SPEC_NAME => testnet:: CKB2023_START_EPOCH ,
816+ _ => 0 , // For other networks (dev/integration tests), no hardfork check
817+ } ;
818+
819+ if local_tip_epoch < required_hardfork_epoch {
820+ return Err ( Error :: invalid_params ( format ! (
821+ "light client is not synced past hardfork: local tip epoch {} < required hardfork epoch {}" ,
822+ local_tip_epoch,
823+ required_hardfork_epoch
824+ ) ) ) ;
825+ }
826+
807827 let tx: packed:: Transaction = tx. into ( ) ;
808828 let tx = tx. into_view ( ) ;
809829 let cycles = verify_tx (
810830 tx. clone ( ) ,
811831 & self . swc ,
812832 Arc :: clone ( & self . consensus ) ,
813- & self . swc . storage ( ) . get_last_state ( ) . 1 . into_view ( ) ,
833+ & local_tip_header ,
814834 )
815835 . map_err ( |e| Error :: invalid_params ( format ! ( "invalid transaction: {:?}" , e) ) ) ?;
816836 self . swc
0 commit comments