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

`DefaultStore.ContainsBlock()` & `DefaultStore.GetBlock<T>()` are not consistent #1539

Closed dahlia closed 1 year ago

dahlia commented 2 years ago

In some corner cases, DefaultStore.GetBlock<T>() can return null while DefaultStore.ContainsBlock() returns true. For example, the following error log was caused due to this corner case:

System.NullReferenceException: Object reference not set to an instance of an object.
   at Libplanet.Blocks.BlockMarshaler.MarshalBlock[T](Block`1 block) in C:\libplanet\Libplanet\Blocks\BlockMarshaler.cs:line 149
   at Libplanet.Net.Swarm`1.TransferBlocks(GetBlocks getData) in C:\libplanet\Libplanet\Net\Swarm.MessageHandlers.cs:line 252
   at Libplanet.Net.Swarm`1.ProcessMessageHandler(Object target, Message message) in C:\libplanet\Libplanet\Net\Swarm.MessageHandlers.cs:line 70
   at Libplanet.Net.Transports.NetMQTransport.<>c__DisplayClass59_0.<ReceiveMessage>b__0() in C:\libplanet\Libplanet\Net\Transports\NetMQTransport.cs:line 576

The exception was thrown from the line 252 of the below code:

https://github.com/planetarium/libplanet/blob/25c385d793cc2d4126c23cc6bf69933679d35b37/Libplanet/Net/Swarm.MessageHandlers.cs#L249-L252

It shows there is a case where _store.ContainsBlock(hash) returns true while _store.GetBlock<T>(..., hash) returns null.

Although I experienced this case with DefaultStore, it can be a bug of BaseStore, or RocksDBStore may have a similar bug too.

stale[bot] commented 2 years ago

This issue has been automatically marked as stale because it has not had recent activity. Thank you for your contributions.