Browse Source

implement transaction fees

Malte Kraus 8 years ago
parent
commit
b666474c36
2 changed files with 23 additions and 17 deletions
  1. 7 4
      src/block.py
  2. 16 13
      src/transaction.py

+ 7 - 4
src/block.py

@@ -141,7 +141,7 @@ class Block:
             return False
             return False
         return True
         return True
 
 
-    def verify_prev_block(self, chain):
+    def verify_prev_block(self, chain: 'Blockchain'):
         """ Verify the previous block pointer points to a valid block in the given block chain. """
         """ Verify the previous block pointer points to a valid block in the given block chain. """
         if self.hash == GENESIS_BLOCK_HASH:
         if self.hash == GENESIS_BLOCK_HASH:
             return True
             return True
@@ -154,7 +154,7 @@ class Block:
             return False
             return False
         return True
         return True
 
 
-    def verify_transactions(self, chain):
+    def verify_transactions(self, chain: 'Blockchain'):
         """ Verify all transaction in this block are valid in the given block chain. """
         """ Verify all transaction in this block are valid in the given block chain. """
         if self.hash == GENESIS_BLOCK_HASH:
         if self.hash == GENESIS_BLOCK_HASH:
             return True
             return True
@@ -176,12 +176,15 @@ class Block:
             if not t.verify(chain, trans_set - {t}, prev_block):
             if not t.verify(chain, trans_set - {t}, prev_block):
                 return False
                 return False
         if mining_reward is not None:
         if mining_reward is not None:
-            if sum(map(lambda t: t.amount, mining_reward.targets)) > chain.compute_blockreward(chain.get_block_by_hash(self.prev_block_hash)):
+            fees = sum(t.get_transaction_fee(chain) for t in self.transactions if t is not mining_reward)
+            reward = chain.compute_blockreward(chain.get_block_by_hash(self.prev_block_hash))
+            used = sum(t.amount for t in mining_reward.targets)
+            if used > fees + reward:
                 logging.warning("mining reward is too large")
                 logging.warning("mining reward is too large")
                 return False
                 return False
         return True
         return True
 
 
-    def verify(self, chain):
+    def verify(self, chain: 'Blockchain'):
         """ Verifies this block contains only valid data consistent with the given block chain. """
         """ Verifies this block contains only valid data consistent with the given block chain. """
         if self.height == 0 and self.hash != GENESIS_BLOCK_HASH:
         if self.height == 0 and self.hash != GENESIS_BLOCK_HASH:
             logging.warning("only the genesis block may have height=0")
             logging.warning("only the genesis block may have height=0")

+ 16 - 13
src/transaction.py

@@ -178,30 +178,33 @@ class Transaction:
                 return False
                 return False
         return True
         return True
 
 
-    def _verify_amounts(self, chain: 'Blockchain') -> bool:
-        """
-        Verifies that the receivers get less or equal money than the senders.
-        """
-        if not self.inputs:
-            return True
-
+    def get_transaction_fee(self, chain: 'Blockchain'):
+        """ Computes the transaction fees this transaction provides. """
         input_amount = 0
         input_amount = 0
         for inp in self.inputs:
         for inp in self.inputs:
             trans = chain.get_transaction_by_hash(inp.transaction_hash)
             trans = chain.get_transaction_by_hash(inp.transaction_hash)
             if trans is None:
             if trans is None:
-                logging.warning("Referenced transaction input could not be found.")
-                return False
+                raise ValueError("Referenced transaction input could not be found.")
             input_amount += trans.targets[inp.output_idx].amount
             input_amount += trans.targets[inp.output_idx].amount
         output_amount = 0
         output_amount = 0
         for outp in self.targets:
         for outp in self.targets:
-            if outp.amount <= 0:
-                logging.warning("Transferred amounts must be positive.")
-                return False
             output_amount += outp.amount
             output_amount += outp.amount
+        return input_amount - output_amount
 
 
-        if input_amount < output_amount:
+    def _verify_amounts(self, chain: 'Blockchain') -> bool:
+        """
+        Verifies that the receivers get less or equal money than the senders.
+        """
+        if not self.inputs:
+            return True
+
+        if self.get_transaction_fee(chain) < 0:
             logging.warning("Transferred amounts are larger than the inputs.")
             logging.warning("Transferred amounts are larger than the inputs.")
             return False
             return False
+        for outp in self.targets:
+            if outp.amount <= 0:
+                logging.warning("Transferred amounts must be positive.")
+                return False
         return True
         return True
 
 
     def verify(self, chain: 'Blockchain', other_trans: 'Set[Transaction]',
     def verify(self, chain: 'Blockchain', other_trans: 'Set[Transaction]',