diff --git a/.gitmodules b/.gitmodules
index 2ae26205cf..d5e540a598 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -65,7 +65,7 @@
   branch = master
 [submodule "vendor/nim-confutils"]
   path = vendor/nim-confutils
-  url = https://github.com/status-im/nim-confutils.git
+	url = https://github.com/siphiuel/nim-confutils.git
   ignore = dirty
   branch = master
 [submodule "vendor/nim-blscurve"]
diff --git a/Makefile b/Makefile
index 7a1a2274ab..0c47d9dc08 100644
--- a/Makefile
+++ b/Makefile
@@ -70,6 +70,7 @@ TOOLS_CSV := $(subst $(SPACE),$(COMMA),$(TOOLS))
 	nimbus \
 	fluffy \
 	nimbus_verified_proxy \
+	libverifproxy \
 	test \
 	test-reproducibility \
 	clean \
@@ -272,9 +273,69 @@ evmstate_test: | build deps evmstate
 txparse: | build deps
 	$(ENV_SCRIPT) nim c $(NIM_PARAMS) "tools/txparse/$@.nim"
 
+# Shared library for verified proxy
+OS = $(shell $(CC) -dumpmachine)
+ifneq (, $(findstring darwin, $(OS)))
+  SHAREDLIBEXT = a
+else
+ifneq (, $(findstring mingw, $(OS))$(findstring cygwin, $(OS))$(findstring msys, $(OS)))
+  SHAREDLIBEXT = lib
+else
+  SHAREDLIBEXT = a
+endif
+endif
+
+VERIF_PROXY_OUT_PATH ?= build/libverifproxy/
+VERIFPROXY_OBJS = $(shell find nimcache/libverifproxy -name "*.o")
+LIBNATPMP_OBJS = $(shell find vendor/nim-nat-traversal/vendor/libnatpmp-upstream -name "*.o")
+LIBMINIUPNPC_OBJS = $(shell find vendor/nim-nat-traversal/vendor/miniupnp/miniupnpc -name "*.o")
+LIBBACKTRACE_OBJS = $(shell find vendor/nim-libbacktrace/vendor/libbacktrace-upstream -name "*.o")
+LIBBACKTRACE_WRAPPER_OBJS = vendor/nim-libbacktrace/libbacktrace_wrapper.o
+ALL_OBJS = $(VERIFPROXY_OBJS) $(LIBNATPMP_OBJS) $(LIBMINIUPNPC_OBJS) $(LIBBACKTRACE_WRAPPER_OBJS) $(LIBBACKTRACE_OBJS)
+
+libverifproxy-objs: | build deps
+	+ echo -e $(BUILD_MSG) "build/$@" && \
+		$(ENV_SCRIPT) nim c --noLinking:on --gc:boehm -d:"libp2p_pki_schemes=secp256k1" --header:verifproxy.h --noMain:on --nimcache:nimcache/libverifproxy -o:build/$@ $(NIM_PARAMS) nimbus_verified_proxy/nimbus_verified_proxy.nim && \
+	mkdir -p build/libverifproxy && \
+	find nimcache/libverifproxy -name "*.o" | xargs -I {} cp {} $(VERIF_PROXY_OUT_PATH) && \
+  find vendor/nim-nat-traversal/vendor/libnatpmp-upstream -name "*.o" | xargs -I {} cp {} $(VERIF_PROXY_OUT_PATH) && \
+  find vendor/nim-nat-traversal/vendor/miniupnp/miniupnpc -name "*.o" | xargs -I {} cp {} $(VERIF_PROXY_OUT_PATH) && \
+	find vendor/nim-libbacktrace/vendor/libbacktrace-upstream -name "*.o" | xargs -I {} cp {} $(VERIF_PROXY_OUT_PATH) && \
+  cp vendor/nim-libbacktrace/libbacktrace_wrapper.o $(VERIF_PROXY_OUT_PATH) && \
+	cp nimcache/libverifproxy/verifproxy.h $(VERIF_PROXY_OUT_PATH)
+	# echo ${ALL_OBJS} | tr ' ' '\n' > build/libverifproxy-objs/objs.lst
+	echo -e $(BUILD_END_MSG) "build/$@"
+	
+	
+
+
+# gc:markAndSweep: exception "URL hostname is missing"
+# vendor/nim-json-rpc/json_rpc/rpcproxy.nim(99) start
+# vendor/nim-chronos/chronos/asyncfutures2.nim(369) futureContinue
+
+# gc:refc: SIGSEGV
+
+# gc:boehm: ok
+
+# gc:go: Error: system module needs: unsureAsgnRef during compilation
+libverifproxy: | build deps
+	+ echo -e $(BUILD_MSG) "build/$@" && \
+		$(ENV_SCRIPT) nim --version && \
+		$(ENV_SCRIPT) nim c --app:staticLib -d:"libp2p_pki_schemes=secp256k1" --opt:size --gc:boehm --header:verifproxy.h --noMain:on --nimcache:nimcache/libverifproxy -o:$(VERIF_PROXY_OUT_PATH)/$@.$(SHAREDLIBEXT) $(NIM_PARAMS) nimbus_verified_proxy/nimbus_verified_proxy.nim
+	cp nimcache/libverifproxy/verifproxy.h $(VERIF_PROXY_OUT_PATH)/
+	cp vendor/nimbus-build-system/vendor/Nim-csources-v1/c_code/nimbase.h $(VERIF_PROXY_OUT_PATH)/
+	echo -e $(BUILD_END_MSG) "build/$@"
+
+
+
+libverifproxy-source: | build deps
+	+ echo -e $(BUILD_MSG) "build/$@" && \
+	$(ENV_SCRIPT) nim c -c --genScript:on --noLinking:on -d:"libp2p_pki_schemes=secp256k1" --header:verifproxy.h --noMain:on --nimcache:nimcache/libverifproxy -o:build/$@ $(NIM_PARAMS) nimbus_verified_proxy/nimbus_verified_proxy.nim
+	echo -e $(BUILD_END_MSG) "build/$@"
+
 # usual cleaning
 clean: | clean-common
-	rm -rf build/{nimbus,fluffy,nimbus_verified_proxy,$(TOOLS_CSV),all_tests,test_kvstore_rocksdb,test_rpc,all_fluffy_tests,all_fluffy_portal_spec_tests,test_portal_testnet,portalcli,blockwalk,eth_data_exporter,utp_test_app,utp_test,*.dSYM}
+	rm -rf build/{nimbus,fluffy,libverifproxy,nimbus_verified_proxy,$(TOOLS_CSV),all_tests,test_kvstore_rocksdb,test_rpc,all_fluffy_tests,all_fluffy_portal_spec_tests,test_portal_testnet,portalcli,blockwalk,eth_data_exporter,utp_test_app,utp_test,*.dSYM}
 	rm -rf tools/t8n/{t8n,t8n_test}
 	rm -rf tools/evmstate/{evmstate,evmstate_test}
 ifneq ($(USE_LIBBACKTRACE), 0)
diff --git a/nimbus_verified_proxy/nimbus_verified_proxy.nim b/nimbus_verified_proxy/nimbus_verified_proxy.nim
index f5ec282f83..50a9192569 100644
--- a/nimbus_verified_proxy/nimbus_verified_proxy.nim
+++ b/nimbus_verified_proxy/nimbus_verified_proxy.nim
@@ -8,7 +8,7 @@
 {.push raises: [].}
 
 import
-  std/[os, strutils],
+  std/[json, os, strutils],
   chronicles, chronicles/chronos_tools, chronos, confutils,
   eth/keys,
   json_rpc/rpcproxy,
@@ -40,14 +40,29 @@ func getConfiguredChainId(networkMetadata: Eth2NetworkMetadata): Quantity =
   else:
     return networkMetadata.cfg.DEPOSIT_CHAIN_ID.Quantity
 
-proc run(config: VerifiedProxyConf) {.raises: [CatchableError].} =
+type OnHeaderCallback* = proc (s: cstring) {.cdecl.}
+
+var optimisticHeaderCallback : OnHeaderCallback = nil
+var finalizedHeaderCallback : OnHeaderCallback = nil
+proc setOptimisticHeaderCallback*(cb: OnHeaderCallback) {.exportc.} =
+  optimisticHeaderCallback = cb
+  echo "optimistic header callback set"
+
+proc setFinalizedHeaderCallback*(cb: OnHeaderCallback) {.exportc.} =
+  finalizedHeaderCallback = cb
+  echo "finalized header callback set"
+
+
+proc run(config: VerifiedProxyConf) {.raises: [CatchableError, Exception].} =
+  # echo "startLightClient inside nimbus-light-client"
+
   # Required as both Eth2Node and LightClient requires correct config type
   var lcConfig = config.asLightClientConf()
 
   setupLogging(config.logLevel, config.logStdout, none(OutFile))
 
   notice "Launching Nimbus verified proxy",
-    version = fullVersionStr, cmdParams = commandLineParams(), config
+    version = fullVersionStr, cmdParams = getCLIParams(), config
 
   let
     metadata = loadEth2Network(config.eth2Network)
@@ -153,6 +168,14 @@ proc run(config: VerifiedProxyConf) {.raises: [CatchableError].} =
       when lcDataFork > LightClientDataFork.None:
         info "New LC finalized header",
           finalized_header = shortLog(forkyHeader)
+        if finalizedHeaderCallback != nil:
+            notice "### Invoking finalizedHeaderCallback"
+            {.gcsafe.}:
+              try:
+                finalizedHeaderCallback(Json.encode(finalizedHeader))
+              except Exception as e:
+                notice "finalizedHeaderCallback exception"
+
 
   proc onOptimisticHeader(
       lightClient: LightClient, optimisticHeader: ForkedLightClientHeader) =
@@ -161,6 +184,14 @@ proc run(config: VerifiedProxyConf) {.raises: [CatchableError].} =
         info "New LC optimistic header",
           optimistic_header = shortLog(forkyHeader)
         optimisticProcessor.setOptimisticHeader(forkyHeader.beacon)
+      if optimisticHeaderCallback != nil:
+        notice "### Invoking optimisticHeaderCallback"
+        {.gcsafe.}:
+          try:
+            optimisticHeaderCallback(Json.encode(optimisticHeader))
+          except Exception:
+            notice "optimisticHeaderCallback exception"
+
 
   lightClient.onFinalizedHeader = onFinalizedHeader
   lightClient.onOptimisticHeader = onOptimisticHeader
@@ -239,10 +270,88 @@ proc run(config: VerifiedProxyConf) {.raises: [CatchableError].} =
   while true:
     poll()
 
-when isMainModule:
-  {.pop.}
-  var config = makeBannerAndConfig(
-    "Nimbus verified proxy " & fullVersionStr, VerifiedProxyConf)
-  {.push raises: [].}
+proc testEcho*() {.exportc.} =
+  echo "in testEcho"
+
+proc quit*() {.exportc.} = 
+  echo "Quitting"
+
+# template createConfig(clientId: string, ConfType: type, configFilePath: string): untyped =
+#   echo "### inside createConfig"
+#   let
+#     version = clientId & "\p" & copyrights & "\p\p" &
+#       "eth2 specification v" & SPEC_VERSION & "\p\p" &
+#       nimBanner
+
+#   # TODO for some reason, copyrights are printed when doing `--help`
+#   {.push warning[ProveInit]: off.}
+#   let config = try:
+#     echo "### inside createConfig before load"
+#     ConfType.load(
+#       version = version, # but a short version string makes more sense...
+#       copyrightBanner = clientId,
+#       secondarySources = proc (config: ConfType, sources: auto) =
+#         sources.addConfigFile(Toml, InputFile(configFilePath))
+#     )
+#   except CatchableError as err:
+#     # We need to log to stderr here, because logging hasn't been configured yet
+#     stderr.write "Failure while loading the configuration:\n"
+#     stderr.write err.msg
+#     stderr.write "\n"
+
+#     if err[] of ConfigurationError and
+#        err.parent != nil and
+#        err.parent[] of TomlFieldReadingError:
+#       let fieldName = ((ref TomlFieldReadingError)(err.parent)).field
+#       if fieldName in ["web3-url", "bootstrap-node",
+#                        "direct-peer", "validator-monitor-pubkey"]:
+#         stderr.write "Since the '" & fieldName & "' option is allowed to " &
+#                      "have more than one value, please make sure to supply " &
+#                      "a properly formatted TOML array\n"
+#     quit 1
+#   {.pop.}
+#   config
+
+proc NimMain() {.importc.}
+proc startProxyViaJson*(configJson: cstring) {.exportc.} =
+  echo "startLcViaJson"
+  NimMain()
+  echo "startLcViaJson 1"
+  let str = $configJson
+  echo "startLcViaJson 2"
+  echo "startLcViaJson 3 ", str
+  try:
+    let jsonNode = parseJson(str)
+
+    let rpcAddr = jsonNode["RpcAddress"].getStr()
+    let config = VerifiedProxyConf(
+      rpcAddress: ValidIpAddress.init(rpcAddr), 
+      listenAddress: defaultListenAddress, 
+      eth2Network: some(jsonNode["Eth2Network"].getStr()), 
+      trustedBlockRoot: Eth2Digest.fromHex(jsonNode["TrustedBlockRoot"].getStr()),
+      web3Url: parseCmdArg(ValidatedWeb3Url, jsonNode["Web3Url"].getStr()),
+      rpcPort: Port(jsonNode["RpcPort"].getInt()),
+      logLevel: jsonNode["LogLevel"].getStr(),
+      maxPeers: 160,
+      nat: NatConfig(hasExtIp: false, nat: NatAny),
+      logStdout: StdoutLogKind.Auto,
+      dataDir: OutDir(defaultVerifiedProxyDataDir()),
+      tcpPort: Port(defaultEth2TcpPort),
+      udpPort: Port(defaultEth2TcpPort),
+      agentString: "nimbus",
+      discv5Enabled: true,
+    )
+
+    run(config)
+  except Exception as err:
+    echo "Exception when running ", getCurrentExceptionMsg(), err.getStackTrace() 
+
+# when isMainModule:
+#   let configFileStr = "config.toml"
+#   {.pop.}
+#   var config = createConfig("Nimbus verified proxy " & fullVersionStr, VerifiedProxyConf, configFileStr)
+
+#   {.push raises: [Defect].}
 
-  run(config)
+#   echo "inside nimbus-light-client before run"
+#   run(config)
diff --git a/vendor/nim-confutils b/vendor/nim-confutils
index 38dfeaaabd..1cd27f83f4 160000
--- a/vendor/nim-confutils
+++ b/vendor/nim-confutils
@@ -1 +1 @@
-Subproject commit 38dfeaaabdc6792d0f4d701621cbe34001978456
+Subproject commit 1cd27f83f42063eabb5515ae1358ea8858176546