Validates the structural constraints on a [`SendBundleRequest`]. Returns `Ok(())` if all restrictions pass, or an RPC error describing the first violated constraint.
(
req: &SendBundleRequest,
current_block: u64,
)
| 90 | /// Returns `Ok(())` if all restrictions pass, or an RPC error describing the |
| 91 | /// first violated constraint. |
| 92 | fn validate_bundle_request( |
| 93 | req: &SendBundleRequest, |
| 94 | current_block: u64, |
| 95 | ) -> Result<(), ErrorObjectOwned> { |
| 96 | if req.txs.len() != 1 { |
| 97 | return Err(validation_err( |
| 98 | "invalid_tx_count", |
| 99 | format!("txs must contain exactly 1 transaction, got {}", req.txs.len()), |
| 100 | )); |
| 101 | } |
| 102 | |
| 103 | let now_ms = crate::transaction::unix_time_millis() as u64; |
| 104 | |
| 105 | if let Some(block_number) = req.block_number { |
| 106 | if block_number < current_block { |
| 107 | return Err(validation_err( |
| 108 | "block_number_past", |
| 109 | format!("blockNumber {block_number} is in the past (current {current_block})",), |
| 110 | )); |
| 111 | } |
| 112 | let max_block = current_block + MAX_BUNDLE_ADVANCE_BLOCKS; |
| 113 | if block_number > max_block { |
| 114 | return Err(validation_err( |
| 115 | "block_number_too_far", |
| 116 | format!( |
| 117 | "blockNumber {block_number} is too far ahead (max {max_block}, current {current_block})", |
| 118 | ), |
| 119 | )); |
| 120 | } |
| 121 | } |
| 122 | |
| 123 | if let Some(min_ts) = req.min_timestamp { |
| 124 | let max_allowed = now_ms + MAX_BUNDLE_ADVANCE_MILLIS; |
| 125 | if min_ts > max_allowed { |
| 126 | return Err(validation_err( |
| 127 | "min_timestamp_too_far", |
| 128 | format!("minTimestamp {min_ts}ms is too far ahead (max {max_allowed}ms)"), |
| 129 | )); |
| 130 | } |
| 131 | } |
| 132 | |
| 133 | if let Some(max_ts) = req.max_timestamp { |
| 134 | if max_ts < now_ms { |
| 135 | return Err(validation_err( |
| 136 | "max_timestamp_past", |
| 137 | format!("maxTimestamp {max_ts}ms is in the past (now {now_ms}ms)"), |
| 138 | )); |
| 139 | } |
| 140 | let max_allowed = now_ms + MAX_BUNDLE_ADVANCE_MILLIS; |
| 141 | if max_ts > max_allowed { |
| 142 | return Err(validation_err( |
| 143 | "max_timestamp_too_far", |
| 144 | format!("maxTimestamp {max_ts}ms is too far ahead (max {max_allowed}ms)"), |
| 145 | )); |
| 146 | } |
| 147 | } |
| 148 | |
| 149 | if let (Some(min_ts), Some(max_ts)) = (req.min_timestamp, req.max_timestamp) |