ソースを参照

avoid money created out of thin air

Malte Kraus 8 年 前
コミット
cfd267ad8a
2 ファイル変更47 行追加1 行削除
  1. 27 1
      src/transaction.py
  2. 20 0
      tests/test_verifications.py

+ 27 - 1
src/transaction.py

@@ -167,11 +167,37 @@ 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
+
+        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
+            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
+
+        if input_amount < output_amount:
+            logging.warning("Transferred amounts are larger than the inputs.")
+            return False
+        return True
+
     def verify(self, chain: 'Blockchain', other_trans: 'Set[Transaction]',
                prev_block: 'Block'=None) -> bool:
         """ Verifies that this transaction is completely valid. """
         return self._verify_single_spend(chain, other_trans, prev_block) and \
-               self._verify_signatures(chain)
+               self._verify_signatures(chain) and self._verify_amounts(chain)
 
 from .blockchain import Blockchain
 from .block import Block

+ 20 - 0
tests/test_verifications.py

@@ -43,3 +43,23 @@ def test_double_spend3(chain, reward_trans):
     key = reward_trans.targets[0].recipient_pk
     trans1.sign([key, key])
     extend_blockchain(chain, [trans1], verify_res=False)
+
+@trans_test
+def test_create_money1(chain, reward_trans):
+    key = reward_trans.targets[0].recipient_pk
+    # create a transaction where the receiver gets 1 more coin than the sender puts in
+    target = TransactionTarget(key, reward_trans.targets[0].amount + 1)
+    trans1 = Transaction([trans_as_input(reward_trans)], [target])
+    trans1.sign([key])
+    extend_blockchain(chain, [trans1], verify_res=False)
+
+@trans_test
+def test_create_money2(chain, reward_trans):
+    # create a transaction where we create money by sending a negative amount N to someone
+    # and the inputs + N to us
+    key = reward_trans.targets[0].recipient_pk
+    target1 = TransactionTarget(key, -10)
+    target2 = TransactionTarget(key, reward_trans.targets[0].amount + 10)
+    trans1 = Transaction([trans_as_input(reward_trans)], [target1, target2])
+    trans1.sign([key])
+    extend_blockchain(chain, [trans1], verify_res=False)