示例#1
0
    def test_compute_root_multiple_hashes(self):
        expected_hash = hashlib.sha256(hashlib.sha256(binascii.unhexlify(b'aa' * 32 + b'bb' * 32)).digest()).digest()

        hash1 = types.UInt256(data=binascii.unhexlify(b'aa' * 32))
        hash2 = types.UInt256(data=binascii.unhexlify(b'bb' * 32))
        hashes = [hash1, hash2]
        root = crypto.MerkleTree.compute_root(hashes)

        self.assertEqual(expected_hash, root.to_array())
示例#2
0
    def test_merkle_node_methods(self):
        hash1 = types.UInt256(data=binascii.unhexlify(b'aa' * 32))
        hash2 = types.UInt256(data=binascii.unhexlify(b'bb' * 32))
        hashes = [hash1, hash2]
        m = crypto.MerkleTree(hashes)

        self.assertEqual(True, m.root.is_root())
        self.assertEqual(False, m.root.is_leaf())
        self.assertEqual(False, m.root.left_child.is_root())
        self.assertEqual(True, m.root.left_child.is_leaf())
示例#3
0
 def deserialize_unsigned(self, reader: serialization.BinaryReader) -> None:
     (self.version,
      prev_hash,
      merkleroot,
      self.timestamp,
      self.index,
      self.primary_index,
      consensus) = struct.unpack("<I32s32sQIB20s", reader._stream.read(101))
     if self.primary_index >= len(settings.standby_validators):
         raise ValueError(f"Deserialization error - primary index {self.primary_index} exceeds validator count "
                          f"{len(settings.standby_validators)}")
     self.prev_hash = types.UInt256(prev_hash)
     self.merkle_root = types.UInt256(merkleroot)
     self.next_consensus = types.UInt160(consensus)
示例#4
0
 def hash(self) -> types.UInt256:
     with serialization.BinaryWriter() as bw:
         self.serialize_unsigned(bw)
         data_to_hash = bytearray(bw._stream.getvalue())
         data = hashlib.sha256(
             hashlib.sha256(data_to_hash).digest()).digest()
         return types.UInt256(data=data)
示例#5
0
    def get_tx_from_block(self, snapshot: storage.Snapshot,
                          block_index_or_hash: bytes,
                          tx_index: int) -> Optional[payloads.Transaction]:
        """
        Get a transaction from a specific block
        Args:
            snapshot:
            block_index_or_hash: the height or block hash of the block we wish to retrieve
            tx_index: the index into the blocks transaction list of the transaction we want to fetch.

        Returns:

        """
        if len(block_index_or_hash) < types.UInt256._BYTE_LEN:
            height = vm.BigInteger(block_index_or_hash)
            if height < 0 or height > 4294967295:  # uint.MaxValue
                raise ValueError("Invalid height")
            block = snapshot.blocks.try_get_by_height(height, read_only=True)
        elif len(block_index_or_hash) == types.UInt256._BYTE_LEN:
            block_hash = types.UInt256(block_index_or_hash)
            block = snapshot.blocks.try_get(block_hash, read_only=True)
        else:
            raise ValueError("Invalid data")

        if block and not self._is_traceable_block(snapshot, block.index):
            block = None
        if tx_index < 0 or tx_index >= len(block.transactions):
            raise ValueError("Transaction index out of range")
        return block.transactions[tx_index]
示例#6
0
    def get_block(self, snapshot: storage.Snapshot,
                  index_or_hash: bytes) -> Optional[payloads.TrimmedBlock]:
        """
        Fetch a block from storage.

        Args:
            snapshot: the snapshot to grab the data from.
            index_or_hash: the height or block hash of the block we wish to retrieve

        Raises:
             ValueError: if the height is invalid (negative or too large)
             ValueError: if the index_or_hash field could not be converted to a valid height or hash.
        """
        if len(index_or_hash) < types.UInt256._BYTE_LEN:
            height = vm.BigInteger(index_or_hash)
            if height < 0 or height > 4294967295:  # uint.MaxValue
                raise ValueError("Invalid height")
            block = snapshot.blocks.try_get_by_height(height, read_only=True)
        elif len(index_or_hash) == types.UInt256._BYTE_LEN:
            block_hash = types.UInt256(index_or_hash)
            block = snapshot.blocks.try_get(block_hash, read_only=True)
        else:
            raise ValueError("Invalid data")

        if block and not self._is_traceable_block(snapshot, block.index):
            block = None
        return block.trim()
示例#7
0
    def _build(leaves: List[_MerkleTreeNode]) -> _MerkleTreeNode:
        if len(leaves) == 0:
            raise ValueError('Leaves must have length')
        if len(leaves) == 1:
            return leaves[0]

        num_parents = int((len(leaves) + 1) / 2)
        parents = [_MerkleTreeNode() for i in range(0, num_parents)]

        for i in range(0, num_parents):
            node = parents[i]
            node.left_child = leaves[i * 2]
            leaves[i * 2].parent = node
            if (i * 2 + 1 == len(leaves)):
                node.right_child = node.left_child
            else:
                node.right_child = leaves[i * 2 + 1]
                leaves[i * 2 + 1].parent = node

            data = node.left_child.hash.to_array(
            ) + node.right_child.hash.to_array()
            hashed_data = hashlib.sha256(
                hashlib.sha256(data).digest()).digest()
            node.hash = types.UInt256(data=hashed_data)

        return MerkleTree._build(parents)
示例#8
0
    def test_to_hash_array(self):
        hash1 = types.UInt256(data=binascii.unhexlify(b'aa' * 32))
        hash2 = types.UInt256(data=binascii.unhexlify(b'bb' * 32))
        hash3 = types.UInt256(data=binascii.unhexlify(b'cc' * 32))
        hash4 = types.UInt256(data=binascii.unhexlify(b'dd' * 32))
        hash5 = types.UInt256(data=binascii.unhexlify(b'ee' * 32))
        hashes = [hash1, hash2, hash3, hash4, hash5]

        m = crypto.MerkleTree(hashes)
        hash_array = m.to_hash_array()

        # sort the array
        hash_array = sorted(hash_array)

        for i, h in enumerate(hashes):
            self.assertEqual(h, hash_array[i])
示例#9
0
 def _convert(self, stack_item: vm.StackItem, class_type: Type[object]) -> object:
     """
     convert VM type to native
     """
     if class_type in [vm.StackItem, vm.PointerStackItem, vm.ArrayStackItem, vm.InteropStackItem]:
         return stack_item
     elif class_type in [int, vm.BigInteger]:
         return stack_item.to_biginteger()
     # mypy bug? https://github.com/python/mypy/issues/9756
     elif class_type in [bytes, bytearray]:  # type: ignore
         return stack_item.to_array()
     elif class_type == bool:
         return stack_item.to_boolean()
     elif class_type == types.UInt160:
         return types.UInt160(data=stack_item.to_array())
     elif class_type == types.UInt256:
         return types.UInt256(data=stack_item.to_array())
     elif class_type == str:
         return stack_item.to_array().decode()
     elif class_type == cryptography.ECPoint:
         return cryptography.ECPoint.deserialize_from_bytes(stack_item.to_array())
     elif issubclass(class_type, enum.Enum):
         stack_item = cast(vm.IntegerStackItem, stack_item)
         # mypy seems to have trouble understanding types that support __int__
         return class_type(int(stack_item))  # type: ignore
     else:
         raise ValueError(f"Unknown class type, don't know how to convert: {class_type}")
示例#10
0
 def hash(self) -> types.UInt256:
     """
     Get a unique block identifier based on the unsigned data portion of the object.
     """
     with serialization.BinaryWriter() as bw:
         self.serialize_unsigned(bw)
         data_to_hash = bytearray(bw._stream.getvalue())
         data = hashlib.sha256(data_to_hash).digest()
         return types.UInt256(data=data)
示例#11
0
    def deserialize_unsigned(self, reader: serialization.BinaryReader) -> None:
        """
        Deserialize the unsigned data part of the object from a binary stream.

        Args:
            reader: instance.

        Raises:
            ValueError: if the primary_index field is greater than the configured consensus validator count.
        """
        (self.version,
         prev_hash,
         merkleroot,
         self.timestamp,
         self.index,
         self.primary_index,
         consensus) = struct.unpack("<I32s32sQIB20s", reader._stream.read(101))
        if self.primary_index >= len(settings.standby_validators):
            raise ValueError(f"Deserialization error - primary index {self.primary_index} exceeds validator count "
                             f"{len(settings.standby_validators)}")
        self.prev_hash = types.UInt256(prev_hash)
        self.merkle_root = types.UInt256(merkleroot)
        self.next_consensus = types.UInt160(consensus)
示例#12
0
    def get_block(self, snapshot: storage.Snapshot,
                  index_or_hash: bytes) -> Optional[payloads.TrimmedBlock]:
        if len(index_or_hash) < types.UInt256._BYTE_LEN:
            height = vm.BigInteger(index_or_hash)
            if height < 0 or height > 4294967295:  # uint.MaxValue
                raise ValueError("Invalid height")
            block = snapshot.blocks.try_get_by_height(height, read_only=True)
        elif len(index_or_hash) == types.UInt256._BYTE_LEN:
            block_hash = types.UInt256(index_or_hash)
            block = snapshot.blocks.try_get(block_hash, read_only=True)
        else:
            raise ValueError("Invalid data")

        if block and not self._is_traceable_block(snapshot, block.index):
            block = None
        return block.trim()
示例#13
0
def _try_get_block(engine: contracts.ApplicationEngine,
                   data: bytes) -> Optional[payloads.Block]:
    if len(data) < types.UInt256._BYTE_LEN:
        height = vm.BigInteger(data)
        if height < 0 or height > 4294967295:  # uint.MaxValue
            raise ValueError("Invalid height")
        block = engine.snapshot.blocks.try_get_by_height(height)
    elif len(data) == types.UInt256._BYTE_LEN:
        block_hash = types.UInt256(data)
        block = engine.snapshot.blocks.try_get(block_hash)
    else:
        raise ValueError("Invalid data")

    if block and not _is_traceable_block(engine.snapshot, block.index):
        block = None  # pragma: no cover (unreachable)
    return block
示例#14
0
    def get_tx_from_block(self, snapshot: storage.Snapshot,
                          block_index_or_hash: bytes,
                          tx_index: int) -> Optional[payloads.Transaction]:
        if len(block_index_or_hash) < types.UInt256._BYTE_LEN:
            height = vm.BigInteger(block_index_or_hash)
            if height < 0 or height > 4294967295:  # uint.MaxValue
                raise ValueError("Invalid height")
            block = snapshot.blocks.try_get_by_height(height, read_only=True)
        elif len(block_index_or_hash) == types.UInt256._BYTE_LEN:
            block_hash = types.UInt256(block_index_or_hash)
            block = snapshot.blocks.try_get(block_hash, read_only=True)
        else:
            raise ValueError("Invalid data")

        if block and not self._is_traceable_block(snapshot, block.index):
            block = None
        if tx_index < 0 or tx_index >= len(block.transactions):
            raise ValueError("Transaction index out of range")
        return block.transactions[tx_index]
示例#15
0
 def hash(self) -> types.UInt256:
     data = hashlib.sha256(hashlib.sha256(
         self.to_array()).digest()).digest()
     return types.UInt256(data=data)
示例#16
0
    def test_compute_root_single_hash(self):
        data = binascii.unhexlify(b'aa' * 32)
        hash1 = types.UInt256(data=data)
        root = crypto.MerkleTree.compute_root([hash1])

        self.assertEqual(data, root.to_array())