diff --git a/include/olm/ratchet.hh b/include/olm/ratchet.hh
index aaa3579731451c32874e1a45d1307795087bda45..13f7097c32a95bd4a20dbb1a6e528015ca5a4097 100644
--- a/include/olm/ratchet.hh
+++ b/include/olm/ratchet.hh
@@ -169,7 +169,8 @@ std::uint8_t * pickle(
 
 std::uint8_t const * unpickle(
     std::uint8_t const * pos, std::uint8_t const * end,
-    Ratchet & value
+    Ratchet & value,
+    bool includes_chain_index
 );
 
 
diff --git a/src/ratchet.cpp b/src/ratchet.cpp
index dd1d42ce5593bf01ca9ec681bdd3ede47c9b635a..671d260c42c9a8a2056d8af813ce79072154da00 100644
--- a/src/ratchet.cpp
+++ b/src/ratchet.cpp
@@ -363,6 +363,10 @@ std::size_t olm::pickle_length(
     length += olm::pickle_length(value.sender_chain);
     length += olm::pickle_length(value.receiver_chains);
     length += olm::pickle_length(value.skipped_message_keys);
+
+    // the logging_enabled branch includes a 'chain_index' field
+    length += olm::pickle_length(std::uint32_t(0));
+
     return length;
 }
 
@@ -374,18 +378,30 @@ std::uint8_t * olm::pickle(
     pos = pickle(pos, value.sender_chain);
     pos = pickle(pos, value.receiver_chains);
     pos = pickle(pos, value.skipped_message_keys);
+
+    // the logging_enabled branch includes a 'chain_index' field; for us, it is
+    // empty.
+    pos = pickle(pos, std::uint32_t(0));
+
     return pos;
 }
 
 
 std::uint8_t const * olm::unpickle(
     std::uint8_t const * pos, std::uint8_t const * end,
-    olm::Ratchet & value
+    olm::Ratchet & value,
+    bool includes_chain_index
 ) {
     pos = unpickle(pos, end, value.root_key);
     pos = unpickle(pos, end, value.sender_chain);
     pos = unpickle(pos, end, value.receiver_chains);
     pos = unpickle(pos, end, value.skipped_message_keys);
+
+    // pickle v2 includes a chain index; pickle v1 did not.
+    if (includes_chain_index) {
+        std::uint32_t dummy;
+        pos = unpickle(pos, end, dummy);
+    }
     return pos;
 }
 
diff --git a/src/session.cpp b/src/session.cpp
index c148c979f3bcf099382a955402ee777e9a20565c..b76a6b8d2cda0bb3232ee8b5151390f7a28f8585 100644
--- a/src/session.cpp
+++ b/src/session.cpp
@@ -396,7 +396,7 @@ std::size_t olm::Session::decrypt(
 }
 
 namespace {
-static const std::uint32_t SESSION_PICKLE_VERSION = 1;
+static const std::uint32_t SESSION_PICKLE_VERSION = 2;
 }
 
 std::size_t olm::pickle_length(
@@ -433,14 +433,26 @@ std::uint8_t const * olm::unpickle(
 ) {
     uint32_t pickle_version;
     pos = olm::unpickle(pos, end, pickle_version);
-    if (pickle_version != SESSION_PICKLE_VERSION) {
-        value.last_error = OlmErrorCode::OLM_UNKNOWN_PICKLE_VERSION;
-        return end;
+
+    bool includes_chain_index;
+    switch (pickle_version) {
+        case 1:
+            includes_chain_index = false;
+            break;
+
+        case 2:
+            includes_chain_index = true;
+            break;
+
+        default:
+            value.last_error = OlmErrorCode::OLM_UNKNOWN_PICKLE_VERSION;
+            return end;
     }
+
     pos = olm::unpickle(pos, end, value.received_message);
     pos = olm::unpickle(pos, end, value.alice_identity_key);
     pos = olm::unpickle(pos, end, value.alice_base_key);
     pos = olm::unpickle(pos, end, value.bob_one_time_key);
-    pos = olm::unpickle(pos, end, value.ratchet);
+    pos = olm::unpickle(pos, end, value.ratchet, includes_chain_index);
     return pos;
 }
diff --git a/tests/test_session.cpp b/tests/test_session.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a0c1f6acd35877027f0f716f29f05f6d4260f4a4
--- /dev/null
+++ b/tests/test_session.cpp
@@ -0,0 +1,144 @@
+#include "olm/session.hh"
+#include "olm/pickle_encoding.h"
+
+#include "unittest.hh"
+
+/* decode into a buffer, which is returned */
+std::uint8_t *decode_hex(
+    const char * input
+) {
+    static std::uint8_t buf[256];
+    std::uint8_t *p = buf;
+    while (*input != '\0') {
+        char high = *(input++);
+        char low = *(input++);
+        if (high >= 'a') high -= 'a' - ('9' + 1);
+        if (low >= 'a') low -= 'a' - ('9' + 1);
+        uint8_t value = ((high - '0') << 4) | (low - '0');
+        *p++ = value;
+    }
+    return buf;
+}
+
+void check_session(const olm::Session &session) {
+    assert_equals(
+        decode_hex("49d640dc96b80176694af69fc4b8ca9fac49aecbd697d01fd8bee1ed2693b6c9"),
+        session.ratchet.root_key, 32
+    );
+
+    assert_equals(
+        std::size_t(1),
+        session.ratchet.sender_chain.size()
+    );
+
+    assert_equals(
+        decode_hex("f77a03eaa9b301fa7d2a5aa6b50286906de12cc96044f526dbbcb12839ad7003"),
+        session.ratchet.sender_chain[0].ratchet_key.public_key, 32
+    );
+
+    assert_equals(
+        decode_hex("d945c6ed4c7c277117adf11fb133a7936d287afe97c0b3ac989644b4490d4f31"),
+        session.ratchet.sender_chain[0].ratchet_key.private_key, 32
+    );
+
+    assert_equals(
+        std::uint32_t(0),
+        session.ratchet.sender_chain[0].chain_key.index
+    );
+
+    assert_equals(
+        std::size_t(0),
+        session.ratchet.receiver_chains.size()
+    );
+
+    assert_equals(
+        std::size_t(0),
+        session.ratchet.skipped_message_keys.size()
+    );
+
+    assert_equals(OLM_SUCCESS, session.last_error);
+    assert_equals(false, session.received_message);
+
+    assert_equals(
+        decode_hex("7326b58623a3f7bd8da11a1bab51f432c02a7430241b326e9fc8916a21eb257e"),
+        session.alice_identity_key.public_key, 32
+    );
+
+    assert_equals(
+        decode_hex("0ab4b30bde20bd374ceccc72861660f0fd046f7516900796c3e5de41c598316c"),
+        session.alice_base_key.public_key, 32
+    );
+
+    assert_equals(
+        decode_hex("585dba930b10d90d81702c715f4085d07c42b0cd2d676010bb6086c86c4cc618"),
+        session.bob_one_time_key.public_key, 32
+    );
+}
+
+int main() {
+
+{
+    TestCase test_case("V1 session pickle");
+
+    const uint8_t *PICKLE_KEY=(uint8_t *)"secret_key";
+    uint8_t pickled[] =
+        "wkEpwMgiAqD7B1/Lw2cKYYDcUZVOd9QHes7ZroWxr/Rp/nWEAySgRsIu/a54YhO67rwitr"
+        "Lpos7tFxxK9IZ7pKB1qrR1coVWIt78V9lp9WgmBAvxHBSY+tu1lkL/JjLi963/yFdPancZ"
+        "+WHMVfaKlV3gWGpo7EfNK6qAOxI1Ea/eCsE2sYrsHEDvLLGlKAA9E56rmmoe2w6TKzsQjs"
+        "ZM2/XT2eJ82EgMO9pL02iLElXWmGNv72Ut7DouR0pQIT50HIEEKcFxYcoTb3WCfJD76Coe"
+        "sE4kx+TA6d45Xu1bwQNNkTGF+nCCu/GmKY+sECXbz9U6WhxG0YdF9Z4T8YkWYAgpKNS0FW"
+        "RV";
+    size_t pickle_len = _olm_enc_input(
+        PICKLE_KEY, strlen((char *)PICKLE_KEY),
+        pickled, strlen((char *)pickled), NULL
+    );
+
+    olm::Session session;
+    const uint8_t *unpickle_res = olm::unpickle(pickled, pickled+sizeof(pickled), session);
+    assert_equals(
+        pickle_len, (size_t)(unpickle_res - pickled)
+    );
+
+    check_session(session);
+
+#if 0
+    size_t rawlen = olm::pickle_length(session);
+    uint8_t *r1 = _olm_enc_output_pos(pickled, rawlen);
+    olm::pickle(r1, session);
+    _olm_enc_output(
+        PICKLE_KEY, strlen((char *)PICKLE_KEY),
+        pickled, rawlen);
+    printf("%s\n", pickled);
+#endif
+}
+
+{
+    TestCase test_case("V2 session pickle");
+
+    const uint8_t *PICKLE_KEY=(uint8_t *)"secret_key";
+    uint8_t pickled[1024] =
+        "XTc0/aHUZIVjq257h6sCI1f4/EFJ42QYSOp6SDn88FSXRkO9dfrxGk8gPvZiNCnXFYWggX"
+        "UkTkaiSd9MFuj6kB49COlLU1zKw3caJmEIgud7umbYrAXhaBMCTl8T3XFVJK5gXThOE3sI"
+        "QCRy4RP4zAVJMTwnvNTzobi3N0aCxEDC+RIol6cEv+bV04zs8wbivdBDVJ7WIDVBF42dzQ"
+        "qPhL4KC5TLB9FYn/eUvrn56tHa5B3udjm1dbPynkjzkRy7Mbp5zUe6XhHDesKo0VxaHhOl"
+        "t117bSOKdf72wK/bStaWTpNdAA9h0AFuj2Rgp7E42yJTHY0tv23lMH1Hd+IHdsMsgMcfvL"
+        "Si";
+
+    size_t pickle_len = _olm_enc_input(
+        PICKLE_KEY, strlen((char *)PICKLE_KEY),
+        pickled, strlen((char *)pickled), NULL
+    );
+
+    olm::Session session;
+    const uint8_t *unpickle_res = olm::unpickle(pickled, pickled+sizeof(pickled), session);
+    assert_equals(
+        pickle_len, (size_t)(unpickle_res - pickled)
+    );
+
+    check_session(session);
+}
+
+
+
+return 0;
+}