static VALUE step_initialize( int argc, VALUE *argv, VALUE self ) { VALUE a, b=Qnil, c=Qnil, d=Qnil, e=Qnil; rb_scan_args(argc, argv, "13", &a, &b, &c, &d); /* Selfs are immutable, so that they should be initialized only once. */ if (rb_ivar_defined(self, id_beg)) { rb_name_error(rb_intern("initialize"), "`initialize' called twice"); } if (rb_obj_is_kind_of(a,rb_cRange)) { if (argc>3) { rb_raise(rb_eArgError, "extra argument"); } d = c; c = b; e = rb_funcall(a, rb_intern("exclude_end?"), 0); //b = rb_ivar_get(a, id_end); b = rb_funcall(a, id_end, 0); //a = rb_ivar_get(a, id_beg); a = rb_funcall(a, id_beg, 0); } step_init(self, a, b, c, d, e); return Qnil; }
void Yao::proc_gen_out() { step_init(); double start; EVL_BEGIN start = MPI_Wtime(); m_gen_out = m_ccts[0].m_gen_out; m_timer_evl += MPI_Wtime() - start; start = MPI_Wtime(); EVL_SEND(m_gen_out); m_timer_com += MPI_Wtime() - start; EVL_END GEN_BEGIN start = MPI_Wtime(); m_gen_out = GEN_RECV(); m_timer_com += MPI_Wtime() - start; GEN_END m_comm_sz += m_gen_out.size(); step_report("chk-gen-out"); }
void Yao::proc_evl_out() { EVL_BEGIN step_init(); double start = MPI_Wtime(); m_evl_out = m_ccts[0].m_evl_out; m_timer_evl += MPI_Wtime() - start; step_report("chk-evl-out"); EVL_END }
VALUE nary_step_new( VALUE beg, VALUE end, VALUE step, VALUE len, VALUE excl ) { VALUE self = rb_obj_alloc(na_cStep); step_init(self, beg, end, step, len, excl); return self; }
void BetterYao2::proc_gen_out() { step_init(); // TODO: implement Ki08 m_gen_out = m_ccts[0].m_gen_out; EVL_BEGIN send_data(Env::world_rank()-1, m_gen_out); EVL_END GEN_BEGIN m_gen_out = recv_data(Env::world_rank()+1); GEN_END step_report("chk-gen-out"); }
void BetterYao2::proc_evl_out() { EVL_BEGIN step_init(); double start; Bytes send, recv; start = MPI_Wtime(); const Bytes ZEROS((Env::circuit().evl_out_cnt()+7)/8, 0); for (size_t ix = 0; ix < m_ccts.size(); ix++) // fill zeros for uniformity (convenient to MPIs) { send += (m_chks[ix])? ZEROS : m_ccts[ix].m_evl_out; } if (Env::group_rank() == 0) { recv.resize(send.size()*Env::node_amnt()); } m_timer_evl += MPI_Wtime() - start; start = MPI_Wtime(); MPI_Gather(&send[0], send.size(), MPI_BYTE, &recv[0], send.size(), MPI_BYTE, 0, m_mpi_comm); m_timer_mpi += MPI_Wtime() - start; start = MPI_Wtime(); if (Env::is_root()) { size_t chks_total = 0; for (size_t ix = 0; ix < m_all_chks.size(); ix++) chks_total += m_all_chks[ix]; // find majority by locating the median of output from evaluation-circuits std::vector<Bytes> vec = recv.split((Env::circuit().evl_out_cnt()+7)/8); size_t median_ix = (chks_total+vec.size())/2; std::nth_element(vec.begin(), vec.begin()+median_ix, vec.end()); m_evl_out = *(vec.begin()+median_ix); } m_timer_evl += MPI_Wtime() - start; step_report("chk-evl-out"); EVL_END }
VALUE nary_step_new2( VALUE range, VALUE step, VALUE len ) { VALUE beg, end, excl; VALUE self = rb_obj_alloc(na_cStep); //beg = rb_ivar_get(range, id_beg); beg = rb_funcall(range, id_beg, 0); //end = rb_ivar_get(range, id_end); end = rb_funcall(range, id_end, 0); excl = rb_funcall(range, rb_intern("exclude_end?"), 0); step_init(self, beg, end, step, len, excl); return self; }
void Yao::oblivious_transfer() { step_init(); double start; // time marker Bytes send, recv, bufr(Env::elm_size_in_bytes()*4); std::vector<Bytes> bufr_chunks, recv_chunks; G X[2], Y[2], gr, hr; Z s[2], t[2], y, a, r; // step 1: generating the CRS: g[0], h[0], g[1], h[1] if (Env::is_root()) { EVL_BEGIN start = MPI_Wtime(); y.random(); a.random(); m_ot_g[0].random(); m_ot_g[1] = m_ot_g[0]^y; // g[1] = g[0]^y m_ot_h[0] = m_ot_g[0]^a; // h[0] = g[0]^a m_ot_h[1] = m_ot_g[1]^(a + Z(1)); // h[1] = g[1]^(a+1) bufr.clear(); bufr += m_ot_g[0].to_bytes(); bufr += m_ot_g[1].to_bytes(); bufr += m_ot_h[0].to_bytes(); bufr += m_ot_h[1].to_bytes(); m_timer_evl += MPI_Wtime() - start; start = MPI_Wtime(); // send to Gen's root process EVL_SEND(bufr); m_timer_com += MPI_Wtime() - start; EVL_END GEN_BEGIN start = MPI_Wtime(); bufr = GEN_RECV(); m_timer_com += MPI_Wtime() - start; GEN_END m_comm_sz += bufr.size(); } // send g[0], g[1], h[0], h[1] to slave processes start = MPI_Wtime(); MPI_Bcast(&bufr[0], bufr.size(), MPI_BYTE, 0, m_mpi_comm); m_timer_mpi += MPI_Wtime() - start; start = MPI_Wtime(); bufr_chunks = bufr.split(Env::elm_size_in_bytes()); m_ot_g[0].from_bytes(bufr_chunks[0]); m_ot_g[1].from_bytes(bufr_chunks[1]); m_ot_h[0].from_bytes(bufr_chunks[2]); m_ot_h[1].from_bytes(bufr_chunks[3]); // pre-processing m_ot_g[0].fast_exp(); m_ot_g[1].fast_exp(); m_ot_h[0].fast_exp(); m_ot_h[1].fast_exp(); // allocate memory for m_keys m_ot_keys.resize(Env::node_load()); for (size_t ix = 0; ix < m_ot_keys.size(); ix++) { m_ot_keys[ix].reserve(Env::circuit().evl_inp_cnt()*2); } m_timer_evl += MPI_Wtime() - start; m_timer_gen += MPI_Wtime() - start; // Step 2: ZKPoK of (g[0], g[1], h[0], h[1]) // TODO // Step 3: gr=g[b]^r, hr=h[b]^r, where b is the evaluator's bit if (Env::is_root()) { EVL_BEGIN start = MPI_Wtime(); bufr.clear(); bufr.reserve(Env::exp_size_in_bytes()*Env::circuit().evl_inp_cnt()); send.clear(); send.reserve(Env::elm_size_in_bytes()*Env::circuit().evl_inp_cnt()*2); for (size_t bix = 0; bix < Env::circuit().evl_inp_cnt(); bix++) { r.random(); bufr += r.to_bytes(); // to be shared with slave evaluators byte bit_value = m_evl_inp.get_ith_bit(bix); send += (m_ot_g[bit_value]^r).to_bytes(); // gr send += (m_ot_h[bit_value]^r).to_bytes(); // hr } m_timer_evl += MPI_Wtime() - start; start = MPI_Wtime(); EVL_SEND(send); // send (gr, hr)'s m_timer_com += MPI_Wtime() - start; m_comm_sz += send.size(); EVL_END GEN_BEGIN start = MPI_Wtime(); bufr = GEN_RECV(); // receive (gr, hr)'s m_timer_com += MPI_Wtime() - start; m_comm_sz += bufr.size(); GEN_END } EVL_BEGIN // forward rs to slave evaluators start = MPI_Wtime(); bufr.resize(Env::exp_size_in_bytes()*Env::circuit().evl_inp_cnt()); m_timer_evl += MPI_Wtime() - start; start = MPI_Wtime(); MPI_Bcast(&bufr[0], bufr.size(), MPI_BYTE, 0, m_mpi_comm); // now every evaluator has r's m_timer_mpi += MPI_Wtime() - start; start = MPI_Wtime(); bufr_chunks = bufr.split(Env::exp_size_in_bytes()); m_timer_evl += MPI_Wtime() - start; EVL_END GEN_BEGIN // forward (gr, hr)s to slave generators start = MPI_Wtime(); bufr.resize(Env::elm_size_in_bytes()*Env::circuit().evl_inp_cnt()*2); m_timer_gen += MPI_Wtime() - start; start = MPI_Wtime(); MPI_Bcast(&bufr[0], bufr.size(), MPI_BYTE, 0, m_mpi_comm); // now every Bob has bufr m_timer_mpi += MPI_Wtime() - start; start = MPI_Wtime(); bufr_chunks = bufr.split(Env::elm_size_in_bytes()); m_timer_gen += MPI_Wtime() - start; GEN_END // Step 4: the generator computes X[0], Y[0], X[1], Y[1] GEN_BEGIN for (size_t bix = 0; bix < Env::circuit().evl_inp_cnt(); bix++) { start = MPI_Wtime(); gr.from_bytes(bufr_chunks[2*bix+0]); hr.from_bytes(bufr_chunks[2*bix+1]); if (m_ot_keys.size() > 2) { gr.fast_exp(); hr.fast_exp(); } m_timer_gen += MPI_Wtime() - start; for (size_t cix = 0; cix < m_ot_keys.size(); cix++) { start = MPI_Wtime(); Y[0].random(); // K[0] Y[1].random(); // K[1] m_ot_keys[cix].push_back(Y[0].to_bytes().hash(Env::k())); m_ot_keys[cix].push_back(Y[1].to_bytes().hash(Env::k())); s[0].random(); s[1].random(); t[0].random(); t[1].random(); // X[b] = ( g[b]^s[b] ) * ( h[b]^t[b] ), where b = 0, 1 X[0] = m_ot_g[0]^s[0]; X[0] *= m_ot_h[0]^t[0]; X[1] = m_ot_g[1]^s[1]; X[1] *= m_ot_h[1]^t[1]; // Y[b] = ( gr^s[b] ) * ( hr^t[b] ) * K[b], where b = 0, 1 Y[0] *= gr^s[0]; Y[0] *= hr^t[0]; Y[1] *= gr^s[1]; Y[1] *= hr^t[1]; send.clear(); send += X[0].to_bytes(); send += X[1].to_bytes(); send += Y[0].to_bytes(); send += Y[1].to_bytes(); m_timer_gen += MPI_Wtime() - start; start = MPI_Wtime(); GEN_SEND(send); m_timer_com += MPI_Wtime() - start; m_comm_sz += send.size(); } } for (size_t ix = 0; ix < m_ot_keys.size(); ix++) { assert(m_ot_keys[ix].size() == Env::circuit().evl_inp_cnt()*2); } GEN_END // Step 5: the evaluator computes K = Y[b]/X[b]^r EVL_BEGIN for (size_t bix = 0; bix < Env::circuit().evl_inp_cnt(); bix++) { start = MPI_Wtime(); int bit_value = m_evl_inp.get_ith_bit(bix); r.from_bytes(bufr_chunks[bix]); m_timer_evl += MPI_Wtime() - start; for (size_t cix = 0; cix < m_ot_keys.size(); cix++) { start = MPI_Wtime(); recv = EVL_RECV(); // receive X[0], X[1], Y[0], Y[1] m_timer_com += MPI_Wtime() - start; m_comm_sz += recv.size(); start = MPI_Wtime(); recv_chunks = recv.split(Env::elm_size_in_bytes()); X[bit_value].from_bytes(recv_chunks[ bit_value]); // X[b] Y[bit_value].from_bytes(recv_chunks[2 + bit_value]); // Y[b] // K = Y[b]/(X[b]^r) Y[bit_value] /= X[bit_value]^r; m_ot_keys[cix].push_back(Y[bit_value].to_bytes().hash(Env::k())); m_timer_evl += MPI_Wtime() - start; } } for (size_t ix = 0; ix < m_ot_keys.size(); ix++) { assert(m_ot_keys[ix].size() == Env::circuit().evl_inp_cnt()); } EVL_END step_report("ob-transfer"); }
void Yao::circuit_evaluate() { step_init(); double start; Bytes bufr; vector<Bytes> bufr_chunks; G M; for (size_t ix = 0; ix < m_ccts.size(); ix++) { GEN_BEGIN start = MPI_Wtime(); m_rnds[ix] = m_prng.rand(Env::k()); m_gen_inp_masks[ix] = m_prng.rand(Env::circuit().gen_inp_cnt()); m_timer_gen += MPI_Wtime() - start; start = MPI_Wtime(); GEN_SEND(m_gen_inp_masks[ix] ^ m_gen_inp); // send the masked gen_inp m_timer_com += MPI_Wtime() - start; start = MPI_Wtime(); m_ccts[ix].gen_init(m_ot_keys[ix], m_gen_inp_masks[ix], m_rnds[ix]); m_timer_gen += MPI_Wtime() - start; GEN_END EVL_BEGIN start = MPI_Wtime(); m_gen_inp_masks[ix] = EVL_RECV(); // receive the masked gen_inp m_timer_com += MPI_Wtime() - start; start = MPI_Wtime(); m_ccts[ix].evl_init(m_ot_keys[ix], m_gen_inp_masks[ix], m_evl_inp); m_timer_evl += MPI_Wtime() - start; EVL_END m_comm_sz += m_gen_inp_masks[ix].size(); } GEN_BEGIN start = MPI_Wtime(); bufr.clear(); for (int ix = 0; ix < Env::circuit().gen_inp_cnt(); ix++) { bool bit_value = m_gen_inp.get_ith_bit(ix); bufr += m_ccts[0].m_M[2*ix+bit_value].to_bytes(); } m_timer_gen += MPI_Wtime() - start; start = MPI_Wtime(); GEN_SEND(bufr); m_timer_com += MPI_Wtime() - start; GEN_END EVL_BEGIN start = MPI_Wtime(); bufr = EVL_RECV(); m_timer_com += MPI_Wtime() - start; start = MPI_Wtime(); bufr_chunks = bufr.split(Env::elm_size_in_bytes()); for (size_t ix = 0, kx = 0; ix < Env::circuit().gen_inp_cnt(); ix++) { M.from_bytes(bufr_chunks[ix]); for (size_t jx = 0; jx < m_ccts.size(); jx++) { m_ccts[jx].m_M.push_back(M); } } m_timer_evl += MPI_Wtime() - start; EVL_END m_comm_sz += bufr.size(); step_report("pre-cir-evl"); step_init(); GEN_BEGIN // generate and send the circuit gate-by-gate start = MPI_Wtime(); while (Env::circuit().more_gate_binary()) { const Gate &g = Env::circuit().next_gate_binary(); for (size_t ix = 0; ix < m_ccts.size(); ix++) { m_ccts[ix].gen_next_gate(g); bufr = m_ccts[ix].send(); m_timer_gen += MPI_Wtime() - start; start = MPI_Wtime(); GEN_SEND(bufr); m_timer_com += MPI_Wtime() - start; m_comm_sz += bufr.size(); start = MPI_Wtime(); // start m_timer_gen } } m_timer_gen += MPI_Wtime() - start; GEN_END EVL_BEGIN // receive and evaluate the circuit gate-by-gate start = MPI_Wtime(); while (Env::circuit().more_gate_binary()) { const Gate &g = Env::circuit().next_gate_binary(); for (size_t ix = 0; ix < m_ccts.size(); ix++) { m_timer_evl += MPI_Wtime() - start; start = MPI_Wtime(); bufr = EVL_RECV(); m_timer_com += MPI_Wtime() - start; m_comm_sz += bufr.size(); start = MPI_Wtime(); m_ccts[ix].recv(bufr); m_ccts[ix].evl_next_gate(g); } } m_timer_evl += MPI_Wtime() - start; EVL_END step_report("circuit-evl"); if (Env::circuit().evl_out_cnt() != 0) proc_evl_out(); if (Env::circuit().gen_out_cnt() != 0) proc_gen_out(); }
void BetterYao2::circuit_evaluate() { step_init(); double start; int verify = 1; Bytes bufr; EVL_BEGIN start = MPI_Wtime(); for (size_t ix = 0; ix < m_ccts.size(); ix++) { if (m_chks[ix]) // check-circuits { m_ccts[ix].gen_init(m_ot_keys[ix], m_gen_inp_masks[ix], m_rnds[ix]); } else // evaluation-circuits { m_ccts[ix].evl_init(m_ot_keys[ix], m_gen_inp_masks[ix], m_evl_inp); } } m_timer_evl += MPI_Wtime() - start; EVL_END step_report("pre-cir-evl"); step_init(); GEN_BEGIN // start generating circuits gate-by-gate start = MPI_Wtime(); while (Env::circuit().more_gate_binary()) { const Gate &g = Env::circuit().next_gate_binary(); for (size_t ix = 0; ix < m_ccts.size(); ix++) { m_ccts[ix].gen_next_gate(g); bufr = m_ccts[ix].send(); m_timer_gen += MPI_Wtime() - start; start = MPI_Wtime(); GEN_SEND(bufr); m_timer_com += MPI_Wtime() - start; m_comm_sz += bufr.size(); start = MPI_Wtime(); // start m_timer_gen } } m_timer_gen += MPI_Wtime() - start; GEN_END EVL_BEGIN start = MPI_Wtime(); int gate_ix = 0; while (Env::circuit().more_gate_binary()) { const Gate &g = Env::circuit().next_gate_binary(); for (size_t ix = 0; ix < m_ccts.size(); ix++) { m_timer_evl += MPI_Wtime() - start; start = MPI_Wtime(); bufr = EVL_RECV(); m_timer_com += MPI_Wtime() - start; m_comm_sz += bufr.size(); start = MPI_Wtime(); if (m_chks[ix]) // check-circuits { m_ccts[ix].gen_next_gate(g); verify &= (m_ccts[ix].send() == bufr); } else // evaluation-circuits { m_ccts[ix].recv(bufr); m_ccts[ix].evl_next_gate(g); } } gate_ix ++; } m_timer_evl += MPI_Wtime() - start; EVL_END EVL_BEGIN // check the hash of all the garbled circuits int all_verify = 0; start = MPI_Wtime(); MPI_Reduce(&verify, &all_verify, 1, MPI_INT, MPI_LAND, 0, m_mpi_comm); m_timer_mpi += MPI_Wtime() - start; start = MPI_Wtime(); if (Env::is_root() && !all_verify) { LOG4CXX_FATAL(logger, "Verification failed"); MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); } m_timer_evl += MPI_Wtime() - start; EVL_END step_report("circuit-evl"); if (Env::circuit().evl_out_cnt() != 0) proc_evl_out(); if (Env::circuit().gen_out_cnt() != 0) proc_gen_out(); }
void BetterYao2::consistency_check() { step_init(); Bytes send, recv, bufr; std::vector<Bytes> recv_chunks, bufr_chunks; double start; Z m; if (Env::is_root()) { GEN_BEGIN // give away the generator's input M_{0,j} start = MPI_Wtime(); bufr.clear(); for (int jx = 0; jx < Env::circuit().gen_inp_cnt(); jx++) { bool bit_value = m_gen_inp.get_ith_bit(jx); bufr += m_ccts[0].m_M[2*jx+bit_value].to_bytes(); } m_timer_gen += MPI_Wtime() - start; start = MPI_Wtime(); GEN_SEND(bufr); m_timer_com += MPI_Wtime() - start; GEN_END EVL_BEGIN start = MPI_Wtime(); bufr = EVL_RECV(); m_timer_com += MPI_Wtime() - start; EVL_END m_comm_sz += bufr.size(); } EVL_BEGIN // forward the generator's input M_{0,j} to slave evaluators start = MPI_Wtime(); bufr.resize(Env::elm_size_in_bytes()*Env::circuit().gen_inp_cnt()); m_timer_evl += MPI_Wtime() - start; start = MPI_Wtime(); MPI_Bcast(&bufr[0], bufr.size(), MPI_BYTE, 0, m_mpi_comm); m_timer_mpi += MPI_Wtime() - start; start = MPI_Wtime(); bufr_chunks = bufr.split(Env::elm_size_in_bytes()); m_timer_evl += MPI_Wtime() - start; EVL_END GEN_BEGIN // give away m_{i,j}-m_{0,j} so that M_{i,j} can be reconstructed start = MPI_Wtime(); if (Env::is_root()) // forward m_{0,j} to slave generators { bufr.clear(); for (size_t jx = 0; jx < Env::circuit().gen_inp_cnt(); jx++) { bool bit_value = m_gen_inp.get_ith_bit(jx); bufr += m_ccts[0].m_m[2*jx+bit_value].to_bytes(); } } bufr.resize(Env::exp_size_in_bytes()*Env::circuit().gen_inp_cnt()); m_timer_gen += MPI_Wtime() - start; start = MPI_Wtime(); MPI_Bcast(&bufr[0], bufr.size(), MPI_BYTE, 0, m_mpi_comm); m_timer_mpi += MPI_Wtime() - start; start = MPI_Wtime(); bufr_chunks = bufr.split(Env::exp_size_in_bytes()); send.clear(); send.reserve(Env::exp_size_in_bytes()*Env::circuit().gen_inp_cnt()*m_ccts.size()); for (size_t jx = 0; jx < Env::circuit().gen_inp_cnt(); jx++) { m.from_bytes(bufr_chunks[jx]); // retrieve m_{0,j} bool bit_value = m_gen_inp.get_ith_bit(jx); for (size_t ix = 0; ix < m_ccts.size(); ix++) { if (m_chks[ix]) // no data for check-circuits continue; send += (m_ccts[ix].m_m[2*jx+bit_value]-m).to_bytes(); // m_{i,j}-m_{0,j} } } m_timer_gen += MPI_Wtime() - start; start = MPI_Wtime(); GEN_SEND(send); m_timer_com += MPI_Wtime() - start; m_comm_sz += send.size(); GEN_END int verify = 1; G M; EVL_BEGIN start = MPI_Wtime(); recv = EVL_RECV(); m_timer_com += MPI_Wtime() - start; m_comm_sz += recv.size(); start = MPI_Wtime(); recv_chunks = recv.split(Env::exp_size_in_bytes()); for (size_t ix = 0, kx = 0; ix < Env::circuit().gen_inp_cnt(); ix++) { M.from_bytes(bufr_chunks[ix]); for (size_t jx = 0; jx < m_ccts.size(); jx++) { if (m_chks[jx]) continue; // reconstruct M_{i,j} m.from_bytes(recv_chunks[kx++]); // m = m_{i,j}-m_{0,j} M *= Env::clawfree().R(m); // M_{i,j} = h^m * M_{0,j} verify &= (m_ccts[jx].m_M[ix] == M); } } m_timer_evl += MPI_Wtime() - start; int all_verify = 0; start = MPI_Wtime(); MPI_Reduce(&verify, &all_verify, 1, MPI_INT, MPI_LAND, 0, m_mpi_comm); m_timer_mpi += MPI_Wtime() - start; start = MPI_Wtime(); if (Env::is_root() && !all_verify) { LOG4CXX_FATAL(logger, "consistency check failed"); MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); } m_timer_evl += MPI_Wtime() - start; EVL_END step_report("const-check"); }
void BetterYao2::cut_and_choose2() { step_init(); double start; Bytes bufr; vector<Bytes> bufr_chunks; m_ot_bit_cnt = Env::node_load(); EVL_BEGIN start = MPI_Wtime(); m_ot_recv_bits.resize((m_ot_bit_cnt+7)/8); for (size_t ix = 0; ix < m_chks.size(); ix++) { m_ot_recv_bits.set_ith_bit(ix, m_chks[ix]); } m_timer_evl += MPI_Wtime() - start; EVL_END ot_init(); ot_random(); GEN_BEGIN start = MPI_Wtime(); for (size_t ix = 0; ix < m_ccts.size(); ix++) { m_rnds[ix] = m_prng.rand(Env::k()); m_gen_inp_masks[ix] = m_prng.rand(Env::circuit().gen_inp_cnt()); m_ccts[ix].gen_init(m_ot_keys[ix], m_gen_inp_masks[ix], m_rnds[ix]); } m_timer_gen += MPI_Wtime() - start; GEN_END Prng prng; G M; for (size_t ix = 0; ix < m_ccts.size(); ix++) { // evaluation-circuit branch of OT GEN_BEGIN start = MPI_Wtime(); // send group elements representing m_gen_inp bufr.clear(); prng.srand(m_ot_out[2*ix+0]); for (size_t bix = 0; bix < Env::circuit().gen_inp_cnt(); bix++) { byte bit_value = m_gen_inp.get_ith_bit(bix); bufr += m_ccts[ix].m_M[2*bix+bit_value].to_bytes(); } bufr ^= prng.rand(bufr.size()*8); m_timer_gen += MPI_Wtime() - start; start = MPI_Wtime(); GEN_SEND(bufr); m_timer_com += MPI_Wtime() - start; GEN_END EVL_BEGIN start = MPI_Wtime(); bufr = EVL_RECV(); m_timer_com += MPI_Wtime() - start; start = MPI_Wtime(); if (m_chks[ix] == 0) { prng.srand(m_ot_out[ix]); bufr ^= prng.rand(bufr.size()*8); bufr_chunks = bufr.split(Env::elm_size_in_bytes()); for (size_t bix = 0; bix < bufr_chunks.size(); bix++) { M.from_bytes(bufr_chunks[bix]); m_ccts[ix].m_M.push_back(M); } } m_timer_evl += MPI_Wtime() - start; EVL_END m_comm_sz += bufr.size(); GEN_BEGIN start = MPI_Wtime(); // send the masked m_gen_inp bufr = m_gen_inp_masks[ix] ^ m_gen_inp; bufr ^= prng.rand(bufr.size()*8); m_timer_gen += MPI_Wtime() - start; start = MPI_Wtime(); GEN_SEND(bufr); m_timer_com += MPI_Wtime() - start; GEN_END EVL_BEGIN start = MPI_Wtime(); bufr = EVL_RECV(); m_timer_com += MPI_Wtime() - start; start = MPI_Wtime(); if (m_chks[ix] == 0) { bufr ^= prng.rand(bufr.size()*8); m_gen_inp_masks[ix] = bufr; } m_timer_evl += MPI_Wtime() - start; EVL_END m_comm_sz += bufr.size(); // check-circuit branch of OT GEN_BEGIN start = MPI_Wtime(); // send the m_gen_inp_masks[ix] prng.srand(m_ot_out[2*ix+1]); bufr = m_gen_inp_masks[ix]; bufr ^= prng.rand(bufr.size()*8); m_timer_gen += MPI_Wtime() - start; start = MPI_Wtime(); GEN_SEND(bufr); m_timer_com += MPI_Wtime() - start; GEN_END EVL_BEGIN start = MPI_Wtime(); bufr = EVL_RECV(); m_timer_com += MPI_Wtime() - start; start = MPI_Wtime(); if (m_chks[ix]) { prng.srand(m_ot_out[ix]); bufr ^= prng.rand(bufr.size()*8); m_gen_inp_masks[ix] = bufr; } m_timer_evl += MPI_Wtime() - start; EVL_END m_comm_sz += bufr.size(); GEN_BEGIN start = MPI_Wtime(); // send the masked m_gen_inp bufr = m_rnds[ix]; bufr ^= prng.rand(bufr.size()*8); m_timer_gen += MPI_Wtime() - start; start = MPI_Wtime(); GEN_SEND(bufr); m_timer_com += MPI_Wtime() - start; GEN_END EVL_BEGIN start = MPI_Wtime(); bufr = EVL_RECV(); m_timer_com += MPI_Wtime() - start; start = MPI_Wtime(); if (m_chks[ix]) { bufr ^= prng.rand(bufr.size()*8); m_rnds[ix] = bufr; } m_timer_evl += MPI_Wtime() - start; EVL_END m_comm_sz += bufr.size(); GEN_BEGIN start = MPI_Wtime(); // send the m_ot_keys bufr = Bytes(m_ot_keys[ix]); bufr ^= prng.rand(bufr.size()*8); m_timer_gen += MPI_Wtime() - start; start = MPI_Wtime(); GEN_SEND(bufr); m_timer_com += MPI_Wtime() - start; GEN_END EVL_BEGIN start = MPI_Wtime(); bufr = EVL_RECV(); m_timer_com += MPI_Wtime() - start; start = MPI_Wtime(); if (m_chks[ix]) { bufr ^= prng.rand(bufr.size()*8); m_ot_keys[ix] = bufr.split(Env::key_size_in_bytes()); } m_timer_evl += MPI_Wtime() - start; EVL_END m_comm_sz += bufr.size(); } step_report("cut-'n-chk2"); }
void BetterYao2::cut_and_choose() { step_init(); double start; if (Env::is_root()) { Bytes coins = m_prng.rand(Env::k()); // Step 0: flip coins Bytes remote_coins, comm, open; EVL_BEGIN start = MPI_Wtime(); comm = EVL_RECV(); // Step 1: receive bob's commitment EVL_SEND(coins); // Step 2: send coins to bob open = EVL_RECV(); m_timer_com += MPI_Wtime() - start; start = MPI_Wtime(); if (!(open.hash(Env::s()) == comm)) // Step 3: check bob's decommitment { LOG4CXX_FATAL(logger, "commitment to coins can't be properly opened"); MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); } remote_coins = Bytes(open.begin()+Env::k()/8, open.end()); m_timer_evl += MPI_Wtime() - start; EVL_END GEN_BEGIN start = MPI_Wtime(); open = m_prng.rand(Env::k()) + coins; // Step 1: commit to coins comm = open.hash(Env::s()); m_timer_gen += MPI_Wtime() - start; start = MPI_Wtime(); GEN_SEND(comm); remote_coins = GEN_RECV(); // Step 2: receive alice's coins GEN_SEND(open); // Step 3: decommit to the coins m_timer_com += MPI_Wtime() - start; GEN_END m_comm_sz = comm.size() + remote_coins.size() + open.size(); start = MPI_Wtime(); coins ^= remote_coins; Prng prng; prng.srand(coins); // use the coins to generate more random bits // make 60-40 check-vs-evaluateion circuit ratio m_all_chks.assign(Env::s(), 1); // FisherÐYates shuffle std::vector<uint16_t> indices(m_all_chks.size()); for (size_t ix = 0; ix < indices.size(); ix++) { indices[ix] = ix; } // starting from 1 since the 0-th circuit is always evaluation-circuit for (size_t ix = 1; ix < indices.size(); ix++) { int rand_ix = prng.rand_range(indices.size()-ix); std::swap(indices[ix], indices[ix+rand_ix]); } int num_of_evls; switch(m_all_chks.size()) { case 0: case 1: LOG4CXX_FATAL(logger, "there isn't enough circuits for cut-and-choose"); MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); break; case 2: case 3: num_of_evls = 1; break; case 4: num_of_evls = 2; break; default: num_of_evls = m_all_chks.size()*2/5; break; } for (size_t ix = 0; ix < num_of_evls; ix++) { m_all_chks[indices[ix]] = 0; } m_timer_evl += MPI_Wtime() - start; m_timer_gen += MPI_Wtime() - start; } start = MPI_Wtime(); m_chks.resize(Env::node_load()); m_timer_evl += MPI_Wtime() - start; m_timer_gen += MPI_Wtime() - start; start = MPI_Wtime(); MPI_Scatter(&m_all_chks[0], m_chks.size(), MPI_BYTE, &m_chks[0], m_chks.size(), MPI_BYTE, 0, m_mpi_comm); m_timer_mpi += MPI_Wtime() - start; step_report("cut-&-check"); }
int main(int argc, char *argv[]) { char *configfile = DEFAULT_CONFIG_FILE; char *base_path = DEFAULT_DEBUG_FIFO; int option; int step = 0; int debuglevel = 2; pthread_t run_tid; int running=1; while((option = getopt(argc, argv, "d:sc:b:")) != -1) { switch(option) { case 'd': debuglevel = atoi(optarg); break; case 'c': configfile = optarg; break; case 'b': base_path = optarg; break; case 's': step = 1; break; default: fprintf(stderr,"Srsly?"); exit(EXIT_FAILURE); } } debug_level(debuglevel); config_init(&main_config); if(config_read_file(&main_config, configfile) != CONFIG_TRUE) { FATAL("Can't read config file (%s, line %d): %s", configfile, config_error_line(&main_config), config_error_text(&main_config)); exit(EXIT_FAILURE); } if(step) step_init(NULL); memory_init(); if(!load_memory()) exit(EXIT_FAILURE); cpu_init(); if(step) { if(pthread_create(&run_tid, NULL, stepwise_proc, &running) < 0) { perror("pthread_create"); exit(EXIT_FAILURE); } } else { } /* here, we should run the event loop required by any drivers. * really, this means the SDL video driver. for osx, all * event polling/pumping has to be done in the main thread, * not background threads. that's kind of a fail. */ while(running) { memory_run_eventloop(); } exit(EXIT_SUCCESS); }
void step_update(uint16_t position, int16_t step_in) // Update the timer delay that trigers a step. The delay time is determined by the step value, which represents a value of the maximum delay. // The farther the step value is from zero, the longer the delay. { uint16_t min_position; uint16_t max_position; uint8_t step_mode; static uint8_t prev_step_mode; static uint16_t prev_pwm_div; static int16_t prev_seek_position; static uint8_t step_accel_idx = 0; uint16_t duty_cycle; uint16_t pwm_div_hi; uint16_t pwm_div_lo; // Read the high and low values for the PWM frequencies. pwm_div_hi is the top frequency and // pwm_div_lo is the bottom frequency pwm_div_hi = (uint16_t)banks_read_byte(CONFIG_BANK, REG_PWM_FREQ_DIVIDER_HI); pwm_div_lo = (uint16_t)banks_read_byte(CONFIG_BANK, REG_PWM_FREQ_DIVIDER_LO); // Store these in the correct 16 bit size pwm_div_hi = (uint8_t)pwm_div_hi << 8; pwm_div_lo = (uint8_t)pwm_div_lo << 8; // Set up for the configured step mode step_mode = banks_read_byte(CONFIG_BANK, REG_STEP_MODE); // Check to see if the step mode has changed in the registers on the fly if (prev_step_mode != step_mode) step_init(); prev_step_mode = step_mode; min_position = banks_read_word(CONFIG_BANK, REG_MIN_SEEK_HI, REG_MIN_SEEK_LO); max_position = banks_read_word(CONFIG_BANK, REG_MAX_SEEK_HI, REG_MAX_SEEK_LO); // Make sure these values are sane 10-bit values. if (min_position > 0x3ff) min_position = 0x3ff; if (max_position > 0x3ff) max_position = 0x3ff; // Disable clockwise movements when position is below the minimum position. if ((position < min_position) && (step_in < 0)) step_in = 0; // Disable counter-clockwise movements when position is above the maximum position. if ((position > max_position) && (step_in > 0)) step_in = 0; // Determine if Stepping is disabled in the registers. // TODO cheeck for braking and disable bridge if (!(registers_read_byte(REG_FLAGS_LO) & (1<<FLAGS_LO_PWM_ENABLED))) step_in = 0; // Determine and set the direction: Stop (0), Clockwise (1), Counter-Clockwise (2). if (step_in < -5) { // Less than zero. Set the direction to clockwise. direction |= R_COUNTER_CLOCKWISE; direction &= ~R_CLOCKWISE; // Calculate our duty cycle value duty_cycle = PWM_OCRN_VALUE(pwm_div_hi, pwm_div_lo, -step_in); } else if (step_in > 5) { // More than zero. Set the direction to counter-clockwise. direction |= R_CLOCKWISE; //DIRECTION = 2 direction &= ~R_COUNTER_CLOCKWISE; // Calculate our duty cycle value duty_cycle = PWM_OCRN_VALUE(pwm_div_hi, pwm_div_lo, step_in); } else { // Stop all stepping output to the motor by setting motor outputs to low. step_stop(); return; } // If acceleration mode is set, the current speed is divided to all incremental // speed. This function also waits for the R_ACCEL_CLEAR flag from the timer interrupt // before starting the next increment. It should take 10 pulses to get up to speed. if ((direction & R_ACCEL) && (direction & R_ACCEL_CLEAR)) { // Scale the current duty cycle by 64 and increment over a loop duty_cycle = (duty_cycle/64)*(step_accel_idx+1); step_accel_idx++; if (step_accel_idx >= 64) { step_accel_idx = 0; direction &= ~R_ACCEL; } // clear the acceleration flag ready for next toggle direction &= ~R_ACCEL_CLEAR; } // If the motor changes direction we need to wait a small amount of time to discharge, // and then start accelerating in the new direction. uint16_t seek_position = registers_read_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO); if (seek_position != prev_seek_position) { direction |= R_ACCEL; step_accel_idx = 0; OCR1A = 6500; // Wait 1ms (at 20mhz) } else { // A slower speed is a larger delay, so calculate the top pwm frequency, and take away the step delay. OCR1A = 65535 - pwm_div_lo - duty_cycle; //Update the CTC compare value with the modified value of step. } prev_seek_position = seek_position; // Enable the timer mask TIMSK1 |= (1 << OCIE1A); }
int main (void) { // Configure pins to the default states. config_pin_defaults(); // Initialize the watchdog module. watchdog_init(); // First, initialize registers that control servo operation. registers_init(); #if PWM_STD_ENABLED || PWM_ENH_ENABLED // Initialize the PWM module. pwm_init(); #endif #if STEP_ENABLED // Initialise the stepper motor step_init(); #endif // Initialize the ADC module. adc_init(); // Initialise the Heartbeart heartbeat_init(); // Initialize the PID algorithm module. pid_init(); #if CURVE_MOTION_ENABLED // Initialize curve motion module. motion_init(); #endif // Initialize the power module. power_init(); #if PULSE_CONTROL_ENABLED pulse_control_init(); #endif #if BACKEMF_ENABLED // Initialise the back emf module backemf_init(); #endif #if ALERT_ENABLED //initialise the alert registers alert_init(); #endif // Initialize the TWI slave module. twi_slave_init(banks_read_byte(POS_PID_BANK, REG_TWI_ADDRESS)); // Finally initialize the timer. timer_set(0); // Enable interrupts. sei(); // Trigger the adc sampling hardware adc_start(ADC_CHANNEL_POSITION); // Wait until initial position value is ready. while (!adc_position_value_is_ready()); #if CURVE_MOTION_ENABLED // Reset the curve motion with the current position of the servo. motion_reset(adc_get_position_value()); #endif // Set the initial seek position and velocity. registers_write_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO, adc_get_position_value()); registers_write_word(REG_SEEK_VELOCITY_HI, REG_SEEK_VELOCITY_LO, 0); // XXX Enable PWM and writing. I do this for now to make development and // XXX tuning a bit easier. Constantly manually setting these values to // XXX turn the servo on and write the gain values get's to be a pain. #if PWM_STD_ENABLED || PWM_ENH_ENABLED pwm_enable(); #endif #if STEP_ENABLED step_enable(); #endif registers_write_enable(); // This is the main processing loop for the servo. It basically looks // for new position, power or TWI commands to be processed. for (;;) { static uint8_t emf_motor_is_coasting = 0; // Is the system heartbeat ready? if (heartbeat_is_ready()) { static int16_t last_seek_position; static int16_t wait_seek_position; static int16_t new_seek_position; // Clear the heartbeat flag heartbeat_value_clear_ready(); #if PULSE_CONTROL_ENABLED // Give pulse control a chance to update the seek position. pulse_control_update(); #endif #if CURVE_MOTION_ENABLED // Give the motion curve a chance to update the seek position and velocity. motion_next(10); #endif // General call support // Check to see if we have the wait flag enabled. If so save the new position, and write in the // old position until we get the move command if (general_call_enabled()) { //we need to wait for the go command before moving if (general_call_wait()) { // store the new position, but let the servo lock to the last seek position wait_seek_position = (int16_t) registers_read_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO); if (wait_seek_position != last_seek_position) // do we have a new position? { new_seek_position = wait_seek_position; registers_write_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO, last_seek_position); } } last_seek_position = registers_read_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO); //check to make sure that we can start the move. if (general_call_start() || ( registers_read_byte(REG_GENERAL_CALL_GROUP_START) == banks_read_byte(CONFIG_BANK, REG_GENERAL_CALL_GROUP))) { // write the new position with the previously saved position registers_write_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO, new_seek_position); general_call_start_wait_reset(); // reset the wait flag general_call_start_reset(); // reset the start flag } } #if BACKEMF_ENABLED // Quick and dirty check to see if pwm is active. This is done to make sure the motor doesn't // whine in the audible range while idling. uint8_t pwm_a = registers_read_byte(REG_PWM_DIRA); uint8_t pwm_b = registers_read_byte(REG_PWM_DIRB); if (pwm_a || pwm_b) { // Disable PWM backemf_coast_motor(); emf_motor_is_coasting = 1; } else { // reset the back EMF value to 0 banks_write_word(INFORMATION_BANK, REG_BACKEMF_HI, REG_BACKEMF_LO, 0); emf_motor_is_coasting = 0; } #endif #if ADC_ENABLED // Trigger the adc sampling hardware. This triggers the position and temperature sample adc_start(ADC_FIRST_CHANNEL); #endif } // Wait for the samples to complete #if TEMPERATURE_ENABLED if (adc_temperature_value_is_ready()) { // Save temperature value to registers registers_write_word(REG_TEMPERATURE_HI, REG_TEMPERATURE_LO, (uint16_t)adc_get_temperature_value()); } #endif #if CURRENT_ENABLED if (adc_power_value_is_ready()) { // Get the new power value. uint16_t power = adc_get_power_value(); // Update the power value for reporting. power_update(power); } #endif #if ADC_POSITION_ENABLED if (adc_position_value_is_ready()) { int16_t position; // Get the new position value from the ADC module. position = (int16_t) adc_get_position_value(); #else if (position_value_is_ready()) { int16_t position; // Get the position value from an external module. position = (int16_t) get_position_value(); #endif int16_t pwm; #if BACKEMF_ENABLED if (emf_motor_is_coasting == 1) { uint8_t pwm_a = registers_read_byte(REG_PWM_DIRA); uint8_t pwm_b = registers_read_byte(REG_PWM_DIRB); // Quick and dirty check to see if pwm is active if (pwm_a || pwm_b) { // Get the backemf sample. backemf_get_sample(); // Turn the motor back on backemf_restore_motor(); emf_motor_is_coasting = 0; } } #endif // Call the PID algorithm module to get a new PWM value. pwm = pid_position_to_pwm(position); #if ALERT_ENABLED // Update the alert status registers and do any throttling alert_check(); #endif // Allow any alerts to modify the PWM value. pwm = alert_pwm_throttle(pwm); #if PWM_STD_ENABLED || PWM_ENH_ENABLED // Update the servo movement as indicated by the PWM value. // Sanity checks are performed against the position value. pwm_update(position, pwm); #endif #if STEP_ENABLED // Update the stepper motor as indicated by the PWM value. // Sanity checks are performed against the position value. step_update(position, pwm); #endif } // Was a command recieved? if (twi_data_in_receive_buffer()) { // Handle any TWI command. handle_twi_command(); } // Update the bank register operations banks_update_registers(); #if MAIN_MOTION_TEST_ENABLED // This code is in place for having the servo drive itself between // two positions to aid in the servo tuning process. This code // should normally be disabled in config.h. #if CURVE_MOTION_ENABLED if (motion_time_left() == 0) { registers_write_word(REG_CURVE_DELTA_HI, REG_CURVE_DELTA_LO, 2000); registers_write_word(REG_CURVE_POSITION_HI, REG_CURVE_POSITION_LO, 0x0100); motion_append(); registers_write_word(REG_CURVE_DELTA_HI, REG_CURVE_DELTA_LO, 1000); registers_write_word(REG_CURVE_POSITION_HI, REG_CURVE_POSITION_LO, 0x0300); motion_append(); registers_write_word(REG_CURVE_DELTA_HI, REG_CURVE_DELTA_LO, 2000); registers_write_word(REG_CURVE_POSITION_HI, REG_CURVE_POSITION_LO, 0x0300); motion_append(); registers_write_word(REG_CURVE_DELTA_HI, REG_CURVE_DELTA_LO, 1000); registers_write_word(REG_CURVE_POSITION_HI, REG_CURVE_POSITION_LO, 0x0100); motion_append(); } #else { // Get the timer. uint16_t timer = timer_get(); // Reset the timer if greater than 800. if (timer > 800) timer_set(0); // Look for specific events. if (timer == 0) { registers_write_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO, 0x0100); } else if (timer == 400) { registers_write_word(REG_SEEK_POSITION_HI, REG_SEEK_POSITION_LO, 0x0300); } } #endif #endif } return 0; }