Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Branch: master
Fetching contributors…

Cannot retrieve contributors at this time

220 lines (176 sloc) 6.258 kB
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Readme</title>
<link href="./elib1.css" rel="stylesheet">
<script src="../../include/jquery-1.3.2.min.js" type="text/javascript"></script>
</head>
<body><chap>
<h1 class="title">Versions</h1>
<p>Suppose we have several versions of the <i>same</i> module (for
example the <c>lists</c> module) throughout the lifetime of Erlang
the lists module has been changed many times - suppoe it was
important to know <i>exactyl which version of lists we mean</i> when
talking about the lists module?</p>
<h1>Problems with names</h1>
<dl>
<dt>The Name collision problem</dt>
<dd>
<p>How can we make sure that moudle names don't collide? In
Erlang module names must be unique. Ho can two independentally
developed program guyarantee that the modukles names they use
don't collide?</p>
</dd>
<dt>The Authentication Problem</dt>
<dd>
<p>How can we be sure that <c>bing.erl</c> was written by
<c>Alice</c>?. We trust the code written by Alice, how can we
be sure that nobody else has tampered with <c>bing.erl</c>?</p>
</dd>
<dt>
The Testing Problem
</dt>
<dd>
<p>On some date we tested some partticular collection of modules
and something went wrong. We want to report a bug. How can we
make sure that we can precisely identifcy exactly whhich modue
were used so that the bug can be reproduced?</p>
</dd>
</dl>
<h1>Module Version and Authentication Tagging</h1>
<p>We propose some new annotations what can be used to precisely identify
a moduke and its prove authorship of the module.</p>
<p>We'll start with an example. Alice starts by writing the module <c>foo</c>
Her first version of the module looks like this:</p>
<pre>
-module(foo).
-export([a/1]).
%% Version$author:Alice$
%% Version$end$
a(X) -&gt;
Y = lists:reverse(X),
foo:baz(Y).
</pre>
<p>Alice tests her program and wishes to publish the program. She
gives the shell command <c>publish</c>. This modifies foo.erl as
follows:</p>
<pre>
-module(foo).
-export([a/1]).
%% Version$author:Alice$
%% Do not edit the Version Block By Hand
-version(lists,"a23545f1acd365231626217365bcad2").
-version(foo, "a23545f1acd365231626217365bcad2").
-version(foo, "623547254726547254725472574527").
-author(foo,alice,"1625371537136512436143654").
%% Version$end$
a(X) -&gt;
Y = lists:reverse(X),
foo:baz(Y).
</pre>
<p>
The annotatiion <c>version(Mod, C)</c> means that <i>The module</i>
<c>M</c> <i>that Alice has tested foo has MD5 checksum</i> <c>C</c>.
<c>-author(foo,alice,S)</c> provides a proof that Alice has written
foo. <c>S</c> is the checksum of <c>foo</c> signed with Alices
public key.
</p>
<p>When this module is now compiled the compiler will compile the
code as if Aliuce had written:</p>
<pre>
-module(foo).
-export([a/1]).
a(X) -&gt;
Y = 'a23545f1acd365231626217365bcad2':reverse(X),
'623547254726547254725472574527':baz(Y).
</pre>
<p>And instead of producing <c>foo.beam</c> the compler will prodiuce
a file called:<c>XXX.beam</c></p>
<h1>The name transformation</h1>
<h2>Step 1 - creating a name map</h2>
<p>The first stup is to create a “name map” of all the files in the
current directory:</p>
<pre>
&gt; elib1_publish:publish().
[elib1_lin,elib1_rsa,io_lib_pretty,filelib]
</pre>
<p>This lists the files which have been added to the name map. The
name map is stored in a file called <c>nmape.erl</c>. The first few lines of this
file look like this:</p>
<pre>
-module(nmap).
%% autogenerated do not edit by hand.
-export([map/0]).
map()-&gt;
[{elib1_lin,"elib1_lin.erl","joe",
mBA4EEB84C7300F1E41DBA739A5B6B5CD,
5006509289449511917694936...},
{elib1_publish,"elib1_publish.erl","joe",
m82025D6B593F591DCA2C22A7B43DB6EC,
63646454995546639274897433290083170...},
...
].
</pre>
<p>the name mape is a list of <c>{Mod, File, Who, Md5, Certificate}</c>
tuples, where:</p>
<dl>
<dt>Mod</dt>
<dd><p>Is a module name</p></dd>
<dt>File</dt>
<dd><p>Is the file name of the file containing the module</p></dd>
<dt>Who</dt>
<dd><p>Is the name of the person signig the module</p></dd>
<dt>Md5</dt>
<dd><p>Is an atom containing an imbedded MD5 checkum of the
contents of <c>File</c></p></dd>
<dt>Certificate</dt>
<dd><p>Is the RSA digital signature of
the Md5 checksum signed with <c>Who</c>'s private key.</p></dd>
</dl>
<h2>Step two - compileing with the name map</h2>
<pre>
&gt; elib1_publish:compile().
creating:"mBA4EEB84C7300F1E41DBA739A5B6B5CD.beam"
creating:"m82025D6B593F591DCA2C22A7B43DB6EC.beam"
creating:"m79D5C6A6F882B11991744F7B2606CA64.beam"
creating:"m446C085CB7758C195CF3CF95B16C9DB0.beam"
creating:"m07A010C6CA0E9A4140EBA235E724F77A.beam"
</pre>
<p>Once we have a name map we can transform all the erlang in the
current directory into an equivalent set of modules <i>where all the
module names have bee replaced by the MD5 sums of the content of the
original source code files containing the modules.</i></p>
<p>Everythjing remains consistent, providing we can call
</p>
<p>This means that the md5 checksum of x1.erl is m273 .... and 2135... is
the MD5 sum signed
with joe's public key</p>
<p>transform all code in x1.erl x2.erl replacing the module names x1,
x2 ... etc.
with the MD5 sums so x1:abc(...) becomes m273...:abc( ...)
</p>
<p>replace apply(M,F,A) with newapply(map(),M, F, A)</p>
<pre>
result - a) no name space collisions
b) exact version control
c) safety (if you can't guess the MD5 sum :-)
</pre>
<p>It's kind of like adding a big "where" clause round a module</p>
<pre>
-module(foo).
a() -&gt; lists:reverse(...)
WHERE
foo = m1283abcd ...
lists = m34aefg ...
</pre>
<p>ie all modules names are converted to the MD5 sums of the original sources.
</p>
<p>This is used to solve a lot of problems with safety, versioning,
testing, namespaces etc.</p>
<p>
(safe erlang can be made by replacing calls to dangerous mods like file etc.
with safe_file ... etc.)
</p>
</chap></body>
</html>
Jump to Line
Something went wrong with that request. Please try again.