Post Office Problem Protocol (Part II)

by Ofer H. Gill


This describes the behavior your Postal Algorithm should take so that
my program can utilize your algorithm the best. Most things mentioned
here are as decided in class. If you have a problem with anything I
say here, bring it up. I'm not a 100% error-free automaton, just human.

The Post Office Problem is as defined by the site:

http://cs.nyu.edu/courses/fall02/G22.3033-007/postoffice.html

Your Postal Algorithm may be written in any language of your
choice. Its purpose is to come up with a protocol that is safe
against the spy. My program will test the security of your
algorithm


----------------------- 1: REQUIRED INPUT ----------------------------

You Postal Algorithm should take in the following input parameters:

N: An integer denoting the number of people who are trying to
   communicate their information to each other (and each person knows 1/Nth
   of the entire plan initially).

M: An integer denoting the number of post offices available for
   sending mail in this algorithm.

v: An integer denoting the number of visits the spy is allowed to make

f: A decimal value such that 0 < f <= 1, denoting the fraction of the
   plan the spy needs to see in order to know the entire plan. (So for
   example, if f=0.5, then the spy need only see half of the N messages to
   know the everything.)


The output of your algorithm should depend on these inputs.


------------------------ 2: REQUIRED OUTPUT ------------------------------

Your algorithm's output should be plain-text, and assume that the people
are labled 1 thru N, and the post offices are labeled 1 thru M. I.e.,
assume we're counting from 1, not 0. (This is just upon output. You
may count your arrays from 0 internally in your program.)

(Updated 11/14) I AM NOT RESPONSIBLE FOR ANY JAVA RUNTIME EXCEPTIONS GENERATED BY
MY PROGRAM BECAUSE OF YOUR FAILURE TO FOLLOW THESE RULES!!!

(Updated 11/14) IF YOUR PROTOCOL DOESN'T CORRRECTLY SEND EVERYONE ALL THE
MESSAGES FROM EVERYONE ELSE, MY PROGRAM MIGHT GO INTO AN ENDLESS LOOP, AND IT
WILL BE YOUR FAULT, NOT MINE!!!

 
Your program's output should look like the following C-like
format. Please note that the protocol has changed! Read everything carefully!

N = 4;
M = 4;
v = 2;
f = 0.75;

1: {
     start: {
	send(msg_with(1), 2, 4);
     }
     ack_of(1): {
	send(msg_with(1), 3, 4);
     }
}

2: {
     start: {
	send(msg_with(2), 3, 3);
     }
     msg_of(1): {
	send(msg_with(1, 2), 4, 4);
	send(ack_with(1), 1, 4);
	send(msg_with(2), 1, 3);
	send(msg_with(2) && ack_with(1), 3, 3);
     }
     ack_of(4): {
	send(ack_with(2), 4, 2);
     }
}

3: {
     on_events(msg_of(1), msg_of(2)): {
	send(msg_with(3), 1, 2);
	send(msg_with(3), 4, 2);
	send(ack_with(4, 3), 4, 2);
     }
}

4: {
     on_events(msg_of(1), msg_of(2), ack_of(3)): {
	send(ack_with(1, 2), 2, 1);
	send(msg_with(4), 1, 1);
	send(ack_with(4), 2, 1);
	send(msg_with(4), 3, 1);
     }
     ack_of(2): {
	send(msg_with(3, 4), 2, 1);
     }
}


(Updated 11/8) The first four lines, with the N, M, f, and v denote the N, M, f, and
v that your protocol is using. (Use the same format I am, or my program
will reject your input.)

As you can probably tell, there are two types of clauses:
outer-clauses (AKA people-clauses), and inner-clauses (AKA
action-clauses). The people-clauses indicate the
behaviors of each person.

So, a clause of the form
i: { ... }
indicates the behavior person i takes in this protocol.

And within each people-clause are the action-clauses of the form

start: { ... }

OR

msg_of(j): { ... }

OR

ack_of(j): { ... }

OR

on_events(...): { ... }

(Updated 11/14):
And, these represent actions person i is to take based on certain
situtations. start denotes the actions person i takes at the start of
the protocol, msg_of(j) denotes the actions person i takes upon
getting person j's information (it doesn't matter from whom person i
gets j's information from here), and ack_of(j) denotes the actions
person i takes upon getting an ack with label "j" (again, it doesn't
matter from who person i gets an ack with label "j"). 

(Updated 11/8) on_events(...) denotes the actions to be taken taken
upon more than one event occuring. Inside the parenthesis for
on_events, you may place as many msg_of or ack_of actions as you
like. What will happen is, when ALL the actions in the parenthesis for
on_events has occurred, the corresponding actions will be taken. So,
in the example above for person 3, when he gets the information of
person 1 AND person 2, he will perform the actions send(msg_with(3), 1, 2),
send(msg_with(3), 4, 2), and send(ack_with(4, 3), 4, 2).

The action-clauses of form start, msg_of(j), ack_of(j), and on_events(...) are entirely
optional. If any of these clauses are missing, it is assumed nothing is
done. (So for example, if person i has no ack_of(j) clause, he does
nothing special upon getting an ack with label "j".)

Within each action-clause are the send commands that are to be done in
response to a certain event.

And, send(msg_with(1), 5, 2); means to send a message to person 5 at post
office # 2, and this message contains the information from person #1.

And, send(msg_with(1, 4, 7), 5, 2); means to send a message to person 5 at post
office # 2, and this message contains the information from persons #1,
#4, and #7.

And, send(ack_with(6), 2, 3); means to send an acknowledgement to person 2 at
post office # 3, and this acknowledgement has label "6".

And, send(ack_with(5, 6), 2, 3); means to send an acknowledgement to person 2 at
post office # 3, and this acknowledgement has labels "5" and "6".

All uses of msg_with() and ack_with() allow one or more arguments,
with the comma used to separate each argument! (However the msg_of() and
ack_of() each only allow one argument. Use the on_events() command to combine more
than one msg_of() or ack_of().)

(Updated 11/15):
You may send acks and messages in one envelope. The way to do this is
using the && in conjunction with the ack_with() and msg_with() operators.

So in the example above, where we see in the clause for person 2:
	send(msg_with(2) && ack_with(1), 3, 3);

This means person with will send an envelope containing a message with
person 2's info, and an ack of label "1". And, this envelope is
directed to person 3 at post office #3.

To combine multiple messages and acks in one envelope, use multiple
arguments for msg_with and ack_with, and && them together. For
example,

	send(msg_with(2, 3, 7) && ack_with(1, 6, 9), 4, 7);

This sends one envelope with the messages of persons 2, 3, and 7, plus
ack's of labels "1", "6", and "9". And, this envelope is directed to
person 4 using post office #7.


(Updated 11/14):
In this problem, unlike the one done in the previous week, you are
allowed to send other peoples' messages to each other. And, to make
thing easier on everyone, I'm also letting the people send ack's with
different labels. However, keep in mind that for person i, he takes the
same response on getting person j's info, regardless of whom sends
person i that info of person j. And similarly, person i takes the same
response on getting an ack labeled "j", regardless of who gives person
i that ack of label "j".

(Updated 11/14):
VERY VERY IMPORTANT!!!! All messages being sent must specify which persons' info is being
contained in it. And, all ack's must be labeled with a number or
numbers. The labels of an ack must be an integer ranging from 1 to N, inclusive. (Same as with
the messages...)

Also, you may use /* ... */ to denote comments, just like in C. (My program will
ignore comments.) For example:

/* OFER'S MAD FLY ALGORITHM */
N = 4;
M = 4;
v = 2;
f = 0.75;

1: {
     start: {	/* Yo yo yall. Let's get things started! */
	send(msg_with(1), 2, 4);
     }
     ack_of(1): { 
	send(msg_with(1), 3, 4); /* The ack is back on attack! */
     }
}

2: {
     start: {
	send(msg_with(2), 3, 3);
     }
     msg_of(1): {
     /*
      *  Upon getting message with 1's info, we do lots of responses!
      *  Mad responses!
      */
	send(msg_with(1, 2), 4, 4);
	send(ack_with(1), 1, 4);
	send(msg_with(2), 1, 3);
	send(msg_with(2) && ack_with(1), 3, 3);
     }
     ack_of(4): {
	send(ack_with(2), 4, 2);
     }
}

3: {
   /* When 1 and 2 come in, 
   you know 3 is next!!! */
     on_events(msg_of(1), msg_of(2)): {
	send(msg_with(3), 1, 2);
	send(msg_with(3), 4, 2);
	send(ack_with(4, 3), 4, 2);
     }
}

4: {
     on_events(msg_of(1), msg_of(2), ack_of(3)): {
	send(ack_with(1, 2), 2, 1);
	send(msg_with(4), 1, 1);
	send(ack_with(4), 2, 1);
	send(msg_with(4), 3, 1);
	/* There might be a flaw in this protocol, see if you can
	   figure it out!*/
     }
     ack_of(2): {
	send(msg_with(3, 4), 2, 1);
     }
}


Lastly, you may use as many spaces, tabs, and newlines as you
want. And it doesn't matter! So the output:

N=15;M=5;v=2;f=0.5;1:{start:{send(msg_with(1), 2, 3);send(msg_with(1), 3, 1);}msg_of(2):{send(ack_with(1), 2, 4);}}

is equivalent to:

N = 15;
M = 5;
v = 2;
f = 0.5;

1: {
     start: {
	send(msg_with(1), 2, 3);
	send(msg_with(1), 3, 1);
     }
     msg_of(2): {
	send(ack_with(1), 2, 4);
     }
}

---------------------- 3: HOW A WINNER IS DETERMINED --------------------------

Under certain input paramters N, M, v, and f, I will run your protocol
several times, each time under a different random seed. Each seed dictates
the number of days each specific letter takes to be sent out. (But the
# of days is always an integer from 1 to 5.)

The winner is the person whose protocol gets ran the most often, under
different seeds, without the spy finding out fraction f of the information or more.

If there is a tie between more than one person's protocol, I will run
all contending protocols with the assumption that each message takes
one day to get to its destination. And whoever's protocol takes the
least number of days is the winner.

Also, you're challenged to give a protocol that's insecure, in order
to see if my program is able to catch a problem. Have fun with this...

---------------------- 4: ASSUMPTIONS LIST ------------------------------

The following is assumed:

- (Updated 11/14) You are expected to change your protocol to
  accomodate my new protocol requirement, which allows users to send other
  peoples' information. 

- (Updated 11/14) The persons' responses are executed immediately the
  moment the necessary letters/acknowledgements have been recieved. So
  for example, suppose you tell person 2 to do a number of things upon
  getting a msg with person 1's info. Then, person 2 will do those
  things immediately the moment after he gets a msg with person 1's
  info.

- (Updated 11/14) Assume the post office takes anywhere from 1 to 5 days to send any
  letter. However, your protocol should be secure regardless of how
  slow or fast the post office is. (And I will reserve the right to purposely allow the
  post office to take more than 5 days on certain messages if it means
  exposing a flaw of security in your protocol...)

- (Updated 11/15) At the moment, my program allows each of the m post
  offices to carry at most 2*(n^3) envelopes (each with as many messages or
  acknowledgements you'd like in it) at one time. This should be enough to support
  almost any protocol you can come up with. If your protocol, at any moment of
  time, causes any one of the post offices to have more than 2*(n^3)
  envelopes, then the behaviour of my program is not guaranteed!

- The spy needs only see any f*N messages to know everything.

- Each person gives their letters directly to any post offices of
  their choice, and each post office sends it mail directly to the
  necessary individuals.

- It takes no time at all for an individual to give mail to the post office. The time
  for the post office to send a piece of mail can vary from 1 to 5
  days. This is determined by my program. (Remember your protocol
  should work regardless of the behavior of the post office.)

- The spy can only read mail, not alter it or send forgery mail to
  individuals.

- The spy can make the visits at any moment of time. The spy can even
  make more than one of his v visits at the same time if he sees it
  fit.

- My program knows the protocol you're using. Therefore, my program
  will "tipoff" the spy about good moments to break-in to certain
  postoffices. Your protocol should be secure enough to guard against
  a spy who's somehow always lucky enough to breakin to post offices
  at the right moments.

- We have decided in class to not have individuals take any special
  actions upon knowing that the spy broke into some post office and
  read certain letters. This makes programming easier on me and
  everyone else (trust me). As a result, this means that Shasha's 
  instrcution: "participants know when spy has visited a post office
  and which one" should not affect your protocols.

- We also voted in class not to use time (# of days so far) as a way
  of dictating what actions each person should take in the protocol
  (since nobody knows for sure how long the post office takes to send
  their stuff).
