viff

changeset 741:16035b12d7ae

Merged with Sphinx documentation.
author Martin Geisler <mg@daimi.au.dk>
date Tue, 29 Apr 2008 08:56:59 +0200
parents 7b4ea9675666 1d741230801b
children 88d4c3f9cee1
files doc/design-talk/design-talk.tex doc/design-talk/example.py doc/design-talk/sample-config.ini viff/runtime.py
diffstat 28 files changed, 1182 insertions(+), 821 deletions(-) [+]
line diff
     1.1 --- a/.hgignore	Mon Apr 28 20:18:55 2008 +0200
     1.2 +++ b/.hgignore	Tue Apr 29 08:56:59 2008 +0200
     1.3 @@ -25,7 +25,6 @@
     1.4  
     1.5  # LaTeX outputs.
     1.6  *.{aux,dvi,log,nav,out,pdf,ps,snm,toc,vrb}
     1.7 -doc/api/
     1.8  
     1.9  # Distutils generated files.
    1.10  build
     2.1 --- a/MANIFEST.in	Mon Apr 28 20:18:55 2008 +0200
     2.2 +++ b/MANIFEST.in	Tue Apr 29 08:56:59 2008 +0200
     2.3 @@ -1,5 +1,3 @@
     2.4 -include doc/design-talk/design-talk.pdf
     2.5 -
     2.6  include doc/api/*.html
     2.7  include doc/api/*.gif
     2.8  include doc/api/*.png
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/doc/conf.py	Tue Apr 29 08:56:59 2008 +0200
     3.3 @@ -0,0 +1,147 @@
     3.4 +# -*- coding: utf-8 -*-
     3.5 +#
     3.6 +# VIFF documentation build configuration file, created by
     3.7 +# sphinx-quickstart on Mon Apr 21 08:54:10 2008.
     3.8 +#
     3.9 +# This file is execfile()d with the current directory set to its
    3.10 +# containing dir.
    3.11 +#
    3.12 +# The contents of this file are pickled, so don't put values in the
    3.13 +# namespace that aren't pickleable (module imports are okay, they're
    3.14 +# removed automatically).
    3.15 +#
    3.16 +# All configuration values have a default value; values that are
    3.17 +# commented out serve to show the default value.
    3.18 +
    3.19 +import sys
    3.20 +
    3.21 +# If your extensions are in another directory, add it here.
    3.22 +#sys.path.append('some/directory')
    3.23 +
    3.24 +# Ensure we load VIFF from the parent directory.
    3.25 +import os
    3.26 +sys.path.insert(0, os.path.abspath('../'))
    3.27 +
    3.28 +# Make viff.util.wrapper a no-op.
    3.29 +os.environ['VIFF_NO_WRAP'] = 'yes'
    3.30 +
    3.31 +# General configuration
    3.32 +# ---------------------
    3.33 +
    3.34 +# Add any Sphinx extension module names here, as strings. They can be
    3.35 +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
    3.36 +# ones.
    3.37 +extensions = ['sphinx.ext.autodoc']
    3.38 +
    3.39 +# Add any paths that contain templates here, relative to this directory.
    3.40 +templates_path = []
    3.41 +
    3.42 +# The suffix of source filenames.
    3.43 +source_suffix = '.txt'
    3.44 +
    3.45 +# The master toctree document.
    3.46 +master_doc = 'index'
    3.47 +
    3.48 +# General substitutions.
    3.49 +project = 'VIFF'
    3.50 +copyright = '2008, VIFF Development Team'
    3.51 +
    3.52 +import viff
    3.53 +
    3.54 +# The default replacements for |version| and |release|, also used in
    3.55 +# various other places throughout the built documents.
    3.56 +#
    3.57 +# The short X.Y version.
    3.58 +version = viff.__version__
    3.59 +# The full version, including alpha/beta/rc tags.
    3.60 +release = viff.__version__
    3.61 +
    3.62 +# There are two options for replacing |today|: either, you set today
    3.63 +# to some non-false value, then it is used:
    3.64 +#today = ''
    3.65 +# Else, today_fmt is used as the format for a strftime call.
    3.66 +today_fmt = '%B %d, %Y'
    3.67 +
    3.68 +# List of documents that shouldn't be included in the build.
    3.69 +#unused_docs = []
    3.70 +
    3.71 +# If true, '()' will be appended to :func: etc. cross-reference text.
    3.72 +#add_function_parentheses = True
    3.73 +
    3.74 +# If true, the current module name will be prepended to all
    3.75 +# description unit titles (such as .. function::).
    3.76 +#add_module_names = True
    3.77 +
    3.78 +# If true, sectionauthor and moduleauthor directives will be shown in
    3.79 +# the output. They are ignored by default.
    3.80 +#show_authors = False
    3.81 +
    3.82 +# The name of the Pygments (syntax highlighting) style to use.
    3.83 +pygments_style = 'sphinx'
    3.84 +
    3.85 +
    3.86 +# Options for HTML output
    3.87 +# -----------------------
    3.88 +
    3.89 +# The style sheet to use for HTML and HTML Help pages. A file of that
    3.90 +# name must exist either in Sphinx' static/ path, or in one of the
    3.91 +# custom paths given in html_static_path.
    3.92 +html_style = 'default.css'
    3.93 +
    3.94 +# Add any paths that contain custom static files (such as style
    3.95 +# sheets) here, relative to this directory. They are copied after the
    3.96 +# builtin static files, so a file named "default.css" will overwrite
    3.97 +# the builtin "default.css".
    3.98 +html_static_path = []
    3.99 +
   3.100 +# If not '', a 'Last updated on:' timestamp is inserted at every page
   3.101 +# bottom, using the given strftime format.
   3.102 +html_last_updated_fmt = '%b %d, %Y'
   3.103 +
   3.104 +# If true, SmartyPants will be used to convert quotes and dashes to
   3.105 +# typographically correct entities.
   3.106 +#html_use_smartypants = True
   3.107 +
   3.108 +# Content template for the index page.
   3.109 +#html_index = ''
   3.110 +
   3.111 +# Custom sidebar templates, maps document names to template names.
   3.112 +#html_sidebars = {}
   3.113 +
   3.114 +# Additional templates that should be rendered to pages, maps page
   3.115 +# names to template names.
   3.116 +#html_additional_pages = {}
   3.117 +
   3.118 +# If false, no module index is generated.
   3.119 +#html_use_modindex = True
   3.120 +
   3.121 +# If true, the reST sources are included in the HTML build as
   3.122 +# _sources/<name>.
   3.123 +#html_copy_source = True
   3.124 +
   3.125 +# Output file base name for HTML help builder.
   3.126 +htmlhelp_basename = 'VIFFdoc'
   3.127 +
   3.128 +
   3.129 +# Options for LaTeX output
   3.130 +# ------------------------
   3.131 +
   3.132 +# The paper size ('letter' or 'a4').
   3.133 +#latex_paper_size = 'letter'
   3.134 +
   3.135 +# The font size ('10pt', '11pt' or '12pt').
   3.136 +#latex_font_size = '10pt'
   3.137 +
   3.138 +# Grouping the document tree into LaTeX files. List of tuples
   3.139 +# (source start file, target name, title, author, document class
   3.140 +# [howto/manual]).
   3.141 +#latex_documents = []
   3.142 +
   3.143 +# Additional stuff for the LaTeX preamble.
   3.144 +#latex_preamble = ''
   3.145 +
   3.146 +# Documents to append as an appendix to all manuals.
   3.147 +#latex_appendices = []
   3.148 +
   3.149 +# If false, no module index is generated.
   3.150 +#latex_use_modindex = True
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/doc/config.txt	Tue Apr 29 08:56:59 2008 +0200
     4.3 @@ -0,0 +1,18 @@
     4.4 +
     4.5 +Config Module
     4.6 +=============
     4.7 +
     4.8 +.. automodule:: viff.config
     4.9 +
    4.10 +   .. autoclass:: Player
    4.11 +      :members: prfs, dealer_prfs
    4.12 +
    4.13 +      .. attribute:: id
    4.14 +                     host
    4.15 +                     port
    4.16 +
    4.17 +         ID, hostname, and portnumber of the player.
    4.18 +
    4.19 +   .. autofunction:: generate_configs
    4.20 +
    4.21 +   .. autofunction:: load_config
     5.1 --- a/doc/design-talk/design-talk.tex	Mon Apr 28 20:18:55 2008 +0200
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,367 +0,0 @@
     5.4 -\documentclass[t,noamsthm]{beamer}
     5.5 -
     5.6 -\mode<presentation>
     5.7 -{
     5.8 -  \usetheme{Goettingen}
     5.9 -  \setbeamercovered{transparent}
    5.10 -  \setbeamertemplate{navigation symbols}{}
    5.11 -}
    5.12 -
    5.13 -\usepackage[english]{babel}
    5.14 -\usepackage[latin1]{inputenc}
    5.15 -\usepackage[T1]{fontenc}
    5.16 -\usepackage{lmodern,textcomp}
    5.17 -
    5.18 -\title[VIFF]{Virtual Ideal Functionality Framework}
    5.19 -
    5.20 -\subtitle{High-Level Design Overview}
    5.21 -
    5.22 -\author{Martin Geisler}
    5.23 -
    5.24 -\institute[BRICS]{
    5.25 -  BRICS\\
    5.26 -  Department of Computer Science\\
    5.27 -  University of Aarhus
    5.28 -}
    5.29 -
    5.30 -\date{September 20th, 2007}
    5.31 -
    5.32 -% \pgfdeclareimage[height=0.5cm]{university-logo}{university-logo-filename}
    5.33 -% \logo{\pgfuseimage{university-logo}}
    5.34 -
    5.35 -% If you wish to uncover everything in a step-wise fashion, uncomment
    5.36 -% the following command: 
    5.37 -%\beamerdefaultoverlayspecification{<+->}
    5.38 -
    5.39 -\usepackage{tikz}
    5.40 -
    5.41 -\newcommand{\rulecolor}{structure!60}
    5.42 -\newcommand{\fillcolor}{structure!15}
    5.43 -
    5.44 -\tikzstyle{player}=[circle,fill=\fillcolor,draw=\rulecolor]
    5.45 -\tikzstyle{every picture}=[thick]
    5.46 -
    5.47 -
    5.48 -\usepackage{listings}
    5.49 -\lstset{
    5.50 -  language=Python,
    5.51 -  basicstyle=\footnotesize,
    5.52 -  columns=fullflexible,
    5.53 -  showstringspaces=false,
    5.54 -  frame=single,
    5.55 -  framerule=0.8pt,
    5.56 -  rulecolor=\color{\rulecolor},
    5.57 -  backgroundcolor=\color{\fillcolor}
    5.58 -}
    5.59 -\newcommand{\py}[1]{\lstinline|#1|}
    5.60 -
    5.61 -\usepackage{nath} \delimgrowth=2
    5.62 -
    5.63 -\begin{document}
    5.64 -
    5.65 -\begin{frame}
    5.66 -  \titlepage
    5.67 -\end{frame}
    5.68 -
    5.69 -%\begin{frame}{Outline}
    5.70 -%  \tableofcontents
    5.71 -%  % You might wish to add the option [pausesections]
    5.72 -%\end{frame}
    5.73 -
    5.74 -\section{Features}
    5.75 -
    5.76 -\begin{frame}{VIFF Features}
    5.77 -
    5.78 -  \begin{itemize}
    5.79 -
    5.80 -  \item API for writing secure multi-party computations
    5.81 -    \begin{itemize}
    5.82 -    \item Easy to use: \py{a + b + c} instead of \py{add(add(a, b), c)}
    5.83 -    \item Simple if you already know Python
    5.84 -    \item A custom language could be added
    5.85 -    \end{itemize}
    5.86 -
    5.87 -  \item<2-> Efficient asynchronous design
    5.88 -    \begin{itemize}
    5.89 -    \item Automatic parallelism
    5.90 -    \item Single-threaded (no locks!)
    5.91 -    \end{itemize}
    5.92 -    
    5.93 -  \item<3-> Simple architecture
    5.94 -    \begin{itemize}
    5.95 -    \item Small code base (2,500 lines)
    5.96 -    \item Few layers of abstraction\dots
    5.97 -    \item \dots but hopefully sufficiently many
    5.98 -    \end{itemize}
    5.99 -
   5.100 -  \end{itemize}
   5.101 -
   5.102 -\end{frame}
   5.103 -
   5.104 -\section{Example}
   5.105 -
   5.106 -\begin{frame}{Example MPC Calculation}
   5.107 -
   5.108 -  \begin{columns}
   5.109 -
   5.110 -    \column{0.5\textwidth}
   5.111 -
   5.112 -    \centering
   5.113 -    \begin{tikzpicture}
   5.114 -      \draw (0,0) + (90:2cm) node[player] (P1) {$P_1$}
   5.115 -                  +(210:2cm) node[player] (P2) {$P_2$}
   5.116 -                  +(330:2cm) node[player] (P3) {$P_3$};
   5.117 -
   5.118 -      \visible<1>{
   5.119 -        \draw (P1.north) node[above] {$x$};
   5.120 -        \draw (P2.south) node[below] {$y$};
   5.121 -        \draw (P3.south) node[below] {$z$};
   5.122 -      }
   5.123 -
   5.124 -      \visible<2>{
   5.125 -        \draw[->] (P1) .. controls +(75:1cm) and +(105:1cm) ..
   5.126 -          node[above,sloped] {$x_1$} (P1);
   5.127 -        \draw[->] (P1) .. controls +(230:1cm) and +(70:1cm) ..
   5.128 -          node[above,sloped] {$x_2$} (P2);
   5.129 -        \draw[->] (P1) .. controls +(-50:1cm) and +(110:1cm) ..
   5.130 -          node[above,sloped] {$x_3$} (P3);
   5.131 -
   5.132 -        \draw[->] (P2) .. controls +(50:1cm) and +(250:1cm) ..
   5.133 -          node[below,sloped] {$y_1$} (P1);
   5.134 -        \draw[->] (P2) .. controls +(225:1cm) and +(255:1cm) ..
   5.135 -          node[below,xshift=1pt] {$y_2$} (P2);
   5.136 -        \draw[->] (P2) .. controls +(10:1cm) and +(170:1cm) ..
   5.137 -          node[above,sloped] {$y_3$} (P3);
   5.138 -
   5.139 -        \draw[->] (P3) .. controls +(130:1cm) and +(-70:1cm) ..
   5.140 -          node[below,sloped] {$z_1$} (P1);
   5.141 -        \draw[->] (P3) .. controls +(-170:1cm) and +(-10:1cm) ..
   5.142 -          node[below,sloped] {$z_2$} (P2);
   5.143 -        \draw[->] (P3) .. controls +(-75:1cm) and +(-45:1cm) ..
   5.144 -          node[below,xshift=-1pt] {$z_3$} (P3);
   5.145 -      }
   5.146 -
   5.147 -      \visible<3>{
   5.148 -        \draw (P1.north) node[above] {$x_1$, $y_1$, $z_1$};
   5.149 -        \draw (P2.south) node[below,xshift=6pt] {$x_2$, $y_2$, $z_2$};
   5.150 -        \draw (P3.south) node[below,xshift=-6pt] {$x_3$, $y_3$, $z_3$};
   5.151 -      }
   5.152 -
   5.153 -      \visible<4>{
   5.154 -        \draw[<->,dashed] (P1) -- (P2);
   5.155 -        \draw[<->,dashed] (P2) -- (P3);
   5.156 -        \draw[<->,dashed] (P3) -- (P1);
   5.157 -      }
   5.158 -
   5.159 -      \visible<5-6>{
   5.160 -        \draw (P1.north) node[above] {$r_1$};
   5.161 -        \draw (P2.south) node[below] {$r_2$};
   5.162 -        \draw (P3.south) node[below] {$r_3$};
   5.163 -      }
   5.164 -
   5.165 -      \visible<6>{
   5.166 -        \draw[->] (P1) .. controls +(230:1cm) and +(70:1cm) ..
   5.167 -          node[above,sloped] {$r_1$} (P2);
   5.168 -        \draw[->] (P1) .. controls +(-50:1cm) and +(110:1cm) ..
   5.169 -          node[above,sloped] {$r_1$} (P3);
   5.170 -
   5.171 -        \draw[->] (P2) .. controls +(50:1cm) and +(250:1cm) ..
   5.172 -          node[below,sloped] {$r_2$} (P1);
   5.173 -        \draw[->] (P2) .. controls +(10:1cm) and +(170:1cm) ..
   5.174 -          node[above,sloped] {$r_2$} (P3);
   5.175 -
   5.176 -        \draw[->] (P3) .. controls +(130:1cm) and +(-70:1cm) ..
   5.177 -          node[below,sloped] {$r_3$} (P1);
   5.178 -        \draw[->] (P3) .. controls +(-170:1cm) and +(-10:1cm) ..
   5.179 -          node[below,sloped] {$r_3$} (P2);
   5.180 -      }
   5.181 -
   5.182 -      \visible<7>{
   5.183 -        \draw (P1.north) node[above] {$r$};
   5.184 -        \draw (P2.south) node[below] {$r$};
   5.185 -        \draw (P3.south) node[below] {$r$};
   5.186 -      }
   5.187 -
   5.188 -    \end{tikzpicture}
   5.189 -
   5.190 -    \column{0.5\textwidth}
   5.191 -
   5.192 -    \begin{itemize}
   5.193 -    \item<1-> Players $P_1$, $P_2$, and $P_3$
   5.194 -    \item<2-> Sharing $x$, $y$, and $z$
   5.195 -    \item<4-> Compute $r= (x+y)\cdot z$
   5.196 -    \item<6-> Opens the result $r$
   5.197 -    \end{itemize}
   5.198 -
   5.199 -  \end{columns}
   5.200 -\end{frame}
   5.201 -
   5.202 -\begin{frame}{Example VIFF Program}
   5.203 -
   5.204 -\mbox{}\vspace{-2\baselineskip}
   5.205 -
   5.206 -\begin{columns}
   5.207 -  \column{0.625\textwidth}
   5.208 -  \lstinputlisting[linerange={1-5}]{example.py}
   5.209 -  \column{0.375\textwidth}
   5.210 -  \begin{itemize}
   5.211 -  \item Import standard and VIFF modules
   5.212 -  \end{itemize}
   5.213 -\end{columns}
   5.214 -
   5.215 -\vspace{-0.75\baselineskip}
   5.216 -
   5.217 -\begin{columns}
   5.218 -  \column{0.625\textwidth}
   5.219 -  \uncover<2->{\lstinputlisting[linerange={7-9}]{example.py}}
   5.220 -  \column{0.375\textwidth}
   5.221 -  \begin{itemize}
   5.222 -  \item<2-> Load command line config
   5.223 -  \end{itemize}
   5.224 -\end{columns}
   5.225 -
   5.226 -\vspace{-0.75\baselineskip}
   5.227 -
   5.228 -\begin{columns}
   5.229 -  \column{0.625\textwidth}
   5.230 -  \uncover<3->{\lstinputlisting[linerange={11-13}]{example.py}}
   5.231 -  \column{0.375\textwidth}
   5.232 -  \begin{itemize}
   5.233 -  \item<3-> Create Runtime, do calculation
   5.234 -  \end{itemize}
   5.235 -\end{columns}
   5.236 -
   5.237 -\vspace{-0.75\baselineskip}
   5.238 -
   5.239 -\begin{columns}
   5.240 -  \column{0.625\textwidth}
   5.241 -  \uncover<4->{\lstinputlisting[linerange={15-17}]{example.py}}
   5.242 -  \column{0.375\textwidth}
   5.243 -  \begin{itemize}
   5.244 -  \item<4-> Open and print result
   5.245 -  \end{itemize}
   5.246 -\end{columns}
   5.247 -
   5.248 -\end{frame}
   5.249 -
   5.250 -\begin{frame}{Example Configuration File}
   5.251 -
   5.252 -  \lstdefinelanguage{ini}{
   5.253 -    morecomment=[l]{\#},
   5.254 -    moredelim=[s][\textbf]{[}{]},
   5.255 -    moredelim=[s][\textbf]{[[}{]]},
   5.256 -    moredelim=[s][\textbf]{[[[}{]]]}
   5.257 -  }
   5.258 -
   5.259 -  \lstinputlisting[language=ini]{sample-config.ini}
   5.260 -
   5.261 -\end{frame}
   5.262 -
   5.263 -\section{Scheduling}
   5.264 -
   5.265 -\begin{frame}{Asynchronous Design}
   5.266 -
   5.267 -  \begin{columns}
   5.268 -
   5.269 -    \column{0.3\textwidth}
   5.270 -
   5.271 -    \begin{tikzpicture}
   5.272 -      \tikzstyle{level 1}=[level distance=10mm]
   5.273 -
   5.274 -      \draw (-0.25,0) node {$r = (x+y) \cdot z$};
   5.275 -      \draw (0,-0.5) node[xshift=-0.75pt,rotate=-90] {$\rightsquigarrow$};
   5.276 -
   5.277 -      \draw (0,-1) node {open}
   5.278 -        child {node {\py{*}}
   5.279 -          child {node {\py{+}}
   5.280 -            child {node {x}}
   5.281 -            child {node {y}}
   5.282 -          }
   5.283 -          child {node {z}}};
   5.284 -    \end{tikzpicture}
   5.285 -
   5.286 -    \column{0.7\textwidth}
   5.287 -
   5.288 -    \begin{itemize}
   5.289 -    \item Entire tree is scheduled as once
   5.290 -    \item Operations wait on their operands
   5.291 -    \item Results are sent when ready
   5.292 -    \item Result is a form of ``greedy scheduling''
   5.293 -    \item Implicit synchronization, no rounds
   5.294 -    \end{itemize}
   5.295 -
   5.296 -  \end{columns}
   5.297 -
   5.298 -\end{frame}
   5.299 -
   5.300 -\begin{frame}{Greedy Scheduling}
   5.301 -  Advantages:
   5.302 -  \begin{itemize}
   5.303 -  \item At least as efficient as round-based scheduling
   5.304 -  \item No cost when adding primitives (modular design)
   5.305 -  \item Automatic parallelism
   5.306 -  \end{itemize}
   5.307 -
   5.308 -  Disadvantages:
   5.309 -  \begin{itemize}
   5.310 -  \item Not yet proven secure\dots
   5.311 -  \end{itemize}
   5.312 -\end{frame}
   5.313 -
   5.314 -
   5.315 -\section{Current Status}
   5.316 -
   5.317 -\begin{frame}{What has been Implemented?}
   5.318 -  \begin{itemize}
   5.319 -  \item Shamir sharing
   5.320 -  \item PRSS
   5.321 -  \item Opening
   5.322 -  \item Addition, multiplication, exclusive-or
   5.323 -  \item Classic SCET comparison
   5.324 -  \end{itemize}
   5.325 -\end{frame}
   5.326 -
   5.327 -
   5.328 -\begin{frame}{Assumptions}
   5.329 -  
   5.330 -  Current primitives assume:
   5.331 -  \begin{itemize}
   5.332 -  \item Fixed number of players
   5.333 -  \item Passive and static adversary
   5.334 -  \item Threshold adversary structure, $t < \frac n 2$
   5.335 -  \end{itemize}
   5.336 -
   5.337 -  
   5.338 -\end{frame}
   5.339 -
   5.340 -\section{Conclusion}
   5.341 -
   5.342 -\begin{frame}{Conclusion}
   5.343 -
   5.344 -\begin{itemize}
   5.345 -\item VIFF offers a light-weight design for doing MPC
   5.346 -\item Asynchronous design gives automatic parallelism
   5.347 -\end{itemize}
   5.348 -
   5.349 -Installation instructions, source code and more:
   5.350 -\begin{itemize}
   5.351 -\item \url{http://viff.dk/}
   5.352 -\end{itemize}
   5.353 -
   5.354 -\visible<2>{
   5.355 -  \begin{center}
   5.356 -    \bigskip
   5.357 -    \begin{tikzpicture}
   5.358 -      \draw node[rectangle,draw=\rulecolor,fill=\fillcolor,
   5.359 -        inner sep=2.5em,font=\huge\bfseries] {Questions?};
   5.360 -    \end{tikzpicture}
   5.361 -  \end{center}
   5.362 -}
   5.363 -
   5.364 -\end{frame}
   5.365 -
   5.366 -
   5.367 -
   5.368 -\end{document}
   5.369 -
   5.370 -% LocalWords:  VIFF API MPC PRSS SCET
     6.1 --- a/doc/design-talk/example.py	Mon Apr 28 20:18:55 2008 +0200
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,17 +0,0 @@
     6.4 -import sys
     6.5 -from viff.field import GF
     6.6 -from viff.config import load_config
     6.7 -from viff.runtime import Runtime
     6.8 -from viff.util import dprint
     6.9 -
    6.10 -Z31 = GF(31)
    6.11 -my_id, conf = load_config(sys.argv[1])
    6.12 -my_input = Z31(int(sys.argv[2]))
    6.13 -
    6.14 -rt = Runtime(conf, my_id, 1)
    6.15 -x, y, z = rt.shamir_share(my_input)
    6.16 -result = (x + y) * z
    6.17 -
    6.18 -opened_result = rt.open(result)
    6.19 -dprint("Result: %s", opened_result)
    6.20 -rt.wait_for(opened_result)
     7.1 --- a/doc/design-talk/sample-config.ini	Mon Apr 28 20:18:55 2008 +0200
     7.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.3 @@ -1,19 +0,0 @@
     7.4 -[Player 1]
     7.5 -  host = camel09
     7.6 -  port = 7100
     7.7 -[Player 2]
     7.8 -  host = camel17
     7.9 -  port = 7200
    7.10 -[Player 3]
    7.11 -  host = camel19
    7.12 -  port = 7300
    7.13 -  [[prss_keys]]
    7.14 -    1 3 = 0x47D5B9B367DAFC9267EDF518AD5B5F396299L
    7.15 -    2 3 = 0x7EBC55E5CF1D014D081EA428B5F35FD12C64L
    7.16 -  [[prss_dealer_keys]]
    7.17 -    [[[Dealer 1]]]
    7.18 -      1 3 = 0x903039893A06800A0FA7175CED8CC17B873BL
    7.19 -      2 3 = 0x11C91354237193397589A1D1C6455F87CB79L
    7.20 -    # More PRSS keys...
    7.21 -
    7.22 -# End of config
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/doc/field.txt	Tue Apr 29 08:56:59 2008 +0200
     8.3 @@ -0,0 +1,23 @@
     8.4 +
     8.5 +Finite Fields Module
     8.6 +====================
     8.7 +
     8.8 +.. automodule:: viff.field
     8.9 +
    8.10 +   .. autoclass:: FieldElement
    8.11 +
    8.12 +   .. autoclass:: GF256
    8.13 +      :members: __add__, __mul__, __pow__, __div__, __neg__, __invert__, __eq__, __nonzero__
    8.14 +
    8.15 +      .. attribute:: GF256.modulus
    8.16 +
    8.17 +         Field modulus, always 256.
    8.18 +
    8.19 +      .. method:: GF256.__sub__(other)
    8.20 +                  GF256.__xor__(other)
    8.21 +
    8.22 +         Subtraction and exclusive-or. Since GF(2^8) has
    8.23 +         characteristic 2, these two operations are identical to
    8.24 +         addition.
    8.25 +
    8.26 +   .. autofunction:: GF
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/doc/glossary.txt	Tue Apr 29 08:56:59 2008 +0200
     9.3 @@ -0,0 +1,18 @@
     9.4 +
     9.5 +Glossary
     9.6 +========
     9.7 +
     9.8 +.. glossary::
     9.9 +
    9.10 +   Ideal functionality
    9.11 +     An ideal functionality is an uncorruptable party in an ideal
    9.12 +     protocol.
    9.13 +
    9.14 +   Program counter
    9.15 +     A label associated with an operation, used to identify the data
    9.16 +     when it is received over the network. Please see :ref:`program-counters`.
    9.17 +
    9.18 +   VIFF
    9.19 +     Abbreviation for *Virtual Ideal Functionality Framework*. VIFF
    9.20 +     allows you to write programs which behave as if they had access
    9.21 +     to an :term:`ideal functionality`.
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/doc/implementation.txt	Tue Apr 29 08:56:59 2008 +0200
    10.3 @@ -0,0 +1,17 @@
    10.4 +
    10.5 +Implementation
    10.6 +==============
    10.7 +
    10.8 +VIFF consists of several modules which will be described next.
    10.9 +
   10.10 +.. toctree::
   10.11 +   :maxdepth: 2
   10.12 +
   10.13 +   util
   10.14 +   field
   10.15 +   shamir
   10.16 +   matrix
   10.17 +   runtime
   10.18 +   prss
   10.19 +   config
   10.20 +   program-counters
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/doc/index.txt	Tue Apr 29 08:56:59 2008 +0200
    11.3 @@ -0,0 +1,25 @@
    11.4 +
    11.5 +Welcome to VIFF's documentation!
    11.6 +================================
    11.7 +
    11.8 +The Virtual Ideal Functionality Framework is a general framework for
    11.9 +doing secure multi-party computation.
   11.10 +
   11.11 +
   11.12 +Contents:
   11.13 +
   11.14 +.. toctree::
   11.15 +   :maxdepth: 2
   11.16 +
   11.17 +   overview
   11.18 +   install
   11.19 +   implementation
   11.20 +   glossary
   11.21 +
   11.22 +
   11.23 +Indices and tables
   11.24 +==================
   11.25 +
   11.26 +* :ref:`genindex`
   11.27 +* :ref:`modindex`
   11.28 +* :ref:`search`
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/doc/install.txt	Tue Apr 29 08:56:59 2008 +0200
    12.3 @@ -0,0 +1,247 @@
    12.4 +.. -*- coding: utf-8 -*-
    12.5 +.. (Links are marked with underscores, see the bottom of the file.)
    12.6 +
    12.7 +====================
    12.8 + Installation Guide
    12.9 +====================
   12.10 +
   12.11 +VIFF is written in Python and uses the Twisted framework for
   12.12 +asynchronous communication, (optionally) python-gnutls for secure
   12.13 +communication, ConfigObj for configuration files, and GMPY for fast
   12.14 +bignum arithmetic. You can find these components here:
   12.15 +
   12.16 +:Python:         http://python.org/
   12.17 +:Twisted:        http://twistedmatrix.com/
   12.18 +:python-gnutls:  http://pypi.python.org/pypi/python-gnutls/
   12.19 +:ConfigObj:      http://voidspace.org.uk/python/configobj.html
   12.20 +:GMPY:           http://code.google.com/p/gmpy/
   12.21 +
   12.22 +VIFF has been successfully tested with the following versions:
   12.23 +
   12.24 +:Python:         2.4.1 and 2.5.0
   12.25 +:Twisted:        2.5.0 (there are `problems with 8.0.1`_)
   12.26 +:python-gnutls:  1.1.4
   12.27 +:ConfigObj:      4.4.0
   12.28 +:GMPY:           1.0alpha and 1.0.2
   12.29 +
   12.30 +Please `report back`_ if you find that VIFF works with other versions
   12.31 +than the ones listed here.
   12.32 +
   12.33 +Below you will find installation instructions for the different
   12.34 +platforms on which we `test VIFF`_.
   12.35 +
   12.36 +
   12.37 +Windows
   12.38 +-------
   12.39 +
   12.40 +This describes the installation procedure for VIFF on Windows. It has
   12.41 +been tested and verified on Windows XP Professional Version 2002 SP2
   12.42 +and Windows Vista Ultimate SP1.
   12.43 +
   12.44 +1) Download and install Python_.
   12.45 +
   12.46 +2) Include the path to your Python installation (e.g. ``C:\Python25\``)
   12.47 +   in the ``PATH`` system environment variable. One way to edit this
   12.48 +   environment variable is by right-clicking My Computer in the Start
   12.49 +   menu, selecting Properties, Advanced, and then pressing the
   12.50 +   Environment Variables button.
   12.51 +
   12.52 +3) Download and install Twisted_.
   12.53 +
   12.54 +4) Download ConfigObj_ and enter::
   12.55 +
   12.56 +      python setup.py install
   12.57 +
   12.58 +   from the folder where you unzipped the files.
   12.59 +
   12.60 +5) Download and install GMPY_. If you are using Vista, right-click on
   12.61 +   the installer and choose the option to run as administrator.
   12.62 +
   12.63 +6) In order to secure the channels between the players using TLS, you
   12.64 +   need to download and install python-gnutls_. However, we haven't
   12.65 +   had the time to test installation of this on Windows yet. Feel free
   12.66 +   to contribute with details about this by sending an email to the
   12.67 +   `VIFF mailing list`_.
   12.68 +
   12.69 +7) Download and install VIFF_. Note that if you are using the
   12.70 +   installer on Vista, you will again need to run it as an
   12.71 +   administrator.
   12.72 +
   12.73 +8) Proceed to `testing`_.
   12.74 +
   12.75 +
   12.76 +Mac OS X
   12.77 +--------
   12.78 +
   12.79 +This describes installation of VIFF on Max OS X 10.5.
   12.80 +
   12.81 +1) Download and install the full MacPython_ version 2.5 (the
   12.82 +   Python-installation which comes with Mac OS X is not entirely
   12.83 +   up-to-date).
   12.84 +
   12.85 +2) Download and Install Twisted_ from source. Notice again that Mac OS
   12.86 +   X comes with a pre-installed version of Twisted, but this is not
   12.87 +   the full Twisted installation. After installation change your
   12.88 +   ``PYTHONPATH`` (in your ``~/.bash_profile``) to::
   12.89 +
   12.90 +      PATH="/Library/Python/2.5/site-packages:${PATH}"
   12.91 +
   12.92 +3) You can skip this step if you do not want secure connections.
   12.93 +   Otherwise install python-gnutls_:
   12.94 +
   12.95 +   a) Install XCode_ from Apple which provides the GCC compiler.
   12.96 +   b) Install gnutls_ (and required packages) from source.
   12.97 +   c) Install python-gnutls_.
   12.98 +
   12.99 +4) Download ConfigObj_ and enter::
  12.100 +
  12.101 +      python setup.py install
  12.102 +
  12.103 +   from the folder where you unzipped the files.
  12.104 +
  12.105 +5) Download and install GMPY_ following the instructions in
  12.106 +   ``gmpy-1.02.macosx.README.txt`` (under Downloads).
  12.107 +
  12.108 +6) Install VIFF from source (see below). If you prefer you can just
  12.109 +   install it in site-packages, it makes no difference. For
  12.110 +   developers, it is perhaps a better solution in to create a symbolic
  12.111 +   link from the site-packages directory to the VIFF Python files
  12.112 +   (``viff/viff/``), as otherwise you need to re-install VIFF each time
  12.113 +   the project is modified.
  12.114 +
  12.115 +7) Proceed to `testing`_.
  12.116 +
  12.117 +
  12.118 +GNU/Linux
  12.119 +---------
  12.120 +
  12.121 +VIFF was originally developed on GNU/Linux and is well supported
  12.122 +there. When installing the VIFF dependencies you either have the
  12.123 +option of using your `package manager`_ or to install from source. VIFF
  12.124 +itself must be installed `from source`_.
  12.125 +
  12.126 +
  12.127 +Using a Package Manager
  12.128 +~~~~~~~~~~~~~~~~~~~~~~~
  12.129 +
  12.130 +Debian Lenny (testing)
  12.131 +  You can install all dependencies by the command::
  12.132 +
  12.133 +     aptitude install python-twisted-core python-gnutls \
  12.134 +                      python-configobj python-gmpy
  12.135 +
  12.136 +  The backslash indicates that both lines should be typed as a single
  12.137 +  line in the terminal.
  12.138 +
  12.139 +Ubuntu
  12.140 +  We expect that the instructions for Debian also apply here.
  12.141 +
  12.142 +
  12.143 +If you know how to install using other package managers, please `let
  12.144 +us know`_.
  12.145 +
  12.146 +VIFF itself is not yet packaged for any distribution, so you will have
  12.147 +to install it from source as described below.
  12.148 +
  12.149 +
  12.150 +Installing from Source
  12.151 +~~~~~~~~~~~~~~~~~~~~~~
  12.152 +
  12.153 +If you do not have permission to use the package manager or simply
  12.154 +prefer to install from source, then (assuming that Python is already
  12.155 +installed) one can easily install VIFF and its dependencies by
  12.156 +downloading and unpacking each of them and executing::
  12.157 +
  12.158 +   python setup.py install --home=$HOME/opt
  12.159 +
  12.160 +That will install everything under the given prefix. With the above
  12.161 +command the Python modules are installed into::
  12.162 +
  12.163 +   $HOME/opt/lib/python
  12.164 +
  12.165 +and some programs are installed into::
  12.166 +
  12.167 +   $HOME/opt/bin
  12.168 +
  12.169 +You should add the first directory to the ``PYTHONPATH`` environment
  12.170 +variable and the latter to the ``PATH`` environment variable.
  12.171 +
  12.172 +Bash uses can normally do this by adding::
  12.173 +
  12.174 +   export PYTHONPATH=$PYTHONPATH:$HOME/opt/lib/python
  12.175 +   export PATH=$PATH:$HOME/opt/bin
  12.176 +
  12.177 +to their ``~/.bash_profile`` file, creating it if it is not already
  12.178 +there. Consult the documentation for your shell to learn how
  12.179 +environment variables are set.
  12.180 +
  12.181 +
  12.182 +Testing
  12.183 +-------
  12.184 +
  12.185 +To verify the installation, try out one of the applications. We will
  12.186 +run the millionaires example with three players and a threshold of
  12.187 +one. For this test, we will let all players run on localhost: Player 1
  12.188 +will run on port 9001, player 2 on port 9002, and player 3 on port
  12.189 +9003. The test is done on Windows, but it works the same on the other
  12.190 +platforms. Do the following:
  12.191 +
  12.192 +1) Go to the ``viff/apps/`` directory and generate the needed
  12.193 +   configuration files by entering::
  12.194 +
  12.195 +     python generate-config-files.py -n 3 -t 1
  12.196 +     localhost:9001 localhost:9002 localhost:9003
  12.197 +
  12.198 +   Both lines should be entered as a single line.
  12.199 +
  12.200 +2) Open three separate command prompts and go to the ``viff/apps/``
  12.201 +   directory in each. In the first, type::
  12.202 +
  12.203 +     python millionaires.py --no-tls player-3.ini
  12.204 +
  12.205 +   in the second, type::
  12.206 +
  12.207 +     python millionaires.py --no-tls player-2.ini
  12.208 +
  12.209 +   and in the last, type::
  12.210 +
  12.211 +     python millionaires.py --no-tls player-1.ini
  12.212 +
  12.213 +   Note that the order in wich you start the players is important: The
  12.214 +   players must start in reverse order, e.g. the last player first. If
  12.215 +   the installation works, you should see something like this from
  12.216 +   e.g. player 3::
  12.217 +
  12.218 +      C:\viff\apps> python millionaires.py --no-tls player-3.ini 
  12.219 +      Seeding random generator with random seed 7416
  12.220 +      Not using TLS
  12.221 +      I am Millionaire 3 and I am worth 20 millions.
  12.222 +      From poorest to richest:
  12.223 +        Millionaire 2
  12.224 +        Millionaire 3 (20 millions)
  12.225 +        Millionaire 1
  12.226 +      Initiating shutdown sequence.
  12.227 +
  12.228 +   If something went wrong, then please `file a bug report`_ or report
  12.229 +   it on the `VIFF mailing list`_. This will help us improve VIFF.
  12.230 +
  12.231 +
  12.232 +.. _problems with 8.0.1: http://tracker.viff.dk/issue37
  12.233 +.. _report back:
  12.234 +.. _VIFF mailing list:
  12.235 +.. _let us know: viff-devel@viff.dk
  12.236 +
  12.237 +.. _VIFF: http://viff.dk/
  12.238 +.. _test VIFF: http://buildbot.viff.dk/
  12.239 +.. _Python: http://python.org/
  12.240 +.. _Twisted: http://twistedmatrix.com/
  12.241 +.. _ConfigObj: http://voidspace.org.uk/python/configobj.html
  12.242 +.. _GMPY: http://code.google.com/p/gmpy/
  12.243 +.. _python-gnutls: http://pypi.python.org/pypi/python-gnutls/
  12.244 +.. _MacPython: http://www.pythonmac.org
  12.245 +.. _XCode: http://developer.apple.com/tools/xcode/
  12.246 +.. _gnutls: http://www.gnu.org/software/gnutls/manual/gnutls.html
  12.247 +            #Downloading-and-Installing
  12.248 +.. _package manager: `Using a Package Manager`_
  12.249 +.. _from source: `Installing from Source`_
  12.250 +.. _file a bug report: http://tracker.viff.dk/
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/doc/matrix.txt	Tue Apr 29 08:56:59 2008 +0200
    13.3 @@ -0,0 +1,10 @@
    13.4 +
    13.5 +Matrix Module
    13.6 +=============
    13.7 +
    13.8 +.. automodule:: viff.matrix
    13.9 +
   13.10 +   .. autoclass:: Matrix
   13.11 +      :members: __add__, __mul__, __str__, transpose, determinant
   13.12 +
   13.13 +   .. autofunction:: hyper
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/doc/overview.txt	Tue Apr 29 08:56:59 2008 +0200
    14.3 @@ -0,0 +1,97 @@
    14.4 +
    14.5 +Overview
    14.6 +========
    14.7 +
    14.8 +VIFF allows you to write a program which will interact with other
    14.9 +programs in order to execute a joint computation. This is called a
   14.10 +multi-party computation, MPC for short.
   14.11 +
   14.12 +The programs will implement what we call a virtual :term:`ideal
   14.13 +functionality` (IF). The idea is that the behavior of the programs
   14.14 +should be indistinguishable from the behavior of programs interacting
   14.15 +with a so-called ideal functionality. An ideal functionality is a
   14.16 +player that cannot be corrupted, also known as a trusted third party
   14.17 +(TTP).
   14.18 +
   14.19 +Interacting with an IF is easy: all players give their inputs to the
   14.20 +IF, which computes the results. The results are then distributed to
   14.21 +the correct players. The inputs and the results are sent over secure
   14.22 +channels, and since the IF cannot be corrupted, this ideal protocol
   14.23 +must be secure.
   14.24 +
   14.25 +In the real world there is no IF, but VIFF allows you to implement a
   14.26 +virtual ideal functionality. The behavior of a bunch of programs using
   14.27 +VIFF is indistinguishable from program running in the ideal world. It
   14.28 +is indistinguishable in the sense that everything that can happen in
   14.29 +the real world protocol could happen in the ideal world too. And since
   14.30 +no attacks can occur in the ideal world, no attacks can occur in the
   14.31 +real world as well. Such a multi-party computation (MPC) is called a
   14.32 +secure multi-party computation (SMPC).
   14.33 +
   14.34 +Security Assumptions
   14.35 +--------------------
   14.36 +
   14.37 +Please note that like all cryptographic systems, VIFF is only secure
   14.38 +as long as certain assumptions are fulfilled. These assumptions
   14.39 +include:
   14.40 +
   14.41 +- The adversary can only corrupt up to a certain threshold of the
   14.42 +  total number of players. The threshold will normally be 1/2 of the
   14.43 +  players, so for three players, at most one player may be corrupted
   14.44 +  (there must be an honest majority).
   14.45 +
   14.46 +- The adversary is computationally bounded. The protocols used by VIFF
   14.47 +  rely on certain computational hardness assumptions, and therefore
   14.48 +  only polynomial time adversaries are allowed.
   14.49 +
   14.50 +- The adversary is passive. Being passive means that the adversary
   14.51 +  only monitors the network traffic, but still follows the protocol.
   14.52 +  We plan to add support for active (Byzantine) adversaries in a
   14.53 +  future version.
   14.54 +
   14.55 +The precise assumptions for each protocol will eventually be included
   14.56 +in the documentation for the corresponding method, but this has not
   14.57 +yet been done.
   14.58 +
   14.59 +Architecture
   14.60 +------------
   14.61 +
   14.62 +VIFF consists of several modules. The :mod:`viff.runtime` module
   14.63 +contains the :class:`Runtime <viff.runtime.Runtime>` and :class:`Share
   14.64 +<viff.runtime.Share>` classes, in which the main functionality is
   14.65 +implemented. The :mod:`viff.field` module contains implementations of
   14.66 +finite fields --- these are the values inside the shares. Other
   14.67 +modules provide support functions.
   14.68 +
   14.69 +Layers
   14.70 +""""""
   14.71 +
   14.72 +The main functionality in VIFF is implemented in the :class:`Runtime
   14.73 +<viff.runtime.Runtime>` class. This class offers methods to do
   14.74 +addition, multiplication, etc. These methods operate on :class:`Share
   14.75 +<viff.runtime.Share>` instances.
   14.76 +
   14.77 +Shares hold either :class:`GFElement <viff.field.GF>` or :class:`GF256
   14.78 +<viff.field.GF256>` elements and are created from the
   14.79 +:meth:`shamir_share <viff.runtime.Runtime.shamir_share>` or
   14.80 +:meth:`prss_share <viff.runtime.Runtime.prss_share>` :class:`Runtime
   14.81 +<viff.runtime.Runtime>` methods. Shares overload the standard
   14.82 +arithmetic operators, so you can write ``a + b - c * d`` with four
   14.83 +shares, and it will be translated correctly into the appropriate
   14.84 +method calls on the :class:`Runtime <viff.runtime.Runtime>` associated
   14.85 +with the shares.
   14.86 +
   14.87 +A field element contain the concrete value on which we do
   14.88 +calculations. This is just a normal Python (long) integer. The value
   14.89 +is wrapped in an object that will keep track of doing modulo
   14.90 +reductions as appropriate.
   14.91 +
   14.92 +So in a nutshell, VIFF has these layers:
   14.93 +
   14.94 +- Top-level layer for application programs: There you manipulate
   14.95 +  Python integers or :class:`viff.runtime.Share` instances.
   14.96 +
   14.97 +- Runtime layer: The runtime deals with Python integers or shares.
   14.98 +
   14.99 +- Field elements: Deals with arithmetic over Python integers, but with
  14.100 +  modulo reductions as needed.
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/doc/program-counters.txt	Tue Apr 29 08:56:59 2008 +0200
    15.3 @@ -0,0 +1,202 @@
    15.4 +
    15.5 +.. _program-counters:
    15.6 +
    15.7 +Program Counters
    15.8 +================
    15.9 +
   15.10 +When two players execute a large computation they need to agree with
   15.11 +each other on a labelling of the individual operations so that they
   15.12 +know where each received result belongs. In VIFF we call these labels
   15.13 +*program counters*. We will try to explain the design of these
   15.14 +counters in this document and list some ideas for alternative
   15.15 +implementations.
   15.16 +
   15.17 +The basic setup in VIFF is a set of players who communicate over
   15.18 +reliable point-to-point links, e.g., TCP or SSL connections. It is
   15.19 +important to remember that these links guarantee that all transmitted
   15.20 +messages arrive unchanged at the destination and that they arrive in
   15.21 +the order sent.
   15.22 +
   15.23 +
   15.24 +The naive solution
   15.25 +------------------
   15.26 +
   15.27 +The very first version of VIFF network data was numbered in the most
   15.28 +naive way possible: using a single counter for each player. This
   15.29 +worked fine most of the time, but once in a while a test would fail to
   15.30 +give the correct result. It was only when one ran thousands of
   15.31 +multiplications that the bug appeared, but its cause was quite simple.
   15.32 +Consider a program like this where we assume that the shares *a*, *b*,
   15.33 +*c*, and *d* have already been correctly defined::
   15.34 +
   15.35 +  x = mul(a, b)
   15.36 +  y = mul(c, d)
   15.37 +
   15.38 +Back then, the :func:`mul` function was implemented like this::
   15.39 +
   15.40 +  def mul(share_a, share_b):
   15.41 +      inc_pc()
   15.42 +      result = gather_shares([share_a, share_b])
   15.43 +      result.addCallback(lambda (a, b): a * b)
   15.44 +      result.addCallback(shamir_share)
   15.45 +      result.addCallback(recombine, threshold=2*threshold)
   15.46 +      return result
   15.47 +
   15.48 +where :func:`inc_pc` took care of incrementing the global program
   15.49 +counter. This simple implementation worked 99.99% of the time with
   15.50 +three players connected on a LAN, but once in a while it would fail to
   15.51 +calculate the correct results.
   15.52 +
   15.53 +In our example program, :func:`shamir_share` is called twice: once
   15.54 +when *a* and *b* are ready, and once when *c* and *d* are ready. Most
   15.55 +of the time *a* and *b* are ready first on all players, and so they
   15.56 +all agree on the program counter value for this call to
   15.57 +:func:`shamir_share`. But when we have bad luck, they one player sees
   15.58 +*c* and *d* arrive first and so the two calls to :func:`shamir_share`
   15.59 +are switched for that player.
   15.60 +
   15.61 +The problem is the asynchronous nature of Twisted: all players agree
   15.62 +on the execution tree, but depending on the exact timing they might
   15.63 +reach the nodes in the tree in a different order. The tree looks like
   15.64 +this in our little example:
   15.65 +
   15.66 +.. code-block:: none
   15.67 +
   15.68 +     x       y
   15.69 +     |       |
   15.70 +    mul     mul
   15.71 +    / \     / \
   15.72 +   a   b   c   d
   15.73 +
   15.74 +and the two :func:`mul` can be called in either order since they do
   15.75 +not depend on each other.
   15.76 +
   15.77 +
   15.78 +The working solution
   15.79 +--------------------
   15.80 +
   15.81 +The solution used now in VIFF has two ingredients. First, callbacks
   15.82 +that depend on the program counter (like `func`:shamir_share in our
   15.83 +example above) are not added with :meth:`addCallback` but instead with
   15.84 +the special :meth:`viff.runtime.BasicRuntime.schedule_callback`
   15.85 +method. This method saves the program counter in effect at the time of
   15.86 +the its call, and ensures that the saved program counter is
   15.87 +temporarily made active when the callback is called.
   15.88 +
   15.89 +Secondly, the program counter is a *list* of counters. This is
   15.90 +necessary to ensure that we can allocate new fresh counters at any
   15.91 +point in the execution tree. The execution tree is never explicitly
   15.92 +constructed in VIFF, so a simple static numbering is not possible.
   15.93 +
   15.94 +Instead we mark methods that need to increment the program counter
   15.95 +with the :func:`viff.runtime.increment_pc` decorator. The program
   15.96 +counter starts at the value ``[0]`` and the decorated method will now
   15.97 +begin by doing::
   15.98 +
   15.99 +  self.program_counter[-1] += 1
  15.100 +  self.program_counter.append(0)
  15.101 +
  15.102 +before it executes its body. When the body is finished, the method
  15.103 +does::
  15.104 +
  15.105 +  self.program_counter.pop()
  15.106 +
  15.107 +before it returns. A method :meth:`foo` defined like this::
  15.108 +
  15.109 +  @increment_pc
  15.110 +  def foo(self):
  15.111 +      print "foo:", self.program_counter
  15.112 +
  15.113 +is thus turned into this::
  15.114 +
  15.115 +  def foo(self):
  15.116 +      self.program_counter[-1] += 1
  15.117 +      self.program_counter.append(0)
  15.118 +      print "foo:", self.program_counter
  15.119 +      self.program_counter.pop()
  15.120 +
  15.121 +and when executed starting from the initial program counter of ``[0]``
  15.122 +we see that it prints ``foo: [1, 0]`` and leaves the program counter
  15.123 +at ``[1]`` after it returns. It is very important that the program
  15.124 +counter is left changed like this, for this means that the next call
  15.125 +to :meth:`foo` will print ``foo: [2, 0]`` and increment the program
  15.126 +counter to ``[2]``.
  15.127 +
  15.128 +If we have a method :meth:`bar` which calls :meth:`foo` several times::
  15.129 +
  15.130 +  @increment_pc
  15.131 +  def bar(self):
  15.132 +      print "bar:", self.program_counter
  15.133 +      self.foo()
  15.134 +      print "bar:", self.program_counter
  15.135 +      self.foo()
  15.136 +      print "bar:", self.program_counter
  15.137 +
  15.138 +then the result of calling :meth:`bar` will be:
  15.139 +
  15.140 +.. code-block:: none
  15.141 +
  15.142 +   bar: [1, 0]
  15.143 +   foo: [1, 1, 0]
  15.144 +   bar: [1, 1]
  15.145 +   foo: [1, 2, 0]
  15.146 +   bar: [1, 2]
  15.147 +
  15.148 +Notice how each sub-call adds another digit to the counter and how it
  15.149 +increments the counter used at the level of the caller. This system
  15.150 +ensures that all program counters are unique.
  15.151 +
  15.152 +
  15.153 +Alternatives
  15.154 +------------
  15.155 +
  15.156 +We have come up with some alternative solutions, which are detailed
  15.157 +below. More good ideas are of course welcome!
  15.158 +
  15.159 +History-based labels
  15.160 +""""""""""""""""""""
  15.161 +
  15.162 +An attractive alternative is to label data sent over the net based on
  15.163 +its *history*. The idea is that we associate a label ``H(x)`` with
  15.164 +each variable *x*. The history is defined when new variables are
  15.165 +defined --- if ``x = a * b``, then we can set ``H(x) = ("mul", H(a),
  15.166 +H(b))``. To avoid growing the history without bounds we can hash it
  15.167 +with a cryptographic hash function to bring it down to a fixed size.
  15.168 +
  15.169 +The problem with this idea is that we sometimes need to assign a
  15.170 +history to a variable that depends on no other variables. An example
  15.171 +of this is the result of a call to :meth:`prss_share
  15.172 +<viff.runtime.Runtime.prss_share>` which takes no useful arguments. A
  15.173 +possible solution would be to add some dummy arguments on which the
  15.174 +history could be based, even though they wont be used by the method.
  15.175 +So if you would normally call the function :func:`hat` with no
  15.176 +arguments to get a :class:`Rabbit` object, you have to change your
  15.177 +code from this::
  15.178 +
  15.179 +  rabbit = hat()
  15.180 +
  15.181 +to this::
  15.182 +
  15.183 +  rabbit = hat(dummy=locals())
  15.184 +
  15.185 +where the call to :func:`locals` gives you access to the local
  15.186 +variables. If the use of :func:`locals` could be hidden this might be
  15.187 +an acceptable solution.
  15.188 +
  15.189 +Using the history of the variables has the big advantage that we label
  15.190 +each piece of transmitted data with just information that is relevant
  15.191 +to it: namely its position in the tree formed by the calculation and
  15.192 +*not* its position in the execution tree formed by the implementation
  15.193 +in VIFF. This is conceptually cleaner than the current solution.
  15.194 +
  15.195 +Program transformation
  15.196 +""""""""""""""""""""""
  15.197 +
  15.198 +Another idea is to solve the labelling problem by having some external
  15.199 +tool transform the program into one with explicit labels. Each send
  15.200 +and each receive operation needs to be labelled and the labels much
  15.201 +match pair-wise.
  15.202 +
  15.203 +It is not entirely clear how this should work in the presence of loops
  15.204 +and if it is possible to implement this in an easier way than the
  15.205 +current program counters.
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/doc/prss.txt	Tue Apr 29 08:56:59 2008 +0200
    16.3 @@ -0,0 +1,12 @@
    16.4 +
    16.5 +PRSS Module
    16.6 +===========
    16.7 +
    16.8 +.. automodule:: viff.prss
    16.9 +
   16.10 +   .. autoclass:: PRF
   16.11 +      :members: __call__
   16.12 +
   16.13 +   .. autofunction:: prss
   16.14 +
   16.15 +   .. autofunction:: generate_subsets
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/doc/runtime.txt	Tue Apr 29 08:56:59 2008 +0200
    17.3 @@ -0,0 +1,88 @@
    17.4 +
    17.5 +Runtime Module
    17.6 +==============
    17.7 +
    17.8 +.. automodule:: viff.runtime
    17.9 +
   17.10 +   .. autoclass:: Share
   17.11 +      :members: clone
   17.12 +
   17.13 +   .. autoclass:: ShareList
   17.14 +
   17.15 +   .. autofunction gather_shares
   17.16 +
   17.17 +   .. autoclass:: ShareExchanger
   17.18 +      :members: sendShare, sendData, loseConnection
   17.19 +
   17.20 +      .. attribute:: ShareExchanger.incoming_data
   17.21 +
   17.22 +         Data from our peer is put here, either as an empty
   17.23 +         :class:`Deferred` if we are waiting on input from the player,
   17.24 +         or the data itself if data is received from the other player
   17.25 +         before we are ready to use it.
   17.26 +
   17.27 +   .. autofunction:: increment_pc
   17.28 +
   17.29 +   .. autofunction:: create_runtime
   17.30 +
   17.31 +   .. autoclass:: BasicRuntime
   17.32 +      :members:
   17.33 +
   17.34 +      .. attribute:: BasicRuntime.id
   17.35 +
   17.36 +         Player ID. This is an integer in the range 1--*n* for *n*
   17.37 +         players.
   17.38 +
   17.39 +      .. attribute:: BasicRuntime.threshold
   17.40 +
   17.41 +         Default threshold used by :meth:`Runtime.shamir_share`,
   17.42 +         :meth:`Runtime.open`, and others.
   17.43 +
   17.44 +      .. attribute:: BasicRuntime.program_counter
   17.45 +
   17.46 +         Whenever a share is sent over the network, it must be
   17.47 +         uniquely identified so that the receiving player known what
   17.48 +         operation the share is a result of. This is done by
   17.49 +         associating a *program counter* with each operation.
   17.50 +
   17.51 +         Keeping the program counter synchronized between all players
   17.52 +         ought to be easy, but because of the asynchronous nature of
   17.53 +         network protocols, all players might not reach the same parts
   17.54 +         of the program at the same time.
   17.55 +
   17.56 +         Consider two players *A* and *B* who are both waiting on the
   17.57 +         variables *a* and *b*. Callbacks have been added to *a* and
   17.58 +         *b*, and the question is what program counter the callbacks
   17.59 +         should use when sending data out over the network.
   17.60 +
   17.61 +         Let *A* receive input for *a* and then for *b* a little
   17.62 +         later, and let *B* receive the inputs in reversed order so
   17.63 +         that the input for *b* arrives first. The goal is to keep the
   17.64 +         program counters synchronized so that program counter *x*
   17.65 +         refers to the same operation on all players. Because the
   17.66 +         inputs arrive in different order at different players,
   17.67 +         incrementing a simple global counter is not enough.
   17.68 +
   17.69 +         Instead, a *tree* is made, which follows the tree of
   17.70 +         execution. At the top level the program counter starts at
   17.71 +         ``[0]``. At the next operation it becomes ``[1]``, and so on.
   17.72 +         If a callback is scheduled (see :meth:`schedule_callback`) at
   17.73 +         program counter ``[x, y, z]``, any calls it makes will be
   17.74 +         numbered ``[x, y, z, 1]``, then ``[x, y, z, 2]``, and so on.
   17.75 +
   17.76 +         Maintaining such a tree of program counters ensures that
   17.77 +         different parts of the program execution never reuses the
   17.78 +         same program counter for different variables.
   17.79 +
   17.80 +         The :func:`increment_pc` decorator is responsible for
   17.81 +         dynamically building the tree as the execution unfolds and
   17.82 +         :meth:`schedule_callback` is responsible for scheduling
   17.83 +         callbacks with the correct program counter.
   17.84 +
   17.85 +         See :ref:`program-counters` for more background information.
   17.86 +
   17.87 +   .. autoclass:: Runtime
   17.88 +      :members:
   17.89 +
   17.90 +   .. autoclass:: ActiveRuntime
   17.91 +      :members: mul, single_share_random, double_share_random, get_triple, generate_triples, broadcast
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/doc/shamir.txt	Tue Apr 29 08:56:59 2008 +0200
    18.3 @@ -0,0 +1,6 @@
    18.4 +
    18.5 +Shamir Module
    18.6 +=============
    18.7 +
    18.8 +.. automodule:: viff.shamir
    18.9 +   :members:
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/doc/util.txt	Tue Apr 29 08:56:59 2008 +0200
    19.3 @@ -0,0 +1,27 @@
    19.4 +
    19.5 +Utility Functions Module
    19.6 +========================
    19.7 +
    19.8 +.. automodule:: viff.util
    19.9 +   :members:
   19.10 +
   19.11 +   .. envvar:: SEED
   19.12 +
   19.13 +      The :data:`rand` random generator is seeded using this
   19.14 +      environment variable, if it is defined.
   19.15 +
   19.16 +   .. data:: rand
   19.17 +
   19.18 +      All VIFF code uses this random number generator for all
   19.19 +      randomness needed.
   19.20 +
   19.21 +      The generator is by default initialized with a random seed,
   19.22 +      unless the environment variable :envvar:`SEED` is set to a
   19.23 +      value, in which case that value is used instead. If
   19.24 +      :envvar:`SEED` is defined, but empty, then no seed is used and a
   19.25 +      protocol run cannot be reproduced exactly.
   19.26 +
   19.27 +   .. envvar:: VIFF_NO_WRAP
   19.28 +
   19.29 +      Setting this environment variable to any value will turn
   19.30 +      :func:`wrapper` into a no-op.
    20.1 --- a/epydoc.conf	Mon Apr 28 20:18:55 2008 +0200
    20.2 +++ b/epydoc.conf	Tue Apr 29 08:56:59 2008 +0200
    20.3 @@ -11,3 +11,5 @@
    20.4  
    20.5  graph: classtree
    20.6  include-log: yes
    20.7 +
    20.8 +external-api: mod, func, data, const, class, exc, meth, attr, exc, file, envvar
    21.1 --- a/run.py	Mon Apr 28 20:18:55 2008 +0200
    21.2 +++ b/run.py	Tue Apr 29 08:56:59 2008 +0200
    21.3 @@ -104,18 +104,12 @@
    21.4      # Generate API docs in doc/api.
    21.5      epydoc('doc')
    21.6  
    21.7 -    # First PDFLaTeX run...
    21.8 -    execute(["pdflatex", "--interaction", "nonstopmode", "design-talk.tex"],
    21.9 -            work_dir="doc/design-talk")
   21.10 -    # Second run to update the table of contents.
   21.11 -    execute(["pdflatex", "--interaction", "nonstopmode", "design-talk.tex"],
   21.12 -            work_dir="doc/design-talk")
   21.13 -
   21.14      # Retrieve the latest version of install.txt and authors.txt from
   21.15      # the website repository, and ship them as INSTALL and AUTHORS.
   21.16      for filename in ('install.txt', 'authors.txt'):
   21.17          url = 'http://hg.viff.dk/viff.dk/raw-file/tip/%s' % filename
   21.18 -        print "Fetching %s" % url,
   21.19 +        print "Fetching %s..." % url,
   21.20 +        sys.stdout.flush()
   21.21          urlretrieve(url, filename[:-4].upper())
   21.22          print "done."
   21.23  
   21.24 @@ -132,7 +126,7 @@
   21.25      target = "%s/api" % build
   21.26      ensure_dir(target)
   21.27      execute(["epydoc", "-vv", "--config", "epydoc.conf"],
   21.28 -            {'EPYDOC': 'YES', 'target': target})
   21.29 +            {'VIFF_NO_WRAP': 'YES', 'target': target})
   21.30  
   21.31  @command('coverage', 'build')
   21.32  def coverage(build):
    22.1 --- a/viff/config.py	Mon Apr 28 20:18:55 2008 +0200
    22.2 +++ b/viff/config.py	Tue Apr 29 08:56:59 2008 +0200
    22.3 @@ -15,19 +15,21 @@
    22.4  # You should have received a copy of the GNU Lesser General Public
    22.5  # License along with VIFF. If not, see <http://www.gnu.org/licenses/>.
    22.6  
    22.7 -"""Functions for loading and saving player configurations.
    22.8 +"""Functions for loading and saving player configurations. Each player
    22.9 +participating in a protocol execution must know some information about
   22.10 +the other players, namely their hostname and port number. The player
   22.11 +also needs to know something about itself, namely the keys used for
   22.12 +pseudo-random secret sharing (PRSS).
   22.13  
   22.14 -Each player participating in a protocol execution must know some
   22.15 -information about the other players, namely their hostname and port
   22.16 -number. The player also needs to know something about itself, namely
   22.17 -the keys used for pseudo-random secret sharing (PRSS).
   22.18 +The :class:`Player` class encapsulates this information. Generating a
   22.19 +player configuration is done using the :func:`generate_configs`
   22.20 +function. The :file:`generate_config_files.py` script uses that
   22.21 +function to generate a player config and save it in a number of
   22.22 +:file:`.ini` files. Such a :file:`.ini` file can be loaded with the
   22.23 +:func:`load_config` function.
   22.24 +"""
   22.25  
   22.26 -The L{Player} class encapsulates this information. Generating a player
   22.27 -configuration is done using the L{generate_configs} function. The
   22.28 -C{apps/generate_config_files.py} script uses that function to generate
   22.29 -a player config and save it in a number of .ini files. Such a .ini
   22.30 -file can be loaded with the L{load_config} function.
   22.31 -"""
   22.32 +__docformat__ = "restructuredtext"
   22.33  
   22.34  from configobj import ConfigObj
   22.35  
   22.36 @@ -53,8 +55,8 @@
   22.37          of a pseudo-random secret sharing for sharing an element
   22.38          random to all players.
   22.39  
   22.40 -        @return: mapping from player subsets to L{PRF} instances.
   22.41 -        @returntype: L{dict} from L{frozenset} to L{PRF} instances.
   22.42 +        Return a mapping from player subsets to :class:`viff.prss.PRF`
   22.43 +        instances.
   22.44          """
   22.45          prfs = {}
   22.46          for subset, key in self.keys.iteritems():
   22.47 @@ -68,8 +70,8 @@
   22.48          The pseudo-random functions are used when this player is the
   22.49          dealer in a pseudo-random secret sharing.
   22.50  
   22.51 -        @return: mapping from player subsets to L{PRF} instances.
   22.52 -        @returntype: L{dict} from L{frozenset} to L{PRF} instances.
   22.53 +        Return a mapping from player subsets to :class:`viff.prss.PRF`
   22.54 +        instances.
   22.55          """
   22.56          dealers = {}
   22.57          for dealer, keys in self.dealer_keys.iteritems():
   22.58 @@ -95,8 +97,8 @@
   22.59      One of the players own the config file and for this player
   22.60      additional information on PRSS keys is available.
   22.61  
   22.62 -    @return: owner ID and a mapping of player IDs to players.
   22.63 -    @returntype: C{int}, C{dict} from C{int} to L{Player} instances.
   22.64 +    Returns the owner ID and a mapping of player IDs to
   22.65 +    :class:`Player` instances.
   22.66      """
   22.67  
   22.68      def s_unstr(str):
   22.69 @@ -149,16 +151,14 @@
   22.70  def generate_configs(n, t, addresses=None, prefix=None):
   22.71      """Generate player configurations.
   22.72  
   22.73 -    The configurations are returned as C{ConfigObj}s and can be saved
   22.74 -    to disk if desired.
   22.75 +    Generates *n* configuration objects with a threshold of *t*. The
   22.76 +    *addresses* is an optional list of ``(host, port)`` pairs and
   22.77 +    *prefix* is a filename prefix.
   22.78  
   22.79 -    @param n: number of players.
   22.80 -    @param t: threshold.
   22.81 -    @param addresses: list of (host, port) pairs.
   22.82 -    @param prefix: filename prefix.
   22.83 +    The configurations are returned as :class:`ConfigObj` instances
   22.84 +    and can be saved to disk if desired.
   22.85  
   22.86 -    @return: mapping from player id to player configuration.
   22.87 -    @returntype: C{dict} from C{int} to C{ConfigObj}.
   22.88 +    Returns a mapping from player ID to player configuration.
   22.89      """
   22.90      players = frozenset(range(1, n+1))
   22.91      max_unqualified_subsets = generate_subsets(players, n-t)
    23.1 --- a/viff/field.py	Mon Apr 28 20:18:55 2008 +0200
    23.2 +++ b/viff/field.py	Tue Apr 29 08:56:59 2008 +0200
    23.3 @@ -15,11 +15,10 @@
    23.4  # You should have received a copy of the GNU Lesser General Public
    23.5  # License along with VIFF. If not, see <http://www.gnu.org/licenses/>.
    23.6  
    23.7 -"""Modeling of Galois (finite) fields.
    23.8 -
    23.9 -The GF function creates classes which implements Galois (finite)
   23.10 -fields of prime order whereas the GF256 class implements the the
   23.11 -GF(2^8) field with characteristic 2.
   23.12 +"""Modeling of Galois (finite) fields. The GF function creates classes
   23.13 +which implements Galois (finite) fields of prime order whereas the
   23.14 +:class:`GF256` class implements the the GF(2^8) field with
   23.15 +characteristic 2.
   23.16  
   23.17  All fields work the same: instantiate an object from a field to get
   23.18  hold of an element of that field. Elements implement the normal
   23.19 @@ -47,7 +46,7 @@
   23.20  {12}
   23.21  
   23.22  Square roots can be found for elements based on GF fields with a Blum
   23.23 -prime modulus (see L{GF} for more information):
   23.24 +prime modulus (see :func:`GF` for more information):
   23.25  
   23.26  >>> x.sqrt()
   23.27  {3}
   23.28 @@ -62,10 +61,13 @@
   23.29      ...
   23.30  TypeError: unsupported operand type(s) for +: 'GFElement' and 'GFElement'
   23.31  
   23.32 -The reason for the slightly confusing error message is that C{x} and
   23.33 -C{z} are instances of two I{different} classes called C{GFElement}.
   23.34 +The reason for the slightly confusing error message is that ``x`` and
   23.35 +``z`` are instances of two *different* classes called ``GFElement``.
   23.36  """
   23.37  
   23.38 +__docformat__ = "restructuredtext"
   23.39 +
   23.40 +
   23.41  from gmpy import mpz
   23.42  
   23.43  
   23.44 @@ -75,15 +77,15 @@
   23.45  
   23.46  #: Logarithm table.
   23.47  #:
   23.48 -#: Maps a value M{x} to M{log3(x)}. See L{_generate_tables}.
   23.49 +#: Maps a value *x* to *log3(x)*. See `_generate_tables`.
   23.50  _log_table = {}
   23.51  #: Exponentiation table.
   23.52  #:
   23.53 -#: Maps a value M{y} to M{3^y}. See L{_generate_tables}.
   23.54 +#: Maps a value *y* to *3^y*. See `_generate_tables`.
   23.55  _exp_table = {}
   23.56  #: Inversion table.
   23.57  #:
   23.58 -#: Maps a value M{x} to M{x^-1}. See L{_generate_tables}.
   23.59 +#: Maps a value *x* to *x^-1*. See `_generate_tables`.
   23.60  _inv_table = {}
   23.61  
   23.62  
   23.63 @@ -91,10 +93,10 @@
   23.64      """Generate tables with logarithms, antilogarithms (exponentials)
   23.65      and inverses.
   23.66  
   23.67 -    This updates the L{_log_table}, L{_exp_table}, and L{_inv_table}
   23.68 -    fields. The generator used is 0x03.
   23.69 +    This updates the `_log_table`, `_exp_table`, and `_inv_table`
   23.70 +    fields. The generator used is ``0x03``.
   23.71  
   23.72 -    Code adapted from U{http://www.samiam.org/galois.html}.
   23.73 +    Code adapted from http://www.samiam.org/galois.html.
   23.74      """
   23.75      a = 1
   23.76      for c in range(255):
   23.77 @@ -164,7 +166,7 @@
   23.78      #: Subtract this and another GF256 element.
   23.79      #:
   23.80      #: Addition is its own inverse in GF(2^8) and so this is the same
   23.81 -    #: as L{__add__}.
   23.82 +    #: as `__add__`.
   23.83      __sub__ = __add__
   23.84      #: Subtract this and another GF256 element (reflected argument version).
   23.85      __rsub__ = __sub__
   23.86 @@ -209,22 +211,14 @@
   23.87          return result
   23.88  
   23.89      def __div__(self, other):
   23.90 -        """Division.
   23.91 -
   23.92 -        @param other: right-hand side.
   23.93 -        @type other: GF256 element
   23.94 -        """
   23.95 +        """Division."""
   23.96          return self * ~other
   23.97  
   23.98      __truediv__ = __div__
   23.99      __floordiv__ = __div__
  23.100  
  23.101      def __rdiv__(self, other):
  23.102 -        """Division (reflected argument version).
  23.103 -
  23.104 -        @param other: the left-hand side.
  23.105 -        @type other: integer
  23.106 -        """
  23.107 +        """Division (reflected argument version)."""
  23.108          return GF256(other) / self
  23.109  
  23.110      __rtruediv__ = __rdiv__
  23.111 @@ -237,7 +231,7 @@
  23.112      def __invert__(self):
  23.113          """Invertion.
  23.114  
  23.115 -        @raise ZeroDivisionError: if trying to inverse the zero
  23.116 +        Raises :exc:`ZeroDivisionError` if trying to inverse the zero
  23.117          element.
  23.118          """
  23.119          if self.value == 0:
    24.1 --- a/viff/matrix.py	Mon Apr 28 20:18:55 2008 +0200
    24.2 +++ b/viff/matrix.py	Tue Apr 29 08:56:59 2008 +0200
    24.3 @@ -15,14 +15,15 @@
    24.4  # You should have received a copy of the GNU Lesser General Public
    24.5  # License along with VIFF. If not, see <http://www.gnu.org/licenses/>.
    24.6  
    24.7 -"""Matrix operations.
    24.8 +"""Matrix operations. This module contains basic matrix operations as
    24.9 +well as a function to build square hyper-invertible matrices. The
   24.10 +matrix implementation provides operator overloading and works with any
   24.11 +type that acts like a number, including :class:`viff.field.GF256` and
   24.12 +:func:`viff.field.GF` elements.
   24.13 +"""
   24.14  
   24.15 -This module contains basic matrix operations as well as a function to
   24.16 -build square hyper-invertible matrices. The matrix implementation
   24.17 -provides operator overloading and works with any type that acts like a
   24.18 -number, including L{viff.field.GF256} and L{viff.field.GF} elements.
   24.19 +__docformat__ = "restructuredtext"
   24.20  
   24.21 -"""
   24.22  
   24.23  from __future__ import division
   24.24  
   24.25 @@ -31,11 +32,7 @@
   24.26      """A matrix."""
   24.27  
   24.28      def _init_zeros(self, m, n):
   24.29 -        """Initialize a new m times n matrix containing zeros.
   24.30 -
   24.31 -        @param m: The number of rows.
   24.32 -        @param n: The number of columns.
   24.33 -        """
   24.34 +        """Initialize a new zero matrix with *m* rows and *n* columns."""
   24.35          self.rows = [[0 for _ in range(n)] for _ in range(m)]
   24.36          self.m = m
   24.37          self.n = n
   24.38 @@ -43,7 +40,7 @@
   24.39      def _init_set(self, rows):
   24.40          """Initializes a matrix to contain specific values.
   24.41  
   24.42 -        @param rows: The rows of the matrix, given as a list of lists.
   24.43 +        The *rows* is a list of lists.
   24.44          """
   24.45          self.rows = rows
   24.46          self.m = len(rows)
   24.47 @@ -52,9 +49,9 @@
   24.48      def __init__(self, *args):
   24.49          """Initializates a matrix.
   24.50  
   24.51 -        @param args: Either a number m and n counting rows and columns
   24.52 -        of an all-zero matrix, or a list of lists representing the
   24.53 -        rows of the matrix.
   24.54 +        The arguments can be either a number *m* and *n* counting rows
   24.55 +        and columns of an all-zero matrix, or a list of lists
   24.56 +        representing the rows of the matrix.
   24.57          """
   24.58          if len(args) == 1:
   24.59              self._init_set(*args)
   24.60 @@ -62,7 +59,7 @@
   24.61              self._init_zeros(*args)
   24.62  
   24.63      def __setitem__(self, (i, j), value):
   24.64 -        """Allows matrix entry assignment using C{[,]}.
   24.65 +        """Allows matrix entry assignment using ``[,]``.
   24.66  
   24.67          The assignment works as follows:
   24.68  
   24.69 @@ -71,24 +68,17 @@
   24.70          >>> print M
   24.71          [[ 0 42]
   24.72           [ 0  0]]
   24.73 -
   24.74 -        param i: The entry row.
   24.75 -        param j: The entry column.
   24.76 -        param value: The value to store in the entry.
   24.77          """
   24.78          self.rows[i][j] = value
   24.79  
   24.80      def __getitem__(self, (i, j)):
   24.81 -        """Allows matrix entry access using C{[, ]}.
   24.82 +        """Allows matrix entry access using ``[, ]``.
   24.83  
   24.84          The access works as follows:
   24.85  
   24.86          >>> M = Matrix([[1, 2], [3, 4]])
   24.87          >>> print M[1,1]
   24.88          4
   24.89 -
   24.90 -        @param i: The entry row.
   24.91 -        @param j: The entry column.
   24.92          """
   24.93          return self.rows[i][j]
   24.94  
   24.95 @@ -108,9 +98,6 @@
   24.96          >>> print A + A
   24.97          [[0 2]
   24.98           [4 6]]
   24.99 -
  24.100 -        @param other: The matrix or element to add to this one.
  24.101 -        @return: The sum.
  24.102          """
  24.103          # we should check that the two matrices have the same size
  24.104          result = Matrix(self.m, self.n)
  24.105 @@ -133,9 +120,6 @@
  24.106          >>> print 10 + Matrix([[0, 1], [2, 3]])
  24.107          [[10 11]
  24.108           [12 13]]
  24.109 -
  24.110 -        @param other: The element to which the matrix will be added.
  24.111 -        @return: The sum.
  24.112          """
  24.113          result = Matrix(self.m, self.n)
  24.114          for i in range(0, self.m):
  24.115 @@ -166,9 +150,6 @@
  24.116          Traceback (most recent call last):
  24.117              ...
  24.118          ValueError: Matrix dimensions do not match for multiplication
  24.119 -
  24.120 -        @param other: The matrix or element to multiply with this one.
  24.121 -        @return: The product.
  24.122          """
  24.123  
  24.124          if not isinstance(other, Matrix):
  24.125 @@ -198,9 +179,6 @@
  24.126          >>> print 10 * Matrix([[0, 1], [2, 3]])
  24.127          [[ 0 10]
  24.128           [20 30]]
  24.129 -
  24.130 -        @param other: The element with which the matrix will be multiplied.
  24.131 -        @return: The product.
  24.132          """
  24.133          result = Matrix(self.m, self.n)
  24.134          for i in range(0, self.m):
  24.135 @@ -216,8 +194,6 @@
  24.136           [ 4  5  6  7]
  24.137           [ 8  9 10 11]
  24.138           [12 13 14 15]]
  24.139 -
  24.140 -        @return: A string representation of the matrix.
  24.141          """
  24.142          width = max([len(str(elem)) for row in self.rows for elem in row])
  24.143          output = [" ".join(["%*s" % (width, e) for e in r]) for r in self.rows]
  24.144 @@ -236,8 +212,6 @@
  24.145          [[0 3 6]
  24.146           [1 4 7]
  24.147           [2 5 8]]
  24.148 -
  24.149 -        @return: The transpose of the matrix.
  24.150          """
  24.151          result = Matrix(self.n, self.m)
  24.152          for i in range(self.m):
  24.153 @@ -247,11 +221,7 @@
  24.154          return result
  24.155  
  24.156      def determinant(mat):
  24.157 -        """Calculates the determinant of a matrix.
  24.158 -
  24.159 -        @param mat: A square matrix.
  24.160 -        @return: The determinant of the matrix.
  24.161 -        """
  24.162 +        """Calculates the determinant of a square matrix."""
  24.163          if mat.m == 1:
  24.164              return mat[0, 0]
  24.165          if mat.m == 2:
  24.166 @@ -271,7 +241,8 @@
  24.167  
  24.168  
  24.169  def hyper(n, field):
  24.170 -    """Makes a hyper-invertible square matrix.
  24.171 +    """Makes an *n* times *n* hyper-invertible square matrix.
  24.172 +    The matrix entries will belong to *field*.
  24.173  
  24.174      A hyper-invertible matrix is a matrix where every sub-matrix is
  24.175      invertible. A sub-matrix consists of an arbitrary subset of the
  24.176 @@ -287,10 +258,6 @@
  24.177      [[ {1} {44}  {3}]
  24.178       [ {3} {39}  {6}]
  24.179       [ {6} {32} {10}]]
  24.180 -
  24.181 -    @param n: The dimension of the matrix (it will be n times n).
  24.182 -    @param field: The field to use. Expected to be a Zp field.
  24.183 -    @return: A hyper-invertible square matrix.
  24.184      """
  24.185      result = Matrix(n, n)
  24.186      for i in range(0, n):
    25.1 --- a/viff/prss.py	Mon Apr 28 20:18:55 2008 +0200
    25.2 +++ b/viff/prss.py	Tue Apr 29 08:56:59 2008 +0200
    25.3 @@ -1,4 +1,4 @@
    25.4 -# Necessary because of the 'å' in 'Damgård': -*- coding: latin-1 -*-
    25.5 +# -*- coding: utf-8 -*-
    25.6  #
    25.7  # Copyright 2007, 2008 VIFF Development Team.
    25.8  #
    25.9 @@ -17,29 +17,32 @@
   25.10  # You should have received a copy of the GNU Lesser General Public
   25.11  # License along with VIFF. If not, see <http://www.gnu.org/licenses/>.
   25.12  
   25.13 -"""Methods for pseudo-random secret sharing.
   25.14 -
   25.15 -Normal Shamir sharing (see the L{shamir} module) requires secure
   25.16 -channels between the players for distributing shares. With
   25.17 -pseudo-random secret sharing one can share a secret using a single
   25.18 -broadcast instead.
   25.19 +u"""Methods for pseudo-random secret sharing. Normal Shamir sharing
   25.20 +(see the :mod:`viff.shamir` module) requires secure channels between
   25.21 +the players for distributing shares. With pseudo-random secret sharing
   25.22 +one can share a secret using a single broadcast instead.
   25.23  
   25.24  PRSS relies on each player having access to a set of previously
   25.25  distributed pseudo-random functions (PRFs) --- or rather the seeds for
   25.26 -such functions. In VIFF, such seeds are generated by the
   25.27 -L{config.generate_configs} function and the L{config.Player.prfs} and
   25.28 -L{config.Player.dealer_prfs} methods give access to the PRFs.
   25.29 +such functions. In VIFF, such seeds are generated by
   25.30 +:func:`viff.config.generate_configs`. The
   25.31 +:meth:`viff.config.Player.prfs` and
   25.32 +:meth:`viff.config.Player.dealer_prfs` methods give access to the
   25.33 +PRFs.
   25.34  
   25.35 -In this module the function L{prss} is used to calculate shares for a
   25.36 -pseudo-random number. The L{generate_subsets} is a general utility
   25.37 -method for generating subsets of a specific size.
   25.38 +In this module the function :func:`prss` is used to calculate shares
   25.39 +for a pseudo-random number. The :func:`generate_subsets` function is a
   25.40 +general utility for generating subsets of a specific size.
   25.41  
   25.42  The code is based on the paper "Share Conversion, Pseudorandom
   25.43  Secret-Sharing and Applications to Secure Computation" by Ronald
   25.44 -Cramer, Ivan Damgård, and Yuval Ishai in Proc. of TCC 2005, LNCS 3378.
   25.45 -U{Download <http://www.cs.technion.ac.il/~yuvali/pubs/CDI05.ps>}.
   25.46 +Cramer, Ivan Damgård, and Yuval Ishai in Proc. of TCC 2005, LNCS 3378.
   25.47 +`Download <http://www.cs.technion.ac.il/~yuvali/pubs/CDI05.ps>`__.
   25.48  """
   25.49  
   25.50 +__docformat__ = "restructuredtext"
   25.51 +
   25.52 +
   25.53  import sha
   25.54  from math import ceil
   25.55  from struct import pack
   25.56 @@ -53,8 +56,9 @@
   25.57  def prss(n, j, field, prfs, key):
   25.58      """Return a pseudo-random secret share for a random number.
   25.59  
   25.60 -    The share is for player j based on the pseudo-random functions
   25.61 -    given. The key is used when evaluating the PRFs.
   25.62 +    The share is for player *j* based on the pseudo-random functions
   25.63 +    given in *prfs* (a mapping from subsets of players to :class:`PRF`
   25.64 +    instances). The *key* is used when evaluating the PRFs.
   25.65  
   25.66      An example with (n,t) = (3,1) and a modulus of 31:
   25.67  
   25.68 @@ -71,12 +75,7 @@
   25.69      {18}
   25.70  
   25.71      We see that the sharing is consistent because each subset of two
   25.72 -    players will recombine their shares to {29}.
   25.73 -
   25.74 -    @param n: number of players.
   25.75 -    @param j: id of dealing player.
   25.76 -    @param field: field to use.
   25.77 -    @param prfs: mapping from subsets of players to L{PRF} instances.
   25.78 +    players will recombine their shares to ``{29}``.
   25.79      """
   25.80      result = 0
   25.81      all = frozenset(range(1, n+1))
    26.1 --- a/viff/runtime.py	Mon Apr 28 20:18:55 2008 +0200
    26.2 +++ b/viff/runtime.py	Tue Apr 29 08:56:59 2008 +0200
    26.3 @@ -1,4 +1,5 @@
    26.4 -# Necessary because of the 'å' in 'Damgård': -*- coding: latin-1 -*-
    26.5 +# -*- coding: utf-8 -*-
    26.6 +#
    26.7  # Copyright 2007, 2008 VIFF Development Team.
    26.8  #
    26.9  # This file is part of VIFF, the Virtual Ideal Functionality Framework.
   26.10 @@ -16,22 +17,22 @@
   26.11  # You should have received a copy of the GNU Lesser General Public
   26.12  # License along with VIFF. If not, see <http://www.gnu.org/licenses/>.
   26.13  
   26.14 -"""VIFF runtime.
   26.15 -
   26.16 -This is where the virtual ideal functionality is hiding! The runtime
   26.17 -is responsible for sharing inputs, handling communication, and running
   26.18 -the calculations.
   26.19 +"""VIFF runtime. This is where the virtual ideal functionality is
   26.20 +hiding! The runtime is responsible for sharing inputs, handling
   26.21 +communication, and running the calculations.
   26.22  
   26.23  Each player participating in the protocol will instantiate a
   26.24 -L{Runtime} object and use it for the calculations.
   26.25 +:class:`Runtime` object and use it for the calculations.
   26.26  
   26.27 -The Runtime returns L{Share} objects for most operations, and these
   26.28 -can be added, subtracted, and multiplied as normal thanks to
   26.29 +The Runtime returns :class:`Share` objects for most operations, and
   26.30 +these can be added, subtracted, and multiplied as normal thanks to
   26.31  overloaded arithmetic operators. The runtime will take care of
   26.32  scheduling things correctly behind the scenes.
   26.33  """
   26.34  from __future__ import division
   26.35  
   26.36 +__docformat__ = "restructuredtext"
   26.37 +
   26.38  import marshal
   26.39  from optparse import OptionParser, OptionGroup
   26.40  from math import ceil
   26.41 @@ -52,22 +53,22 @@
   26.42  class Share(Deferred):
   26.43      """A shared number.
   26.44  
   26.45 -    The L{Runtime} operates on shares, represented by this class.
   26.46 +    The :class:`Runtime` operates on shares, represented by this class.
   26.47      Shares are asynchronous in the sense that they promise to attain a
   26.48      value at some point in the future.
   26.49  
   26.50 -    Shares overload the arithmetic operations so that C{x = a + b}
   26.51 -    will create a new share C{x}, which will eventually contain the
   26.52 -    sum of C{a} and C{b}. Each share is associated with a L{Runtime}
   26.53 -    and the arithmetic operations simply call back to that runtime.
   26.54 +    Shares overload the arithmetic operations so that ``x = a + b``
   26.55 +    will create a new share *x*, which will eventually contain the
   26.56 +    sum of *a* and *b*. Each share is associated with a
   26.57 +    :class:`Runtime` and the arithmetic operations simply call back to
   26.58 +    that runtime.
   26.59      """
   26.60  
   26.61      def __init__(self, runtime, field, value=None):
   26.62          """Initialize a share.
   26.63  
   26.64 -        @param runtime: The L{Runtime} to use.
   26.65 -        @param field: The field where the value lies.
   26.66 -        @param value: The initial value of the share (if known).
   26.67 +        If an initial value is given, it will be passed to
   26.68 +        :meth:`callback` right away.
   26.69          """
   26.70          assert field is not None, "Cannot construct share without a field."
   26.71          assert callable(field), "The field is not callable, wrong argument?"
   26.72 @@ -133,8 +134,8 @@
   26.73      def clone(self):
   26.74          """Clone a share.
   26.75  
   26.76 -        Works like L{util.clone_deferred} except that it returns a new
   26.77 -        Share instead of a Deferred.
   26.78 +        Works like :meth:`util.clone_deferred` except that it returns a new
   26.79 +        :class:`Share` instead of a :class:`Deferred`.
   26.80          """
   26.81  
   26.82          def split_result(result):
   26.83 @@ -148,11 +149,12 @@
   26.84  class ShareList(Share):
   26.85      """Create a share that waits on a number of other shares.
   26.86  
   26.87 -    Roughly modelled after the Twisted C{DeferredList} class. The
   26.88 -    advantage of this class is that it is a L{Share} (not just a
   26.89 -    C{Deferred}) and that it can be made to trigger when a certain
   26.90 -    threshold of the shares are ready. This example shows how the
   26.91 -    C{pprint} callback is triggered when C{a} and C{c} are ready:
   26.92 +    Roughly modelled after the Twisted :class:`DeferredList`
   26.93 +    class. The advantage of this class is that it is a :class:`Share`
   26.94 +    (not just a :class:`Deferred`) and that it can be made to trigger
   26.95 +    when a certain threshold of the shares are ready. This example
   26.96 +    shows how the :meth:`pprint` callback is triggered when *a* and
   26.97 +    *c* are ready:
   26.98  
   26.99      >>> from pprint import pprint
  26.100      >>> from viff.field import GF256
  26.101 @@ -166,24 +168,22 @@
  26.102      >>> c.callback(20)
  26.103      [(True, 10), None, (True, 20)]
  26.104  
  26.105 -    The C{pprint} function is called with a list of pairs. The first
  26.106 +    The :meth:`pprint` function is called with a list of pairs. The first
  26.107      component of each pair is a boolean indicating if the callback or
  26.108 -    errback method was called on the corresponding L{Share}, and the
  26.109 -    second component is the value given to the callback/errback.
  26.110 +    errback method was called on the corresponding :class:`Share`, and
  26.111 +    the second component is the value given to the callback/errback.
  26.112  
  26.113      If a threshold less than the full number of shares is used, some
  26.114 -    of the pairs may be missing and C{None} is used instead. In the
  26.115 -    example above the C{b} Share arrived later than C{a} and C{c}, and
  26.116 -    so the list contains a C{None} on its place.
  26.117 +    of the pairs may be missing and :const:`None` is used instead. In
  26.118 +    the example above the *b* share arrived later than *a* and *c*,
  26.119 +    and so the list contains a :const:`None` on its place.
  26.120      """
  26.121 -
  26.122      def __init__(self, shares, threshold=None):
  26.123          """Initialize a share list.
  26.124  
  26.125 -        @param shares: non-empty list of L{Share} objects.
  26.126 -        @param threshold: number of shares to wait for. This is either
  26.127 -        a number such that C{0 < threshold <= len(shares)} or C{None}
  26.128 -        if all shares should be waited for.
  26.129 +        The list of shares must be non-empty and if a threshold is
  26.130 +        given, it must hold that ``0 < threshold <= len(shares)``. The
  26.131 +        default threshold is ``len(shares)``.
  26.132          """
  26.133          assert len(shares) > 0, "Cannot create empty ShareList"
  26.134          assert threshold is None or 0 < threshold <= len(shares), \
  26.135 @@ -213,10 +213,10 @@
  26.136  def gather_shares(shares):
  26.137      """Gather shares.
  26.138  
  26.139 -    Roughly modelled after the Twisted C{gatherResults} function. It
  26.140 -    takes a list of shares and returns a new L{Share} which will be
  26.141 -    triggered with a list of values, namely the values from the
  26.142 -    initial shares:
  26.143 +    Roughly modelled after the Twisted :meth:`gatherResults`
  26.144 +    function. It takes a list of shares and returns a new
  26.145 +    :class:`Share` which will be triggered with a list of values,
  26.146 +    namely the values from the initial shares:
  26.147  
  26.148      >>> from pprint import pprint
  26.149      >>> from viff.field import GF256
  26.150 @@ -228,9 +228,6 @@
  26.151      >>> a.callback(10)
  26.152      >>> b.callback(20)
  26.153      [10, 20]
  26.154 -
  26.155 -    @param shares: the shares.
  26.156 -    @type shares: C{list} of L{Share} objects
  26.157      """
  26.158  
  26.159      def filter_results(results):
  26.160 @@ -247,22 +244,14 @@
  26.161      Twisted protocol is one such connection. It is used to send and
  26.162      receive shares from one other player.
  26.163  
  26.164 -    The C{marshal} module is used for converting the data to bytes for
  26.165 -    the network and to convert back again to structured data.
  26.166 +    The :mod:`marshal` module is used for converting the data to bytes
  26.167 +    for the network and to convert back again to structured data.
  26.168      """
  26.169  
  26.170      def __init__(self):
  26.171          self.peer_id = None
  26.172  
  26.173          #: Data expected to be received in the future.
  26.174 -        #:
  26.175 -        #: Data from our peer is put here, either as an empty Deferred
  26.176 -        #: if we are waiting on input from the player, or the data
  26.177 -        #: itself if data is received from the other player before we
  26.178 -        #: are ready to use it.
  26.179 -        #:
  26.180 -        #: @type: C{dict} from C{(program_counter, data_type)} to
  26.181 -        #: deferred data.
  26.182          self.incoming_data = {}
  26.183  
  26.184      def connectionMade(self):
  26.185 @@ -277,11 +266,7 @@
  26.186  
  26.187          The string received is unmarshalled into the program counter,
  26.188          and a data part. The data is passed the appropriate Deferred
  26.189 -        in L{self.incoming_data}.
  26.190 -
  26.191 -        @param string: bytes from the network.
  26.192 -        @type string: C{(program_counter, data)} in
  26.193 -        marshalled form
  26.194 +        in :class:`self.incoming_data`.
  26.195          """
  26.196          if self.peer_id is None:
  26.197              # TODO: Handle ValueError if the string cannot be decoded.
  26.198 @@ -319,9 +304,6 @@
  26.199  
  26.200          The program counter and the share are marshalled and sent to
  26.201          the peer.
  26.202 -
  26.203 -        @param program_counter: the program counter associated with
  26.204 -        the share.
  26.205          """
  26.206          self.sendData(program_counter, "share", share.value)
  26.207  
  26.208 @@ -350,13 +332,11 @@
  26.209  
  26.210  
  26.211  def increment_pc(method):
  26.212 -    """Make method automatically increment the program counter.
  26.213 +    """Make *method* automatically increment the program counter.
  26.214  
  26.215 -    Adding this decorator to a L{Runtime} method will ensure that the
  26.216 -    program counter is incremented correctly when entering the method.
  26.217 -
  26.218 -    @param method: the method.
  26.219 -    @type method: a method of L{Runtime}
  26.220 +    Adding this decorator to a :class:`Runtime` method will ensure
  26.221 +    that the program counter is incremented correctly when entering
  26.222 +    the method.
  26.223      """
  26.224  
  26.225      @wrapper(method)
  26.226 @@ -374,15 +354,14 @@
  26.227      """Track calls to this method.
  26.228  
  26.229      The decorated method will be replaced with a proxy method which
  26.230 -    first tries to get the data needed from C{self._pool}, and if that
  26.231 -    fails it falls back to the original method.
  26.232 +    first tries to get the data needed from
  26.233 +    :attr:`BasicRuntime._pool`, and if that fails it falls back to the
  26.234 +    original method.
  26.235  
  26.236 -    The C{generator} method is only used to record where the data
  26.237 -    should be generated from, the method is not actually called.
  26.238 -
  26.239 -    @param generator: Use this method as the generator for
  26.240 -    pre-processed data.
  26.241 -    @type generator: C{str}
  26.242 +    The *generator* method is only used to record where the data
  26.243 +    should be generated from, the method is not actually called. This
  26.244 +    must be the name of the method (a string) and not the method
  26.245 +    itself.
  26.246      """
  26.247  
  26.248      def preprocess_decorator(method):
  26.249 @@ -447,8 +426,8 @@
  26.250          Initialized a runtime owned by the given, the threshold, and
  26.251          optionally a set of options. The runtime has no network
  26.252          connections and knows of no other players -- the
  26.253 -        L{create_runtime} function should be used instead to create a
  26.254 -        usable runtime.
  26.255 +        :func:`create_runtime` function should be used instead to
  26.256 +        create a usable runtime.
  26.257          """
  26.258          assert threshold > 0, "Must use a positive threshold."
  26.259          #: ID of this player.
  26.260 @@ -473,64 +452,23 @@
  26.261          self._needed_data = {}
  26.262  
  26.263          #: Current program counter.
  26.264 -        #:
  26.265 -        #: Whenever a share is sent over the network, it must be
  26.266 -        #: uniquely identified so that the receiving player known what
  26.267 -        #: operation the share is a result of. This is done by
  26.268 -        #: associating a X{program counter} with each operation.
  26.269 -        #:
  26.270 -        #: Keeping the program counter synchronized between all
  26.271 -        #: players ought to be easy, but because of the asynchronous
  26.272 -        #: nature of network protocols, all players might not reach
  26.273 -        #: the same parts of the program at the same time.
  26.274 -        #:
  26.275 -        #: Consider two players M{A} and M{B} who are both waiting on
  26.276 -        #: the variables C{a} and C{b}. Callbacks have been added to
  26.277 -        #: C{a} and C{b}, and the question is what program counter the
  26.278 -        #: callbacks should use when sending data out over the
  26.279 -        #: network.
  26.280 -        #:
  26.281 -        #: Let M{A} receive input for C{a} and then for C{b} a little
  26.282 -        #: later, and let M{B} receive the inputs in reversed order so
  26.283 -        #: that the input for C{b} arrives first. The goal is to keep
  26.284 -        #: the program counters synchronized so that program counter
  26.285 -        #: M{x} refers to the same operation on all players. Because
  26.286 -        #: the inputs arrive in different order at different players,
  26.287 -        #: incrementing a simple global counter is not enough.
  26.288 -        #:
  26.289 -        #: Instead, a I{tree} is made, which follows the tree of
  26.290 -        #: execution. At the top level the program counter starts at
  26.291 -        #: C{[0]}. At the next operation it becomes C{[1]}, and so on.
  26.292 -        #: If a callback is scheduled (see L{schedule_callback}) at
  26.293 -        #: program counter C{[x, y, z]}, any calls it makes will be
  26.294 -        #: numbered C{[x, y, z, 1]}, then C{[x, y, z, 2]}, and so on.
  26.295 -        #:
  26.296 -        #: Maintaining such a tree of program counters ensures that
  26.297 -        #: different parts of the program execution never reuses the
  26.298 -        #: same program counter for different variables.
  26.299 -        #:
  26.300 -        #: The L{increment_pc} decorator is responsible for
  26.301 -        #: dynamically building the tree as the execution unfolds and
  26.302 -        #: L{schedule_callback} is responsible for scheduling
  26.303 -        #: callbacks with the correct program counter.
  26.304 -        #:
  26.305 -        #: @type: C{list} of integers.
  26.306          self.program_counter = [0]
  26.307  
  26.308          #: Connections to the other players.
  26.309          #:
  26.310 -        #: @type: C{dict} from Player ID to L{ShareExchanger} objects.
  26.311 +        #: Mapping from from Player ID to :class:`ShareExchanger`
  26.312 +        #: objects.
  26.313          self.protocols = {}
  26.314  
  26.315          #: Number of known players.
  26.316          #:
  26.317 -        #: Equal to C{len(players)}, but storing it here is more
  26.318 +        #: Equal to ``len(self.players)``, but storing it here is more
  26.319          #: direct.
  26.320          self.num_players = 0
  26.321  
  26.322          #: Information on players.
  26.323          #:
  26.324 -        #: @type: C{dict} from player_id to L{Player} objects.
  26.325 +        #: Mapping from Player ID to :class:`Player` objects.
  26.326          self.players = {}
  26.327          # Add ourselves, but with no protocol since we wont be
  26.328          # communicating with ourselves.
  26.329 @@ -563,9 +501,6 @@
  26.330          """Make the runtime wait for the variables given.
  26.331  
  26.332          The runtime is shut down when all variables are calculated.
  26.333 -
  26.334 -        @param vars: variables to wait for.
  26.335 -        @type  vars: list of L{Deferred}s
  26.336          """
  26.337          dl = DeferredList(vars)
  26.338          dl.addCallback(lambda _: self.shutdown())
  26.339 @@ -581,12 +516,7 @@
  26.340          Deferred as usual.
  26.341  
  26.342          Any extra arguments are passed to the callback as with
  26.343 -        addCallback.
  26.344 -
  26.345 -        @param deferred: the Deferred.
  26.346 -        @param func: the callback.
  26.347 -        @param args: extra arguments.
  26.348 -        @param kwargs: extra keyword arguments.
  26.349 +        :meth:`addCallback`.
  26.350          """
  26.351          # TODO, http://tracker.viff.dk/issue22: When several callbacks
  26.352          # are scheduled from the same method, they all save the same
  26.353 @@ -657,25 +587,21 @@
  26.354      def preprocess(self, program):
  26.355          """Generate preprocess material.
  26.356  
  26.357 -        The C{program} specifies which methods to call and with which
  26.358 +        The *program* specifies which methods to call and with which
  26.359          arguments. The generator methods called must adhere to the
  26.360          following interface:
  26.361  
  26.362 -          - They must return a C{(int, Deferred)} tuple where the
  26.363 -            C{int} tells us how many items of pre-processed data the
  26.364 -            Deferred will yield.
  26.365 +        - They must return a ``(int, Deferred)`` tuple where the
  26.366 +          ``int`` tells us how many items of pre-processed data the
  26.367 +          :class:`Deferred` will yield.
  26.368  
  26.369 -          - The Deferred must yield a C{list} of the promissed length.
  26.370 +        - The Deferred must yield a list of the promissed length.
  26.371  
  26.372 -          - The C{list} contains the actual data. This data can be
  26.373 -            either a Deferred or a C{tuple} of Deferreds.
  26.374 +        - The list contains the actual data. This data can be either a
  26.375 +          Deferred or a tuple of Deferreds.
  26.376  
  26.377 -        The L{ActiveRuntime.generate_triples} method is an example of
  26.378 -        a method fulfilling this interface.
  26.379 -
  26.380 -        @param program: A description of the needed data.
  26.381 -        @type program: C{dict} mapping C{(str, args)} tuples to
  26.382 -        program counters
  26.383 +        The :meth:`ActiveRuntime.generate_triples` method is an
  26.384 +        example of a method fulfilling this interface.
  26.385          """
  26.386  
  26.387          def update(results, program_counters):
  26.388 @@ -723,18 +649,20 @@
  26.389  class Runtime(BasicRuntime):
  26.390      """The VIFF runtime.
  26.391  
  26.392 -    The runtime is used for sharing values (L{shamir_share} or
  26.393 -    L{prss_share}) into L{Share} object and opening such shares
  26.394 -    (L{open}) again. Calculations on shares is normally done through
  26.395 -    overloaded arithmetic operations, but it is also possible to call
  26.396 -    L{add}, L{mul}, etc. directly if one prefers.
  26.397 +    The runtime is used for sharing values (:meth:`shamir_share` or
  26.398 +    :meth:`prss_share`) into :class:`Share` object and opening such
  26.399 +    shares (:meth:`open`) again. Calculations on shares is normally
  26.400 +    done through overloaded arithmetic operations, but it is also
  26.401 +    possible to call :meth:`add`, :meth:`mul`, etc. directly if one
  26.402 +    prefers.
  26.403  
  26.404 -    Each player in the protocol uses a Runtime object. To create an
  26.405 -    instance and connect it correctly with the other players, please
  26.406 -    use the L{create_runtime} function instead of instantiating a
  26.407 -    Runtime directly. The L{create_runtime} function will take care of
  26.408 -    setting up network connections and return a Deferred which
  26.409 -    triggers with the Runtime object when it is ready.
  26.410 +    Each player in the protocol uses a :class:`Runtime` object. To
  26.411 +    create an instance and connect it correctly with the other
  26.412 +    players, please use the :func:`create_runtime` function instead of
  26.413 +    instantiating a Runtime directly. The :func:`create_runtime`
  26.414 +    function will take care of setting up network connections and
  26.415 +    return a :class:`Deferred` which triggers with the
  26.416 +    :class:`Runtime` object when it is ready.
  26.417      """
  26.418  
  26.419      def __init__(self, player, threshold, options=None):
  26.420 @@ -745,24 +673,13 @@
  26.421      def open(self, share, receivers=None, threshold=None):
  26.422          """Open a secret sharing.
  26.423  
  26.424 +        The *receivers* are the players that will eventually obtain
  26.425 +        the opened result. The default is to let everybody know the
  26.426 +        result. By default the :attr:`threshold` + 1 shares are
  26.427 +        reconstructed, but *threshold* can be used to override this.
  26.428 +
  26.429          Communication cost: every player sends one share to each
  26.430          receiving player.
  26.431 -
  26.432 -        @param share: the player's private part of the sharing to open.
  26.433 -        @type share: Share
  26.434 -
  26.435 -        @param receivers: the IDs of the players that will eventually
  26.436 -            obtain the opened result or None if all players should
  26.437 -            obtain the opened result.
  26.438 -        @type receivers: None or a C{list} of integers
  26.439 -
  26.440 -        @param threshold: the threshold used to open the sharing or None
  26.441 -            if the runtime default should be used.
  26.442 -        @type threshold: integer or None
  26.443 -
  26.444 -        @return: the result of the opened sharing if the player's ID
  26.445 -            is in C{receivers}, otherwise None.
  26.446 -        @returntype: Share or None
  26.447          """
  26.448          assert isinstance(share, Share)
  26.449          # all players receive result by default
  26.450 @@ -874,30 +791,20 @@
  26.451      @increment_pc
  26.452      def prss_share(self, inputters, field, element=None):
  26.453          """Creates pseudo-random secret sharings.
  26.454 +        
  26.455 +        This protocol creates a secret sharing for each player in the
  26.456 +        subset of players specified in *inputters*. Each inputter
  26.457 +        provides an integer. The result is a list of shares, one for
  26.458 +        each inputter.
  26.459  
  26.460 -        This protocol creates a secret sharing for each player in the
  26.461 -        subset of players specified in C{inputters}. The protocol uses the
  26.462 -        pseudo-random secret sharing technique described in the paper "Share
  26.463 -        Conversion, Pseudorandom Secret-Sharing and Applications to Secure
  26.464 -        Computation" by Ronald Cramer, Ivan Damgård, and Yuval Ishai in Proc.
  26.465 -        of TCC 2005, LNCS 3378.
  26.466 -        U{Download <http://www.cs.technion.ac.il/~yuvali/pubs/CDI05.ps>}.
  26.467 +        The protocol uses the pseudo-random secret sharing technique
  26.468 +        described in the paper "Share Conversion, Pseudorandom
  26.469 +        Secret-Sharing and Applications to Secure Computation" by
  26.470 +        Ronald Cramer, Ivan Damgård, and Yuval Ishai in Proc. of TCC
  26.471 +        2005, LNCS 3378. `Download
  26.472 +        <http://www.cs.technion.ac.il/~yuvali/pubs/CDI05.ps>`__
  26.473  
  26.474          Communication cost: Each inputter does one broadcast.
  26.475 -
  26.476 -        @param inputters: The IDs of the players that will share a secret.
  26.477 -        @type inputters: C{list} of integers
  26.478 -
  26.479 -        @param field: The field over which to share all the secrets.
  26.480 -        @type field: L{FieldElement}
  26.481 -
  26.482 -        @param element: The secret that this player shares or C{None} if this
  26.483 -            player is not in C{inputters}.
  26.484 -        @type element: int, long, or None
  26.485 -
  26.486 -        @return: A list of shares corresponding to the secrets submitted by
  26.487 -            the players in C{inputters}.
  26.488 -        @returntype: C{List} of C{Shares}
  26.489          """
  26.490          # Verifying parameters.
  26.491          if element is None:
  26.492 @@ -1008,10 +915,10 @@
  26.493  
  26.494      @increment_pc
  26.495      def shamir_share(self, inputters, field, number=None, threshold=None):
  26.496 -        """Secret share C{number} over C{field} using Shamir's method.
  26.497 +        """Secret share *number* over *field* using Shamir's method.
  26.498  
  26.499 -        The number is shared using polynomial of degree C{threshold}
  26.500 -        (defaults to L{self.threshold}). Returns a list of shares
  26.501 +        The number is shared using polynomial of degree *threshold*
  26.502 +        (defaults to :attr:`threshold`). Returns a list of shares
  26.503          unless unless there is only one inputter in which case the
  26.504          share is returned directly.
  26.505  
  26.506 @@ -1062,7 +969,7 @@
  26.507      """A runtime secure against active adversaries.
  26.508  
  26.509      This class currently inherits most of its functionality from the
  26.510 -    normal L{Runtime} class and is thus I{not} yet secure.
  26.511 +    normal :class:`Runtime` class and is thus **not** yet secure.
  26.512      """
  26.513  
  26.514      def __init__(self, player, threshold, options=None):
  26.515 @@ -1070,9 +977,9 @@
  26.516  
  26.517          #: A hyper-invertible matrix.
  26.518          #:
  26.519 -        #: It should be suitable for L{self.num_players} players, but
  26.520 +        #: It should be suitable for :attr:`num_players` players, but
  26.521          #: since we don't know the total number of players yet, we set
  26.522 -        #: it to C{None} here and update it as necessary.
  26.523 +        #: it to :const:`None` here and update it as necessary.
  26.524          self._hyper = None
  26.525          Runtime.__init__(self, player, threshold, options)
  26.526  
  26.527 @@ -1132,13 +1039,9 @@
  26.528          """Share a random secret.
  26.529  
  26.530          The guarantee is that a number of shares are made and out of
  26.531 -        those, the T that are returned by this method will be correct
  26.532 -        sharings of a random number using C{degree} as the polynomial
  26.533 -        degree.
  26.534 -
  26.535 -        @param T: The number of shares output.
  26.536 -        @param degree: The degree of the polynomial.
  26.537 -        @param field: The field over which to share the secret.
  26.538 +        those, the *T* that are returned by this method will be
  26.539 +        correct sharings of a random number using *degree* as the
  26.540 +        polynomial degree.
  26.541          """
  26.542          # TODO: Move common code between single_share and
  26.543          # double_share_random out to their own methods.
  26.544 @@ -1219,14 +1122,9 @@
  26.545          """Double-share a random secret using two polynomials.
  26.546  
  26.547          The guarantee is that a number of shares are made and out of
  26.548 -        those, the T that are returned by this method will be correct
  26.549 -        double-sharings of a random number using d1 and d2 as the
  26.550 +        those, the *T* that are returned by this method will be correct
  26.551 +        double-sharings of a random number using *d1* and *d2* as the
  26.552          polynomial degrees.
  26.553 -
  26.554 -        @param T: The number of double-shares output.
  26.555 -        @param d1: The degree of the first polynomial.
  26.556 -        @param d2: The degree of the second polynomial.
  26.557 -        @param field: The field over which to share the secret.
  26.558          """
  26.559          inputters = range(1, self.num_players + 1)
  26.560          if self._hyper is None:
  26.561 @@ -1330,13 +1228,11 @@
  26.562      def generate_triples(self, field):
  26.563          """Generate multiplication triples.
  26.564  
  26.565 -        These are random numbers M{a}, M{b}, and M{c} such that M{c =
  26.566 -        ab}. This function can be used in pre-processing.
  26.567 +        These are random numbers *a*, *b*, and *c* such that ``c =
  26.568 +        ab``. This function can be used in pre-processing.
  26.569  
  26.570 -        @return: Number of triples returned and a Deferred which will
  26.571 -        yield a C{list} of 3-tuples.
  26.572 -        @returntype: (C{int}, C{list} of Deferred C{(Share, Share,
  26.573 -        Share)})
  26.574 +        Returns a tuple with the number of triples generated and a
  26.575 +        Deferred which will yield a list of 3-tuples.
  26.576          """
  26.577          n = self.num_players
  26.578          t = self.threshold
  26.579 @@ -1374,9 +1270,6 @@
  26.580          the paper "An asynchronous [(n-1)/3]-resilient consensus
  26.581          protocol" by G. Bracha in Proc. 3rd ACM Symposium on
  26.582          Principles of Distributed Computing, 1984, pages 154-162.
  26.583 -
  26.584 -        @param sender: the sender of the broadcast message.
  26.585 -        @param message: the broadcast message, used only by the sender.
  26.586          """
  26.587  
  26.588          result = Deferred()
  26.589 @@ -1470,10 +1363,10 @@
  26.590      def broadcast(self, senders, message=None):
  26.591          """Perform one or more Bracha broadcast(s).
  26.592  
  26.593 -        The list of senders given will determine the subset of players
  26.594 +        The list of *senders* given will determine the subset of players
  26.595          who wish to broadcast a message. If this player wishes to
  26.596          broadcast, its ID must be in the list of senders and the
  26.597 -        optional message parameter must be used.
  26.598 +        optional *message* parameter must be used.
  26.599  
  26.600          If the list of senders consists only of a single sender, the
  26.601          result will be a single element, otherwise it will be a list.
  26.602 @@ -1483,10 +1376,6 @@
  26.603          the paper "An asynchronous [(n-1)/3]-resilient consensus
  26.604          protocol" by G. Bracha in Proc. 3rd ACM Symposium on
  26.605          Principles of Distributed Computing, 1984, pages 154-162.
  26.606 -
  26.607 -        @param senders: the list of senders.
  26.608 -        @param message: the broadcast message, used if this player is
  26.609 -        a sender.
  26.610          """
  26.611          assert message is None or self.id in senders
  26.612  
  26.613 @@ -1505,7 +1394,7 @@
  26.614  
  26.615  
  26.616  def create_runtime(id, players, threshold, options=None, runtime_class=Runtime):
  26.617 -    """Create a L{Runtime} and connect to the other players.
  26.618 +    """Create a :class:`Runtime` and connect to the other players.
  26.619  
  26.620      This function should be used in normal programs instead of
  26.621      instantiating the Runtime directly. This function makes sure that
    27.1 --- a/viff/shamir.py	Mon Apr 28 20:18:55 2008 +0200
    27.2 +++ b/viff/shamir.py	Tue Apr 29 08:56:59 2008 +0200
    27.3 @@ -15,11 +15,13 @@
    27.4  # You should have received a copy of the GNU Lesser General Public
    27.5  # License along with VIFF. If not, see <http://www.gnu.org/licenses/>.
    27.6  
    27.7 -"""Shamir secret sharing and recombination.
    27.8 +"""Shamir secret sharing and recombination. Based on the paper *How to
    27.9 +share a secret* by Adi Shamir in *Communications of the ACM* **22**
   27.10 +(11): 612-613.
   27.11 +"""
   27.12  
   27.13 -Based on the paper "How to share a secret" by Adi Shamir in
   27.14 -I{Communications of the ACM} B{22} (11): 612-613.
   27.15 -"""
   27.16 +__docformat__ = "restructuredtext"
   27.17 +
   27.18  
   27.19  import operator
   27.20  from viff.util import rand
   27.21 @@ -28,6 +30,10 @@
   27.22  def share(secret, threshold, num_players):
   27.23      """Shamir share secret.
   27.24  
   27.25 +    The *threshold* indicates the maximum number of shares that reveal
   27.26 +    nothing about *secret*. The return value is a list of ``(player
   27.27 +    id, share)`` pairs.
   27.28 +
   27.29      It holds that sharing and recombination cancels each other:
   27.30  
   27.31      >>> from field import GF
   27.32 @@ -41,25 +47,12 @@
   27.33      >>> share(Zp(10), 0, 5)
   27.34      [({1}, {10}), ({2}, {10}), ({3}, {10}), ({4}, {10}), ({5}, {10})]
   27.35  
   27.36 -    up to but not including C{num_players}:
   27.37 +    up to but not including *num_players*:
   27.38  
   27.39      >>> share(Zp(10), 5, 5)
   27.40      Traceback (most recent call last):
   27.41        ...
   27.42      AssertionError: Threshold out of range
   27.43 -
   27.44 -    @param secret: the secret to be shared.
   27.45 -    @type secret: a field element
   27.46 -
   27.47 -    @param threshold: maximum number of shares that reveal nothing
   27.48 -    about the secret.
   27.49 -    @type threshold: integer
   27.50 -
   27.51 -    @param num_players: number of players.
   27.52 -    @type num_players: integer
   27.53 -
   27.54 -    @return: shares, one for each player.
   27.55 -    @returntype: C{list} of (player id, share) pairs
   27.56      """
   27.57      assert threshold >= 0 and threshold < num_players, "Threshold out of range"
   27.58  
   27.59 @@ -93,19 +86,17 @@
   27.60  
   27.61  #: Cached recombination vectors.
   27.62  #:
   27.63 -#: The recombination vector used by L{recombine} depends only on the
   27.64 +#: The recombination vector used by `recombine` depends only on the
   27.65  #: recombination point and the player IDs of the shares, and so it can
   27.66  #: be cached for efficiency.
   27.67  _recombination_vectors = {}
   27.68  
   27.69  
   27.70  def recombine(shares, x_recomb=0):
   27.71 -    """Recombines list of (xi, yi) pairs.
   27.72 +    """Recombines list of ``(xi, yi)`` pairs.
   27.73  
   27.74 -    Recombination is done in the optional point M{x}.
   27.75 -
   27.76 -    @param shares: M{threshold+1} shares.
   27.77 -    @type shares: C{list} of (player id, share) pairs
   27.78 +    Shares is a list of *threshold* + 1 ``(player id, share)`` pairs.
   27.79 +    Recombination is done in the optional point *x_recomb*.
   27.80      """
   27.81      xs = [x_i for (x_i, _) in shares]
   27.82      ys = [y_i for (_, y_i) in shares]
   27.83 @@ -137,11 +128,6 @@
   27.84      True
   27.85      >>> verify_sharing(shares, 1)
   27.86      False
   27.87 -    >>>
   27.88 -
   27.89 -    @param shares: The shares to be checked.
   27.90 -    @param degree: The maximum degree of the interpolating polynomial.
   27.91 -    @return: C{True} if the sharing is correct, otherwise C{False}.
   27.92      """
   27.93      used_shares = shares[0:degree+1]
   27.94      for i in range(degree+1, len(shares)+1):
    28.1 --- a/viff/util.py	Mon Apr 28 20:18:55 2008 +0200
    28.2 +++ b/viff/util.py	Tue Apr 29 08:56:59 2008 +0200
    28.3 @@ -15,14 +15,14 @@
    28.4  # You should have received a copy of the GNU Lesser General Public
    28.5  # License along with VIFF. If not, see <http://www.gnu.org/licenses/>.
    28.6  
    28.7 -"""Miscellaneous utility functions.
    28.8 +"""Miscellaneous utility functions. This module contains various
    28.9 +utility functions used in all parts of the VIFF code. The most
   28.10 +important is the :data:`rand` random generator which is seeded with a
   28.11 +known seed each time. Using this generator for all random numbers
   28.12 +ensures that a protocol run can be reproduced at a later time.
   28.13 +"""
   28.14  
   28.15 -This module contains various utility functions used in all parts of
   28.16 -the VIFF code. The most important is the L{rand} random generator
   28.17 -which is seeded with a known seed each time. Using this generator for
   28.18 -all random numbers ensures that a protocol run can be reproduced at a
   28.19 -later time.
   28.20 -"""
   28.21 +__docformat__ = "restructuredtext"
   28.22  
   28.23  import os
   28.24  import random
   28.25 @@ -30,7 +30,7 @@
   28.26  from twisted.internet.defer import Deferred, succeed, gatherResults
   28.27  from gmpy import mpz
   28.28  
   28.29 -#: Seed for L{rand}.
   28.30 +#: Seed for :data:`rand`.
   28.31  _seed = os.environ.get('SEED')
   28.32  
   28.33  if _seed is None:
   28.34 @@ -41,8 +41,8 @@
   28.35      #: Random number generator used by all VIFF code.
   28.36      #:
   28.37      #: The generator is by default initialized with a random seed,
   28.38 -    #: unless the environment variable C{SEED} is set to a value, in
   28.39 -    #: which case that value is used instead. If C{SEED} is defined,
   28.40 +    #: unless the environment variable :envvar:`SEED` is set to a value, in
   28.41 +    #: which case that value is used instead. If :envvar:`SEED` is defined,
   28.42      #: but empty, then no seed is used and a protocol cannot be
   28.43      #: reproduced exactly.
   28.44      rand = random.Random(_seed)
   28.45 @@ -61,21 +61,19 @@
   28.46      """Decorator used for wrapper functions.
   28.47  
   28.48      It is important to use this decorator on any wrapper functions in
   28.49 -    order to ensure that they end up with correct C{__name__} and
   28.50 -    C{__doc__} attributes.
   28.51 +    order to ensure that they end up with correct :attr:`__name__` and
   28.52 +    :attr:`__doc__` attributes.
   28.53  
   28.54 -    In addition, if the environment variable C{EPYDOC} is defined,
   28.55 -    then the wrapper functions will be turned into functions that I{do
   28.56 -    not} wrap -- instead they let their argument function through
   28.57 -    unchanged. This is done so that epydoc can see the true function
   28.58 -    arguments when generating documentation. Just remember that your
   28.59 -    code will break if C{EPYDOC} is set, so it should only be used
   28.60 -    when epydoc is being run.
   28.61 -
   28.62 -    @param func: the function that will be wrapped.
   28.63 -    @type func: callable
   28.64 +    In addition, if the environment variable :envvar:`VIFF_NO_WRAP` is
   28.65 +    defined, then the wrapper functions will be turned into functions
   28.66 +    that *do not* wrap -- instead they let their argument function
   28.67 +    through unchanged. This is done so that epydoc and Sphinx can see
   28.68 +    the true function arguments when generating documentation. Just
   28.69 +    remember that your code will break if :envvar:`VIFF_NO_WRAP` is
   28.70 +    set, so it should only be used when documentation is being
   28.71 +    generated.
   28.72      """
   28.73 -    if os.environ.get('EPYDOC'):
   28.74 +    if os.environ.get('VIFF_NO_WRAP'):
   28.75          # Return a decorator which ignores the functions it is asked
   28.76          # to decorate and instead returns func:
   28.77          return lambda _: func
   28.78 @@ -168,10 +166,11 @@
   28.79      """Clone a Deferred.
   28.80  
   28.81      The returned clone will fire with the same result as the original
   28.82 -    Deferred, but will otherwise be independent.
   28.83 +    :class:`Deferred`, but will otherwise be independent.
   28.84  
   28.85 -    It is an error to call callback on the clone as it will result in
   28.86 -    an AlreadyCalledError when the original Deferred is triggered.
   28.87 +    It is an error to call :meth:`callback` on the clone as it will
   28.88 +    result in an :exc:`AlreadyCalledError` when the original
   28.89 +    :class:`Deferred` is triggered.
   28.90  
   28.91      >>> x = Deferred()
   28.92      >>> x.addCallback(lambda result: result * 10) # doctest: +ELLIPSIS