def stringReceived(self, encryptedMsg): self.responseReceived = True self.transport.loseConnection() blob = self.factory.bank.decrypt_message(encryptedMsg) log_msg("ACoin REQUEST response received.", 4) responseCode, blob = Basic.read_byte(blob) #we had enough credits in our account if responseCode == 0: (newBalance, number), coins = Basic.read_message('!II', blob) #update the balance self.factory.bank.on_new_balance_from_bank(newBalance) acoinStrFormat = "%ss" % (Globals.ACOIN_KEY_BYTES) format = '!' + (acoinStrFormat * number) sigs = list(struct.unpack(format, coins)) while len(self.factory.requests) > 0: request = self.factory.requests.pop(0) sig = sigs.pop(0) coin = BankMessages.parse_acoin_response(self.factory.bank, sig, request, ProgramState.DEBUG) if coin: self.factory.bank.add_acoin(coin) else: log_msg("Got an invalid ACoin from the bank!?", 3) #the bank could not check out the coins because our account doesn't have enough credits! else: (newBalance,), blob = Basic.read_message('!I', blob) self.factory.bank.on_new_balance_from_bank(newBalance)
def success(result, request=request): log_msg("success") self.payments += 1 # self.start_payment_loop() #validate the ACoin code, sig = Basic.read_byte(result) coin = BankMessages.parse_acoin_response(Bank.get(), sig, request, False) if not coin: log_msg("Invalid ACoin sent for payment!") else: Bank.get().on_earned_coin(coin)
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()