Просмотр исходного кода

handle invalid transactions better

Malte Kraus 8 лет назад
Родитель
Сommit
a51e625830
3 измененных файлов с 12 добавлено и 2 удалено
  1. 6 1
      src/chainbuilder.py
  2. 2 1
      src/mining.py
  3. 4 0
      src/transaction.py

+ 6 - 1
src/chainbuilder.py

@@ -15,6 +15,8 @@ class ChainBuilder:
 
         self.block_cache = { GENESIS_BLOCK_HASH: GENESIS_BLOCK }
         self.unconfirmed_transactions = {}
+        # TODO: we want this to be sorted by some function of rewards and age
+        # TODO: we want two lists, one with known valid, unapplied transactions, the other with all known transactions (with some limit)
 
         self.chain_change_handlers = []
 
@@ -37,9 +39,12 @@ class ChainBuilder:
         Does all the housekeeping that needs to be done when a new longest chain is found.
         """
         self.primary_block_chain = chain
+        keys = set()
         for (hash_val, trans) in self.unconfirmed_transactions.items():
             if not trans.verify(chain):
-                del self.unconfirmed_transactions[hash_val]
+                keys.add(hash_val)
+        for hash_val in keys:
+            del self.unconfirmed_transactions[hash_val]
 
         for handler in self.chain_change_handlers:
             handler()

+ 2 - 1
src/mining.py

@@ -47,5 +47,6 @@ class Miner:
         primary chain changes.
         """
         chain = self.chainbuilder.primary_block_chain
-        block = mining_strategy.create_block(chain, self.chainbuilder.unconfirmed_transactions.values(), self.reward_pubkey)
+        transactions = [t for t in self.chainbuilder.unconfirmed_transactions if t.verify(chain)]
+        block = mining_strategy.create_block(chain, transactions, self.reward_pubkey)
         self.start_mining(block)

+ 4 - 0
src/transaction.py

@@ -102,12 +102,16 @@ class Transaction:
     def _verify_single_sig(self, sig: str, inp: TransactionInput, chain: Blockchain):
         """ Verifies the signature on a single input. """
         trans = chain.get_transaction_by_hash(inp.transaction_hash)
+        if trans is None:
+            return False
         sender_pk = trans.targets[inp.output_idx].recipient_pk
         return sender_pk.verify_sign(self.get_hash(), sig)
 
 
     def _verify_single_spend(self, chain: Blockchain, prev_block: Block):
         """ Verifies that all inputs have not been spent yet. """
+        if len(self.inputs) != len(set(self.inputs)):
+            return False
         for i in self.inputs:
             if not chain.is_coin_still_valid(i, prev_block):
                 return False