def handle(self, message): if not isinstance(message, CoinsRedeem) and not isinstance( message, CoinsReject) and not isinstance(message, CoinsAccept): if self.manager.walletMessageType.globals.lastState == MessageHello: # we are now on a different message. Oops. raise MessageError( 'Coins should have already been removed. It was not. Very odd. Message: %s LastMessage: %s' % (message.identifier, self.manager.walletMessageType.globals.lastState)) else: raise MessageError( 'We somehow called Coins.handle() but cannot be there. Message: %s' % message.identifier) if isinstance(message, CoinsRedeem): # we output this. Previous step was Hello. Do nothing. print 'Got a CoinsRedeem. I did not know we got these.' elif isinstance(message, CoinsAccept): self.removeSpentCoins(self.manager.entity.coins, self.manager.coins) self.manager.walletMessageType.removeCallback(self.handle) self.manager.success(message, self) elif isinstance(message, CoinsReject): self.reason = self.manager.walletMessageType.persistant.reason self.manager.walletMessageType.removeCallback(self.handle) # undo the damage and tell someone self.manager.failure(message, self) self._setLastState(message.identifier)
def handle(self, message): if not isinstance(message, MintRequest) and not isinstance(message, MintAccept) and not isinstance(message, MintReject): if self.manager.messageType.globals.lastState == MessageHello: # we are now on a different message. Oops. raise MessageError('Mint should have already been removed. It was not. Very odd. Message: %s LastMessage: %s' % (message.identifier, self.manager.messageType.globals.lastState)) else: print 'message class: %s' % message.__class__ raise MessageError('We somehow called Mint.handle() but cannot be there. Message: %s' % message.identifier) if isinstance(message, MintRequest): self.request_id = self.manager.messageType.persistant.request_id self.blinds = self.manager.messageType.persistant.blinds type, result = self.request(self.request_id, self.blinds, self.manager.entity.minting_keys_key_id, self.timeNow()) if type == 'ACCEPT': if self.request_id != result: raise MessageError('request_id changed. Was: %s, Received: %s' % (self.request_id, result)) self.manager.messageType.removeCallback(self.handle) self.__createAndOutput(MintAccept) elif type == 'REJECT': self.manager.messageType.persistant.reason = result self.manager.messageType.removeCallback(self.handle) self.__createAndOutput(MintReject) else: raise MessageError('Received an impossible type: %s' % self.type) elif isinstance(message, MintAccept) or isinstance(message, MintReject): # we output this. Next step can only be Goodbye self.manager.messageType.removeCallback(self.handle)
def handle(self, message): if not isinstance(message, BlankPresent) and not isinstance(message, BlankAccept) and not isinstance(message, BlankReject) \ and not isinstance(message, BlankFailure): if self.manager.walletMessageType.globals.lastState == MessageHello: # we are now on a different message. Oops. raise MessageError( 'Blank should have already been removed. It was not. Very odd. Message: %s LastMessage: %s' % (message.identifier, self.manager.walletMessageType.globals.lastState)) else: raise MessageError( 'We somehow called Blank.handle() but cannot be there. Message: %s' % message.identifier) if isinstance(message, BlankPresent): # we output this. Previous step was Hello. Do nothing. self._verifyLastState(['DSDB_KEY_PASS']) print 'Got a BlankPresent. I did not know we got these.' elif isinstance(message, BlankAccept): self.manager.walletMessageType.persistant.coins = self.manager.coins self.manager.walletMessageType.removeCallback( self.handle) #remove the callback. Not coming here again self._createAndOutputWallet(CoinsRedeem) elif isinstance(message, BlankFailure): self.reason = self.manager.walletMessageType.persistant.reason # undo the damage and tell someone self.manager.failure(message, self) elif isinstance(message, BlankReject): self.reason = self.manager.walletMessageType.persistant.reason self.manager.failure(message, self) self._setLastState(message.identifier)
def handle(self, message): if not isinstance(message, DSDBKeyRequest) and not isinstance( message, DSDBKeyPass): if self.manager.isMessageType.globals.lastState == MessageHello: # we are now on a different message. Oops. raise MessageError( 'RedeemCoins should have already been removed. It was not. Very odd. Message: %s LastMessage: %s' % (message.identifier, self.manager.isMessageType.globals.lastState)) else: raise MessageError( 'We somehow called RedeemCoins.handle() but cannot be there. Message: %s' % message.identifier) self._verifyLastState([None]) if isinstance(message, DSDBKeyRequest): # we output this. Previous step was Hello. Do nothing. print 'Got a DSDBKeyRequest. I did not know we got these.' elif isinstance(message, DSDBKeyPass): self.dsdb_certificate = self.manager.isMessageType.persistant.dsdb_certificate self.manager.persistant.dsdb_certificate = self.dsdb_certificate # keep a copy for me self.manager.walletMessageType.persistant.dsdb_certificate = self.dsdb_certificate # and we need to encode it if not self.validCertificate(self.dsdb_certificate, self.manager.cdd, self.timeNow()): raise MessageError('Invalid DSDB Certificate') self.createBlinds(self.dsdb_certificate, self.manager.coins) self.manager.isMessageType.removeCallback( self.handle) # not coming back here again self._createAndOutputWallet(BlankPresent) self._setLastState(message.identifier)
def verifyCoins(self, coins, mintingKeys, blanks, dsdb_keycertificate, cdds): failure = False failures = [] if len(coins) != len(blanks): raise MessageError('Different amounts of coins and blanks') if len(coins) == 0: raise MessageError('Need atleast one coin') # this *should* be impossible due to the previus error. for i in range(len(coins)): type, result = self.verifySingleCoin(coins[i], mintingKeys, blanks[i], dsdb_keycertificate, cdds) if type == 'VALID': pass elif type == 'FAILURE': failure = True failures.append((coins[i], result)) else: raise MessageError('Got an imposisble type: %s' % type) if failure: return 'REJECT', failures else: return 'ACCEPT', None
def handle(self, message): if not isinstance(message, UnlockCoinsRequest) and not isinstance( message, UnlockCoinsPass) and not isinstance( message, UnlockCoinsFailure): if message.messageLayer.globals.lastState == MessageHello: # we are now on a different message. Oops. raise MessageError( 'UnlockCoins should have already been removed. It was not. Very odd. Message: %s LastMessage: %s' % (message.identifier, message.messageLayer.globals.lastState)) else: raise MessageError( 'We somehow called UnlockCoins.handle() but cannot be there. Message: %s' % message.identifier) self._verifyLastState([]) # FIXME: Figure it out later if isinstance(message, UnlockCoinsRequest): # we output this. Previous step was in ????? print 'Got a UnlockCoinsRequest. I did not know we got these.' elif isinstance(message, UnlockCoinsPass): #FIXME: do something USEFUL here self.manager.dsdbMessageType.removeCallback(self.handle) elif isinstance(message, UnlockCoinsFailure): #FIXME: do something USEFUL here self.manager.dsdbMessageType.removeCallback(self.handle) #self.manager.failure(message, self) self._setLastState(message.identifier)
def handle(self, message): if not isinstance(message, RedeemCoinsRequest) and not isinstance( message, RedeemCoinsAccept) and not isinstance( message, RedeemCoinsReject): if message.messageLayer.globals.lastState == MessageHello: # we are now on a different message. Oops. raise MessageError( 'RedeemCoins should have already been removed. It was not. Very odd. Message: %s LastMessage: %s' % (message.identifier, message.messageLayer.globals.lastState)) else: raise MessageError( 'We somehow called RedeemCoins.handle() but cannot be there. Message: %s' % message.identifier) self._verifyLastState( [''] ) # we should have two of them in here when it works. (maybe three with REDEEM_COINS_REQUEST) if isinstance(message, RedeemCoinsRequest): # we output this. Previous step was in ???? print 'Got a RedeemCoinsRequest. I did not know we got these.' elif isinstance(message, RedeemCoinsAccept): if self.isRequiresMRbeforeRCR: # We have our MintRequest and RedeemCoinsRequests in. All to do now is Fetch our coins! self.manager.isMessageType.persistant.request_id = self.manager.persistant.mintRequestID self.manager.isMessageType.removeCallback( self.handle) #remove the callback. Not coming here again self._createAndOutputIS(FetchMintedRequest) else: # We have done our RedeemCoinsRequest. Now do a MintRequest, and then finaly a FetchMintedRequest self.manager.isMessageType.persistant.request_id = self.manager.persistant.mintRequestID # setup blinds only for the MintRequest message blinds = [] for b in self.manager.persistant.mintBlanks: b.blind_blank( self.manager.entity.cdds ) # XXX should this be in makeBlanks() instead? blinds.append((b.key_identifier, b.blind_value)) self.manager.isMessageType.persistant.blinds = blinds self.manager.isMessageType.removeCallback(self.handle) self._createAndOutputIS(MintRequest) elif isinstance(message, RedeemCoinsReject): self.reason = self.manager.isMessageType.persistant.reason # undo the damage and tell someone self.manager.isMessageType.removeCallback(self.handle) self.manager.failure(message, self) self._setLastState(message.identifier)
def handle(self, message): if not isinstance(message, LockCoinsRequest) and not isinstance( message, LockCoinsAccept) and not isinstance( message, LockCoinsFailure): if self.manager.messageType.globals.lastState == MessageHello: # we are now on a different message. Oops. raise MessageError( 'LockCoins should have already been removed. It was not. Very odd. Message: %s LastMessage: %s' % (message.identifier, self.manager.messageType.globals.lastState)) else: print 'message class: %s' % message.__class__ raise MessageError( 'We somehow called LockCoins.handle() but cannot be there. Message: %s' % message.identifier) if isinstance(message, LockCoinsRequest): self.key_id = self.manager.messageType.persistant.key_id self.transaction_id = self.manager.messageType.persistant.transaction_id self.blanks = self.manager.messageType.persistant.blanks # blanks is a tuple of mint_key_id and obfuscated serial self.type, self.result = self.lock( self.key_id, self.transaction_id, self.blanks, self.manager.dsdb_key, self.manager.entity.dsdb_database, self.manager.entity.dsdb_requests, self.manager.entity.minting_keys_key_id, self.timeNow()) if self.type == 'ACCEPT': transaction_id, self.dsdb_lock = self.result if self.transaction_id != transaction_id: raise MessageError( 'transaction_id changed. Was: %s, Received: %s' % (self.transaction_id, transaction_id)) self.manager.messageType.persistant.dsdb_lock = self.dsdb_lock self.manager.messageType.removeCallback( self.handle) # we are done here self.__createAndOutput(LockCoinsAccept) elif self.type == 'REJECT': self.manager.messageType.persistant.reason = self.result self.manager.messageType.removeCallback( self.handle) # we are done here self.__createAndOutput(LockCoinsFailure) else: raise MessageError('Received an impossible type: %s' % self.type) elif isinstance(message, LockCoinsAccept) or isinstance( message, LockCoinsFailure): # we output this. Next step can only be Goodbye self.manager.messageType.removeCallback(self.handle)
def handle(self, message): if not isinstance(message, MintRequest) and not isinstance( message, MintAccept) and not isinstance(message, MintReject): if message.messageLayer.globals.lastState == MessageHello: # we are now on a different message. Oops. raise MessageError( 'Mint should have already been removed. It was not. Very odd. Message: %s LastMessage: %s' % (message.identifier, message.messageLayer.globals.lastState)) else: raise MessageError( 'We somehow called Mint.handle() but cannot be there. Message: %s' % message.identifier) self._verifyLastState( [''] ) # I have no idea what will actually be here, nor to I care right now. This will show us. if isinstance(message, MintRequest): # we output this. Previous step was in ????? print 'Got a MintRequest. I did not know we got these.' elif isinstance(message, MintAccept): if self.manager.persistant.mintRequestID != self.manager.isMessageType.persistant.request_id: raise MessageError( 'request_id changed. Was: %s Now %s' % (self.manager.persistant.mintingRequestID, self.manager.isMessageType.persistant.request_id)) if self.isRequiresMRbeforeRCR: # We've already done the MintRequest. Nothing stopping us from trying to Redeem now. self.manager.isMessageType.persistant.trasaction_id = self.manager.persistant.mintRequestID self.manager.isMessageType.persistant.target = self.manager.persistant.target self.manager.isMessageType.persistant.coins = self.manager.persistant.coins self.manager.isMessageType.removeCallback(self.handle) self._createAndOutputIS(RedeemCoinsRequest) else: # We already did the RedeemRequest. Time to fetch self.manager.isMessageType.persistant.request_id = self.manager.persistant.mintRequestID self.manager.isMessageType.removeCallback(self.handle) self._createAndOutputIS(FetchMintedRequest) elif isinstance(message, MintReject): self.reason = self.manager.isMessageType.persistant.reason self.manager.isMessageType.removeCallback(self.handle) # undo the damage and tell someone self.manager.failure(message, self) self._setLastState(message.identifier)
def handle(self, message): if not isinstance(message, MintingKeyFetchDenomination) and not isinstance(message, MintingKeyFetchKeyID) and not \ isinstance(message, MintingKeyFailure) and not isinstance(message, MintingKeyPass): if self.manager.messageType.globals.lastState == MessageHello: # we are now on a different message. Oops. raise MessageError('MintingKey should have already been removed. It was not. Very odd. Message: %s LastMessage: %s' % (message.identifier, self.manager.messageType.globals.lastState)) else: print 'message class: %s' % message.__class__ raise MessageError('We somehow called MintingKey.handle() but cannot be there. Message: %s' % message.identifier) if isinstance(message, MintingKeyFetchKeyID) or isinstance(message, MintingKeyFetchDenomination): if isinstance(message, MintingKeyFetchKeyID): self.key_id = self.manager.messageType.persistant.key_id self.denomination = None else: self.denomination = self.manager.messageType.persistant.denomination self.key_id = None type, result = self.findKey(self.key_id, self.denomination) if type == 'PASS': self.minting_certificate = result self.manager.messageType.persistant.minting_certificate = self.minting_certificate self.manager.messageType.removeCallback(self.handle) self.__createAndOutput(MintingKeyPass) elif type == 'FAILURE': self.manager.messageType.persistant.reason = result if result == 'Unknown key_id': self.reason = 'Unknown key_id' self.manager.messageType.persistant.reason = self.reason self.manager.messageType.removeCallback(self.handle) self.__createAndOutput(MintingKeyFailure) elif result == 'Unknown denomination': self.reason = 'Unknown denomination' self.manager.messageType.persistant.reason = self.reason self.manager.messageType.removeCallback(self.handle) self.__createAndOutput(MintingKeyFailure) else: raise MessageError('Received impossible result: %s' % result) else: raise MessageError('Received impossible type: %s' % type) elif isinstance(message, MintingKeyPass) or isinstance(message, MintingKeyFailure): # we output this. Next step can only be Goodbye print 'we should never get here. Message: %s' % message.identifier self.manager.messageType.removeCallback(self.handle)
def handle(self, message): if not isinstance(message, FetchMintedRequest) and not isinstance(message, FetchMintedAccept) and not \ isinstance(message, FetchMintedFailure) and not isinstance(message, FetchMintedWait): if message.messageLayer.globals.lastState == MessageHello: # we are now on a different message. Oops. raise MessageError( 'FetchMinted should have already been removed. It was not. Very odd. Message: %s LastMessage: %s' % (message.identifier, message.messageLayer.globals.lastState)) else: raise MessageError( 'We somehow called FetchMinted.handle() but cannot be there. Message: %s' % message.identifier) self._verifyLastState( ['REDEEM_COINS_ACCEPT', 'MINT_ACCEPT', 'FETCH_MINTED_REQUEST']) if isinstance(message, FetchMintedRequest): # we output this. Previous step was in ???? print 'Got a FetchMintedRequest. I did not know we got these.' elif isinstance(message, FetchMintedAccept): self.signatures = self.manager.isMessageType.persistant.signatures self.manager.persistant.signatures = self.signatures successes, failures = self.verifySignatures( self.signatures, self.manager.persistant.mintingKeysDenomination, self.manager.persistant.mintBlanks, self.manager.entity.cdds) self.manager.persistant.newCoins = successes self.manager.persistant.mintingFailures = failures if successes: self.depositCoins(self.manager.entity.coins, successes) self.manager.success(self, message) if failures: self.manager.failure(self, message) self.manager.isMessageType.removeCallback(self.handle) elif isinstance(message, FetchMintedWait) or isinstance( message, FetchMintedFailure): self.reason = self.manager.isMessageType.persistant.reason # undo the damage and tell someone self.manager.failure(message, self) self.manager.isMessageType.removeCallback(self.handle) self._setLastState(message.identifier)
def verifySignatures(self, signatures, minting_keys, minting_blanks, cdds): """verifies the signatures received and makes coins out of blanks.""" successes = [] failures = [] if len(minting_blanks) != len(signatures): #FIXME: logging #pass # nothing we can do here. Try to salvage what we can. We are going to assume they still line up raise MessageError( 'minting_blanks and signatures are different lengths' ) # screw it for i in range(len(signatures)): sig = signatures[i] bnk = minting_blanks[i] #FIXME another 'Only one CDD per transaction' belief. This one may be valid -- talking to IS cdd = cdds[minting_blanks[0].currency_identifier] unblinded = bnk.unblind_signature(sig) try: coin = bnk.newCoin(unblinded, cdd, minting_keys[bnk.denomination]) # the call to newCoin verifies the signature successes.append(coin) except CryptoError: failures.append(bnk, sig) return successes, failures
def resumeConversation(self, message, result): if isinstance(message, BlankPresent): self.setHandler(BlankAndMintingKey( self, message)) # First we receive the blanks elif isinstance(message, MintAccept) or isinstance( message, MintReject): self.setHandler(Mint( self, message)) # Then we (may) try to mint our own blanks elif isinstance(message, LockCoinsFailure) or isinstance( message, LockCoinsAccept): self.setHandler(LockCoins( self, message)) # We also have to try to lock the coins... elif isinstance(message, CoinsRedeem): self.setHandler( Coins(self, message) ) # We locked the coins, and they are valid. We sent a BlankAccept. Next we get told to redeem them elif isinstance(message, RedeemCoinsReject) or isinstance( message, RedeemCoinsAccept): self.setHandler( RedeemCoins(self, message) ) # Now we redeem them (note: the next step may be to try to mint them...) elif isinstance(message, FetchMintedWait) or isinstance( message, FetchMintedFailure) or isinstance( message, FetchMintedAccept): self.setHandler(FetchMinted( self, message)) # And finally, get the coins. elif isinstance(message, UnlockCoinsPass) or isinstance( message, UnlockCoinsFailure): self.setHandler(UnlockCoins( self, message)) # If we erred, we unlock to be nice else: raise MessageError('Message %s does not continue a conversation' % message.identifier)
def __init__(self, messageType, entity): self.messageType = messageType self.entity = entity # the entity that spawned us self.dsdb_key = self.entity.dsdb_key if not self.messageType.globals.status.can( MessageStatuses.PrivilegeServer): raise MessageError( 'given messageType does not have PrivilegeServer') class messages: pass self.messages = messages del messages #create conversation starting messages to trigger self.startConversation self.messages.LCR = LockCoinsRequest(self.startConversation) self.messages.UCR = UnlockCoinsRequest(self.startConversation) #add all of our special mesasges as MessageHandlers self.messageType.addMessageHandler(self.messages.LCR) self.messageType.addMessageHandler(self.messages.UCR) #everything that can't start a conversation self.messageType.addMessageHandler(LockCoinsAccept()) self.messageType.addMessageHandler(LockCoinsFailure()) self.messageType.addMessageHandler(UnlockCoinsPass()) self.messageType.addMessageHandler(UnlockCoinsFailure()) self.manager = None
def handle(self, message): if not isinstance(message, FetchMintedRequest) and not isinstance(message, FetchMintedFailure) and not \ isinstance(message, FetchMintedWait) and not isinstance(message, FetchMintedAccept): if self.manager.messageType.globals.lastState == MessageHello: # we are now on a different message. Oops. raise MessageError('FetchMinted should have already been removed. It was not. Very odd. Message: %s' % message.identifier) self.manager.messageType.removeCallback(self.handle) else: print 'message class: %s' % message.__class__ raise MessageError('We somehow called FetchMinted.handle() but cannot be there. Message: %s' % message.identifier) if isinstance(message, FetchMintedRequest): self.request_id = self.manager.messageType.persistant.request_id # FIXME: Hack to ensure we try to mint things. Run the minting right now, if we have it self.manager.entity.attemptToMint() # this tries to mint everything waiting type, result = self.findRequest(self.request_id, self.manager.entity.credited_transactions) if type == 'ACCEPT': self.signatures = result self.manager.messageType.persistant.signatures = result self.__createAndOutput(FetchMintedAccept) elif type == 'WAIT': self.reason = result self.manager.messageType.persistant.reason = result self.__createAndOutput(FetchMintedWait) elif type == 'FAILURE': self.reason = result self.manager.messageType.persistant.reason = result self.__createAndOutput(FetchMintedFailure) else: raise MessageError('Received unknown type: %s' % type) elif isinstance(message, FetchMintedAccept): # we output this. Next step can only be Goodbye self.manager.messageType.removeCallback(self.handle) elif isinstance(message, FetchMintedFailure): #we output this. Next step can only be Goodbye self.manager.messageType.removeCallback(self.handle) elif isinstance(message, FetchMintedWait): # we output this. Next step can only be Goodbye self.manager.messageType.removeCallback(self.handle)
def startConversation(self, message, result): if isinstance(message, self.messages.LCR.__class__): self.setHandler(LockCoins(self, message)) elif isinstance(message, self.messages.UCR.__class__): self.setHandler(UnlockCoins(self, message)) else: raise MessageError("Message %s does not start a conversation" % message.identifier)
def createBlinds(self, dsdb_certificate, coins): if len(coins) == 0: raise MessageError('Can not blind no coins!') blinds = [] for c in coins: blinds.append(self.createBlind(dsdb_certificate, c)) self.manager.walletMessageType.persistant.blanks = blinds
def getCDD(self, cdds, blanks): """Returns the CDD for the blanks. Assumes only one CDD (Raise MessageError if multiple).""" try: currency_identifier = blanks[0].currency_identifier except IndexError: raise MessageError('No blanks') #FIXME: somehow allow multiple cdds? for b in blanks: if currency_identifier != b.currency_identifier: raise MessageError( 'This client is too stupid to deal with more than one currency.' ) if not cdds.has_key(currency_identifier): return 'Unknown issuer' else: return cdds[currency_identifier]
def _verifyLastState(self, state): """_verifyLastState is used to make sure that we are progressing properly through messages which can start at Hello. For any message which can start at Hello, perform a check to make sure that we have the required lastState in the manager. A lastState of None is the beginning. """ if not self.manager.lastMessageIdentifier in state: raise MessageError( 'Did not find expected last state. Found: %s, Wanted: %s' % (self.manager.lastMessageIdentifier, state))
def handle(self, message): if not isinstance(message, DSDBKeyRequest) and not isinstance(message, DSDBKeyPass): if self.manager.messageType.globals.lastState == MessageHello: # we are now on a different message. Oops. raise MessageError('DSDBKey should have already been removed. It was not. Very odd. Message: %s LastMessage: %s' % (message.identifier, self.manager.messageType.globals.lastState)) else: print 'message class: %s' % message.__class__ raise MessageError('We somehow called DSDBKey.handle() but cannot be there. Message: %s' % message.identifier) if isinstance(message, DSDBKeyRequest): self.dsdb_certificate = self.dsdbKey() self.manager.messageType.persistant.dsdb_certificate = self.dsdb_certificate self.__createAndOutput(DSDBKeyPass) elif isinstance(message, DSDBKeyPass): # we output this. Next step can only be Goodbye self.manager.messageType.removeCallback(self.handle)
def _verifyLastState(self, state): """_verifyLastState is used to make sure that we are progressing properly through messages which can start at Hello. For any message which can start at Hello, perform a check to make sure that we have the required lastState in the manager. A lastState of None is the beginning. """ return #FIXME: lastState isn't being set due to function calls. Figure this out later. (Note: not having this breaks verification) if not self.manager.lastMessageIdentifier in state: raise MessageError( 'Did not find expected last state. Found: %s, Wanted: %s' % (self.manager.lastMessageIdentifier, state))
def handle(self, message): if not isinstance(message, UnlockCoinsRequest) and not isinstance( message, UnlockCoinsPass) and not isinstance( message, UnlockCoinsFailure): if self.manager.messageType.globals.lastState == MessageHello: # we are now on a different message. Oops. raise MessageError( 'UnlockCoins should have already been removed. It was not. Very odd. Message: %s LastMessage: %s' % (message.identifier, self.manager.messageType.globals.lastState)) else: print 'message class: %s' % message.__class__ raise MessageError( 'We somehow called UnlockCoins.handle() but cannot be there. Message: %s' % message.identifier) if isinstance(message, UnlockCoinsRequest): self.transaction_id = self.manager.messageType.persistant.transaction_id self.type, self.result = self.unlock(self.transaction_id) if self.type == 'ACCEPT': self.manager.messageType.removeCallback(self.handle) self.__createAndOutput(UnlockCoinsPass) elif self.type == 'REJECT': transaction_id, self.reason = self.result if self.transaction_id != transaction_id: raise MessageError( 'transaction_id changed. Was: %s, Now: %s' % (self.transation_id, transaction_id)) self.manager.messageType.persistant.reason = self.reason self.manager.messageType.removeCallback(self.handle) self.__createAndOutput(UnlockCoinsFailure) else: raise MessageError('Received an impossible type: %s' % self.type) elif isinstance(message, UnlockCoinsPass) or isinstance( message, UnlockCoinsFailure): # we output this. Next step can only be Goodbye self.manager.messageType.removeCallback(self.handle)
def lock(self, dsdb_key_id, transaction_id, blanks, dsdb_key, dsdb_database, dsdb_requests, minting_keys_key_id, now): failure = False failures = [] blanksAndSerials = [] # FIXME: This code does not work well with threading. To fix, change testBlank to something closer to unblind with # possible errors for being unable to blind or a bad minting key. Then do the call to lockBlanks which then # tries one by one to lock the serials in the database. If it gets any failures, it unwinds the locks it has # done and gives the errors it came across. # # Actually, FIXME: Does the protocol allow us to just stop if we have bad keys in minting keys or are we supposed # just keep going coming up with all the errors we can find? if len(blanks) == 0: raise MessageError('request %s has no blinds' % request_id) if not self.validDSDBKeyID(dsdb_key_id, dsdb_key, now): return 'REJECT', 'Key ID of DSDB is unknown or expired' for b in blanks: type, result = self.testBlank(b, dsdb_key_id, dsdb_key, dsdb_database, dsdb_requests, minting_keys_key_id, now) if type == 'ACCEPT': blanksAndSerials.append( (b, result)) # Add the tuple of the blank and the serial elif type == 'REJECT': failure = True failures.append((b, result)) else: raise MessageError('Received impossible type: %s' % type) if failure: return 'REJECT', failures dsdb_lock_time = self.lockBlanks(transaction_id, blanksAndSerials, dsdb_key, dsdb_database, dsdb_requests, now) return 'ACCEPT', (transaction_id, dsdb_lock_time)
def startConversation(self, message, result): if isinstance(message, DSDBKeyRequest): self.setHandler(DSDBKey(self, message)) elif isinstance(message, FetchMintedRequest): self.setHandler(FetchMinted(self, message)) elif isinstance(message, MintRequest): self.setHandler(Mint(self, message)) elif isinstance(message, MintingKeyFetchDenomination) or isinstance(message, MintingKeyFetchKeyID): self.setHandler(MintingKey(self, message)) elif isinstance(message, RedeemCoinsRequest): self.setHandler(RedeemCoins(self, message)) else: raise MessageError("Message %s does not start a conversation" % message.identifier)
def resumeConversation(self, message, result): if isinstance(message, DSDBKeyPass): self.setHandler(DSDBKey(self, message)) elif isinstance(message, BlankReject) or isinstance( message, BlankFailure) or isinstance(message, BlankAccept): self.setHandler(Blank(self, message)) elif isinstance(message, CoinsReject) or isinstance( message, CoinsAccept): self.setHandler(Coins(self, message)) else: raise MessageError('Message %s does not continue a conversation' % message.identifier)
def handle(self, message): if not isinstance(message, LockCoinsRequest) and not isinstance( message, LockCoinsAccept) and not isinstance( message, LockCoinsFailure): if message.messageLayer.globals.lastState == MessageHello: # we are now on a different message. Oops. raise MessageError( 'LockCoins should have already been removed. It was not. Very odd. Message: %s LastMessage: %s' % (message.identifier, message.messageLayer.globals.lastState)) else: raise MessageError( 'We somehow called LockCoins.handle() but cannot be there. Message: %s' % message.identifier) self._verifyLastState(['BlankAndMintingKey', 'LOCK_COINS_REQUEST']) if isinstance(message, LockCoinsRequest): # we output this. Previous step was in BlankAndMintingKey print 'Got a LockCoinsRequest. I did not know we got these.' elif isinstance(message, LockCoinsAccept): self.dsdb_lock = self.manager.dsdbMessageType.persistant.dsdb_lock self.manager.persistant.dsdb_lock = self.dsdb_lock if not self.validDSDBLock(self.dsdb_lock, self.timeNow()): raise MessageError('Invalid DSDB Lock') self.manager.dsdbMessageType.removeCallback( self.handle ) #remove the callback to the DSDB. Not coming here again self._createAndOutputWallet(BlankAccept) elif isinstance(message, LockCoinsFailure): self.reason = self.manager.dsdbMessageType.persistant.reason # undo the damage and tell someone self.manager.failure(message, self) self._setLastState(message.identifier)
def redeem(self, transaction_id, target, coins, currency_description_document, minting_keys_key_id, dsdb_database, dsdb_requests, credited_transactions): """redeem checks the validity of the coins. redeem first checks the validity of the coins. It then verifies the target. Finally, it tries to redeem all the coins at once. This action first verifies then updates the DSDB. """ failure = False failures = [] if len(coins) == 0: raise MessageError('transaction %s has no coins' % transaction_id) if len(coins) != len(set(coins)): return 'REJECT', 'Sent two copies of the same coin!' #FIXME: This error isn't in the standard for c in coins: type, result = self.testCoin(c, transaction_id, currency_description_document, minting_keys_key_id) if type == 'ACCEPT': pass elif type == 'REJECT': failure = True failures.append( (coin, result) ) else: raise MessageError('Received impossible type: %s' % type) if failure: return 'REJECT', failures if not self.checkValidTarget(target, credited_transactions): return 'REJECT', 'Unknown target' type, result = self.redeemCoins(transaction_id, target, coins, dsdb_database, dsdb_requests, credited_transactions) if type == 'ACCEPT': return 'ACCEPT', None elif type == 'REJECT': return 'REJECT', result else: raise MessageError('Received impossible type: %s' % type)
def handle(self, message): if not isinstance(message, RedeemCoinsRequest) and not isinstance(message, RedeemCoinsAccept) and not isinstance(message, RedeemCoinsReject): if self.manager.messageType.globals.lastState == MessageHello: # we are now on a different message. Oops. raise MessageError('RedeemCoins should have already been removed. It was not. Very odd. Message: %s LastMessage: %s' % (message.identifier, self.manager.messageType.globals.lastState)) else: print 'message class: %s' % message.__class__ raise MessageError('We somehow called RedeemCoins.handle() but cannot be there. Message: %s' % message.identifier) if isinstance(message, RedeemCoinsRequest): self.transaction_id = self.manager.messageType.persistant.transaction_id self.target = self.manager.messageType.persistant.target self.coins = self.manager.messageType.persistant.coins type, result = self.redeem(self.transaction_id, self.target, self.coins, self.manager.entity.cdd, self.manager.entity.minting_keys_key_id, self.manager.entity.dsdb_database, self.manager.entity.dsdb_requests, self.manager.entity.credited_transactions) if type == 'ACCEPT': self.manager.messageType.removeCallback(self.handle) self.__createAndOutput(RedeemCoinsAccept) elif type == 'REJECT': self.manager.messageType.persistant.reason = result self.manager.messageType.removeCallback(self.handle) self.__createAndOutput(RedeemCoinsReject) else: raise MessageError('Received an impossible type: %s' % self.type) elif isinstance(message, RedeemCoinsAccept) or isinstance(message, RedeemCoinReject): # we output this. Next step can only be Goodbye self.manager.messageType.removeCallback(self.handle) else: raise MessageError('Trying to handle a message we are not designed for: %s' % message.identifier)
def __init__(self, walletMessageType, entity, coins): self.walletMessageType = walletMessageType self.entity = entity #self.isMessageType = isMessageType if not self.walletMessageType.globals.status.can( MessageStatuses.PrivilegeClient): raise MessageError( 'given messageType does not have PrivilegeClient') class messages: pass self.walletMessages = messages() self.isMessages = messages() del messages # All the responses we can get from the IS self.isMessages.DKP = DSDBKeyPass(self.resumeConversation) # All the responses we can get from the other wallet self.walletMessages.BR = BlankReject(self.resumeConversation) self.walletMessages.BF = BlankFailure(self.resumeConversation) self.walletMessages.BA = BlankAccept(self.resumeConversation) self.walletMessages.CR = CoinsReject(self.resumeConversation) self.walletMessages.CA = CoinsAccept(self.resumeConversation) # Add handlers for all the messages using walletMessages if continues conversation self.walletMessageType.addMessageHandler(BlankPresent()) self.walletMessageType.addMessageHandler(self.walletMessages.BR) self.walletMessageType.addMessageHandler(self.walletMessages.BF) self.walletMessageType.addMessageHandler(self.walletMessages.BA) self.walletMessageType.addMessageHandler(CoinsRedeem()) self.walletMessageType.addMessageHandler(self.walletMessages.CR) self.walletMessageType.addMessageHandler(self.walletMessages.CA) self.coins = coins class state: pass self.persistant = state() del state self.lastMessageIdentifier = None
def checkValidObfuscatedBlanksAndKnownIssuers(self, blanks, cdds, mintingKeysKeyID): failure = False failures = [] if len(blanks) == 0: raise MessageError('Need atleast one blank!') for b in blanks: if not self.checkValidObfuscatedBlank(b, cdds, mintingKeysKeyID): failure = True failures.append((b, 'Malformed blank')) elif not self.checkKnownIssuer(b, self.manager.entity.cdds): failure = True failures.append((b, 'Unknown issuer')) if failure: return 'FAILED', failures else: return 'PASS', None