[Webfunds-commits] java/webfunds/ricardian Contract.java ContractException.java Currency.java KeyUtil.java Support.java

Ian Grigg iang@cypherpunks.ai
Mon, 4 Sep 2000 11:45:18 -0400 (AST)


iang        00/09/04 11:45:18

  Modified:    webfunds/ricardian Contract.java ContractException.java
                        Currency.java KeyUtil.java Support.java
  Log:
  Added some code to deal with issue_power or currency_power.
  (also deleted some blanks).
  currency_fraction is quite clumsy, in that it involves doubles,
  etc, so makes maths less precise.  Power solves this for all
  straight decimal contracts (the only envisaged form).  Also,
  it is now clear that every contract type will benefit from the
  power concept, so it's been put in the issue_part as well.
  Testing it out with the new Glitter contract.

Revision  Changes    Path
1.41      +34 -28    java/webfunds/ricardian/Contract.java

Index: Contract.java
===================================================================
RCS file: /home/webfunds/cvsroot/java/webfunds/ricardian/Contract.java,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -r1.40 -r1.41
--- Contract.java	2000/09/03 17:04:02	1.40
+++ Contract.java	2000/09/04 15:45:17	1.41
@@ -1,4 +1,4 @@
-/* $Id: Contract.java,v 1.40 2000/09/03 17:04:02 iang Exp $
+/* $Id: Contract.java,v 1.41 2000/09/04 15:45:17 iang Exp $
  *
  * Copyright (c) Systemics Ltd 1995-1999 on behalf of
  * the WebFunds Development Team.  All Rights Reserved.
@@ -60,7 +60,7 @@
  * Rewritten from the sox.Contract and the Perl equivalents.
  * Refer to:
  * <a href="http://www.systemics.com/docs/ricardo/issuer/contract.html">
- * http://www.systemics.com/docs/ricardo/issuer/contract.html</a> 
+ * http://www.systemics.com/docs/ricardo/issuer/contract.html</a>
  * for the specification of a contract.
  *
  * NOTE that this was erroneously part of SOX hierarchy.
@@ -97,7 +97,13 @@
     protected   String  fileName;
     protected   String  type = null;
 
+    private     int     power = 0;
+    private     boolean isPower = false;
+    public      int     getPower()        { return power; }
+    public      boolean isPower()         { return isPower; }
+    protected   void    setPower(int p)   { power = p; isPower = true; }
 
+
     protected String logfix = "     C ";
 
     /**
@@ -155,7 +161,7 @@
 
         this.fileName = fileNameFromDigest(hash);
         //logmsg("fileName = " + fileName);
-            
+
 
         this.type           = getField(SECT_ISSUE, "type");
         if (this.type == null || this.type.equals(""))
@@ -256,7 +262,7 @@
     public static final String X509_END   = END + "SIGNATURE-----";
     public static final String PGP_END    = END + "PGP SIGNATURE-----";
 
-    /**       
+    /**
      * This method prepares data to be canonically hashed:
      *
      *    + all lines end with \r\n
@@ -266,7 +272,7 @@
      * This used to be Armoury.prepareDataToSign().
      * @param data the original data
      * @return canonical data
-     */      
+     */
     public static byte[] prepareContractForCanonicalDigest(byte[] data, int v)
         throws ContractException
     {
@@ -470,8 +476,8 @@
             FileInputStream fis = new FileInputStream(contractfile2);
             contractData = new byte[fis.available()];
             fis.read(contractData);
-    
-    
+
+
             // Read localfile
             File locfile = new File(root + ".loc");
             localData = new byte[0];
@@ -481,7 +487,7 @@
                 localData = new byte[fis.available()];
                 fis.read(localData);
             }
-    
+
             // Read my file
             File myfile = new File(root + ".fuz");
             userData = new byte[0];
@@ -515,7 +521,7 @@
         else
             return name ;
     }
-        
+
 
     /**
      * Read in a contract given a URL
@@ -677,16 +683,16 @@
         s = getApplicationName();
         if (s != null && !"".equals(s))
             hush.put(s, s);
-        
+
         s = getField(type, "name");            // contract name
         if (s != null && !"".equals(s))
             hush.put(s, s);
-        
+
         String[] names = new String[hush.size()];
         Enumeration e = hush.keys();
         for (int i = 0; i < hush.size(); i++)
             names[i] = (String)e.nextElement();
-            
+
         return names ;
     }
 
@@ -712,7 +718,7 @@
 
 /////////// Signatures /////////////////////////////////////////
 
-  //  ..  ..  Get Certificates  ..  ..  ..  ..  ..  ..  ..  ..  ..  .. 
+  //  ..  ..  Get Certificates  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..
 
 
     /**
@@ -846,13 +852,13 @@
         Certificate cert = null;
 
         if (text.indexOf("-----BEGIN PGP") >= 0) {
-        
+
             // OpenPGP key
             cert = getOpenPGPCertFromString(text, name, errno, userIdTag);
 
 
         } else if (text.indexOf("-----BEGIN CERTIFICATE") >= 0) {
-        
+
             // X.509 key
             cert = getX509CertFromString(text, name, errno);
 
@@ -950,7 +956,7 @@
         return cert;
     }
 
-  //  ..  ..  Verify Contract  ..  ..  ..  ..  ..  ..  ..  ..  ..  .. 
+  //  ..  ..  Verify Contract  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..
 
     /**
      *  Verify that the contract is signed correctly by the cert.
@@ -967,7 +973,7 @@
         if (s.startsWith("-----BEGIN PGP SIGNED MESSAGE-----")) {
 
             return verifyOpenPGPSignatures();
-            
+
         } else {  // X.509 signed contract
 
             return verifyX509Signatures();
@@ -1014,7 +1020,7 @@
          *  "server-key-signing-key" for the legal contract issuer.
          */
         Certificate serverCert = getServerCert(); // getting it will check it
-        
+
         /*
          *  Verify the signature on the contract.
          */
@@ -1031,7 +1037,7 @@
         if (!contractSigned)
             throw new ContractException(ContractException.SIG_VERIFY,
                       "Contract signature failed!");
-         
+
         PGPPublicKey topLevelKey = (PGPPublicKey)topLevelCert.getPublicKey();
 
         /*
@@ -1194,7 +1200,7 @@
      * This goes into a file.fuz that is independant
      * of the external files.
      * Can only be called if saveAsFile() is called first
-     * as the object needs a file name context to save to. 
+     * as the object needs a file name context to save to.
      *
      * We probably need a setArray and set multiline as well.
      *
@@ -1402,7 +1408,7 @@
         {
             if (!isChanged(f, data))
                 return ;
-    
+
             //
             //  Need to move existing file out of the way.
             //
@@ -1459,16 +1465,16 @@
 
         // ### FIXME (edwin): Figure out a better way to check this
         if (s.startsWith("-----BEGIN PGP SIGNED MESSAGE-----")) {
-        
+
             PGPArmoury pgparmoury = new PGPArmoury(s);
             return new String(pgparmoury.getClearText());
-        
+
         } else { // X.509 signed contract
 
             return new String(Armoury.decodeData(contractData));
-        
+
         }
-        
+
     }
 
 
@@ -1519,7 +1525,7 @@
         return getName();
     }
 
-    /**  
+    /**
      *  Take a string, interpret it is a Ricardian Contract,
      *  and extract out the base - the part from the BEGIN SIG
      *  to the keys.
@@ -1538,7 +1544,7 @@
         String[] lines = IniFileReader.toLines(buf);
         int numLines = lines.length;
 System.err.println("lines " + numLines);
-     
+
         String s;
         int start = 0;
         while(start < numLines)          // skip empty
@@ -1577,7 +1583,7 @@
                  throw new ContractException(ContractException.NOT_A_CONTRACT,
                                        "Armoury failed to unsign!");
 
-            return getBase(payload); //  RECURSIVE !?! 
+            return getBase(payload); //  RECURSIVE !?!
         }
 
         /*



1.3       +4 -2      java/webfunds/ricardian/ContractException.java

Index: ContractException.java
===================================================================
RCS file: /home/webfunds/cvsroot/java/webfunds/ricardian/ContractException.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- ContractException.java	2000/08/16 18:40:48	1.2
+++ ContractException.java	2000/09/04 15:45:17	1.3
@@ -1,5 +1,5 @@
 /*
- * $Id: ContractException.java,v 1.2 2000/08/16 18:40:48 iang Exp $
+ * $Id: ContractException.java,v 1.3 2000/09/04 15:45:17 iang Exp $
  *
  * Copyright (c) Systemics Ltd 1995-1999 on behalf of
  * the WebFunds Development Team.  All Rights Reserved.
@@ -18,6 +18,7 @@
                               NO_DATA        = 3, // not enough contract data
                               MULTILINE      = 4, // multiline not terminated
                               NOT_A_CONTRACT = 5, // important fields missing
+                              FRACTION_FAIL  = 6, // power or fraction fields
 
                               KEY_TOP_LEVEL  = 10, // top level key bad
                               KEY_CONTRACT   = 11, // contract signing key bad
@@ -38,7 +39,8 @@
                               "No Data",
                               "Multi-line Field Is Not Terminated",
                               "Not A Contract",
-                                    null, null, null, null,
+                              "Fractional Component Is Unclear",
+                                    null, null, null,
 
                               "Bad Top-level Certification Key",
                               "Bad Contract Signing Key",



1.7       +25 -3     java/webfunds/ricardian/Currency.java

Index: Currency.java
===================================================================
RCS file: /home/webfunds/cvsroot/java/webfunds/ricardian/Currency.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- Currency.java	2000/06/05 00:51:24	1.6
+++ Currency.java	2000/09/04 15:45:17	1.7
@@ -1,5 +1,5 @@
 /*
- * $Id: Currency.java,v 1.6 2000/06/05 00:51:24 iang Exp $
+ * $Id: Currency.java,v 1.7 2000/09/04 15:45:17 iang Exp $
  *
  * Copyright (c) Systemics Ltd 1995-1999 on behalf of
  * the WebFunds Development Team.  All Rights Reserved.
@@ -16,8 +16,30 @@
         throws ContractException
     {
         super(contractD, localD, userD);
-        String s = getField("currency", "factor");
-        this.factor = new Double(s).doubleValue();
+        String s;
+        s = getField("issue", "power");
+        if (s == null || s.length() == 0)
+            s = getField("currency", "power");
+
+        if (s != null && s.length() > 0)
+        {
+System.err.println("got new power: " + s);
+            int p = Support.powerInt(s);
+System.err.println("set new power: " + p);
+            setPower(p);
+            this.factor = Support.power2factorDouble(p);
+        }
+        else
+        {
+            s = getField("currency", "factor");
+            this.factor = Support.factorDouble(s);
+            try {
+                int p = Support.factor2powerInt(this.factor);
+                setPower(p);
+            } catch (ContractException ex) {
+System.err.println("not a power: " + ex);
+            }
+        }
     }
 
     protected final double factor;



1.8       +22 -22    java/webfunds/ricardian/KeyUtil.java

Index: KeyUtil.java
===================================================================
RCS file: /home/webfunds/cvsroot/java/webfunds/ricardian/KeyUtil.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- KeyUtil.java	2000/08/28 14:42:56	1.7
+++ KeyUtil.java	2000/09/04 15:45:17	1.8
@@ -1,7 +1,7 @@
 /*
- * $Id: KeyUtil.java,v 1.7 2000/08/28 14:42:56 edwin Exp $
+ * $Id: KeyUtil.java,v 1.8 2000/09/04 15:45:17 iang Exp $
  *
- * Copyright (c) 2000 Systemics Inc on behalf of 
+ * Copyright (c) 2000 Systemics Inc on behalf of
  * the WebFunds Development Team.  All Rights Reserved.
  */
 
@@ -44,7 +44,7 @@
             throw new ArmouredKeyException(ArmouredKeyException.ISA_SECRET);
         return (PGPPublicKey)key;
     }
-        
+
     public static PGPSecretKey secretKeyFromString(String s)
         throws ArmouredKeyException
     {
@@ -53,23 +53,23 @@
             throw new ArmouredKeyException(ArmouredKeyException.ISA_PUBLIC);
         return (PGPSecretKey)key;
     }
-        
+
     static final String PUBLIC_KEY_BLOCK = "PGP PUBLIC KEY BLOCK";
     static final String SECRET_KEY_BLOCK = "PGP PRIVATE KEY BLOCK";
-            
+
     public static String secretKeyToString(PGPSecretKey sk)
     {
         PGPArmoury armouredKey = new PGPArmoury(sk.getEncoded(),
                                          SECRET_KEY_BLOCK);
         return armouredKey.toString();
     }
-        
+
     public static String publicKeyToString(PGPPublicKey pk)
     {
         PGPArmoury armouredKey = new PGPArmoury(pk.getEncoded(),
                                          PUBLIC_KEY_BLOCK);
-        return armouredKey.toString();   
-       
+        return armouredKey.toString();
+
     }
 
     /**
@@ -92,7 +92,7 @@
             throw new ArmouredKeyException(ArmouredKeyException.NOT_ARMOURED,
                                    iae.getMessage());
         }
-   
+
         // get the unarmoured key
         PGPKeyFactory factory = new PGPKeyFactory();
         Vector keys;
@@ -125,10 +125,10 @@
                                           PGPPublicKey signer)
         throws StripKeyException, ArmouredKeyException
     {
-       
+
         PGPPublicKey pk = publicKeyFromString(armouredKey);
         // check that the signer has signed
-     
+
         return KeyUtil.stripAndVerifyKey(pk, tag, signer);
     }
 
@@ -137,8 +137,8 @@
 
     /**
      * Strip the given key of all superfluous data. The key being returned
-     * will have at most one userId (containing the string userIdTag) which 
-     * is both self-signed and (optionally) signed by 'userIdSigner' (if 
+     * will have at most one userId (containing the string userIdTag) which
+     * is both self-signed and (optionally) signed by 'userIdSigner' (if
      * 'userIdSigner' != null).
      *
      * @throws IllegalArgumentException
@@ -150,8 +150,8 @@
      *         multiple sigs by userIdSigner (dunno if that's possible) or has
      *         multiple matching userIds.  See the number in StripKeyException.
      */
-    public static PGPPublicKey 
-    stripAndVerifyKey(PGPPublicKey key, 
+    public static PGPPublicKey
+    stripAndVerifyKey(PGPPublicKey key,
                       String userIdTag, PGPPublicKey userIdSigner)
     throws StripKeyException
     {
@@ -167,7 +167,7 @@
 
             // find the userId we want
             PGPUserID uid = findUserId(key, userIdTag);
-            if (uid == null) 
+            if (uid == null)
                 throw new StripKeyException(StripKeyException.NO_SUCH_USERID,
                     "UserId with tag (" + userIdTag + ") doesn't exist.");
 
@@ -225,11 +225,11 @@
      * Verify that the given key is valid. Valid is defined as "stripAndVerify
      * will not throw StripKeyException".
      */
-    public static boolean 
+    public static boolean
     verifyKey(PGPPublicKey key, String userIdTag, PGPPublicKey userIdSigner) {
 
         try {
-        
+
             if( key==null || userIdTag==null )
                 throw new IllegalArgumentException();
 
@@ -261,11 +261,11 @@
             stripAndVerifyKey(key, userIdTag, userIdSigner);
 
             return true;
-            
+
         } catch (StripKeyException e) {
-        
+
             return false;
-            
+
         }
 
     }
@@ -284,7 +284,7 @@
             PGPUserID uid = (PGPUserID)uids.elementAt(i);
             String s = uid.getValue();
             if( isMatch(s, userIdTag) ) {
-                if (res!=null) 
+                if (res!=null)
                     throw new StripKeyException(
                               StripKeyException.TOO_MANY_USERID,
                               "Multiple matching userIds found.");



1.3       +173 -3    java/webfunds/ricardian/Support.java

Index: Support.java
===================================================================
RCS file: /home/webfunds/cvsroot/java/webfunds/ricardian/Support.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- Support.java	1999/11/27 15:58:42	1.2
+++ Support.java	2000/09/04 15:45:18	1.3
@@ -1,5 +1,5 @@
 /*
- * $Id: Support.java,v 1.2 1999/11/27 15:58:42 iang Exp $
+ * $Id: Support.java,v 1.3 2000/09/04 15:45:18 iang Exp $
  *
  * Copyright (c) Systemics Ltd 1995-1999 on behalf of
  * the WebFunds Development Team.  All Rights Reserved.
@@ -66,10 +66,180 @@
     }
 
 
+    /**
+     *  @return double value found in String
+     *  @except ContractException interpreted as factor
+     */
+    static double factorDouble(String s)
+        throws ContractException
+    {
+        double factor;
+        try {
+             factor = new Double(s).doubleValue();
+        } catch (Exception ex) {
+            throw new ContractException(ContractException.FRACTION_FAIL,    
+                                        "factor <<" + s + ">> is not numeric");
+        }
+        return factor;
+    }
+
+    /**
+     *  @return int value found in String
+     *  @except ContractException interpreted as power
+     */
+    static int powerInt(String s)
+        throws ContractException
+    {
+        int p;
+        try {
+             p = new Integer(s).intValue();
+        } catch (Exception ex) {
+            throw new ContractException(ContractException.FRACTION_FAIL,    
+                                        "power <<" + s + ">> is not numeric");
+        }
+        return p;
+    }
+
+    /**
+     *  @return factor value represented by power
+     *  @except ContractException if the power is too large
+     */
+    static double power2factorDouble(int p)
+        throws ContractException
+    {
+        String fr = power2factorString(p);
+        return factorDouble(fr);
+    }
+
+    /**
+     *  @return factor value represented by power, as String
+     *  @except ContractException if the power is too large
+     */
+    static String power2factorString(int p)
+        throws ContractException
+    {
+
+        if (! (-10 <= p && p <= 10) )
+             throw new ContractException(ContractException.FRACTION_FAIL,
+                                        "power is too big! " + p);
+
+        String fr;
+        if (p == 0)
+            fr = "1";
+        else if (p < 0)
+        {
+            fr = "1";
+            while (p != 0)
+            {
+                 p++;
+                 fr += "0";
+            }
+        }
+        else // if (p > 0)
+        {
+            fr = "0.";
+            while (--p > 0)
+            {
+                 fr += "0";
+            }
+            fr += "1";
+        }
+
+        return fr;
+    }
+
+
+    /**
+     *  @return true if the double is close enough to one
+     */
+    static boolean equalsOne(double d)
+    {
+        return ((0.99999 <= d) && (d <= 1.00001));
+    }
+
+
+    /**
+     *  Turn the factor into a power.
+     *  Some factors (e.g. 0.5) are not powers, so you have to
+     *  catch the exception and deal with it.
+     *
+     *  @return power represented by this factor
+     *  @except ContractException if not a power (not multiple of 1)
+     */
+    static int factor2powerInt(double d)
+        throws ContractException
+    {
+
+        String e = "double " + d + " is not a power!";
+
+        int power;
+        if (equalsOne(d))
+            power = 0;
+        else if (d < 1)
+        {
+            power = 0;
+            while (! equalsOne(d))
+            {
+                 d *= 10;
+                 if (d > 1 && !equalsOne(d))
+                     throw new ContractException(
+                                        ContractException.FRACTION_FAIL,
+                                        e);
+                 power += 1;
+            }
+        }
+        else // if (d > 1)
+        {
+            power = 0;
+            while (! equalsOne(d))
+            {
+                 d /= 10;
+                 if (d < 1 && !equalsOne(d))
+                     throw new ContractException(
+                                        ContractException.FRACTION_FAIL,
+                                        e);
+                 power -= 1;
+            }
+        }
+        return power;
+    }
+
+    /**
+     *  Some factors (e.g. 0.5) are not powers, so you have to
+     *  catch the exception and deal with it.
+     *
+     *  @return power represented by this factor, as String
+     *  @except ContractException if not a power (not multiple of 1)
+     */
+    static String factor2powerString(double d)
+        throws ContractException
+    {
+        int p = factor2powerInt(d);
+        return p + "";
+    }
+
+
 
-/*
     public static void main(String[] args)
+        throws ContractException
     {
+        int ints[] = { 0, 1, -1, 2, -2, 10, -10 };
+        for (int i = 0; i < ints.length; i++)
+        {
+            int test = ints[i];
+            System.err.println(i + ": " + test);
+            String s = power2factorString(test);
+            System.err.println("   factor string " + s);
+            double d = power2factorDouble(test);
+            System.err.println("   factor double " + d);
+
+            int p = factor2powerInt(d);
+            System.err.println("   power int     " + p);
+            s = factor2powerString(d);
+            System.err.println("   power string  " + s);
+
+            if (p != test)
+                throw new RuntimeException("test == " + test + "   p == " + p);
+        }
     }
-*/
 }