def handle_receipt(self, msg): """Handle a receipt message from our merchant""" ourId, msg = Basic.read_long(msg) if not self.read_payment_tokens(msg): return #check if we are waiting on new tokens: if len(self.pendingPayments) > 0 and ((self.pendingPayments[0][0] + self.pendingPayments[0][1])/Globals.CELLS_PER_PAYMENT) <= len(self.pendingPayments): readTokens, writeTokens, paymentId = self.pendingPayments.pop(0) self.start_bank_process(readTokens, writeTokens, paymentId) #and trigger any callbacks waiting for this receipt paymentDeferred = self.paymentDeferreds[ourId] del self.paymentDeferreds[ourId] paymentDeferred.callback(True)
def handle_payment(self, msg): """Unpack, process, and respond to a payment message. @param msg: the payment message from the origin. @type msg: str""" #if there are any failures, log them, and close the circuit: try: #read the PAR protocol version: version, msg = Basic.read_byte(msg) assert version == 1, "currently only accept PAR version 1" readTokens, msg = Basic.read_int(msg) writeTokens, msg = Basic.read_int(msg) #read their request ID too theirId, msg = Basic.read_long(msg) #read the number of coins: numCoins, msg = Basic.read_byte(msg) #read each coin: creditsEarned = 0 requests = [] for i in range(0, numCoins): #what type of coin is this? coinType, msg = Basic.read_byte(msg) #we only accept acoins for now: assert coinType == PaymentStream.COIN_TYPES[ 'A'], "bad coin type" #get the matching request: requestId, msg = Basic.read_long(msg) requests.append(requestId) assert len(msg) % numCoins == 0, "bad payment message length" coinLen = len(msg) / numCoins for requestId in requests: #if this is not true, there wont even be another part to the response assert Basic.read_byte(msg)[0] == ord( '0'), "bad leading byte in payment message" blob, msg = msg[:coinLen], msg[coinLen:] request = self.requests[requestId] del self.requests[requestId] code, sig = Basic.read_byte(blob) #validate the ACoin coin = BankMessages.parse_acoin_response( self.bank, sig, request) if not coin: raise Exception("Invalid ACoin sent for payment!") #success! creditsEarned += coin.get_expected_value() coin.originCircuit = self self.bank.on_earned_coin(coin) receiptMessageDeferred = self.send_receipt_message( theirId, numCoins) if not receiptMessageDeferred: return #check that they paid enough: requestedTokens = readTokens + writeTokens paidTokens = creditsEarned * Globals.CELLS_PER_PAYMENT if paidTokens < requestedTokens: raise Exception("Relays asked for %s, but only paid for %s" % (requestedTokens, paidTokens)) #inform Tor that we got a payment message: addTokensDeferred = self.add_tokens(readTokens, writeTokens) if not addTokensDeferred: return def response(result): if result: read, write = result log_msg( "%s paid us %s for exit stream, now %d / %d" % (Basic.clean(self.baseCircuit.prevHexId[:4]), creditsEarned, read, write), 3, "par") addTokensDeferred.addCallback(response) except Exception, error: log_ex(error, "Got bad PAR message") self.close()
def handle_payment(self, msg): """Unpack, process, and respond to a payment message. @param msg: the payment message from the origin. @type msg: str""" #if there are any failures, log them, and close the circuit: try: #read the PAR protocol version: version, msg = Basic.read_byte(msg) assert version == 1, "currently only accept PAR version 1" readTokens, msg = Basic.read_int(msg) writeTokens, msg = Basic.read_int(msg) #read their request ID too theirId, msg = Basic.read_long(msg) #read the number of coins: numCoins, msg = Basic.read_byte(msg) #read each coin: creditsEarned = 0 requests = [] for i in range(0, numCoins): #what type of coin is this? coinType, msg = Basic.read_byte(msg) #we only accept acoins for now: assert coinType == PaymentStream.COIN_TYPES['A'], "bad coin type" #get the matching request: requestId, msg = Basic.read_long(msg) requests.append(requestId) assert len(msg) % numCoins == 0, "bad payment message length" coinLen = len(msg) / numCoins for requestId in requests: #if this is not true, there wont even be another part to the response assert Basic.read_byte(msg)[0] == ord('0'), "bad leading byte in payment message" blob, msg = msg[:coinLen], msg[coinLen:] request = self.requests[requestId] del self.requests[requestId] code, sig = Basic.read_byte(blob) #validate the ACoin coin = BankMessages.parse_acoin_response(self.bank, sig, request) if not coin: raise Exception("Invalid ACoin sent for payment!") #success! creditsEarned += coin.get_expected_value() coin.originCircuit = self self.bank.on_earned_coin(coin) receiptMessageDeferred = self.send_receipt_message(theirId, numCoins) if not receiptMessageDeferred: return #check that they paid enough: requestedTokens = readTokens + writeTokens paidTokens = creditsEarned * Globals.CELLS_PER_PAYMENT if paidTokens < requestedTokens: raise Exception("Relays asked for %s, but only paid for %s" % (requestedTokens, paidTokens)) #inform Tor that we got a payment message: addTokensDeferred = self.add_tokens(readTokens, writeTokens) if not addTokensDeferred: return def response(result): if result: read, write = result log_msg("%s paid us %s for exit stream, now %d / %d" % (Basic.clean(self.baseCircuit.prevHexId[:4]), creditsEarned, read, write), 3, "par") addTokensDeferred.addCallback(response) except Exception, error: log_ex(error, "Got bad PAR message") self.close()