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(), [])
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 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_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_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 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] ))
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 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_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())
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_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])
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))
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')
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:])
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()
def test_1_get_from_empty(self): with self.assertRaises(Block.DoesNotExist): Block.get(self.blocks[0].id)
def test_0_empty(self): self.assertEqual(len(Block.get_ids_list()), 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()