planetarium / libplanet

Blockchain in C#/.NET for on-chain, decentralized gaming
https://docs.libplanet.io/
GNU Lesser General Public License v2.1
506 stars 142 forks source link

Cannot insert duplicate key in unique index '_id'. #465

Closed moreal closed 4 years ago

moreal commented 5 years ago

LiteException: Cannot insert duplicate key in unique index '_id'. made infinity loop.

Uploading Crash Report
LiteException: Cannot insert duplicate key in unique index '_id'. The duplicate value is '"54b775d6701ec0b01f3cc58121b8212eb58260e5e36d6aecfca6a57508e893cd95909fb000ee0ec3453d84dcdaed2bf7f9240000"'.
  at LiteDB.IndexService.AddNode (LiteDB.CollectionIndex index, LiteDB.BsonValue key, System.Byte level, LiteDB.IndexNode last) [0x00132] in <0e7fe05a592849968cfe23dfc2a26585>:0
  at LiteDB.IndexService.AddNode (LiteDB.CollectionIndex index, LiteDB.BsonValue key, LiteDB.IndexNode last) [0x00028] in <0e7fe05a592849968cfe23dfc2a26585>:0
  at LiteDB.LiteEngine.InsertDocument (LiteDB.CollectionPage col, LiteDB.BsonDocument doc, LiteDB.BsonType autoId) [0x001a6] in <0e7fe05a592849968cfe23dfc2a26585>:0
  at LiteDB.LiteEngine+<>c__DisplayClass22_0.<Insert>b__0 (LiteDB.CollectionPage col) [0x00017] in <0e7fe05a592849968cfe23dfc2a26585>:0
  at LiteDB.LiteEngine.Transaction[T] (System.String collection, System.Boolean addIfNotExists, System.Func`2[T,TResult] action) [0x0004e] in <0e7fe05a592849968cfe23dfc2a26585>:0
  at LiteDB.LiteEngine.Insert (System.String collection, System.Collections.Generic.IEnumerable`1[T] docs, LiteDB.BsonType autoId) [0x00041] in <0e7fe05a592849968cfe23dfc2a26585>:0
  at LiteDB.LiteEngine.InsertBulk (System.String collection, System.Collections.Generic.IEnumerable`1[T] docs, System.Int32 batchSize, LiteDB.BsonType autoId) [0x00051] in <0e7fe05a592849968cfe23dfc2a26585>:0
  at LiteDB.LiteCollection`1[T].InsertBulk (System.Collections.Generic.IEnumerable`1[T] docs, System.Int32 batchSize) [0x00026] in <0e7fe05a592849968cfe23dfc2a26585>:0
  at Libplanet.Store.LiteDBStore.StoreStateReference[T] (System.String namespace, System.Collections.Immutable.IImmutableSet`1[T] addresses, Libplanet.Blocks.Block`1[T] block) [0x00034] in <8bab8556e6ff499d983b16b19e71c0f4>:0
  at Libplanet.Net.Swarm`1+<SyncRecentStatesFromTrustedPeersAsync>d__90[T].MoveNext () [0x00320] in <8bab8556e6ff499d983b16b19e71c0f4>:0
--- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in <1f0c1ef1ad524c38bbc5536809c46b48>:0
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in <1f0c1ef1ad524c38bbc5536809c46b48>:0
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in <1f0c1ef1ad524c38bbc5536809c46b48>:0
  at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in <1f0c1ef1ad524c38bbc5536809c46b48>:0
  at System.Runtime.CompilerServices.TaskAwaiter`1[TResult].GetResult () [0x00000] in <1f0c1ef1ad524c38bbc5536809c46b48>:0
  at Libplanet.Net.Swarm`1+<PreloadAsync>d__82[T].MoveNext () [0x00370] in <8bab8556e6ff499d983b16b19e71c0f4>:0
--- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in <1f0c1ef1ad524c38bbc5536809c46b48>:0
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in <1f0c1ef1ad524c38bbc5536809c46b48>:0
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in <1f0c1ef1ad524c38bbc5536809c46b48>:0
  at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in <1f0c1ef1ad524c38bbc5536809c46b48>:0
  at System.Runtime.CompilerServices.TaskAwaiter.GetResult () [0x00000] in <1f0c1ef1ad524c38bbc5536809c46b48>:0
  at Nekoyume.BlockChain.Agent+<>c__DisplayClass41_0+<<CoSwarmRunner>b__0>d.MoveNext () [0x00085] in /Users/moreal/github/planetarium/nekoyume-unity/nekoyume/Assets/_Scripts/BlockChain/Agent.cs:155
Rethrow as AggregateException: One or more errors occurred.
  at Nekoyume.BlockChain.Agent+<CoSwarmRunner>d__41.MoveNext () [0x0028f] in /Users/moreal/github/planetarium/nekoyume-unity/nekoyume/Assets/_Scripts/BlockChain/Agent.cs:215
  at UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) [0x00028] in /Users/builduser/buildslave/unity/build/Runtime/Export/Scripting/Coroutines.cs:17

(Filename: <0e7fe05a592849968cfe23dfc2a26585> Line: 0)

Try Dequeue Actions. Total Count: 0
Finish Dequeue Actions.
Try Dequeue Actions. Total Count: 0
Finish Dequeue Actions.
Try Dequeue Actions. Total Count: 0
Finish Dequeue Actions.
Try Dequeue Actions. Total Count: 0
Finish Dequeue Actions.
Try Dequeue Actions. Total Count: 0
Finish Dequeue Actions.
Try Dequeue Actions. Total Count: 0
Finish Dequeue Actions.
Try Dequeue Actions. Total Count: 0
Finish Dequeue Actions.
Try Dequeue Actions. Total Count: 0
Finish Dequeue Actions.
Try Dequeue Actions. Total Count: 0
Finish Dequeue Actions.
Try Dequeue Actions. Total Count: 0
Finish Dequeue Actions.
... (Infinity loop)
dahlia commented 5 years ago

This is reproduced when two nodes mine blocks and one trusts other one's precalculated states during preloading phase:

  1. Node A mines blocks. (Say its height is 1 and hash is X.)
  2. Node B trusts Node A as states validator and downloads blocks and states from Node A.
    • Node A mines more blocks. (Says its height is 2 and hash is YA.)
    • Node B mines more blocks. (Says its height is 2 and hash is YB.)
  3. Node B terminates before sending the block YB or receiving the block YA.
  4. Node B starts again, and tries to download blocks and states from Node A.

The error happens at the last moment, because Node B sends GetRecentStates from YB (which is unknown for Node A) to YA, so that Node A responds with RecentStates from the genesis block to YA.

We should fix this to find the common ancestor (i.e., branchpoint) between YA and YB.