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

Change rlp to alloy-rlp #46

Merged
merged 25 commits into from
Nov 29, 2023
Merged

Change rlp to alloy-rlp #46

merged 25 commits into from
Nov 29, 2023

Conversation

armaganyildirak
Copy link
Member

Try to change rlp to alloy-rlp.

@armaganyildirak armaganyildirak marked this pull request as ready for review August 17, 2023 20:14
@armaganyildirak armaganyildirak changed the title [WIP] change rlp to alloy-rlp Change rlp to alloy-rlp Aug 17, 2023
Copy link
Collaborator

@divagant-martian divagant-martian left a comment

Choose a reason for hiding this comment

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

I'm starting to review this.

Great job in getting this done and making all the tests pass.
Since I'm just starting to get familiar with alloy-rlp it will take me a bit to give a proper review. For now, one main comment:

Changes as they are right now generate way too many vector allocations that are freed almost immediately. This is less than ideal. We should try to reduce the number of calls to to_vec as much as possible. This copies the data to a new vector, and most of the time, this is used to move the data to yet another final location. This includes avoiding when possible calls to alloy_rlp::encode. I left an example of avoiding these two in the review.

Following this line of thought, since this is a breaking change: the Encodable and Decodable traits are now different (from rlp to alloy-rlp) we have now the freedom to change the public api since it's no longer an "implementation detail" change. I'd like us to consider these two changes:

pub fn get(&self, key: impl AsRef<[u8]>) -> Option<impl AsRef<[u8]> + '_> 

and

pub fn get_raw_rlp(&self, key: impl AsRef<[u8]>) -> Option<impl AsRef<[u8]> + '_> 

I think these two are good part of the sources of temporary vec allocations. I have not checked if this works or how ergonomic it is but we should give it a go in pro of performance.

Unrelated comment, but alloy_rlp already implements encoding and decoding for the ip/ipv4/ipv6 types. We should check if the default implementation is compatible and use that instead of relaying on encoding of the octects ourselves if possible

src/builder.rs Outdated Show resolved Hide resolved
src/builder.rs Outdated Show resolved Hide resolved
@divagant-martian
Copy link
Collaborator

hi @armaganyildirak is this ready for review again? when it is, can you hit the re-request review button so that I get notified?

Copy link
Collaborator

@divagant-martian divagant-martian left a comment

Choose a reason for hiding this comment

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

I realized get does not need to change. By updating that function a lot of changes will be triggered that revert the need to use for example as_slice in a good couple of places

Also you can obtain a Bytes from a BytesMut using freeze(). There is no need to copy there.

Note that I've signaled just some of the places where changes can be improved

Cargo.toml Outdated Show resolved Hide resolved
src/builder.rs Outdated Show resolved Hide resolved
src/keys/ed25519.rs Outdated Show resolved Hide resolved
src/keys/k256_key.rs Outdated Show resolved Hide resolved
src/keys/rust_secp256k1.rs Outdated Show resolved Hide resolved
src/lib.rs Outdated Show resolved Hide resolved
src/lib.rs Outdated Show resolved Hide resolved
Copy link
Collaborator

@divagant-martian divagant-martian left a comment

Choose a reason for hiding this comment

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

yet more vecs and copy that we can avoid. I did not check them all, so it would be good to go over the whole diff and see based on these suggestions, what over copy_from_slice and to_vec can be avoided.

Also remember to merge master to fix the conflicts

It's getting there, good work

src/builder.rs Outdated Show resolved Hide resolved
src/builder.rs Outdated Show resolved Hide resolved
src/keys/ed25519.rs Outdated Show resolved Hide resolved
src/keys/k256_key.rs Outdated Show resolved Hide resolved
src/keys/rust_secp256k1.rs Outdated Show resolved Hide resolved
src/lib.rs Outdated Show resolved Hide resolved
src/lib.rs Outdated Show resolved Hide resolved
src/lib.rs Outdated Show resolved Hide resolved
src/lib.rs Outdated Show resolved Hide resolved
src/lib.rs Outdated Show resolved Hide resolved
Copy link
Collaborator

@divagant-martian divagant-martian left a comment

Choose a reason for hiding this comment

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

few changes but I think after this one we can merge. I have some questions for age so will post later again

src/lib.rs Outdated
Comment on lines 267 to 269
/// # Panics
///
/// Will panic if data is not sanitized
Copy link
Collaborator

Choose a reason for hiding this comment

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

this is not necessary due to the allow lint below

@@ -119,7 +119,7 @@
//! assert_eq!(decoded_enr.ip4(), Some("192.168.0.1".parse().unwrap()));
//! assert_eq!(decoded_enr.id(), Some("v4".into()));
//! assert_eq!(decoded_enr.tcp4(), Some(8001));
//! assert_eq!(decoded_enr.get("custom_key"), Some(vec![0,0,1].as_slice()));
//! assert_eq!(decoded_enr.get("custom_key").as_ref().map(AsRef::as_ref), Some(vec![0,0,1]).as_deref());
Copy link
Collaborator

Choose a reason for hiding this comment

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

could you check if this can be simplified?

Copy link
Member Author

Choose a reason for hiding this comment

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

Sorry I couldn't find a way to make it simple because the first part (.get("custom_key")) is Option<Bytes> and the second part (Some(vec![0, 0, 1])) is Option<Vec<{integer}>>. I couldn't find any relation with these two. I'm waiting your suggestions.

src/lib.rs Outdated
Comment on lines 411 to 413
/// # Panics
///
/// Will panic if the content does not has a public key
Copy link
Collaborator

Choose a reason for hiding this comment

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

this looks like a merge that left some traces. The panic info is already in the next lines

src/lib.rs Outdated
Comment on lines 971 to 983
let mut list = Vec::<u8>::new();
self.signature.as_slice().encode(&mut list);
self.seq.encode(&mut list);
for (k, v) in &self.content {
k.as_slice().encode(&mut list);
list.extend_from_slice(v);
}
let header = Header {
list: true,
payload_length: list.len(),
};
header.encode(out);
out.put_slice(&list);
Copy link
Collaborator

Choose a reason for hiding this comment

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

use append_rlp_content here please

let payload_info = rlp.payload_info()?;
if rlp.as_raw().len() != payload_info.header_len + payload_info.value_len {
return Err(DecoderError::RlpInconsistentLengthAndData);
let payload = &mut &buf[..header.payload_length];
Copy link
Collaborator

Choose a reason for hiding this comment

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

this can panic if buf is of less size than payload_length. You need to check the size of the buffer first

Copy link
Member

@AgeManning AgeManning Nov 29, 2023

Choose a reason for hiding this comment

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

@armaganyildirak - I think this needs to be addressed.

We should probably fuzz these changes as they are extensive and involve the decoder

Copy link
Member Author

@armaganyildirak armaganyildirak Nov 29, 2023

Choose a reason for hiding this comment

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

I think we don't need to check it because payload_lenght has to be always less size than buffer size but I have already added the size check. https://github.com/armaganyildirak/enr/blob/alloy-rlp/src/lib.rs#L990C1-L993C1

Copy link
Member

Choose a reason for hiding this comment

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

oh yeah, i see. Nice

src/lib.rs Outdated
.map_err(|err| EnrError::InvalidRlpData(err.to_string()))?;
if id_bytes != b"v4" {
if id_bytes.to_vec() != b"v4" {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
if id_bytes.to_vec() != b"v4" {
if id_bytes.as_ref() != b"v4" {

Copy link
Member

@AgeManning AgeManning left a comment

Choose a reason for hiding this comment

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

Nice work!

@AgeManning AgeManning merged commit 77bde01 into sigp:master Nov 29, 2023
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants