Example #1
0
    def test_3_get_and_remove(self):
        for block in self.blocks:
            block.put()

        for block in self.blocks:
            new_block = Block.get(block.id)
            self.assertEqual(new_block.id, block.id)

        for block in self.blocks[:2]:
            with self.assertRaisesRegex(Block.ChainOperationBlockedError, "can't remove: blocked by another block"):
                block.remove()

        self.assertCountEqual(Block.get_ids_list(), [block.id for block in self.blocks])

        self.blocks[2].remove()

        for block in self.blocks[:2]:
            with self.assertRaisesRegex(Block.ChainOperationBlockedError, "can't remove: blocked by another block"):
                block.remove()

        self.blocks[3].remove()

        self.assertCountEqual(Block.get_ids_list(), [block.id for block in self.blocks[:2]])

        with self.assertRaisesRegex(Block.ChainOperationBlockedError, "can't remove: blocked by another block"):
            self.blocks[0].remove()

        self.blocks[1].remove()
        self.blocks[0].remove()

        for block in self.blocks:
            with self.assertRaises(Block.DoesNotExist):
                block.remove()

        self.assertEqual(Block.get_ids_list(), [])
Example #2
0
    def test_no_database(self):
        with self.assertRaisesRegex(pmpi.database.Database.InitialisationError, "initialise database first"):
            Block.get_ids_list()

        with self.assertRaisesRegex(pmpi.database.Database.InitialisationError, "initialise database first"):
            Block.get(sha256(b'something').digest())

        private_key = SigningKey.generate()
        public_key = PublicKey.from_signing_key(private_key)

        operations = [
            Operation(OperationRev(), 'http://example0.com/', [public_key]),
            Operation(OperationRev(), 'http://example1.com/', [public_key])
        ]

        for op in operations:
            sign_object(public_key, private_key, op)

        block = Block.from_operations_list(BlockRev(), int(time.time()), operations)
        block.mine()
        sign_object(public_key, private_key, block)

        with self.assertRaisesRegex(pmpi.database.Database.InitialisationError, "initialise database first"):
            block.put()

        with self.assertRaisesRegex(pmpi.database.Database.InitialisationError, "initialise database first"):
            block.remove()
Example #3
0
    def setUp(self):
        initialise_database('test_database_file')

        self.private_key = SigningKey.generate()
        self.public_key = PublicKey.from_signing_key(self.private_key)
        # self.uuids = [uuid4() for _ in range(3)]

        self.operations = [[
            Operation(OperationRev(),'http://example0.com/v0/', [self.public_key]),
            Operation(OperationRev(),'http://example1.com/v0/', [self.public_key])
        ]]

        for op in self.operations[0]:
            sign_object(self.public_key, self.private_key, op)

        self.operations.append([
            Operation(OperationRev.from_obj(self.operations[0][0]), 'http://example0.com/v1/', [self.public_key]),
            Operation(OperationRev.from_obj(self.operations[0][1]), 'http://example1.com/v1/', [self.public_key]),
            Operation(OperationRev(), 'http://example2.com/v0/', [self.public_key])
        ])

        for op in self.operations[1]:
            sign_object(self.public_key, self.private_key, op)

        self.operations.append([
            Operation(OperationRev.from_obj(self.operations[1][0]),'http://example0.com/v2/', [self.public_key]),
            Operation(OperationRev.from_obj(self.operations[1][1]), 'http://example1.com/v2/', [self.public_key])
        ])

        for op in self.operations[2]:
            sign_object(self.public_key, self.private_key, op)

        self.operations.append([
            Operation(OperationRev.from_obj(self.operations[1][1]), 'http://alternative1.com/', [self.public_key]),
            Operation(OperationRev.from_obj(self.operations[1][2]), 'http://alternative2.com/', [self.public_key])
        ])

        for op in self.operations[3]:
            sign_object(self.public_key, self.private_key, op)

        timestamp = int(time.time()) - 100

        self.blocks = [Block.from_operations_list(BlockRev(), timestamp, self.operations[0])]
        self.blocks[0].mine()
        sign_object(self.public_key, self.private_key, self.blocks[0])
        self.blocks.append(
            Block.from_operations_list(BlockRev.from_obj(self.blocks[0]), timestamp + 20, self.operations[1]))
        self.blocks[1].mine()
        sign_object(self.public_key, self.private_key, self.blocks[1])
        self.blocks.append(
            Block.from_operations_list(BlockRev.from_obj(self.blocks[1]), timestamp + 40, self.operations[2]))
        self.blocks[2].mine()
        sign_object(self.public_key, self.private_key, self.blocks[2])
        self.blocks.append(
            Block.from_operations_list(BlockRev.from_obj(self.blocks[1]), timestamp + 60, self.operations[3]))
        self.blocks[3].mine()
        sign_object(self.public_key, self.private_key, self.blocks[3])
Example #4
0
 def test_wrong_limit(self):
     block = Block.from_operations_list(BlockRev(), int(time.time()), self.operations)
     block.operations_limit = Block.MAX_OPERATIONS + 1
     block.mine()
     sign_object(self.public_key, self.private_key, block)
     with self.assertRaisesRegex(Block.VerifyError, "operations_limit out of range"):
         block.verify()
Example #5
0
 def test_too_much(self):
     block = Block.from_operations_list(BlockRev(), int(time.time()), self.operations)
     block.operations_limit = Block.MIN_OPERATIONS
     block.mine()
     sign_object(self.public_key, self.private_key, block)
     with self.assertRaisesRegex(Block.VerifyError, "number of operations doesn't satisfy limitations"):
         block.verify()
Example #6
0
 def test_unsigned_operation(self):
     with self.assertRaisesRegex(Block.VerifyError, "at least one of the operations is not properly signed"):
         self.block = Block.from_operations_list(self.block.previous_block_rev, self.block.timestamp, (
             Operation(self.block.operations[0].previous_operation_rev,
                       'http://different.example.com/', self.block.operations[0].owners),
             self.block.operations[1]
         ))
Example #7
0
    def test_only_one_genesis_block(self):
        ops = self.add_operations()
        blocks = [
            Block.from_operations_list(BlockRev(), 42, [ops[1], ops[3], ops[4]]),
            Block.from_operations_list(BlockRev(), 43, [ops[5], ops[7], ops[9]])
        ]

        for block in blocks:
            block.mine()
            sign_object(self.public_keys[0], self.private_keys[0], block)

        blocks[0].put()

        for block in blocks:
            with self.assertRaisesRegex(Block.GenesisBlockDuplicationError, "trying to create multiple genesis blocks"):
                block.put()
Example #8
0
    def add_blocks(self, ops):
        """
        create blocks:
        blocks[0] -> blocks[1] -> blocks[2] -> blocks[3] -> blocks[5]
                                           \-> blocks[4] -> blocks[6]
        """
        start_time = 42
        blocks = [Block.from_operations_list(BlockRev(), start_time, [ops[0], ops[1]])]
        blocks[0].mine()
        sign_object(self.public_keys[0], self.private_keys[0], blocks[0])
        blocks.append(Block.from_operations_list(BlockRev.from_obj(blocks[0]), start_time + 10, [ops[2], ops[6]]))
        blocks[1].mine()
        sign_object(self.public_keys[0], self.private_keys[0], blocks[1])
        blocks.append(Block.from_operations_list(BlockRev.from_obj(blocks[1]), start_time + 20, [ops[3], ops[5]]))
        blocks[2].mine()
        sign_object(self.public_keys[0], self.private_keys[0], blocks[2])
        blocks.append(Block.from_operations_list(BlockRev.from_obj(blocks[2]), start_time + 30, [ops[8], ops[4]]))
        blocks[3].mine()
        sign_object(self.public_keys[0], self.private_keys[0], blocks[3])
        blocks.append(Block.from_operations_list(BlockRev.from_obj(blocks[2]), start_time + 40, [ops[4], ops[7]]))
        blocks[4].mine()
        sign_object(self.public_keys[0], self.private_keys[0], blocks[4])
        blocks.append(Block.from_operations_list(BlockRev.from_obj(blocks[3]), start_time + 50, [ops[7], ops[9]]))
        blocks[5].mine()
        sign_object(self.public_keys[0], self.private_keys[0], blocks[5])
        blocks.append(Block.from_operations_list(BlockRev.from_obj(blocks[4]), start_time + 60, [ops[8], ops[9]]))
        blocks[6].mine()
        sign_object(self.public_keys[0], self.private_keys[0], blocks[6])

        return blocks
Example #9
0
    def test_from_raw(self):
        new_block = Block.from_raw_with_operations(self.block.raw_with_operations())

        self.assertIsInstance(new_block, Block)
        for attr in ('previous_block_rev', 'timestamp', 'operations_limit', 'difficulty',
                     'padding', 'signature'):
            self.assertEqual(getattr(new_block, attr), getattr(self.block, attr))

        self.assertEqual(new_block.operations_full_raw(), self.block.operations_full_raw())
        self.assertEqual(new_block.public_key.der, self.block.public_key.der)
        self.assertEqual(new_block.is_checksum_correct(), self.block.is_checksum_correct())
Example #10
0
    def setUp(self):
        self.private_key = SigningKey.generate()
        self.public_key = PublicKey.from_signing_key(self.private_key)
        self.timestamp = int(time.time())

        self.operations = (
            Operation(OperationRev(), 'http://example1.com/', [self.public_key]),
            Operation(OperationRev(), 'http://example2.com/', [self.public_key])
        )

        for op in self.operations:
            sign_object(self.public_key, self.private_key, op)

        self.block = Block.from_operations_list(BlockRev(), self.timestamp, self.operations)

        self.block.mine()
        sign_object(self.public_key, self.private_key, self.block)
Example #11
0
    def setUp(self):
        initialise_database('test_database_file')

        self.operations = [
            Operation(OperationRev(), 'http://example.com/' + url, [PublicKey.from_signing_key(SigningKey.generate())])
            for url in ('first/', 'second/')]

        for op in self.operations:
            sk = SigningKey.generate()
            sign_object(PublicKey.from_signing_key(sk), sk, op)

        block = Block.from_operations_list(BlockRev(), 42, self.operations)
        block.mine()
        sk = SigningKey.generate()
        sign_object(PublicKey.from_signing_key(sk), sk, block)
        block.put()

        self.identifiers = [Identifier.from_operation(op) for op in self.operations]
Example #12
0
    def test_2_put(self):
        self.blocks[0].put()

        with self.assertRaisesRegex(Block.GenesisBlockDuplicationError, "trying to create multiple genesis blocks"):
            self.blocks[0].put()

        self.blocks[1].put()

        with self.assertRaisesRegex(Block.DuplicationError, "object id already in the database"):
            self.blocks[1].put()

        self.blocks[2].put()
        self.blocks[3].put()

        revision_id_list = Block.get_ids_list()

        self.assertEqual(len(revision_id_list), 4)
        self.assertCountEqual(revision_id_list, [block.id for block in self.blocks])
Example #13
0
        def mint_block():

            if len(ops) >= MIN_OPS_IN_BLOCK:
                print("Preparing block with {} operations.".format(len(ops)))

                blockchain = pmpi.core.get_blockchain()
                rev = BlockRev.from_id(blockchain.head) if blockchain.max_depth > 0 else BlockRev()
                block = Block.from_operations_list(rev, int(time.time()), ops)
                block.difficulty = 10  # TODO difficulty!
                block.mine()
                self.user.sign_object(block)
                block.verify()

                print("Block minted. Sending.")

                self.transport.write(b'BL' + block.raw_with_operations())
            else:
                print("There are not enough operations to mint a block")
                for op in ops:
                    asyncio.ensure_future(operation_queue.put(op))
Example #14
0
def test():
    try:
        os.remove('test_database_file')
    except OSError:
        pass
    initialise_database('test_database_file')

    obj_private_key = SigningKey.generate()
    obj_public_key = PublicKey.from_signing_key(obj_private_key)
    obj_uuids = [uuid4() for _ in range(3)]

    obj_operations = [[
        Operation(OperationRev(), 'http://example0.com/v0/', [obj_public_key]),
        Operation(OperationRev(), 'http://example1.com/v0/', [obj_public_key])
    ]]

    for op in obj_operations[0]:
        sign_object(obj_public_key, obj_private_key, op)

    obj_operations.append([
        Operation(OperationRev.from_obj(obj_operations[0][0]), 'http://example0.com/v1/', [obj_public_key]),
        Operation(OperationRev.from_obj(obj_operations[0][1]), 'http://example1.com/v1/', [obj_public_key]),
        Operation(OperationRev(), 'http://example2.com/v0/', [obj_public_key])
    ])

    for op in obj_operations[1]:
        sign_object(obj_public_key, obj_private_key, op)

    obj_operations.append([
        Operation(OperationRev.from_obj(obj_operations[1][0]), 'http://example0.com/v2/', [obj_public_key]),
        Operation(OperationRev.from_obj(obj_operations[1][1]), 'http://example1.com/v2/', [obj_public_key])
    ])

    for op in obj_operations[2]:
        sign_object(obj_public_key, obj_private_key, op)

    obj_operations.append([
        Operation(OperationRev.from_obj(obj_operations[1][1]), 'http://alternative1.com/', [obj_public_key]),
        Operation(OperationRev.from_obj(obj_operations[1][2]), 'http://alternative2.com/', [obj_public_key])
    ])

    for op in obj_operations[3]:
        sign_object(obj_public_key, obj_private_key, op)

    timestamp = int(time.time()) - 100

    obj_blocks = [Block.from_operations_list(BlockRev(), timestamp, obj_operations[0])]
    obj_blocks[0].mine()
    sign_object(obj_public_key, obj_private_key, obj_blocks[0])
    obj_blocks.append(
        Block.from_operations_list(BlockRev.from_obj(obj_blocks[0]), timestamp + 20, obj_operations[1]))
    obj_blocks[1].mine()
    sign_object(obj_public_key, obj_private_key, obj_blocks[1])
    obj_blocks.append(
        Block.from_operations_list(BlockRev.from_obj(obj_blocks[1]), timestamp + 40, obj_operations[2]))
    obj_blocks[2].mine()
    sign_object(obj_public_key, obj_private_key, obj_blocks[2])
    obj_blocks.append(
        Block.from_operations_list(BlockRev.from_obj(obj_blocks[1]), timestamp + 60, obj_operations[3]))
    obj_blocks[3].mine()
    sign_object(obj_public_key, obj_private_key, obj_blocks[3])

    for block in obj_blocks:
        block.put()

    for block in obj_blocks:
        new_block = Block.get(block.id)
        assert new_block.id == block.id

    for block in obj_blocks[:2]:
        try:
            block.remove()
            raise AssertionError
        except Block.ChainOperationBlockedError:
            pass

    assert sorted(Block.get_ids_list()) == sorted([block.id for block in obj_blocks])

    obj_blocks[2].remove()

    for block in obj_blocks[:2]:
        try:
            block.remove()
            raise AssertionError
        except Block.ChainOperationBlockedError:
            pass

    obj_blocks[3].remove()

    try:
        obj_blocks[0].remove()
        raise AssertionError
    except Block.ChainOperationBlockedError:
        pass

    obj_blocks[1].remove()
    obj_blocks[0].remove()

    for block in obj_blocks:
        try:
            block.remove()
            raise AssertionError
        except Block.DoesNotExist:
            pass

    assert Block.get_ids_list() == []

    close_database()
    os.remove('test_database_file')
Example #15
0
    def test_mangled_raw(self):
        raw = self.block.raw_with_operations()

        with self.assertRaisesRegex(RawFormatError, "raw input too short"):
            Block.from_raw_with_operations(raw[:-1])
        with self.assertRaisesRegex(RawFormatError, "raw input too long"):
            Block.from_raw_with_operations(raw + b'\x00')

        with self.assertRaisesRegex(Block.VerifyError, "wrong signature"):
            mangled_raw = bytearray(raw)
            mangled_raw[-1] = 0
            Block.from_raw_with_operations(mangled_raw).verify_id(self.block.id)

        with self.assertRaisesRegex(Block.VerifyError, "wrong object id"):
            Block.from_raw_with_operations(raw).verify_id(b'wrong hash')

        with self.assertRaisesRegex(Block.VerifyError, "wrong object id"):
            Block.from_raw_with_operations(raw).verify_id(sha256(b'wrong hash'))

        with self.assertRaisesRegex(RawFormatError, "version number mismatch"):
            Block.from_raw((2).to_bytes(4, 'big') + self.block.raw()[4:])
Example #16
0
 def test_block_not_signed(self):
     block = Block.from_operations_list(BlockRev(), int(time.time()), self.operations)
     with self.assertRaisesRegex(Block.VerifyError, "object is not signed"):
         block.verify()
Example #17
0
 def test_1_get_from_empty(self):
     with self.assertRaises(Block.DoesNotExist):
         Block.get(self.blocks[0].id)
Example #18
0
 def test_0_empty(self):
     self.assertEqual(len(Block.get_ids_list()), 0)
Example #19
0
    def process_block(self, raw_block):
        block = Block.from_raw_with_operations(raw_block)

        with patch.object(BlockChain, '_get_new_blocks', return_value=[block]):
            pmpi.core.get_blockchain().update_blocks()