nimiq / core-rs-albatross

Rust implementation of the Albatross protocol
https://nimiq.com
Other
159 stars 63 forks source link

Upstreaming libp2p broke NodeJS support of the web-client #2301

Closed sisou closed 3 weeks ago

sisou commented 5 months ago

General information

Bug report

Expected behavior

NodeJS can run the client in a worker_thread, for which I created a special entry point.

Actual behavior

The client in a NodeJS worker thread panics with 'to have a window or worker context', which is the exact panic added in https://github.com/libp2p/rust-libp2p/pull/4889.

Steps to reproduce

Run the NodeJS example in the web-client/example/node. Make sure to follow the instructions in web-client/example/README.md.

Crash log? Screenshots? Videos? Sample project?

image

2024-03-08T20:11:56.006000128Z ERROR panic                | thread '<unnamed>' panicked at 'to have a window or worker context': /home/soeren/.cargo/registry/src/index.crates.io-6f17d22bba15001f/libp2p-websocket-websys-0.3.1/src/lib.rs:308 

Question or Feature Request

Add support for NodeJS Worker Threads to libp2p's websocket-websys transport?

I need to find out how it worked before libp2p was upstreamed in #2047, as it did work before, when I added NodeJS support and the example.

sisou commented 5 months ago

Before the change to WindowOrWorkerContext, the websocket-websys transport was patched to bind to global setTimeout and clearTimeout directly, without having to have web-sys's Window or WorkerContext: https://github.com/jsdanielh/rust-libp2p/commit/34f65f1c2d670be02a572412bf90a093a04835af

sisou commented 5 months ago

I'm able to pass the first initialization check of the client by mocking WorkerGlobalScope in the NodeJS worker thread:

global.WorkerGlobalScope = global;

However, the client still exits with an error later on, after requesting/receiving ZKPs. On my second run, it actually established consensus and then errored and exited. Unfortunately the error is not very descriptive, even when run in vscode's debugger:

 Uncaught Error Error
     at <anonymous> (node:internal/event_target:1062:28)
     at processTicksAndRejections (node:internal/process/task_queues:77:11)
     --- TickObject ---
     at init (node:internal/inspector_async_hook:25:19)
     at emitInitNative (node:internal/async_hooks:200:43)
     at emitInitScript (node:internal/async_hooks:503:3)
     at nextTick (node:internal/process/task_queues:132:5)
     at emitUncaughtException (node:internal/event_target:1062:11)
     at [nodejs.internal.kHybridDispatch] (node:internal/event_target:794:9)
     at exports.emitMessage (node:internal/per_context/messageport:23:28)
     at callbackTrampoline (node:internal/async_hooks:128:17)
     --- MESSAGEPORT ---
     at init (node:internal/inspector_async_hook:25:19)
     at emitInitNative (node:internal/async_hooks:200:43)
     at Worker (node:internal/worker:207:21)
     at <anonymous> (file:///home/soeren/nimiq/core-rs-albatross/web-client/example/node/node_modules/@nimiq/core-web/nodejs/index.js:15:11)
     at create (file:///home/soeren/nimiq/core-rs-albatross/web-client/example/node/node_modules/@nimiq/core-web/lib/node/client-proxy.js:28:22)
     at main (file:///home/soeren/nimiq/core-rs-albatross/web-client/example/node/index.js:7:39)
     at <anonymous> (file:///home/soeren/nimiq/core-rs-albatross/web-client/example/node/index.js:15:1)
     at Module._compile (node:internal/modules/cjs/loader:1356:14)
     at Module._extensions..js (node:internal/modules/cjs/loader:1414:10)
     at Module.load (node:internal/modules/cjs/loader:1197:32)
     at Module._load (node:internal/modules/cjs/loader:1013:12)
     at executeUserEntryPoint (node:internal/modules/run_main:128:12)
     at <anonymous> (node:internal/main/run_main_module:28:49)
 Process exited with code 1
Eligioo commented 5 months ago

It turns out the uncaught error that is thrown and mentioned by @sisou is closure invoked recursively or after being dropped meaning that on the 'JS-side' a closure (probably) is being called that already has been dropped. In NodeJS this is causes an uncaught exception, which makes sense. But nowadays NodeJS actually exits the process on uncaught exceptions.

So this is unrelated to requesting/receiving zkps but rather connections that aren't cleaned up properly.

sisou commented 5 months ago

I have created a PR in libp2p to fix part of the closure invoked after being dropped problem: https://github.com/libp2p/rust-libp2p/pull/5229. The main problem remains, though.

sisou commented 3 weeks ago

Workaround was merged in #2302.