Feature: Use napi-rs instead of neon
This commit is contained in:
		
							parent
							
								
									20dbcf14c9
								
							
						
					
					
						commit
						35764a29a7
					
				
							
								
								
									
										152
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										152
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							@ -2,12 +2,27 @@
 | 
			
		||||
# It is not intended for manual editing.
 | 
			
		||||
version = 3
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "aho-corasick"
 | 
			
		||||
version = "1.0.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "memchr",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "autocfg"
 | 
			
		||||
version = "1.1.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "bitflags"
 | 
			
		||||
version = "2.3.2"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "6dbe3c979c178231552ecba20214a8272df4e09f232a87aef4320cf06539aded"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "bytes"
 | 
			
		||||
version = "1.4.0"
 | 
			
		||||
@ -20,12 +35,33 @@ version = "1.0.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "convert_case"
 | 
			
		||||
version = "0.6.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "unicode-segmentation",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "ctor"
 | 
			
		||||
version = "0.2.2"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "1586fa608b1dab41f667475b4a41faec5ba680aee428bfa5de4ea520fdc6e901"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "quote",
 | 
			
		||||
 "syn 2.0.20",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "gbt"
 | 
			
		||||
version = "0.1.0"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "bytes",
 | 
			
		||||
 "neon",
 | 
			
		||||
 "napi",
 | 
			
		||||
 "napi-build",
 | 
			
		||||
 "napi-derive",
 | 
			
		||||
 "once_cell",
 | 
			
		||||
 "priority-queue",
 | 
			
		||||
]
 | 
			
		||||
@ -48,53 +84,75 @@ dependencies = [
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "libloading"
 | 
			
		||||
version = "0.6.7"
 | 
			
		||||
version = "0.7.4"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883"
 | 
			
		||||
checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "cfg-if",
 | 
			
		||||
 "winapi",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "neon"
 | 
			
		||||
version = "0.10.1"
 | 
			
		||||
name = "memchr"
 | 
			
		||||
version = "2.5.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "28e15415261d880aed48122e917a45e87bb82cf0260bb6db48bbab44b7464373"
 | 
			
		||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "napi"
 | 
			
		||||
version = "2.13.2"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "0ede2d12cd6fce44da537a4be1f5510c73be2506c2e32dfaaafd1f36968f3a0e"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "neon-build",
 | 
			
		||||
 "neon-macros",
 | 
			
		||||
 "neon-runtime",
 | 
			
		||||
 "semver",
 | 
			
		||||
 "smallvec",
 | 
			
		||||
 "bitflags",
 | 
			
		||||
 "ctor",
 | 
			
		||||
 "napi-derive",
 | 
			
		||||
 "napi-sys",
 | 
			
		||||
 "once_cell",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "neon-build"
 | 
			
		||||
version = "0.10.1"
 | 
			
		||||
name = "napi-build"
 | 
			
		||||
version = "2.0.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "8bac98a702e71804af3dacfde41edde4a16076a7bbe889ae61e56e18c5b1c811"
 | 
			
		||||
checksum = "882a73d9ef23e8dc2ebbffb6a6ae2ef467c0f18ac10711e4cc59c5485d41df0e"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "neon-macros"
 | 
			
		||||
version = "0.10.1"
 | 
			
		||||
name = "napi-derive"
 | 
			
		||||
version = "2.13.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "b7288eac8b54af7913c60e0eb0e2a7683020dffa342ab3fd15e28f035ba897cf"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "quote",
 | 
			
		||||
 "syn",
 | 
			
		||||
 "syn-mid",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "neon-runtime"
 | 
			
		||||
version = "0.10.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "4676720fa8bb32c64c3d9f49c47a47289239ec46b4bdb66d0913cc512cb0daca"
 | 
			
		||||
checksum = "da1c6a8fa84d549aa8708fcd062372bf8ec6e849de39016ab921067d21bde367"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "cfg-if",
 | 
			
		||||
 "convert_case",
 | 
			
		||||
 "napi-derive-backend",
 | 
			
		||||
 "proc-macro2",
 | 
			
		||||
 "quote",
 | 
			
		||||
 "syn 1.0.109",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "napi-derive-backend"
 | 
			
		||||
version = "1.0.52"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "20bbc7c69168d06a848f925ec5f0e0997f98e8c8d4f2cc30157f0da51c009e17"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "convert_case",
 | 
			
		||||
 "once_cell",
 | 
			
		||||
 "proc-macro2",
 | 
			
		||||
 "quote",
 | 
			
		||||
 "regex",
 | 
			
		||||
 "semver",
 | 
			
		||||
 "syn 1.0.109",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "napi-sys"
 | 
			
		||||
version = "2.2.3"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "166b5ef52a3ab5575047a9fe8d4a030cdd0f63c96f071cd6907674453b07bae3"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "libloading",
 | 
			
		||||
 "smallvec",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
@ -132,25 +190,27 @@ dependencies = [
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "semver"
 | 
			
		||||
version = "0.9.0"
 | 
			
		||||
name = "regex"
 | 
			
		||||
version = "1.8.3"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
 | 
			
		||||
checksum = "81ca098a9821bd52d6b24fd8b10bd081f47d39c22778cafaa75a2857a62c6390"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "semver-parser",
 | 
			
		||||
 "aho-corasick",
 | 
			
		||||
 "memchr",
 | 
			
		||||
 "regex-syntax",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "semver-parser"
 | 
			
		||||
version = "0.7.0"
 | 
			
		||||
name = "regex-syntax"
 | 
			
		||||
version = "0.7.2"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
 | 
			
		||||
checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "smallvec"
 | 
			
		||||
version = "1.10.0"
 | 
			
		||||
name = "semver"
 | 
			
		||||
version = "1.0.17"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
 | 
			
		||||
checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "syn"
 | 
			
		||||
@ -164,14 +224,14 @@ dependencies = [
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "syn-mid"
 | 
			
		||||
version = "0.5.3"
 | 
			
		||||
name = "syn"
 | 
			
		||||
version = "2.0.20"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "baa8e7560a164edb1621a55d18a0c59abf49d360f47aa7b821061dd7eea7fac9"
 | 
			
		||||
checksum = "fcb8d4cebc40aa517dfb69618fa647a346562e67228e2236ae0042ee6ac14775"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "proc-macro2",
 | 
			
		||||
 "quote",
 | 
			
		||||
 "syn",
 | 
			
		||||
 "unicode-ident",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
@ -180,6 +240,12 @@ version = "1.0.9"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "unicode-segmentation"
 | 
			
		||||
version = "1.10.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "winapi"
 | 
			
		||||
version = "0.3.9"
 | 
			
		||||
 | 
			
		||||
@ -2,3 +2,7 @@
 | 
			
		||||
members = [
 | 
			
		||||
	"./backend/rust-gbt",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[profile.release]
 | 
			
		||||
lto = true
 | 
			
		||||
codegen-units = 1
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2
									
								
								backend/rust-gbt/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								backend/rust-gbt/.gitignore
									
									
									
									
										vendored
									
									
								
							@ -1,4 +1,4 @@
 | 
			
		||||
index.node
 | 
			
		||||
*.node
 | 
			
		||||
**/node_modules
 | 
			
		||||
**/.DS_Store
 | 
			
		||||
npm-debug.log*
 | 
			
		||||
 | 
			
		||||
@ -15,8 +15,8 @@ crate-type = ["cdylib"]
 | 
			
		||||
priority-queue = "1.3.2"
 | 
			
		||||
bytes = "1.4.0"
 | 
			
		||||
once_cell = "1.18.0"
 | 
			
		||||
napi = { version = "2.13.2", features = ["napi8"] }
 | 
			
		||||
napi-derive = "2.13.0"
 | 
			
		||||
 | 
			
		||||
[dependencies.neon]
 | 
			
		||||
version = "0.10"
 | 
			
		||||
default-features = false
 | 
			
		||||
features = ["napi-6","channel-api"]
 | 
			
		||||
[build-dependencies]
 | 
			
		||||
napi-build = "2.0.1"
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										3
									
								
								backend/rust-gbt/build.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								backend/rust-gbt/build.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
			
		||||
fn main() {
 | 
			
		||||
    napi_build::setup();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13
									
								
								backend/rust-gbt/index.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								backend/rust-gbt/index.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
 | 
			
		||||
/* auto-generated by NAPI-RS */
 | 
			
		||||
 | 
			
		||||
export function make(mempoolBuffer: Uint8Array, callback: (arg0: GbtResult) => void): void
 | 
			
		||||
export function update(newTxs: Uint8Array, removeTxs: Uint8Array, callback: (arg0: GbtResult) => void): void
 | 
			
		||||
export class GbtResult {
 | 
			
		||||
  blocks: Array<Array<number>>
 | 
			
		||||
  clusters: Array<Array<number>>
 | 
			
		||||
  rates: Array<Array<number>>
 | 
			
		||||
  constructor(blocks: Array<Array<number>>, clusters: Array<Array<number>>, rates: Array<Array<number>>)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										259
									
								
								backend/rust-gbt/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										259
									
								
								backend/rust-gbt/index.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,259 @@
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
/* prettier-ignore */
 | 
			
		||||
 | 
			
		||||
/* auto-generated by NAPI-RS */
 | 
			
		||||
 | 
			
		||||
const { existsSync, readFileSync } = require('fs')
 | 
			
		||||
const { join } = require('path')
 | 
			
		||||
 | 
			
		||||
const { platform, arch } = process
 | 
			
		||||
 | 
			
		||||
let nativeBinding = null
 | 
			
		||||
let localFileExisted = false
 | 
			
		||||
let loadError = null
 | 
			
		||||
 | 
			
		||||
function isMusl() {
 | 
			
		||||
  // For Node 10
 | 
			
		||||
  if (!process.report || typeof process.report.getReport !== 'function') {
 | 
			
		||||
    try {
 | 
			
		||||
      const lddPath = require('child_process').execSync('which ldd').toString().trim()
 | 
			
		||||
      return readFileSync(lddPath, 'utf8').includes('musl')
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      return true
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    const { glibcVersionRuntime } = process.report.getReport().header
 | 
			
		||||
    return !glibcVersionRuntime
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
switch (platform) {
 | 
			
		||||
  case 'android':
 | 
			
		||||
    switch (arch) {
 | 
			
		||||
      case 'arm64':
 | 
			
		||||
        localFileExisted = existsSync(join(__dirname, 'gbt.android-arm64.node'))
 | 
			
		||||
        try {
 | 
			
		||||
          if (localFileExisted) {
 | 
			
		||||
            nativeBinding = require('./gbt.android-arm64.node')
 | 
			
		||||
          } else {
 | 
			
		||||
            nativeBinding = require('gbt-android-arm64')
 | 
			
		||||
          }
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
          loadError = e
 | 
			
		||||
        }
 | 
			
		||||
        break
 | 
			
		||||
      case 'arm':
 | 
			
		||||
        localFileExisted = existsSync(join(__dirname, 'gbt.android-arm-eabi.node'))
 | 
			
		||||
        try {
 | 
			
		||||
          if (localFileExisted) {
 | 
			
		||||
            nativeBinding = require('./gbt.android-arm-eabi.node')
 | 
			
		||||
          } else {
 | 
			
		||||
            nativeBinding = require('gbt-android-arm-eabi')
 | 
			
		||||
          }
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
          loadError = e
 | 
			
		||||
        }
 | 
			
		||||
        break
 | 
			
		||||
      default:
 | 
			
		||||
        throw new Error(`Unsupported architecture on Android ${arch}`)
 | 
			
		||||
    }
 | 
			
		||||
    break
 | 
			
		||||
  case 'win32':
 | 
			
		||||
    switch (arch) {
 | 
			
		||||
      case 'x64':
 | 
			
		||||
        localFileExisted = existsSync(
 | 
			
		||||
          join(__dirname, 'gbt.win32-x64-msvc.node')
 | 
			
		||||
        )
 | 
			
		||||
        try {
 | 
			
		||||
          if (localFileExisted) {
 | 
			
		||||
            nativeBinding = require('./gbt.win32-x64-msvc.node')
 | 
			
		||||
          } else {
 | 
			
		||||
            nativeBinding = require('gbt-win32-x64-msvc')
 | 
			
		||||
          }
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
          loadError = e
 | 
			
		||||
        }
 | 
			
		||||
        break
 | 
			
		||||
      case 'ia32':
 | 
			
		||||
        localFileExisted = existsSync(
 | 
			
		||||
          join(__dirname, 'gbt.win32-ia32-msvc.node')
 | 
			
		||||
        )
 | 
			
		||||
        try {
 | 
			
		||||
          if (localFileExisted) {
 | 
			
		||||
            nativeBinding = require('./gbt.win32-ia32-msvc.node')
 | 
			
		||||
          } else {
 | 
			
		||||
            nativeBinding = require('gbt-win32-ia32-msvc')
 | 
			
		||||
          }
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
          loadError = e
 | 
			
		||||
        }
 | 
			
		||||
        break
 | 
			
		||||
      case 'arm64':
 | 
			
		||||
        localFileExisted = existsSync(
 | 
			
		||||
          join(__dirname, 'gbt.win32-arm64-msvc.node')
 | 
			
		||||
        )
 | 
			
		||||
        try {
 | 
			
		||||
          if (localFileExisted) {
 | 
			
		||||
            nativeBinding = require('./gbt.win32-arm64-msvc.node')
 | 
			
		||||
          } else {
 | 
			
		||||
            nativeBinding = require('gbt-win32-arm64-msvc')
 | 
			
		||||
          }
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
          loadError = e
 | 
			
		||||
        }
 | 
			
		||||
        break
 | 
			
		||||
      default:
 | 
			
		||||
        throw new Error(`Unsupported architecture on Windows: ${arch}`)
 | 
			
		||||
    }
 | 
			
		||||
    break
 | 
			
		||||
  case 'darwin':
 | 
			
		||||
    localFileExisted = existsSync(join(__dirname, 'gbt.darwin-universal.node'))
 | 
			
		||||
    try {
 | 
			
		||||
      if (localFileExisted) {
 | 
			
		||||
        nativeBinding = require('./gbt.darwin-universal.node')
 | 
			
		||||
      } else {
 | 
			
		||||
        nativeBinding = require('gbt-darwin-universal')
 | 
			
		||||
      }
 | 
			
		||||
      break
 | 
			
		||||
    } catch {}
 | 
			
		||||
    switch (arch) {
 | 
			
		||||
      case 'x64':
 | 
			
		||||
        localFileExisted = existsSync(join(__dirname, 'gbt.darwin-x64.node'))
 | 
			
		||||
        try {
 | 
			
		||||
          if (localFileExisted) {
 | 
			
		||||
            nativeBinding = require('./gbt.darwin-x64.node')
 | 
			
		||||
          } else {
 | 
			
		||||
            nativeBinding = require('gbt-darwin-x64')
 | 
			
		||||
          }
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
          loadError = e
 | 
			
		||||
        }
 | 
			
		||||
        break
 | 
			
		||||
      case 'arm64':
 | 
			
		||||
        localFileExisted = existsSync(
 | 
			
		||||
          join(__dirname, 'gbt.darwin-arm64.node')
 | 
			
		||||
        )
 | 
			
		||||
        try {
 | 
			
		||||
          if (localFileExisted) {
 | 
			
		||||
            nativeBinding = require('./gbt.darwin-arm64.node')
 | 
			
		||||
          } else {
 | 
			
		||||
            nativeBinding = require('gbt-darwin-arm64')
 | 
			
		||||
          }
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
          loadError = e
 | 
			
		||||
        }
 | 
			
		||||
        break
 | 
			
		||||
      default:
 | 
			
		||||
        throw new Error(`Unsupported architecture on macOS: ${arch}`)
 | 
			
		||||
    }
 | 
			
		||||
    break
 | 
			
		||||
  case 'freebsd':
 | 
			
		||||
    if (arch !== 'x64') {
 | 
			
		||||
      throw new Error(`Unsupported architecture on FreeBSD: ${arch}`)
 | 
			
		||||
    }
 | 
			
		||||
    localFileExisted = existsSync(join(__dirname, 'gbt.freebsd-x64.node'))
 | 
			
		||||
    try {
 | 
			
		||||
      if (localFileExisted) {
 | 
			
		||||
        nativeBinding = require('./gbt.freebsd-x64.node')
 | 
			
		||||
      } else {
 | 
			
		||||
        nativeBinding = require('gbt-freebsd-x64')
 | 
			
		||||
      }
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      loadError = e
 | 
			
		||||
    }
 | 
			
		||||
    break
 | 
			
		||||
  case 'linux':
 | 
			
		||||
    switch (arch) {
 | 
			
		||||
      case 'x64':
 | 
			
		||||
        if (isMusl()) {
 | 
			
		||||
          localFileExisted = existsSync(
 | 
			
		||||
            join(__dirname, 'gbt.linux-x64-musl.node')
 | 
			
		||||
          )
 | 
			
		||||
          try {
 | 
			
		||||
            if (localFileExisted) {
 | 
			
		||||
              nativeBinding = require('./gbt.linux-x64-musl.node')
 | 
			
		||||
            } else {
 | 
			
		||||
              nativeBinding = require('gbt-linux-x64-musl')
 | 
			
		||||
            }
 | 
			
		||||
          } catch (e) {
 | 
			
		||||
            loadError = e
 | 
			
		||||
          }
 | 
			
		||||
        } else {
 | 
			
		||||
          localFileExisted = existsSync(
 | 
			
		||||
            join(__dirname, 'gbt.linux-x64-gnu.node')
 | 
			
		||||
          )
 | 
			
		||||
          try {
 | 
			
		||||
            if (localFileExisted) {
 | 
			
		||||
              nativeBinding = require('./gbt.linux-x64-gnu.node')
 | 
			
		||||
            } else {
 | 
			
		||||
              nativeBinding = require('gbt-linux-x64-gnu')
 | 
			
		||||
            }
 | 
			
		||||
          } catch (e) {
 | 
			
		||||
            loadError = e
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        break
 | 
			
		||||
      case 'arm64':
 | 
			
		||||
        if (isMusl()) {
 | 
			
		||||
          localFileExisted = existsSync(
 | 
			
		||||
            join(__dirname, 'gbt.linux-arm64-musl.node')
 | 
			
		||||
          )
 | 
			
		||||
          try {
 | 
			
		||||
            if (localFileExisted) {
 | 
			
		||||
              nativeBinding = require('./gbt.linux-arm64-musl.node')
 | 
			
		||||
            } else {
 | 
			
		||||
              nativeBinding = require('gbt-linux-arm64-musl')
 | 
			
		||||
            }
 | 
			
		||||
          } catch (e) {
 | 
			
		||||
            loadError = e
 | 
			
		||||
          }
 | 
			
		||||
        } else {
 | 
			
		||||
          localFileExisted = existsSync(
 | 
			
		||||
            join(__dirname, 'gbt.linux-arm64-gnu.node')
 | 
			
		||||
          )
 | 
			
		||||
          try {
 | 
			
		||||
            if (localFileExisted) {
 | 
			
		||||
              nativeBinding = require('./gbt.linux-arm64-gnu.node')
 | 
			
		||||
            } else {
 | 
			
		||||
              nativeBinding = require('gbt-linux-arm64-gnu')
 | 
			
		||||
            }
 | 
			
		||||
          } catch (e) {
 | 
			
		||||
            loadError = e
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        break
 | 
			
		||||
      case 'arm':
 | 
			
		||||
        localFileExisted = existsSync(
 | 
			
		||||
          join(__dirname, 'gbt.linux-arm-gnueabihf.node')
 | 
			
		||||
        )
 | 
			
		||||
        try {
 | 
			
		||||
          if (localFileExisted) {
 | 
			
		||||
            nativeBinding = require('./gbt.linux-arm-gnueabihf.node')
 | 
			
		||||
          } else {
 | 
			
		||||
            nativeBinding = require('gbt-linux-arm-gnueabihf')
 | 
			
		||||
          }
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
          loadError = e
 | 
			
		||||
        }
 | 
			
		||||
        break
 | 
			
		||||
      default:
 | 
			
		||||
        throw new Error(`Unsupported architecture on Linux: ${arch}`)
 | 
			
		||||
    }
 | 
			
		||||
    break
 | 
			
		||||
  default:
 | 
			
		||||
    throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
if (!nativeBinding) {
 | 
			
		||||
  if (loadError) {
 | 
			
		||||
    throw loadError
 | 
			
		||||
  }
 | 
			
		||||
  throw new Error(`Failed to load native binding`)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const { make, update, GbtResult } = nativeBinding
 | 
			
		||||
 | 
			
		||||
module.exports.make = make
 | 
			
		||||
module.exports.update = update
 | 
			
		||||
module.exports.GbtResult = GbtResult
 | 
			
		||||
							
								
								
									
										22
									
								
								backend/rust-gbt/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										22
									
								
								backend/rust-gbt/package-lock.json
									
									
									
										generated
									
									
									
								
							@ -9,16 +9,26 @@
 | 
			
		||||
      "version": "0.1.0",
 | 
			
		||||
      "hasInstallScript": true,
 | 
			
		||||
      "devDependencies": {
 | 
			
		||||
        "cargo-cp-artifact": "^0.1"
 | 
			
		||||
        "@napi-rs/cli": "^2.16.1"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">= 12"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/cargo-cp-artifact": {
 | 
			
		||||
      "version": "0.1.8",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/cargo-cp-artifact/-/cargo-cp-artifact-0.1.8.tgz",
 | 
			
		||||
      "integrity": "sha512-3j4DaoTrsCD1MRkTF2Soacii0Nx7UHCce0EwUf4fHnggwiE4fbmF2AbnfzayR36DF8KGadfh7M/Yfy625kgPlA==",
 | 
			
		||||
    "node_modules/@napi-rs/cli": {
 | 
			
		||||
      "version": "2.16.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@napi-rs/cli/-/cli-2.16.1.tgz",
 | 
			
		||||
      "integrity": "sha512-L0Gr5iEQIDEbvWdDr1HUaBOxBSHL1VZhWSk1oryawoT8qJIY+KGfLFelU+Qma64ivCPbxYpkfPoKYVG3rcoGIA==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "bin": {
 | 
			
		||||
        "cargo-cp-artifact": "bin/cargo-cp-artifact.js"
 | 
			
		||||
        "napi": "scripts/index.js"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">= 10"
 | 
			
		||||
      },
 | 
			
		||||
      "funding": {
 | 
			
		||||
        "type": "github",
 | 
			
		||||
        "url": "https://github.com/sponsors/Brooooooklyn"
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -2,16 +2,32 @@
 | 
			
		||||
  "name": "gbt",
 | 
			
		||||
  "version": "0.1.0",
 | 
			
		||||
  "description": "An inefficient re-implementation of the getBlockTemplate algorithm in Rust",
 | 
			
		||||
  "main": "index.node",
 | 
			
		||||
  "main": "index.js",
 | 
			
		||||
  "types": "index.d.ts",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "build": "cargo-cp-artifact -nc index.node -- cargo build --message-format=json-render-diagnostics",
 | 
			
		||||
    "artifacts": "napi artifacts",
 | 
			
		||||
    "build": "napi build --platform",
 | 
			
		||||
    "build-debug": "npm run build --",
 | 
			
		||||
    "build-release": "npm run build -- --release",
 | 
			
		||||
    "install": "npm run build-release",
 | 
			
		||||
    "prepublishOnly": "napi prepublish -t npm",
 | 
			
		||||
    "test": "cargo test"
 | 
			
		||||
  },
 | 
			
		||||
  "author": "mononaut",
 | 
			
		||||
  "napi": {
 | 
			
		||||
    "name": "gbt",
 | 
			
		||||
    "triples": {
 | 
			
		||||
      "defaults": false,
 | 
			
		||||
      "additional": [
 | 
			
		||||
        "x86_64-unknown-linux-gnu",
 | 
			
		||||
        "x86_64-unknown-freebsd"
 | 
			
		||||
      ]
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "cargo-cp-artifact": "^0.1"
 | 
			
		||||
    "@napi-rs/cli": "^2.16.1"
 | 
			
		||||
  },
 | 
			
		||||
  "engines": {
 | 
			
		||||
    "node": ">= 12"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -1,9 +1,12 @@
 | 
			
		||||
use priority_queue::PriorityQueue;
 | 
			
		||||
use std::cmp::Ordering;
 | 
			
		||||
use std::collections::{HashMap, HashSet, VecDeque};
 | 
			
		||||
use std::{
 | 
			
		||||
    cmp::Ordering,
 | 
			
		||||
    collections::{HashMap, HashSet, VecDeque},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
use crate::audit_transaction::AuditTransaction;
 | 
			
		||||
use crate::thread_transaction::ThreadTransaction;
 | 
			
		||||
use crate::{
 | 
			
		||||
    audit_transaction::AuditTransaction, thread_transaction::ThreadTransaction, GbtResult,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const BLOCK_WEIGHT_UNITS: u32 = 4_000_000;
 | 
			
		||||
const BLOCK_SIGOPS: u32 = 80_000;
 | 
			
		||||
@ -35,14 +38,6 @@ impl Ord for TxPriority {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// The result from calling the gbt function.
 | 
			
		||||
///
 | 
			
		||||
/// This tuple contains the following:
 | 
			
		||||
/// 1. A 2D Vector of transaction IDs (u32), the inner Vecs each represent a block.
 | 
			
		||||
/// 2. A Vector of tuples containing transaction IDs (u32) and effective fee per vsize (f64)
 | 
			
		||||
/// 3. A 2D Vector of transaction IDs representing clusters of dependent mempool transactions
 | 
			
		||||
pub type GbtResult = (Vec<Vec<u32>>, Vec<(u32, f64)>, Vec<Vec<u32>>);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
* Build projected mempool blocks using an approximation of the transaction selection algorithm from Bitcoin Core
 | 
			
		||||
* (see BlockAssembler in https://github.com/bitcoin/bitcoin/blob/master/src/node/miner.cpp)
 | 
			
		||||
@ -51,7 +46,7 @@ pub type GbtResult = (Vec<Vec<u32>>, Vec<(u32, f64)>, Vec<Vec<u32>>);
 | 
			
		||||
pub fn gbt(mempool: &mut HashMap<u32, ThreadTransaction>) -> Option<GbtResult> {
 | 
			
		||||
    let mut audit_pool: HashMap<u32, AuditTransaction> = HashMap::new();
 | 
			
		||||
    let mut mempool_array: VecDeque<u32> = VecDeque::new();
 | 
			
		||||
    let mut cluster_array: Vec<Vec<u32>> = Vec::new();
 | 
			
		||||
    let mut clusters: Vec<Vec<u32>> = Vec::new();
 | 
			
		||||
 | 
			
		||||
    // Initialize working structs
 | 
			
		||||
    for (uid, tx) in mempool {
 | 
			
		||||
@ -130,7 +125,7 @@ pub fn gbt(mempool: &mut HashMap<u32, ThreadTransaction>) -> Option<GbtResult> {
 | 
			
		||||
            package.sort_unstable_by_key(|a| 0 - a.1);
 | 
			
		||||
 | 
			
		||||
            if is_cluster {
 | 
			
		||||
                cluster_array.push(cluster);
 | 
			
		||||
                clusters.push(cluster);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            let cluster_rate = next_tx
 | 
			
		||||
@ -197,14 +192,18 @@ pub fn gbt(mempool: &mut HashMap<u32, ThreadTransaction>) -> Option<GbtResult> {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // make a list of dirty transactions and their new rates
 | 
			
		||||
    let mut rates: Vec<(u32, f64)> = Vec::new();
 | 
			
		||||
    let mut rates: Vec<Vec<f64>> = Vec::new();
 | 
			
		||||
    for (txid, tx) in audit_pool {
 | 
			
		||||
        if tx.dirty {
 | 
			
		||||
            rates.push((txid, tx.effective_fee_per_vsize));
 | 
			
		||||
            rates.push(vec![txid as f64, tx.effective_fee_per_vsize]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Some((blocks, rates, cluster_array))
 | 
			
		||||
    Some(GbtResult {
 | 
			
		||||
        blocks,
 | 
			
		||||
        rates,
 | 
			
		||||
        clusters,
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn set_relatives(txid: u32, audit_pool: &mut HashMap<u32, AuditTransaction>) {
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,6 @@
 | 
			
		||||
use neon::{prelude::*, types::buffer::TypedArray};
 | 
			
		||||
use napi::bindgen_prelude::*;
 | 
			
		||||
use napi_derive::napi;
 | 
			
		||||
 | 
			
		||||
use once_cell::sync::Lazy;
 | 
			
		||||
use std::collections::HashMap;
 | 
			
		||||
use std::sync::Mutex;
 | 
			
		||||
@ -12,115 +14,66 @@ use thread_transaction::ThreadTransaction;
 | 
			
		||||
static THREAD_TRANSACTIONS: Lazy<Mutex<HashMap<u32, ThreadTransaction>>> =
 | 
			
		||||
    Lazy::new(|| Mutex::new(HashMap::new()));
 | 
			
		||||
 | 
			
		||||
fn make(mut cx: FunctionContext) -> JsResult<JsUndefined> {
 | 
			
		||||
    let mempool_arg = cx
 | 
			
		||||
        .argument::<JsArrayBuffer>(0)?
 | 
			
		||||
        .root(&mut cx)
 | 
			
		||||
        .into_inner(&mut cx);
 | 
			
		||||
    let callback = cx.argument::<JsFunction>(1)?.root(&mut cx);
 | 
			
		||||
    let channel = cx.channel();
 | 
			
		||||
 | 
			
		||||
    let buffer = mempool_arg.as_slice(&cx);
 | 
			
		||||
 | 
			
		||||
#[napi]
 | 
			
		||||
pub fn make<F>(mempool_buffer: Uint8Array, callback: F) -> Result<()>
 | 
			
		||||
where
 | 
			
		||||
    F: Fn(GbtResult) -> Result<()>,
 | 
			
		||||
{
 | 
			
		||||
    let mut map = HashMap::new();
 | 
			
		||||
    for tx in ThreadTransaction::batch_from_buffer(buffer) {
 | 
			
		||||
    for tx in ThreadTransaction::batch_from_buffer(&mempool_buffer) {
 | 
			
		||||
        map.insert(tx.uid, tx);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let mut global_map = THREAD_TRANSACTIONS.lock().unwrap();
 | 
			
		||||
    *global_map = map;
 | 
			
		||||
 | 
			
		||||
    run_in_thread(channel, callback);
 | 
			
		||||
 | 
			
		||||
    Ok(cx.undefined())
 | 
			
		||||
    run_in_thread(callback)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn update(mut cx: FunctionContext) -> JsResult<JsUndefined> {
 | 
			
		||||
    let new_txs_arg = cx
 | 
			
		||||
        .argument::<JsArrayBuffer>(0)?
 | 
			
		||||
        .root(&mut cx)
 | 
			
		||||
        .into_inner(&mut cx);
 | 
			
		||||
    let remove_txs_arg = cx
 | 
			
		||||
        .argument::<JsArrayBuffer>(1)?
 | 
			
		||||
        .root(&mut cx)
 | 
			
		||||
        .into_inner(&mut cx);
 | 
			
		||||
    let callback = cx.argument::<JsFunction>(2)?.root(&mut cx);
 | 
			
		||||
    let channel = cx.channel();
 | 
			
		||||
 | 
			
		||||
#[napi]
 | 
			
		||||
pub fn update<F>(new_txs: Uint8Array, remove_txs: Uint8Array, callback: F) -> Result<()>
 | 
			
		||||
where
 | 
			
		||||
    F: Fn(GbtResult) -> Result<()>,
 | 
			
		||||
{
 | 
			
		||||
    let mut map = THREAD_TRANSACTIONS.lock().unwrap();
 | 
			
		||||
    let new_tx_buffer = new_txs_arg.as_slice(&cx);
 | 
			
		||||
    for tx in ThreadTransaction::batch_from_buffer(new_tx_buffer) {
 | 
			
		||||
    for tx in ThreadTransaction::batch_from_buffer(&new_txs) {
 | 
			
		||||
        map.insert(tx.uid, tx);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let remove_tx_buffer = remove_txs_arg.as_slice(&cx);
 | 
			
		||||
    for txid in &utils::txids_from_buffer(remove_tx_buffer) {
 | 
			
		||||
    for txid in &utils::txids_from_buffer(&remove_txs) {
 | 
			
		||||
        map.remove(txid);
 | 
			
		||||
    }
 | 
			
		||||
    drop(map);
 | 
			
		||||
 | 
			
		||||
    run_in_thread(channel, callback);
 | 
			
		||||
 | 
			
		||||
    Ok(cx.undefined())
 | 
			
		||||
    run_in_thread(callback)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn run_in_thread(channel: Channel, callback: Root<JsFunction>) {
 | 
			
		||||
    std::thread::spawn(move || {
 | 
			
		||||
        let mut map = THREAD_TRANSACTIONS.lock().unwrap();
 | 
			
		||||
        let (blocks, rates, clusters) = gbt::gbt(&mut map).unwrap();
 | 
			
		||||
        drop(map);
 | 
			
		||||
/// The result from calling the gbt function.
 | 
			
		||||
///
 | 
			
		||||
/// This tuple contains the following:
 | 
			
		||||
///   blocks: A 2D Vector of transaction IDs (u32), the inner Vecs each represent a block.
 | 
			
		||||
/// clusters: A 2D Vector of transaction IDs representing clusters of dependent mempool transactions
 | 
			
		||||
///    rates: A Vector of tuples containing transaction IDs (u32) and effective fee per vsize (f64)
 | 
			
		||||
#[napi(constructor)]
 | 
			
		||||
pub struct GbtResult {
 | 
			
		||||
    pub blocks: Vec<Vec<u32>>,
 | 
			
		||||
    pub clusters: Vec<Vec<u32>>,
 | 
			
		||||
    pub rates: Vec<Vec<f64>>, // Tuples not supported. u32 fits inside f64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
        channel.send(move |mut cx| {
 | 
			
		||||
            let result = JsObject::new(&mut cx);
 | 
			
		||||
 | 
			
		||||
            let js_blocks = JsArray::new(&mut cx, blocks.len() as u32);
 | 
			
		||||
            for (i, block) in blocks.iter().enumerate() {
 | 
			
		||||
                let inner = JsArray::new(&mut cx, block.len() as u32);
 | 
			
		||||
                for (j, uid) in block.iter().enumerate() {
 | 
			
		||||
                    let v = cx.number(*uid);
 | 
			
		||||
                    inner.set(&mut cx, j as u32, v)?;
 | 
			
		||||
                }
 | 
			
		||||
                js_blocks.set(&mut cx, i as u32, inner)?;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            let js_clusters = JsArray::new(&mut cx, clusters.len() as u32);
 | 
			
		||||
            for (i, cluster) in clusters.iter().enumerate() {
 | 
			
		||||
                let inner = JsArray::new(&mut cx, cluster.len() as u32);
 | 
			
		||||
                for (j, uid) in cluster.iter().enumerate() {
 | 
			
		||||
                    let v = cx.number(*uid);
 | 
			
		||||
                    inner.set(&mut cx, j as u32, v)?;
 | 
			
		||||
                }
 | 
			
		||||
                js_clusters.set(&mut cx, i as u32, inner)?;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            let js_rates = JsArray::new(&mut cx, rates.len() as u32);
 | 
			
		||||
            for (i, (uid, rate)) in rates.iter().enumerate() {
 | 
			
		||||
                let inner = JsArray::new(&mut cx, 2);
 | 
			
		||||
                let js_uid = cx.number(*uid);
 | 
			
		||||
                let js_rate = cx.number(*rate);
 | 
			
		||||
                inner.set(&mut cx, 0, js_uid)?;
 | 
			
		||||
                inner.set(&mut cx, 1, js_rate)?;
 | 
			
		||||
                js_rates.set(&mut cx, i as u32, inner)?;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            result.set(&mut cx, "blocks", js_blocks)?;
 | 
			
		||||
            result.set(&mut cx, "clusters", js_clusters)?;
 | 
			
		||||
            result.set(&mut cx, "rates", js_rates)?;
 | 
			
		||||
 | 
			
		||||
            let callback = callback.into_inner(&mut cx);
 | 
			
		||||
            let this = cx.undefined();
 | 
			
		||||
            let args = vec![result.upcast()];
 | 
			
		||||
 | 
			
		||||
            callback.call(&mut cx, this, args)?;
 | 
			
		||||
 | 
			
		||||
            Ok(())
 | 
			
		||||
        });
 | 
			
		||||
fn run_in_thread<F>(callback: F) -> Result<()>
 | 
			
		||||
where
 | 
			
		||||
    F: Fn(GbtResult) -> Result<()>,
 | 
			
		||||
{
 | 
			
		||||
    let handle = std::thread::spawn(|| -> Result<GbtResult> {
 | 
			
		||||
        let mut map = THREAD_TRANSACTIONS
 | 
			
		||||
            .lock()
 | 
			
		||||
            .map_err(|_| napi::Error::from_reason("THREAD_TRANSACTIONS Mutex poisoned"))?;
 | 
			
		||||
        gbt::gbt(&mut map).ok_or_else(|| napi::Error::from_reason("gbt failed"))
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[neon::main]
 | 
			
		||||
fn main(mut cx: ModuleContext) -> NeonResult<()> {
 | 
			
		||||
    cx.export_function("make", make)?;
 | 
			
		||||
    cx.export_function("update", update)?;
 | 
			
		||||
    Ok(())
 | 
			
		||||
    callback(
 | 
			
		||||
        handle
 | 
			
		||||
            .join()
 | 
			
		||||
            .map_err(|_| napi::Error::from_reason("thread panicked"))??,
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user