Exemple #1
0
def test_G2_compress_and_decompress_flags(pt, on_curve, is_infinity):
    if on_curve:
        z1, z2 = compress_G2(pt)
        x1 = z1 % POW_2_381
        c_flag1 = (z1 % 2**384) // POW_2_383
        b_flag1 = (z1 % POW_2_383) // POW_2_382
        a_flag1 = (z1 % POW_2_382) // POW_2_381
        x2 = z2 % POW_2_381
        c_flag2 = (z2 % 2**384) // POW_2_383
        b_flag2 = (z2 % POW_2_383) // POW_2_382
        a_flag2 = (z2 % POW_2_382) // POW_2_381
        assert x1 < q
        assert x2 < q
        assert c_flag2 == b_flag2 == a_flag2 == 0
        assert c_flag1 == 1
        if is_infinity:
            assert b_flag1 == 1
            assert a_flag1 == x1 == x2 == 0
        else:
            assert b_flag1 == 0
            _, y = normalize(pt)
            _, y_im = y.coeffs
            # TODO: need a case for y_im == 0
            assert a_flag1 == (y_im * 2) // q
        # Correct flags should decompress correct x, y
        normalize(decompress_G2((z1, z2))) == normalize(pt)
    else:
        with pytest.raises(ValueError):
            compress_G2(pt)
def test_map_to_curve_matches_spec(proxy_contract, signing_root):
    field_elements_parts = proxy_contract.functions.hashToField(signing_root).call()
    field_elements = tuple(
        _convert_fp2_to_int(fp2_repr) for fp2_repr in field_elements_parts
    )

    # NOTE: mapToCurve (called below) precompile includes "clearing the cofactor"
    first_group_element = normalize(
        clear_cofactor_G2(map_to_curve_G2(field_elements[0]))
    )

    computed_first_group_element_parts = proxy_contract.functions.mapToCurve(
        field_elements_parts[0]
    ).call()
    computed_first_group_element = tuple(
        _convert_fp2_to_int(fp2_repr) for fp2_repr in computed_first_group_element_parts
    )
    assert computed_first_group_element == first_group_element

    second_group_element = normalize(
        clear_cofactor_G2(map_to_curve_G2(field_elements[1]))
    )

    computed_second_group_element_parts = proxy_contract.functions.mapToCurve(
        field_elements_parts[1]
    ).call()
    computed_second_group_element = tuple(
        _convert_fp2_to_int(fp2_repr)
        for fp2_repr in computed_second_group_element_parts
    )
    assert computed_second_group_element == second_group_element
Exemple #3
0
def compress_G2(pt: G2Uncompressed) -> G2Compressed:
    """
    The compressed point (z1, z2) has the bit order:
    z1: (c_flag1, b_flag1, a_flag1, x1)
    z2: (c_flag2, b_flag2, a_flag2, x2)
    where
    - c_flag1 is always set to 1
    - b_flag1 indicates infinity when set to 1
    - a_flag1 helps determine the y-coordinate when decompressing,
    - a_flag2, b_flag2, and c_flag2 are always set to 0
    """
    if not is_on_curve(pt, b2):
        raise ValueError(
            "The given point is not on the twisted curve over FQ**2")
    if is_inf(pt):
        return G2Compressed((POW_2_383 + POW_2_382, 0))
    x, y = normalize(pt)
    x_re, x_im = x.coeffs
    y_re, y_im = y.coeffs
    # Record the leftmost bit of y_im to the a_flag1
    # If y_im happens to be zero, then use the bit of y_re
    a_flag1 = (y_im * 2) // q if y_im > 0 else (y_re * 2) // q

    # Imaginary part of x goes to z1, real part goes to z2
    # c_flag1 = 1, b_flag1 = 0
    z1 = x_im + a_flag1 * POW_2_381 + POW_2_383
    # a_flag2 = b_flag2 = c_flag2 = 0
    z2 = x_re
    return G2Compressed((z1, z2))
Exemple #4
0
def generate_proof(data_tree, commitment_tree, proof_tree, indices, setup):
    committee_root = commitment_tree[0][0]
    # Generate a random r value; we use a power of r as a coefficient for each sub-leaf
    # to create a random linear combination
    r = int.from_bytes(
        hash(str([committee_root[0].n] + indices).encode('utf-8')),
        'big') % b.curve_order
    #print("r", r)

    # Total polynomial that we are evaluating
    total_poly_evaluations = [0] * WIDTH
    # The set of all intermediate commitments
    commitments = []
    total_proofs = b.Z1

    for i, index in enumerate(indices):
        c = []
        # Walk from top to bottom of the tree
        for d in range(DEPTH):
            # Power of r for this leaf
            rfactor = pow(r, i * DEPTH + d, MODULUS)
            # Position of the index in this layer of data
            position_of_leaf = index // WIDTH**(DEPTH - d - 1)
            # Position of the index within its data chunk
            sub_index = position_of_leaf % WIDTH
            proof = proof_tree[d][position_of_leaf]

            # Add in rfactor*D / (X - w**i) to the total
            total_proofs = b.add(total_proofs, b.multiply(proof, rfactor))
            # Provide as part of the proof all intermediate-level commitments
            if d > 0:
                c.append(commitment_tree[d][position_of_leaf // WIDTH])
        commitments.append(c)
    # Generate a polynomial commitment for the result
    return commitments, b.normalize(total_proofs)
def test_hash_to_curve_matches_spec(proxy_contract, signing_root, dst):
    result = proxy_contract.functions.hashToCurve(signing_root).call()
    converted_result = tuple(_convert_fp2_to_int(fp2_repr) for fp2_repr in result)

    spec_result = normalize(hash_to_G2(signing_root, dst, hashlib.sha256))

    assert converted_result == spec_result
Exemple #6
0
 def from_point(cls, point: G1Uncompressed) -> 'BLS12_381_G1Type':
     if bls12_381.is_inf(point):
         x, y = POW_2_382, 0
     else:
         x_pt, y_pt = bls12_381.normalize(point)
         x, y = x_pt.n, y_pt.n
     value = x.to_bytes(48, 'big') + y.to_bytes(48, 'big')
     return cls.from_value(value)
Exemple #7
0
 def to_hex(g1_point: G1Point) -> str:
     if bls12_381.is_inf(g1_point):
         xxx, yyy = bls.constants.POW_2_382, 0
     else:
         xxx_pt, yyy_pt = bls12_381.normalize(g1_point)
         xxx, yyy = xxx_pt.n, yyy_pt.n
     xxx_bytes = xxx.to_bytes(48, byteorder='big')
     yyy_bytes = yyy.to_bytes(48, byteorder='big')
     return f'0x{(xxx_bytes + yyy_bytes).hex()}'
Exemple #8
0
 def from_point(cls, point: G2Uncompressed) -> 'BLS12_381_G2Type':
     if bls12_381.is_inf(point):
         x_re, x_im, y_re, y_im = 0, POW_2_382, 0, 0
     else:
         x, y = bls12_381.normalize(point)
         x_re, x_im = x.coeffs
         y_re, y_im = y.coeffs
     value = x_im.to_bytes(48, 'big') + x_re.to_bytes(48, 'big') \
         + y_im.to_bytes(48, 'big') + y_re.to_bytes(48, 'big')
     return cls(value)
def test_bls_pairing_check(proxy_contract, signing_root, bls_public_key, signature):
    public_key_point = pubkey_to_G1(bls_public_key)
    public_key = normalize(public_key_point)
    public_key_repr = (
        _convert_int_to_fp_repr(public_key[0]),
        _convert_int_to_fp_repr(public_key[1]),
    )

    # skip some data wrangling by calling contract function for this...
    message_on_curve = proxy_contract.functions.hashToCurve(signing_root).call()

    projective_signature_point = signature_to_G2(signature)
    signature_point = normalize(projective_signature_point)
    signature_repr = (
        _convert_int_to_fp2_repr(signature_point[0]),
        _convert_int_to_fp2_repr(signature_point[1]),
    )
    assert proxy_contract.functions.blsPairingCheck(
        public_key_repr, message_on_curve, signature_repr
    ).call()
def test_verify_and_deposit_fails_with_incorrect_signature(
    proxy_contract,
    deposit_contract,
    bls_public_key,
    withdrawal_credentials,
    signature,
    deposit_data_root,
    public_key_witness,
    signature_witness,
    deposit_amount,
    assert_tx_failed,
    signing_root,
    bls_private_key,
):
    assert (
        int.from_bytes(
            deposit_contract.functions.get_deposit_count().call(), byteorder="little"
        )
        == 0
    )
    assert (
        deposit_contract.functions.get_deposit_root().call().hex() == EMPTY_DEPOSIT_ROOT
    )

    public_key_witness_repr = _convert_int_to_fp_repr(public_key_witness)

    another_message = hashlib.sha256(b"not the signing root").digest()
    assert signing_root != another_message
    signature = G2ProofOfPossession.Sign(bls_private_key, another_message)
    group_element = signature_to_G2(signature)
    normalized_group_element = normalize(group_element)
    signature_witness = normalized_group_element[1]
    signature_witness_repr = _convert_int_to_fp2_repr(signature_witness)

    amount_in_wei = deposit_amount * 10 ** 9
    txn = proxy_contract.functions.verifyAndDeposit(
        bls_public_key,
        withdrawal_credentials,
        signature,
        deposit_data_root,
        public_key_witness_repr,
        signature_witness_repr,
    )
    assert_tx_failed(lambda: txn.transact({"value": amount_in_wei}))

    assert (
        int.from_bytes(
            deposit_contract.functions.get_deposit_count().call(), byteorder="little"
        )
        == 0
    )
Exemple #11
0
def test_G1_compress_and_decompress_flags(pt, on_curve, is_infinity):
    assert on_curve == is_on_curve(pt, b)
    z = compress_G1(pt)
    if on_curve:
        x = z % POW_2_381
        c_flag = (z % 2**384) // POW_2_383
        b_flag = (z % POW_2_383) // POW_2_382
        a_flag = (z % POW_2_382) // POW_2_381
        assert x < q
        assert c_flag == 1
        if is_infinity:
            assert b_flag == 1
            assert a_flag == x == 0
        else:
            assert b_flag == 0
            pt_x, pt_y = normalize(pt)
            assert a_flag == (pt_y.n * 2) // q
            assert x == pt_x.n
        # Correct flags should decompress correct x, y
        normalize(decompress_G1(z)) == normalize(pt)
    else:
        with pytest.raises(ValueError):
            decompress_G1(z)
Exemple #12
0
 def to_hex(g2_point: G2Point) -> str:
     if bls12_381.is_inf(g2_point):
         x_re, x_im, y_re, y_im = 0, bls.constants.POW_2_382, 0, 0
     else:
         xxx, yyy = bls12_381.normalize(g2_point)
         x_re, x_im = xxx.coeffs
         y_re, y_im = yyy.coeffs
     x_re_bytes = x_re.to_bytes(48, byteorder='big')
     x_im_bytes = x_im.to_bytes(48, byteorder='big')
     y_re_bytes = y_re.to_bytes(48, byteorder='big')
     y_im_bytes = y_im.to_bytes(48, byteorder='big')
     x_bytes = x_im_bytes + x_re_bytes
     y_bytes = y_im_bytes + y_re_bytes
     return f'0x{(x_bytes + y_bytes).hex()}'
def test_verify_and_deposit_fails_with_incorrect_public_key(
    proxy_contract,
    deposit_contract,
    withdrawal_credentials,
    signature,
    deposit_data_root,
    public_key_witness,
    signature_witness,
    deposit_amount,
    assert_tx_failed,
    seed,
):
    assert (
        int.from_bytes(
            deposit_contract.functions.get_deposit_count().call(), byteorder="little"
        )
        == 0
    )
    assert (
        deposit_contract.functions.get_deposit_root().call().hex() == EMPTY_DEPOSIT_ROOT
    )

    another_seed = "another-secret".encode()
    assert seed != another_seed
    another_private_key = G2ProofOfPossession.KeyGen(another_seed)
    public_key = G2ProofOfPossession.SkToPk(another_private_key)

    group_element = pubkey_to_G1(public_key)
    normalized_group_element = normalize(group_element)
    public_key_witness = normalized_group_element[1]
    public_key_witness_repr = _convert_int_to_fp_repr(public_key_witness)
    signature_witness_repr = _convert_int_to_fp2_repr(signature_witness)
    amount_in_wei = deposit_amount * 10 ** 9
    txn = proxy_contract.functions.verifyAndDeposit(
        public_key,
        withdrawal_credentials,
        signature,
        deposit_data_root,
        public_key_witness_repr,
        signature_witness_repr,
    )
    assert_tx_failed(lambda: txn.transact({"value": amount_in_wei}))

    assert (
        int.from_bytes(
            deposit_contract.functions.get_deposit_count().call(), byteorder="little"
        )
        == 0
    )
Exemple #14
0
def compress_G1(pt: G1Uncompressed) -> G1Compressed:
    """
    A compressed point is a 384-bit integer with the bit order (c_flag, b_flag, a_flag, x),
    where the c_flag bit is always set to 1,
    the b_flag bit indicates infinity when set to 1,
    the a_flag bit helps determine the y-coordinate when decompressing,
    and the 381-bit integer x is the x-coordinate of the point.
    """
    if is_inf(pt):
        # Set c_flag = 1 and b_flag = 1. leave a_flag = x = 0
        return G1Compressed(POW_2_383 + POW_2_382)
    else:
        x, y = normalize(pt)
        # Record y's leftmost bit to the a_flag
        a_flag = (y.n * 2) // q
        # Set c_flag = 1 and b_flag = 0
        return G1Compressed(x.n + a_flag * POW_2_381 + POW_2_383)
Exemple #15
0
def test_bls_core(privkey):
    domain = (0).to_bytes(8, "little")
    p1 = multiply(G1, privkey)
    p2 = multiply(G2, privkey)
    msg = str(privkey).encode('utf-8')
    msghash = hash_to_G2(msg, domain=domain)

    assert normalize(decompress_G1(compress_G1(p1))) == normalize(p1)
    assert normalize(decompress_G2(compress_G2(p2))) == normalize(p2)
    assert normalize(decompress_G2(compress_G2(msghash))) == normalize(msghash)
    sig = sign(msg, privkey, domain=domain)
    pub = privtopub(privkey)
    assert verify(msg, pub, sig, domain=domain)
def test_bls_signature_is_valid_fails_with_invalid_signature(
    proxy_contract, bls_public_key, signing_root, public_key_witness, bls_private_key
):
    public_key_witness_repr = _convert_int_to_fp_repr(public_key_witness)

    another_message = hashlib.sha256(b"not the signing root").digest()
    assert signing_root != another_message
    signature = G2ProofOfPossession.Sign(bls_private_key, another_message)
    group_element = signature_to_G2(signature)
    normalized_group_element = normalize(group_element)
    signature_witness = normalized_group_element[1]

    signature_witness_repr = _convert_int_to_fp2_repr(signature_witness)

    assert not proxy_contract.functions.blsSignatureIsValid(
        signing_root,
        bls_public_key,
        signature,
        public_key_witness_repr,
        signature_witness_repr,
    ).call()
def test_bls_signature_is_valid_fails_with_invalid_public_key(
    proxy_contract, seed, signing_root, signature, signature_witness
):
    another_seed = "another-secret".encode()
    assert seed != another_seed
    another_private_key = G2ProofOfPossession.KeyGen(another_seed)
    public_key = G2ProofOfPossession.SkToPk(another_private_key)

    group_element = pubkey_to_G1(public_key)
    normalized_group_element = normalize(group_element)
    public_key_witness = normalized_group_element[1]
    public_key_witness_repr = _convert_int_to_fp_repr(public_key_witness)

    signature_witness_repr = _convert_int_to_fp2_repr(signature_witness)

    assert not proxy_contract.functions.blsSignatureIsValid(
        signing_root,
        public_key,
        signature,
        public_key_witness_repr,
        signature_witness_repr,
    ).call()
Exemple #18
0
def serialize_point(pt):
    pt = b.normalize(pt)
    return pt[0].n.to_bytes(64, 'little') + pt[1].n.to_bytes(64, 'little')
        a = int.from_bytes(subchunk, "little")
        prod *= gmpy2.mpz((s1 if i % 2 == 0 else s2) + a)
    return 1 - jacobi_bit_mpz(prod, q)


def legendre_aggregate_mpz_premul(x, s1, s2):
    bits = [
        legendre_aggregate_chunk_mpz_premul(chunk, s1, s2)
        for chunk in chunkify(x)
    ]
    return jacobi_bit_mpz(int.from_bytes(bitarray_to_bytes(bits), "little"), q)


time0 = timer()

signature = normalize(
    signature_to_G2(sign(period_bytes, validator_privkey, DOMAIN_RANDAO)))

time1 = timer()

s1, s2 = signature[0].coeffs

x = test_vector(2**21)

time2 = timer()

legendre_aggregate(x, gmpy2.mpz(s1), gmpy2.mpz(s2))

time3 = timer()

legendre_aggregate_mpz(x, gmpy2.mpz(s1), gmpy2.mpz(s2))
Exemple #20
0
def layer_commit(values, setup):
    values += [0] * (WIDTH - len(values))
    coeffs = fft(values, MODULUS, ROOT_OF_UNITY, inv=True)
    return b.normalize(lincomb(setup[0][:len(coeffs)], coeffs, b.add, b.Z1))
def test_G1_pubkey_encode_decode():
    G1_point = multiply(G1, 42)
    pubkey = G1_to_pubkey(G1_point)
    assert (normalize(pubkey_to_G1(pubkey)) == normalize(G1_point))
Exemple #22
0
def compress_G1(pt: Tuple[FQ, FQ, FQ]) -> int:
    x, y = normalize(pt)
    return x.n + 2**383 * (y.n % 2)
Exemple #23
0
def compress_G2(pt: Tuple[FQP, FQP, FQP]) -> Tuple[int, int]:
    if not is_on_curve(pt, b2):
        raise ValueError(
            "The given point is not on the twisted curve over FQ**2")
    x, y = normalize(pt)
    return (int(x.coeffs[0] + 2**383 * (y.coeffs[0] % 2)), int(x.coeffs[1]))
def test_G2_signature_encode_decode():
    G2_point = multiply(G2, 42)
    signature = G2_to_signature(G2_point)
    assert (normalize(signature_to_G2(signature)) == normalize(G2_point))