Changeset 338 for trunk

Show
Ignore:
Timestamp:
06/18/11 18:23:42 (1 year ago)
Author:
ocjhb
Message:

Cleaning up files and documentation; Changes to documentation.py to allow full dump of messages; Updated wallet to handle double spend better

Location:
trunk/sandbox/jhb/oc2
Files:
3 added
6 modified
9 moved

Legend:

Unmodified
Added
Removed
  • trunk/sandbox/jhb/oc2/README

    r310 r338  
    1 (c) 2009 Joerg Baach, License: GPL V3 
     1(c) 2009 Joerg Baach, License: GPL 
     2 
     3Please check out svn.opencoin.org/svn/opencoin/trunk/sandbox/jhb/simplejson 
     4either into this directory or symlink it into this directory (oc2).  
     5 
     6Most documentation is in documentation.py, but also have a look into docs. 
     7 
     8IMPORTANT: the whole crypto implementation was done to have a pure python 
     9version suitable for Nokia phones. Its only purpose is to demo the feasibiltiy 
     10 
     11                      !!! DON'T USE FOR PRODUCTION !!! 
     12 
     13 
     14                       
     15 
     16 
     17 
     18 
  • trunk/sandbox/jhb/oc2/demoissuer.py

    r320 r338  
     1"""run this file to run an issuer. If required, it will setup a currency""" 
     2 
     3### minmal config ### 
     4 
     5#where can this server be reached? 
     6baseurl = 'http://192.168.2.101' 
     7#what port to run on? 
     8port = 9090 
     9 
     10### nothing to config below this ### 
     11 
    112import BaseHTTPServer 
    213import issuer, mint,authorizer,storage 
    314from testserver import Handler 
    4  
    5  
    6  
    7  
    8  
    9  
    10 port = 9090 
    1115 
    1216issuerstorage = storage.Storage().setFilename('data/issuerstorage.bin').restore() 
     
    2428    print 'issuer: setup currency discription' 
    2529    denominations=[1,2,5,10,20,50,100,200,500,1000,2000,5000,10000,20000,50000,100000,200000,500000] 
    26     cdd = issuer.makeCDD('TestCent','tc',[str(d) for d in denominations],'http://192.168.2.101:%s/' % port,'') 
     30    cdd = issuer.makeCDD('TestCent','tc',[str(d) for d in denominations],'%s:%s/' % (baseurl,port),'') 
    2731    mint.setCDD(cdd) 
    2832     
  • trunk/sandbox/jhb/oc2/doc/README.txt

    r335 r338  
    11The sequence diagrams are made with http://sdedit.sourceforge.net/index.html 
     2 
     3Please check the doctests in documentation.py one level up. 
  • trunk/sandbox/jhb/oc2/documentation.py

    r337 r338  
    11""" 
     2This is documentation (and doctest) file. It shows how the API is used, and  
     3how the system is supposed to work. 
     4 
     5Please have a look at doc/message_dump.txt, or turn on the transports.printmessages 
     6below, and generate the output for yourself. The section headers in the output 
     7are generated by the 'printSection' commands in this file. 
     8 
     9 
     10>>> import transports 
     11>>> from transports import DirectTransport as DT 
     12>>> from transports import printSection 
     13 
     14toggle printing of the messages 
     15>>> transports.printmessages = 0 
     16 
     17 
    218 
    319############################################################################### 
     
    3349 
    3450 
     51>>> import storage 
    3552 
    3653Wallet fetches cdd from issuer 
    3754 
    38 >>> #faked request 
     55>>> printSection('Basic Setup') 
     56 
     57we could use the method directly 
    3958>>> from wallet import Wallet 
    40 >>> wallet = Wallet({}) 
     59>>> wallet = Wallet(storage.EmptyStorage()) 
    4160>>> cdd == wallet.askLatestCDD(issuer.giveLatestCDD) 
    4261True 
    4362 
    44 >>> #using http 
    45 >>> import transports 
    46 >>> import testserver 
     63but its better to use more real transports 
     64>>> import testutils 
    4765>>> transport = transports.HTTPTransport('http://localhost:%s/' % port) 
    48 >>> testserver.run_once(port,issuer) 
     66>>> testutils.run_once(port,issuer) 
    4967>>> cdd2 = wallet.askLatestCDD(transport) 
    5068>>> cdd2.toString(True) == cdd.toString(True) 
     
    5674Wallet: fetches current public minting keys for denomination 
    5775 
    58 >>> testserver.run_once(port,issuer) 
     76 
     77>>> printSection('Prepare Blinds') 
     78 
     79>>> testutils.run_once(port,issuer) 
    5980>>> mkcs = wallet.fetchMintKeys(transport,cdd,denominations=['1','5']) 
    6081>>> mkcs[0].toString() == issuer.getCurrentMKCs()['1'].toString() 
     
    83104 
    84105We first need to setup an authorizer, to (surpise) authorize the request. Nils says 
    85 the mint should more or less just mint 
     106the mint should just mint 
    86107 
    87108>>> from authorizer import Authorizer 
     
    93114Lets have the authorizer denying the request 
    94115 
     116>>> printSection('Blinding I') 
     117 
    95118>>> authorizer.deny = True 
    96 >>> testserver.run_once(port,issuer=issuer,mint=mint,authorizer=authorizer) 
     119>>> testutils.run_once(port,issuer=issuer,mint=mint,authorizer=authorizer) 
    97120>>> wallet.requestTransfer(transport,tid,'foo',[[mkc.keyId,blind]],[]).header 
    98121'TransferReject' 
     
    100123Now have a well working one 
    101124 
     125>>> printSection('Blinding II') 
     126 
    102127>>> authorizer.deny = False 
    103 >>> testserver.run_once(port,issuer=issuer,mint=mint,authorizer=authorizer) 
     128>>> testutils.run_once(port,issuer=issuer,mint=mint,authorizer=authorizer) 
    104129>>> response = wallet.requestTransfer(transport,tid,'foo',[[mkc.keyId,blind]],[]) 
    105130>>> response.header 
     
    121146The mint can also be a bit slow 
    122147 
     148>>> printSection('Delay I') 
     149 
    123150>>> mint.delay = True 
    124 >>> testserver.run_once(port,issuer=issuer,mint=mint,authorizer=authorizer) 
     151>>> testutils.run_once(port,issuer=issuer,mint=mint,authorizer=authorizer) 
    125152>>> wallet.requestTransfer(transport,tid,'foo',[[mkc.keyId,blind]],[]).header 
    126153'TransferDelay' 
     
    130157Or the issuer is slow 
    131158 
     159>>> printSection('Delay II') 
     160 
    132161>>> issuer.delay = True 
    133 >>> testserver.run_once(port,issuer=issuer) 
     162>>> testutils.run_once(port,issuer=issuer) 
    134163>>> wallet.resumeTransfer(transport,tid).header 
    135164'TransferDelay' 
     
    138167So we need to resume 
    139168 
    140 >>> testserver.run_once(port,issuer=issuer) 
     169>>> printSection('Resume') 
     170 
     171>>> testutils.run_once(port,issuer=issuer) 
    141172>>> wallet.resumeTransfer(transport,tid).header 
    142173'TransferAccept' 
     
    156187a sum, and bob dedices if he wants to accept it 
    157188 
     189>>> printSection('W2W: Announce') 
    158190>>> alice = wallet 
    159 >>> bobport = 9091 
    160 >>> bob = Wallet({}) 
    161 >>> import test 
     191>>> bob = Wallet(storage.EmptyStorage()) 
    162192>>> bob.approval = "I don't like odd sums" 
    163193>>> alicetid = alice.makeSerial() 
    164 >>> alice.announceSum(bob.listenSum, alicetid, 5, 'foobar')  
     194>>> alice.announceSum(DT(bob.listenSum), alicetid, 5, 'foobar')  
    165195"I don't like odd sums" 
    166196 
    167197>>> bob.approval = True 
    168 >>> alice.announceSum(bob.listenSum, alicetid, 5, 'foobar')  
     198>>> alice.announceSum(DT(bob.listenSum), alicetid, 5, 'foobar')  
    169199True 
    170200 
     
    173203serial and signature) 
    174204 
     205For testing this we need to have a special transport that actually  
     206allows the two consecutive requests that bob needs to make 
     207 
     208>>> tht = transports.TestingHTTPTransport(port,issuer=issuer,mint=mint) 
     209 
     210>>> printSection('W2W: Rejected I') 
     211 
    175212Lets have first a wrong transactionId 
    176 >>> #transport = transports.YieldTransport(bob.run,[]) 
    177 >>> alice.requestSpend(bob.listenSpend,'foobar',[coin]) 
     213>>> alice.requestSpend(DT(bob.listenSpend,tht),'foobar',[coin]) 
    178214Traceback (most recent call last): 
    179215    .... 
     
    182218Or lets try to send a wrong amount 
    183219 
    184 >>> alice.announceSum(bob.listenSum, alicetid, 5, 'foobar') 
    185 True 
    186 >>> alice.requestSpend(bob.listenSpend,alicetid,[]) 
     220>>> printSection('W2W: Rejected II') 
     221>>> alice.announceSum(DT(bob.listenSum), alicetid, 5, 'foobar') 
     222True 
     223>>> alice.requestSpend(DT(bob.listenSpend,tht),alicetid,[]) 
    187224Traceback (most recent call last): 
    188225    .... 
    189226SpendReject: amount of coins does not match announced one. Announced: 5, got 0 
    190227 
    191  
    192 >>> alice.announceSum(bob.listenSum, alicetid, 5, 'foobar') 
    193 True 
    194 >>> alice.requestSpend(bob.listenSpend, alicetid, [coin])  
    195 True 
    196  
    197  
    198  
    199 ############################################################################### 
    200 Now, lets first pretend we are on Bobs side. Fix that later, but assume we  
    201 received the coins, we know what cdd and mkc to use. We need to exchange now 
    202  
    203 >>> coins = [coin] 
    204 >>> key = mkc.publicKey 
    205 >>> bobblank = bob._makeBlank(cdd,mkc) 
    206 >>> bobsecret, bobblind = key.blindBlank(bobblank) 
    207 >>> blinds = [[mkc.keyId,bobblind]] 
     228And now, finally 
     229 
     230>>> printSection('W2W: Success') 
     231>>> alice.announceSum(DT(bob.listenSum), alicetid, 5, 'foobar') 
     232True 
     233>>> alice.requestSpend(DT(bob.listenSpend,tht), alicetid, [coin])  
     234True 
     235 
     236That was so fun, lets do it again 
     237 
     238>>> printSection('W2W: Double Spend') 
     239>>> alicetid = alice.makeSerial() 
     240>>> bob.approval = True 
     241>>> alice.announceSum(DT(bob.listenSum), alicetid, 5, 'foobar') 
     242True 
     243>>> alice.requestSpend(DT(bob.listenSpend,tht), alicetid, [coin]) 
     244Traceback (most recent call last): 
     245    .... 
     246SpendReject: did not go through 
     247 
     248 
     249>>> printSection('Redeem') 
    208250>>> bobtid = wallet.makeSerial() 
    209  
    210 >>> testserver.run_once(port,issuer=issuer,mint=mint) 
    211 >>> response = bob.requestTransfer(transport,tid,blinds = blinds, coins = coins) 
    212 >>> bobblank.signature = key.unblind(bobsecret,response.signatures[0]) 
    213 >>> bobcoin = bobblank 
    214 >>> key.verifyContainerSignature(bobcoin) 
    215 True 
    216  
    217 Lets try to double spend 
    218  
    219 >>> import messages 
    220 >>> bobblank = bob._makeBlank(cdd,mkc) 
    221 >>> bobsecret, bobblind = key.blindBlank(bobblank) 
    222 >>> blinds = [[mkc.keyId,bobblind]] 
    223 >>> bobtid = wallet.makeSerial() 
    224 >>> testserver.run_once(port,issuer=issuer,mint=mint) 
    225 >>> wallet.requestTransfer(transport,tid,blinds = blinds, coins = coins).header 
    226 'TransferReject' 
    227  
    228  
    229  
    230 ############################################################################### 
    231 Last step - bob wants to redeem the coins 
    232  
    233 >>> bobtid = wallet.makeSerial() 
    234 >>> testserver.run_once(port,issuer=issuer,mint=mint) 
    235 >>> bob.requestTransfer(transport,tid,target='foo', coins = [bobcoin]).header 
     251>>> testutils.run_once(port,issuer=issuer,mint=mint) 
     252>>> bobscoins = bob.storage[cdd.currencyId]['coins'] 
     253>>> bob.requestTransfer(transport,tid,target='foo', coins = bobscoins).header 
    236254'TransferAccept' 
     255 
    237256 
    238257""" 
  • trunk/sandbox/jhb/oc2/messages.py

    r274 r338  
    8383    ] 
    8484 
    85 class TransferResume(Message): 
    86      fields = Message.fields + [ 
    87         Field('transactionId'), 
    88     ] 
    89  
    90 class TransferResume(Message): 
    91      fields = Message.fields + [ 
    92         Field('transactionId'), 
    93     ] 
    94  
    9585class SumAnnounce(Message): 
    9686     fields = Message.fields + [ 
  • trunk/sandbox/jhb/oc2/testutils.py

    r290 r338  
     1"""This file is needed by documentation.py and testissuer.py""" 
     2 
    13import BaseHTTPServer, threading 
    24import issuer, mint, transports, urllib 
     
    2729        self.wfile.write(answer.toString(True)) 
    2830 
     31class TestingHandler(Handler): 
     32    """Supress output to stderr""" 
    2933 
     34    def log_message(self, format, *args): 
     35        pass 
    3036 
    3137def run_once(port,issuer=None,mint=None,authorizer=None): 
     
    3541    Handler.mint = mint 
    3642    Handler.authorizer = authorizer 
    37     httpd = BaseHTTPServer.HTTPServer(("", port), Handler) 
     43    httpd = BaseHTTPServer.HTTPServer(("", port), TestingHandler) 
    3844    import threading 
    3945    t = threading.Thread(target=httpd.handle_request)      
  • trunk/sandbox/jhb/oc2/transports.py

    r320 r338  
    1 import messages,  simplejson 
     1import messages,  simplejson, urllib, sys 
     2from pprint import pformat 
     3 
     4 
     5printmessages = 0 
     6 
     7def printMessage(message): 
     8    sys.stderr.write('\n') 
     9    sys.stderr.write('-'*30) 
     10    sys.stderr.write('\n\n') 
     11    sys.stderr.write(pformat(message.getData(1))+'\n') 
     12 
     13def printSection(header): 
     14    if printmessages: 
     15        out = """ 
     16 
     17#################################################################### 
     18   %s 
     19#################################################################### 
     20         
     21        """ % header 
     22 
     23        sys.stderr.write(out) 
     24 
    225 
    326def createMessage(data): 
     
    1942      
    2043    def __call__(self,message): 
    21         import  urllib 
     44         
     45        if printmessages: 
     46            printMessage(message) 
     47         
    2248        response = urllib.urlopen(self.url,message.toString(True)) 
    23         return createMessage(response.read()) 
     49        reply =  createMessage(response.read()) 
     50         
     51        if printmessages: 
     52            printMessage(reply)         
     53         
     54        return reply 
    2455 
    25 import sys 
     56class TestingHTTPTransport(object): 
     57     
     58    def __init__(self,port,**kwargs): 
     59        self.port = port 
     60        self.kwargs = kwargs 
     61 
     62    def __call__(self,message): 
     63        import testutils 
     64        testutils.run_once(self.port,**self.kwargs) 
     65        transport = HTTPTransport('http://localhost:%s/' % self.port) 
     66        return transport(message) 
     67 
    2668 
    2769class BTTransport(object): 
     
    4890        return createMessage(received) 
    4991 
     92 
     93class DirectTransport(object): 
     94 
     95    def __init__(self,target,transport2=None): 
     96        self.target = target 
     97        self.transport2 = transport2 
     98 
     99    def __call__(self,message): 
    50100     
     101        if printmessages: 
     102            printMessage(message) 
     103         
     104        if self.transport2: 
     105            response = self.target(message,self.transport2) 
     106        else:             
     107            response = self.target(message) 
     108         
     109        if printmessages: 
     110            printMessage(response) 
     111         
     112        return response 
    51113 
    52114class YieldTransport(object): 
     
    70132        self.results = list(args) 
    71133        self.debug = 0 
     134 
    72135    def __call__(self,message): 
    73136        if self.debug: 
     
    75138        result = self.results.pop(0) 
    76139         
    77         if type(result) == type([]) or type(result) == type(()): 
     140        if type(result) == list or type(result) == tuple: 
    78141            method = result[0] 
    79142            args = list(result[1:]) 
  • trunk/sandbox/jhb/oc2/wallet.py

    r337 r338  
    151151            answer.reason = 'unknown transactionId' 
    152152            return answer 
     153 
    153154        #check sum 
    154155        if amount != int(orig.amount): 
     
    156157            answer.reason = 'amount of coins does not match announced one. Announced: %s, got %s' % (orig.amount, amount) 
    157158            return answer 
     159 
    158160        #do exchange 
    159161        if transport: 
     
    161163            currency = self.getCurrency(cdd.currencyId) 
    162164            newcoins = message.coins  
    163             self.freshenUp(transport,cdd,newcoins) 
    164  
     165            answer = self.freshenUp(transport,cdd,newcoins) 
     166            if answer.header != 'TransferAccept': 
     167                answer = messages.SpendReject() 
     168                answer.reason = 'did not go through' 
     169                return answer 
     170         
    165171        answer = messages.SpendAccept() 
    166172        answer.transactionId = tid 
     
    305311            tid = self.makeSerial() 
    306312            response = self.requestTransfer(transport,tid,None,data,paycoins+newcoins) 
     313            if response.header != 'TransferAccept': 
     314                return response 
    307315            coins = currency['coins'] 
    308316            for coin in paycoins: 
     
    310318            coins.extend(self.unblindWithSignatures(secrets,response.signatures))  
    311319            self.storage.save() 
     320            return response  
     321        else: 
     322            return messages.Error() 
    312323 
    313324    def prepare4exchange(self,transport,cdd,oldcoins,newcoins):