def start_payment_loop(self): coin = Bank.get().get_acoins(1) if not coin: log_msg("No ACoins left!") return coin = coin[0] #generate ACoin request request = BankMessages.make_acoin_request(Bank.get(), Bank.get().currentACoinInterval, 1) #make the message: bankMsg = Basic.write_byte(1) bankMsg += coin.write_binary() + request.msg key = EncryptedDatagram.ClientSymKey(Bank.get().PUBLIC_KEY) bankMsg = Basic.write_byte(1) + key.encrypt(Basic.write_byte(3) + bankMsg) payment = UDPPayment.UDPPayment(Bank.get(), bankMsg) paymentDeferred = payment.get_deferred() 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) paymentDeferred.addCallback(success) def failure(error): self.start_payment_loop() log_ex(error, "Failure during test?") self.failures += 1 paymentDeferred.addErrback(failure)
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 generate_payment_request_message(self): """Create a payment request object, store it for later, increase ID, and create the message associated with it @returns: str (message for payment request)""" #REFACTOR cost = self.torApp.get_relay().get_cost() interval = self.bank.currentACoinInterval #generate ACoin request request = BankMessages.make_acoin_request(self.bank, interval, cost) request.id = self.currentRequestId self.requests[request.id] = request self.currentRequestId += 1 return Basic.write_long(request.id) + request.msg + Globals.PRIVATE_KEY.sign(request.msg)
def __init__(self, bank, value, number): BankMessages.BankConnectionFactory.__init__(self, bank) #: the value for each ACoin to have, individually self.value = value #: a list of all ACoinRequests self.requests = [] #: how many coins to request self.number = number interval = self.bank.currentACoinInterval for i in range(0, number): #store the values for later: self.requests.append(BankMessages.make_acoin_request(self.bank, interval, value))
def generate_payment_request_message(self): """Create a payment request object, store it for later, increase ID, and create the message associated with it @returns: str (message for payment request)""" #REFACTOR cost = self.torApp.get_relay().get_cost() interval = self.bank.currentACoinInterval #generate ACoin request request = BankMessages.make_acoin_request(self.bank, interval, cost) request.id = self.currentRequestId self.requests[request.id] = request self.currentRequestId += 1 return Basic.write_long( request.id) + request.msg + Globals.PRIVATE_KEY.sign(request.msg)
def start_payment_loop(self): coin = Bank.get().get_acoins(1) if not coin: log_msg("No ACoins left!") return coin = coin[0] #generate ACoin request request = BankMessages.make_acoin_request( Bank.get(), Bank.get().currentACoinInterval, 1) #make the message: bankMsg = Basic.write_byte(1) bankMsg += coin.write_binary() + request.msg key = EncryptedDatagram.ClientSymKey(Bank.get().PUBLIC_KEY) bankMsg = Basic.write_byte(1) + key.encrypt( Basic.write_byte(3) + bankMsg) payment = UDPPayment.UDPPayment(Bank.get(), bankMsg) paymentDeferred = payment.get_deferred() 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) paymentDeferred.addCallback(success) def failure(error): self.start_payment_loop() log_ex(error, "Failure during test?") self.failures += 1 paymentDeferred.addErrback(failure)
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()