Kaynağa Gözat

implement transaction fees

Malte Kraus 8 yıl önce
ebeveyn
işleme
b666474c36
2 değiştirilmiş dosya ile 23 ekleme ve 17 silme
  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 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. """
         if self.hash == GENESIS_BLOCK_HASH:
             return True
@@ -154,7 +154,7 @@ class Block:
             return False
         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. """
         if self.hash == GENESIS_BLOCK_HASH:
             return True
@@ -176,12 +176,15 @@ class Block:
             if not t.verify(chain, trans_set - {t}, prev_block):
                 return False
         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")
                 return False
         return True
 
-    def verify(self, chain):
+    def verify(self, chain: 'Blockchain'):
         """ Verifies this block contains only valid data consistent with the given block chain. """
         if self.height == 0 and self.hash != GENESIS_BLOCK_HASH:
             logging.warning("only the genesis block may have height=0")

+ 16 - 13
src/transaction.py

@@ -178,30 +178,33 @@ class Transaction:
                 return False
         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
         for inp in self.inputs:
             trans = chain.get_transaction_by_hash(inp.transaction_hash)
             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
         output_amount = 0
         for outp in self.targets:
-            if outp.amount <= 0:
-                logging.warning("Transferred amounts must be positive.")
-                return False
             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.")
             return False
+        for outp in self.targets:
+            if outp.amount <= 0:
+                logging.warning("Transferred amounts must be positive.")
+                return False
         return True
 
     def verify(self, chain: 'Blockchain', other_trans: 'Set[Transaction]',