Exemple #1
0
void struct_maps()
{
    // here we have a custom type which has a LIST_HEADER and a string key
    // `true` indicates that we should use string ordering.
    Map *map = map_new_node(true);

    // since the key is part of the data we don't use `map_put`. `map_put_struct` is used
    // for inserting single values.
    map_put_structs(map,
        Data_new("bob",22,1),
        Data_new("alice",21,0),
        Data_new("roger",40,1),
        Data_new("liz",16,0),
        NULL
    );
    printf("size was %d\n",map_size(map));

    // you can now look up data using the key
    dump(D map_get(map,"alice"));
    dump(D map_get(map,"roger"));

    Data *rog = (Data*)map_remove(map,"roger");
    printf("size was %d\n",map_size(map));

    FOR_MAP(iter,map) {
        printf("[%s]=%d,",(char*)iter->key,((Data*)(iter->value))->age );
    }
Exemple #2
0
Data* parse_string( char** p )
{
	char* ret = (char*)malloc(65536);
	int   len = 0;
	if( *((*p)++) != '"' )
	{
		free(ret);
		return Raise(SYNTAX);	
	}
	while( **p )
	{
		//putchar(**p);
		if( (*p)[0] == '"' )
			if( (*p)[1] == '"' && (*p)[2] == '"' && (*p)[3] == '"' )
				(*p) += 3 , ret[len++] = '"';
			else
			{
				//(*p)++;
				break;
			}
		else
			if( len < 65536 ) ret[len++] = **p;
		(*p)++; 
	}
	if( **p != '"' )
	{
		free(ret);
		return Raise(SYNTAX);
	}
	(*p)++;
	ret[len] = 0;
	return Data_new( TYPE_STRING , (Storage)ret , 1 );
}
Exemple #3
0
Array *Array_new(void)
{
    Array *self = (Array *)calloc(1, sizeof(Array));
    self->data = Data_new();
    self->itemType = CTYPE_uint8_t;
    self->itemSize = 1;
    return self;
}
Exemple #4
0
Data* parse_numeric( char** p )
{
	double ret = 0;
	if( ISNUMERIC(**p) )
		while( ISNUMERIC(**p) )
		{
			ret = ret * 10 + (**p) - '0';
			(*p)++;
		} 
	if( **p == '.' )
	{
		(*p)++;	
		double scale = .1;
		while( ISNUMERIC(**p) )
		{
			ret = ret + scale * ( **p - '0' );
			scale /= 10;
			(*p)++;
		}
	}
	if( **p == 'E' )
	{
		int sign = 1;
		int exponent = 0;
		(*p)++;
		if( **p == '-' )
			sign = -1 , (*p)++;
		else if( **p == '+' )
			(*p)++;
		while( ISNUMERIC(**p) )
		{
			exponent = exponent * 10 + **p - '0';
			(*p)++;
		}
#ifndef __WIN32
		if(sign > 0)
			ret *= exp10(exponent);
		else
			ret /= exp10(exponent);
#else
		if(sign > 0)
			ret *= exp(log(10)*exponent);
		else
			ret /= exp(log(10)*exponent);
	
#endif
	}
	return Data_new( TYPE_REAL , (Storage)ret , 1 );
}
static Data build_delta_string(OE oe, List proof_tasks, XORcommitResult xom, byte and_challenge) {
	Data result = Data_new(oe,(proof_tasks->size()+7)/8);
	uint i =0 ;
	for (i = 0; i < proof_tasks->size();++i) {
		ProofTask pt = proof_tasks->get_element(i);
		uint j = 0;
		byte delta = 0;
		uint lind = pt->value >> 1;
		for( j = 0; j < lind;++j) {
			delta ^= get_bit(xom->m0,pt->indicies[j]);
		}
		set_bit(result->data,i,delta);
	}
	return result;
}
Exemple #6
0
int main(int c, char **a) {
    OE oe = (OE)OperatingEnvironment_LinuxNew();
    MiniMacs mm = 0;
    Data input = 0;
    uint count=0,i=0;
    init_polynomial();

    mm = GenericMiniMacs_DefaultLoadNew(oe,a[1]);

    InitStats(oe);

    if (!mm) {
        oe->p("Error could not create instance of MiniMacs");
        OperatingEnvironment_LinuxDestroy(&oe);
        return -1;
    }

    {
        CliArg arg = (CliArg)oe->getmem(sizeof(*arg));
        arg->file = a[2];
        arg->oe = oe;
        oe->newthread(client,arg);
    }

    mm->init_heap(2);
    mm->invite(1,8080);
    printf("Got client ... \n");

    input = Data_new(oe, mm->get_ltext());
    for(i = 0; i < mm->get_ltext(); ++i) {
        input->data[i] = 'r';
    }

    mm->secret_input(0,0,input);

    for(count = 0; count < COUNT; ++count) {
        CHECK_POINT_S("Mul server");
        mm->mul(1,0,0);
        CHECK_POINT_E("Mul server");
    }

    usleep(5);
    PrintMeasurements(oe);

    return 0;
}
Exemple #7
0
Data* parse_expression( char **p )
{
	/*TODO: logic */
	//return parse_aexpr(p);
	Data* ret = NULL;
	while(1)
	{
		char op;
		int neg ;
		Data* aexpr;
		if( ret )
		{/*if it is not the first expression , a logic operator expected*/
			if( p[0][0] == 'A' && p[0][1] == 'N' && p[0][2] == 'D' && ( p[0][3] = ' ' || p[0][3] == '\t' ) )
			{
				op = 'A';
				(*p)+=4;
			}
			else if( p[0][0] == 'O' && p[0][1] == 'R' && ( p[0][2] = ' ' || p[0][2] == '\t' ) )
			 {
				op = 'O';
				(*p)+=3;
			}
			else break; /*if not operator */
		}
		neg  = parse_neg(p);
		aexpr = parse_aexpr(p);
		parse_ws(p);
		if( aexpr->type == TYPE_ERROR )
		{
			dispose(ret);
			return aexpr;
		}
		if( **p == '=' || **p == '>' || **p == '<' )
		{ 
			int flag;
			Data* right/* = parse_aexpr(p)*/;
			switch(**p)
		 	{
			case '=':
#define EQ 0
				flag = 0;  /*EQ*/
				(*p)++;
				break;
			case '>':
				if( p[0][1] == '=' )
				{
					(*p)+=2;
#define GE 3
					flag = 3;   /*GE*/
				}
				else
				{
#define G 1
					(*p)++;
					flag = 1;   /*G*/
				}
				break;
			case '<':
				if( p[0][1] == '=' )
				{
					(*p)+=2;
#define LE 4
					flag = 4; /*LE*/
				}
				else if( p[0][1] == '>' )
				{
					(*p)+=2;
#define NE 5
					flag = 5;  /*NE*/
				}
				else
				{
					(*p)++;
#define L 2
					flag = 2; /*L*/
				}
			}
			right = parse_aexpr(p);
			if( right->type == TYPE_ERROR )
			{
				dispose(ret);
				dispose(aexpr);
				return right;
			}
			if( right->type == TYPE_STRING )
			{//String
				if( aexpr->type != TYPE_STRING )
				{
					dispose(ret);
					dispose(aexpr);
					dispose(right);
					return Raise(TYPE_MISMATCH);
				}
				else
				{
					Data* temp = Data_new(TYPE_INTEGER,(Storage)(short)0,1); 
					int result = strcmp( aexpr->storage.String , right->storage.String);
					switch(flag)
					{
					case EQ:
						temp->storage.Integer = (result == 0);
						break;
					case L:
						temp->storage.Integer = (result < 0 );
						break;
					case LE:
						temp->storage.Integer = (result <= 0 );
						break;
					case G:
						temp->storage.Integer = (result > 0 );
						break;
					case GE:
						temp->storage.Integer = (result >= 0 );
						break;
					case NE:
						temp->storage.Integer = (result != 0 );
					}
					dispose(aexpr);
					dispose(right);
					aexpr = temp;
	
				}
			} 
			else 
			{//numeric
				if( aexpr->type == TYPE_STRING )
				{
					dispose(right);
					dispose(aexpr);
					dispose(ret);
					return Raise(TYPE_MISMATCH); 
				}
				else
				{
					Data* temp = Data_new(TYPE_INTEGER,(Storage)(short)0,1); 
					int result ;
					if( aexpr->type == TYPE_INTEGER )
					{
						aexpr->type = TYPE_REAL;
						aexpr->storage.Real = aexpr->storage.Integer;
					}
					if( right->type == TYPE_INTEGER )
					{
						right->type = TYPE_REAL;
						right->storage.Real = right->storage.Integer;
					}
					double t = aexpr->storage.Real - right->storage.Real;
					if( t < 0 ) result = -1;
					if( t == 0 ) result = 0;
					if( t > 0 ) result = 1;
					switch(flag)
					{
					case EQ:
						temp->storage.Integer = (result == 0);
						break;
					case L:
						temp->storage.Integer = (result < 0 );
						break;
					case LE:
						temp->storage.Integer = (result <= 0 );
						break;
					case G:
						temp->storage.Integer = (result > 0 );
						break;
					case GE:
						temp->storage.Integer = (result >= 0 );
						break;
					case NE:
						temp->storage.Integer = (result != 0 );
					}
					dispose(aexpr);
					dispose(right);
					aexpr = temp;
				}
			}	
		}
		if( aexpr->type == TYPE_ERROR )
		{
			dispose(ret);
			return aexpr; 
		}
		if( neg )
		{/*one or more NOT parsed*/
			if( aexpr->type == TYPE_STRING ) /*NOT "illegal"*/
			{
				dispose(aexpr);
				dispose(ret);
				return Raise(TYPE_MISMATCH );
			}
			if( aexpr->type == TYPE_REAL )
			{
				aexpr->type = TYPE_INTEGER;
				aexpr->storage.Integer = (int)(aexpr->storage.Real+.001);	
			}
			if( aexpr->storage.Integer )
				aexpr->storage.Integer = 1;
			else
				aexpr->storage.Integer = 0;
			if( neg < 0 )
				aexpr->storage.Integer = !aexpr->storage.Integer;
		}
		if( !ret )
		{/* first expression */
			ret = aexpr;
		}
		else
		{
			ret = temp_var(ret);
			if( aexpr->type == TYPE_STRING )
			{
				dispose(aexpr);
				dispose(ret);
				return Raise(TYPE_MISMATCH);
			}
			if( aexpr->type == TYPE_REAL )
			{
				aexpr->type = TYPE_INTEGER;
				aexpr->storage.Integer = (int)(aexpr->storage.Real+.001);
			}
			if( ret->type == TYPE_REAL )
			{
				ret->type = TYPE_INTEGER;
				ret->storage.Integer = (int)(ret->storage.Real+.001);
			}
			if( op == 'A' )
				ret->storage.Integer &= aexpr->storage.Integer;
			else
				ret->storage.Integer |= aexpr->storage.Integer;
			dispose(aexpr);
		}
	}
	return ret;
}
Exemple #8
0
Data* parse_term( char** p )
{
	Data* ret = NULL;
	while(1)
	{
		char op;
		int sign;
		if( ret )
		{
			parse_ws(p);
			op = *((*p));
			if( op != '*' && op != '/' ) 
			{
				break; /*last chr should not be parsed*/
			}
			else
				(*p)++;
		}
		sign=parse_sign(p);
		if( sign == 0 ) sign = 1;
		Data* factor = parse_factor(p);
		if( factor->type == TYPE_ERROR )
		{
			dispose(ret);
			return factor; /*throw*/
		}
		if( sign == -1 )
		{
			if( factor->type == TYPE_STRING )
			{
				dispose(factor);
				dispose(ret);
				return Raise(SYNTAX);
			}
			else if( factor->type == TYPE_REAL )
				factor->storage.Real = -factor->storage.Real;
			else
				factor->storage.Integer = - factor->storage.Integer;
		}
		parse_ws(p);
		if( **p == '^' )
		{/*exponent*/
			(*p)++;
			Data* exponent = parse_factor(p);
			factor = temp_var(factor);
			if( exponent->type == TYPE_ERROR )
			{
				dispose(ret);
				dispose(factor);
				return exponent;
			}
			if( exponent->type == TYPE_STRING || factor->type == TYPE_STRING)
			{
				dispose(ret);
				dispose(factor);	
				dispose(exponent);
				return Data_new( TYPE_ERROR , (Storage)Error_new(TYPE_MISMATCH) , 1 );
			}
			if( factor->type == TYPE_INTEGER )
			{
				factor->storage.Real = factor->storage.Integer;
				factor->type = TYPE_REAL;
			}
			if( exponent->type == TYPE_INTEGER )
			{
				factor->storage.Real = factor->storage.Integer;
				factor->type = TYPE_REAL;
			}
			factor->storage.Real = exp( log(factor->storage.Real) * exponent->storage.Real); 
			dispose(exponent);
		}
		
		if( ret == NULL )
			ret = factor;
		else
		{
			ret = temp_var(ret);
			if( ret->type == TYPE_STRING )
			{
				dispose(ret);
				dispose(factor);
				return Raise(TYPE_MISMATCH);
			}
			else
			{
				if( op == '*' )
				{
					if( ret->type == TYPE_REAL || factor->type == TYPE_REAL )
					{
						if( ret->type == TYPE_INTEGER )
						{
							ret->type = TYPE_REAL;
							ret->storage.Real = ret->storage.Integer;
						}
						if( factor->type == TYPE_INTEGER )
						{
							factor->type = TYPE_REAL;
							factor->storage.Real = factor->storage.Integer;
						}
						ret->storage.Real *= factor->storage.Real;
											
					}
					else
						ret->storage.Integer *= factor->storage.Integer;
				}
				else
				{
					if( ret->type == TYPE_INTEGER )
					{
						ret->type = TYPE_REAL;
						ret->storage.Real = ret->storage.Integer;
					}
					if( factor->type == TYPE_INTEGER )
					{
						factor->type = TYPE_REAL;
						factor->storage.Real = factor->storage.Integer;
					}
					if( factor->storage.Real == 0 )
					{
						dispose( ret );
						dispose( factor );
						return Raise(DIV_BY_ZERO);
					}
					ret->storage.Real /= factor->storage.Real;
				}
					
			}
			dispose(factor);
		}
	}
	return ret;
}
Exemple #9
0
Data* parse_factor( char** p)
{
	Data* ret;
	int curves = 0;
	while(1)
	{
		parse_ws(p);
		if( **p == '(' )
			curves ++;
		else 
			break;
		(*p)++;
		break;
	}
	if( curves )
	{/* (((...(( parsed , expression expected */
		ret = parse_expression(p);
		if( ret->type == TYPE_ERROR )
		{/* error occured*/
			return ret;
		}
		while(curves--)
		{
			/*check ')'*/
			parse_ws(p);
			if( **p != ')' )
			{/*syntax error , curves dose not match*/
				dispose(ret);
				return Raise(SYNTAX);
			}
			(*p)++;
		}
	}
	else
	{/* Constant , Variable , Array and Functions*/
	 /* INKEY$*/
		parse_ws(p);
		if( **p == '"' )
			ret = parse_string(p);
		else if(ISNUMERIC(**p) || **p == '.') 
			ret = parse_numeric(p);
		else if( ISALPHA(**p) || **p == '_' )
		{
			char* id = parse_id(p);
			parse_ws(p);
			if(**p == '(' )
			{
				Subscript *arg;
				Function* f;
				arg = parse_arg(p);
				f = get_fun(id);
				if( f == NULL )
					return Raise(SYNTAX);
				if( arg == NULL )
					return Raise(SYNTAX);
				if( arg->dimension[arg->dimensions-1]->type == TYPE_ERROR )
				{
					ret = Data_new( TYPE_ERROR , 
					                (Storage)arg->dimension[--arg->dimensions]->storage,
					                1);
					free(arg);
				}
				else
				{
					if( f->is_function )
					{/*function call*/
						ret = f->f.foo( arg );
					}
					else
					{/*array*/
						ret = get_arr_element( &f->f.arr , arg );
					}
					dispose_arg(arg);
				}
			}
			else
			{
				/*variable*/
				if( strcmp( id , "INKEY$") == 0 )
				{
					ret = Data_new( TYPE_STRING , (Storage)(char*)malloc(2) , 1 );
					ret->storage.String[0] = inkey();
					ret->storage.String[1] = 0;
				}
				else if( strcmp( id , "__LASTERR$" ) == 0 )
				{
					ret = Data_new( TYPE_STRING , (Storage)(char*)malloc(strlen(err_str[Last_Error.id])) , 1 );
					strcpy( ret->storage.String , err_str[Last_Error.id] );
				}
				else if( strcmp( id, "__LASTERRNO") == 0 )
				{
					ret = Data_new( TYPE_REAL , (Storage)(double)Last_Error.id,1);
				}
				else
					ret = get_var(id);
			}
			free(id);
		}
		else
		{
			ret =Raise(SYNTAX);
		}
	}
	return ret;
}
COO_DEF(Rtz14,bool,executeProof, List circuit, byte * witness, char * ip, uint port) {
	Rtz14Impl impl = (Rtz14Impl)this->impl;
	OE oe = impl->oe;
	Map input_gates = 0;
	CircuitVisitor emitter = 0;
	// TODO(rwz): take the igv as constructor argument.
	CircuitVisitor igv = 0;
	EmiterResult emitter_res = 0;
	byte * emitted_circuit = 0;
	CArena conn = 0;
	CircuitVisitor proof_task_builder = 0;
	List proof_tasks = 0;
	CircuitVisitor gpam = 0;
	CircuitVisitor poc = 0;
	CircuitVisitor ogv = 0;
	List output_gates = 0;
	Rnd rnd = 0;
	GPam gpam_res = 0;
	DateTime d = DateTime_New(oe);
	ull start = d->getMilliTime();
	uint no_inputs = 0;

	_Bool accept = 0;
	ProofTask check_out_bit = (ProofTask)oe->getmem(sizeof(*check_out_bit));


	// create and call helper strategies
	// TODO(rwz): strategies should be given as constructor arguments instead
	// of being created here. (for testability and maintainability)

	// default one address is 0, however it can be set during create of
	// RTZ14.
	poc = PatchOneConstants_New(oe,impl->address_of_one);
	if (!poc) return False;

	// patch addresses.
	poc->visit(circuit);

	// compute map mapping addresses to input
	igv = InputGateVisitor_New(oe);
	if (!igv) return False;

	input_gates = igv->visit(circuit);
	if (!input_gates) return False;
	no_inputs = input_gates->size();

	ogv = OutputGateVisitor_New(oe);
	if (!ogv) return False;

	output_gates = ogv->visit(circuit);
	if (!output_gates) {
		return False;
	}

	if (output_gates->size() != 1) {
		oe->syslog(OSAL_LOGLEVEL_FATAL,"The provided circuit does not have one unique output.");
		return False;
	}
	check_out_bit->indicies[0] = output_gates->get_element(0);
	check_out_bit->indicies[1] = impl->address_of_one;
	check_out_bit->indicies[2] = impl->address_of_one;


	OutputGateVisitor_Destroy(&ogv);
	SingleLinkedList_destroy(&output_gates);



	// go online
	conn = CArena_new(oe);
	if (!conn) return False;


	if (ip == 0) {
		// -----------------------------
		// ----------- Prover ----------
		// -----------------------------
		MpcPeer verifier = 0;
		byte and_challenge[1] = {0};
		Data challenge_commitment = Data_new(oe,80);
		XORcommitResult xom = 0;
		Data epsilon = Data_new(oe,1);
		Data delta = 0;
		Data judgement = Data_new(oe,8);
		// The message containing the evaluated circuit, input bits (witness)
		// and the auxiliary informations for each and-gate.
		Data message = 0;

		if (witness == 0) {
			oe->syslog(OSAL_LOGLEVEL_FATAL,"No witness !");
			return False;
		}

		UserReport(oe,"Prover preparing ... ");
		// compute evaluated circuit
		emitter = EvaluationStringEmitter_New(oe, input_gates, witness);
		if (!emitter) return False;

		emitter_res = emitter->visit(circuit);
		if (!emitter_res) return False;

		// generate random permutations and majority tests
		rnd = LibcWeakRandomSource_New(oe);
		if (!rnd) return False;

		gpam = GeneratePermuationsAndMajorities_New(oe,rnd,
							    emitter_res->emitted_string,
							    impl->address_of_one);
		if (!gpam) return False;

		gpam_res = gpam->visit(circuit);
		if (!gpam_res) return False;

		// create message
		{
			uint bit_i = 0;
			uint aux_bit_len = gpam_res->no_ands*3;
			uint emitted_string_bit_len = circuit->size() + no_inputs;
			uint bit_l = emitted_string_bit_len + aux_bit_len;
			message = Data_new(oe,(bit_l+7)/8);
			for(bit_i = 0; bit_i < bit_l;++bit_i) {
				if (bit_i < emitted_string_bit_len) {
					set_bit(message->data,bit_i,get_bit(emitter_res->emitted_string,bit_i));
				} else {
					set_bit(message->data,bit_i,get_bit(gpam_res->aux,bit_i-emitted_string_bit_len));
				}
			}
		}
		UserReport(oe, "Bit String Committed to: ");
		print_bit_string(oe,message);

		// inform the user what is happening
		UserReport(oe,"[%lums] Prover is Online and ready, awaiting Verifier to connect ... ",d->getMilliTime()-start);
		conn->listen_wait(1,port);
		oe->p("Verifier connected ...  ");
		verifier = conn->get_peer(0);
		if (verifier == 0) {
			oe->syslog(OSAL_LOGLEVEL_FATAL,"Establishing listening socket or connection failed upon connection. Please check the given port is free and try again. ");
			return False;
		}

		// ---------------------------------------------
		// The Rtz14 protocol starts here for the prover
		// ---------------------------------------------
		UserReport(oe, "Starting proof");
		start = d->getMilliTime();

		// receive commitment to challenge from verifier.
		verifier->receive(challenge_commitment);
		oe->p("Verifier is committed to his challenges");
		UserReport(oe,"[%lums] %s",d->getMilliTime()-start,"Verifier has committed to his challenge");

		// build xor commit to the emitted string
		xom = xor_commit(oe,impl->rnd,impl->cs,message->data, message->ldata);
		UserReport(oe,"[%lums] %s",d->getMilliTime()-start,"[Prover] XOR Commitment prepared");
		print_bit_string(oe,Data_shallow(xom->m0,xom->lm0));
		print_bit_string(oe,Data_shallow(xom->m1,xom->lm1));

		// send the emitted string
		verifier->send(Data_shallow(xom->commitment,xom->lcommitment));

		// receive and and_challenge b
		verifier->receive(Data_shallow(and_challenge,1));
		UserReport(oe,"[%lums] %s",d->getMilliTime()-start,"Received and challenge");

		// send permutation or majority tests
		if (and_challenge[0] == 0) {
			check_out_bit->value = 3;
			verifier->send(Data_shallow(gpam_res->permutations,(gpam_res->no_ands*3+7)/8));
			proof_task_builder = ProofTaskBuilder_New(oe,and_challenge[0],gpam_res->permutations,(gpam_res->no_ands*3+7)/8,no_inputs, impl->address_of_one);
		} else {
			verifier->send(Data_shallow(gpam_res->majority,(gpam_res->no_ands*2+7)/8));
			proof_task_builder = ProofTaskBuilder_New(oe,and_challenge[0],gpam_res->majority,(gpam_res->no_ands*2+7)/8,no_inputs,impl->address_of_one);
			check_out_bit->value = 2;
		}
		UserReport(oe, "[%lums", d->getMilliTime()-start);

		// build linear proof tasks
		proof_tasks = proof_task_builder->visit(circuit);
		proof_tasks->add_element(check_out_bit);
		UserReport(oe,"[%lums] %u %s",d->getMilliTime()-start,proof_tasks->size(),
				"Proof Tasks computed ...");
		

		// build delta string
		delta = build_delta_string(oe,proof_tasks,xom,and_challenge[0]);
		print_bit_string(oe,delta);

		// send delta string to verifier
		UserReport(oe,"[%lums] Sending delta string (%lu)",d->getMilliTime()-start,delta->ldata);
		verifier->send(delta);
		Data_destroy(oe,&delta);

		// challenge for the linear tests
		UserReport(oe,"[%lums] waiting for challenge (epsilon %u) ... ",
			   d->getMilliTime()-start,epsilon->ldata);
		verifier->receive(epsilon);
		UserReport(oe,"[%lums] %s",
			   d->getMilliTime()-start,"Delta string sent and challenge opened receive.");

		// send the m_epsilon string to the verifier
		if (epsilon->data[0] == 0) {
			UserReport(oe,"Sending m0 = %u",xom->lm0);
			verifier->send(Data_shallow(xom->m0,xom->lm0));
		} else {
			UserReport(oe,"Sending m1 = %u",xom->lm0);
			verifier->send(Data_shallow(xom->m1,xom->lm1));
		}

		// receive the string accept/reject from the verifier
		verifier->receive(judgement);
		UserReport(oe,"[%lums] %s",d->getMilliTime()-start,"Proof complete.");

		// tell result to prover.
		oe->p("The verifier says: ");
		oe->p((char *)judgement->data);


		if (judgement->data[0] == 'a') {
			accept = True;
		} else {
			accept = False;
		}

		//TODO(rwz): clean up
		/*
		Data_destroy(oe,&judgement);
		Data_destroy(oe,&message);
		Circuit_Destroy(oe, &circuit);
		GPam_Destroy(oe,&gpam);
		EvaluationStringEmitter_Destroy(&emitter);
*/
	} else {
		// -----------------------------
		// ---------- Verifier ---------
		// -----------------------------

		// ---- The Rtz protocol starts here for the verifier ---

		MpcPeer prover = 0;
		Data challenge_commitment = 0;
		Data challenge = Data_new(oe,64);
		Data commitment_to_circuit = 0;
		Data and_challenge = Data_new(oe,1);
		Data permajor = 0;
		Data delta = 0;
		Data m_challenge = 0;
		uint i = 0, no_ands = 0;
		ull proto_time = 0;

		// generate random challenges and commit to them
		impl->rnd->rand(challenge->data,challenge->ldata);
		challenge->data[0] = challenge->data[0] % 2;
		challenge_commitment = impl->cs->commit(challenge);

		// generate random and-challenge (permutations or majority tests)
		impl->rnd->rand(and_challenge->data,and_challenge->ldata);
		and_challenge->data[0] = (and_challenge->data[0] % 2);

		UserReport(oe,"[%lums] %s", d->getMilliTime()-start,"Verifier connecting to Prover ... ");
		// connect to the prover
		conn->connect(ip,port);
		prover = conn->get_peer(0);

		if (!prover) {
			oe->p("No prover sorry, leaving.");
			return -2;
		}


		// send challenge commitment
		prover->send(challenge_commitment);
		UserReport(oe,"[%lums] %s %u bytes", d->getMilliTime()-start,"Commitment to challenge sent",challenge_commitment->ldata);

		// receive the xor-commitment to the circuit
		commitment_to_circuit = Data_new(oe,128);
		prover->receive(commitment_to_circuit);
		UserReport(oe,"[%lums] %s", d->getMilliTime()-start,"Circuit XOM commitments received.");
		proto_time = d->getMilliTime();

		// send the and challenge
		prover->send(and_challenge);
		UserReport(oe,"[%lums] %s", d->getMilliTime()-start,"And challenge sent");

		// count number of ands to anticipate size permajor
		for(i = 0; i < circuit->size();++i) {
			Gate g = circuit->get_element(i);
			if (g->type == G_AND)
				no_ands ++;
		}

		// allocate permajor
		if (and_challenge->data[0] == 0) {
			// permutations
			permajor = Data_new(oe,(3*no_ands+7)/8);
		} else {
			// majority
			permajor = Data_new(oe,(2*no_ands+7)/8);
		}

		// receive permutation or majority tests
		prover->receive(permajor);
		UserReport(oe,"[%lums] %s", d->getMilliTime()-start,"Received permutations/majority tests");

		// compute proof tasks the prover must do
		proof_task_builder = ProofTaskBuilder_New(oe,and_challenge->data[0],
							  permajor->data,permajor->ldata,
							  no_inputs, impl->address_of_one);
		proof_tasks = proof_task_builder->visit(circuit);
		UserReport(oe,"[%lums] %u %s", d->getMilliTime()-start,proof_tasks->size(),
				      "Proof Tasks built...");

		if (and_challenge->data[0] == 0) {
			check_out_bit->value = 3;
			proof_tasks->add_element(check_out_bit);
		} else {
			check_out_bit->value = 2;
		}


		// --- Do linear proofs ---

		// --- Receive Delta ---
		delta = Data_new(oe,(proof_tasks->size()+7)/8);
		UserReport(oe, "[%lums] %s delta->size %lu", d->getMilliTime()-start,"Waiting for delta string",delta->ldata);
		prover->receive(delta);
		UserReport(oe,"[%lums] %s", d->getMilliTime()-start,"Received deltas from Prover...");

		// send the committed to challenge from the beginning
		challenge->ldata =1;
		prover->send(challenge);

		// receive m_{challange}
		m_challenge = Data_new(oe,(input_gates->size() + circuit->size()+no_ands*3+7)/8);
		prover->receive(m_challenge);
		UserReport(oe,"[%lums] %s", d->getMilliTime()-start,"Received XOM partial opening, checking linear relations ...");

		UserReport(oe,"%lums] %s",  d->getMilliTime()-start, "Delta:");
		print_bit_string(oe,delta);

		UserReport(oe,"m_challenge = %u",m_challenge->ldata);
		print_bit_string(oe,m_challenge);
		accept = True;
		for(i = 0; i < proof_tasks->size();++i) {
			byte xor = 0;
			byte b = 0;
			uint j = 0;
			ProofTask cur = proof_tasks->get_element(i);
			uint * indicies = (uint *)&cur->indicies;
			uint lindicies = cur->value >> 1;
			b = (cur->value & 0x01);
			for(j = 0;j < lindicies;++j) {
				uint index_j = (uint)indicies[j];
				xor ^= get_bit(m_challenge->data,index_j);
			}

			if (xor != ((byte)get_bit(delta->data,i) ^ (challenge->data[0] & b))) {
				accept = False;
				UserReport(oe,"Proof Task %u failed [{%u,%u,%u},%u].",i,cur->indicies[0],cur->indicies[1],cur->indicies[2],cur->value);
			}
		}
		UserReport(oe, " PROTOCOL TOOK: %llu ms", d->getMilliTime() - proto_time);
		if (accept) {
			prover->send(Data_shallow((byte*)"accept ",8));
			oe->p("Verifier accepted proof.");
			accept = True;
		} else {
			prover->send(Data_shallow((byte*)"reject ",8));
			oe->p("Verifier rejected proof");
			accept = 0;
		}
		UserReport(oe,"[%lums] %s", d->getMilliTime()-start,"Verifier Done.");
	}

	{
		byte aes[] = {0x66,0xE9,0x4B,0xD4,0xEF,0x8A,0x2C,0x3B,0x88,0x4C,0xFA,0x59,0xCA,0x34,0x2B,0x2E};
		UserReport(oe,"These are the bits we are looking for !");
		print_bit_string(oe,Data_shallow(aes,sizeof(aes)));
	}


	// close all connections.
	CArena_destroy(&conn);

	return accept;
	error:
	return accept;
}}