proposal for random selection process for nominations

Craig Partridge <craig@aland.bbn.com> Mon, 30 November 1992 18:24 UTC

Received: from ietf.nri.reston.va.us by IETF.CNRI.Reston.VA.US id aa07742; 30 Nov 92 13:24 EST
Received: from CNRI.RESTON.VA.US by IETF.CNRI.Reston.VA.US id aa07731; 30 Nov 92 13:24 EST
Received: from ietf.cnri.reston.va.us by CNRI.Reston.VA.US id aa09298; 30 Nov 92 13:25 EST
Received: from CNRI.RESTON.VA.US by IETF.CNRI.Reston.VA.US id aa07721; 30 Nov 92 13:24 EST
Received: from uu2.psi.com by CNRI.Reston.VA.US id aa09261; 30 Nov 92 13:25 EST
Received: from port10.sunnyvale.pub-ip.psi.net by uu2.psi.com (5.65b/4.0.071791-PSI/PSINet) id AA03912; Mon, 30 Nov 92 13:25:09 -0500
Received: by aland.bbn.com (4.1/3.1.090690-BBN) id AA19386; Mon, 30 Nov 92 10:23:36 PST
Message-Id: <9211301823.AA19386@aland.bbn.com>
To: poised@CNRI.Reston.VA.US
Subject: proposal for random selection process for nominations
Sender: ietf-archive-request@IETF.CNRI.Reston.VA.US
From: Craig Partridge <craig@aland.bbn.com>
Date: Mon, 30 Nov 1992 10:23:36 -0800
X-Orig-Sender: craig@aland.bbn.com

After much musing, here's my proposal for how we pick folks at random for
nominations:

* Persons willing to serve on the IETF and IAB nominations committees
    may, at any time, submit their names and the dates of the two IETF
    meetings they have attended to the IETF Secretariat.  This request to
    be on the list is valid for one year.  The IETF Secretariat must
    acknowledge receipt of the volunteer's message.

    [I'll note that it is important for the Secretariat to beat the bushes
    to get volunteers]

* On the first business day following January 1 and July 1st, the Ombudsman
    e-mails to the ietf mailing list a list of one hundred random numbers.

* On the day following the Ombudsman's posting, the IETF Secretariat
    publishes the current list of persons willing to serve.  This list
    is valid for the next six months. This list must be in alphabetical
    order by last name.  Persons who signed up with the Secretariat but
    are not on the list may demand to be added by presenting the
    acknowledgement from the Secretariat.

* Seven members of the nominating committee plus two alternates are selected
    at random using the selection program available by anonymous FTP
    from various IETF respositories.  This program takes a random seed
    and the list of persons willing to serve and generates a list of
    members plus alternates.  For the first committee in a six month period,
    the first number on the Ombudsman's list of numbers will be used, for
    the second committee, the second number, etc.

============================================================================

DISCUSSION:

    The merit of this scheme is that anyone can compute the members of
    the committee (using the program which is appended).

    It is not quite secure -- if the Ombudsman and the Secretariat collude,
    they can stack the committees.  If the Ombudsman is colluding with
    anyone we've probably got a credibility problem anyway.  But if the
    Ombudsman is honest, we're safe, since the Secretariat cannot manipulate
    the list, and the Ombudsman has not seen the list before it goes out.
    (There's a subtle point about whether folks can subvert the Secretariat's
    list by forging acks from the Secretariat.  Perhaps the Secretariat should
    send PEM-signed messages?).

    The list of a hundred numbers is huge relative to the two or three
    committees we expect to empanel in a six-month period so no worry
    about running out of numbers.  Also, the list of a hundred numbers is
    probably big enough that one can run a reasonable statistical test over
    them to see if they are in fact pseudo-random.

    So it is a public process and takes some effort to subvert, which seems
    about right.

    NOTE: I haven't dealt with recall.  The question is whether recall
    activities are public.  If not, the list of numbers used needs to
    be private, or else the fact that recalls have been attempted must
    be public.  I suppose the Ombudsman could provide a private list
    to the ISOC Trustees and be responsbile to the ISOC Trustees for
    accounting for the numbers used in a six month period if the list
    must be private.

ALTERNATIVE SCHEMES:

    One could make the process stronger by doing things like having each
    volunteers submit their name using PEM and having them include a random
    number with their nomination.  The sum of the volunteers numbers could
    be the key to the selection program (as long as just one volunteer
    picks a random number, the value is random).  But this seems rather
    extreme.

    At the other end of the spectrum, one could just commission someone
    (the Ombudsman, the Secretariat, whomever) to pull names out of a hat
    each time a committee is needed.  But then there's always the chance
    that if the nomination committee makes a decision that some find
    surprising, there will be accusations of a "cooked" committee.  By
    having the selection program public and the list of random numbers
    subject to statistical test, this accusation can be shown to be
    highly unlikely (and thus probably unfounded).

    Various permutations of these alternatives are possible and all seem
    to have the problem of being rather painful, not quite secure (and
    thus no better than the one proposed) or subject to hard to refute
    accusations of cooking the committees.

========================================================================

/**************************************************************************/
/*     a possible IETF nominations committee selection program            */
/**************************************************************************/

#include <stdio.h>
#include <errno.h>

#define CHOICES 7
#define ALTERNATES 2

extern int sys_nerr;
extern char *sys_errlist[];
extern int errno;
extern long countlines();
extern long random();

struct list_elem {
    int position;	/* what file position */
    int alternate;	/* is this person an alternate juror? */
};

/**************************************************************************/

main(argc,argv)
int argc;
char **argv;
{
    FILE *names;
    long filelen;


    /* initialize */
    if (init(&names,argc,argv) != 0)
	return(1);

    /* get the length of the list of names */
    if ((filelen = countlines(names,argv[2],argv[0])) < 0)
	return(2);

    if (filelen < (CHOICES+ALTERNATES))
    {
	(void) fprintf(stderr,"%s: not enough candidates\n",argv[0]);
	return(3);
    }

    if (pick(names,filelen,argv[2],argv[0]) != 0)
	return(4);

    return(0);
}

/**************************************************************************/

init(names,argc,argv)
FILE **names;
int argc;
char **argv;
{
    int seed;

    if (argc != 3)
    {
	(void) fprintf(stderr,"usage: %s seed file\n",argv[0]);
	return(1);
    }

    seed = atoi(argv[1]);

    if ((*names = fopen(argv[2],"r")) == NULL)
    {
	(void) fprintf(stderr,"%s: can't open %s, %s\n",argv[0],argv[2],
	    ((errno < sys_nerr) ? sys_errlist[errno] : "unknown error"));
	return(2);
    }

    srandom(seed);

    (void) printf("starting selection with seed = %d\n",seed);
    return(0);
}

/**************************************************************************/
/* count lines in file and do some straightforward error checks against   */
/* accidents..                                                            */
/**************************************************************************/

long countlines(fp,file,program)
register FILE *fp;
char *file, *program;
{
    register i;
    register long l;
    char buf[BUFSIZ];

    l = 0;
    while (fgets(buf,sizeof(buf),fp) != NULL)
    {
	l++;
	i = strlen(buf);
	/* zero length or huge lines */
	if ((i == 1) || (buf[i-1] != '\n'))
	{
	    (void) fprintf(stderr,"%s: error on %s line %d\n",program,file,l);
	    return(-1);
	}
    }
    (void) rewind(fp);
    return(l);
}

/**************************************************************************/
/*                                                                        */
/**************************************************************************/

pick(fp,len,file,program)
register FILE *fp;
register long len;
char *file, *program;
{
    register int i, j;
    static struct list_elem list[CHOICES+ALTERNATES];
    char buf[BUFSIZ];

    for (i=0; i < CHOICES+ALTERNATES; i++)
    {
	list[i].alternate = (i < CHOICES?0:1);
	while(1)
	{
	    /* if random doesn't mix low bits well, this next line is bad */
	    list[i].position = (int) (random() % len);
	    /* ensure no dupes... */
	    for(j=0; j < i; j++)
	    {
		if (list[i].position == list[j].position)
		    break;
	    }
	    if (j == i)
		break;
	}
    }

    sortlist(list,CHOICES+ALTERNATES);

    for(i=j=0; j < CHOICES+ALTERNATES; i++)
    {
	if (fgets(buf,sizeof(buf),fp) == NULL)
	{
	    (void) fprintf(stderr,"%s: %s file too short (program bug!)\n",
		program,file);
	    return(1);
	}

	buf[strlen(buf)-1] = '\0';	/* null out \n*/

	if (i == list[j].position)
	{
	    if (fprintf(stdout,"%s %s\n",
		buf,(list[j].alternate? "ALTERNATE":"")) == EOF)
	    {
		(void) fprintf(stderr,"%s: can't write to stdout\n",program);
		return(1);
	    }
	    j++;
	}
    }

    return(0);
}

/**************************************************************************/

sortlist(list,len)
register struct list_elem *list;
register int len;
{
    register int i,j;
    struct list_elem le;

    for(i=0; i < len; i++)
    {
	for (j=i+1; j < len; j++)
	{
	    if (list[i].position > list[j].position)
	    {
		le = list[i];
		list[i] = list[j];
		list[j] = le;
	    }
	}
    }
}