Skip to content

Commit 46e41ff

Browse files
committed
enhance PoT verification handling for development mode
1 parent 6977f11 commit 46e41ff

File tree

4 files changed

+133
-101
lines changed

4 files changed

+133
-101
lines changed

crates/subspace-malicious-operator/src/bin/subspace-malicious-operator.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ fn main() -> Result<(), Error> {
201201
&consensus_chain_config,
202202
false,
203203
&pot_external_entropy,
204+
false, // dev_no_farming: malicious operator doesn't use dev mode
204205
)
205206
.map_err(|error| {
206207
sc_service::Error::Other(format!("Failed to build a full subspace node: {error:?}"))

crates/subspace-node/src/commands/run.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ pub async fn run(run_options: RunOptions) -> Result<(), Error> {
140140
ChainSyncMode::Snap => true,
141141
},
142142
&pot_external_entropy,
143+
subspace_configuration.dev_no_farming,
143144
)
144145
.map_err(|error| {
145146
sc_service::Error::Other(format!(

crates/subspace-node/src/main.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ fn main() -> Result<(), Error> {
141141
&config,
142142
false,
143143
&derive_pot_external_entropy(&config, None)?,
144+
false, // dev_no_farming: utility commands don't need dev mode
144145
)?;
145146
Ok((
146147
cmd.run(client, import_queue).map_err(Error::SubstrateCli),
@@ -160,6 +161,7 @@ fn main() -> Result<(), Error> {
160161
&config,
161162
false,
162163
&derive_pot_external_entropy(&config, None)?,
164+
false, // dev_no_farming: utility commands don't need dev mode
163165
)?;
164166
Ok((
165167
cmd.run(client, config.database)
@@ -180,6 +182,7 @@ fn main() -> Result<(), Error> {
180182
&config,
181183
false,
182184
&derive_pot_external_entropy(&config, None)?,
185+
false, // dev_no_farming: utility commands don't need dev mode
183186
)?;
184187
Ok((
185188
cmd.run(client, config.chain_spec)
@@ -201,6 +204,7 @@ fn main() -> Result<(), Error> {
201204
&config,
202205
false,
203206
&derive_pot_external_entropy(&config, None)?,
207+
false, // dev_no_farming: utility commands don't need dev mode
204208
)?;
205209
Ok((
206210
cmd.run(client, import_queue).map_err(Error::SubstrateCli),
@@ -224,6 +228,7 @@ fn main() -> Result<(), Error> {
224228
&config,
225229
false,
226230
&derive_pot_external_entropy(&config, None)?,
231+
false, // dev_no_farming: utility commands don't need dev mode
227232
)?;
228233
Ok((
229234
cmd.run(client, backend, None).map_err(Error::SubstrateCli),
@@ -251,6 +256,7 @@ fn main() -> Result<(), Error> {
251256
&config,
252257
false,
253258
&derive_pot_external_entropy(&config, None)?,
259+
false, // dev_no_farming: benchmark commands don't need dev mode
254260
)?;
255261

256262
cmd.run(client)
@@ -262,6 +268,7 @@ fn main() -> Result<(), Error> {
262268
&config,
263269
false,
264270
&derive_pot_external_entropy(&config, None)?,
271+
false, // dev_no_farming: benchmark commands don't need dev mode
265272
)?;
266273
let db = backend.expose_db();
267274
let storage = backend.expose_storage();

crates/subspace-service/src/lib.rs

Lines changed: 124 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ struct SubspaceExtensionsFactory<PosTable, Client, DomainBlock> {
244244
pot_verifier: PotVerifier,
245245
domains_executor: Arc<sc_domains::RuntimeExecutor>,
246246
confirmation_depth_k: BlockNumber,
247+
dev_no_farming: bool,
247248
_pos_table: PhantomData<(PosTable, DomainBlock)>,
248249
}
249250

@@ -276,123 +277,139 @@ where
276277
let mut exts = Extensions::new();
277278
exts.register(KzgExtension::new(self.kzg.clone()));
278279
exts.register(PosExtension::new::<PosTable>());
279-
exts.register(PotExtension::new({
280-
let client = Arc::clone(&self.client);
281-
let pot_verifier = self.pot_verifier.clone();
282-
283-
Box::new(
284-
move |parent_hash, slot, proof_of_time, quick_verification| {
285-
let parent_hash = {
286-
let mut converted_parent_hash = Block::Hash::default();
287-
converted_parent_hash.as_mut().copy_from_slice(&parent_hash);
288-
converted_parent_hash
289-
};
290-
291-
let parent_header = match client.header(parent_hash) {
292-
Ok(Some(parent_header)) => parent_header,
293-
Ok(None) => {
294-
if quick_verification {
280+
281+
// In dev-no-farming mode, always accept PoT verification (bypass actual verification)
282+
if self.dev_no_farming {
283+
exts.register(PotExtension::new(Box::new(
284+
move |_parent_hash, _slot, _proof_of_time, _quick_verification| {
285+
// Always return true in dev mode - bypass PoT verification
286+
debug!(
287+
"🔧 Dev mode: bypassing PoT verification for slot {}, parent_hash: {:?}",
288+
_slot, _parent_hash
289+
);
290+
true
291+
},
292+
)));
293+
} else {
294+
// Production path: use actual PoT verification
295+
exts.register(PotExtension::new({
296+
let client = Arc::clone(&self.client);
297+
let pot_verifier = self.pot_verifier.clone();
298+
299+
Box::new(
300+
move |parent_hash, slot, proof_of_time, quick_verification| {
301+
let parent_hash = {
302+
let mut converted_parent_hash = Block::Hash::default();
303+
converted_parent_hash.as_mut().copy_from_slice(&parent_hash);
304+
converted_parent_hash
305+
};
306+
307+
let parent_header = match client.header(parent_hash) {
308+
Ok(Some(parent_header)) => parent_header,
309+
Ok(None) => {
310+
if quick_verification {
311+
error!(
312+
%parent_hash,
313+
"Header not found during proof of time verification"
314+
);
315+
316+
return false;
317+
} else {
318+
debug!(
319+
%parent_hash,
320+
"Header not found during proof of time verification"
321+
);
322+
323+
// This can only happen during special sync modes there are no other
324+
// cases where parent header may not be available, hence allow it
325+
return true;
326+
}
327+
}
328+
Err(error) => {
295329
error!(
330+
%error,
296331
%parent_hash,
297-
"Header not found during proof of time verification"
332+
"Failed to retrieve header during proof of time verification"
298333
);
299334

300335
return false;
301-
} else {
302-
debug!(
336+
}
337+
};
338+
339+
let parent_pre_digest = match extract_pre_digest(&parent_header) {
340+
Ok(parent_pre_digest) => parent_pre_digest,
341+
Err(error) => {
342+
error!(
343+
%error,
303344
%parent_hash,
304-
"Header not found during proof of time verification"
345+
parent_number = %parent_header.number(),
346+
"Failed to extract pre-digest from parent header during proof of \
347+
time verification, this must never happen"
305348
);
306349

307-
// This can only happen during special sync modes there are no other
308-
// cases where parent header may not be available, hence allow it
309-
return true;
350+
return false;
310351
}
311-
}
312-
Err(error) => {
313-
error!(
314-
%error,
315-
%parent_hash,
316-
"Failed to retrieve header during proof of time verification"
317-
);
318-
319-
return false;
320-
}
321-
};
322-
323-
let parent_pre_digest = match extract_pre_digest(&parent_header) {
324-
Ok(parent_pre_digest) => parent_pre_digest,
325-
Err(error) => {
326-
error!(
327-
%error,
328-
%parent_hash,
329-
parent_number = %parent_header.number(),
330-
"Failed to extract pre-digest from parent header during proof of \
331-
time verification, this must never happen"
332-
);
352+
};
333353

354+
let parent_slot = parent_pre_digest.slot();
355+
if slot <= *parent_slot {
334356
return false;
335357
}
336-
};
337-
338-
let parent_slot = parent_pre_digest.slot();
339-
if slot <= *parent_slot {
340-
return false;
341-
}
342358

343-
let pot_parameters = match client.runtime_api().pot_parameters(parent_hash) {
344-
Ok(pot_parameters) => pot_parameters,
345-
Err(error) => {
346-
debug!(
347-
%error,
348-
%parent_hash,
349-
parent_number = %parent_header.number(),
350-
"Failed to retrieve proof of time parameters during proof of time \
351-
verification"
352-
);
359+
let pot_parameters = match client.runtime_api().pot_parameters(parent_hash) {
360+
Ok(pot_parameters) => pot_parameters,
361+
Err(error) => {
362+
debug!(
363+
%error,
364+
%parent_hash,
365+
parent_number = %parent_header.number(),
366+
"Failed to retrieve proof of time parameters during proof of time \
367+
verification"
368+
);
353369

354-
return false;
355-
}
356-
};
370+
return false;
371+
}
372+
};
357373

358-
let pot_input = if parent_header.number().is_zero() {
359-
PotNextSlotInput {
360-
slot: parent_slot + Slot::from(1),
361-
slot_iterations: pot_parameters.slot_iterations(),
362-
seed: pot_verifier.genesis_seed(),
374+
let pot_input = if parent_header.number().is_zero() {
375+
PotNextSlotInput {
376+
slot: parent_slot + Slot::from(1),
377+
slot_iterations: pot_parameters.slot_iterations(),
378+
seed: pot_verifier.genesis_seed(),
379+
}
380+
} else {
381+
let pot_info = parent_pre_digest.pot_info();
382+
383+
PotNextSlotInput::derive(
384+
pot_parameters.slot_iterations(),
385+
parent_slot,
386+
pot_info.proof_of_time(),
387+
&pot_parameters.next_parameters_change(),
388+
)
389+
};
390+
391+
// Ensure proof of time and future proof of time included in upcoming block are
392+
// valid
393+
394+
if quick_verification {
395+
pot_verifier.try_is_output_valid(
396+
pot_input,
397+
Slot::from(slot) - parent_slot,
398+
proof_of_time,
399+
pot_parameters.next_parameters_change(),
400+
)
401+
} else {
402+
pot_verifier.is_output_valid(
403+
pot_input,
404+
Slot::from(slot) - parent_slot,
405+
proof_of_time,
406+
pot_parameters.next_parameters_change(),
407+
)
363408
}
364-
} else {
365-
let pot_info = parent_pre_digest.pot_info();
366-
367-
PotNextSlotInput::derive(
368-
pot_parameters.slot_iterations(),
369-
parent_slot,
370-
pot_info.proof_of_time(),
371-
&pot_parameters.next_parameters_change(),
372-
)
373-
};
374-
375-
// Ensure proof of time and future proof of time included in upcoming block are
376-
// valid
377-
378-
if quick_verification {
379-
pot_verifier.try_is_output_valid(
380-
pot_input,
381-
Slot::from(slot) - parent_slot,
382-
proof_of_time,
383-
pot_parameters.next_parameters_change(),
384-
)
385-
} else {
386-
pot_verifier.is_output_valid(
387-
pot_input,
388-
Slot::from(slot) - parent_slot,
389-
proof_of_time,
390-
pot_parameters.next_parameters_change(),
391-
)
392-
}
393-
},
394-
)
395-
}));
409+
},
410+
)
411+
}));
412+
}
396413

397414
exts.register(FraudProofExtension::new(Arc::new(
398415
FraudProofHostFunctionsImpl::<_, _, DomainBlock, _, _>::new(
@@ -472,6 +489,7 @@ pub fn new_partial<PosTable, RuntimeApi>(
472489
// TODO: Replace with check for `ChainSyncMode` once we get rid of ^ `Configuration`
473490
snap_sync: bool,
474491
pot_external_entropy: &[u8],
492+
dev_no_farming: bool,
475493
) -> Result<PartialComponents<RuntimeApi>, ServiceError>
476494
where
477495
PosTable: Table,
@@ -557,6 +575,10 @@ where
557575
// ensure the extracted confirmation_depth matches the one from runtime
558576
assert_eq!(confirmation_depth_k, chain_constants.confirmation_depth_k());
559577

578+
if dev_no_farming {
579+
warn!("🔧 Dev mode: Registering PoT bypass extension for bundle validation");
580+
}
581+
560582
client
561583
.execution_extensions()
562584
.set_extensions_factory(SubspaceExtensionsFactory::<PosTable, _, DomainBlock> {
@@ -566,6 +588,7 @@ where
566588
domains_executor: Arc::new(domains_executor),
567589
backend: backend.clone(),
568590
confirmation_depth_k: chain_constants.confirmation_depth_k(),
591+
dev_no_farming,
569592
_pos_table: PhantomData,
570593
});
571594

0 commit comments

Comments
 (0)