123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838 |
- #include <iostream>
- #include <fstream>
- #include <sstream>
- #include <ctime>
- #include <chrono>
- #include "networkServer.hpp"
- /********************************************************
- ********* *********
- ********* server networking public functions *********
- ********* *********
- ********************************************************/
- /*
- * CREATOR FOR A NEW SERVER
- */
- PrsonaServer *create_server(
- std::default_random_engine& rng,
- std::string dealerIP,
- int dealerPort,
- bool bgnDealer,
- size_t numServers)
- {
- // We simulate the distributed BGN key generation; in our case, the dealer makes the BGN individually and shares it with other servers
- if (bgnDealer)
- return new PrsonaServer(numServers);
- // If we're not the dealer, get the BGN private key from the dealer
- BGN privateKey = get_bgn_private_key(rng, dealerIP, dealerPort);
- // And make a server object accounting for that
- return new PrsonaServer(numServers, privateKey);
- }
- /*
- * CHECK IN FUNCTION USED FOR SYNCHRONIZATION IN SETUP
- */
- void check_in_with_dealer(
- std::string dealerIP,
- int dealerPort)
- {
- std::stringstream buffer;
- std::string data;
- // The actual check in process is very simple; just make the correct GET request
- buffer << "GET " << SERVER_CHECK_IN_URI << " HTTP/1.1\r\n";
- buffer << "Host: " << dealerIP << ":" << dealerPort << "\r\n\r\n";
- data = buffer.str();
- // This also means things are slightly less cumbersome than making a websocket connection would be
- struct mg_connection *conn = mg_connect_client(dealerIP.c_str(), dealerPort, USE_SSL, NULL, 0);
- // Make the actual GET request
- mg_write(conn, data.c_str(), data.length());
- // We don't really care about the response, so we can just ignore it
- mg_close_connection(conn);
- }
- /*
- * INITIATER FOR SHARED GLOBAL VALUES
- */
- void initiate_generators(
- std::default_random_engine& rng,
- PrsonaServer* prsonaServer,
- const std::vector<std::string>& serverIPs,
- const std::vector<int>& serverPorts,
- const std::string& selfIP,
- int selfPort)
- {
- // Form and distribute the first fresh generator
- std::vector<Proof> pi;
- Twistpoint freshGenerator = make_generator(rng, prsonaServer, serverIPs, serverPorts, selfIP, selfPort, true, pi);
- distribute_generator(prsonaServer, serverIPs, serverPorts, selfIP, selfPort, true, pi, freshGenerator);
- // Form and distribute the H used in ElGamal operations
- Twistpoint blindGenerator = make_generator(rng, prsonaServer, serverIPs, serverPorts, selfIP, selfPort, false, pi);
- distribute_generator(prsonaServer, serverIPs, serverPorts, selfIP, selfPort, false, pi, blindGenerator);
- }
- /*
- * FUNCTION TO PERFORM OPERATIONS FOR EXPERIMENT
- */
- void make_epoch(
- std::default_random_engine& rng,
- PrsonaServer *prsonaServer,
- const std::vector<std::string>& serverIPs,
- const std::vector<int>& serverPorts,
- const std::string& selfIP,
- int selfPort,
- std::mutex& updateMtx,
- std::atomic<size_t>& epochNum,
- const CivetServer& civetServer,
- std::mutex& buildUpOutputMtx,
- const std::string& buildUpOutputFilename,
- std::mutex& breakDownOutputMtx,
- const std::string& breakDownOutputFilename,
- std::mutex& fullOutputMtx,
- const std::string& fullOutputFilename,
- std::mutex& usageMtx,
- const std::string& usageFilename)
- {
- // As before, the fresh generator always starts from the same G
- Twistpoint nextGenerator = PrsonaServer::EL_GAMAL_GENERATOR;
- std::vector<size_t> bandwidthData(2);
- std::unique_lock<std::mutex> updateLock(updateMtx, std::defer_lock);
- std::vector<size_t> bandwidthDataBefore = get_server_log_data(civetServer.getContext());
- std::chrono::high_resolution_clock::time_point wallTimeBefore = std::chrono::high_resolution_clock::now();
- clock_t cpuTimeBefore = clock();
- // Take update locks on every machine
- obtain_update_locks(updateLock, serverIPs, serverPorts, selfIP, selfPort, bandwidthData);
- // Do the first half of the epoch calculations (building up the intermediary values)
- std::vector<Proof> generatorProof = epoch_build_up(rng, prsonaServer, serverIPs, serverPorts, selfIP, selfPort, nextGenerator, civetServer, buildUpOutputMtx, buildUpOutputFilename, usageMtx, usageFilename, bandwidthData);
- // Tally up the current scores at the end of the epoch for the users
- std::vector<EGCiphertext> currentUserEncryptedTallies;
- std::vector<CurveBipoint> currentServerEncryptedTallies;
- tally_scores(prsonaServer, serverIPs, serverPorts, selfIP, selfPort, nextGenerator, currentUserEncryptedTallies, currentServerEncryptedTallies, bandwidthData);
- // And distribute these to each server
- distribute_tallied_scores(prsonaServer, serverIPs, serverPorts, selfIP, selfPort, nextGenerator, currentUserEncryptedTallies, currentServerEncryptedTallies, bandwidthData);
- // Do the second half of the epoch calculations (breaking down values to their final values, to be given to users)
- epoch_break_down(rng, prsonaServer, serverIPs, serverPorts, selfIP, selfPort, generatorProof, nextGenerator, civetServer, breakDownOutputMtx, breakDownOutputFilename, usageMtx, usageFilename, bandwidthData);
- // Indicate we are in a new epoch
- epochNum.fetch_add(1);
- // Release the update locks from every machine
- release_update_locks(updateLock, serverIPs, serverPorts, selfIP, selfPort, bandwidthData);
-
- clock_t cpuTimeAfter = clock();
- std::chrono::high_resolution_clock::time_point wallTimeAfter = std::chrono::high_resolution_clock::now();
- std::vector<size_t> bandwidthDataAfter = get_server_log_data(civetServer.getContext());
- std::vector<double> timingData(2);
- timingData[0] = std::chrono::duration_cast<std::chrono::duration<double>>(wallTimeAfter - wallTimeBefore).count();
- timingData[1] = ((double)(cpuTimeAfter - cpuTimeBefore)) / CLOCKS_PER_SEC;
- bandwidthData[0] += bandwidthDataAfter[0] - bandwidthDataBefore[0];
- bandwidthData[1] += bandwidthDataAfter[1] - bandwidthDataBefore[1];
- write_log_data(fullOutputMtx, fullOutputFilename, timingData, bandwidthData);
- write_usage_data(usageMtx, usageFilename);
- }
- /*********************************************************
- ********* *********
- ********* server networking private functions *********
- ********* *********
- *********************************************************/
- /*
- * SHARED GLOBAL UPDATE LOCK GETTERS AND RELEASERS
- */
- void obtain_update_locks(
- std::unique_lock<std::mutex> &updateLock,
- const std::vector<std::string>& serverIPs,
- const std::vector<int>& serverPorts,
- const std::string& selfIP,
- int selfPort,
- std::vector<size_t>& bandwidthData)
- {
- // Get locks on each machine (in a predetermined order, defined universally for all servers)
- size_t i = 0;
- while (i < serverIPs.size())
- {
- // When it's our turn, it's easy to take the lock
- if (serverIPs[i] == selfIP && serverPorts[i] == selfPort)
- {
- updateLock.lock();
- i++;
- continue;
- }
- struct synchronization_tool sync;
- struct mg_connection *conn = NULL;
- // Connect to the server
- std::unique_lock<std::mutex> lck(sync.mtx);
- sync.val = 0;
- sync.val2 = 0;
- while (!conn)
- {
- conn = mg_connect_websocket_client(serverIPs[i].c_str(), serverPorts[i], USE_SSL, NULL, 0, UPDATE_LOCK_URI, "null", synchro_websocket_data_handler, synchro_websocket_close_handler, &sync);
- if (!conn)
- std::cerr << "Couldn't connect to server " << i << " to obtain its lock" << std::endl;
- }
- std::vector<size_t> bandwidthDataBefore = get_conn_log_data(mg_get_context(conn), true);
- // Ask for its lock
- mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
- // Wait for its response (or the connection to die)
- while (!sync.val2)
- sync.cv.wait(lck);
- std::vector<size_t> bandwidthDataAfter = get_conn_log_data(mg_get_context(conn), true);
- bandwidthData[0] += bandwidthDataAfter[0] - bandwidthDataBefore[0];
- bandwidthData[1] += bandwidthDataAfter[1] - bandwidthDataBefore[1];
- // Close connection
- mg_close_connection(conn);
- // Only move forward once we've confirmed we have the lock (or else we risk deadlock!)
- if (sync.val)
- i++;
- }
- }
- void release_update_locks(
- std::unique_lock<std::mutex> &updateLock,
- const std::vector<std::string>& serverIPs,
- const std::vector<int>& serverPorts,
- const std::string& selfIP,
- int selfPort,
- std::vector<size_t>& bandwidthData)
- {
- // Release locks on each machine (in the opposite of the predetermined order we used to take them)
- ssize_t i = serverIPs.size() - 1;
- while (i >= 0)
- {
- // When it's our turn, it's easy to release the lock
- if (serverIPs[i] == selfIP && serverPorts[i] == selfPort)
- {
- updateLock.unlock();
- i--;
- continue;
- }
- struct synchronization_tool sync;
- struct mg_connection *conn = NULL;
- // Connect to the server
- std::unique_lock<std::mutex> lck(sync.mtx);
- sync.val = 0;
- sync.val2 = 0;
- while (!conn)
- {
- conn = mg_connect_websocket_client(serverIPs[i].c_str(), serverPorts[i], USE_SSL, NULL, 0, UPDATE_UNLOCK_URI, "null", synchro_websocket_data_handler, synchro_websocket_close_handler, &sync);
- if (!conn)
- std::cerr << "Couldn't connect to server " << i << " to release its lock" << std::endl;
- }
- std::vector<size_t> bandwidthDataBefore = get_conn_log_data(mg_get_context(conn), true);
- // Return its lock
- mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
- // Wait for its response (or the connection to die)
- while (!sync.val2)
- sync.cv.wait(lck);
- std::vector<size_t> bandwidthDataAfter = get_conn_log_data(mg_get_context(conn), true);
- bandwidthData[0] += bandwidthDataAfter[0] - bandwidthDataBefore[0];
- bandwidthData[1] += bandwidthDataAfter[1] - bandwidthDataBefore[1];
- // Close connection
- mg_close_connection(conn);
- // Only move forward once we've confirmed we released the lock (or else we risk deadlock!)
- if (sync.val)
- i--;
- }
- }
- /*
- * GETTER FOR DEALER VALUE
- */
- BGN get_bgn_private_key(
- std::default_random_engine& rng,
- std::string dealerIP,
- int dealerPort)
- {
- struct synchronization_tool sync;
- char *filename;
- struct mg_connection *conn = NULL;
- // Set up connection to the dealer
- std::unique_lock<std::mutex> lck(sync.mtx);
- sync.val = 0;
- while (!conn)
- {
- conn = mg_connect_websocket_client(dealerIP.c_str(), dealerPort, USE_SSL, NULL, 0, REQUEST_BGN_PRIVKEY_URI, "null", file_websocket_data_handler, file_websocket_close_handler, &sync);
- if (!conn)
- std::cerr << "Couldn't connect to dealer to obtain BGN details." << std::endl;
- }
- // Establish a file to receive BGN data at
- filename = set_temp_filename(rng, conn);
- // Tell dealer to go ahead with data
- mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
- // Wait for data
- while (!sync.val)
- sync.cv.wait(lck);
- // Close connection
- mg_close_connection(conn);
- // Un-serialize BGN private key
- BGN retval = get_bgn_private_key_from_file(filename);
- remove(filename);
- delete [] filename;
- return retval;
- }
- /*
- * HELPERS TO INITIATE SHARED GLOBAL VALUES
- */
- Twistpoint make_generator(
- std::default_random_engine& rng,
- PrsonaServer *prsonaServer,
- const std::vector<std::string>& serverIPs,
- const std::vector<int>& serverPorts,
- const std::string& selfIP,
- int selfPort,
- bool fresh,
- std::vector<Proof>& pi)
- {
- // Either way, we always start from the same, default G
- Twistpoint retval = PrsonaServer::EL_GAMAL_GENERATOR;
- pi.clear();
- // Make sure we instruct the servers to contribute correctly (in practice, there is basically no difference between these)
- const char* which = (fresh ? REQUEST_ADD_CURR_SEED_FOR_FRESH_GENERATOR_URI : REQUEST_ADD_RAND_SEED_FOR_EG_BLIND_GENERATOR_URI);
- // Ask each server for its contribution
- for (size_t i = 0; i < serverIPs.size(); i++)
- {
- // Add our own contribution
- if (serverIPs[i] == selfIP && serverPorts[i] == selfPort)
- {
- if (fresh)
- retval = prsonaServer->add_curr_seed_to_generator(pi, retval);
- else
- retval = prsonaServer->add_rand_seed_to_generator(pi, retval);
- continue;
- }
- struct synchronization_tool sync;
- char *filename;
- struct mg_connection *conn = NULL;
- // Serialize current state of generator
- std::stringstream buffer;
- std::string data;
- buffer << retval;
- data = buffer.str();
- // Set up connection to current server
- std::unique_lock<std::mutex> lck(sync.mtx);
- sync.val = 0;
- while (!conn)
- {
- conn = mg_connect_websocket_client(serverIPs[i].c_str(), serverPorts[i], USE_SSL, NULL, 0, which, "null", file_websocket_data_handler, file_websocket_close_handler, &sync);
- if (!conn)
- std::cerr << "Couldn't get server " << i << "'s update on generator" << std::endl;
- }
- // Establish a file to receive the new generator at
- filename = set_temp_filename(rng, conn);
- // Send the current state of the generator
- mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), data.length());
- mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
- // Wait for response
- while (!sync.val)
- sync.cv.wait(lck);
- // Close connection
- mg_close_connection(conn);
- // Un-serialize the new state of the generator
- Proof currProof;
- retval = get_generator_from_file(filename, currProof);
- pi.push_back(currProof);
- remove(filename);
- delete [] filename;
- }
- return retval;
- }
- void distribute_generator(
- PrsonaServer *prsonaServer,
- const std::vector<std::string>& serverIPs,
- const std::vector<int>& serverPorts,
- const std::string& selfIP,
- int selfPort,
- bool fresh,
- const std::vector<Proof>& pi,
- const Twistpoint& generator)
- {
- // Serialize the final generator, and its proof of correctness
- std::stringstream buffer;
- std::string data;
- BinarySizeT sizeOfVector(pi.size());
- buffer << sizeOfVector;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- buffer << pi[i];
- buffer << generator;
- data = buffer.str();
- // Make sure we tell the servers which generator we're giving them correctly
- const char* which = (fresh ? SUBMIT_FRESH_GENERATOR_URI : SUBMIT_EG_BLIND_GENERATOR_URI);
-
- // Distribute the generator to each server
- for (size_t i = 0; i < serverIPs.size(); i++)
- {
- // Load the generator into our own server object
- if (serverIPs[i] == selfIP && serverPorts[i] == selfPort)
- {
- if (fresh)
- prsonaServer->initialize_fresh_generator(pi, generator);
- else
- prsonaServer->set_EG_blind_generator(pi, generator);
- continue;
- }
- struct mg_connection *conn = NULL;
- // Connect to the server
- while (!conn)
- {
- conn = mg_connect_websocket_client(serverIPs[i].c_str(), serverPorts[i], USE_SSL, NULL, 0, which, "null", empty_websocket_data_handler, empty_websocket_close_handler, NULL);
- if (!conn)
- std::cerr << "Couldn't connect to server " << i << " to give them the " << (fresh ? "fresh" : "blind") << " generator." << std::endl;
- }
- // Send the generator to the server
- mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), data.length());
- mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
- // Don't bother waiting for a response; we can just move on to the next
- mg_close_connection(conn);
- }
- }
- /*
- * HELPERS FOR EPOCH CALCULATIONS
- */
- std::vector<Proof> epoch_build_up(
- std::default_random_engine& rng,
- PrsonaServer *prsonaServer,
- const std::vector<std::string>& serverIPs,
- const std::vector<int>& serverPorts,
- const std::string& selfIP,
- int selfPort,
- Twistpoint& nextGenerator,
- const CivetServer& civetServer,
- std::mutex& outputMtx,
- const std::string& outputFilename,
- std::mutex& usageMtx,
- const std::string& usageFilename,
- std::vector<size_t>& overallBandwidthData)
- {
- std::vector<std::vector<std::vector<Proof>>> pi;
- std::vector<std::vector<std::vector<Twistpoint>>> permutationCommits;
- std::vector<std::vector<std::vector<Twistpoint>>> freshPseudonymCommits;
- std::vector<std::vector<std::vector<Twistpoint>>> freshPseudonymSeedCommits;
- std::vector<std::vector<std::vector<CurveBipoint>>> serverTallyCommits;
- std::vector<std::vector<std::vector<std::vector<TwistBipoint>>>> partwayVoteMatrixCommits;
- std::vector<std::vector<std::vector<std::vector<TwistBipoint>>>> finalVoteMatrixCommits;
- std::vector<std::vector<Proof>> generatorProofHolder(1);
- // Go through each server to perform the epoch calculation at hand
- for (size_t i = 0; i < serverIPs.size(); i++)
- {
- // When it's our turn, do things as normal
- if (serverIPs[i] == selfIP && serverPorts[i] == selfPort)
- {
- pi.clear();
- pi.push_back(generatorProofHolder);
- permutationCommits.clear();
- freshPseudonymCommits.clear();
- freshPseudonymSeedCommits.clear();
- serverTallyCommits.clear();
- partwayVoteMatrixCommits.clear();
- finalVoteMatrixCommits.clear();
- std::vector<size_t> bandwidthData(2);
- std::vector<std::vector<size_t>> otherBandwidthDataBefore;
- std::vector<size_t> serverBandwidthDataBefore = get_server_log_data(civetServer.getContext());
- std::chrono::high_resolution_clock::time_point wallTimeBefore = std::chrono::high_resolution_clock::now();
- clock_t cpuTimeBefore = clock();
-
- // Perform the actual calculation
- prsonaServer->build_up_midway_pseudonyms(pi, permutationCommits, freshPseudonymCommits, freshPseudonymSeedCommits, serverTallyCommits, partwayVoteMatrixCommits, finalVoteMatrixCommits, nextGenerator);
- std::vector<std::vector<Twistpoint>> currUserTallyMaskCommits;
- std::vector<std::vector<Twistpoint>> currUserTallyMessageCommits;
- std::vector<std::vector<Twistpoint>> currUserTallySeedCommits;
- // Serialize the relevant data
- std::string data = make_epoch_update_string(pi[1], permutationCommits[0], freshPseudonymCommits[0], freshPseudonymSeedCommits[0], serverTallyCommits[0], partwayVoteMatrixCommits[0], finalVoteMatrixCommits[0], currUserTallyMaskCommits, currUserTallyMessageCommits, currUserTallySeedCommits, nextGenerator, false);
- struct synchronization_tool sync;
- std::vector<struct mg_connection *> conns;
- // Distribute the data to each server (in parallel, roughly)
- std::unique_lock<std::mutex> lck(sync.mtx);
- sync.val = 1;
- for (size_t j = 0; j < serverIPs.size(); j++)
- {
- // But, obviously, don't send it back to ourselves
- if (i == j)
- continue;
- // Send that data
- struct mg_connection *currConn = distribute_epoch_updates(serverIPs[j], serverPorts[j], data, &sync);
- otherBandwidthDataBefore.push_back(get_conn_log_data(mg_get_context(currConn), false));
- // But keep track of that connection, as we can't close it until we know the server's gotten its data
- conns.push_back(currConn);
- }
- // Wait for the other servers to all report back that they have received the update
- while (sync.val < serverIPs.size())
- sync.cv.wait(lck);
- for (size_t j = 0; j < conns.size(); j++)
- {
- std::vector<size_t> currBandwidthDataAfter = get_conn_log_data(mg_get_context(conns[j]), false);
- bandwidthData[0] += currBandwidthDataAfter[0] - otherBandwidthDataBefore[j][0];
- bandwidthData[1] += currBandwidthDataAfter[1] - otherBandwidthDataBefore[j][1];
- overallBandwidthData[0] += currBandwidthDataAfter[0] - otherBandwidthDataBefore[j][0];
- overallBandwidthData[1] += currBandwidthDataAfter[1] - otherBandwidthDataBefore[j][1];
- mg_close_connection(conns[j]);
- }
- clock_t cpuTimeAfter = clock();
- std::chrono::high_resolution_clock::time_point wallTimeAfter = std::chrono::high_resolution_clock::now();
- std::vector<size_t> serverBandwidthDataAfter = get_server_log_data(civetServer.getContext());
- std::vector<double> timingData(2);
- timingData[0] = std::chrono::duration_cast<std::chrono::duration<double>>(wallTimeAfter - wallTimeBefore).count();
- timingData[1] = ((double)(cpuTimeAfter - cpuTimeBefore)) / CLOCKS_PER_SEC;
- bandwidthData[0] += serverBandwidthDataAfter[0] - serverBandwidthDataBefore[0];
- bandwidthData[1] += serverBandwidthDataAfter[1] - serverBandwidthDataBefore[1];
- write_log_data(outputMtx, outputFilename, timingData, bandwidthData);
- write_usage_data(usageMtx, usageFilename);
- // Keep an up-to-date version of the proof of the new fresh generator
- generatorProofHolder = pi[0];
- }
- else // When it's another server's turn, tell them to do their part
- {
- // Serialize the request
- std::string data = make_epoch_initiator_string(generatorProofHolder[0], nextGenerator);
- // And have them do that request
- nextGenerator = initiate_epoch_updates(rng, serverIPs[i], serverPorts[i], data, false, generatorProofHolder, overallBandwidthData);
- }
- }
- // Return the proof of the fresh generator
- return generatorProofHolder[0];
- }
- void epoch_break_down(
- std::default_random_engine& rng,
- PrsonaServer *prsonaServer,
- const std::vector<std::string>& serverIPs,
- const std::vector<int>& serverPorts,
- const std::string& selfIP,
- int selfPort,
- const std::vector<Proof>& generatorProof,
- const Twistpoint& nextGenerator,
- const CivetServer& civetServer,
- std::mutex& outputMtx,
- const std::string& outputFilename,
- std::mutex& usageMtx,
- const std::string& usageFilename,
- std::vector<size_t>& overallBandwidthData)
- {
- std::vector<std::vector<std::vector<Proof>>> pi;
- std::vector<std::vector<std::vector<Twistpoint>>> permutationCommits;
- std::vector<std::vector<std::vector<Twistpoint>>> freshPseudonymCommits;
- std::vector<std::vector<std::vector<Twistpoint>>> freshPseudonymSeedCommits;
- std::vector<std::vector<std::vector<CurveBipoint>>> serverTallyCommits;
- std::vector<std::vector<std::vector<std::vector<TwistBipoint>>>> partwayVoteMatrixCommits;
- std::vector<std::vector<std::vector<std::vector<TwistBipoint>>>> finalVoteMatrixCommits;
- std::vector<std::vector<std::vector<Twistpoint>>> userTallyMaskCommits;
- std::vector<std::vector<std::vector<Twistpoint>>> userTallyMessageCommits;
- std::vector<std::vector<std::vector<Twistpoint>>> userTallySeedCommits;
- // Go through each server to perform the epoch calculation at hand
- for (size_t i = 0; i < serverIPs.size(); i++)
- {
- // When it's our turn, do things as normal
- if (serverIPs[i] == selfIP && serverPorts[i] == selfPort)
- {
- pi.clear();
- permutationCommits.clear();
- freshPseudonymCommits.clear();
- freshPseudonymSeedCommits.clear();
- serverTallyCommits.clear();
- partwayVoteMatrixCommits.clear();
- finalVoteMatrixCommits.clear();
- userTallyMaskCommits.clear();
- userTallyMessageCommits.clear();
- userTallySeedCommits.clear();
- std::vector<size_t> bandwidthData(2);
- std::vector<std::vector<size_t>> otherBandwidthDataBefore;
- std::vector<size_t> serverBandwidthDataBefore = get_server_log_data(civetServer.getContext());
- std::chrono::high_resolution_clock::time_point wallTimeBefore = std::chrono::high_resolution_clock::now();
- clock_t cpuTimeBefore = clock();
- // Perform the actual calculation
- prsonaServer->break_down_midway_pseudonyms(generatorProof, pi, permutationCommits, freshPseudonymCommits, freshPseudonymSeedCommits, serverTallyCommits, partwayVoteMatrixCommits, finalVoteMatrixCommits, userTallyMaskCommits, userTallyMessageCommits, userTallySeedCommits, nextGenerator);
- // Serialize the relevant data
- std::string data = make_epoch_update_string(pi[0], permutationCommits[0], freshPseudonymCommits[0], freshPseudonymSeedCommits[0], serverTallyCommits[0], partwayVoteMatrixCommits[0], finalVoteMatrixCommits[0], userTallyMaskCommits[0], userTallyMessageCommits[0], userTallySeedCommits[0], nextGenerator, true);
- struct synchronization_tool sync;
- std::vector<struct mg_connection *> conns;
- // Distribute the data to each server (in parallel, roughly)
- std::unique_lock<std::mutex> lck(sync.mtx);
- sync.val = 1;
- for (size_t j = 0; j < serverIPs.size(); j++)
- {
- // But, obviously, don't send it back to ourselves
- if (i == j)
- continue;
- // Send that data
- struct mg_connection *currConn = distribute_epoch_updates(serverIPs[j], serverPorts[j], data, &sync);
- otherBandwidthDataBefore.push_back(get_conn_log_data(mg_get_context(currConn), false));
- // But keep track of that connection, as we can't close it until we know the server's gotten its data
- conns.push_back(currConn);
- }
- // Wait for the other servers to all report back that they have received the update
- while (sync.val < serverIPs.size())
- sync.cv.wait(lck);
- for (size_t j = 0; j < conns.size(); j++)
- {
- std::vector<size_t> currBandwidthDataAfter = get_conn_log_data(mg_get_context(conns[j]), false);
- bandwidthData[0] += currBandwidthDataAfter[0] - otherBandwidthDataBefore[j][0];
- bandwidthData[1] += currBandwidthDataAfter[1] - otherBandwidthDataBefore[j][1];
- overallBandwidthData[0] += currBandwidthDataAfter[0] - otherBandwidthDataBefore[j][0];
- overallBandwidthData[1] += currBandwidthDataAfter[1] - otherBandwidthDataBefore[j][1];
- mg_close_connection(conns[j]);
- }
- clock_t cpuTimeAfter = clock();
- std::chrono::high_resolution_clock::time_point wallTimeAfter = std::chrono::high_resolution_clock::now();
- std::vector<size_t> serverBandwidthDataAfter = get_server_log_data(civetServer.getContext());
- std::vector<double> timingData(2);
- timingData[0] = std::chrono::duration_cast<std::chrono::duration<double>>(wallTimeAfter - wallTimeBefore).count();
- timingData[1] = ((double)(cpuTimeAfter - cpuTimeBefore)) / CLOCKS_PER_SEC;
- bandwidthData[0] += serverBandwidthDataAfter[0] - serverBandwidthDataBefore[0];
- bandwidthData[1] += serverBandwidthDataAfter[1] - serverBandwidthDataBefore[1];
- write_log_data(outputMtx, outputFilename, timingData, bandwidthData);
- write_usage_data(usageMtx, usageFilename);
- }
- else // When it's another server's turn, tell them to do their part
- {
- std::vector<std::vector<Proof>> unused;
- // Serialize the request
- std::string data = make_epoch_initiator_string(generatorProof, nextGenerator);
-
- // And have them do that request
- initiate_epoch_updates(rng, serverIPs[i], serverPorts[i], data, true, unused, overallBandwidthData);
- }
- }
- }
- /*
- * HELPERS FOR EPOCH HELPERS
- */
- Twistpoint initiate_epoch_updates(
- std::default_random_engine& rng,
- const std::string& recipient,
- int recipientPort,
- const std::string& data,
- bool isBreakdown,
- std::vector<std::vector<Proof>>& generatorProofHolder,
- std::vector<size_t>& bandwidthData)
- {
- Twistpoint retval;
- struct synchronization_tool sync;
- char * filename = NULL;
- const char* which = (isBreakdown ? REQUEST_EPOCH_BREAK_DOWN_URI : REQUEST_EPOCH_BUILD_UP_URI);
- // Make sure we don't move on until this server has conducted its epoch calculations
- std::unique_lock<std::mutex> lck(sync.mtx);
- sync.val = 0;
- while (!sync.val)
- {
- struct mg_connection *conn = NULL;
-
- // Connect to a server
- sync.val2 = 0;
- while (!conn)
- {
- conn = mg_connect_websocket_client(recipient.c_str(), recipientPort, USE_SSL, NULL, 0, which, "null", epoch_websocket_data_handler, epoch_websocket_close_handler, &sync);
- if (!conn)
- std::cerr << "Couldn't initiate epoch update with server at " << recipient << ":" << recipientPort << std::endl;
- }
-
- // Establish a file to receive update data (when relevant)
- if (!isBreakdown)
- filename = set_temp_filename(rng, conn);
-
- // Send the relevant data
- mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), data.length());
- mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
- // Wait for a response (or the connection to die)
- while (!sync.val2)
- sync.cv.wait(lck);
- // Close connection
- mg_close_connection(conn);
- }
-
- // In the second half of the epoch, we don't have a data response to un-serialize, so just move on
- if (isBreakdown)
- return retval;
- std::vector<Proof> generatorProof;
- generatorProofHolder.clear();
- // Otherwise, un-serialize the updated fresh generator (and its proof of correctness)
- retval = get_generator_from_file(filename, generatorProof);
- generatorProofHolder.push_back(generatorProof);
- remove(filename);
- delete [] filename;
- return retval;
- }
- struct mg_connection *distribute_epoch_updates(
- const std::string& recipient,
- int recipientPort,
- const std::string& data,
- struct synchronization_tool* sync)
- {
- struct mg_connection *conn = NULL;
- // Connect to the server
- while (!conn)
- {
- conn = mg_connect_websocket_client(recipient.c_str(), recipientPort, USE_SSL, NULL, 0, SUBMIT_EPOCH_UPDATES_URI, "null", synchro_websocket_data_handler, synchro_websocket_close_handler, sync);
- if (!conn)
- std::cerr << "Couldn't give epoch updates to server at " << recipient << ":" << recipientPort << std::endl;
- }
- // Send the update
- mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), data.length());
- mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
- return conn;
- }
- /*
- * SCORE TALLYING AND DISTRIBUTION HELPERS
- */
- void tally_scores(
- PrsonaServer *prsonaServer,
- const std::vector<std::string>& serverIPs,
- const std::vector<int>& serverPorts,
- const std::string& selfIP,
- int selfPort,
- const Twistpoint& nextGenerator,
- std::vector<EGCiphertext>& userTallyScores,
- std::vector<CurveBipoint>& serverTallyScores,
- std::vector<size_t>& bandwidthData)
- {
- struct synchronization_tool sync;
- std::vector<struct mg_connection *> conns;
- std::vector<std::vector<size_t>> allBandwidthDataBefore;
- // Connect to each server (roughly in parallel)
- std::unique_lock<std::mutex> lck(sync.mtx);
- sync.val = 1;
- for (size_t i = 0; i < serverIPs.size(); i++)
- {
- // Except, skip ourselves (obviously)
- if (serverIPs[i] == selfIP && serverPorts[i] == selfPort)
- continue;
-
- struct mg_connection *currConn = NULL;
- while (!currConn)
- {
- currConn = mg_connect_websocket_client(serverIPs[i].c_str(), serverPorts[i], USE_SSL, NULL, 0, REQUEST_PARTIAL_DECRYPTION_URI, "null", synchro_websocket_data_handler, synchro_websocket_close_handler, &sync);
- if (!currConn)
- std::cerr << "Trouble getting partial decryption from server at " << serverIPs[i] << ":" << serverPorts[i] << std::endl;
- }
- allBandwidthDataBefore.push_back(get_conn_log_data(mg_get_context(currConn), true));
- // Ping server for simulated distributed BGN
- mg_websocket_client_write(currConn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
- conns.push_back(currConn);
- }
- // Since we're only simulating distributed BGN, we're only waiting for ACKs here
- while (sync.val < serverIPs.size())
- sync.cv.wait(lck);
- // Close connections
- for (size_t i = 0; i < conns.size(); i++)
- {
- std::vector<size_t> currBandwidthDataAfter = get_conn_log_data(mg_get_context(conns[i]), true);
- bandwidthData[0] += currBandwidthDataAfter[0] - allBandwidthDataBefore[i][0];
- bandwidthData[1] += currBandwidthDataAfter[1] - allBandwidthDataBefore[i][1];
- mg_close_connection(conns[i]);
- }
- // Now we do the actual calculations
- std::vector<EGCiphertext> retval;
- std::vector<Twistpoint> currentPseudonyms = prsonaServer->get_current_pseudonyms();
- std::vector<Scalar> decryptedTalliedScores = prsonaServer->tally_scores();
- mpz_class maxScorePossibleThisRound = prsonaServer->get_max_possible_score().toInt() * PrsonaBase::get_max_allowed_vote();
- mpz_class topOfScoreRange = decryptedTalliedScores.size() * PrsonaBase::get_max_allowed_vote();
- userTallyScores.clear();
- serverTallyScores.clear();
- for (size_t i = 0; i < decryptedTalliedScores.size(); i++)
- {
- // Scale scores correctly to keep in the desired range
- decryptedTalliedScores[i] = Scalar((decryptedTalliedScores[i].toInt() * topOfScoreRange) / maxScorePossibleThisRound);
- EGCiphertext currCiphertext;
- userTallyScores.push_back(currCiphertext);
- CurveBipoint currServerScore;
- serverTallyScores.push_back(currServerScore);
- Scalar currMask;
- currMask.set_random();
- // Give the server the new weights for the next epoch's calculation, to get passed around to the other servers
- prsonaServer->encrypt(serverTallyScores[i], decryptedTalliedScores[i]);
- // Encrypt the scores for the partway pseudonyms (since we're in the middle of the epoch calculations)
- userTallyScores[i].mask = currentPseudonyms[i] * currMask;
- userTallyScores[i].encryptedMessage = (nextGenerator * currMask) + (prsonaServer->get_blinding_generator() * decryptedTalliedScores[i]);
- }
- }
- void distribute_tallied_scores(
- PrsonaServer *prsonaServer,
- const std::vector<std::string>& serverIPs,
- const std::vector<int>& serverPorts,
- const std::string& selfIP,
- int selfPort,
- const Twistpoint& nextGenerator,
- const std::vector<EGCiphertext>& userTallyScores,
- const std::vector<CurveBipoint>& serverTallyScores,
- std::vector<size_t>& bandwidthData)
- {
- // Serialize scores
- std::stringstream buffer;
- std::string data;
- BinarySizeT sizeOfVector(userTallyScores.size());
- buffer << sizeOfVector;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- buffer << userTallyScores[i];
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- buffer << serverTallyScores[i];
- data = buffer.str();
- struct synchronization_tool sync;
- std::vector<struct mg_connection *> conns;
- std::vector<std::vector<size_t>> allBandwidthDataBefore;
- // Connect to each server (roughly in parallel)
- std::unique_lock<std::mutex> lck(sync.mtx);
- sync.val = 1;
- for (size_t i = 0; i < serverIPs.size(); i++)
- {
- // When it's our turn, receive our actual new scores for the next epoch
- if (serverIPs[i] == selfIP && serverPorts[i] == selfPort)
- {
- prsonaServer->receive_tallied_scores(userTallyScores, serverTallyScores);
- continue;
- }
-
- struct mg_connection *currConn = NULL;
- while (!currConn)
- {
- currConn = mg_connect_websocket_client(serverIPs[i].c_str(), serverPorts[i], USE_SSL, NULL, 0, SUBMIT_PARTIAL_DECRYPTION_URI, "null", synchro_websocket_data_handler, synchro_websocket_close_handler, &sync);
- if (!currConn)
- std::cerr << "Trouble giving full re-encryption to server at " << serverIPs[i] << ":" << serverPorts[i] << std::endl;
- }
- allBandwidthDataBefore.push_back(get_conn_log_data(mg_get_context(currConn), false));
- // Send the relevant data
- mg_websocket_client_write(currConn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), data.length());
- mg_websocket_client_write(currConn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
- conns.push_back(currConn);
- }
- // Wait for each server to ACK the scores
- while (sync.val < serverIPs.size())
- sync.cv.wait(lck);
- // Close connections
- for (size_t i = 0; i < conns.size(); i++)
- {
- std::vector<size_t> currBandwidthDataAfter = get_conn_log_data(mg_get_context(conns[i]), false);
- bandwidthData[0] += currBandwidthDataAfter[0] - allBandwidthDataBefore[i][0];
- bandwidthData[1] += currBandwidthDataAfter[1] - allBandwidthDataBefore[i][1];
- mg_close_connection(conns[i]);
- }
- }
- /*
- * FILE I/O HELPERS
- */
- BGN get_bgn_private_key_from_file(
- const char *filename)
- {
- std::ifstream bgnFile(filename);
- BGN privateKey;
- bgnFile >> privateKey;
- return privateKey;
- }
- Twistpoint get_generator_from_file(
- const char *filename,
- Proof& pi)
- {
- std::ifstream genFile(filename);
- Twistpoint retval;
- genFile >> pi;
- genFile >> retval;
- return retval;
- }
- Twistpoint get_generator_from_file(
- const char *filename,
- std::vector<Proof>& pi)
- {
- std::ifstream epochFile(filename);
-
- Twistpoint retval;
- BinarySizeT sizeOfVector;
- pi.clear();
- epochFile >> sizeOfVector;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- {
- Proof currProof;
- epochFile >> currProof;
- pi.push_back(currProof);
- }
- epochFile >> retval;
- return retval;
- }
- /*
- * EPOCH DATA SERIALIZERS/UN-SERIALIZERS
- */
- std::string make_epoch_initiator_string(
- const std::vector<Proof>& generatorProof,
- const Twistpoint& nextGenerator)
- {
- std::stringstream buffer;
-
- BinarySizeT sizeOfVector(generatorProof.size());
- buffer << sizeOfVector;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- buffer << generatorProof[i];
-
- buffer << nextGenerator;
- return buffer.str();
- }
- ssize_t read_epoch_initiator_string(
- const char *filename,
- std::vector<Proof>& generatorProof,
- Twistpoint& nextGenerator)
- {
- std::ifstream file(filename);
- file.ignore(std::numeric_limits<std::streamsize>::max());
- std::streamsize retval = file.gcount();
- file.clear();
- file.seekg(0, std::ios_base::beg);
- BinarySizeT sizeOfVector;
- generatorProof.clear();
- file >> sizeOfVector;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- {
- Proof currProof;
- file >> currProof;
- generatorProof.push_back(currProof);
- }
-
- file >> nextGenerator;
- return retval;
- }
- std::string make_epoch_update_string(
- const std::vector<std::vector<Proof>>& pi,
- const std::vector<std::vector<Twistpoint>>& permutationCommits,
- const std::vector<std::vector<Twistpoint>>& freshPseudonymCommits,
- const std::vector<std::vector<Twistpoint>>& freshPseudonymSeedCommits,
- const std::vector<std::vector<CurveBipoint>>& serverTallyCommits,
- const std::vector<std::vector<std::vector<TwistBipoint>>>& partwayVoteMatrixCommits,
- const std::vector<std::vector<std::vector<TwistBipoint>>>& finalVoteMatrixCommits,
- const std::vector<std::vector<Twistpoint>>& userTallyMaskCommits,
- const std::vector<std::vector<Twistpoint>>& userTallyMessageCommits,
- const std::vector<std::vector<Twistpoint>>& userTallySeedCommits,
- const Twistpoint& nextGenerator,
- bool doUserTallies)
- {
- std::stringstream buffer;
-
- BinarySizeT sizeOfVectorI, sizeOfVectorJ;
- sizeOfVectorI.set(pi.size());
- buffer << sizeOfVectorI;
- for (size_t i = 0; i < sizeOfVectorI.val(); i++)
- {
- sizeOfVectorJ.set(pi[i].size());
- buffer << sizeOfVectorJ;
- for (size_t j = 0; j < sizeOfVectorJ.val(); j++)
- buffer << pi[i][j];
- }
- sizeOfVectorI.set(permutationCommits.size());
- buffer << sizeOfVectorI;
- for (size_t i = 0; i < sizeOfVectorI.val(); i++)
- for (size_t j = 0; j < sizeOfVectorI.val(); j++)
- buffer << permutationCommits[i][j];
- sizeOfVectorI.set(freshPseudonymCommits.size());
- buffer << sizeOfVectorI;
- for (size_t i = 0; i < sizeOfVectorI.val(); i++)
- for (size_t j = 0; j < sizeOfVectorI.val(); j++)
- buffer << freshPseudonymCommits[i][j];
- sizeOfVectorI.set(freshPseudonymSeedCommits.size());
- buffer << sizeOfVectorI;
- for (size_t i = 0; i < sizeOfVectorI.val(); i++)
- for (size_t j = 0; j < sizeOfVectorI.val(); j++)
- buffer << freshPseudonymSeedCommits[i][j];
- sizeOfVectorI.set(serverTallyCommits.size());
- buffer << sizeOfVectorI;
- for (size_t i = 0; i < sizeOfVectorI.val(); i++)
- for (size_t j = 0; j < sizeOfVectorI.val(); j++)
- buffer << serverTallyCommits[i][j];
- sizeOfVectorI.set(partwayVoteMatrixCommits.size());
- buffer << sizeOfVectorI;
- for (size_t i = 0; i < sizeOfVectorI.val(); i++)
- for (size_t j = 0; j < sizeOfVectorI.val(); j++)
- for (size_t k = 0; k < sizeOfVectorI.val(); k++)
- buffer << partwayVoteMatrixCommits[i][j][k];
- sizeOfVectorI.set(finalVoteMatrixCommits.size());
- buffer << sizeOfVectorI;
- for (size_t i = 0; i < sizeOfVectorI.val(); i++)
- for (size_t j = 0; j < sizeOfVectorI.val(); j++)
- for (size_t k = 0; k < sizeOfVectorI.val(); k++)
- buffer << finalVoteMatrixCommits[i][j][k];
- sizeOfVectorI.set(userTallyMaskCommits.size());
- buffer << sizeOfVectorI;
- for (size_t i = 0; i < sizeOfVectorI.val(); i++)
- for (size_t j = 0; j < sizeOfVectorI.val(); j++)
- buffer << userTallyMaskCommits[i][j];
- sizeOfVectorI.set(userTallyMessageCommits.size());
- buffer << sizeOfVectorI;
- for (size_t i = 0; i < sizeOfVectorI.val(); i++)
- for (size_t j = 0; j < sizeOfVectorI.val(); j++)
- buffer << userTallyMessageCommits[i][j];
- sizeOfVectorI.set(userTallySeedCommits.size());
- buffer << sizeOfVectorI;
- for (size_t i = 0; i < sizeOfVectorI.val(); i++)
- for (size_t j = 0; j < sizeOfVectorI.val(); j++)
- buffer << userTallySeedCommits[i][j];
- buffer << nextGenerator;
- BinaryBool flag(doUserTallies);
- buffer << flag;
- return buffer.str();
- }
- ssize_t read_epoch_update_string(
- const char *filename,
- std::vector<std::vector<Proof>>& pi,
- std::vector<std::vector<Twistpoint>>& permutationCommits,
- std::vector<std::vector<Twistpoint>>& freshPseudonymCommits,
- std::vector<std::vector<Twistpoint>>& freshPseudonymSeedCommits,
- std::vector<std::vector<CurveBipoint>>& serverTallyCommits,
- std::vector<std::vector<std::vector<TwistBipoint>>>& partwayVoteMatrixCommits,
- std::vector<std::vector<std::vector<TwistBipoint>>>& finalVoteMatrixCommits,
- std::vector<std::vector<Twistpoint>>& userTallyMaskCommits,
- std::vector<std::vector<Twistpoint>>& userTallyMessageCommits,
- std::vector<std::vector<Twistpoint>>& userTallySeedCommits,
- Twistpoint& nextGenerator,
- bool& doUserTallies)
- {
- std::ifstream file(filename);
- file.ignore(std::numeric_limits<std::streamsize>::max());
- std::streamsize retval = file.gcount();
- file.clear();
- file.seekg(0, std::ios_base::beg);
- BinarySizeT sizeOfVectorI, sizeOfVectorJ;
-
- pi.clear();
- permutationCommits.clear();
- freshPseudonymCommits.clear();
- freshPseudonymSeedCommits.clear();
- serverTallyCommits.clear();
- partwayVoteMatrixCommits.clear();
- finalVoteMatrixCommits.clear();
- userTallyMaskCommits.clear();
- userTallyMessageCommits.clear();
- userTallySeedCommits.clear();
- file >> sizeOfVectorI;
- for (size_t i = 0; i < sizeOfVectorI.val(); i++)
- {
- std::vector<Proof> currRow;
- file >> sizeOfVectorJ;
- for (size_t j = 0; j < sizeOfVectorJ.val(); j++)
- {
- Proof currProof;
- file >> currProof;
- currRow.push_back(currProof);
- }
- pi.push_back(currRow);
- }
- file >> sizeOfVectorI;
- for (size_t i = 0; i < sizeOfVectorI.val(); i++)
- {
- std::vector<Twistpoint> currRow;
- for (size_t j = 0; j < sizeOfVectorI.val(); j++)
- {
- Twistpoint currCommit;
- file >> currCommit;
- currRow.push_back(currCommit);
- }
- permutationCommits.push_back(currRow);
- }
- file >> sizeOfVectorI;
- for (size_t i = 0; i < sizeOfVectorI.val(); i++)
- {
- std::vector<Twistpoint> currRow;
- for (size_t j = 0; j < sizeOfVectorI.val(); j++)
- {
- Twistpoint currCommit;
- file >> currCommit;
- currRow.push_back(currCommit);
- }
- freshPseudonymCommits.push_back(currRow);
- }
- file >> sizeOfVectorI;
- for (size_t i = 0; i < sizeOfVectorI.val(); i++)
- {
- std::vector<Twistpoint> currRow;
- for (size_t j = 0; j < sizeOfVectorI.val(); j++)
- {
- Twistpoint currCommit;
- file >> currCommit;
- currRow.push_back(currCommit);
- }
- freshPseudonymSeedCommits.push_back(currRow);
- }
- file >> sizeOfVectorI;
- for (size_t i = 0; i < sizeOfVectorI.val(); i++)
- {
- std::vector<CurveBipoint> currRow;
- for (size_t j = 0; j < sizeOfVectorI.val(); j++)
- {
- CurveBipoint currCommit;
- file >> currCommit;
- currRow.push_back(currCommit);
- }
- serverTallyCommits.push_back(currRow);
- }
- file >> sizeOfVectorI;
- for (size_t i = 0; i < sizeOfVectorI.val(); i++)
- {
- std::vector<std::vector<TwistBipoint>> currMatrix;
- for (size_t j = 0; j < sizeOfVectorI.val(); j++)
- {
- std::vector<TwistBipoint> currRow;
- for (size_t k = 0; k < sizeOfVectorI.val(); k++)
- {
- TwistBipoint currCommit;
- file >> currCommit;
- currRow.push_back(currCommit);
- }
- currMatrix.push_back(currRow);
- }
- partwayVoteMatrixCommits.push_back(currMatrix);
- }
- file >> sizeOfVectorI;
- for (size_t i = 0; i < sizeOfVectorI.val(); i++)
- {
- std::vector<std::vector<TwistBipoint>> currMatrix;
- for (size_t j = 0; j < sizeOfVectorI.val(); j++)
- {
- std::vector<TwistBipoint> currRow;
- for (size_t k = 0; k < sizeOfVectorI.val(); k++)
- {
- TwistBipoint currCommit;
- file >> currCommit;
- currRow.push_back(currCommit);
- }
- currMatrix.push_back(currRow);
- }
- finalVoteMatrixCommits.push_back(currMatrix);
- }
- file >> sizeOfVectorI;
- for (size_t i = 0; i < sizeOfVectorI.val(); i++)
- {
- std::vector<Twistpoint> currRow;
- for (size_t j = 0; j < sizeOfVectorI.val(); j++)
- {
- Twistpoint currCommit;
- file >> currCommit;
- currRow.push_back(currCommit);
- }
- userTallyMaskCommits.push_back(currRow);
- }
- file >> sizeOfVectorI;
- for (size_t i = 0; i < sizeOfVectorI.val(); i++)
- {
- std::vector<Twistpoint> currRow;
- for (size_t j = 0; j < sizeOfVectorI.val(); j++)
- {
- Twistpoint currCommit;
- file >> currCommit;
- currRow.push_back(currCommit);
- }
- userTallyMessageCommits.push_back(currRow);
- }
- file >> sizeOfVectorI;
- for (size_t i = 0; i < sizeOfVectorI.val(); i++)
- {
- std::vector<Twistpoint> currRow;
- for (size_t j = 0; j < sizeOfVectorI.val(); j++)
- {
- Twistpoint currCommit;
- file >> currCommit;
- currRow.push_back(currCommit);
- }
- userTallySeedCommits.push_back(currRow);
- }
- file >> nextGenerator;
-
- BinaryBool binaryDoUserTallies;
- file >> binaryDoUserTallies;
- doUserTallies = binaryDoUserTallies.val();
- return retval;
- }
- /**********************************************************
- **** ****
- **** other server-relevant handler member functions ****
- **** ****
- **********************************************************/
- /*
- * EPOCH READY HANDLER
- */
- EpochReadyHandler::EpochReadyHandler(
- struct synchronization_tool *exitSync,
- struct synchronization_tool *readySync,
- std::mutex& updateMtx,
- size_t numServers)
- : exitSync(exitSync), readySync(readySync), updateMtx(updateMtx), numServers(numServers)
- { /* */ }
- bool EpochReadyHandler::handleGet(
- CivetServer *server,
- struct mg_connection *conn)
- {
- std::unique_lock<std::mutex> exitLock(exitSync->mtx, std::defer_lock);
- std::unique_lock<std::mutex> updateLock(updateMtx, std::defer_lock);
- std::unique_lock<std::mutex> readyLock(readySync->mtx);
- if (readySync->val < numServers)
- {
- mg_printf(conn, "HTTP/1.1 503 Service Unavailable\r\n"
- "Content-Type: text/plain\r\n"
- "Connection: close\r\n\r\n");
- mg_printf(conn, "Server is waiting for other servers to begin.\n");
- }
- else if (!exitLock.try_lock())
- {
- mg_printf(conn, "HTTP/1.1 503 Service Unavailable\r\n"
- "Content-Type: text/plain\r\n"
- "Connection: close\r\n\r\n");
- mg_printf(conn, "Server is still in a previous epoch.\n");
- }
- else if (!updateLock.try_lock())
- {
- mg_printf(conn, "HTTP/1.1 503 Service Unavailable\r\n"
- "Content-Type: text/plain\r\n"
- "Connection: close\r\n\r\n");
- mg_printf(conn, "Server is handling other updates.\n");
- }
- else
- {
- mg_printf(conn, "HTTP/1.1 200 OK\r\n"
- "Content-Type: text/plain\r\n"
- "Connection: close\r\n\r\n");
- mg_printf(conn, "Server is ready for epoch.\n");
- }
- return true;
- }
- /*
- * EPOCH NUM HANDLER
- */
- EpochNumHandler::EpochNumHandler(
- std::atomic<size_t>& epochNum)
- : epochNum(epochNum)
- { /* */ }
- bool EpochNumHandler::handleGet(
- CivetServer *server,
- struct mg_connection *conn)
- {
- mg_printf(conn, "HTTP/1.1 200 OK\r\n"
- "Content-Type: text/plain\r\n"
- "Connection: close\r\n\r\n");
- mg_printf(conn, "Epoch num: %lu\n", epochNum.load());
- return true;
- }
- /*
- * UPDATE LOCK HANDLER
- */
- UpdateLockWebSocketHandler::UpdateLockWebSocketHandler(
- std::mutex& updateMtx,
- std::unique_lock<std::mutex> **lockHolder,
- bool isLocking)
- : updateMtx(updateMtx), lockHolder(lockHolder), isLocking(isLocking)
- { /* */ }
- UpdateLockWebSocketHandler::~UpdateLockWebSocketHandler()
- {
- delete *lockHolder;
- *lockHolder = NULL;
- }
- bool UpdateLockWebSocketHandler::handleConnection(
- CivetServer *server,
- const struct mg_connection *conn)
- {
- return true;
- }
- void UpdateLockWebSocketHandler::handleReadyState(
- CivetServer *server,
- struct mg_connection *conn)
- { /* */ }
- bool UpdateLockWebSocketHandler::handleData(
- CivetServer *server,
- struct mg_connection *conn,
- int bits,
- char *data,
- size_t data_len)
- {
- switch (bits & 0xf)
- {
- case MG_WEBSOCKET_OPCODE_DATACOMPLETE:
- if (isLocking)
- {
- std::unique_lock<std::mutex> *tempHolder = new std::unique_lock<std::mutex>(updateMtx);
-
- // Once you get to this line, we now hold the lock, and lockHolder is guaranteed to be NULL
- *lockHolder = tempHolder;
- // Respond to notify that the requesting process holds the lock
- mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
- }
- else
- {
- // You must do things in this order so that *lockHolder will be guaranteed to be NULL at the time the lock unlocks (deletion of the lock object)
- std::unique_lock<std::mutex> *tempHolder = *lockHolder;
- *lockHolder = NULL;
- delete tempHolder;
-
- // Respond to notify that the requesting process has released the lock
- mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
- }
- break;
- case MG_WEBSOCKET_OPCODE_CONNECTION_CLOSE:
- break;
- default:
- std::cerr << "Unknown opcode: failing." << std::endl;
- break;
- }
- return false;
- }
- void UpdateLockWebSocketHandler::handleClose(
- CivetServer *server,
- const struct mg_connection *conn)
- { /* */ }
- /*********************************************************
- **** ****
- **** PrsonaServerWebSocketHandler member functions ****
- **** ****
- *********************************************************/
- /*
- * CONSTRUCTOR
- */
- PrsonaServerWebSocketHandler::PrsonaServerWebSocketHandler(
- std::default_random_engine& rng,
- PrsonaServer *prsonaServer,
- const std::vector<std::string>& serverIPs,
- const std::vector<int>& serverPorts,
- const std::string& selfIP,
- int selfPort,
- std::mutex& updateMtx,
- std::atomic<size_t>& epochNum,
- std::mutex& buildUpOutputMtx,
- const std::string& buildUpOutputFilename,
- std::mutex& breakDownOutputMtx,
- const std::string& breakDownOutputFilename,
- std::mutex& updateOutputMtx,
- const std::string& updateOutputFilename,
- std::mutex& voteOutputMtx,
- const std::string& voteOutputFilename,
- std::mutex& usageMtx,
- const std::string& usageFilename)
- : rng(rng), prsonaServer(prsonaServer), serverIPs(serverIPs), serverPorts(serverPorts), selfIP(selfIP), selfPort(selfPort), updateMtx(updateMtx), epochNum(epochNum), buildUpOutputMtx(buildUpOutputMtx), buildUpOutputFilename(buildUpOutputFilename), breakDownOutputMtx(breakDownOutputMtx), breakDownOutputFilename(breakDownOutputFilename), updateOutputMtx(updateOutputMtx), updateOutputFilename(updateOutputFilename), voteOutputMtx(voteOutputMtx), voteOutputFilename(voteOutputFilename), usageMtx(usageMtx), usageFilename(usageFilename)
- { /* */ }
- /*
- * REQUIRED BY INHERITED CLASS
- */
- bool PrsonaServerWebSocketHandler::handleConnection(
- CivetServer *server,
- const struct mg_connection *conn)
- {
- const struct mg_request_info *info = mg_get_request_info(conn);
-
- // Check if the request being made is something this server can respond to
- bool flag = info->query_string && info->query_string[0] >= PRSONA_GIVE_BGN_PUBKEY && info->query_string[0] <= PRSONA_RECEIVE_EPOCH_UPDATE;
- flag = flag || (info->query_string && info->query_string[0] == PRSONA_GIVE_PARTIAL_DECRYPTION);
- flag = flag || (info->query_string && info->query_string[0] == PRSONA_RECEIVE_PARTIAL_DECRYPTION);
- return flag;
- }
- void PrsonaServerWebSocketHandler::handleReadyState(
- CivetServer *server,
- struct mg_connection *conn)
- {
- const struct mg_request_info *info = mg_get_request_info(conn);
- // Set filenames for query types that will need to un-serialize data to respond correctly
- switch (info->query_string[0])
- {
- case PRSONA_GIVE_VOTE_ROW:
- case PRSONA_GIVE_VOTE_MATRIX:
- case PRSONA_GIVE_CLIENT_TALLY:
- case PRSONA_GIVE_SERVER_TALLY:
- case PRSONA_GIVE_PSEUDONYMS:
- case PRSONA_GIVE_VOTE_ROW_COMMITMENT:
- case PRSONA_GIVE_VOTE_MATRIX_COMMITMENT:
- case PRSONA_GIVE_CLIENT_TALLY_COMMITMENT:
- case PRSONA_GIVE_SERVER_TALLY_COMMITMENT:
- case PRSONA_GIVE_PSEUDONYMS_COMMITMENT:
- case PRSONA_RECEIVE_NEW_CLIENT:
- case PRSONA_RECEIVE_VOTE:
- case PRSONA_RECEIVE_UPDATE_WITH_NEW_USER:
- case PRSONA_ADD_CURR_SEED_TO_GENERATOR:
- case PRSONA_RECEIVE_FRESH_GENERATOR:
- case PRSONA_ADD_RAND_SEED_TO_GENERATOR:
- case PRSONA_RECEIVE_EG_BLIND_GENERATOR:
- case PRSONA_PERFORM_EPOCH_BUILD_UP:
- case PRSONA_PERFORM_EPOCH_BREAK_DOWN:
- case PRSONA_RECEIVE_EPOCH_UPDATE:
- case PRSONA_RECEIVE_PARTIAL_DECRYPTION:
- set_temp_filename(rng, conn);
- break;
- default:
- mg_set_user_connection_data(conn, NULL);
- break;
- }
- }
- bool PrsonaServerWebSocketHandler::handleData(
- CivetServer *server,
- struct mg_connection *conn,
- int bits,
- char *data,
- size_t data_len)
- {
- char *filename = (char *) mg_get_user_connection_data(conn);
- FILE *currFile = NULL;
- switch (bits & 0xf)
- {
- // Requester has indicated they have sent all relevant data
- case MG_WEBSOCKET_OPCODE_CONNECTION_CLOSE:
- case MG_WEBSOCKET_OPCODE_DATACOMPLETE:
- generate_response(server, conn, filename);
- break;
- // Requester has sent more data (which may theoretically be broken up into multiple packets)
- case MG_WEBSOCKET_OPCODE_BINARY:
- case MG_WEBSOCKET_OPCODE_CONTINUATION:
- currFile = fopen(filename, "ab");
- fwrite(data, sizeof(char), data_len, currFile);
- fclose(currFile);
- return true;
- // Something strange has happened
- default:
- std::cerr << "Unknown packet type received. Failing." << std::endl;
- break;
- }
- return false;
- }
- void PrsonaServerWebSocketHandler::handleClose(
- CivetServer *server,
- const struct mg_connection *conn)
- {
- char *filename = (char *) mg_get_user_connection_data(conn);
- // If we didn't have a temp file for this request, don't do anything
- if (!filename)
- return;
- // If we did, delete it
- remove(filename);
- delete [] filename;
- }
- /*
- * RESPONSE ROUTER FUNCTION
- */
- void PrsonaServerWebSocketHandler::generate_response(
- CivetServer *server,
- struct mg_connection *conn,
- const char *filename)
- {
- const struct mg_request_info *info = mg_get_request_info(conn);
- // Select the correct response for this type of request
- switch (info->query_string[0])
- {
- // BASIC PUBLIC SYSTEM INFO GETTERS
- case PRSONA_GIVE_BGN_PUBKEY:
- get_bgn_public_key(conn);
- break;
- case PRSONA_GIVE_NUM_CLIENTS:
- get_num_clients(conn);
- break;
- case PRSONA_GIVE_NUM_SERVERS:
- get_num_servers(conn);
- break;
- case PRSONA_GIVE_FRESH_GENERATOR:
- get_generator(conn, true);
- break;
- case PRSONA_GIVE_EG_BLIND_GENERATOR:
- get_generator(conn, false);
- break;
- // ENCRYPTED DATA GETTERS
- case PRSONA_GIVE_VOTE_ROW:
- get_current_votes_by(conn, filename);
- break;
- case PRSONA_GIVE_VOTE_MATRIX:
- get_all_current_votes(conn);
- break;
- case PRSONA_GIVE_CLIENT_TALLY:
- get_current_user_encrypted_tally(conn, filename);
- break;
- case PRSONA_GIVE_SERVER_TALLY:
- get_current_server_encrypted_tally(conn, filename);
- break;
- case PRSONA_GIVE_PSEUDONYMS:
- get_current_pseudonyms(conn);
- break;
- // PROOF COMMITMENT GETTERS
- case PRSONA_GIVE_VOTE_ROW_COMMITMENT:
- get_vote_row_commitment(conn, filename);
- break;
- case PRSONA_GIVE_VOTE_MATRIX_COMMITMENT:
- get_vote_matrix_commitment(conn);
- break;
- case PRSONA_GIVE_CLIENT_TALLY_COMMITMENT:
- get_user_tally_commitment(conn, filename);
- break;
- case PRSONA_GIVE_SERVER_TALLY_COMMITMENT:
- get_server_tally_commitment(conn, filename);
- break;
- case PRSONA_GIVE_PSEUDONYMS_COMMITMENT:
- get_pseudonyms_commitment(conn);
- break;
- // CLIENT INTERACTIONS
- case PRSONA_RECEIVE_NEW_CLIENT:
- add_new_client(conn, filename);
- break;
- case PRSONA_RECEIVE_VOTE:
- receive_vote(server, conn, filename);
- break;
- // CLIENT INTERACTION HELPER
- case PRSONA_RECEIVE_UPDATE_WITH_NEW_USER:
- import_new_user_update(conn, filename);
- break;
- // CONSTRUCTOR HELPERS
- case PRSONA_GIVE_BGN_PRIVKEY:
- get_bgn_details(conn);
- break;
- case PRSONA_ADD_CURR_SEED_TO_GENERATOR:
- add_seed_to_generator(conn, filename, true);
- break;
- case PRSONA_RECEIVE_FRESH_GENERATOR:
- set_generator(filename, true);
- break;
- case PRSONA_ADD_RAND_SEED_TO_GENERATOR:
- add_seed_to_generator(conn, filename, false);
- break;
- case PRSONA_RECEIVE_EG_BLIND_GENERATOR:
- set_generator(filename, false);
- break;
- // EPOCH ROUNDS
- case PRSONA_PERFORM_EPOCH_BUILD_UP:
- build_up_midway_pseudonyms(server, conn, filename);
- break;
- case PRSONA_PERFORM_EPOCH_BREAK_DOWN:
- break_down_midway_pseudonyms(server, conn, filename);
- break;
- case PRSONA_RECEIVE_EPOCH_UPDATE:
- accept_epoch_updates(server, conn, filename);
- break;
- // DISTRIBUTED BGN
- case PRSONA_GIVE_PARTIAL_DECRYPTION:
- get_partial_decryption(conn);
- break;
- case PRSONA_RECEIVE_PARTIAL_DECRYPTION:
- receive_tallied_scores(conn, filename);
- break;
- default:
- break;
- }
- }
- /*
- * BASIC PUBLIC SYSTEM INFO GETTERS
- */
- void PrsonaServerWebSocketHandler::get_bgn_public_key(
- struct mg_connection *conn) const
- {
- // Retrieve value
- BGNPublicKey pubKey = prsonaServer->get_bgn_public_key();
- // Serialize response
- std::stringstream buffer;
- std::string data;
- buffer << pubKey;
- data = buffer.str();
- // Send response
- mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), data.length());
- }
- void PrsonaServerWebSocketHandler::get_num_clients(
- struct mg_connection *conn) const
- {
- // Retrieve value
- BinarySizeT numClients(prsonaServer->get_num_clients());
- // Serialize response
- std::stringstream buffer;
- std::string data;
- buffer << numClients;
- data = buffer.str();
- // Send response
- mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), data.length());
- }
- void PrsonaServerWebSocketHandler::get_num_servers(
- struct mg_connection *conn) const
- {
- // Retrieve value
- BinarySizeT numServers(prsonaServer->get_num_servers());
- // Serialize response
- std::stringstream buffer;
- std::string data;
- buffer << numServers;
- data = buffer.str();
- // Send response
- mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), data.length());
- }
- void PrsonaServerWebSocketHandler::get_generator(
- struct mg_connection *conn,
- bool fresh)
- {
- // Retrieve value
- Twistpoint generator;
- std::vector<Proof> pi;
- if (fresh)
- generator = prsonaServer->get_fresh_generator(pi);
- else
- generator = prsonaServer->get_blinding_generator(pi);
- // Serialize response
- std::stringstream buffer;
- std::string data;
- BinarySizeT sizeOfVector(pi.size());
- buffer << sizeOfVector;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- buffer << pi[i];
- buffer << generator;
- data = buffer.str();
- // Send response
- mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), data.length());
- mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
- }
- /*
- * ENCRYPTED DATA GETTERS
- */
- void PrsonaServerWebSocketHandler::get_current_votes_by(
- struct mg_connection *conn,
- const char *filename) const
- {
- std::ifstream file(filename);
- // Un-serialize request
- Twistpoint shortTermPublicKey;
- file >> shortTermPublicKey;
- // Retrieve value
- Proof pi;
- std::vector<TwistBipoint> votes = prsonaServer->get_current_votes_by(pi, shortTermPublicKey);
- // Serialize response
- std::stringstream buffer;
- std::string data;
- buffer << pi;
- BinarySizeT sizeOfVector(votes.size());
- buffer << sizeOfVector;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- buffer << votes[i];
- data = buffer.str();
- // Send response
- mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), data.length());
- }
- void PrsonaServerWebSocketHandler::get_all_current_votes(
- struct mg_connection *conn) const
- {
- // Retrieve value
- Proof pi;
- std::vector<std::vector<TwistBipoint>> votes = prsonaServer->get_all_current_votes(pi);
- // Serialize response
- std::stringstream buffer;
- std::string data;
- buffer << pi;
- BinarySizeT sizeOfVector(votes.size());
- buffer << sizeOfVector;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- for (size_t j = 0; j < sizeOfVector.val(); j++)
- buffer << votes[i][j];
- data = buffer.str();
- // Send response
- mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), data.length());
- }
- void PrsonaServerWebSocketHandler::get_current_user_encrypted_tally(
- struct mg_connection *conn,
- const char *filename) const
- {
- std::ifstream file(filename);
- // Un-serialize request
- Twistpoint shortTermPublicKey;
- file >> shortTermPublicKey;
- // Retrieve value
- Proof pi;
- EGCiphertext tally = prsonaServer->get_current_user_encrypted_tally(pi, shortTermPublicKey);
- // Serialize response
- std::stringstream buffer;
- std::string data;
- buffer << pi;
- buffer << tally;
- data = buffer.str();
- // Send response
- mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), data.length());
- }
- void PrsonaServerWebSocketHandler::get_current_server_encrypted_tally(
- struct mg_connection *conn,
- const char *filename) const
- {
- std::ifstream file(filename);
- // Un-serialize request
- Twistpoint shortTermPublicKey;
- file >> shortTermPublicKey;
- // Retrieve value
- Proof pi;
- CurveBipoint tally = prsonaServer->get_current_server_encrypted_tally(pi, shortTermPublicKey);
- // Serialize response
- std::stringstream buffer;
- std::string data;
- buffer << pi;
- buffer << tally;
- data = buffer.str();
- // Send response
- mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), data.length());
- }
- void PrsonaServerWebSocketHandler::get_current_pseudonyms(
- struct mg_connection *conn) const
- {
- // Retrieve value
- Proof pi;
- std::vector<Twistpoint> pseudonyms = prsonaServer->get_current_pseudonyms(pi);
- // Serialize response
- std::stringstream buffer;
- std::string data;
- buffer << pi;
- BinarySizeT sizeOfVector(pseudonyms.size());
- buffer << sizeOfVector;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- buffer << pseudonyms[i];
- data = buffer.str();
- // Send response
- mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), data.length());
- }
- /*
- * PROOF COMMITMENT GETTERS
- */
- void PrsonaServerWebSocketHandler::get_vote_row_commitment(
- struct mg_connection *conn,
- const char *filename) const
- {
- std::ifstream file(filename);
- // Un-serialize request
- Twistpoint shortTermPublicKey;
- file >> shortTermPublicKey;
- // Retrieve value
- Proof pi = prsonaServer->get_vote_row_commitment(shortTermPublicKey);
- // Serialize response
- std::stringstream buffer;
- std::string data;
- buffer << pi;
- data = buffer.str();
- // Send response
- mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), data.length());
- }
- void PrsonaServerWebSocketHandler::get_vote_matrix_commitment(
- struct mg_connection *conn) const
- {
- // Retrieve value
- Proof pi = prsonaServer->get_vote_matrix_commitment();
- // Serialize response
- std::stringstream buffer;
- std::string data;
- buffer << pi;
- data = buffer.str();
- // Send response
- mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), data.length());
- }
- void PrsonaServerWebSocketHandler::get_user_tally_commitment(
- struct mg_connection *conn,
- const char *filename) const
- {
- std::ifstream file(filename);
- // Un-serialize request
- Twistpoint shortTermPublicKey;
- file >> shortTermPublicKey;
- // Retrieve value
- Proof pi = prsonaServer->get_user_tally_commitment(shortTermPublicKey);
- // Serialize response
- std::stringstream buffer;
- std::string data;
- buffer << pi;
- data = buffer.str();
- // Send response
- mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), data.length());
- }
- void PrsonaServerWebSocketHandler::get_server_tally_commitment(
- struct mg_connection *conn,
- const char *filename) const
- {
- std::ifstream file(filename);
- // Un-serialize request
- Twistpoint shortTermPublicKey;
- file >> shortTermPublicKey;
- // Retrieve value
- Proof pi = prsonaServer->get_server_tally_commitment(shortTermPublicKey);
- // Serialize response
- std::stringstream buffer;
- std::string data;
- buffer << pi;
- data = buffer.str();
- // Send response
- mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), data.length());
- }
- void PrsonaServerWebSocketHandler::get_pseudonyms_commitment(
- struct mg_connection *conn) const
- {
- // Retrieve value
- Proof pi = prsonaServer->get_pseudonyms_commitment();
- // Serialize response
- std::stringstream buffer;
- std::string data;
- buffer << pi;
- data = buffer.str();
- // Send response
- mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), data.length());
- }
- /*
- * CLIENT INTERACTIONS
- */
- void PrsonaServerWebSocketHandler::add_new_client(
- struct mg_connection *conn,
- const char *filename)
- {
- std::ifstream file(filename);
- // Un-serialize request
- Proof proofOfValidKey;
- file >> proofOfValidKey;
- Twistpoint shortTermPublicKey, empty;
- file >> shortTermPublicKey;
- std::vector<size_t> bandwidthData(2);
- // Obtain global update lock
- std::unique_lock<std::mutex> updateLock(updateMtx, std::defer_lock);
- obtain_update_locks(updateLock, serverIPs, serverPorts, selfIP, selfPort, bandwidthData);
- // Add new client to server object
- std::vector<Proof> proofOfValidAddition;
- prsonaServer->add_new_client(proofOfValidAddition, proofOfValidKey, shortTermPublicKey);
- // Share this update with other servers
- std::vector<CurveBipoint> previousVoteTallies;
- std::vector<Twistpoint> currentPseudonyms;
- std::vector<EGCiphertext> currentUserEncryptedTallies;
- std::vector<std::vector<TwistBipoint>> voteMatrix;
- prsonaServer->export_new_user_update(previousVoteTallies, currentPseudonyms, currentUserEncryptedTallies, voteMatrix);
- distribute_new_user_updates(proofOfValidAddition, previousVoteTallies, currentPseudonyms, currentUserEncryptedTallies, voteMatrix);
- // Release global update lock
- release_update_locks(updateLock, serverIPs, serverPorts, selfIP, selfPort, bandwidthData);
- // Serialize response
- std::stringstream buffer;
- std::string data;
- BinarySizeT sizeOfVector(proofOfValidAddition.size());
- buffer << sizeOfVector;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- buffer << proofOfValidAddition[i];
- data = buffer.str();
- // Send response
- mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), data.length());
- }
- void PrsonaServerWebSocketHandler::receive_vote(
- CivetServer *civetServer,
- struct mg_connection *conn,
- const char *filename)
- {
- std::ifstream file(filename);
- file.ignore(std::numeric_limits<std::streamsize>::max());
- std::streamsize bandwidthRcv = file.gcount();
- file.clear();
- file.seekg(0, std::ios_base::beg);
- // Un-serialize request
- BinarySizeT sizeOfVector;
- file >> sizeOfVector;
- std::vector<Proof> pi;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- {
- Proof currProof;
- file >> currProof;
- pi.push_back(currProof);
- }
- file >> sizeOfVector;
- std::vector<TwistBipoint> newVotes;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- {
- TwistBipoint currVote;
- file >> currVote;
- newVotes.push_back(currVote);
- }
- Twistpoint shortTermPublicKey;
- file >> shortTermPublicKey;
- BinaryBool shouldDeal;
- file >> shouldDeal;
- // If we're dealing this update to the other servers, obtain global update lock
- std::unique_lock<std::mutex> updateLock(updateMtx, std::defer_lock);
- std::vector<size_t> bandwidthData(2);
- std::vector<size_t> bandwidthDataBefore = get_server_log_data(civetServer->getContext());
- std::chrono::high_resolution_clock::time_point wallTimeBefore = std::chrono::high_resolution_clock::now();
- clock_t cpuTimeBefore = clock();
- if (shouldDeal.val())
- obtain_update_locks(updateLock, serverIPs, serverPorts, selfIP, selfPort, bandwidthData);
- // Load votes into server object
- prsonaServer->receive_vote(pi, newVotes, shortTermPublicKey);
- // If we're dealing this update to the other servers, actually do that
- if (shouldDeal.val())
- {
- distribute_new_vote(pi, newVotes, shortTermPublicKey, bandwidthData);
- // Then release the global update lock
- release_update_locks(updateLock, serverIPs, serverPorts, selfIP, selfPort, bandwidthData);
- }
- clock_t cpuTimeAfter = clock();
- std::chrono::high_resolution_clock::time_point wallTimeAfter = std::chrono::high_resolution_clock::now();
- std::vector<size_t> bandwidthDataAfter = get_server_log_data(civetServer->getContext());
- std::vector<double> timingData(2);
- timingData[0] = std::chrono::duration_cast<std::chrono::duration<double>>(wallTimeAfter - wallTimeBefore).count();
- timingData[1] = ((double)(cpuTimeAfter - cpuTimeBefore)) / CLOCKS_PER_SEC;
- bandwidthData[0] += bandwidthDataAfter[0] - bandwidthDataBefore[0] + bandwidthRcv;
- bandwidthData[1] += bandwidthDataAfter[1] - bandwidthDataBefore[1];
- write_log_data(voteOutputMtx, voteOutputFilename, timingData, bandwidthData);
- write_usage_data(usageMtx, usageFilename);
- // Notify client their request has been completed
- mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
- }
- /*
- * DISTRIBUTION HELPERS FOR CLIENT INTERACTIONS
- */
- void PrsonaServerWebSocketHandler::distribute_new_user_updates(
- const std::vector<Proof>& proofOfValidAddition,
- const std::vector<CurveBipoint>& previousVoteTallies,
- const std::vector<Twistpoint>& currentPseudonyms,
- const std::vector<EGCiphertext>& currentUserEncryptedTallies,
- const std::vector<std::vector<TwistBipoint>>& voteMatrix) const
- {
- struct synchronization_tool sync;
- // Serialize data
- std::stringstream buffer;
- std::string data;
- BinarySizeT sizeOfVector;
- sizeOfVector.set(proofOfValidAddition.size());
- buffer << sizeOfVector;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- buffer << proofOfValidAddition[i];
- sizeOfVector.set(previousVoteTallies.size());
- buffer << sizeOfVector;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- buffer << previousVoteTallies[i];
- sizeOfVector.set(currentPseudonyms.size());
- buffer << sizeOfVector;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- buffer << currentPseudonyms[i];
- sizeOfVector.set(currentUserEncryptedTallies.size());
- buffer << sizeOfVector;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- buffer << currentUserEncryptedTallies[i];
- sizeOfVector.set(voteMatrix.size());
- buffer << sizeOfVector;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- for (size_t j = 0; j < sizeOfVector.val(); j++)
- buffer << voteMatrix[i][j];
- data = buffer.str();
- // Connect to each server and give them data on the new user
- size_t i = 0;
- while (i < serverIPs.size())
- {
- if (serverIPs[i] == selfIP && serverPorts[i] == selfPort)
- {
- i++;
- continue;
- }
- struct mg_connection *conn = NULL;
- std::unique_lock<std::mutex> lck(sync.mtx);
- sync.val = 0;
- sync.val2 = 0;
- while (!conn)
- {
- conn = mg_connect_websocket_client(serverIPs[i].c_str(), serverPorts[i], USE_SSL, NULL, 0, SUBMIT_UPDATE_WITH_NEW_USER_URI, "null", synchro_websocket_data_handler, synchro_websocket_close_handler, &sync);
-
- if (!conn)
- std::cerr << "Couldn't give server " << i << " new user" << std::endl;
- }
- // Send the server the new user data
- mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), data.length());
- mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
- // Wait for its response (or the connection to die)
- while (!sync.val2)
- sync.cv.wait(lck);
- // Close connection
- mg_close_connection(conn);
- // Only move forward once we've confirmed we correctly gave the update (or else we risk synchronization issues!)
- if (sync.val)
- i++;
- }
- }
- void PrsonaServerWebSocketHandler::distribute_new_vote(
- std::vector<Proof> pi,
- std::vector<TwistBipoint> newVotes,
- Twistpoint shortTermPublicKey,
- std::vector<size_t>& bandwidthData) const
- {
- struct synchronization_tool sync;
- // Serialize data
- std::stringstream buffer;
- std::string data;
- BinarySizeT sizeOfVector;
- sizeOfVector.set(pi.size());
- buffer << sizeOfVector;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- buffer << pi[i];
- sizeOfVector.set(newVotes.size());
- buffer << sizeOfVector;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- buffer << newVotes[i];
- buffer << shortTermPublicKey;
- BinaryBool flag(false);
- buffer << flag;
- data = buffer.str();
- // Connect to each server and give them the new votes
- size_t i = 0;
- while (i < serverIPs.size())
- {
- if (serverIPs[i] == selfIP && serverPorts[i] == selfPort)
- {
- i++;
- continue;
- }
- struct mg_connection *conn = NULL;
- std::unique_lock<std::mutex> syncLock(sync.mtx);
- sync.val = 0;
- sync.val2 = 0;
- while (!conn)
- {
- conn = mg_connect_websocket_client(serverIPs[i].c_str(), serverPorts[i], USE_SSL, NULL, 0, SUBMIT_VOTE_URI, "null", synchro_websocket_data_handler, synchro_websocket_close_handler, &sync);
- if (!conn)
- std::cerr << "Couldn't give server " << i << " new vote data" << std::endl;
- }
- std::vector<size_t> bandwidthDataBefore = get_conn_log_data(mg_get_context(conn), false);
-
- // Send the server the new vote data
- mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), data.length());
- mg_websocket_client_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
- // Wait for its response (or the connection to die)
- while (!sync.val2)
- sync.cv.wait(syncLock);
- std::vector<size_t> bandwidthDataAfter = get_conn_log_data(mg_get_context(conn), false);
- bandwidthData[0] += bandwidthDataAfter[0] - bandwidthDataBefore[0];
- bandwidthData[1] += bandwidthDataAfter[1] - bandwidthDataBefore[1];
- // Close connection
- mg_close_connection(conn);
- // Only move forward once we've confirmed we correctly gave the update (or else we risk synchronization issues!)
- if (sync.val)
- i++;
- }
- }
- void PrsonaServerWebSocketHandler::import_new_user_update(
- struct mg_connection *conn,
- const char *filename)
- {
- std::vector<Proof> proofOfValidAddition;
- std::vector<CurveBipoint> previousVoteTallies;
- std::vector<Twistpoint> currentPseudonyms;
- std::vector<EGCiphertext> currentUserEncryptedTallies;
- std::vector<std::vector<TwistBipoint>> voteMatrix;
- std::ifstream file(filename);
- // Un-serialize request
- BinarySizeT sizeOfVector;
-
- file >> sizeOfVector;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- {
- Proof currProof;
- file >> currProof;
- proofOfValidAddition.push_back(currProof);
- }
- file >> sizeOfVector;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- {
- CurveBipoint currTally;
- file >> currTally;
- previousVoteTallies.push_back(currTally);
- }
- file >> sizeOfVector;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- {
- Twistpoint currNym;
- file >> currNym;
- currentPseudonyms.push_back(currNym);
- }
- file >> sizeOfVector;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- {
- EGCiphertext currTally;
- file >> currTally;
- currentUserEncryptedTallies.push_back(currTally);
- }
- file >> sizeOfVector;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- {
- std::vector<TwistBipoint> currRow;
- for (size_t j = 0; j < sizeOfVector.val(); j++)
- {
- TwistBipoint currVote;
- file >> currVote;
- currRow.push_back(currVote);
- }
- voteMatrix.push_back(currRow);
- }
- // Load data into server object
- prsonaServer->import_new_user_update(proofOfValidAddition, previousVoteTallies, currentPseudonyms, currentUserEncryptedTallies, voteMatrix);
- // Acknowledge successful request
- mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
- }
- /*
- * CONSTRUCTOR HELPERS
- */
- void PrsonaServerWebSocketHandler::get_bgn_details(
- struct mg_connection *conn) const
- {
- // Retrieve value
- const BGN& sharedBGN = prsonaServer->get_bgn_details();
- // Serialize response
- std::stringstream buffer;
- std::string data;
- buffer << sharedBGN;
- data = buffer.str();
- // Send response
- mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), data.length());
- }
- void PrsonaServerWebSocketHandler::add_seed_to_generator(
- struct mg_connection *conn,
- const char *filename,
- bool fresh) const
- {
- std::ifstream file(filename);
- // Un-serialize request
- Twistpoint currGenerator;
- file >> currGenerator;
- // Retrieve value
- std::vector<Proof> pi;
- if (fresh)
- currGenerator = prsonaServer->add_curr_seed_to_generator(pi, currGenerator);
- else
- currGenerator = prsonaServer->add_rand_seed_to_generator(pi, currGenerator);
- // Serialize response
- std::stringstream buffer;
- std::string data;
- buffer << pi[0];
- buffer << currGenerator;
- data = buffer.str();
- // Send response
- mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), data.length());
- }
- void PrsonaServerWebSocketHandler::set_generator(
- const char *filename,
- bool fresh)
- {
- std::ifstream file(filename);
- // Un-serialize request
- BinarySizeT sizeOfVector;
- file >> sizeOfVector;
- std::vector<Proof> pi;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- {
- Proof currProof;
- file >> currProof;
- pi.push_back(currProof);
- }
- Twistpoint newGenerator;
- file >> newGenerator;
- // Load value into server object
- if (fresh)
- prsonaServer->initialize_fresh_generator(pi, newGenerator);
- else
- prsonaServer->set_EG_blind_generator(pi, newGenerator);
- }
- /*
- * EPOCH ROUNDS
- */
- void PrsonaServerWebSocketHandler::build_up_midway_pseudonyms(
- CivetServer *civetServer,
- struct mg_connection *conn,
- const char *filename)
- {
- std::vector<std::vector<Proof>> generatorProofHolder;
- std::vector<Proof> generatorProof;
- Twistpoint nextGenerator;
- // Un-serialize request
- ssize_t bandwidthRcv = read_epoch_initiator_string(filename, generatorProof, nextGenerator);
- generatorProofHolder.push_back(generatorProof);
- std::vector<std::vector<std::vector<Proof>>> pi;
- pi.push_back(generatorProofHolder);
- std::vector<std::vector<std::vector<Twistpoint>>> permutationCommits;
- std::vector<std::vector<std::vector<Twistpoint>>> freshPseudonymCommits;
- std::vector<std::vector<std::vector<Twistpoint>>> freshPseudonymSeedCommits;
- std::vector<std::vector<std::vector<CurveBipoint>>> serverTallyCommits;
- std::vector<std::vector<std::vector<std::vector<TwistBipoint>>>> partwayVoteMatrixCommits;
- std::vector<std::vector<std::vector<std::vector<TwistBipoint>>>> finalVoteMatrixCommits;
- std::vector<size_t> bandwidthData(2);
- std::vector<std::vector<size_t>> otherBandwidthDataBefore;
- std::vector<size_t> serverBandwidthDataBefore = get_server_log_data(civetServer->getContext());
- std::chrono::high_resolution_clock::time_point wallTimeBefore = std::chrono::high_resolution_clock::now();
- clock_t cpuTimeBefore = clock();
- // Do actual epoch calculation
- prsonaServer->build_up_midway_pseudonyms(pi, permutationCommits, freshPseudonymCommits, freshPseudonymSeedCommits, serverTallyCommits, partwayVoteMatrixCommits, finalVoteMatrixCommits, nextGenerator);
- std::vector<std::vector<Twistpoint>> userTallyMaskCommits, userTallyMessageCommits, userTallySeedCommits;
- // Serialize update data
- std::string data = make_epoch_update_string(pi[1], permutationCommits[0], freshPseudonymCommits[0], freshPseudonymSeedCommits[0], serverTallyCommits[0], partwayVoteMatrixCommits[0], finalVoteMatrixCommits[0], userTallyMaskCommits, userTallyMessageCommits, userTallySeedCommits, nextGenerator, false);
- struct synchronization_tool sync;
- std::vector<struct mg_connection *> conns;
- // Connect to all other servers (roughly in parallel)
- std::unique_lock<std::mutex> lck(sync.mtx);
- sync.val = 1;
- for (size_t i = 0; i < serverIPs.size(); i++)
- {
- if (serverIPs[i] == selfIP && serverPorts[i] == selfPort)
- continue;
- // Send them update data
- struct mg_connection *currConn = distribute_epoch_updates(serverIPs[i], serverPorts[i], data, &sync);
- conns.push_back(currConn);
- otherBandwidthDataBefore.push_back(get_conn_log_data(mg_get_context(currConn), false));
- }
- // Wait for all to acknowledge receipt of the update data
- while (sync.val < serverIPs.size())
- sync.cv.wait(lck);
- // Close connections
- for (size_t i = 0; i < conns.size(); i++)
- {
- std::vector<size_t> currBandwidthDataAfter = get_conn_log_data(mg_get_context(conns[i]), false);
- bandwidthData[0] += currBandwidthDataAfter[0] - otherBandwidthDataBefore[i][0];
- bandwidthData[1] += currBandwidthDataAfter[1] - otherBandwidthDataBefore[i][1];
- mg_close_connection(conns[i]);
- }
- clock_t cpuTimeAfter = clock();
- std::chrono::high_resolution_clock::time_point wallTimeAfter = std::chrono::high_resolution_clock::now();
- std::vector<size_t> serverBandwidthDataAfter = get_server_log_data(civetServer->getContext());
- std::vector<double> timingData(2);
- timingData[0] = std::chrono::duration_cast<std::chrono::duration<double>>(wallTimeAfter - wallTimeBefore).count();
- timingData[1] = ((double)(cpuTimeAfter - cpuTimeBefore)) / CLOCKS_PER_SEC;
- bandwidthData[0] += serverBandwidthDataAfter[0] - serverBandwidthDataBefore[0] + bandwidthRcv;
- bandwidthData[1] += serverBandwidthDataAfter[1] - serverBandwidthDataBefore[1];
- write_log_data(buildUpOutputMtx, buildUpOutputFilename, timingData, bandwidthData);
- write_usage_data(usageMtx, usageFilename);
-
- // Serialize response
- data = make_epoch_initiator_string(pi[0][0], nextGenerator);
- // Send response
- mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_BINARY, data.c_str(), data.length());
- mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
- }
- void PrsonaServerWebSocketHandler::break_down_midway_pseudonyms(
- CivetServer *civetServer,
- struct mg_connection *conn,
- const char *filename)
- {
- std::vector<Proof> generatorProof;
- Twistpoint nextGenerator;
- // Un-serialize request
- ssize_t bandwidthRcv = read_epoch_initiator_string(filename, generatorProof, nextGenerator);
-
- std::vector<std::vector<std::vector<Proof>>> pi;
- std::vector<std::vector<std::vector<Twistpoint>>> permutationCommits;
- std::vector<std::vector<std::vector<Twistpoint>>> freshPseudonymCommits;
- std::vector<std::vector<std::vector<Twistpoint>>> freshPseudonymSeedCommits;
- std::vector<std::vector<std::vector<CurveBipoint>>> serverTallyCommits;
- std::vector<std::vector<std::vector<std::vector<TwistBipoint>>>> partwayVoteMatrixCommits;
- std::vector<std::vector<std::vector<std::vector<TwistBipoint>>>> finalVoteMatrixCommits;
- std::vector<std::vector<std::vector<Twistpoint>>> userTallyMaskCommits;
- std::vector<std::vector<std::vector<Twistpoint>>> userTallyMessageCommits;
- std::vector<std::vector<std::vector<Twistpoint>>> userTallySeedCommits;
- std::vector<size_t> bandwidthData(2);
- std::vector<std::vector<size_t>> otherBandwidthDataBefore;
- std::vector<size_t> serverBandwidthDataBefore = get_server_log_data(civetServer->getContext());
- std::chrono::high_resolution_clock::time_point wallTimeBefore = std::chrono::high_resolution_clock::now();
- clock_t cpuTimeBefore = clock();
- // Do actual epoch calculation
- prsonaServer->break_down_midway_pseudonyms(generatorProof, pi, permutationCommits, freshPseudonymCommits, freshPseudonymSeedCommits, serverTallyCommits, partwayVoteMatrixCommits, finalVoteMatrixCommits, userTallyMaskCommits, userTallyMessageCommits, userTallySeedCommits, nextGenerator);
- // Serialize update data
- std::string data = make_epoch_update_string(pi[0], permutationCommits[0], freshPseudonymCommits[0], freshPseudonymSeedCommits[0], serverTallyCommits[0], partwayVoteMatrixCommits[0], finalVoteMatrixCommits[0], userTallyMaskCommits[0], userTallyMessageCommits[0], userTallySeedCommits[0], nextGenerator, true);
- struct synchronization_tool sync;
- std::vector<struct mg_connection *> conns;
- // Connect to all other servers (roughly in parallel)
- std::unique_lock<std::mutex> lck(sync.mtx);
- sync.val = 1;
- for (size_t i = 0; i < serverIPs.size(); i++)
- {
- if (serverIPs[i] == selfIP && serverPorts[i] == selfPort)
- continue;
- // Send them update data
- struct mg_connection *currConn = distribute_epoch_updates(serverIPs[i], serverPorts[i], data, &sync);
- conns.push_back(currConn);
- otherBandwidthDataBefore.push_back(get_conn_log_data(mg_get_context(currConn), false));
- }
- // Wait for all to acknowledge receipt of the update data
- while (sync.val < serverIPs.size())
- sync.cv.wait(lck);
- // Close connections
- for (size_t i = 0; i < conns.size(); i++)
- {
- std::vector<size_t> currBandwidthDataAfter = get_conn_log_data(mg_get_context(conns[i]), false);
- bandwidthData[0] += currBandwidthDataAfter[0] - otherBandwidthDataBefore[i][0];
- bandwidthData[1] += currBandwidthDataAfter[1] - otherBandwidthDataBefore[i][1];
- mg_close_connection(conns[i]);
- }
- clock_t cpuTimeAfter = clock();
- std::chrono::high_resolution_clock::time_point wallTimeAfter = std::chrono::high_resolution_clock::now();
- std::vector<size_t> serverBandwidthDataAfter = get_server_log_data(civetServer->getContext());
- std::vector<double> timingData(2);
- timingData[0] = std::chrono::duration_cast<std::chrono::duration<double>>(wallTimeAfter - wallTimeBefore).count();
- timingData[1] = ((double)(cpuTimeAfter - cpuTimeBefore)) / CLOCKS_PER_SEC;
- bandwidthData[0] += serverBandwidthDataAfter[0] - serverBandwidthDataBefore[0] + bandwidthRcv;
- bandwidthData[1] += serverBandwidthDataAfter[1] - serverBandwidthDataBefore[1];
- write_log_data(breakDownOutputMtx, breakDownOutputFilename, timingData, bandwidthData);
- write_usage_data(usageMtx, usageFilename);
- // Keep our epoch value up-to-date
- epochNum.fetch_add(1);
- // Tell initiator we have finished
- mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
- }
- void PrsonaServerWebSocketHandler::accept_epoch_updates(
- CivetServer *civetServer,
- struct mg_connection *conn,
- const char *filename)
- {
- std::vector<std::vector<Proof>> pi;
- std::vector<std::vector<Twistpoint>> permutationCommits;
- std::vector<std::vector<Twistpoint>> freshPseudonymCommits;
- std::vector<std::vector<Twistpoint>> freshPseudonymSeedCommits;
- std::vector<std::vector<CurveBipoint>> serverTallyCommits;
- std::vector<std::vector<std::vector<TwistBipoint>>> partwayVoteMatrixCommits;
- std::vector<std::vector<std::vector<TwistBipoint>>> finalVoteMatrixCommits;
- std::vector<std::vector<Twistpoint>> userTallyMaskCommits;
- std::vector<std::vector<Twistpoint>> userTallyMessageCommits;
- std::vector<std::vector<Twistpoint>> userTallySeedCommits;
- Twistpoint nextGenerator;
- bool doUserTallies;
- // Un-serialize request
- ssize_t bandwidthRcv = read_epoch_update_string(filename, pi, permutationCommits, freshPseudonymCommits, freshPseudonymSeedCommits, serverTallyCommits, partwayVoteMatrixCommits, finalVoteMatrixCommits, userTallyMaskCommits, userTallyMessageCommits, userTallySeedCommits, nextGenerator, doUserTallies);
- std::vector<size_t> bandwidthDataBefore = get_server_log_data(civetServer->getContext());
- std::chrono::high_resolution_clock::time_point wallTimeBefore = std::chrono::high_resolution_clock::now();
- clock_t cpuTimeBefore = clock();
- // Load data into server object
- prsonaServer->accept_epoch_updates(pi, permutationCommits, freshPseudonymCommits, freshPseudonymSeedCommits, serverTallyCommits, partwayVoteMatrixCommits, finalVoteMatrixCommits, userTallyMaskCommits, userTallyMessageCommits, userTallySeedCommits, nextGenerator, doUserTallies);
- clock_t cpuTimeAfter = clock();
- std::chrono::high_resolution_clock::time_point wallTimeAfter = std::chrono::high_resolution_clock::now();
- std::vector<size_t> bandwidthDataAfter = get_server_log_data(civetServer->getContext());
- std::vector<double> timingData(2);
- timingData[0] = std::chrono::duration_cast<std::chrono::duration<double>>(wallTimeAfter - wallTimeBefore).count();
- timingData[1] = ((double)(cpuTimeAfter - cpuTimeBefore)) / CLOCKS_PER_SEC;
- std::vector<size_t> bandwidthData(2);
- bandwidthData[0] = bandwidthDataAfter[0] - bandwidthDataBefore[0] + bandwidthRcv;
- bandwidthData[1] = bandwidthDataAfter[1] - bandwidthDataBefore[1];
- write_log_data(updateOutputMtx, updateOutputFilename, timingData, bandwidthData);
- write_usage_data(usageMtx, usageFilename);
- // Acknowledge receipt of request
- mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
- }
- /*
- * DISTRIBUTED BGN
- */
- void PrsonaServerWebSocketHandler::get_partial_decryption(
- struct mg_connection *conn) const
- {
- // Send back ACK (since all we do here is simulate distributed BGN)
- mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
- }
- void PrsonaServerWebSocketHandler::receive_tallied_scores(
- struct mg_connection *conn,
- const char *filename)
- {
- std::ifstream file(filename);
- // Un-serialize request
- std::vector<EGCiphertext> userScores;
- std::vector<CurveBipoint> serverScores;
- BinarySizeT sizeOfVector;
- file >> sizeOfVector;
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- {
- EGCiphertext currScore;
- file >> currScore;
- userScores.push_back(currScore);
- }
- for (size_t i = 0; i < sizeOfVector.val(); i++)
- {
- CurveBipoint currScore;
- file >> currScore;
- serverScores.push_back(currScore);
- }
- // Load into server object
- prsonaServer->receive_tallied_scores(userScores, serverScores);
- // Acknowledge receipt of data
- mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
- }
|