ZoKrates icon indicating copy to clipboard operation
ZoKrates copied to clipboard

Simplify packing / unpacking of field elements to binary representation

Open stefandeml opened this issue 6 years ago • 0 comments

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 and unpack128 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 and unpack128 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

stefandeml avatar Feb 06 '19 17:02 stefandeml