Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Use a more typesafe approach for managing indexed data #5503

Closed
wants to merge 33 commits into from

Conversation

tifecool
Copy link
Contributor

My attempt to resolve issue: paritytech/polkadot-sdk#978

Currently incomplete, having an error at polkadot-erasure-coding preventing me from testing, was hoping to get some advice and confirmation that I'm going about this the right way!

@tifecool
Copy link
Contributor Author

@eskimor

Copy link
Member

@eskimor eskimor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good at first pass.

impl From<usize> for ValidatorIndex {
fn from(n: usize) -> Self {
// can't panic, so need to truncate
let n = n.try_into().unwrap_or(u32::MAX);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

debug_assert would be good.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would I implement this?

primitives/src/v2/mod.rs Outdated Show resolved Hide resolved
runtime/parachains/src/inclusion/tests.rs Outdated Show resolved Hide resolved
@tifecool
Copy link
Contributor Author

Thanks so much for the review! @eskimor
Will keep at it and implement the suggested changes ❤️

@ordian
Copy link
Member

ordian commented May 18, 2022

I'd vote for creating our own type-wrapper for Vec instead of using a dependency. We don't seem to need most of its methods other than type-safe indexing, which can be implemented easily as pointed out in paritytech/polkadot-sdk#978.

As a side note, please revert unrelated changes.

@tifecool
Copy link
Contributor Author

tifecool commented May 19, 2022

I'd vote for creating our own type-wrapper for Vec instead of using a dependency. We don't seem to need most of its methods other than type-safe indexing, which can be implemented easily as pointed out in #2403 (comment).

Might need a bit of assistance/step through with this, but I think I have an idea of how to implement the change. Also, could I get help with why the checks are failing? Working on it

As a side note, please revert unrelated changes.

Which changes?

@paritytech-ci paritytech-ci requested review from a team May 19, 2022 22:54
@tifecool
Copy link
Contributor Author

tifecool commented May 19, 2022

Not the best at git. Apologies for the numerous pushes

}
}

impl From<usize> for ValidatorIndex {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need an impl for From<usize> if it's not guaranteed to be ok? Wouldn't a From<u32> not make more sense and leave it to the user to decide what to do on errors instead of generating a garbage ValidatorIndex? TryFrom<usize> and From<u32> seem more reasonable to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While working on this, the error:

the trait bound `K: From<usize>` is not satisfied
    --> primitives/src/v2/mod.rs:1616:17
     |
1616 | #[derive(Clone, RuntimeDebug)]
     |                 ^^^^^^^^^^^^ the trait `From<usize>` is not implemented for `K`

came up. This is why I likely implemented the From<usize> trait.

@paritytech-ci paritytech-ci requested a review from a team May 20, 2022 11:15
@@ -631,10 +632,10 @@ mod tests {
Sr25519Keyring::Bob,
Sr25519Keyring::Charlie,
]),
validator_groups: vec![
validator_groups: TypeVec::from(vec![
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should consider adding a custom macro that resembles the ergonomy of vec![..]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't write macros.

@paritytech-ci paritytech-ci requested a review from a team May 20, 2022 11:22
primitives/src/v2/mod.rs Outdated Show resolved Hide resolved
primitives/src/v2/mod.rs Outdated Show resolved Hide resolved
}
}

impl<K: From<usize>, V: Clone> From<Vec<V>> for TypeVec<K, V> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
impl<K: From<usize>, V: Clone> From<Vec<V>> for TypeVec<K, V> {
impl<K: From<usize>, V: Clone, I: IntoIterator<Item=V>> From<I> for TypeVec<K, V> {

type Identity = ();

fn type_info() -> Type {
todo!()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Must be fixed before merge

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not quite sure how to implement this trait.

Copy link
Contributor

@drahnr drahnr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your contribution and the time invested! The direction of the impl is definitely something we want rather sooner than later 👍

Though, I am not sure the chosen crate is the best choice. Having a fallback of u32::MAX is not necessarily a good thing when values are out of bounds when the only reason to have those bounds is the chosen crate to require From<usize> to be implemented. I am aware that practically speaking this should never happen, I am just very reluctanct to introduce a future footgun.

fn from(vec: Vec<V>) -> Self {
let mut type_vec: TypeVec<K, V> = TypeVec::new();
for value in vec.into_iter() {
type_vec.0.push(value)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a very inefficient impl considering that TiVec impls From<Vec<T>>

#[cfg(feature = "std")]
impl<K: From<usize>, V: Clone> MallocSizeOf for TypeVec<K, V> {
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

incorrect, should delegate to Vec impl

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Attempting this is causing issues.

Copy link
Contributor Author

@tifecool tifecool May 20, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#[cfg(feature = "std")]
has to be implemented in numerous places to trait bound generic type V

Copy link
Contributor Author

@tifecool tifecool May 20, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Attempted implementation:

#[cfg(feature = "std")]
impl<K: From<usize>, V: Clone> MallocSizeOf for TypeVec<K, V> {
	fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
		self.to_vec().size_of(ops)
	}
}

0
}
fn constant_size() -> Option<usize> {
Some(0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

incorrect, shouldn't be implemented

frame_election_provider_support::ElectionDataProvider
<Self as pallet_election_provider_multi_phase::Config>::DataProvider
as
frame_election_provider_support::ElectionDataProvider
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unrelated change (and probably doesn't pass rustfmt)

@@ -1394,9 +1422,11 @@ pub type CheckedMultiDisputeStatementSet = Vec<CheckedDisputeStatementSet>;
#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, TypeInfo)]
pub struct DisputeState<N = BlockNumber> {
/// A bitfield indicating all validators for the candidate.
pub validators_for: BitVec<u8, bitvec::order::Lsb0>, // one bit per validator.
pub validators_for: BitVec<u8, bitvec::order::Lsb0>,
// one bit per validator.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please revert unrelated formatting changes, we're using a specific nightly version for fmt

@@ -258,7 +258,7 @@ where
// construct trie mapping each chunk's index to its hash.
{
let mut trie = TrieDBMut::new(&mut trie_storage, &mut root);
for (i, chunk) in chunks.as_ref().iter().enumerate() {
for (i, chunk) in chunks.iter().enumerate() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unrelated change

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was getting this error:

error[E0282]: type annotations needed
   --> erasure-coding/src/lib.rs:261:28
    |
261 |         for (i, chunk) in chunks.as_ref().iter().enumerate() {
    |                           -------^^^^^^--
    |                           |      |
    |                           |      cannot infer type for type parameter `T` declared on the trait `AsRef`
    |                           this method call resolves to `&T`
    |
    = note: type must be known at this point

And on debugging saw the as_ref() made no difference to the object.

@paritytech-ci paritytech-ci requested a review from a team May 20, 2022 13:50
tifecool and others added 2 commits May 20, 2022 19:03
@tifecool
Copy link
Contributor Author

Going to reattempt this from scratch

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants