diff --git a/lib/ucoinpy/documents/block.py b/lib/ucoinpy/documents/block.py index 031c69f1d3e7da54dde37631930a32bcda4a97cc..873f404d09bc74de170d779aa1145ac6968863f1 100644 --- a/lib/ucoinpy/documents/block.py +++ b/lib/ucoinpy/documents/block.py @@ -11,6 +11,7 @@ from .membership import Membership from .transaction import Transaction import re +import logging class Block(Document): @@ -104,7 +105,7 @@ BOTTOM_SIGNATURE self.transactions = transactions @classmethod - def from_signed_raw(cls, raw, signature=None): + def from_signed_raw(cls, raw): lines = raw.splitlines(True) n = 0 @@ -211,9 +212,19 @@ BOTTOM_SIGNATURE if Block.re_transactions.match(lines[n]): n = n + 1 while not Block.re_signature.match(lines[n]): - transaction = Transaction.from_compact(version, lines[n]) + tx_lines = "" + header_data = Transaction.re_header.match(lines[n]) + version = int(header_data.group(1)) + issuers_num = int(header_data.group(2)) + inputs_num = int(header_data.group(3)) + outputs_num = int(header_data.group(4)) + has_comment = int(header_data.group(5)) + tx_max = n+issuers_num*2+inputs_num+outputs_num+has_comment+1 + for i in range(n, tx_max): + tx_lines += lines[n] + n = n + 1 + transaction = Transaction.from_compact(version, tx_lines) transactions.append(transaction) - n = n + 1 signature = Block.re_signature.match(lines[n]).group(1) diff --git a/lib/ucoinpy/documents/transaction.py b/lib/ucoinpy/documents/transaction.py index 24989c069c9a50fee2af52e82650882727e83c27..a69b4a28ee47fe961155b2b08c651a6f4c2ebd49 100644 --- a/lib/ucoinpy/documents/transaction.py +++ b/lib/ucoinpy/documents/transaction.py @@ -7,7 +7,6 @@ Created on 2 déc. 2014 from . import Document import re - class Transaction(Document): ''' Document format : @@ -45,7 +44,7 @@ SIGNATURE re_issuers = re.compile("Issuers:\n") re_inputs = re.compile("Inputs:\n") re_outputs = re.compile("Outputs:\n") - re_compact_comment = re.compile("-----@@@-----([^\n]+)\n") + re_compact_comment = re.compile("([^\n]+)\n") re_comment = re.compile("Comment:(?:)?([^\n]*)\n") re_pubkey = re.compile("([1-9A-Za-z][^OIl]{42,45})\n") @@ -71,13 +70,13 @@ SIGNATURE issuers_num = int(header_data.group(2)) inputs_num = int(header_data.group(3)) outputs_num = int(header_data.group(4)) + has_comment = int(header_data.group(5)) n = n + 1 issuers = [] inputs = [] outputs = [] signatures = [] - logging.debug(compact) for i in range(0, issuers_num): issuer = Transaction.re_pubkey.match(lines[n]).group(1) issuers.append(issuer) @@ -94,7 +93,7 @@ SIGNATURE n = n + 1 comment = None - if Transaction.re_comment.match(lines[n]): + if has_comment == 1: comment = Transaction.re_compact_comment.match(lines[n]).group(1) n = n + 1 diff --git a/src/cutecoin/core/account.py b/src/cutecoin/core/account.py index 27c0c9efbb9a4a3599970237d83d85009fca3d51..c5e00b1acd20cc29e0b4ee22a27e507938ccb081 100644 --- a/src/cutecoin/core/account.py +++ b/src/cutecoin/core/account.py @@ -143,14 +143,21 @@ class Account(object): received = [] for w in self.wallets: for t in w.transactions_received(community): - received.append(t) + # Lets remove transactions from our own wallets + pubkeys = [wallet.pubkey for wallet in self.wallets] + if t.issuers[0] not in pubkeys: + received.append(t) return received def transactions_sent(self, community): sent = [] for w in self.wallets: for t in w.transactions_sent(community): - sent.append(t) + # Lets remove transactions to our own wallets + pubkeys = [wallet.pubkey for wallet in self.wallets] + outputs = [o for o in t.outputs if o.pubkey not in pubkeys] + if len(outputs) > 0: + sent.append(t) return sent def member_of(self, community): diff --git a/src/cutecoin/core/wallet.py b/src/cutecoin/core/wallet.py index 0aa4b721e626cf11f250e8bf24ce69bffb9f8be7..92f41a39907fb4df9c83fe468604a726497940f1 100644 --- a/src/cutecoin/core/wallet.py +++ b/src/cutecoin/core/wallet.py @@ -6,12 +6,62 @@ Created on 1 févr. 2014 from ucoinpy import PROTOCOL_VERSION from ucoinpy.api import bma +from ucoinpy.documents.block import Block from ucoinpy.documents.transaction import InputSource, OutputSource, Transaction from ucoinpy.key import SigningKey from ..tools.exceptions import NotEnoughMoneyError import logging +class Cache(): + def __init__(self, wallet): + self.latest_block = 0 + self.wallet = wallet + self.tx_sent = [] + self.tx_received = [] + + def from_json(self, data): + pass + + def to_json(self): + data_received = [] + for r in self.tx_received: + data_received.append({'amount': r.amount, + 'pubkey': r.pubkey}) + return {'received': data_received} + + def latest_sent(self, community): + self._refresh(community) + return self.tx_sent + + def latest_received(self, community): + self._refresh(community) + return self.tx_received + + def _refresh(self, community): + current_block = community.request(bma.blockchain.Current) + with_tx = community.request(bma.blockchain.TX) + # We parse only blocks with transactions + parsed_blocks = reversed(range(self.latest_block, + current_block['number'])) + parsed_blocks = [n for n in parsed_blocks if n in with_tx['result']['blocks']] + for block_number in parsed_blocks: + block = community.request(bma.blockchain.Block, + req_args={'number': block_number}) + signed_raw = "{0}{1}\n".format(block['raw'], block['signature']) + block_doc = Block.from_signed_raw(signed_raw) + for tx in block_doc.transactions: + for o in tx.outputs: + if o.pubkey == self.wallet.pubkey: + self.tx_received.append(tx) + + for i in tx.issuers: + if i == self.wallet.pubkey: + self.tx_sent.append(tx) + + self.latest_block = current_block['number'] + + class Wallet(object): ''' A wallet is used to manage money with a unique key. @@ -25,7 +75,8 @@ class Wallet(object): self.walletid = walletid self.pubkey = pubkey self.name = name - self.inputs_cache = None + self.available_inputs = None + self.cache = Cache(self) @classmethod def create(cls, walletid, salt, password, name): @@ -70,16 +121,16 @@ class Wallet(object): inputs = [] block = community.request(bma.blockchain.Current) sources = self.sources(community) - if not self.inputs_cache: - self.inputs_cache = (block['number'], sources) - elif self.inputs_cache[0] < block['number']: - self.inputs_cache = (block['number'], sources) + if not self.available_inputs: + self.available_inputs = (block['number'], sources) + elif self.available_inputs[0] < block['number']: + self.available_inputs = (block['number'], sources) - for s in self.inputs_cache[1]: + for s in self.available_inputs[1]: value += s.amount s.index = 0 inputs.append(s) - self.inputs_cache[1].remove(s) + self.available_inputs[1].remove(s) if value >= amount: return inputs @@ -123,7 +174,8 @@ class Wallet(object): post_args={'transaction': tx.signed_raw()}) def sources(self, community): - data = community.request(bma.tx.Sources, req_args={'pubkey': self.pubkey}) + data = community.request(bma.tx.Sources, + req_args={'pubkey': self.pubkey}) tx = [] for s in data['sources']: tx.append(InputSource.from_bma(s)) @@ -131,11 +183,11 @@ class Wallet(object): #TODO: Build a cache of latest transactions def transactions_sent(self, community): - return [] + return self.cache.latest_sent(community) #TODO: Build a cache of latest transactions def transactions_received(self, community): - return [] + return self.cache.latest_received(community) def get_text(self, community): return "%s : \n \ diff --git a/src/cutecoin/models/received.py b/src/cutecoin/models/received.py index bb57984d90d5c9ff150c879079c430238878949b..056da3b268e452b5110c294522789ac5daafd7a9 100644 --- a/src/cutecoin/models/received.py +++ b/src/cutecoin/models/received.py @@ -5,6 +5,7 @@ Created on 5 févr. 2014 ''' import logging +from ..core.person import Person from PyQt5.QtCore import QAbstractListModel, Qt @@ -29,7 +30,14 @@ class ReceivedListModel(QAbstractListModel): if role == Qt.DisplayRole: row = index.row() transactions = self.account.transactions_received(self.community) - value = transactions[row].get_receiver_text() + amount = 0 + for o in transactions[row].outputs: + pubkeys = [w.pubkey for w in self.account.wallets] + if o.pubkey in pubkeys: + amount += o.amount + pubkey = transactions[row].issuers[0] + sender = Person.lookup(pubkey, self.community) + value = "{0} from {1}".format(amount, sender.name) return value def flags(self, index): diff --git a/src/cutecoin/models/sent.py b/src/cutecoin/models/sent.py index 0bbbfeea5f3c00075f2d26d5f26f38168c626335..25bdb1fa020b8e1e7bbaa73bc249917450dd28ad 100644 --- a/src/cutecoin/models/sent.py +++ b/src/cutecoin/models/sent.py @@ -5,6 +5,7 @@ Created on 5 févr. 2014 ''' import logging +from ..core.person import Person from PyQt5.QtCore import QAbstractListModel, Qt @@ -30,7 +31,15 @@ class SentListModel(QAbstractListModel): if role == Qt.DisplayRole: row = index.row() transactions = self.account.transactions_sent(self.community) - value = transactions[row].get_sender_text() + amount = 0 + outputs = [] + for o in transactions[row].outputs: + pubkeys = [w.pubkey for w in self.account.wallets] + if o.pubkey not in pubkeys: + outputs.append(o) + amount += o.amount + receiver = Person.lookup(outputs[0].pubkey, self.community) + value = "{0} to {1}".format(amount, receiver.name) return value def flags(self, index):