1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
use flatbuffers::{emplace_scalar, EndianScalar, FlatBufferBuilder};
use std::io;
use std::mem::size_of;
use writing::{CircuitOwned, VariablesOwned};
use zkinterface_generated::zkinterface::{
    BilinearConstraint,
    BilinearConstraintArgs,
    Message,
    R1CSConstraints,
    R1CSConstraintsArgs,
    Root,
    RootArgs,
    Variables,
    VariablesArgs,
    Witness,
    WitnessArgs,
};


pub fn example_circuit() -> CircuitOwned {
    example_circuit_inputs(3, 4, 25)
}

/// A test circuit of inputs x,y,zz such that x^2 + y^2 = zz.
pub fn example_circuit_inputs(x: u32, y: u32, zz: u32) -> CircuitOwned {
    CircuitOwned {
        connections: VariablesOwned {
            variable_ids: vec![1, 2, 3],  // x, y, zz
            values: Some(serialize_small(&[x, y, zz])),
        },
        free_variable_id: 6,
        r1cs_generation: true,
        field_maximum: None,
    }
}


pub fn write_example_constraints<W: io::Write>(mut writer: W) -> io::Result<()> {
    let constraints: Vec<((Vec<u64>, Vec<u8>), (Vec<u64>, Vec<u8>), (Vec<u64>, Vec<u8>))> = vec![
        // (A ids values)  *  (B ids values)  =  (C ids values)
        ((vec![1], vec![1]), (vec![1], vec![1]), (vec![4], vec![1])),       // x * x = xx
        ((vec![2], vec![1]), (vec![2], vec![1]), (vec![5], vec![1])),       // y * y = yy
        ((vec![0], vec![1]), (vec![4, 5], vec![1, 1]), (vec![3], vec![1])), // 1 * (xx + yy) = z
    ];

    let mut builder = &mut FlatBufferBuilder::new();
    let mut constraints_built = vec![];

    for (lca, lcb, lcc) in constraints {
        let lca = VariablesOwned {
            variable_ids: lca.0,
            values: Some(lca.1),
        }.build(builder);
        let lcb = VariablesOwned {
            variable_ids: lcb.0,
            values: Some(lcb.1),
        }.build(builder);
        let lcc = VariablesOwned {
            variable_ids: lcc.0,
            values: Some(lcc.1),
        }.build(builder);

        constraints_built.push(BilinearConstraint::create(builder, &BilinearConstraintArgs {
            linear_combination_a: Some(lca),
            linear_combination_b: Some(lcb),
            linear_combination_c: Some(lcc),
        }));
    }

    let constraints_built = builder.create_vector(&constraints_built);
    let r1cs = R1CSConstraints::create(&mut builder, &R1CSConstraintsArgs {
        constraints: Some(constraints_built),
        info: None,
    });

    let message = Root::create(&mut builder, &RootArgs {
        message_type: Message::R1CSConstraints,
        message: Some(r1cs.as_union_value()),
    });
    builder.finish_size_prefixed(message, None);

    writer.write_all(builder.finished_data())
}


pub fn write_example_witness<W: io::Write>(writer: W) -> io::Result<()> {
    write_example_witness_inputs(writer, 3, 4)
}

pub fn write_example_witness_inputs<W: io::Write>(mut writer: W, x: u32, y: u32) -> io::Result<()> {
    let ids = [4, 5 as u64]; // xx, yy
    let values = serialize_small(&[
        x * x, // var_4 = xx = x^2
        y * y, // var_5 = yy = y^2
    ]);

    let mut builder = &mut FlatBufferBuilder::new();
    let ids = builder.create_vector(&ids);
    let values = builder.create_vector(&values);
    let values = Variables::create(&mut builder, &VariablesArgs {
        variable_ids: Some(ids),
        values: Some(values),
        info: None,
    });
    let assign = Witness::create(&mut builder, &WitnessArgs {
        assigned_variables: Some(values),
    });
    let message = Root::create(&mut builder, &RootArgs {
        message_type: Message::Witness,
        message: Some(assign.as_union_value()),
    });
    builder.finish_size_prefixed(message, None);

    writer.write_all(builder.finished_data())
}

pub fn serialize_small<T: EndianScalar>(values: &[T]) -> Vec<u8> {
    let sz = size_of::<T>();
    let mut buf = vec![0u8; sz * values.len()];
    for i in 0..values.len() {
        emplace_scalar(&mut buf[sz * i..], values[i]);
    }
    buf
}


#[test]
fn test_examples() {
    use reading::Messages;

    let mut buf = Vec::<u8>::new();
    example_circuit().write(&mut buf).unwrap();
    write_example_constraints(&mut buf).unwrap();
    write_example_witness(&mut buf).unwrap();

    let mut msg = Messages::new(1);
    msg.push_message(buf).unwrap();
    assert_eq!(msg.into_iter().count(), 3);
    assert_eq!(msg.circuits().len(), 1);
    assert_eq!(msg.iter_constraints().count(), 3);
    assert_eq!(msg.iter_witness().count(), 2);
}