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

do not send block hashes through the network

Malte Kraus 8 лет назад
Родитель
Сommit
aef2d573fa
3 измененных файлов с 15 добавлено и 31 удалено
  1. 15 23
      src/block.py
  2. 0 6
      tests/test_verifications.py
  3. 0 2
      tests/utils.py

+ 15 - 23
src/block.py

@@ -36,8 +36,7 @@ class Block:
     :vartype transactions: List[Transaction]
     :vartype transactions: List[Transaction]
     """
     """
 
 
-    def __init__(self, hash_val, prev_block_hash, time, nonce, height, received_time, difficulty, transactions, merkle_root_hash=None):
-        self.hash = hash_val
+    def __init__(self, prev_block_hash, time, nonce, height, received_time, difficulty, transactions, merkle_root_hash=None):
         self.prev_block_hash = prev_block_hash
         self.prev_block_hash = prev_block_hash
         self.merkle_root_hash = merkle_root_hash
         self.merkle_root_hash = merkle_root_hash
         self.time = time
         self.time = time
@@ -46,11 +45,11 @@ class Block:
         self.received_time = received_time
         self.received_time = received_time
         self.difficulty = difficulty
         self.difficulty = difficulty
         self.transactions = transactions
         self.transactions = transactions
+        self.hash = self._get_hash()
 
 
     def to_json_compatible(self):
     def to_json_compatible(self):
         """ Returns a JSON-serializable representation of this object. """
         """ Returns a JSON-serializable representation of this object. """
         val = {}
         val = {}
-        val['hash'] = hexlify(self.hash).decode()
         val['prev_block_hash'] = hexlify(self.prev_block_hash).decode()
         val['prev_block_hash'] = hexlify(self.prev_block_hash).decode()
         val['merkle_root_hash'] = hexlify(self.merkle_root_hash).decode()
         val['merkle_root_hash'] = hexlify(self.merkle_root_hash).decode()
         val['time'] = self.time.strftime("%Y-%m-%dT%H:%M:%S.%f UTC")
         val['time'] = self.time.strftime("%Y-%m-%dT%H:%M:%S.%f UTC")
@@ -64,8 +63,7 @@ class Block:
     def from_json_compatible(cls, val):
     def from_json_compatible(cls, val):
         """ Create a new block from its JSON-serializable representation. """
         """ Create a new block from its JSON-serializable representation. """
         from .transaction import Transaction
         from .transaction import Transaction
-        return cls(unhexlify(val['hash']),
-                   unhexlify(val['prev_block_hash']),
+        return cls(unhexlify(val['prev_block_hash']),
                    datetime.strptime(val['time'], "%Y-%m-%dT%H:%M:%S.%f UTC"),
                    datetime.strptime(val['time'], "%Y-%m-%dT%H:%M:%S.%f UTC"),
                    int(val['nonce']),
                    int(val['nonce']),
                    int(val['height']),
                    int(val['height']),
@@ -85,16 +83,12 @@ class Block:
             ts = datetime.utcnow()
             ts = datetime.utcnow()
         if ts <= blockchain.head.time:
         if ts <= blockchain.head.time:
             ts = blockchain.head.time + timedelta(microseconds=1)
             ts = blockchain.head.time + timedelta(microseconds=1)
-        return Block(None, blockchain.head.hash, ts, 0, blockchain.head.height + difficulty,
+        return Block(blockchain.head.hash, ts, 0, blockchain.head.height + difficulty,
                      None, difficulty, transactions, tree.get_hash())
                      None, difficulty, transactions, tree.get_hash())
 
 
     def __str__(self):
     def __str__(self):
         return json.dumps(self.to_json_compatible(), indent=4)
         return json.dumps(self.to_json_compatible(), indent=4)
 
 
-    def verify_merkle(self):
-        """ Verify that the merkle root hash is correct for the transactions in this block. """
-        return merkle_tree(self.transactions).get_hash() == self.merkle_root_hash
-
     @staticmethod
     @staticmethod
     def _int_to_bytes(val: int) -> bytes:
     def _int_to_bytes(val: int) -> bytes:
         """ Turns an (arbitrarily long) integer into a bytes sequence. """
         """ Turns an (arbitrarily long) integer into a bytes sequence. """
@@ -107,7 +101,7 @@ class Block:
         """
         """
         Computes a hash over the contents of this block, except for the nonce. The proof of
         Computes a hash over the contents of this block, except for the nonce. The proof of
         work can use this partial hash to efficiently try different nonces. Other uses should
         work can use this partial hash to efficiently try different nonces. Other uses should
-        use :any:`get_hash` to get the complete hash.
+        use `hash` to get the complete hash.
         """
         """
         hasher = get_hasher()
         hasher = get_hasher()
         hasher.update(self.prev_block_hash)
         hasher.update(self.prev_block_hash)
@@ -120,22 +114,22 @@ class Block:
         """
         """
         Finishes the hash in `hasher` with the nonce in this block. The proof of
         Finishes the hash in `hasher` with the nonce in this block. The proof of
         work can use this function to efficiently try different nonces. Other uses should
         work can use this function to efficiently try different nonces. Other uses should
-        use :any:`get_hash` to get the complete hash in one step.
+        use `hash` to get the complete hash in one step.
         """
         """
         hasher.update(self._int_to_bytes(self.nonce))
         hasher.update(self._int_to_bytes(self.nonce))
         return hasher.digest()
         return hasher.digest()
 
 
-    def get_hash(self):
+    def _get_hash(self):
         """ Compute the hash of the header data. This is not necessarily the received hash value for this block! """
         """ Compute the hash of the header data. This is not necessarily the received hash value for this block! """
         hasher = self.get_partial_hash()
         hasher = self.get_partial_hash()
         return self.finish_hash(hasher)
         return self.finish_hash(hasher)
 
 
+    def verify_merkle(self):
+        """ Verify that the merkle root hash is correct for the transactions in this block. """
+        return merkle_tree(self.transactions).get_hash() == self.merkle_root_hash
+
     def verify_difficulty(self):
     def verify_difficulty(self):
         """ Verifies that the hash value is correct and fulfills its difficulty promise. """
         """ Verifies that the hash value is correct and fulfills its difficulty promise. """
-        # TODO: move this some better place
-        if self.hash != self.get_hash():
-            logging.warning("block has invalid hash value")
-            return False
         if self.hash == GENESIS_BLOCK_HASH:
         if self.hash == GENESIS_BLOCK_HASH:
             return True
             return True
         if not verify_proof_of_work(self):
         if not verify_proof_of_work(self):
@@ -208,11 +202,9 @@ from .proof_of_work import verify_proof_of_work, GENESIS_DIFFICULTY, DIFFICULTY_
         DIFFICULTY_TARGET_TIMEDELTA
         DIFFICULTY_TARGET_TIMEDELTA
 
 
 
 
-GENESIS_BLOCK = Block(b"",
-        "None; {} {}".format(DIFFICULTY_BLOCK_INTERVAL, DIFFICULTY_TARGET_TIMEDELTA).encode(),
-        datetime(2017, 3, 3, 10, 35, 26, 922898), 0, 0, datetime.utcnow(), GENESIS_DIFFICULTY, [],
-        merkle_tree([]).get_hash())
-GENESIS_BLOCK_HASH = GENESIS_BLOCK.get_hash()
-GENESIS_BLOCK.hash = GENESIS_BLOCK_HASH
+GENESIS_BLOCK = Block("None; {} {}".format(DIFFICULTY_BLOCK_INTERVAL,
+        DIFFICULTY_TARGET_TIMEDELTA).encode(), datetime(2017, 3, 3, 10, 35, 26, 922898), 0, 0,
+        datetime.utcnow(), GENESIS_DIFFICULTY, [], merkle_tree([]).get_hash())
+GENESIS_BLOCK_HASH = GENESIS_BLOCK.hash
 
 
 from .blockchain import Blockchain
 from .blockchain import Blockchain

+ 0 - 6
tests/test_verifications.py

@@ -178,12 +178,6 @@ def test_invalid_proof_of_work(chain):
     block = Block.create(chain, [])
     block = Block.create(chain, [])
     assert chain.try_append(block) is None
     assert chain.try_append(block) is None
 
 
-@block_test()
-def test_invalid_hash(chain):
-    block = Block.create(chain, [])
-    block.hash = b"invalid"
-    assert chain.try_append(block) is None
-
 @block_test()
 @block_test()
 def test_invalid_prev_hash(chain):
 def test_invalid_prev_hash(chain):
     block = create_block(chain, prev_block_hash="0001020304")
     block = create_block(chain, prev_block_hash="0001020304")

+ 0 - 2
tests/utils.py

@@ -14,7 +14,6 @@ logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)-8s %(me
 def extend_blockchain(chain, trans:list=None, verify_res=True):
 def extend_blockchain(chain, trans:list=None, verify_res=True):
     ts = datetime.utcfromtimestamp(0)
     ts = datetime.utcfromtimestamp(0)
     new_block = Block.create(chain, trans, ts)
     new_block = Block.create(chain, trans, ts)
-    new_block.hash = new_block.get_hash()
     new_chain = chain.try_append(new_block)
     new_chain = chain.try_append(new_block)
     assert (new_chain is not None) == verify_res
     assert (new_chain is not None) == verify_res
     return new_chain
     return new_chain
@@ -28,7 +27,6 @@ def create_block(chain, **manipulate_fields):
         assert k in obj, "setting an unknown field is useless"
         assert k in obj, "setting an unknown field is useless"
         obj[k] = v
         obj[k] = v
     block = Block.from_json_compatible(obj)
     block = Block.from_json_compatible(obj)
-    block.hash = block.get_hash()
     return block
     return block
 
 
 def trans_as_input(trans, out_idx=0):
 def trans_as_input(trans, out_idx=0):