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()
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()
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()
def setUp(self): self.private_key = SigningKey.generate(curve=NIST256p) self.public_key = PublicKey.from_signing_key(self.private_key) self.operation = Operation(OperationRev(), 'http://example.com/', [self.public_key]) sign_object(self.public_key, self.private_key, self.operation)
def sign_object(self, obj): """ Sign given operation by this user. :param obj: operation to sign """ sign_object(self._public_key, self._private_key, obj)
def test_wrong_operations(self): operations = self.add_operations() blocks = self.add_blocks(operations) bc = get_blockchain() with patch.object(BlockChain, '_get_new_blocks', return_value=blocks): bc.update_blocks() with self.assertRaisesRegex(Block.VerifyError, "some of the new operations have been added to the block already"): blocks[5].extend_operations([operations[9]]) illegal_operation = Operation(operations[7].get_rev(), 'illegal address', []) sign_object(self.public_keys[2], self.private_keys[2], illegal_operation) blocks[5].extend_operations([illegal_operation]) blocks[5].mine() with self.assertRaisesRegex(Block.ChainError, "operations are creating tree inside the block"): blocks[5].put() blocks[2].extend_operations([operations[6]]) blocks[2].mine() with self.assertRaisesRegex(Block.ChainError, "operation's previous_operation_rev is not pointing at " "the last operation on current blockchain"): blocks[2].put()
def test_3_get_and_remove(self): sign_object(self.public_key, self.private_key, self.operations[0]) self.operations[1] = Operation(OperationRev.from_obj(self.operations[0]), self.operations[1].address, self.operations[1].owners) for op in self.operations: sign_object(self.public_key, self.private_key, op) op.put() for op in self.operations: new_op = Operation.get(op.id) self.assertEqual(new_op.id, op.id) self.assertCountEqual(Operation.get_ids_list(), [op.id for op in self.operations]) self.operations[1].remove() self.operations[0].remove() self.assertCountEqual(Operation.get_ids_list(), [self.operations[2].id]) self.operations[2].remove() for op in self.operations: with self.assertRaises(Operation.DoesNotExist): op.remove() self.assertEqual(Operation.get_ids_list(), [])
def setUp(self): self.private_key = SigningKey.generate() self.public_keys = tuple(PublicKey.from_signing_key(SigningKey.generate()) for _ in range(2)) self.operation = Operation(OperationRev(), 'http://example.com', self.public_keys) sign_object(PublicKey.from_signing_key(self.private_key), self.private_key, self.operation) self.uuid = self.operation.uuid self.identifier = Identifier.from_operation(self.operation)
def test_4_wrong_previous_block(self): self.blocks[0].previous_block_rev = BlockRev.from_id(double_sha(b'something')) self.blocks[0].mine() sign_object(self.public_key, self.private_key, self.blocks[0]) with self.assertRaisesRegex(Block.ChainError, "previous_block_rev does not exist"): self.blocks[0].verify()
def setUp(self): self.private_key = SigningKey.generate() self.public_key = PublicKey.from_signing_key(self.private_key) self.operations = [Operation( OperationRev(), 'http://example.com/', [self.public_key]) for _ in range(Block.MIN_OPERATIONS + 1)] for op in self.operations: sign_object(self.public_key, self.private_key, op)
def test_put_operation0_and_copy(self): sign_object(self.public_keys[0], self.private_keys[0], self.operation[0]) self.operation[0].put() copied_op = Operation(self.operation[0].previous_operation_rev, self.operation[0].address, self.operation[0].owners) sign_object(self.public_keys[1], self.private_keys[1], copied_op) with self.assertRaisesRegex(Operation.VerifyError, "trying to create a minting operation for an existing uuid"): copied_op.put()
def test_0_operation(self): with self.assertRaisesRegex(Operation.VerifyError, "object is not signed"): self.operation[0].raw() # attempt to call .raw() on unsigned operation with self.assertRaisesRegex(Operation.VerifyError, "object is not signed"): self.operation[0].verify() # attempt to verify operation without signing with self.assertRaisesRegex(Operation.VerifyError, "wrong signature"): # wrong because of incompatibility between public (self.public_key[1]) and private (self.private_key[0]) sign_object(self.public_keys[1], self.private_keys[0], self.operation[0]) self.operation[0].verify() sign_object(self.public_keys[1], self.private_keys[1], self.operation[0]) self.operation[0].verify()
def test_put_operation1(self): sign_object(self.public_keys[0], self.private_keys[0], self.operation[0]) self.operation[0].put() self.operation[1] = Operation._construct_with_uuid(OperationRev(), self.operation[0].uuid, self.operation[1].address, self.operation[1].owners) sign_object(self.public_keys[0], self.private_keys[0], self.operation[1]) with self.assertRaisesRegex(Operation.UUIDError, "UUID of the minting operation does not fulfill the requirements"): self.operation[1].put() self.operation[1] = Operation(OperationRev.from_obj(self.operation[0]), self.operation[1].address, self.operation[1].owners) sign_object(self.public_keys[0], self.private_keys[0], self.operation[1]) with self.assertRaises(Operation.OwnershipError): self.operation[1].put() sign_object(self.public_keys[1], self.private_keys[1], self.operation[1]) self.operation[1].put()
def test_owners(self): self.operation = Operation(self.operation.previous_operation_rev, self.operation.address, [self.public_key, self.public_key]) sign_object(self.public_key, self.private_key, self.operation) with self.assertRaisesRegex(Operation.VerifyError, "duplicated owners"): self.operation.verify() self.operation = Operation(self.operation.previous_operation_rev, self.operation.address, []) sign_object(self.public_key, self.private_key, self.operation) self.assertTrue(self.operation.verify())
def test_no_database(self): with self.assertRaisesRegex(pmpi.database.Database.InitialisationError, "initialise database first"): Operation.get_ids_list() with self.assertRaisesRegex(pmpi.database.Database.InitialisationError, "initialise database first"): Operation.get(sha256(b'something').digest()) operation = Operation(OperationRev(), 'http://example.com/', []) sk = SigningKey.generate() sign_object(PublicKey.from_signing_key(sk), sk, operation) with self.assertRaisesRegex(pmpi.database.Database.InitialisationError, "initialise database first"): operation.put(BlockRev()) with self.assertRaisesRegex(pmpi.database.Database.InitialisationError, "initialise database first"): operation.remove(BlockRev())
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()
def test_no_database(self): with self.assertRaisesRegex(pmpi.database.Database.InitialisationError, "initialise database first"): Identifier.get_uuid_list() with self.assertRaisesRegex(pmpi.database.Database.InitialisationError, "initialise database first"): Identifier.get(uuid4()) operation = Operation(OperationRev(), 'http://example.com/', []) sk = SigningKey.generate() sign_object(PublicKey.from_signing_key(sk), sk, operation) identifier = Identifier.from_operation(operation) with self.assertRaisesRegex(pmpi.database.Database.InitialisationError, "initialise database first"): identifier.put() with self.assertRaisesRegex(pmpi.database.Database.InitialisationError, "initialise database first"): identifier.remove()
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)
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]
def test_put_operation_2(self): with self.assertRaisesRegex(Operation.ChainError, "previous_operation_rev does not exist"): self.operation[2] = Operation(OperationRev.from_id( sha256(b'wrong hash').digest()), self.operation[2].address, self.operation[2].owners) sign_object(self.public_keys[0], self.private_keys[0], self.operation[1]) self.operation[2] = Operation._construct_with_uuid(OperationRev.from_obj(self.operation[1]), self.operation[2].uuid, self.operation[2].address, self.operation[2].owners) sign_object(self.public_keys[1], self.private_keys[1], self.operation[2]) with self.assertRaisesRegex(Operation.UUIDError, "UUID mismatch"): self.operation[2].put() self.operation[2] = Operation._construct_with_uuid(OperationRev(), self.operation[2].uuid, self.operation[2].address, self.operation[2].owners) sign_object(self.public_keys[1], self.private_keys[1], self.operation[2]) self.operation[2].put() with self.assertRaisesRegex(Operation.DuplicationError, "object id already in the database"): self.operation[2].put()
def test_2_operation(self): sign_object(self.public_keys[1], self.private_keys[1], self.operation[0]) self.operation[1] = Operation(OperationRev.from_obj(self.operation[0]), 'http://new.example.com/', [self.public_keys[2]]) sign_object(self.public_keys[2], self.private_keys[2], self.operation[1]) self.operation[2] = Operation._construct_with_uuid(OperationRev.from_obj(self.operation[1]), uuid4(), 'http://new2.example.com', []) with self.assertRaisesRegex(Operation.UUIDError, "UUID mismatch"): sign_object(self.public_keys[2], self.private_keys[2], self.operation[2]) self.operation[2].verify() self.operation[2] = Operation(OperationRev.from_obj(self.operation[1]), 'http://new2.example.com', []) sign_object(self.public_keys[2], self.private_keys[2], self.operation[2]) self.operation[2].verify()
def test_1_operation(self): sign_object(self.public_keys[0], self.private_keys[0], self.operation[0]) self.operation[1] = Operation(OperationRev.from_obj(self.operation[0]), 'http://illegal.example.com/', [self.public_keys[2]]) with self.assertRaises(Operation.OwnershipError): sign_object(self.public_keys[0], self.private_keys[0], self.operation[1]) self.operation[1].verify() self.operation[1] = Operation(OperationRev.from_obj(self.operation[0]), 'http://new.example.com/', [self.public_keys[2]]) sign_object(self.public_keys[2], self.private_keys[2], self.operation[1]) self.assertTrue(self.operation[1].verify())
def test_2_put(self): sign_object(self.public_key, self.private_key, self.operations[0]) self.operations[0].put() with self.assertRaisesRegex(Operation.DuplicationError, "object id already in the database"): self.operations[0].put() self.operations[1] = Operation(OperationRev.from_obj(self.operations[0]), self.operations[1].address, self.operations[1].owners) sign_object(self.public_key, self.private_key, self.operations[1]) self.operations[1].put() sign_object(self.public_key, self.private_key, self.operations[2]) self.operations[2].put() revision_id_list = Operation.get_ids_list() self.assertEqual(len(revision_id_list), 3) self.assertCountEqual(revision_id_list, [op.id for op in self.operations])
def add_operations(self): """ create operations: for uuid[0]: op[0] -> op[2] -> op[6] -> op[8]; for uuid[1]: op[1] -> op[3] -> op[4]; for uuid[2]: op[5] -> op[7] -> op[9] """ ops = [ Operation(OperationRev(), 'http://example1.com/', [self.public_keys[0]]), Operation(OperationRev(), 'http://example2.com/', [self.public_keys[1]]), ] sign_object(self.public_keys[0], self.private_keys[0], ops[0]) sign_object(self.public_keys[0], self.private_keys[0], ops[1]) ops.extend([ Operation(OperationRev.from_obj(ops[0]), 'http://example1.com/v2/', [self.public_keys[0]]), Operation(OperationRev.from_obj(ops[1]), 'http://example2.com/v2/', [self.public_keys[1]]) ]) sign_object(self.public_keys[0], self.private_keys[0], ops[2]) sign_object(self.public_keys[1], self.private_keys[1], ops[3]) ops.append( Operation(OperationRev.from_obj(ops[3]), 'http://example2.com/v3/', [self.public_keys[1]]) ) sign_object(self.public_keys[1], self.private_keys[1], ops[4]) ops.extend([ Operation(OperationRev(), 'http://example3.com/', [self.public_keys[1], self.public_keys[2]]), Operation(OperationRev.from_obj(ops[2]), 'http://example1.com/v3/', [self.public_keys[0], self.public_keys[2]]) ]) sign_object(self.public_keys[2], self.private_keys[2], ops[5]) sign_object(self.public_keys[0], self.private_keys[0], ops[6]) ops.extend([ Operation(OperationRev.from_obj(ops[5]), 'http://example3.com/v2/', [self.public_keys[2]]), Operation(OperationRev.from_obj(ops[6]), 'http://example1.com/v4/', [self.public_keys[2]]) ]) sign_object(self.public_keys[1], self.private_keys[1], ops[7]) sign_object(self.public_keys[2], self.private_keys[2], ops[8]) ops.append( Operation(OperationRev.from_obj(ops[7]), 'http://example3.com/v3/', [self.public_keys[2]]) ) sign_object(self.public_keys[2], self.private_keys[2], ops[9]) return ops
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])
def test_put_operation0(self): with self.assertRaisesRegex(Operation.VerifyError, "object is not signed"): self.operation[0].put() sign_object(self.public_keys[0], self.private_keys[0], self.operation[0]) self.operation[0].put()
def test_1_get_from_empty(self): with self.assertRaises(Operation.DoesNotExist): sign_object(self.public_key, self.private_key, self.operations[0]) Operation.get(self.operations[0].id)
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
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')