Changeset 276 for trunk

Show
Ignore:
Timestamp:
04/23/09 18:42:34 (3 years ago)
Author:
ocjhb
Message:

made documentation shorter - removed the spec text

Location:
trunk/sandbox/jhb/oc2
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • trunk/sandbox/jhb/oc2/documentation.py

    r275 r276  
    11""" 
    2 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  
    3  
    4       This is just a todo for jhb, and not the real spec 
    5  
    6 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  
    7  
    8 OpenCoin Project                                            N. Toedtmann 
    9 http://opencoin.org/                                         J. H. Baach 
    10 Category: Draft                                                 M. Ryden 
    11  
    12                       OpenCoin Formats and Protocol 
    13  
    14 Status of this Memo 
    15  
    16    This draft is work in heavy progress. Do not consider it's content 
    17    stable in any sense as long as this note is present. Get in touch 
    18    with opencoin.org [1] and fetch a recent copy [2]. 
    19     
    20  
    21 Copyright Notice 
    22  
    23    Copyright (c) N. Toedtmann, J. H. Baach, M. Ryden (2008). 
    24  
    25  
    26 Abstract 
    27  
    28    This document describes the OpenCoin protocol which seeks to 
    29    implement David Chaum's concept of "untraceable payments" [3]. 
    30  
    31  
    32 ToDo 
    33  
    34    - licence of this document (GNU FDL, CC-BY-SA, Public Domain)? 
    35    - "Introduction", including scope of protocol 
    36    - JSON, 7-bit ASCII 
    37    - define token/certificate format, encryption padding 
    38    - define validity of certificates and tokens 
    39    - add note on randomness 
    40    - add PROTOCOL_ERROR 
    41    - add HANDSHAKE, CONTINUE, GOODBYE; warning that GOODBYE will disappear 
    42    - throw out reduntant "TRANSFER_TOKEN" explanatoins 
    43    - add authentication and authorization, at least for "target" 
    44      when minting 
    45    - add mandatory trusted channel (Bluetooth, TLS) 
    46    - reformat this into RFC-XML 
    47    - add warning on differences to scientific notation 
    48  
    49  
    50 Table of Contents 
    51  
    52    1. Introduction 
    53       1.1  Object of the OpenCoin protocol 
    54       1.2  Limited scope of the OpenCoin protocol 
    55       1.3  General Layout of the OpenCoin protocol 
    56       1.4  Encoding of messages, tokens and certificates 
    57    2. General guidelines 
    58    3. The OpenCoin protocol 
    59       3.1.  Issuer setup 
    60       3.2.  Wallet setup 
    61       3.3.  Wallet creates blanks 
    62       3.3.5."TRANSFER_TOKEN": A generic wallet-issuer request 
    63       3.4.  Wallet send minting request to issuer   
    64       3.5.  Wallet gets token back 
    65       3.6.  Wallet to wallet 
    66       3.7.  Redeeming tokens 
    67    4. References 
    68  
    69  
    70 1. Introduction 
    71  
    72 1.1 Object of the OpenCoin protocol 
    73  
    74 The OpenCoin protocol aims to implement David Chaum's concept of "untraceable  
    75 payments" [3]. The general procedure is this: 
    76  
    77 * Minting 
    78   * A payer creates a yet unsigned, 'blank' token according to the rules  
    79     published by the issuer. It includes a serial number. 
    80   * He obfuscates this blank, yielding the 'blind'. He send the blind to the 
    81     issuer and request signing with a special minting key. 
    82   * If the issuer's requirements for minting (which may include a payment)  
    83     are met, he signs the payer's  blind with the nominated minting key. 
    84   * The payer fetches the signed blind from the issuer and 'unblinds'. The  
    85     result is a token including a valid signature from the issuer. 
    86  
    87 * Spending 
    88     A payer sends the token to a payee. The payee verifies that the token is 
    89     valid according to the issuer's rules (format, data, signature, ...). In 
    90     the standard online case, he also checks it against the issuer's double  
    91     spending database (DSDB). He tells the payer if he accepts the token. 
    92  
    93 * Redemption 
    94     The payee sends the token to the issuer. The issuer verifies that the  
    95     token is valid and checks it against his DSDB. If he accepts the token,  
    96     he adds its serial number to the DSDB. He may offer the payee something  
    97     in exchange for the token (like a payment). 
    98  
    99 In the standard case of online payment, spending and redemption are actually  
    100 entwined to one simultanious operation. 
    101  
    102 Tokens include a reference to this protocol, a reference to the issuer, a  
    103 denomination, a random serial and the mint's signature over this data. The 
    104 minting key used to sign the token is deticated to mint exclusivly tokens  
    105 of this denomination. 
    106  
    107 This protocol is designed such that tokens are unforgable and untracable: 
    108  
    109 * Unforgeability/balance 
    110   Without knowledge of the issuer's private minting keys, no combination of  
    111   payers and payees can successfully redeem tokens of a total denomination  
    112   higher than the total denomination of tokens minted by the issuer for them.  
    113   In Particular, no one (except the issuer) can produce N+1 valid tokens  
    114   from N valid tokens ('one-more-forgery'). 
    115  
    116 * Untraceability 
    117   No combination of the issuer and a set of payees are able to correlate  
    118   blinds and tokens of a payer just by looking at them (but maybe by traffic 
    119   analysis). 
    120  
    121  
    122 1.2 Limited scope of the OpenCoin protocol 
    123  
    124 [ToDo] 
    125  
    126  
    127 1.3 General Layout of the OpenCoin protocol 
    128  
    129 The OpenCoin protocol typically involves three parties: the issuer, a sender/ 
    130 payer (Alice) and a receiver/payee (Bob). We call the OpenCoin user agents of  
    131 payer and payee 'wallets'. The issuer consists of four parts: 
    132 * The 'master key holder' (MHK) generates and keeps the master key pair  
    133   and signes and publishes the 'currency description document' (CDD) and  
    134   all the certificates. 
    135 * The mint generates and keeps the minting keys and signes blinds. 
    136 * The 'double spending database' (DSDB) keeps track of the serials of  
    137   tokens which got redeemed. 
    138 * The 'issuer service' (IS) is the public interface of the issuer on the 
    139   internet. 
    140  
    141 The participants send each other messages in request/response pairs. The  
    142 universal scheme is this: 
    143  
    144      * session initiation * 
    145  
    146    -- [ HANDSHAKE, DATA ] --> 
    147   <-- [ HANDSHAKE, null ] -- 
    148  
    149    -- [ REQUEST_1, DATA ] --> 
    150   <-- [ RESPONSE_1,DATA ] -- 
    151  
    152    -- [ REQUEST_2, DATA ] --> 
    153   <-- [ RESPONSE_2,DATA ] -- 
    154  
    155    -- [ CONTINUE,  null ] --> 
    156   <-- [ CONTINUE,  null ] -- 
    157  
    158           * pause * 
    159  
    160    -- [ REQUEST_3, DATA ] --> 
    161   <-- [ RESPONSE_3,DATA ] -- 
    162  
    163    -- [ REQUEST_4, DATA ] --> 
    164   <-- [ RESPONSE_4,DATA ] -- 
    165  
    166    -- [ GOODBYE,   null ] --> 
    167   <-- [ GOODBYE,   null ] -- 
    168  
    169      * session termination * 
    170  
    171 The standard case involves three sessions: 
    172  
    173    Payer Alice  --[minting]--------------------------------->  Issuer 
    174    Payer Alice  --[spending]-->  Payee Bob  --[redemption]-->  Issuer 
    175  
    176 the latter two usually happening at the same time ('online case'). 
    177  
    178  
    179 1.4 Encoding of messages, tokens and certificates 
    180  
    181 [ToDo] 
    182  
    183  
    184  
    185 2. General guidelines 
    186  
    187 [ToDo] 
    188  
    189  
    190 3. The OpenCoin protocol 
    191   
    192 3.1 Issuer setup 
    193  
    194 * issuer generates master key pair (ALG,pM,sM) 
    195 ############################################################################### 
    196  
    197 >>> from storage import Item 
     2Setup an issuer 
     3 
    1984>>> from issuer import Issuer 
    1995>>> issuer = Issuer({}) 
    2006>>> issuer.createMasterKeys() 
    2017 
    202 ############################################################################### 
    203  
    204 * issuer sets up "currency description document" = CDD (like a root certificate) 
    205  
    206    { 
    207      standard version             = http://opencoin.org/OpenCoinProtocol/1.0 
    208      currency identifier          = http://opencent.net/OpenCent 
    209      short currency identifier    = OC  
    210      issuer service location      = opencoin://issuer.opencent.net:8002 
    211      denominations                = strlist(1, 2, 5, 10, 20, 50, 100, 200, 500, 1000)  #list of strings seperated by commas 
    212      issuer cipher suite          = HASH-ALG, SIGN-ALG, BLINDING-ALG 
    213      issuer public master key     = base64(pM) 
    214       
    215      issuer                       = base64(hash(pM)) 
    216      base64(sig(sM,hash(content part))) 
    217    } 
    218  
    219    (question: is the "short currency identifier" needed?) 
    220    (question: "not use after") 
    221    (future: add additionial signatures, e.g. from wallet software vendors (set up in containers already)) 
    222  
    223  
    224 ############################################################################### 
     8 
     9 
     10issuer sets up "currency description document" = CDD (like a root certificate) 
    22511 
    22612>>> port = 9090 
    22713>>> denominations = [0,1,2,5,10,20] 
    228 >>> cdd = issuer.makeCDD('OpenCentA', 
    229 ...                      'oca', 
    230 ...                      [str(d) for d in denominations], 
    231 ...                      'http://localhost:%s/' % port, 
    232 ...                      '') 
     14>>> cdd = issuer.makeCDD('OpenCentA','oca',[str(d) for d in denominations],'http://localhost:%s/' % port,'') 
    23315>>> issuer.getMasterPubKey().verifyContainerSignature(cdd) 
    23416True 
    23517 
    236 ############################################################################### 
    237  
    238  
    239 * issuer publishes CDD at "currency identifier" URL 
    240  
    241 * mint (regularily) creates keypairs (pP,sP) for all denominations and id(p). 
    242   Master key holder generates keys certificate 
    243  
    244   { 
    245     key identifier      = base64(hash(pP)) 
    246     currency identifier = http://opencent.net/OpenCent 
    247     denomination        = denomination 
    248     not_before          = TIME(...) 
    249     key_not_after       = TIME(...) 
    250     token_not_after      = TIME(...) 
    251     public key          = base64(pP) 
    252  
    253     issuer              = base64(hash(pM)) 
    254     base64(sig(sM, hash(content part))) 
    255   } 
    256  
    257  
    258 ############################################################################### 
     18 
     19 
     20mint (regularily) creates keypairs (pP,sP) for all denominations and id(p).  
     21Master key holder generates keys certificate 
    25922 
    26023>>> from mint import Mint 
     
    26629True 
    26730 
    268 ############################################################################### 
    269  
    270    
    271   Questions: 
    272   * CDD? 
    273  
    274 * issuer fires up issuer service (=IS) at <opencoin://issuer.opencent.net:8002> 
    275  
    276  
    277 3.2 Wallet setup 
    278  
    279 * fetch "currency description document" from issuer 
    280  
    281 ############################################################################### 
     31 
     32 
     33Wallet fetches cdd from issuer 
    28234 
    28335>>> #faked request 
     
    30052True 
    30153 
    302 ############################################################################### 
    303  
    304  
    305 3.3 Wallet creates blanks 
    306  
    307 * Wallet: fetches current public minting keys for denomination 
    308  
    309 Wallet: 
    310     MINTING_KEY_FETCH_DENOMINATION(denomination) or MINTING_KEY_FETCH_KEYID(key_id) 
    311 IS: 
    312     MINTING_KEY_PASS(keycertificate) or MINTING_KEY_FAILURE(reason) 
    313  
    314 ############################################################################### 
     54 
     55 
     56Wallet: fetches current public minting keys for denomination 
    31557 
    31658>>> clientside = protocols.FetchMintKeys(transport,denominations=['1','5']) 
     
    32062True 
    32163 
    322 ############################################################################### 
    323  
    324 * Wallet: creates blank according to CDD: 
    325  
    326   { 
    327       standard identifier = http://opencoin.org/OpenCoinProtocol/1.0 
    328       currency identifier = http://opencent.net/OpenCent  
    329       denomination        = denomination 
    330       key identifier      = key_id(signing key) 
    331       serial              = base64(128bit random number) 
    332   } 
    333  
    334 #XXX: ist key id wirklich vom secret key, oder vom public key? 
    335  
    336  
    337 * Wallet: create random r, calculate  
    338  
    339     blind = blinding(r, pub_minting_key, hash(blank)) 
    340   
    341   Calculate a collision-free random transaction ID (128 bit) 
    342  
    343   Keep (r, blank, blind) in mind.  
    344    
    345 ############################################################################### 
     64 
     65 
     66Wallet creates  blank and blinds it 
    34667 
    34768>>> mkc = mkcs[1] 
     
    35475>>> secret, blind = key.blindBlank(blank) 
    35576>>> tid = wallet.makeSerial() 
    356  
    35777>>> int(mkc.denomination) 
    358785 
    35979 
    360 ############################################################################### 
    361  
    362  
    363 3.3.5 "TRANSFER_TOKEN": A generic wallet-issuer request 
    364  
    365 The atom for this transaction is a list of tokens - if one of the tokens /blanks 
    366 fail, the whole transaction fails. 
    367  
    368 * Client sends 
    369     
    370         TRANSFER_TOKEN_REQUEST(  
    371             transaction_id, target, list_of_blinds+keyids,  
    372             list_of_tokens, list_of_options ) 
    373  
    374   [ WARNING: In future versions of this protocol, it wll change to 
    375         TRANSFER_TOKEN_REQUEST ( 
    376             transaction_id, list_of_options, 
    377             target, list_of_blinds+keyids, list_of_tokens ) 
    378   ] 
    379  
    380   to IS (issuer service), where  
    381  
    382   * transaction_id is a base64(random(128bit)) referencing this transaction 
    383     e.g. for later resume after an abort. 
    384   * list_of_option may contain variable=value pairs like "JITM=mandatory". 
    385     It must contain the option "type", which can have three values: 
    386     * mint    : A minting request. target is a payment reference,  
    387                 list_of_tokens must be empty. 
    388     * redeem  : A token redemption. target is an account reference, 
    389                 list_of_blinds+keyids must be empty. 
    390     * exchange: A request to mint new tokens for old ones. target must be  
    391                 empty, value of blinds must equal value of tokens. 
    392  
    393   If at least one of the blinds or tokens is rejected, the issuer answers 
    394  
    395         TRANSFER_TOKEN_REJECT(  
    396             transaction_id, reason, 
    397             list( (blind1.key_id, reason1), ... ), 
    398             list( (token1.key_id,  reason1), ... )  ) 
    399  
    400   where "reason" may be some general failure like "500 minting not available". 
    401   If the request is accepted with no delay, IS answers 
    402  
    403         TRANSFER_TOKEN_ACCEPT(  
    404             transaction_id, message, list_of_signed_blinds) 
    405  
    406   (with list_of_singed_blinds empty if no minting was required) 
    407   If minting was requested and acccepted but postponed, IS answers 
    408  
    409         TRANSFER_TOKEN_DELAY( transaction_id, message ) 
    410  
    411   In this case, the wallet can fetch the signed blinds later by  
    412  
    413         TRANSFER_TOKEN_RESUME( transaction_id ) 
    414  
    415  
    416 3.4 Wallet send minting request to issuer   
    417  
    418 * Send 
    419  
    420         TRANSFER_TOKEN_REQUEST( transaction_id, target,  
    421             list_of_blinds+keyids, (empty list) , list_of_options, ) 
    422  
    423   to issuer service 
    424    
    425    
    426 ############################################################################### 
     80 
     81 
     82Lets try to get a coin minted 
    42783 
    42884We first need to setup an authorizer, to (surpise) authorize the request. Nils says 
     
    43692>>> clientside = protocols.TransferRequest(transport,tid,'foo',[[mkc.keyId,blind]],[]) 
    43793 
    438 ############################################################################### 
    439  
    440 * Issuer: if request will not be minted (e.g., "Bad Key ID" if the key_id 
    441   is not current): 
    442  
    443         TRANSFER_TOKEN_REJECT( transaction_id, reason, 
    444             list( (blind1.key_id, reason1), ... ), (empty list1)  ) 
    445          
    446 ############################################################################### 
    447 >>> import time 
    448 >>> time.sleep(1) 
     94Lets have the authorizer denying the request 
     95 
    44996>>> authorizer.deny = True 
    45097>>> testserver.run_once(port,mint=mint,authorizer=authorizer) 
     
    45299'TransferReject' 
    453100 
    454  
    455 ############################################################################### 
    456  
    457   ElseIf minting is done just-in-time, IS answers 
    458  
    459         TRANSFER_TOKEN_ACCEPT( transaction_id, message, list_of_signed_blinds) 
    460  
    461 ############################################################################### 
     101Now have a well working one 
    462102 
    463103>>> authorizer.deny = False 
     
    466106>>> response.header 
    467107'TransferAccept' 
     108 
     109And check it 
     110 
    468111>>> blindsign = response.signatures[0] 
    469112>>> blank.signature = key.unblind(secret,blindsign) 
     
    477120>>> mint.addToTransactions = issuer.addToTransactions 
    478121 
    479  
    480 ############################################################################### 
    481  
    482   Else IS queues blind to the mint and tells wallet to wait 
    483  
    484         TRANSFER_TOKEN_DELAY( transaction_id, reason ) 
    485  
    486  
    487 ############################################################################### 
     122The mint can also be a bit slow 
    488123 
    489124>>> mint.delay = True 
     
    491126>>> clientside.run().header 
    492127'TransferDelay' 
     128 
    493129>>> mint.delay = False 
    494130 
    495 ############################################################################### 
    496  
    497  
    498   Session is terminated. 
    499  
    500  
    501   In case of delayed minting, mint processes request (signs blind with key_id) 
    502   some time later and passes "signed blind"="blind token" back to IS  
    503  
    504  
    505  
    506  
    507  
    508  
    509  
    510 3.5 Wallet gets token back 
    511  
    512 * Wallet asks issuer service 
    513  
    514         TRANSFER_TOKEN_RESUME( transaction_id ) 
    515  
    516 * IS either rejects finally 
    517  
    518         TRANSFER_TOKEN_REJECT( transaction_id, reason, 
    519             list( (blind1.key_id, reason1), ... ), (empty list) ) 
    520   
    521   with reasons like "TID Unknown", "TID expired", "TID rejected", ..., 
    522   or tells to wait longer 
    523  
    524         TRANSFER_TOKEN_DELAY( transaction_id, reason ) 
    525  
    526 ############################################################################### 
     131Or the issuer is slow 
    527132 
    528133>>> issuer.delay = True 
     
    533138>>> issuer.delay = False 
    534139 
    535 ############################################################################### 
    536  
    537   (question: what about key expiration while request is in mining queue) 
    538   (oierw thinks: as long as the key is valid for minting when the request is made, we are good) 
    539  
    540   or passes signed blinds to wallet Bob, must preserve order 
    541  
    542         TRANSFER_TOKEN_ACCEPT( transaction_id, message, list_of_singed_blinds ) 
    543     
    544  
    545 ############################################################################### 
     140So we need to resume 
    546141 
    547142>>> clientside = protocols.TransferResume(transport,tid) 
     
    551146'TransferAccept' 
    552147 
    553 ############################################################################### 
    554  
    555   Session terminates 
    556  
    557 * wallet checks if blind fits request id and if blind was correctly signed.  
    558   If not, delete blind and inform user (optional: inform issuer about error) 
    559   (optional: if yes, inform issuer that he may delete the request) 
    560  
    561 * Wallet unblinds signed blind and yields token  (or reblinds) 
    562  
    563 ############################################################################### 
     148And we have a valid coin 
    564149 
    565150>>> blindsign = response.signatures[0] 
     
    569154True 
    570155 
    571 ############################################################################### 
    572  
    573  
    574 3.6 Wallet to wallet 
    575  
    576 Alice - sends a token 
    577 Bob   - receives the token 
    578  
    579   [ Warning:  
    580     The messages "SPEND_TOKEN_*" may get exchanged by "TRANSFER_TOKEN_*" of  
    581     type "redeem" or "spend" in future versions of this protocol. ] 
    582  
    583 * Prerequisites 
    584   * Wallet Alice locates Wallet Bob and sets up (secure) connection 
    585   * Alice knows how much to send and tells her Wallet 
    586   * Wallet Alice calculates a splitting of sum into tokens (units) 
    587     and reates a list of tokens to send 
    588   * Wallet Alice and Wallet Bob are synchronized to UTC (within some small  
    589     margin of error) 
    590  
    591  
    592 * [ToDo] Handshake 
    593  
    594  
    595 * Wallet Alice announces sum of tokens she wishes to spend for a certain 
    596   prupose=target, wallet Bob decides if it is going to accept them: 
    597  
    598     A:      SUM_ANNOUNCE( transaction_id, sum, target ) 
    599     B:      SUM_ACCEPT( transaction_id ) 
    600         or  SUM_REJECT( transaction_id, "Reason" ) 
    601  
    602 ############################################################################### 
     156 
     157 
     158Now, wallet to wallet. We setup an alice and a bob side. Alice announces 
     159a sum, and bob dedices if he wants to accept it 
    603160 
    604161>>> bobport = 9091 
     
    616173True 
    617174 
    618 ############################################################################### 
    619  
    620 * Wallet Alice sends tokens to Wallet Bob (this time including their clear  
    621   serial and signature) 
    622    
    623     A:      SPEND_TOKEN_REQUEST( transaction_id, list(token1, ...) ) 
    624  
    625 * The atom for a SPEND_TOKEN_REQUEST is the entire list of tokens 
    626  
    627 * Wallet Bob checks if the sum of their values matches the announced sum, if  
    628   they are valid and (if the former tests do not fail) tries itself to spent 
    629   the tokens at the issuer with a TRANSFER_TOKEN_REQUEST of type "redeem" or 
    630   "exchange", using a new, different transaction_id. If one of these fail, 
    631   wallet Bob rejects the request it with a reason/reasons, otherwise accepts 
    632   them: 
    633  
    634     B:      SPEND_TOKEN_REJECT( transaction_id, list( (tokenN, "ReasonN") ) ) 
    635         or  SPEND_TOKEN_REJECT( transaction_id, emptylist, "Reason") 
    636         or  SPEND_TOKEN_ACCEPT( transaction_id ) 
    637  
    638   Possible reasons are "unknown", "invalid" ... [ToDo]. 
    639  
    640   In case of rejection, wallet Alice itself should immediatly exchange these  
    641   tokens at the issuer as an emergancy countermeasure against token theft. 
    642  
    643   In case of acceptance, wallet Alice must delete all instances of the spent 
    644   tokens. 
    645  
    646 ############################################################################### 
     175 
     176 
     177Wallet Alice sends tokens to Wallet Bob (this time including their clear  
     178serial and signature) 
     179 
     180Lets have first a wrong transactionId 
    647181 
    648182>>> bob = protocols.SpendListen(bobwallet) 
     
    653187    .... 
    654188SpendReject: unknown transactionId 
     189 
     190Or lets try to send a wrong amount 
    655191 
    656192>>> alice = protocols.SpendRequest(bob.run, wallet, alicetid, [])  
     
    683219 
    684220Lets try to double spend 
     221 
    685222>>> import messages 
    686223>>> bobblank = bobwallet._makeBlank(cdd,mkc) 
     
    695232 
    696233 
    697 ############################################################################### 
    698  
    699 3.7 Redeeming tokens  
    700  
    701 * Wallet sends tokens + target to IS 
    702  
    703     W:  TRANSFER_TOKEN_REQUEST( 
    704             transaction_id, list_of_options, target, (empty list), list_of_tokens  
    705         ) 
    706  
    707   target may be an account and is of the form: 
    708  
    709         MINT_REQUEST=#base64(request_id) 
    710         ONLINE_BANKING_ACCOUNT=#string(account_identifier) 
    711         and so on... to be defined with relationship between IS and individual 
    712  
    713  
    714 * IS checks if tokens and target are valid 
    715     - if minting keys are still valid (XXX token has not expired) 
    716     - if serial is still valid (against DSDB) 
    717     - if signature is valid 
    718  
    719   If not, IS rejects with reason (key id unknown, token outdated, token spent,  
    720   signature invalid) per token or sweeping 
    721  
    722     IS: TRANSFER_TOKEN_REJECT(  
    723             transaction_id, reason, (empty list), list( (token1.key_id,  reason1), ... )  ) 
    724         ) 
    725  
    726   If tokens and target are valid, IS enters the serials of the tokens into the 
    727   DSDB, servers the target and replies 
    728  
    729     IS: TRANSFER_TOKEN_ACCEPT(  
    730             transaction_id, message, (empty list) 
    731         ) 
    732  
    733  
    734 ############################################################################### 
     234Last step - bob wants to redeem the coins 
    735235 
    736236>>> bobtid = wallet.makeSerial() 
     
    740240'TransferAccept' 
    741241 
    742  
    743 ############################################################################### 
    744  
    745  
    746  
    747 4. References 
    748  
    749 [1]         The OpenCoin project <http://opencoin.org/> 
    750  
    751 [2]         The OpenCoin project, "OpenCoin protocol v1.0" 
    752             <https://trac.opencoin.org/trac/opencoin/browser/trunk/standards/protocol.txt> 
    753  
    754 [3]         David Chaum, "Blind signatures for untraceable payments", Advances 
    755             in Cryptology - Crypto '82, Springer-Verlag (1983), 199-203. 
    756  
    757 [RFC4086]   D. Eastlake, J. Schiller and S. Crocker, "Randomness Requirements  
    758             for Security", RFC 4086, June 2005 
    759  
    760 [RFC4627]   D. Crockford, "The application/json Media Type for JavaScript  
    761             Object Notation (JSON)", RFC 4627, July 2006 
    762242""" 
    763243 
  • trunk/sandbox/jhb/oc2/protocols.py

    r275 r276  
    244244 
    245245 
    246 class CoinsSpendSender(Protocol): 
    247  
    248     def __init__(self,coins,target): 
    249         self.coins = coins 
    250         self.target = target 
    251  
    252     def spendCoins(self,message): 
    253         return '' 
    254  
    255     def announceCoins(self,message): 
    256         return '' 
    257  
    258  
    259  
    260 class CoinsSpendRecipient(Protocol): 
    261  
    262     def hearCoins(self,message): 
    263         return '' 
    264  
    265     def receiveCoins(self,message): 
    266         return '' 
    267  
    268  
    269