ZoKrates
ZoKrates copied to clipboard
Simplify packing / unpacking of field elements to binary representation
Currently ZoKrates has support for 128bit packing and unpacking via the pack128
and unpack128
functions.
We see use-cases where (un)packing of more bits is useful, for example scalar multiplication in elliptic curve cryptography. The function signature could look like: scalarMult(scalar, generator)
.
The underlying algorithm is based on a binary decomposition of the scalar. With babyJubJub as embedded curve we can support scalars up to 253bits. As we currently can't decompose the scalar to it's bits the following verbose function signature needs to be used: scalarMult(scalar[253], generator)
With this refactor we ideally can continue the process of pushing logic from the backed to the ZoKrates DSL, which has started with the SHA256 refactor. This could lead to the following changes:
- deprecate
pack128
andunpack128
as injected code from the backend - add a
split(field)-> field[254]
function for binary decomposition of any field element, similar to the opcode defined in the Pinoccio paper. We will pad the MSB to always return 254bits - add ZoKrates DSL implementations for existing
pack128
andunpack128
support:
pack128
:
def pack128(field[128] i) -> (field):
field out = i[0] + i[1] + i[2] + i[3] + i[4] + i[5] + i[6] + i[7] + i[8] + i[9] + i[10] + i[11] + i[12] + i[13] + i[14] + i[15] + i[16] + i[17] + i[18] + i[19] + i[20] + i[21] + i[22] + i[23] + i[24] + i[25] + i[26] + i[27] + i[28] + i[29] + i[30] + i[31] + i[32] + i[33] + i[34] + i[35] + i[36] + i[37] + i[38] + i[39] + i[40] + i[41] + i[42] + i[43] + i[44] + i[45] + i[46] + i[47] + i[48] + i[49] + i[50] + i[51] + i[52] + i[53] + i[54] + i[55] + i[56] + i[57] + i[58] + i[59] + i[60] + i[61] + i[62] + i[63] + i[64] + i[65] + i[66] + i[67] + i[68] + i[69] + i[70] + i[71] + i[72] + i[73] + i[74] + i[75] + i[76] + i[77] + i[78] + i[79] + i[80] + i[81] + i[82] + i[83] + i[84] + i[85] + i[86] + i[87] + i[88] + i[89] + i[90] + i[91] + i[92] + i[93] + i[94] + i[95] + i[96] + i[97] + i[98] + i[99] + i[100] + i[101] + i[102] + i[103] + i[104] + i[105] + i[106] + i[107] + i[108] + i[109] + i[110] + i[111] + i[112] + i[113] + i[114] + i[115] + i[116] + i[117] + i[118] + i[119] + i[120] + i[121] + i[122] + i[123] + i[124] + i[125] + i[126] + i[127]
return out
unpack128
:
import RUSTHELPER/split as split
def unpack128(field i) -> (field[128]):
assert i < 2**128
field[256] b = split(i)
field[128] out = [b[128], b[129], b[130], b[131], b[132], b[133], b[134], b[135], b[136], b[137], b[138], b[139], b[140], b[141], b[142], b[143], b[144], b[145], b[146], b[147], b[148], b[149], b[150], b[151], b[152], b[153], b[154], b[155], b[156], b[157], b[158], b[159], b[160], b[161], b[162], b[163], b[164], b[165], b[166], b[167], b[168], b[169], b[170], b[171], b[172], b[173], b[174], b[175], b[176], b[177], b[178], b[179], b[180], b[181], b[182], b[183], b[184], b[185], b[186], b[187], b[188], b[189], b[190], b[191], b[192], b[193], b[194], b[195], b[196], b[197], b[198], b[199], b[200], b[201], b[202], b[203], b[204], b[205], b[206], b[207], b[208], b[209], b[210], b[211], b[212], b[213], b[214], b[215], b[216], b[217], b[218], b[219], b[220], b[221], b[222], b[223], b[224], b[225], b[226], b[227], b[228], b[229], b[230], b[231], b[232], b[233], b[234], b[235], b[236], b[237], b[238], b[239], b[240], b[241], b[242], b[243], b[244], b[245], b[246], b[247], b[248], b[249], b[250], b[251], b[252], b[253], b[254], b[255]]
return out
@Schaeff @JacobEberhardt