_verifyPiecesUsingBitfield (cb) {
    const piecesToCheck = new Set()
    const piecesToFilesMap = new Map()
    // First step, optimistically mark what is verified and what is not by blindly trusting the bitfield
    // and construct a list of pieces to verify ( max 1 piece for each file, in some edge cases that piece could overlap )
    for (const file of this.files) {
      let checkFile = 2
      let pieceToCheckForThisFile = null
      for (let i = file._startPiece; i <= file._endPiece; ++i) {
        if (this.bitfield.get(i)) {
          if (checkFile) {
            pieceToCheckForThisFile = i
            checkFile--
          }
          if (!piecesToFilesMap.has(i)) {
            piecesToFilesMap.set(i, [])
          }
          piecesToFilesMap.get(i).push(file)
        }
      }
      if (pieceToCheckForThisFile !== null) {
        piecesToCheck.add(pieceToCheckForThisFile)
      }
    }
    // Second step, for each piece that needs to be verified we verify it using hashing
    this._verifyPiecesUsingHash([...piecesToCheck], (err) => {
      if (err) {
        return cb(err)
      }
      const filesToCheck = new Set()
      for (const piece of piecesToCheck) {
        if (!this.bitfield.get(piece)) {
          const filesOnPiece = piecesToFilesMap.get(piece)
          for (const file of filesOnPiece) {
            filesToCheck.add(file)
          }
        }
      }
      // Third step, if we need to recheck files we are going to fully recheck them
      if (filesToCheck.size) {
        const piecesToRecheck = []
        for (const file of filesToCheck) {
          for (let i = file._startPiece; i <= file._endPiece; ++i) {
            if (piecesToRecheck.indexOf(i) === -1) {
              piecesToRecheck.push(i)
            }
          }
        }
        return this._verifyPiecesUsingHash(piecesToRecheck, cb)
      }
      cb(null)
    })
  }
Verify pieces using bitfield, in case of in-congruences it will re-verify the file using hashing
@param {callbackWithError} cb
@private