Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove support for the changes trie #2034

Merged
merged 2 commits into from
Feb 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 13 additions & 37 deletions src/executor/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -446,9 +446,6 @@ pub enum HostVm {
/// Need to provide the trie root of the storage.
#[from]
ExternalStorageRoot(ExternalStorageRoot),
/// Need to provide the trie root of the changes trie.
#[from]
ExternalStorageChangesRoot(ExternalStorageChangesRoot),
/// Need to provide the storage key that follows a specific one.
#[from]
ExternalStorageNextKey(ExternalStorageNextKey),
Expand Down Expand Up @@ -500,7 +497,6 @@ impl HostVm {
HostVm::ExternalStorageAppend(inner) => inner.inner.into_prototype(),
HostVm::ExternalStorageClearPrefix(inner) => inner.inner.into_prototype(),
HostVm::ExternalStorageRoot(inner) => inner.inner.into_prototype(),
HostVm::ExternalStorageChangesRoot(inner) => inner.inner.into_prototype(),
HostVm::ExternalStorageNextKey(inner) => inner.inner.into_prototype(),
HostVm::ExternalOffchainStorageSet(inner) => inner.inner.into_prototype(),
HostVm::CallRuntimeVersion(inner) => inner.inner.into_prototype(),
Expand Down Expand Up @@ -931,8 +927,19 @@ impl ReadyToRun {
}
}
HostFunction::ext_storage_changes_root_version_1 => {
// TODO: there's a parameter
HostVm::ExternalStorageChangesRoot(ExternalStorageChangesRoot { inner: self.inner })
// The changes trie is an obsolete attempt at having a second trie containing, for
// each storage item, the latest block height where this item has been modified.
// When this function returns `None`, it indicates that the changes trie is
// disabled. While this function used to be called by the runtimes of
// Westend/Polkadot/Kusama (and maybe others), it has never returned anything else
// but `None`. The entire changes trie mechanism was ultimately removed in
// October 2021.
// This function is no longer called by recent runtimes, but must be preserved for
// backwards compatibility.
self.inner.alloc_write_and_return_pointer_size(
HostFunction::ext_storage_changes_root_version_1.name(),
iter::once(&[0][..]),
)
}
HostFunction::ext_storage_next_key_version_1 => {
let (key_ptr, key_size) = expect_pointer_size_raw!(0);
Expand Down Expand Up @@ -1996,37 +2003,6 @@ impl fmt::Debug for ExternalStorageRoot {
}
}

/// Must provide the trie root hash of the changes trie.
pub struct ExternalStorageChangesRoot {
inner: Inner,
}

impl ExternalStorageChangesRoot {
/// Writes the trie root hash to the Wasm VM and prepares it for resume.
// TODO: document why it can be `None`
pub fn resume(self, hash: Option<&[u8; 32]>) -> HostVm {
if let Some(hash) = hash {
// Writing the `Some` of the SCALE-encoded `Option`.
self.inner.alloc_write_and_return_pointer_size(
HostFunction::ext_storage_changes_root_version_1.name(),
iter::once(&[1][..]).chain(iter::once(&hash[..])),
)
} else {
// Writing a SCALE-encoded `None`.
self.inner.alloc_write_and_return_pointer_size(
HostFunction::ext_storage_changes_root_version_1.name(),
iter::once(&[0][..]),
)
}
}
}

impl fmt::Debug for ExternalStorageChangesRoot {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("ExternalStorageChangesRoot").finish()
}
}

/// Must provide the storage key that follows, in lexicographic order, a specific one.
pub struct ExternalStorageNextKey {
inner: Inner,
Expand Down
29 changes: 6 additions & 23 deletions src/executor/runtime_host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,12 +196,12 @@ impl StorageGet {
/// Returns the key whose value must be passed to [`StorageGet::inject_value`].
pub fn key(&'_ self) -> impl Iterator<Item = impl AsRef<[u8]> + '_> + '_ {
match &self.inner.vm {
host::HostVm::ExternalStorageGet(req) => either::Left(iter::once(either::Left(
either::Left(either::Left(req.key())),
))),
host::HostVm::ExternalStorageAppend(req) => either::Left(iter::once(either::Left(
either::Left(either::Right(req.key())),
))),
host::HostVm::ExternalStorageGet(req) => {
either::Left(iter::once(either::Left(either::Left(req.key()))))
}
host::HostVm::ExternalStorageAppend(req) => {
either::Left(iter::once(either::Left(either::Right(req.key()))))
}

host::HostVm::ExternalStorageRoot(_) => {
if let calculate_root::RootMerkleValueCalculation::StorageValue(value_request) =
Expand All @@ -214,10 +214,6 @@ impl StorageGet {
}
}

host::HostVm::ExternalStorageChangesRoot(_) => either::Left(iter::once(either::Left(
either::Right(&b":changes_trie"[..]),
))),

// We only create a `StorageGet` if the state is one of the above.
_ => unreachable!(),
}
Expand Down Expand Up @@ -270,14 +266,6 @@ impl StorageGet {
panic!()
}
}
host::HostVm::ExternalStorageChangesRoot(req) => {
if value.is_none() {
self.inner.vm = req.resume(None);
} else {
// TODO: this is probably one of the most complicated things to implement
todo!()
}
}

// We only create a `StorageGet` if the state is one of the above.
_ => unreachable!(),
Expand Down Expand Up @@ -681,11 +669,6 @@ impl Inner {
}
}

host::HostVm::ExternalStorageChangesRoot(req) => {
self.vm = req.into();
return RuntimeHostVm::StorageGet(StorageGet { inner: self });
}

host::HostVm::ExternalStorageNextKey(req) => {
self.vm = req.into();
return RuntimeHostVm::NextKey(NextKey {
Expand Down
107 changes: 2 additions & 105 deletions src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,6 @@ impl<'a> DigestRef<'a> {
aura_predigest_index = Some(item_num);
}
DigestItem::AuraPreDigest(_) => return Err(Error::MultipleAuraPreRuntimeDigests),
DigestItem::ChangesTrieRoot(_) => {}
DigestItem::AuraConsensus(_) => {}
DigestItem::BabePreDigest(_) if babe_predigest_index.is_none() => {
babe_predigest_index = Some(item_num);
Expand Down Expand Up @@ -635,9 +634,7 @@ impl<'a> DigestRef<'a> {
has_runtime_environment_updated = true;
}
DigestItem::BabeSeal(_) => return Err(Error::SealIsntLastItem),
DigestItem::ChangesTrieSignal(_)
| DigestItem::Beefy { .. }
| DigestItem::PolkadotParachain { .. } => {}
DigestItem::Beefy { .. } | DigestItem::PolkadotParachain { .. } => {}
}
}

Expand Down Expand Up @@ -684,7 +681,6 @@ impl<'a> DigestRef<'a> {
DigestItemRef::AuraPreDigest(_) => {
return Err(Error::MultipleAuraPreRuntimeDigests)
}
DigestItemRef::ChangesTrieRoot(_) => {}
DigestItemRef::AuraConsensus(_) => {}
DigestItemRef::BabePreDigest(_) if babe_predigest_index.is_none() => {
babe_predigest_index = Some(item_num);
Expand Down Expand Up @@ -728,9 +724,7 @@ impl<'a> DigestRef<'a> {
has_runtime_environment_updated = true;
}
DigestItemRef::BabeSeal(_) => return Err(Error::SealIsntLastItem),
DigestItemRef::ChangesTrieSignal(_)
| DigestItemRef::Beefy { .. }
| DigestItemRef::PolkadotParachain { .. } => {}
DigestItemRef::Beefy { .. } | DigestItemRef::PolkadotParachain { .. } => {}
}
}

Expand Down Expand Up @@ -961,9 +955,6 @@ pub enum DigestItemRef<'a> {

GrandpaConsensus(GrandpaConsensusLogRef<'a>),

ChangesTrieRoot(&'a [u8; 32]),
ChangesTrieSignal(ChangesTrieSignal),

/// Item related to the BEEFY algorithm (Mountain Merkle Ranges). Allows proving that a block
/// is a child of another.
Beefy {
Expand Down Expand Up @@ -1096,27 +1087,6 @@ impl<'a> DigestItemRef<'a> {
ret.extend_from_slice(seal);
iter::once(ret)
}
DigestItemRef::ChangesTrieSignal(ref changes) => {
let mut ret = vec![7];
match changes {
ChangesTrieSignal::NewConfiguration(Some(cfg)) => {
ret.extend_from_slice(&[0]);
ret.extend_from_slice(&[1]);
ret.extend_from_slice(&cfg.digest_interval.to_le_bytes());
ret.extend_from_slice(&cfg.digest_levels.to_le_bytes());
}
ChangesTrieSignal::NewConfiguration(None) => {
ret.extend_from_slice(&[0]);
ret.extend_from_slice(&[0]);
}
}
iter::once(ret)
}
DigestItemRef::ChangesTrieRoot(data) => {
let mut ret = vec![2];
ret.extend_from_slice(data);
iter::once(ret)
}
DigestItemRef::Beefy { opaque } => {
let mut ret = vec![4];
ret.extend_from_slice(b"BEEF");
Expand Down Expand Up @@ -1146,8 +1116,6 @@ impl<'a> From<&'a DigestItem> for DigestItemRef<'a> {
DigestItem::BabeConsensus(v) => DigestItemRef::BabeConsensus(v.into()),
DigestItem::BabeSeal(v) => DigestItemRef::BabeSeal(v),
DigestItem::GrandpaConsensus(v) => DigestItemRef::GrandpaConsensus(v.into()),
DigestItem::ChangesTrieRoot(v) => DigestItemRef::ChangesTrieRoot(v),
DigestItem::ChangesTrieSignal(v) => DigestItemRef::ChangesTrieSignal(v.clone()),
DigestItem::Beefy { opaque } => DigestItemRef::Beefy { opaque: &*opaque },
DigestItem::PolkadotParachain { opaque } => {
DigestItemRef::PolkadotParachain { opaque: &*opaque }
Expand All @@ -1172,9 +1140,6 @@ pub enum DigestItem {

GrandpaConsensus(GrandpaConsensusLog),

ChangesTrieRoot([u8; 32]),
ChangesTrieSignal(ChangesTrieSignal),

/// See [`DigestItemRef::Beefy`].
Beefy {
/// Smoldot doesn't interpret the content of the log item at the moment.
Expand Down Expand Up @@ -1210,8 +1175,6 @@ impl<'a> From<DigestItemRef<'a>> for DigestItem {
DigestItem::BabeSeal(seal)
}
DigestItemRef::GrandpaConsensus(v) => DigestItem::GrandpaConsensus(v.into()),
DigestItemRef::ChangesTrieRoot(v) => DigestItem::ChangesTrieRoot(*v),
DigestItemRef::ChangesTrieSignal(v) => DigestItem::ChangesTrieSignal(v),
DigestItemRef::Beefy { opaque } => DigestItem::Beefy {
opaque: opaque.to_vec(),
},
Expand All @@ -1223,42 +1186,6 @@ impl<'a> From<DigestItemRef<'a>> for DigestItem {
}
}

/// Available changes trie signals.
// TODO: review documentation
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum ChangesTrieSignal {
/// New changes trie configuration is enacted, starting from **next block**.
///
/// The block that emits this signal will contain changes trie (CT) that covers
/// blocks range [BEGIN; current block], where BEGIN is (order matters):
/// - LAST_TOP_LEVEL_DIGEST_BLOCK+1 if top level digest CT has ever been created
/// using current configuration AND the last top level digest CT has been created
/// at block LAST_TOP_LEVEL_DIGEST_BLOCK;
/// - LAST_CONFIGURATION_CHANGE_BLOCK+1 if there has been CT configuration change
/// before and the last configuration change happened at block
/// LAST_CONFIGURATION_CHANGE_BLOCK;
/// - 1 otherwise.
NewConfiguration(Option<ChangesTrieConfiguration>),
}

/// Substrate changes trie configuration.
// TODO: review documentation
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ChangesTrieConfiguration {
/// Interval (in blocks) at which level1-digests are created. Digests are not
/// created when this is less or equal to 1.
pub digest_interval: u32,

/// Maximal number of digest levels in hierarchy. 0 means that digests are not
/// created at all (even level1 digests). 1 means only level1-digests are created.
/// 2 means that every digest_interval^2 there will be a level2-digest, and so on.
/// Please ensure that maximum digest interval (i.e. digest_interval^digest_levels)
/// is within `u32` limits. Otherwise you'll never see digests covering such intervals
/// && maximal digests interval will be truncated to the last interval that fits
/// `u32` limits.
pub digest_levels: u32,
}

/// Decodes a single digest log item. On success, returns the item and the data that remains
/// after the item.
fn decode_item(mut slice: &[u8]) -> Result<(DigestItemRef, &[u8]), Error> {
Expand Down Expand Up @@ -1288,36 +1215,6 @@ fn decode_item(mut slice: &[u8]) -> Result<(DigestItemRef, &[u8]), Error> {
let item = decode_item_from_parts(index, engine_id, content)?;
Ok((item, slice))
}
2 => {
if slice.len() < 32 {
return Err(Error::TooShort);
}

let hash: &[u8; 32] = TryFrom::try_from(&slice[0..32]).unwrap();
slice = &slice[32..];
Ok((DigestItemRef::ChangesTrieRoot(hash), slice))
}
7 => {
let (slice, item) = nom::combinator::map(
nom::sequence::preceded(
nom::bytes::complete::tag(&[0u8]),
crate::util::nom_option_decode(nom::combinator::map(
nom::sequence::tuple((
nom::number::complete::le_u32,
nom::number::complete::le_u32,
)),
|(digest_interval, digest_levels)| ChangesTrieConfiguration {
digest_interval,
digest_levels,
},
)),
),
ChangesTrieSignal::NewConfiguration,
)(slice)
.map_err(|_: nom::Err<nom::error::Error<&[u8]>>| Error::DigestItemDecodeError)?;

Ok((DigestItemRef::ChangesTrieSignal(item), slice))
}
8 => Ok((DigestItemRef::RuntimeEnvironmentUpdated, slice)),
ty => Err(Error::UnknownDigestLogType(ty)),
}
Expand Down