Feature: Use napi-rs instead of neon
This commit is contained in:
parent
0f1f151d65
commit
2d4963c2df
152
Cargo.lock
generated
152
Cargo.lock
generated
@ -2,12 +2,27 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
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]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6dbe3c979c178231552ecba20214a8272df4e09f232a87aef4320cf06539aded"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bytes"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
@ -20,12 +35,33 @@ version = "1.0.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
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]]
|
[[package]]
|
||||||
name = "gbt"
|
name = "gbt"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"neon",
|
"napi",
|
||||||
|
"napi-build",
|
||||||
|
"napi-derive",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"priority-queue",
|
"priority-queue",
|
||||||
]
|
]
|
||||||
@ -48,53 +84,75 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libloading"
|
name = "libloading"
|
||||||
version = "0.6.7"
|
version = "0.7.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883"
|
checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "neon"
|
name = "memchr"
|
||||||
version = "0.10.1"
|
version = "2.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
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 = [
|
dependencies = [
|
||||||
"neon-build",
|
"bitflags",
|
||||||
"neon-macros",
|
"ctor",
|
||||||
"neon-runtime",
|
"napi-derive",
|
||||||
"semver",
|
"napi-sys",
|
||||||
"smallvec",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "neon-build"
|
name = "napi-build"
|
||||||
version = "0.10.1"
|
version = "2.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8bac98a702e71804af3dacfde41edde4a16076a7bbe889ae61e56e18c5b1c811"
|
checksum = "882a73d9ef23e8dc2ebbffb6a6ae2ef467c0f18ac10711e4cc59c5485d41df0e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "neon-macros"
|
name = "napi-derive"
|
||||||
version = "0.10.1"
|
version = "2.13.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b7288eac8b54af7913c60e0eb0e2a7683020dffa342ab3fd15e28f035ba897cf"
|
checksum = "da1c6a8fa84d549aa8708fcd062372bf8ec6e849de39016ab921067d21bde367"
|
||||||
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"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"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",
|
"libloading",
|
||||||
"smallvec",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -132,25 +190,27 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver"
|
name = "regex"
|
||||||
version = "0.9.0"
|
version = "1.8.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
checksum = "81ca098a9821bd52d6b24fd8b10bd081f47d39c22778cafaa75a2857a62c6390"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"semver-parser",
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver-parser"
|
name = "regex-syntax"
|
||||||
version = "0.7.0"
|
version = "0.7.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "semver"
|
||||||
version = "1.10.0"
|
version = "1.0.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
|
checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
@ -164,14 +224,14 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn-mid"
|
name = "syn"
|
||||||
version = "0.5.3"
|
version = "2.0.20"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baa8e7560a164edb1621a55d18a0c59abf49d360f47aa7b821061dd7eea7fac9"
|
checksum = "fcb8d4cebc40aa517dfb69618fa647a346562e67228e2236ae0042ee6ac14775"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -180,6 +240,12 @@ version = "1.0.9"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"
|
checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-segmentation"
|
||||||
|
version = "1.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
members = [
|
members = [
|
||||||
"./backend/rust-gbt",
|
"./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
|
**/node_modules
|
||||||
**/.DS_Store
|
**/.DS_Store
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
|
@ -15,8 +15,8 @@ crate-type = ["cdylib"]
|
|||||||
priority-queue = "1.3.2"
|
priority-queue = "1.3.2"
|
||||||
bytes = "1.4.0"
|
bytes = "1.4.0"
|
||||||
once_cell = "1.18.0"
|
once_cell = "1.18.0"
|
||||||
|
napi = { version = "2.13.2", features = ["napi8"] }
|
||||||
|
napi-derive = "2.13.0"
|
||||||
|
|
||||||
[dependencies.neon]
|
[build-dependencies]
|
||||||
version = "0.10"
|
napi-build = "2.0.1"
|
||||||
default-features = false
|
|
||||||
features = ["napi-6","channel-api"]
|
|
||||||
|
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",
|
"version": "0.1.0",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cargo-cp-artifact": "^0.1"
|
"@napi-rs/cli": "^2.16.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/cargo-cp-artifact": {
|
"node_modules/@napi-rs/cli": {
|
||||||
"version": "0.1.8",
|
"version": "2.16.1",
|
||||||
"resolved": "https://registry.npmjs.org/cargo-cp-artifact/-/cargo-cp-artifact-0.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/@napi-rs/cli/-/cli-2.16.1.tgz",
|
||||||
"integrity": "sha512-3j4DaoTrsCD1MRkTF2Soacii0Nx7UHCce0EwUf4fHnggwiE4fbmF2AbnfzayR36DF8KGadfh7M/Yfy625kgPlA==",
|
"integrity": "sha512-L0Gr5iEQIDEbvWdDr1HUaBOxBSHL1VZhWSk1oryawoT8qJIY+KGfLFelU+Qma64ivCPbxYpkfPoKYVG3rcoGIA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"bin": {
|
"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",
|
"name": "gbt",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"description": "An inefficient re-implementation of the getBlockTemplate algorithm in Rust",
|
"description": "An inefficient re-implementation of the getBlockTemplate algorithm in Rust",
|
||||||
"main": "index.node",
|
"main": "index.js",
|
||||||
|
"types": "index.d.ts",
|
||||||
"scripts": {
|
"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-debug": "npm run build --",
|
||||||
"build-release": "npm run build -- --release",
|
"build-release": "npm run build -- --release",
|
||||||
"install": "npm run build-release",
|
"install": "npm run build-release",
|
||||||
|
"prepublishOnly": "napi prepublish -t npm",
|
||||||
"test": "cargo test"
|
"test": "cargo test"
|
||||||
},
|
},
|
||||||
"author": "mononaut",
|
"author": "mononaut",
|
||||||
|
"napi": {
|
||||||
|
"name": "gbt",
|
||||||
|
"triples": {
|
||||||
|
"defaults": false,
|
||||||
|
"additional": [
|
||||||
|
"x86_64-unknown-linux-gnu",
|
||||||
|
"x86_64-unknown-freebsd"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cargo-cp-artifact": "^0.1"
|
"@napi-rs/cli": "^2.16.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,9 +1,12 @@
|
|||||||
use priority_queue::PriorityQueue;
|
use priority_queue::PriorityQueue;
|
||||||
use std::cmp::Ordering;
|
use std::{
|
||||||
use std::collections::{HashMap, HashSet, VecDeque};
|
cmp::Ordering,
|
||||||
|
collections::{HashMap, HashSet, VecDeque},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::audit_transaction::AuditTransaction;
|
use crate::{
|
||||||
use crate::thread_transaction::ThreadTransaction;
|
audit_transaction::AuditTransaction, thread_transaction::ThreadTransaction, GbtResult,
|
||||||
|
};
|
||||||
|
|
||||||
const BLOCK_WEIGHT_UNITS: u32 = 4_000_000;
|
const BLOCK_WEIGHT_UNITS: u32 = 4_000_000;
|
||||||
const BLOCK_SIGOPS: u32 = 80_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
|
* 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)
|
* (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> {
|
pub fn gbt(mempool: &mut HashMap<u32, ThreadTransaction>) -> Option<GbtResult> {
|
||||||
let mut audit_pool: HashMap<u32, AuditTransaction> = HashMap::new();
|
let mut audit_pool: HashMap<u32, AuditTransaction> = HashMap::new();
|
||||||
let mut mempool_array: VecDeque<u32> = VecDeque::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
|
// Initialize working structs
|
||||||
for (uid, tx) in mempool {
|
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);
|
package.sort_unstable_by_key(|a| 0 - a.1);
|
||||||
|
|
||||||
if is_cluster {
|
if is_cluster {
|
||||||
cluster_array.push(cluster);
|
clusters.push(cluster);
|
||||||
}
|
}
|
||||||
|
|
||||||
let cluster_rate = next_tx
|
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
|
// 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 {
|
for (txid, tx) in audit_pool {
|
||||||
if tx.dirty {
|
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>) {
|
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 once_cell::sync::Lazy;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
@ -12,115 +14,66 @@ use thread_transaction::ThreadTransaction;
|
|||||||
static THREAD_TRANSACTIONS: Lazy<Mutex<HashMap<u32, ThreadTransaction>>> =
|
static THREAD_TRANSACTIONS: Lazy<Mutex<HashMap<u32, ThreadTransaction>>> =
|
||||||
Lazy::new(|| Mutex::new(HashMap::new()));
|
Lazy::new(|| Mutex::new(HashMap::new()));
|
||||||
|
|
||||||
fn make(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
#[napi]
|
||||||
let mempool_arg = cx
|
pub fn make<F>(mempool_buffer: Uint8Array, callback: F) -> Result<()>
|
||||||
.argument::<JsArrayBuffer>(0)?
|
where
|
||||||
.root(&mut cx)
|
F: Fn(GbtResult) -> Result<()>,
|
||||||
.into_inner(&mut cx);
|
{
|
||||||
let callback = cx.argument::<JsFunction>(1)?.root(&mut cx);
|
|
||||||
let channel = cx.channel();
|
|
||||||
|
|
||||||
let buffer = mempool_arg.as_slice(&cx);
|
|
||||||
|
|
||||||
let mut map = HashMap::new();
|
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);
|
map.insert(tx.uid, tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut global_map = THREAD_TRANSACTIONS.lock().unwrap();
|
let mut global_map = THREAD_TRANSACTIONS.lock().unwrap();
|
||||||
*global_map = map;
|
*global_map = map;
|
||||||
|
|
||||||
run_in_thread(channel, callback);
|
run_in_thread(callback)
|
||||||
|
|
||||||
Ok(cx.undefined())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
#[napi]
|
||||||
let new_txs_arg = cx
|
pub fn update<F>(new_txs: Uint8Array, remove_txs: Uint8Array, callback: F) -> Result<()>
|
||||||
.argument::<JsArrayBuffer>(0)?
|
where
|
||||||
.root(&mut cx)
|
F: Fn(GbtResult) -> Result<()>,
|
||||||
.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();
|
|
||||||
|
|
||||||
let mut map = THREAD_TRANSACTIONS.lock().unwrap();
|
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_txs) {
|
||||||
for tx in ThreadTransaction::batch_from_buffer(new_tx_buffer) {
|
|
||||||
map.insert(tx.uid, tx);
|
map.insert(tx.uid, tx);
|
||||||
}
|
}
|
||||||
|
for txid in &utils::txids_from_buffer(&remove_txs) {
|
||||||
let remove_tx_buffer = remove_txs_arg.as_slice(&cx);
|
|
||||||
for txid in &utils::txids_from_buffer(remove_tx_buffer) {
|
|
||||||
map.remove(txid);
|
map.remove(txid);
|
||||||
}
|
}
|
||||||
drop(map);
|
drop(map);
|
||||||
|
|
||||||
run_in_thread(channel, callback);
|
run_in_thread(callback)
|
||||||
|
|
||||||
Ok(cx.undefined())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_in_thread(channel: Channel, callback: Root<JsFunction>) {
|
/// The result from calling the gbt function.
|
||||||
std::thread::spawn(move || {
|
///
|
||||||
let mut map = THREAD_TRANSACTIONS.lock().unwrap();
|
/// This tuple contains the following:
|
||||||
let (blocks, rates, clusters) = gbt::gbt(&mut map).unwrap();
|
/// blocks: A 2D Vector of transaction IDs (u32), the inner Vecs each represent a block.
|
||||||
drop(map);
|
/// 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| {
|
fn run_in_thread<F>(callback: F) -> Result<()>
|
||||||
let result = JsObject::new(&mut cx);
|
where
|
||||||
|
F: Fn(GbtResult) -> Result<()>,
|
||||||
let js_blocks = JsArray::new(&mut cx, blocks.len() as u32);
|
{
|
||||||
for (i, block) in blocks.iter().enumerate() {
|
let handle = std::thread::spawn(|| -> Result<GbtResult> {
|
||||||
let inner = JsArray::new(&mut cx, block.len() as u32);
|
let mut map = THREAD_TRANSACTIONS
|
||||||
for (j, uid) in block.iter().enumerate() {
|
.lock()
|
||||||
let v = cx.number(*uid);
|
.map_err(|_| napi::Error::from_reason("THREAD_TRANSACTIONS Mutex poisoned"))?;
|
||||||
inner.set(&mut cx, j as u32, v)?;
|
gbt::gbt(&mut map).ok_or_else(|| napi::Error::from_reason("gbt failed"))
|
||||||
}
|
|
||||||
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(())
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
#[neon::main]
|
callback(
|
||||||
fn main(mut cx: ModuleContext) -> NeonResult<()> {
|
handle
|
||||||
cx.export_function("make", make)?;
|
.join()
|
||||||
cx.export_function("update", update)?;
|
.map_err(|_| napi::Error::from_reason("thread panicked"))??,
|
||||||
Ok(())
|
)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user