ec.h(3)
okay bestie, sit down, hydrate, we're doing elliptic curves 💖 This is the Library Functions Manual page for ec.h — that's section 3 of the manual, iykyk. It's a whole saga, so it's split into parts, and this is part 1. Grab a snack. 🍓
✨ NAME ✨
ec.h — Эллиптические кривые (aka elliptic curves, for anyone who doesn't read Cyrillic 💅)
🌸 SYNOPSIS 🌸
#include 'bee2/math/qr.h'
Yes, those are single quotes around the path. Copy it character for character, bestie — do not go "fixing" it into angle brackets, that's not the vibe. 🎀
💖 Классы (Classes) 💖
struct ec_o— Описание эллиптической кривой. It's the description of an elliptic curve. That's it, that's the whole struct's job, and honestly? Iconic. 👑
🦋 Определения типов (Typedefs) 🦋
These are the function-pointer typedefs — the little plug-in slots the library uses for all its point math. Every signature below is verbatim, because I am not about to paraphrase a signature and have you debugging for three business days. 😭
typedef bool_t(* ec_froma_i) (word b[], const word a[], const struct ec_o *ec, void *stack)— Импорт из аффинной точки. Importing from an affine point ✨typedef bool_t(* ec_toa_i) (word b[], const word a[], const struct ec_o *ec, void *stack)— Экспорт в аффинную точку. Exporting into an affine point ✨typedef void(* ec_neg_i) (word b[], const word a[], const struct ec_o *ec, void *stack)— Обратная точка. The inverse point.typedef void(* ec_add_i) (word c[], const word a[], const word b[], const struct ec_o *ec, void *stack)— Сложение точек. Adding points together.typedef void(* ec_adda_i) (word c[], const word a[], const word b[], const struct ec_o *ec, void *stack)— Сложение с аффинной точкой. Adding with an affine point.typedef void(* ec_sub_i) (word c[], const word a[], const word b[], const struct ec_o *ec, void *stack)— Вычитание точек. Subtracting points.typedef void(* ec_suba_i) (word c[], const word a[], const word b[], const struct ec_o *ec, void *stack)— Вычитание аффинной точки. Subtracting an affine point.typedef void(* ec_dbl_i) (word b[], const word a[], const struct ec_o *ec, void *stack)— Удвоение точки. Doubling a point.typedef void(* ec_dbla_i) (word b[], const word a[], const struct ec_o *ec, void *stack)— Удвоение аффинной точки. Doubling an affine point.typedef void(* ec_tpl_i) (word b[], const word a[], const struct ec_o *ec, void *stack)— Утроение точки. Tripling a point. (yes, tripling, she does it all 💅)typedef struct ec_o ec_o— Описание эллиптической кривой. Yeah it's the description of an elliptic curve again — this time as a typedef of the struct itself. Not me double-dipping, that's just how the header rolls. 🙈
👑 Функции (Functions) 👑
bool_t ecIsOperable (const ec_o *ec)— Описание эллиптической кривой работоспособно? Is this elliptic curve description operable? Hands you back abool_t, obviously. 🔥bool_t ecIsOperable2 (const ec_o *ec)— Описание отдельной эллиптической кривой работоспособно? Is the description of a single elliptic curve operable? Note the2, she's the specific one.bool_t ecGroupCreate (ec_o *ec, const octet xbase[], const octet ybase[], const octet order[], size_t order_len, u32 cofactor, void *stack)— Создание группы точек эллиптической кривой. Building a group of elliptic curve points, fromxbase,ybase,order,order_len,cofactorand astack. 🫶bool_t ecGroupIsOperable (const ec_o *ec)— Группа точек эллиптической кривой работоспособна? Is the elliptic curve point group operable?bool_t ecMulA (word b[], const word a[], const ec_o *ec, const word d[], size_t m, void *stack)— Кратная точка. A multiple of a point. ✨bool_t ecHasOrderA (const word a[], const ec_o *ec, const word q[], size_t m, void *stack)— Имеет порядок? Does it have the order? the drama of this question, honestlybool_t ecAddMulA (word b[], const ec_o *ec, void *stack, size_t k,...)— Сумма кратных точек. The sum of multiples of points. Yes that trailing...is real, keep it. 🦋
that's just the top of the page bestie — part 2 keeps rolling, don't you dare close the tab 👀
💜 DESCRIPTION 💜
okay bestie so here's the whole situation. We're defining computation on elliptic curves over finite fields, and it's giving very much main character energy. The field itself gets modelled as a residue ring using a struct of type qr_o (go peek at the header file qr.h, iykyk). And the curve description follows the conventions of ANSI X 9.62 (ECDSA) plus all the standards that came after it. slay.
An elliptic curve is described by a struct of type ec_o. Say ec is a pointer to one of those. Then ec->f points at the description of the base field, and ec->A and ec->B are coefficients from the base field that pin down the equation of the elliptic curve. iconic.
Now, inside that base field description ec->f you've got the arithmetic functions for the field. The calling program has to set all of that up itself, no cap (check the description of qrCreate() in qr.h for how).
We use the internal representation of base field elements — internal to ec->f, that is. Importing base field elements from octet strings? That's what ec->f->from() is for. Exporting them? That's ec->f->to(). You can also just use the macros qrFrom and qrTo (see header file qr.h). pick your fighter 💅
A point on the elliptic curve is given by ec->d coordinates from the base field. Each coordinate takes up ec->f->n machine words. The coordinates get written one after another, and together they form the array pt made of ec->d * ec->f->n machine words. The first three coordinates are the named ones: X, Y, Z. And the macros ecX, ecY, ecZ are there to pull those named coordinates out of the buffer pt. 🫶
Points with two coordinates are called affine, and points pt = (X : Y : Z :...) with three or more coordinates are projective. The point at infinity, O, can't be represented affinely — no way — but it can be projective: point O corresponds to a point pt where Z == 0. The macros ecSetO and ecIsO handle assigning pt = O and checking pt == O respectively.
For the math to actually work out, you need the point at infinity to exist among the points of the elliptic curve. Which means projective coordinates (projective points) are mandatory, bestie. Dimension ec->d >= 3. periodt.
You can build a projective point out of an affine point (x, y) using the interface function ec_froma_i. As a rule, the construction is just these assignments:
X <- x, Y <- y, Z <- ec->f->unity,....
And the other direction works too: a projective point can be converted into an affine one with the interface function ec_toa_i (and when you're converting the point at infinity, that function hands back the corresponding flag).
Also, an ec description can be used to organise computation in affine coordinates, even though the description itself says projective. so flexible of it.
✨ Прим. (note) ✨
If ec->d == 3, then the Z-coordinate of point pt always equals one for pt != O and zero for pt == O — which means the computation on the curve is actually happening in affine coordinates. sneaky but correct.
The struct of type ec_o has fields set aside for describing the cyclic group of points of the elliptic curve. That group is given by the generator ec->base. The generator is represented as an affine point, i.e. it's given by 2 * ec->f->n machine words. The order of the cyclic group, ec->order, is given by 2 * ec->f->n + 1 machine words. And the cofactor — the ratio of the number of all ec->f-rational points to ec->order — is given by one machine word, ec->cofactor. 🎀
If you're not planning to do anything with the point group, then the fields base, order and cofactor don't have to be set at all. lowkey freeing.
At the address ec->params you can stash extra data — for example, specific multiples of the base point, which you can use to speed up cryptographic computation on the elliptic curve. ✨
The ec description of an elliptic curve includes pointers to the arithmetic functions in the point group of that curve. The interface function ec_tpl_i may not be supported — and a pointer to an unsupported function has to be null. don't be weird about it.
The ring description is organised as an object, so you can go ahead and use the functions described in the header file obj.h. 🌈
An elliptic curve must be created by the special function ecCreate(), which is basically the constructor of the whole situation. You pass into it a pointer ec to a struct of type ec_o. That's where the curve's description (its state) gets placed. And here's the thing — more memory than sizeof(ec_o) may be reserved at the address ec. Why? Because the coefficients A, B, the order order and the base point base can all live in the open-size field descr. Which means ecCreate() must be accompanied by the function ecCreate_keep(), which handles computing the length of the state (in octets). 💀
ecCreate_keep() has to estimate the state length from above. The estimate is allowed to be inexact. The exact state length gets fixed when ecCreate() is actually executed, and it's stored in the keep field of the curve description. no notes.
A pointer to memory for the stack must be passed into ecCreate(). And ecCreate() must be accompanied by the function ecCreate_deep(), which computes the stack depth. When computing that depth, you should assume that all the functions of the curve interfaces are called — explicitly or implicitly — inside ecCreate(). Once external programs have the result from ecCreate_deep(), they can work out how much auxiliary memory they'll need for every possible way of working with the arithmetic functions on the curve. 🧚
The stack depth estimate produced by ecCreate_deep() is allowed to be inexact too. The exact depth gets fixed when ecCreate() is actually executed, and it's stored in the deep field of the curve description.
Also! The parameters base, order and cofactor — the ones that determine the structure of the point group — may not be passed into ecCreate(), even though buffers for base and order may well be prepared inside ecCreate(). Those parameters can be set later on with the function ecGroupCreate(). very "we'll figure it out later" of you.
🚨 Предусловие (precondition) 🚨
- All pointers must be valid.
- Curve point buffers must not intersect with the buffers that support the description of the elliptic curve.
fr fr, read that second one twice. overlapping buffers here is not the vibe you want. 😭
✨ ТИПЫ ✨
okay bestie, this is the types section and it's basically a whole lineup of function-pointer typedefs that make the elliptic-curve math go brrr 💅 every single one of them is a lil contract: here's what you hand me, here's what I promise, here's what has to be true before you even knock on my door. let's go one by one, no skips, no cap 🫶
🦋 ec_add_i
typedef void(* ec_add_i) (word c[], const word a[], const word b[], const
struct ec_o *ec, void *stack)
This is the addition girlie ✨ On the elliptic curve ec, it computes the sum [ec->d * ec->f->n]c of the points [ec->d * ec->f->n]a and [ec->d * ec->f->n]b:
c <- a + b.
Предусловие
- Описание
ecработоспособно. - Буфер
cлибо не пересекается с каждым из буферовaиb, либо совпадает с некоторым из них. - Координаты
aиbлежат в базовом поле.
Ожидается
- Описание
ecкорректно.
Ожидается
- Точки
aиbлежат на кривой.
Аргументы
c— суммаa— первое слагаемоеb— второе слагаемоеec— описание эллиптической кривойstack— вспомогательная память
🌸 ec_adda_i
typedef void(* ec_adda_i) (word c[], const word a[], const word b[], const
struct ec_o *ec, void *stack)
Same addition energy, but this one's mixing representations 🌈 On the curve ec it computes the sum [ec->d * ec->f->n]c of the projective point [ec->d * ec->f->n]a and the affine point [2 * ec->f->n]b:
c <- a + b.
Предусловие
- Описание
ecработоспособно. - Буфер
cлибо не пересекается с каждым из буферовaиb, либо указательcсовпадает с некоторым из указателейaилиb. - Координаты
aиbлежат в базовом поле.
Ожидается
- Описание
ecкорректно.
Ожидается
- Точки
aиbлежат на кривой.
Аргументы
c— суммаa— первое слагаемоеb— второе слагаемоеec— описание эллиптической кривойstack— вспомогательная память
🎀 ec_dbl_i
typedef void(* ec_dbl_i) (word b[], const word a[], const struct ec_o *ec,
void *stack)
doubling, doubling, doubling ✨ On the curve ec it gives you the point [ec->d * ec->f->n]b you get by doubling the point [ec->d * ec->f->n]a:
b <- 2 a.
Предусловие
- Описание
ecработоспособно. - Буфер
bлибо не пересекается, либо совпадает с буферомa. - Координаты
aлежат в базовом поле.
Ожидается
- Описание
ecкорректно.
Ожидается
- Точка
aлежит на кривой.
Аргументы
b— удвоенная точкаa— первоначальная точкаec— описание эллиптической кривойstack— вспомогательная память
💜 ec_dbla_i
typedef void(* ec_dbla_i) (word b[], const word a[], const struct ec_o *ec,
void *stack)
the affine-to-projective doubling situation 💅 On the curve ec it gives you the projective point [ec->d * ec->f->n]b produced by doubling the affine point [2 * ec->f->n]a:
b <- 2 a.
Предусловие
- Описание
ecработоспособно. - Буферы
aиbлибо не пересекаются, либо указателиaиbсовпадают. - Координаты
aлежат в базовом поле.
Ожидается
- Описание
ecкорректно.
Ожидается
- Точка
aлежит на кривой.
Аргументы
b— удвоенная точкаa— первоначальная точкаec— описание эллиптической кривойstack— вспомогательная память
🧚 ec_froma_i
typedef bool_t(* ec_froma_i) (word b[], const word a[], const struct ec_o
*ec, void *stack)
the glow-up function 🦋 it takes the affine point [2 * ec->f->n]a on the curve ec and builds the point [ec->d * ec->f->n]b out of it.
Предусловие
- Описание
ecработоспособно. - Буферы
aиbлибо не пересекаются, либо указателиaиbсовпадают. - Координаты
aлежат в базовом поле.
Ожидается
- Описание
ecкорректно.
Ожидается
- Точка
aлежит на кривой.
Возвращает
TRUE, если преобразование успешно выполнено, иFALSEв противном случае.
Аргументы
b— выходная точкаa— аффинная точкаec— описание эллиптической кривойstack— вспомогательная память
🍓 ec_neg_i
typedef void(* ec_neg_i) (word b[], const word a[], const struct ec_o *ec,
void *stack)
negation, but make it cute 😌 On the curve ec it gives you the point [ec->d * ec->f->n]b that's the inverse of the point [ec->d * ec->f->n]a:
b <- -a.
Предусловие
- Описание
ecработоспособно. - Буфер
bлибо не пересекается, либо совпадает с буферомa. - Координаты
aлежат в базовом поле.
Ожидается
- Описание
ecкорректно.
Ожидается
- Точка
aлежит на кривой.
Аргументы
b— обратная точкаa— обращаемая точкаec— описание эллиптической кривойstack— вспомогательная память
👑 ec_o
typedef struct ec_o ec_o
the main character of this whole file, fr fr 💖 This struct describes an elliptic curve, the rules for how its elements are represented, the group of points, and the functions that implement the operations in that group.
Прим. В таблицу указателей описания кривой как объекта входят поляf,A,B,base,order,params. Полеfявляется указателем на объект.
🌈 ec_sub_i
typedef void(* ec_sub_i) (word c[], const word a[], const word b[], const
struct ec_o *ec, void *stack)
subtraction era 🔥 On the curve ec it computes the difference [ec->d * ec->f->n]c of the points [ec->d * ec->f->n]a and [ec->d * ec->f->n]b:
c <- a - b.
Предусловие
- Описание
ecработоспособно. - Буфер
cлибо не пересекается с каждым из буферовaиb, либо совпадает с некоторым из них. - Координаты
aиbлежат в базовом поле.
Ожидается
- Описание
ecкорректно.
Ожидается
- Точки
aиbлежат на кривой.
Аргументы
c— разностьa— уменьшаемоеb— вычитаемоеec— описание эллиптической кривойstack— вспомогательная память
⭐ ec_suba_i
typedef void(* ec_suba_i) (word c[], const word a[], const word b[], const
struct ec_o *ec, void *stack)
subtraction with a representation switch, iykyk 💫 On the curve ec it computes the difference [ec->d * ec->f->n]c between the projective point [ec->d * ec->f->n]a and the affine point [2 * ec->f->n]b:
c <- a - b.
Предусловие
- Описание
ecработоспособно. - Буфер
cлибо не пересекается с каждым из буферовaиb, либо указательcсовпадает с некоторым из указателейaилиb. - Координаты
aиbлежат в базовом поле.
Ожидается
- Описание
ecкорректно.
Ожидается
- Точки
aиbлежат на кривой.
Аргументы
c— разностьa— уменьшаемоеb— вычитаемоеec— описание эллиптической кривойstack— вспомогательная память
🦋 ec_toa_i
typedef bool_t(* ec_toa_i) (word b[], const word a[], const struct ec_o *ec,
void *stack)
the reverse glow-down (affine-ify her) 🎀 From the point [ec->d * ec->f->n]a on the curve ec it builds the affine point [2 * ec->f->n]b.
Предусловие
- Описание
ecработоспособно. - Буферы
aиbлибо не пересекаются, либо указателиaиbсовпадают. - Координаты
aлежат в базовом поле.
Ожидается
- Описание
ecкорректно.
Ожидается
- Точка
aлежит на кривой.
Возвращает
TRUE, если аффинная точка построена, иFALSE, если точкеaсоответствует бесконечно удаленная точка.
Аргументы
b— аффинная точкаa— входная точкаec— описание эллиптической кривойstack— вспомогательная память
💅 ec_tpl_i
typedef void(* ec_tpl_i) (word b[], const word a[], const struct ec_o *ec,
void *stack)
tripling, because sometimes twice just isn't enough 😭 On the curve ec it gives you the point [ec->d * ec->f->n]b you get by tripling the point [ec->d * ec->f->n]a:
b <- 3 a.
Предусловие
- Описание
ecработоспособно. - Буфер
bлибо не пересекается, либо совпадает с буферомa. - Координаты
aлежат в базовом поле.
Ожидается
- Описание
ecкорректно.
Ожидается
- Точка
aлежит на кривой.
Аргументы
b— утроенная точкаa— первоначальная точкаec— описание эллиптической кривойstack— вспомогательная память
🎀 Функции 🎀
Окей, вот и самое вкусное — сами функции. Их тут семь, и каждая по-своему икона. Погнали, бести. 💅
✨ ecAddMulA
bool_t ecAddMulA (word b[], const ec_o * ec, void * stack, size_t k, ...)
Так вот, эта функция определяет точку [2n]b эллиптической кривой ec, и эта точка — сумма [m[i]]d[i]-кратных точек [2n]a[i], где i = 1, 2,.., k:
b <- d[1] a[1] + d[2] a[2] + ... + d[k] a[k].
Тройки a[i], d[i], m[i] передаются как дополнительные параметры типов const word[], const word[], size_t соответственно. Да, это вариадик, и да, он дерзкий. 🦋
Предусловие — то есть «не присылай мне это, если не выполнено»:
- Описание
ecработоспособно. k > 0.- Координаты точек
a[1], a[2],..., a[k]лежат в базовом поле.
Ожидается — то есть «я тебе верю, но вообще-то должно быть так»:
- Описание
ecкорректно.
Ожидается:
- Точки
a[1], a[2],..., a[k]лежат наec.
Возвращает: TRUE, если полученная точка является аффинной, и FALSE в противном случае (b == O). Так что FALSE тут — не драма, это просто когда b == O. 😌
Схема расчета глубины stack:
ecAddMulA_deep(ec->f->n, ec->d, ec->deep, m[1], ..., m[k]).
Аргументы:
b— кратная точкаec— описание кривойstack— вспомогательная памятьk— число троек (a[i],d[i],m[i])...— тройки (a[i],d[i],m[i])
🌸 ecGroupCreate
bool_t ecGroupCreate (ec_o * ec, const octet xbase[], const octet ybase[],
const octet order[], size_t order_len, u32 cofactor, void * stack)
Эта крошка добавляет в описание ec эллиптической кривой описание группы, порожденной точкой ([ec->f->no]xbase, [ec->f->no]ybase). Группа имеет порядок [order_len]order, и ее кофактор равняется cofactor. Собираем группу, как аутфит. 👑
Предусловие:
- Описание
ecработоспособно. - Буферы
[2 * ec->f->n]ec->base,[ec->f->n + 1]ec->orderкорректны.
Ожидается [FALSE]:
- Число
[octet_len]octetукладывается вec->f->n + 1машинных слов.
Ожидается [FALSE]:
cofactor != 0 && cofactorукладывается в машинное слово.
Ожидается:
- Описание
ecкорректно.
Возвращает: TRUE, если описание группы успешно задано, и FALSE в противном случае.
Прим.: Любой из указателей xbase, ybase может быть нулевым. При нулевом указателе соответствующая координата базовой точки устанавливается равной нулю. То есть можно спокойно скипать одну координату, и это нормально, no cap. 🙈
Схема расчета глубины stack:
ecGroupCreate_deep(f_deep).
Аргументы:
ec— описание кривойxbase— x-координата базовой точкиybase— y-координата базовой точкиorder— порядок группы точекorder_len— длинаordercofactor— кофактор группы точекstack— вспомогательная память
🧚 ecGroupIsOperable
bool_t ecGroupIsOperable (const ec_o * ec)
Проверяется работоспособность описания группы точек эллиптической кривой ec. Смотрим вот на эти условия, как на чек-лист перед выходом из дома:
- буферы
[ec->n + 1]ec->order,[2 * ec->n]ec->baseкорректны; ec->order != 0;cofactor != 0.
Предусловие:
- Описание
ecработоспособно.
Возвращает: Признак корректности.
Аргументы:
ec— описание кривой
💜 ecHasOrderA
bool_t ecHasOrderA (const word a[], const ec_o * ec, const word q[], size_t
m, void * stack)
Проверяется, что аффинная точка [2 * ec->f->n]a имеет порядок [m]q в группе точек кривой ec. Типа «а ты точно той самой величины, милая?» 🔍
Предусловие:
- Описание
ecработоспособно. - Координаты
aлежат в базовом поле. q > 0.
Ожидается:
- Описание
ecкорректно.
Ожидается:
- Точка
aлежит наec.
Ожидается:
- Число
q-- простое. Еслиq-- составное, то точка порядкаq1 | qможет быть ошибочно признана точкой порядкаq.
Это, кстати, важный момент, не проскочи: с составнымqпроверка может обмануться. Так чтоqподавай простым, окей? 💀
Возвращает: Признак успеха проверки.
Схема расчета глубины stack:
ecpHasOrderA_deep(ec->f->n, ec->d, ec->f->deep, m).
Аргументы:
a— точкаec— описание кривойq— порядокm— длинаqв машинных словахstack— вспомогательная память
🫶 ecIsOperable
bool_t ecIsOperable (const ec_o * ec)
Проверяется работоспособность описания ec эллиптической кривой. Проверяются следующие условия — вот прям весь список, ничего не пропускаем:
- объект
ecработоспособен; objKeep(ec) >= sizeof(ec_o);objPCount(ec) == 6 && objOCount(ec) == 1;ec->d >= 3;qrIsOperable(ec->f) == TRUE;- буферы
[ec->n]ec->A,[ec->n]ec->Bкорректны; - указатели
ec->froma, r->toa, ..., r->dblaкорректны; ec->deep >= ec->f->deep.
Возвращает: Признак корректности.
Прим.: Поля ec->base, ec->order и ec->cofactor, описывающие группу точек, не контролируются. Так что не удивляйся, что их тут нет в списке — это фича, не баг. 😭
Аргументы:
ec— описание кривой
🍓 ecIsOperable2
bool_t ecIsOperable2 (const ec_o * ec)
Проверяется работоспособность описания ec эллиптической кривой без учета ссылочного описания базового поля. То есть тот же вайб-чек, но без строчки про поле. Проверяются следующие условия:
- объект
ecработоспособен; objKeep(ec) >= sizeof(ec_o);objPCount(ec) == 6 && objOCount(ec) == 1;ec->d >= 3;- буферы
[ec->n]ec->A,[ec->n]ec->Bкорректны; - указатели
ec->froma, r->toa, ..., r->dblaкорректны.
Возвращает: Признак корректности.
Прим.: Поля ec->base, ec->order и ec->cofactor, описывающие группу точек, не контролируются. Опять. Да, и тут тоже. 🫠
Аргументы:
ec— описание кривой
🔥 ecMulA
bool_t ecMulA (word b[], const word a[], const ec_o * ec, const word d[],
size_t m, void * stack)
Определяется аффинная точка [2 * ec->f->n]b эллиптической кривой ec, которая является [m]d-кратной аффинной точки [2 * ec->f->n]a:
b <- d a.
Просто, но так мощно. Умножаем точку на кратность и живём. 💅
Предусловие:
- Описание
ecработоспособно. - Координаты
aлежат в базовом поле.
Ожидается:
- Описание
ecкорректно.
Ожидается:
- Точка
aлежит наec.
Возвращает: TRUE, если кратная точка является аффинной, и FALSE в противном случае (b == O).
Схема расчета глубины stack:
ecpMulA_deep(ec->f->n, ec->d, ec->f->deep, m).
Аргументы:
b— кратная точкаa— базовая точкаec— описание кривойd— кратностьm— длинаdв машинных словахstack— вспомогательная память
🌈 Автор
Автоматически создано Doxygen для Библиотека Bee2 из исходного текста. Да, буквально — Doxygen просто сгенерил, а мы тут навели красоту. ✨
Всё, бести, страничка закончилась. 🥹 И да, если тебе интересно, откуда это всё прилетело: это ec.h(3) из Библиотека Bee2, дата — Вс 25 Янв 2026 00:00:00. Изи, красиво, забирай и пользуйся. Пока-пока, любимая, не забудь освободить stack! 💖🎀🦋
📦 where this page comes from
- fedora 44: bee2-devel 2.2.0-1.fc44 · GPL-3.0-only and GPL-3.0-or-later
- fedora 44: bee2-devel 2.2.0-1.fc44 · GPL-3.0-only and GPL-3.0-or-later
- 💖 girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms