Journey through Cairo III— A deep dive into Strings and Felts with Starklings
Welcome to the third part of our series, Journey through Cairo! In our last article found here, we took a good look at some basic fundamentals of Cairo, including namespaces, structs etc, today we’d be going deeper into Strings and Felts.
As always, if you are just joining us mid-flight, do well to checkout the previous articles, as we’d be kicking off from our last checkpoint!
So last week, we completed the Starklings challenges under the Syntax section, today we’d be attempting the challenges in the Strings folder, but before then, i need us understanding a very important concept in Cairo, felts.
Felts
Unlike Solidity, where you have quite a number of various data types, such as uints, strings, bools, etc, Cairo comes with just one data type….felts.
Felts stands for Field elements. In simple terms, they are unsigned integers with up to 76 decimals.
Whilst using Felts have a lot of advantages, i feel like they have some annoying downsides too. For example:
- They are a 252 bit integer, which gives problems when we want to fit a uint256 value into it. We can put felts together into tuples to solve this.
- According to the official Cairo docs, In Cairo, the basic data type is an integer in the range 0≤x<P where P is a prime number. All the computations are done modulo P. This can pose some very serious issues with divisions as, all divisive operation (x/y), must satisfy the condition:
(x / y) * y == x
For those with non-mathematical background, the equation above means, that if let’s say we divide 10 by 5, where x = 10, and y = 5, whatever answer we get, when multiplied by y(which is 5), must give back x(which is 10). So 10/5 = 2, and 2 * 5 = 10.
But what if we were to do 10/3? in other CPUs, this should either be 3 (ignoring the remainder) or 3.33333333333. But remember it does not satisfy our equation above, so here’s the result in Cairo..a string of weird numbers..
1206167596222043737899107594365023368541035738443865566657697352045290673497
To solve this issue, Cairo has a library that contains a set of pre-written Cairo codes, that we could import and use directly in our code. An example of these pre-written functions is the unsigned_div_rem found here, which can be used for safe divisions, returning both the integer and the remainder after division.
If you want to dive deeper into how Felts work under the hood, you could checkout the docs here. But having had an idea of how felts function generally, let’s delve right into Strings!
Strings In Cairo
Whilst we call them strings, Cairo generally does not have support for Strings currently. What Cairo rather supports are what we call short strings.
A short string is a string whose length is at most 31 characters, and therefore can fit into a single field element. Whilst they might look like strings, they are encoded as ASCII under the hood, and as such can be represented with felts.
- strings00.cairo
This exercise returns a series of variables, which we are supposed to assign the necessary short strings to pass.
Passing this exercise is very straight forward, as we can do that by just copying and pasting the short strings from the tests, like this.
and voila! we passed.
but then we’d miss out on some important points being passed across. What we’d rather do, is create a python script that converts felts to strings, and hex to strings, so we could see the resulting short strings.
To play around with these conversions:
- Ensure you have python3 installed in your device.
- Create a file named utils.py, and paste the code below in it.
MAX_LEN_FELT = 31
def str_to_felt(text):
if len(text) > MAX_LEN_FELT:
raise Exception("Text length too long to convert to felt.")
return int.from_bytes(text.encode(), "big")
def felt_to_str(felt):
length = (felt.bit_length() + 7) // 8
return felt.to_bytes(length, byteorder="big").decode("utf-8")
def str_to_felt_array(text):
return [str_to_felt(text[i:i+MAX_LEN_FELT]) for i in range(0, len(text), MAX_LEN_FELT)]
def uint256_to_int(uint256):
return uint256[0] + uint256[1]*2**128
def uint256(val):
return (val & 2**128-1, (val & (2**256-2**128)) >> 128)
def hex_to_felt(val):
return int(val, 16)
3. Open up your terminal and run
python3 -i utils.py
And you should have your terminal looking like this:
Next, we are going to try converting our given short string, to see the resulting felt. To do this, run
str_to_felt("Hello Starklings")
You could see that short strings are easily representable using felts!
Next let’s try converting our felt to short string:
Cool! Lastly let’s try converting the hex to short string..To do this, we’d need to first convert to hex, and then to short string.
Awesome!
This proves that short strings are just encoded ASCIIs, and as such can be interchanged with equivalent felts and hex.
2. strings01.cairo
Do you know that you could perform mathematical operations on short strings? Wild right? but remember they are just encoded ASCIIs, and as such you could do with them, whatever you can do with felts!
Now let’s do some short strings mathematics, to pass the decode_cipher1 function:
If that looks strange, i want you to first forget these are short strings and rather think of them as numbers.
using the popular BODMAS rule, if:
plaintext = ciphertext + key
then:
key = plaintext - ciphertext
and plaintext(or decoded_string as its called in test) was already given in the test as ‘Twinkle Twinkle Little Star’.
therefore:
key = 'Twinkle Twinkle Little Star' - ciphertext
Now over to the decode_cipher2 function:
Here, we need to solve for the ciphertext.
Remember the plaintext was given to be:
plaintext = 1337 * ciphertext + 0xc0de
using BODMAS rule again:
ciphertext = (plaintext - 0xc0de) / 1337
and plaintext(or decoded_string as its called in test) was already given in the test as ‘Magic Starknet Money’.
therefore, ciphertext can be said to be:
ciphertext = ('Magic Starknet Money' - 0xc0de) / 1337
Fingers crossed, now let’s see if our test passes.
Yeap! it does.
Conclusion
If you got to this point, a huge congratulations! You’ve made a significant progress on your journey to becoming a Cairo expert!
We’d continue with this series every two days, so i’d advice rather than wait until the next series, you could go ahead to attempt other sections of the Starklings tutorial, in anticipation of our next article.
Remember if you ever got stuck with anything, i have the solutions to these exercises in my repo here.
In our next article, we’d go through the storage exercises.
If you got value from this article, do well to share with others.
You could also connect with me on the following socials, especially on Twitter, where i share my little findings on Cairo!
Twitter: https://twitter.com/0xdarlington
LinkedIn: https://www.linkedin.com/in/nnamdarlington
Github: https://github.com/Darlington02
New to trading? Try crypto trading bots or copy trading