Skip to content

Commit

Permalink
Merge branch 'master' into davidk/disable_host_functions_not_in_revive
Browse files Browse the repository at this point in the history
  • Loading branch information
davidk-pt authored Dec 11, 2024
2 parents fc2fc69 + da2dd9b commit 11cff39
Show file tree
Hide file tree
Showing 53 changed files with 1,705 additions and 457 deletions.
247 changes: 221 additions & 26 deletions Cargo.lock

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -594,8 +594,7 @@ zero-prefixed-literal = { level = "allow", priority = 2 } # 00_1000_0
Inflector = { version = "0.11.4" }
aes-gcm = { version = "0.10" }
ahash = { version = "0.8.2" }
alloy-primitives = { version = "0.4.2", default-features = false }
alloy-sol-types = { version = "0.4.2", default-features = false }
alloy-core = { version = "0.8.15", default-features = false }
always-assert = { version = "0.1" }
anyhow = { version = "1.0.81", default-features = false }
approx = { version = "0.5.1" }
Expand Down
6 changes: 2 additions & 4 deletions bridges/snowbridge/pallets/inbound-queue/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ codec = { features = ["derive"], workspace = true }
scale-info = { features = ["derive"], workspace = true }
hex-literal = { optional = true, workspace = true, default-features = true }
log = { workspace = true }
alloy-primitives = { features = ["rlp"], workspace = true }
alloy-sol-types = { workspace = true }
alloy-core = { workspace = true, features = ["sol-types"] }

frame-benchmarking = { optional = true, workspace = true }
frame-support = { workspace = true }
Expand Down Expand Up @@ -49,8 +48,7 @@ hex-literal = { workspace = true, default-features = true }
[features]
default = ["std"]
std = [
"alloy-primitives/std",
"alloy-sol-types/std",
"alloy-core/std",
"codec/std",
"frame-benchmarking/std",
"frame-support/std",
Expand Down
7 changes: 3 additions & 4 deletions bridges/snowbridge/pallets/inbound-queue/src/envelope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ use snowbridge_core::{inbound::Log, ChannelId};
use sp_core::{RuntimeDebug, H160, H256};
use sp_std::prelude::*;

use alloy_primitives::B256;
use alloy_sol_types::{sol, SolEvent};
use alloy_core::{primitives::B256, sol, sol_types::SolEvent};

sol! {
event OutboundMessageAccepted(bytes32 indexed channel_id, uint64 nonce, bytes32 indexed message_id, bytes payload);
Expand Down Expand Up @@ -36,15 +35,15 @@ impl TryFrom<&Log> for Envelope {
fn try_from(log: &Log) -> Result<Self, Self::Error> {
let topics: Vec<B256> = log.topics.iter().map(|x| B256::from_slice(x.as_ref())).collect();

let event = OutboundMessageAccepted::decode_log(topics, &log.data, true)
let event = OutboundMessageAccepted::decode_raw_log(topics, &log.data, true)
.map_err(|_| EnvelopeDecodeError)?;

Ok(Self {
gateway: log.address,
channel_id: ChannelId::from(event.channel_id.as_ref()),
nonce: event.nonce,
message_id: H256::from(event.message_id.as_ref()),
payload: event.payload,
payload: event.payload.into(),
})
}
}
14 changes: 0 additions & 14 deletions bridges/snowbridge/pallets/inbound-queue/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,20 +248,6 @@ impl inbound_queue::Config for Test {
type AssetTransactor = SuccessfulTransactor;
}

pub fn last_events(n: usize) -> Vec<RuntimeEvent> {
frame_system::Pallet::<Test>::events()
.into_iter()
.rev()
.take(n)
.rev()
.map(|e| e.event)
.collect()
}

pub fn expect_events(e: Vec<RuntimeEvent>) {
assert_eq!(last_events(e.len()), e);
}

pub fn setup() {
System::set_block_number(1);
Balances::mint_into(
Expand Down
23 changes: 11 additions & 12 deletions bridges/snowbridge/pallets/inbound-queue/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use sp_keyring::Sr25519Keyring as Keyring;
use sp_runtime::DispatchError;
use sp_std::convert::From;

use crate::{Error, Event as InboundQueueEvent};
use crate::Error;

use crate::mock::*;

Expand All @@ -35,17 +35,16 @@ fn test_submit_happy_path() {
assert_eq!(Balances::balance(&channel_sovereign), initial_fund);

assert_ok!(InboundQueue::submit(origin.clone(), message.clone()));
expect_events(vec![InboundQueueEvent::MessageReceived {
channel_id: hex!("c173fac324158e77fb5840738a1a541f633cbec8884c6a601c567d2b376a0539")
.into(),
nonce: 1,
message_id: [
118, 166, 139, 182, 84, 52, 165, 189, 54, 14, 178, 73, 2, 228, 192, 97, 153, 201,
4, 75, 151, 15, 82, 6, 164, 187, 162, 133, 26, 183, 186, 126,
],
fee_burned: 110000000000,
}
.into()]);

let events = frame_system::Pallet::<Test>::events();
assert!(
events.iter().any(|event| matches!(
event.event,
RuntimeEvent::InboundQueue(Event::MessageReceived { nonce, ..})
if nonce == 1
)),
"no event emit."
);

let delivery_cost = InboundQueue::calculate_delivery_cost(message.encode().len() as u32);
assert!(
Expand Down
4 changes: 2 additions & 2 deletions cumulus/polkadot-omni-node/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ chain-spec-builder create --relay-chain <relay_chain_id> --para-id <id> -r <runt

### 3. Run Omni Node

And now with the generated chain spec we can start Omni Node like so:
And now with the generated chain spec we can start the node in development mode like so:

```bash
polkadot-omni-node --chain <chain_spec.json>
polkadot-omni-node --dev --chain <chain_spec.json>
```

## Useful links
Expand Down
11 changes: 8 additions & 3 deletions cumulus/polkadot-omni-node/lib/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,14 @@ pub struct Cli<Config: CliConfig> {

/// Start a dev node that produces a block each `dev_block_time` ms.
///
/// This is a dev option, and it won't result in starting or connecting to a parachain network.
/// The resulting node will work on its own, running the wasm blob and artificially producing
/// a block each `dev_block_time` ms, as if it was part of a parachain.
/// This is a dev option. It enables a manual sealing, meaning blocks are produced manually
/// rather than being part of an actual network consensus process. Using the option won't
/// result in starting or connecting to a parachain network. The resulting node will work on
/// its own, running the wasm blob and artificially producing a block each `dev_block_time` ms,
/// as if it was part of a parachain.
///
/// The `--dev` flag sets the `dev_block_time` to a default value of 3000ms unless explicitly
/// provided.
#[arg(long)]
pub dev_block_time: Option<u64>,

Expand Down
15 changes: 13 additions & 2 deletions cumulus/polkadot-omni-node/lib/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,13 @@ use cumulus_client_service::storage_proof_size::HostFunctions as ReclaimHostFunc
use cumulus_primitives_core::ParaId;
use frame_benchmarking_cli::{BenchmarkCmd, SUBSTRATE_REFERENCE_HARDWARE};
use log::info;
use sc_cli::{Result, SubstrateCli};
use sc_cli::{CliConfiguration, Result, SubstrateCli};
use sp_runtime::traits::AccountIdConversion;
#[cfg(feature = "runtime-benchmarks")]
use sp_runtime::traits::HashingFor;

const DEFAULT_DEV_BLOCK_TIME_MS: u64 = 3000;

/// Structure that can be used in order to provide customizers for different functionalities of the
/// node binary that is being built using this library.
pub struct RunConfig {
Expand Down Expand Up @@ -230,10 +232,19 @@ pub fn run<CliConfig: crate::cli::CliConfig>(cmd_config: RunConfig) -> Result<()
.ok_or("Could not find parachain extension in chain-spec.")?,
);

if cli.run.base.is_dev()? {
// Set default dev block time to 3000ms if not set.
// TODO: take block time from AURA config if set.
let dev_block_time = cli.dev_block_time.unwrap_or(DEFAULT_DEV_BLOCK_TIME_MS);
return node_spec
.start_manual_seal_node(config, para_id, dev_block_time)
.map_err(Into::into);
}

if let Some(dev_block_time) = cli.dev_block_time {
return node_spec
.start_manual_seal_node(config, para_id, dev_block_time)
.map_err(Into::into)
.map_err(Into::into);
}

// If Statemint (Statemine, Westmint, Rockmine) DB exists and we're using the
Expand Down
143 changes: 110 additions & 33 deletions polkadot/node/network/approval-distribution/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ impl Default for AggressionConfig {
fn default() -> Self {
AggressionConfig {
l1_threshold: Some(16),
l2_threshold: Some(28),
l2_threshold: Some(64),
resend_unfinalized_period: Some(8),
}
}
Expand Down Expand Up @@ -512,6 +512,8 @@ struct BlockEntry {
vrf_story: RelayVRFStory,
/// The block slot.
slot: Slot,
/// Backing off from re-sending messages to peers.
last_resent_at_block_number: Option<u32>,
}

impl BlockEntry {
Expand Down Expand Up @@ -878,6 +880,7 @@ impl State {
candidates_metadata: meta.candidates,
vrf_story: meta.vrf_story,
slot: meta.slot,
last_resent_at_block_number: None,
});

self.topologies.inc_session_refs(meta.session);
Expand Down Expand Up @@ -1317,6 +1320,33 @@ impl State {
self.enable_aggression(network_sender, Resend::No, metrics).await;
}

// When finality is lagging as a last resort nodes start sending the messages they have
// multiples times. This means it is safe to accept duplicate messages without punishing the
// peer and reduce the reputation and can end up banning the Peer, which in turn will create
// more no-shows.
fn accept_duplicates_from_validators(
blocks_by_number: &BTreeMap<BlockNumber, Vec<Hash>>,
topologies: &SessionGridTopologies,
aggression_config: &AggressionConfig,
entry: &BlockEntry,
peer: PeerId,
) -> bool {
let topology = topologies.get_topology(entry.session);
let min_age = blocks_by_number.iter().next().map(|(num, _)| num);
let max_age = blocks_by_number.iter().rev().next().map(|(num, _)| num);

// Return if we don't have at least 1 block.
let (min_age, max_age) = match (min_age, max_age) {
(Some(min), Some(max)) => (*min, *max),
_ => return false,
};

let age = max_age.saturating_sub(min_age);

aggression_config.should_trigger_aggression(age) &&
topology.map(|topology| topology.is_validator(&peer)).unwrap_or(false)
}

async fn import_and_circulate_assignment<A, N, RA, R>(
&mut self,
approval_voting_sender: &mut A,
Expand Down Expand Up @@ -1381,20 +1411,29 @@ impl State {
if peer_knowledge.contains(&message_subject, message_kind) {
// wasn't included before
if !peer_knowledge.received.insert(message_subject.clone(), message_kind) {
gum::debug!(
target: LOG_TARGET,
?peer_id,
?message_subject,
"Duplicate assignment",
);

modify_reputation(
&mut self.reputation,
network_sender,
if !Self::accept_duplicates_from_validators(
&self.blocks_by_number,
&self.topologies,
&self.aggression_config,
entry,
peer_id,
COST_DUPLICATE_MESSAGE,
)
.await;
) {
gum::debug!(
target: LOG_TARGET,
?peer_id,
?message_subject,
"Duplicate assignment",
);

modify_reputation(
&mut self.reputation,
network_sender,
peer_id,
COST_DUPLICATE_MESSAGE,
)
.await;
}

metrics.on_assignment_duplicate();
} else {
gum::trace!(
Expand Down Expand Up @@ -1710,6 +1749,9 @@ impl State {
assignments_knowledge_key: &Vec<(MessageSubject, MessageKind)>,
approval_knowledge_key: &(MessageSubject, MessageKind),
entry: &mut BlockEntry,
blocks_by_number: &BTreeMap<BlockNumber, Vec<Hash>>,
topologies: &SessionGridTopologies,
aggression_config: &AggressionConfig,
reputation: &mut ReputationAggregator,
peer_id: PeerId,
metrics: &Metrics,
Expand Down Expand Up @@ -1738,20 +1780,27 @@ impl State {
.received
.insert(approval_knowledge_key.0.clone(), approval_knowledge_key.1)
{
gum::trace!(
target: LOG_TARGET,
?peer_id,
?approval_knowledge_key,
"Duplicate approval",
);

modify_reputation(
reputation,
network_sender,
if !Self::accept_duplicates_from_validators(
blocks_by_number,
topologies,
aggression_config,
entry,
peer_id,
COST_DUPLICATE_MESSAGE,
)
.await;
) {
gum::trace!(
target: LOG_TARGET,
?peer_id,
?approval_knowledge_key,
"Duplicate approval",
);
modify_reputation(
reputation,
network_sender,
peer_id,
COST_DUPLICATE_MESSAGE,
)
.await;
}
metrics.on_approval_duplicate();
}
return false
Expand Down Expand Up @@ -1843,6 +1892,9 @@ impl State {
&assignments_knowledge_keys,
&approval_knwowledge_key,
entry,
&self.blocks_by_number,
&self.topologies,
&self.aggression_config,
&mut self.reputation,
peer_id,
metrics,
Expand Down Expand Up @@ -2253,18 +2305,43 @@ impl State {
&self.topologies,
|block_entry| {
let block_age = max_age - block_entry.number;
// We want to resend only for blocks of min_age, there is no point in
// resending for blocks newer than that, because we are just going to create load
// and not gain anything.
let diff_from_min_age = block_entry.number - min_age;

// We want to back-off on resending for blocks that have been resent recently, to
// give time for nodes to process all the extra messages, if we still have not
// finalized we are going to resend again after unfinalized_period * 2 since the
// last resend.
let blocks_since_last_sent = block_entry
.last_resent_at_block_number
.map(|last_resent_at_block_number| max_age - last_resent_at_block_number);

let can_resend_at_this_age = blocks_since_last_sent
.zip(config.resend_unfinalized_period)
.map(|(blocks_since_last_sent, unfinalized_period)| {
blocks_since_last_sent >= unfinalized_period * 2
})
.unwrap_or(true);

if resend == Resend::Yes &&
config
.resend_unfinalized_period
.as_ref()
.map_or(false, |p| block_age > 0 && block_age % p == 0)
{
config.resend_unfinalized_period.as_ref().map_or(false, |p| {
block_age > 0 &&
block_age % p == 0 && diff_from_min_age == 0 &&
can_resend_at_this_age
}) {
// Retry sending to all peers.
for (_, knowledge) in block_entry.known_by.iter_mut() {
knowledge.sent = Knowledge::default();
}

block_entry.last_resent_at_block_number = Some(max_age);
gum::debug!(
target: LOG_TARGET,
block_number = ?block_entry.number,
?max_age,
"Aggression enabled with resend for block",
);
true
} else {
false
Expand Down
Loading

0 comments on commit 11cff39

Please sign in to comment.