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

Get rid of bytes type #258

Closed
cburgdorf opened this issue Feb 18, 2021 · 5 comments
Closed

Get rid of bytes type #258

cburgdorf opened this issue Feb 18, 2021 · 5 comments

Comments

@cburgdorf
Copy link
Collaborator

Remove bytes type

Disclaimer: There may be very good reasons to keep the bytes type so I'm creating this issue in anticipation of push back to see if anyone can bring up good reasons to keep a dedicated bytes type.

Today, Fe has a primitive bytes that isn't actually well integrated in the language yet and I'm going to argue that we should stop right here and don't try to do so. Instead, let's follow Rust which also doesn't have a native bytes type in the language.

If one wants to express a single byte the native type to do so in Rust is u8. If one wants to express two bytes, it would be [u8; 2]. A fixed size array of two u8s.

If we write out a byte string such as b"foo" in Rust the type that the compiler assigns is &[u8; 3].

I believe the only reason why Fe has a bytes type is because of its Python origin but that seems to be rooted in the fact that Python lumps all numbers together and doesn't have a way to express a single byte as u8.

To me it seems that keeping a seperate bytes type only introduces friction without any clear benefits. E.g. we would probably want a way to cast an u8 to bytes like bytes(5) but we would then also have to go further to introduce casting from u8[n] to bytes[n]. I'm having difficulty to justify why would want to introduce all this when bytes seems to be a synonym for u8 at best.

@cburgdorf
Copy link
Collaborator Author

Just a quick addition after discussing that with @g-r-a-n-t

The one tricky thing is that from an ABI perspective u8[n] is being defined as serialize into integers that are padded to u256 whereas byte[n] is defined as serializing the unpadded u8s.

One idea how to deal with that is to say that in Feu8[n], u16[n] do actually serialize without padding and if someone wants to serialize with padding they have to convert it into u256[n] which could also get special language support (e.g. my_u8s.as_u256_array().

It seems to me that this would feel consistent as far as Fe is concerned at the expense of having an inconsistency with the general Ethereum ABI.

@g-r-a-n-t
Copy link
Member

u8[n]would be the only exceptional case, right? since there is no ABI type that expects packed 16 bit integers.

One thing that I considered after our discussion was how this would work with structs.

For example:

struct House:
  color: string10
  occupied: bool
  rooms: u8
  entry_code: u8[4]

the entry_code attribute would be serialized to bytes by default, which I imagine isn't something the user would want.

So maybe we would want to do something like this:

struct House:
  color: string10
  occupied: bool
  rooms: u8
  @[abi_type = "uint[4]"]
  entry_code: u8[4]

# and
@[abi_type = "uint[42]"]
pub def foo() -> u8[42]
  # stuff
  pass

I'm wondering if using annotations to inform the encoding of data is something that would be useful in other situations too?

@cburgdorf
Copy link
Collaborator Author

the entry_code attribute would be serialized to bytes by default, which I imagine isn't something the user would want.

And it would be unreasonable to use entry_code: u256[4] instead to not waste space in storage and memory I suppose?

@[abi_type = "uint[4]"]

Yes, that could be reasonable. I wonder how often that would become an issue. If people would end up having to use these decorators a lot I'm inclined to say we should look for another solution (including keeping bytes).

I'm wondering if using annotations to inform the encoding of data is something that would be useful in other situations too?

I do think these annotations will come in handy to deal with the snake/camel case conversion e.g.

@[abi_casing = Casing::CamelCase]
pub def balance_of(owner: address) -> u256:
    ...

This would then ensure balance_of gets exposed as balanceOf.

@g-r-a-n-t
Copy link
Member

And it would be unreasonable to use entry_code: u256[4] instead to not waste space in storage and memory I suppose?

Yeah, I think forcing people to use a larger type for this would be too heavy-handed.

I do think these annotations will come in handy to deal with the snake/camel case conversion

Good point, camel casing is another problem that this could solve. People may also choose to use non-standard types of encoding, which could fit nicely with annotations.

@[encoding = "abi_packed"]
pub def my_func() -> MyTuple:
  ...

@cburgdorf
Copy link
Collaborator Author

This happened

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

No branches or pull requests

2 participants