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

feat: felt creation from bytes is infallible #16

Merged
merged 5 commits into from
Nov 22, 2023

Conversation

Oppen
Copy link
Contributor

@Oppen Oppen commented Nov 17, 2023

Expose 4 ways to create a field element from arbitrary bytes:

  • from_bytes_be/from_bytes_le: take exactly 32 bytes and interpret them as a big/little endian number of 256 bits and then build a field element from it, modulo STARK prime (in whatever representation Stark252PrimeField uses, currently Montgomery);
  • from_bytes_be_slice/from_bytes_le_slice: take any number of bytes and interpret them as a big/little endian number modulo STARK prime by decomposing into 256 bits integers and multiplying by the appropriate factors.

Pull Request type

  • Feature

What is the current behavior?

Current behavior mimics that of lambdaworks, where depending on the length of the slice passed to from_bytes_xe (where x is either b or l) one of the following happens:

  1. Length is exactly 32 bytes: conversion succeeds and the bytes are interpreted as a single 256 bits integer that is then stored modulo P;
  2. Length is less than 32 bytes: conversion fails and an error is returned;
  3. Length is more than 32 bytes: excess bytes are ignored, and 32 bytes are interpreted as a single 256 bits integer that is then stored modulo P.

What is the new behavior?

Now the functionality is divided in two:

  • One family for exactly 32 bytes;
  • One family for arbitrary length, where:
    1. If length is exactly 32 bytes, we see the old behavior;
    2. If length is less than 32 bytes, we 0-pad the most significant bytes to fit 32 bytes;
    3. If length is more than 32 bytes, we split the number in 32 bytes chunks (0-padding when needed) and compute the number as ∑Di*2^i where Di is the i-th "digit" of 512 bits units. This should be exactly equivalent to the following code (for little endian):
      let x = BigUint::from_bytes_le(bytes);
      let x = x % P;
      This way, we get the same result but without allocations on the heap. The powers of 2 are computed on demand by multiplying a constant.

Does this introduce a breaking change?

Yes. The signature of the from_bytes_xe functions change, they no longer return an error.

Expose 4 ways to create a field element from arbitrary bytes:
- `from_bytes_be`/`from_bytes_le`: take exactly 32 bytes and interpret
  them as a big/little endian number of 256 bits and then build a field
  element from it, modulo STARK prime (in whatever representation
  `Stark252PrimeField` uses, currently Montgomery);
- `from_bytes_be_slice`/`from_bytes_le_slice`: take any number of bytes
  and interpret them as a big/little endian number modulo STARK prime by
  decomposing into 256 bits integers and multiplying by the appropriate
  factors.
@0xLucqs 0xLucqs merged commit 3d46777 into starknet-io:main Nov 22, 2023
2 checks passed
@pefontana pefontana mentioned this pull request Nov 24, 2023
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.

4 participants