Skip to content

Commit 62b83cb

Browse files
feat: add client-side code for HOP promotion
1 parent 54354f2 commit 62b83cb

File tree

17 files changed

+495
-54
lines changed

17 files changed

+495
-54
lines changed

Cargo.lock

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,8 +277,8 @@ members = [
277277
"substrate/client/executor/polkavm",
278278
"substrate/client/executor/runtime-test",
279279
"substrate/client/executor/wasmtime",
280-
"substrate/client/informant",
281280
"substrate/client/hop",
281+
"substrate/client/informant",
282282
"substrate/client/keystore",
283283
"substrate/client/merkle-mountain-range",
284284
"substrate/client/merkle-mountain-range/rpc",
@@ -509,6 +509,7 @@ members = [
509509
"substrate/primitives/ethereum-standards",
510510
"substrate/primitives/externalities",
511511
"substrate/primitives/genesis-builder",
512+
"substrate/primitives/hop",
512513
"substrate/primitives/inherents",
513514
"substrate/primitives/io",
514515
"substrate/primitives/keyring",
@@ -1363,6 +1364,7 @@ sp-database = { path = "substrate/primitives/database", default-features = false
13631364
sp-debug-derive = { path = "substrate/primitives/debug-derive", default-features = false }
13641365
sp-externalities = { path = "substrate/primitives/externalities", default-features = false }
13651366
sp-genesis-builder = { path = "substrate/primitives/genesis-builder", default-features = false }
1367+
sp-hop = { path = "substrate/primitives/hop", default-features = false }
13661368
sp-inherents = { path = "substrate/primitives/inherents", default-features = false }
13671369
sp-io = { path = "substrate/primitives/io", default-features = false }
13681370
sp-keyring = { path = "substrate/primitives/keyring", default-features = false }

cumulus/polkadot-omni-node/lib/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ sp-consensus = { workspace = true, default-features = true }
7272
sp-consensus-aura = { workspace = true, default-features = true }
7373
sp-core = { workspace = true, default-features = true }
7474
sp-genesis-builder = { workspace = true }
75+
sp-hop = { workspace = true, default-features = true }
7576
sp-inherents = { workspace = true, default-features = true }
7677
sp-keystore = { workspace = true, default-features = true }
7778
sp-offchain = { workspace = true, default-features = true }

cumulus/polkadot-omni-node/lib/src/cli.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,13 @@ pub struct Cli<Config: CliConfig> {
266266
#[arg(long, default_value_t = 60)]
267267
pub hop_check_interval: u64,
268268

269+
/// How many blocks before expiry to start promoting entries to chain storage.
270+
///
271+
/// At 6 seconds per block, 1200 blocks is approximately 2 hours.
272+
/// Only relevant when `--enable-hop` is used.
273+
#[arg(long, default_value_t = 1200)]
274+
pub hop_buffer_blocks: u32,
275+
269276
/// Directory for HOP persistent data storage.
270277
///
271278
/// If not specified, defaults to `<chain-data-dir>/hop`.
@@ -325,6 +332,7 @@ impl<Config: CliConfig> Cli<Config> {
325332
hop_max_pool_size_mb: self.hop_max_pool_size,
326333
hop_retention_blocks: self.hop_retention_blocks,
327334
hop_check_interval: self.hop_check_interval,
335+
hop_buffer_blocks: self.hop_buffer_blocks,
328336
hop_data_dir: self.hop_data_dir.clone(),
329337
}
330338
}

cumulus/polkadot-omni-node/lib/src/common/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ use sc_offchain::OffchainWorkerApi;
3636
use serde::de::DeserializeOwned;
3737
use sp_api::{ApiExt, CallApiAt, ConstructRuntimeApi, Metadata};
3838
use sp_block_builder::BlockBuilder;
39+
use sp_hop::HopPromotionApi;
3940
use sp_runtime::{
4041
traits::{Block as BlockT, BlockNumber, Header as HeaderT, NumberFor},
4142
OpaqueExtrinsic,
@@ -76,6 +77,7 @@ pub trait NodeRuntimeApi<Block: BlockT>:
7677
+ GetParachainInfo<Block>
7778
+ TransactionStorageApi<Block>
7879
+ RelayParentOffsetApi<Block>
80+
+ HopPromotionApi<Block>
7981
+ Sized
8082
{
8183
}
@@ -91,6 +93,7 @@ impl<T, Block: BlockT> NodeRuntimeApi<Block> for T where
9193
+ CollectCollationInfo<Block>
9294
+ GetParachainInfo<Block>
9395
+ TransactionStorageApi<Block>
96+
+ HopPromotionApi<Block>
9497
{
9598
}
9699

@@ -149,6 +152,9 @@ pub struct NodeExtraArgs {
149152
/// HOP promotion check interval in seconds.
150153
pub hop_check_interval: u64,
151154

155+
/// How many blocks before expiry to start promoting entries to chain storage.
156+
pub hop_buffer_blocks: u32,
157+
152158
/// Directory for HOP persistent data storage.
153159
pub hop_data_dir: Option<PathBuf>,
154160
}

cumulus/polkadot-omni-node/lib/src/common/rpc.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,7 @@ where
8383
if let Some(hop_pool) = hop_pool {
8484
use sc_hop::{HopApiServer, HopRpcServer, NoopVerifier};
8585
module.merge(
86-
HopRpcServer::new(hop_pool, client.clone(), Arc::new(NoopVerifier))
87-
.into_rpc(),
86+
HopRpcServer::new(hop_pool, client.clone(), Arc::new(NoopVerifier)).into_rpc(),
8887
)?;
8988
}
9089
module.merge(Dev::new(client).into_rpc())?;

cumulus/polkadot-omni-node/lib/src/common/spec.rs

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -426,26 +426,18 @@ pub(crate) trait NodeSpec: BaseNodeSpec {
426426
parachain_config.database.path().map(|p| p.to_path_buf()),
427427
)?;
428428
if let Some(ref pool) = hop_pool {
429-
let task_pool = pool.clone();
429+
let promoter = sc_hop::try_build_promoter(&client, &transaction_pool);
430430
let task_client = client.clone();
431-
let check_interval = node_extra_args.hop_check_interval;
432-
task_manager.spawn_handle().spawn("hop-promotion", None, async move {
433-
loop {
434-
futures_timer::Delay::new(Duration::from_secs(check_interval)).await;
435-
let block = task_client
436-
.info()
437-
.best_number
438-
.saturated_into::<u32>();
439-
let freed = task_pool.cleanup_expired(block);
440-
if freed > 0 {
441-
log::info!(
442-
target: "hop",
443-
"Cleaned up expired HOP entries, freed {} bytes",
444-
freed,
445-
);
446-
}
447-
}
448-
});
431+
let best_block: Arc<dyn Fn() -> u32 + Send + Sync> =
432+
Arc::new(move || task_client.info().best_number.saturated_into::<u32>());
433+
let maintenance = sc_hop::HopMaintenanceTask::new(
434+
pool.clone(),
435+
promoter,
436+
best_block,
437+
node_extra_args.hop_buffer_blocks,
438+
node_extra_args.hop_check_interval,
439+
);
440+
task_manager.spawn_handle().spawn("hop-maintenance", None, maintenance.run());
449441
}
450442

451443
if parachain_config.offchain_worker.enabled {

cumulus/polkadot-omni-node/lib/src/fake_runtime_api/utils.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,16 @@ macro_rules! impl_node_runtime_apis {
252252
unimplemented!()
253253
}
254254
}
255+
256+
impl sp_hop::HopPromotionApi<$block> for $runtime {
257+
fn create_promotion_extrinsic(_: Vec<u8>) -> <$block as BlockT>::Extrinsic {
258+
unimplemented!()
259+
}
260+
261+
fn max_promotion_size() -> u32 {
262+
unimplemented!()
263+
}
264+
}
255265
}
256266
};
257267
}

substrate/client/hop/Cargo.toml

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,24 +13,31 @@ workspace = true
1313
[dependencies]
1414
# Core
1515
codec = { workspace = true, features = ["derive"] }
16+
hex = { workspace = true }
1617
parking_lot = { workspace = true }
18+
serde = { workspace = true, features = ["derive"] }
1719
thiserror = { workspace = true }
18-
hex = { workspace = true }
1920
tracing = { workspace = true }
20-
serde = { workspace = true, features = ["derive"] }
2121

2222
# CLI
2323
clap = { workspace = true, features = ["derive"] }
2424

2525
# RPC
26-
jsonrpsee = { workspace = true, features = ["server", "client", "macros"] }
26+
jsonrpsee = { workspace = true, features = ["client", "macros", "server"] }
27+
28+
# Async
29+
futures-timer = { workspace = true }
2730

2831
# Substrate primitives (client-side, always with std)
29-
sp-core = { workspace = true, default-features = true }
32+
polkadot-primitives = { workspace = true, default-features = true }
3033
sp-api = { workspace = true, default-features = true }
3134
sp-blockchain = { workspace = true, default-features = true }
35+
sp-core = { workspace = true, default-features = true }
36+
sp-hop = { workspace = true, default-features = true }
3237
sp-runtime = { workspace = true, default-features = true }
33-
polkadot-primitives = { workspace = true, default-features = true }
38+
39+
# Substrate client
40+
sc-transaction-pool-api = { workspace = true, default-features = true }
3441

3542
[dev-dependencies]
3643
tempfile = { workspace = true }

substrate/client/hop/src/cli.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,13 @@ pub struct HopParams {
5454
#[arg(long, default_value = "60")]
5555
pub hop_check_interval: u64,
5656

57+
/// How many blocks before expiry to start promoting entries to chain storage.
58+
///
59+
/// At 6 seconds per block, 1200 blocks is approximately 2 hours.
60+
/// Only relevant when `--enable-hop` is used.
61+
#[arg(long, default_value = "1200")]
62+
pub hop_buffer_blocks: u32,
63+
5764
/// Directory for HOP persistent data storage.
5865
///
5966
/// If not specified, defaults to `<chain-data-dir>/hop`.
@@ -68,6 +75,7 @@ impl Default for HopParams {
6875
hop_max_pool_size: (DEFAULT_MAX_POOL_SIZE / (1024 * 1024)), // Convert to MiB
6976
hop_retention_blocks: DEFAULT_RETENTION_BLOCKS, // 24 hours
7077
hop_check_interval: 60, // 1 minute
78+
hop_buffer_blocks: 1200, // ~2 hours
7179
hop_data_dir: None,
7280
}
7381
}

0 commit comments

Comments
 (0)