ConsenSysMesh / cava

ConsenSys core libraries for Java & Kotlin
Apache License 2.0
84 stars 34 forks source link

Periodic sodium OutOfMemory exception when consuming scuttlebutt streams #205

Closed Happy0 closed 5 years ago

Happy0 commented 5 years ago

When consuming a scuttlebutt stream, there are periodic sodium OutOfMemory exception errors while decrypting the messages received as responses from the server for random messages received:

2019-04-02 09:37:20.086+0000 ERROR [localhost:8008] Sodium.sodium_malloc failed allocating 24
java.lang.OutOfMemoryError: Sodium.sodium_malloc failed allocating 24
    at net.consensys.cava.crypto.sodium.Sodium.malloc(Sodium.java:224)
    at net.consensys.cava.crypto.sodium.Sodium.dup(Sodium.java:262)
    at net.consensys.cava.crypto.sodium.Sodium.dup(Sodium.java:273)
    at net.consensys.cava.crypto.sodium.SecretBox$Nonce.fromBytes(SecretBox.java:230)
    at net.consensys.cava.crypto.sodium.SecretBox$Nonce.fromBytes(SecretBox.java:213)
    at net.consensys.cava.scuttlebutt.handshake.SecureScuttlebuttStream.decryptMessage(SecureScuttlebuttStream.java:107)
    at net.consensys.cava.scuttlebutt.handshake.SecureScuttlebuttStream.decrypt(SecureScuttlebuttStream.java:85)
    at net.consensys.cava.scuttlebutt.handshake.SecureScuttlebuttStream.readFromServer(SecureScuttlebuttStream.java:53)
    at net.consensys.cava.scuttlebutt.handshake.vertx.SecureScuttlebuttVertxClient$NetSocketClientHandler.handle(SecureScuttlebuttVertxClient.java:98)
    at io.vertx.core.net.impl.NetSocketImpl$DataMessageHandler.handle(NetSocketImpl.java:392)
    at io.vertx.core.streams.impl.InboundBuffer.handleEvent(InboundBuffer.java:225)
    at io.vertx.core.streams.impl.InboundBuffer.write(InboundBuffer.java:123)
    at io.vertx.core.net.impl.NetSocketImpl.handleMessage(NetSocketImpl.java:370)
    at io.vertx.core.net.impl.ConnectionBase.handleRead(ConnectionBase.java:386)
    at io.vertx.core.impl.ContextImpl.executeTask(ContextImpl.java:320)
    at io.vertx.core.impl.EventLoopContext.execute(EventLoopContext.java:43)
    at io.vertx.core.impl.ContextImpl.executeFromIO(ContextImpl.java:188)
    at io.vertx.core.net.impl.VertxHandler.channelRead(VertxHandler.java:174)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
    at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1434)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:965)
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:644)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:579)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:496)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:458)
    at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:897)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.lang.Thread.run(Thread.java:748)

Steps to reproduce:

  1. Check out the branch underlying https://github.com/ConsenSys/cava/pull/202/files
  2. Modify the postMessageTest test in the PatchworkIntegrationText file in the mux test package to post 20,000 messages by changing the for loop to iterate more and run the test. I'm not sure the minimum number of items in a stream required to make the error happen.
  3. Run the streamTest test in the PatchworkIntegrationTest file in the mux package.
  4. Observe the above error is occasionally output in the log.
Happy0 commented 5 years ago

To stop the vertx event loop timing out on futures that are waiting seconds for their turn for their message to be written, I had to change the test to just block on each write to reproduce this:

 public void postMessageTest(@VertxInstance Vertx vertx) throws Exception {

    RPCHandler rpcHandler = makeRPCHandler(vertx);

    for (int i = 0; i < 10000; i++) {
      // Note: in a real use case, this would more likely be a Java class with these fields
      HashMap<String, String> params = new HashMap<>();
      params.put("type", "post");
      params.put("text", "test test " + i);

      RPCAsyncRequest asyncRequest = new RPCAsyncRequest(new RPCFunction("publish"), Arrays.asList(params));

      AsyncResult<RPCMessage> rpcMessageAsyncResult = rpcHandler.makeAsyncRequest(asyncRequest);
      System.out.println(rpcMessageAsyncResult.get());

    }
  }