예제 #1
0
    def _get_wal_writer(self, precommit_data: 'PrecommitData',
                        is_calc_period_start_block: bool):
        wal_writer: 'WriteAheadLogWriter' = WriteAheadLogWriter(
            precommit_data.revision,
            max_log_count=2,
            block=precommit_data.block,
            instant_block_hash=precommit_data.block.hash)
        wal_writer.open(self.log_path)

        state_wal: 'StateWAL' = StateWAL(precommit_data.block_batch)
        revision: int = precommit_data.rc_db_revision if is_calc_period_start_block else -1
        tx_index: int = IconScoreContext.storage.rc.get_tx_index(
            is_calc_period_start_block)
        iiss_wal: 'IissWAL' = IissWAL(precommit_data.rc_block_batch, tx_index,
                                      revision)
        return wal_writer, state_wal, iiss_wal
예제 #2
0
    def run(self, icx_db: 'KeyValueDatabase', rc_db: 'KeyValueDatabase',
            revision: int, prev_block: 'Block', block_batch: 'BlockBatch',
            iiss_wal: 'IissWAL', is_calc_period_start_block: bool,
            instant_block_hash: bytes):
        """Backup the previous block state

        :param icx_db:
        :param rc_db:
        :param revision:
        :param prev_block: the latest confirmed block height during commit
        :param block_batch:
        :param iiss_wal:
        :param is_calc_period_start_block:
        :param instant_block_hash:
        :return:
        """
        Logger.debug(tag=TAG, msg="backup() start")

        path: str = self._get_backup_file_path(prev_block.height)
        Logger.info(tag=TAG, msg=f"backup_file_path={path}")

        writer = WriteAheadLogWriter(revision,
                                     max_log_count=2,
                                     block=prev_block,
                                     instant_block_hash=instant_block_hash)
        writer.open(path)

        if is_calc_period_start_block:
            writer.write_state(WALBackupState.CALC_PERIOD_END_BLOCK.value)

        self._backup_rc_db(writer, rc_db, iiss_wal)
        self._backup_state_db(writer, icx_db, block_batch)

        writer.close()

        Logger.debug(tag=TAG, msg="backup() end")
예제 #3
0
    def test_invalid_magic_key(self):
        revision = Revision.IISS.value
        log_count = 2
        instant_block_hash = create_block_hash()

        writer = WriteAheadLogWriter(revision, log_count, self.block,
                                     instant_block_hash)
        writer.open(self.path)
        writer.close()

        # Make the magic key invalid
        with open(self.path, "rb+") as f:
            ret = f.write(b"iwal")
            assert ret == 4

        reader = WriteAheadLogReader()
        with pytest.raises(IllegalFormatException):
            reader.open(self.path)
예제 #4
0
    def test_out_of_header_size(self):
        revision = Revision.IISS.value
        log_count = 2
        instant_block_hash = create_block_hash()

        writer = WriteAheadLogWriter(revision=revision,
                                     max_log_count=log_count,
                                     block=self.block,
                                     instant_block_hash=instant_block_hash)
        writer.open(self.path)
        writer.close()

        f = open(self.path, "rb+")
        f.truncate(_HEADER_SIZE - 4)
        f.close()

        reader = WriteAheadLogReader()
        with pytest.raises(IllegalFormatException):
            reader.open(self.path)
예제 #5
0
    def test_invalid_version(self):
        revision = Revision.IISS.value
        log_count = 2
        instant_block_hash = create_block_hash()

        writer = WriteAheadLogWriter(revision, log_count, self.block,
                                     instant_block_hash)
        writer.open(self.path)
        writer.close()

        # Make the version invalid
        with open(self.path, "rb+") as f:
            f.seek(_OFFSET_VERSION)
            version = 0xFFFFFFFF
            ret = f.write(version.to_bytes(4, "big"))
            assert ret == 4

        reader = WriteAheadLogReader()
        with pytest.raises(IllegalFormatException):
            reader.open(self.path)
예제 #6
0
    def test_writer_and_reader(self):
        revision = Revision.IISS.value
        log_count = 2
        instant_block_hash = create_block_hash()

        writer = WriteAheadLogWriter(revision, log_count, self.block,
                                     instant_block_hash)
        writer.open(self.path)

        writer.write_state(WALState.CALC_PERIOD_START_BLOCK.value, add=False)

        writer.write_walogable(WALogableData(self.log_data[0]))
        writer.write_state(WALState.WRITE_RC_DB.value, add=True)

        writer.write_walogable(WALogableData(self.log_data[1]))
        writer.write_state(WALState.WRITE_STATE_DB.value, add=True)

        state = (WALState.WRITE_RC_DB | WALState.WRITE_STATE_DB).value
        writer.write_state(state, add=False)
        writer.close()

        reader = WriteAheadLogReader()
        reader.open(self.path)
        assert reader.magic_key == _MAGIC_KEY
        assert reader.version == _FILE_VERSION
        assert reader.revision == revision
        assert reader.state == state
        assert reader.log_count == log_count
        assert reader.block == self.block
        assert reader.instant_block_hash == instant_block_hash

        for i in range(len(self.log_data)):
            data = {}

            for key, value in reader.get_iterator(i):
                data[key] = value

            assert data == self.log_data[i]
            assert id(data) != id(self.log_data[i])

        reader.close()