private void migrateV1toV2() throws BlockStoreException, IOException {
        long currentLength = randomAccessFile.length();
        long currentBlocksLength = currentLength - FILE_PROLOGUE_BYTES;
        if (currentBlocksLength % RECORD_SIZE_V1 != 0)
            throw new BlockStoreException(
                    "File size on disk indicates this is not a V1 block store: " + currentLength);
        int currentCapacity = (int) (currentBlocksLength / RECORD_SIZE_V1);

        randomAccessFile.setLength(fileLength);
        // Map it into memory again because of the length change.
        buffer.force();
        buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, fileLength);

        // migrate magic header
        ((Buffer) buffer).rewind();
        buffer.put(HEADER_MAGIC_V2);

        // migrate headers
        final byte[] zeroPadding = new byte[20]; // 32 (V2 work) - 12 (V1 work)
        for (int i = currentCapacity - 1; i >= 0; i--) {
            byte[] record = new byte[RECORD_SIZE_V1];
            buffer.position(FILE_PROLOGUE_BYTES + i * RECORD_SIZE_V1);
            buffer.get(record);
            buffer.position(FILE_PROLOGUE_BYTES + i * RECORD_SIZE_V2);
            buffer.put(record, 0, 32); // hash
            buffer.put(zeroPadding);
            buffer.put(record, 32, RECORD_SIZE_V1 - 32); // work, height, block header
        }

        // migrate cursor
        int cursorRecord = (getRingCursor() - FILE_PROLOGUE_BYTES) / RECORD_SIZE_V1;
        setRingCursor(FILE_PROLOGUE_BYTES + cursorRecord * RECORD_SIZE_V2);
    }
@Test
    public void migrateV1toV2() throws Exception {
        // create V1 format
        RandomAccessFile raf = new RandomAccessFile(blockStoreFile, "rw");
        FileChannel channel = raf.getChannel();
        ByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0,
                SPVBlockStore.FILE_PROLOGUE_BYTES + SPVBlockStore.RECORD_SIZE_V1 * 3);
        buffer.put(SPVBlockStore.HEADER_MAGIC_V1); // header magic
        Block genesisBlock = TESTNET.getGenesisBlock();
        StoredBlock storedGenesisBlock = new StoredBlock(genesisBlock.cloneAsHeader(), genesisBlock.getWork(), 0);
        Sha256Hash genesisHash = storedGenesisBlock.getHeader().getHash();
        ((Buffer) buffer).position(SPVBlockStore.FILE_PROLOGUE_BYTES);
        buffer.put(genesisHash.getBytes());
        storedGenesisBlock.serializeCompact(buffer);
        buffer.putInt(4, buffer.position()); // ring cursor
        ((Buffer) buffer).position(8);
        buffer.put(genesisHash.getBytes()); // chain head
        raf.close();

        // migrate to V2 format
        SPVBlockStore store = new SPVBlockStore(TESTNET, blockStoreFile);

        // check block is the same
        assertEquals(genesisHash, store.getChainHead().getHeader().getHash());
        // check ring cursor
        assertEquals(SPVBlockStore.FILE_PROLOGUE_BYTES + SPVBlockStore.RECORD_SIZE_V2 * 1,
                store.getRingCursor());
        store.close();
    }