diff --git a/src/test/blockindex_tests.cpp b/src/test/blockindex_tests.cpp
--- a/src/test/blockindex_tests.cpp
+++ b/src/test/blockindex_tests.cpp
@@ -87,6 +87,27 @@
     }
 }
 
+BOOST_AUTO_TEST_CASE(get_block_hash) {
+    CBlockIndex index = CBlockIndex();
+
+    /* Test with all 0 hash */
+    uint256 zeroHash = uint256();
+    index.phashBlock = &zeroHash;
+    uint256 hash = index.GetBlockHash();
+    BOOST_CHECK(hash == zeroHash);
+
+    /* Test with a random hash */
+    std::vector<uint8_t> hashBytes(32);
+
+    std::generate(hashBytes.begin(), hashBytes.end(),
+                  []() { return (uint8_t)(rand() % 255); });
+
+    uint256 randomHash = uint256(hashBytes);
+    index.phashBlock = &randomHash;
+    hash = index.GetBlockHash();
+    BOOST_CHECK(hash == randomHash);
+}
+
 BOOST_AUTO_TEST_CASE(received_time) {
     // Set to UINT32_MAX because that's the maximum value header.nTime can hold
     const int64_t expectedBlockTime = std::numeric_limits<uint32_t>::max();
@@ -163,6 +184,81 @@
     }
 }
 
+BOOST_AUTO_TEST_CASE(to_string) {
+    CBlockHeader header = CBlockHeader();
+    header.hashMerkleRoot = uint256();
+
+    CBlockIndex index = CBlockIndex(header);
+    uint256 hashBlock = uint256();
+    index.phashBlock = &hashBlock;
+    index.nHeight = 123;
+
+    CBlockIndex indexPrev = CBlockIndex();
+
+    std::string expectedString = "";
+    std::string indexString = "";
+
+    /* CASE 1 : pprev is null */
+    expectedString =
+        "CBlockIndex(pprev=0, nHeight=123, "
+        "merkle="
+        "0000000000000000000000000000000000000000000000000000000000000000, "
+        "hashBlock="
+        "0000000000000000000000000000000000000000000000000000000000000000)";
+    index.pprev = nullptr;
+    indexString = index.ToString();
+    BOOST_CHECK(indexString == expectedString);
+
+    /* CASE 2 : pprev is indexPrev */
+    expectedString = strprintf(
+        "CBlockIndex(pprev=%p, nHeight=123, "
+        "merkle="
+        "0000000000000000000000000000000000000000000000000000000000000000, "
+        "hashBlock="
+        "0000000000000000000000000000000000000000000000000000000000000000)",
+        &indexPrev);
+    index.pprev = &indexPrev;
+    indexString = index.ToString();
+    BOOST_CHECK(indexString == expectedString);
+
+    /* CASE 3 : height is max(int) */
+    expectedString = strprintf(
+        "CBlockIndex(pprev=%p, nHeight=2147483647, "
+        "merkle="
+        "0000000000000000000000000000000000000000000000000000000000000000, "
+        "hashBlock="
+        "0000000000000000000000000000000000000000000000000000000000000000)",
+        &indexPrev);
+    index.nHeight = INT32_MAX;
+    indexString = index.ToString();
+    BOOST_CHECK(indexString == expectedString);
+
+    /* CASE 4 : set some Merkle root hash */
+    expectedString = strprintf(
+        "CBlockIndex(pprev=%p, nHeight=2147483647, "
+        "merkle="
+        "0000000000000000000000000000000000000000000000000123456789abcdef, "
+        "hashBlock="
+        "0000000000000000000000000000000000000000000000000000000000000000)",
+        &indexPrev);
+    index.hashMerkleRoot = uint256S("0123456789ABCDEF");
+    indexString = index.ToString();
+    BOOST_CHECK(indexString == expectedString);
+
+    /* CASE 5 : set some block hash */
+    expectedString = strprintf(
+        "CBlockIndex(pprev=%p, nHeight=2147483647, "
+        "merkle="
+        "0000000000000000000000000000000000000000000000000123456789abcdef, "
+        "hashBlock="
+        "000000000000000000000000000000000000000000000000fedcba9876543210)",
+        &indexPrev);
+    uint256 emptyHashBlock = uint256S("FEDCBA9876543210");
+    index.phashBlock = &emptyHashBlock;
+    indexString = index.ToString();
+    BOOST_CHECK(indexString == expectedString);
+}
+
 BOOST_AUTO_TEST_CASE(index_validity_tests) {
     CBlockIndex index;
 
@@ -220,4 +316,108 @@
     }
 }
 
+BOOST_AUTO_TEST_CASE(index_ancestors) {
+    std::array<CBlockIndex, 256> indexes;
+
+    /* Check the skip pointer don't build when there is no precedence */
+    for (size_t i = 0; i < indexes.size(); i++) {
+        indexes[i] = CBlockIndex();
+        indexes[i].nHeight = i;
+
+        indexes[i].pprev = nullptr;
+        indexes[i].pskip = nullptr;
+
+        indexes[i].BuildSkip();
+
+        /* Check that skip not rebuilt if there is no preceding index */
+        BOOST_CHECK(indexes[i].pskip == nullptr);
+    }
+
+    for (size_t i = 0; i < indexes.size(); i++) {
+        if (i > 0) {
+            indexes[i].pprev = &indexes[i - 1];
+            indexes[i].BuildSkip();
+
+            /* Check that skip is built */
+            BOOST_CHECK(indexes[i].pskip != nullptr);
+
+            /*
+             * Starting from height 2, pskip should be more efficient that
+             * pprev.
+             * Ensure pskip.nHeight < pprev.nHeight
+             */
+            if (i > 1) {
+                BOOST_CHECK(indexes[i].pskip->nHeight <
+                            indexes[i].pprev->nHeight);
+            }
+
+            /* Find an ancestor 16 indexes behind */
+            if (i > 16) {
+                CBlockIndex *ancestor =
+                    indexes[i].GetAncestor(indexes[i].nHeight - 16);
+                BOOST_CHECK(ancestor != nullptr);
+                BOOST_CHECK(ancestor->nHeight == (indexes[i].nHeight - 16));
+            }
+        }
+    }
+
+    /*
+     * Reorder these indexes to setup multiple branches:
+     *
+     *                                     (248)->(...)->(255)
+     *                                    /
+     *                 (128)->(...)->(191)->(...)->(247)
+     *                /
+     * (0)->(...)->(63)->(...)->(127)
+     */
+    for (size_t i = 0; i < indexes.size(); i++) {
+        /* Build the tree */
+        indexes[i].pskip = nullptr;
+        if (i > 0) {
+            indexes[i].pprev = &indexes[i - 1];
+        }
+        if (i < 128) {
+            indexes[i].nHeight = i;
+        } else if (i < 248) {
+            /* Branch at 128 */
+            if (i == 128) {
+                indexes[i].pprev = &indexes[63];
+            }
+            indexes[i].nHeight = i - 64;
+        } else {
+            /* Branch at 248 */
+            if (i == 248) {
+                indexes[i].pprev = &indexes[191];
+            }
+            indexes[i].nHeight = i - 128 + 8;
+        }
+
+        /* Build and test skip pointer */
+        if (i > 0) {
+            indexes[i].BuildSkip();
+
+            /* Check that skip is built */
+            BOOST_CHECK(indexes[i].pskip != nullptr);
+
+            /*
+             * Starting from height 2, pskip should be more efficient that
+             * pprev.
+             * Ensure pskip.nHeight < pprev.nHeight
+             */
+            if (i > 1) {
+                BOOST_CHECK(indexes[i].pskip->nHeight <
+                            indexes[i].pprev->nHeight);
+            }
+        }
+
+        /* Find an ancestor 37 indexes behind */
+        if (i > 37) {
+            CBlockIndex *ancestor =
+                indexes[i].GetAncestor(indexes[i].nHeight - 37);
+            BOOST_CHECK(ancestor != nullptr);
+            BOOST_CHECK(ancestor->nHeight == (indexes[i].nHeight - 37));
+        }
+    }
+}
+
 BOOST_AUTO_TEST_SUITE_END()