diff --git a/src/Database.js b/src/Database.js
index 650a8f4fbd23bbcde1f5a917410748a2331b942c..2beb4e259e931e8112855b8bbb5ee549a0d9a5fa 100644
--- a/src/Database.js
+++ b/src/Database.js
@@ -216,11 +216,15 @@ module.exports = function (Y /* :any */) {
     whenUserIdSet (f) {
       this.userIdPromise.then(f)
     }
-    getNextOpId () {
-      if (this.userId == null) {
+    getNextOpId (numberOfIds) {
+      if (numberOfIds == null) {
+        throw new Error('getNextOpId expects the number of created ids to create!')
+      } else if (this.userId == null) {
         throw new Error('OperationStore not yet initialized!')
       } else {
-        return [this.userId, this.opClock++]
+        var id = [this.userId, this.opClock]
+        this.opClock += numberOfIds
+        return id
       }
     }
     /*
@@ -294,7 +298,7 @@ module.exports = function (Y /* :any */) {
         for (var sid in ls) {
           var l = ls[sid]
           var id = JSON.parse(sid)
-          var op = yield* this.getOperation(id)
+          var op = yield* this.getInsertion(id)
           if (op == null) {
             store.listenersById[sid] = l
           } else {
diff --git a/src/SpecHelper.js b/src/SpecHelper.js
index e2afb847bc59b3c4b4dac3c4f3746d443700940e..303153c11a3d84469e795c4143739006b0efb46e 100644
--- a/src/SpecHelper.js
+++ b/src/SpecHelper.js
@@ -25,7 +25,7 @@ g.g = g
 
 g.YConcurrency_TestingMode = true
 
-jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000
+jasmine.DEFAULT_TIMEOUT_INTERVAL = 2000
 
 g.describeManyTimes = function describeManyTimes (times, name, f) {
   for (var i = 0; i < times; i++) {
diff --git a/src/Struct.js b/src/Struct.js
index 32a1d30cbbb04479f66660886014c93ff64e0bb0..2ca4d6a32e7e1682aa76cbd7a35bdf2a799a17ea 100644
--- a/src/Struct.js
+++ b/src/Struct.js
@@ -93,21 +93,17 @@ module.exports = function (Y/* :any */) {
         return ids
       },
       getDistanceToOrigin: function * (op) {
-        if (op.left == null) {
-          return 0
-        } else {
-          var d = 0
-          var o = yield* this.getInsertion(op.left)
-          while (!Y.utils.compareIds(op.origin, (o ? o.id : null))) {
-            d++
-            if (o.left == null) {
-              break
-            } else {
-              o = yield* this.getInsertion(o.left)
-            }
+        var d = 0
+        var o = op
+        while (!Y.utils.matchesId(o, op.origin)) {
+          d++
+          if (o.left == null) {
+            break
+          } else {
+            o = yield* this.getInsertion(o.left)
           }
-          return d
         }
+        return d
       },
       /*
       # $this has to find a unique position between origin and the next known character
@@ -162,14 +158,14 @@ module.exports = function (Y/* :any */) {
             if (oOriginDistance === i) {
               // case 1
               if (o.id[0] < op.id[0]) {
-                op.left = o.id
-                distanceToOrigin = i + 1
+                op.left = Y.utils.getLastId(o)
+                distanceToOrigin = i + 1 // just ignore o.content.length, doesn't make a difference
               }
             } else if (oOriginDistance < i) {
               // case 2
               if (i - distanceToOrigin <= oOriginDistance) {
-                op.left = o.id
-                distanceToOrigin = i + 1
+                op.left = Y.utils.getLastId(o)
+                distanceToOrigin = i + 1 // just ignore o.content.length, doesn't make a difference
               }
             } else {
               break
@@ -194,7 +190,8 @@ module.exports = function (Y/* :any */) {
 
         // reconnect left and set right of op
         if (op.left != null) {
-          left = yield* this.getOperation(op.left)
+          left = yield* this.getInsertion(op.left)
+          // TODO: remove false
           if (false && op.content != null && left.content != null && left.id[0] === op.id[0] && left.id[1] + left.content.length === op.id[1] && left.originOf == null && left.deleted !== true && left.gc !== true) {
             // extend left
             left.content = left.content.concat(op.content)
@@ -214,7 +211,7 @@ module.exports = function (Y/* :any */) {
         if (op.right != null) {
           // TODO: wanna connect right too?
           right = yield* this.getOperation(op.right)
-          right.left = op.id
+          right.left = Y.utils.getLastId(op)
 
           // if right exists, and it is supposed to be gc'd. Remove it from the gc
           if (right.gc != null) {
@@ -257,7 +254,7 @@ module.exports = function (Y/* :any */) {
         end: null,
         struct: "List",
         type: "",
-        id: this.os.getNextOpId()
+        id: this.os.getNextOpId(1)
       }
       */
       create: function (id) {
@@ -338,7 +335,7 @@ module.exports = function (Y/* :any */) {
           map: {},
           struct: "Map",
           type: "",
-          id: this.os.getNextOpId()
+          id: this.os.getNextOpId(1)
         }
       */
       create: function (id) {
diff --git a/src/Transaction.js b/src/Transaction.js
index b0a54eb806b53bbce8f56aa6431f317073e17b75..99c37702d1cce52986e6353c650df1a705d99221 100644
--- a/src/Transaction.js
+++ b/src/Transaction.js
@@ -101,7 +101,7 @@ module.exports = function (Y/* :any */) {
     }
     * createType (typedefinition, id) {
       var structname = typedefinition[0].struct
-      id = id || this.store.getNextOpId()
+      id = id || this.store.getNextOpId(1)
       var op
       if (id[0] === '_') {
         op = yield* this.getOperation(id)
@@ -121,7 +121,7 @@ module.exports = function (Y/* :any */) {
     }
     /* createType (typedefinition, id) {
       var structname = typedefinition[0].struct
-      id = id || this.store.getNextOpId()
+      id = id || this.store.getNextOpId(1)
       var op = Y.Struct[structname].create(id)
       op.type = typedefinition[0].name
       if (typedefinition[0].appendAdditionalInfo != null) {
@@ -224,7 +224,7 @@ module.exports = function (Y/* :any */) {
         }
         var left
         if (target.left != null) {
-          left = yield* this.getOperation(target.left)
+          left = yield* this.getInsertion(target.left)
         } else {
           left = null
         }
@@ -417,7 +417,7 @@ module.exports = function (Y/* :any */) {
             }
           }
           if (op.deleted && op.left != null) {
-            var left = yield* this.getOperation(op.left)
+            var left = yield* this.getInsertion(op.left)
             this.store.addToGarbageCollector(op, left)
           }
         }
@@ -434,7 +434,7 @@ module.exports = function (Y/* :any */) {
     */
     * garbageCollectOperation (id) {
       this.store.addToDebug('yield* this.garbageCollectOperation(', id, ')')
-      var o = yield* this.getOperation(id)
+      var o = yield* this.getInsertionCleanStartEnd(id)
       yield* this.markGarbageCollected(id, 1) // always mark gc'd
       // if op exists, then clean that mess up..
       if (o != null) {
@@ -470,7 +470,7 @@ module.exports = function (Y/* :any */) {
 
         // remove gc'd op from the left op, if it exists
         if (o.left != null) {
-          var left = yield* this.getOperation(o.left)
+          var left = yield* this.getInsertion(o.left)
           left.right = o.right
           yield* this.setOperation(left)
         }
@@ -486,7 +486,7 @@ module.exports = function (Y/* :any */) {
             var neworigin = o.left
             var neworigin_ = null
             while (neworigin != null) {
-              neworigin_ = yield* this.getOperation(neworigin)
+              neworigin_ = yield* this.getInsertion(neworigin)
               if (neworigin_.deleted) {
                 break
               }
@@ -554,7 +554,7 @@ module.exports = function (Y/* :any */) {
         // o may originate in another operation.
         // Since o is deleted, we have to reset o.origin's `originOf` property
         if (o.origin != null) {
-          var origin = yield* this.getOperation(o.origin)
+          var origin = yield* this.getInsertion(o.origin)
           origin.originOf = origin.originOf.filter(function (_id) {
             return !Y.utils.compareIds(id, _id)
           })
@@ -604,7 +604,7 @@ module.exports = function (Y/* :any */) {
       var o = yield* this.getOperation([user, state.clock])
       while (o != null && o.id[1] === state.clock && user === o.id[0]) {
         // either its a new operation (1. case), or it is an operation that was deleted, but is not yet in the OS
-        state.clock++
+        state.clock += o.content == null ? 1 : o.content.length
         yield* this.checkDeleteStoreForState(state)
         o = yield* this.os.findNext(o.id)
       }
@@ -762,7 +762,7 @@ module.exports = function (Y/* :any */) {
     }
     * getInsertionCleanStartEnd (id) {
       yield* this.getInsertionCleanStart(id)
-      yield* this.getInsertionCleanEnd(id)
+      return yield* this.getInsertionCleanEnd(id)
     }
     // Return an insertion such that id is the first element of content
     // This function manipulates an operation, if necessary
@@ -775,11 +775,12 @@ module.exports = function (Y/* :any */) {
           var left = Y.utils.copyObject(ins)
           ins.content = left.content.splice(ins.id[1] - id[1])
           ins.id = id
-          ins.origin = left.id
+          var leftLid = Y.utils.getLastId(left)
+          ins.origin = leftLid
           left.originOf = [ins.id]
           left.right = ins.id
-          ins.left = left.id
-          debugger // check
+          ins.left = leftLid
+          // debugger // check
           yield* this.setOperation(left)
           yield* this.setOperation(ins)
           return ins
@@ -799,11 +800,12 @@ module.exports = function (Y/* :any */) {
           var right = Y.utils.copyObject(ins)
           right.content = ins.content.splice(-(ins.id[1] + ins.content.length - 1 - id[1])) // cut off remainder
           right.id = [id[0], id[1] + 1]
-          right.origin = ins.id
+          var insLid = Y.utils.getLastId(ins)
+          right.origin = insLid
           ins.originOf = [right.id]
           ins.right = right.id
-          right.left = ins.id
-          debugger // check
+          right.left = insLid
+          // debugger // check
           yield* this.setOperation(right)
           yield* this.setOperation(ins)
           return ins
@@ -961,17 +963,17 @@ module.exports = function (Y/* :any */) {
                 }
                 break
               }
-              o = yield* this.getOperation(o.left)
+              o = yield* this.getInsertion(o.left)
               // we set another o, check if we can reduce $missing_origins
               while (missing_origins.length > 0 && Y.utils.compareIds(missing_origins[missing_origins.length - 1].origin, o.id)) {
                 missing_origins.pop()
               }
               if (o.id[1] < (startSS[o.id[0]] || 0)) {
                 // case 2. o is known
-                op.left = o.id
+                op.left = Y.utils.getLastId(o)
                 send.push(op)
                 break
-              } else if (Y.utils.compareIds(o.id, op.origin)) {
+              } else if (Y.utils.matchesId(o, op.origin)) {
                 // case 3. o is op.origin
                 op.left = op.origin
                 send.push(op)
diff --git a/src/Utils.js b/src/Utils.js
index 2f87c4de3fe39026950fb81451220d3abbcb733a..f15ca71879c30b2be6737ece094daa896440ef10 100644
--- a/src/Utils.js
+++ b/src/Utils.js
@@ -244,21 +244,36 @@ module.exports = function (Y /* : any*/) {
 
   function compareIds (id1, id2) {
     if (id1 == null || id2 == null) {
-      if (id1 == null && id2 == null) {
-        return true
+      return id1 === id2
+    } else {
+      return id1[0] === id2[0] && id1[1] === id2[1]
+    } 
+  }
+  Y.utils.compareIds = compareIds
+
+  function matchesId (op, id) {
+    if (id == null || op == null) {
+      return id === op
+    } else {
+      if (id[0] === op.id[0]) {
+        if (op.content == null) {
+          return id[1] === op.id[1]
+        } else {
+          return id[1] >= op.id[1] && id[1] < op.id[1] + op.content.length
+        }
       }
-      return false
     }
-    if (id1[0] === id2[0]) {
-      var add1 = id1.length > 2 ? id1[2] : 0
-      var add2 = id2.length > 2 ? id2[2] : 0
-      if (id1[1] + add1 === id2[1] + add2) {
-        return true
-      }
+  }
+  Y.utils.matchesId = matchesId
+  
+  function getLastId (op) {
+    if (op.content == null || op.content.length === 1) {
+      return op.id
+    } else {
+      return [op.id[0], op.id[1] + op.content.length - 1]
     }
-    return false
   }
-  Y.utils.compareIds = compareIds
+  Y.utils.getLastId = getLastId
 
   function createEmptyOpsArray (n) {
     var a = new Array(n)
@@ -288,7 +303,7 @@ module.exports = function (Y /* : any*/) {
         this.writeBuffer = createEmptyOpsArray(5)
         this.readBuffer = createEmptyOpsArray(10)
       }
-      * find (id) {
+      * find (id, noSuperCall) {
         var i, r
         for (i = this.readBuffer.length - 1; i >= 0; i--) {
           r = this.readBuffer[i]
@@ -311,7 +326,7 @@ module.exports = function (Y /* : any*/) {
             break
           }
         }
-        if (i < 0) {
+        if (i < 0 && noSuperCall === undefined) {
           // did not reach break in last loop
           // read id and put it to the end of readBuffer
           o = yield* super.find(id)
@@ -378,7 +393,7 @@ module.exports = function (Y /* : any*/) {
         yield* super.delete(id)
       }
       * findWithLowerBound (id) {
-        var o = yield* this.find(id)
+        var o = yield* this.find(id, true)
         if (o != null) {
           return o
         } else {
@@ -387,7 +402,7 @@ module.exports = function (Y /* : any*/) {
         }
       }
       * findWithUpperBound (id) {
-        var o = yield* this.find(id)
+        var o = yield* this.find(id, true)
         if (o != null) {
           return o
         } else {