Implement rust gbt updateBlockTemplates
This commit is contained in:
47
backend/rust-gbt/Cargo.lock
generated
47
backend/rust-gbt/Cargo.lock
generated
@@ -2,6 +2,18 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
@@ -12,7 +24,26 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
name = "gbt"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"neon",
|
||||
"once_cell",
|
||||
"priority-queue",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -66,6 +97,22 @@ dependencies = [
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||
|
||||
[[package]]
|
||||
name = "priority-queue"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fff39edfcaec0d64e8d0da38564fad195d2d51b680940295fcc307366e101e61"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"indexmap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.60"
|
||||
|
||||
@@ -14,6 +14,7 @@ crate-type = ["cdylib"]
|
||||
[dependencies]
|
||||
priority-queue = "1.3.2"
|
||||
bytes = "1.4.0"
|
||||
once_cell = "1.18.0"
|
||||
|
||||
[dependencies.neon]
|
||||
version = "0.10"
|
||||
|
||||
@@ -34,13 +34,7 @@ impl Ord for TxPriority {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn gbt(mempool_array: Vec<ThreadTransaction>) -> (Vec<Vec<u32>>, Vec<(u32, f64)>, Vec<Vec<u32>>) {
|
||||
let mut mempool: HashMap<u32,ThreadTransaction> = HashMap::new();
|
||||
for transaction in mempool_array {
|
||||
mempool.insert(transaction.uid, transaction);
|
||||
}
|
||||
|
||||
|
||||
pub fn gbt(mempool: &mut HashMap<u32,ThreadTransaction>) -> (Vec<Vec<u32>>, Vec<(u32, f64)>, Vec<Vec<u32>>) {
|
||||
return make_block_templates(mempool);
|
||||
}
|
||||
|
||||
@@ -49,13 +43,13 @@ pub fn gbt(mempool_array: Vec<ThreadTransaction>) -> (Vec<Vec<u32>>, Vec<(u32, f
|
||||
* (see BlockAssembler in https://github.com/bitcoin/bitcoin/blob/master/src/node/miner.cpp)
|
||||
* Ported from https://github.com/mempool/mempool/blob/master/backend/src/api/tx-selection-worker.ts
|
||||
*/
|
||||
fn make_block_templates(mempool: HashMap<u32,ThreadTransaction>) -> (Vec<Vec<u32>>, Vec<(u32, f64)>, Vec<Vec<u32>>) {
|
||||
fn make_block_templates(mempool: &mut HashMap<u32,ThreadTransaction>) -> (Vec<Vec<u32>>, Vec<(u32, f64)>, Vec<Vec<u32>>) {
|
||||
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();
|
||||
|
||||
// Initialize working structs
|
||||
for (uid, tx) in &mempool {
|
||||
for (uid, tx) in mempool {
|
||||
let audit_tx = AuditTransaction {
|
||||
uid: tx.uid,
|
||||
fee: tx.fee,
|
||||
|
||||
@@ -1,11 +1,20 @@
|
||||
use neon::{prelude::*, types::buffer::TypedArray};
|
||||
use std::collections::HashMap;
|
||||
use std::ops::DerefMut;
|
||||
use std::sync::Mutex;
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
mod gbt;
|
||||
mod thread_transaction;
|
||||
mod audit_transaction;
|
||||
use thread_transaction::{ThreadTransaction};
|
||||
mod utils;
|
||||
use thread_transaction::ThreadTransaction;
|
||||
|
||||
fn go(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
||||
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();
|
||||
@@ -13,8 +22,48 @@ fn go(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
||||
let buffer = mempool_arg.as_slice(&mut cx);
|
||||
let thread_transactions = ThreadTransaction::batch_from_buffer(buffer);
|
||||
|
||||
let mut map = THREAD_TRANSACTIONS.lock().unwrap();
|
||||
map.clear();
|
||||
for tx in thread_transactions {
|
||||
map.insert(tx.uid, tx);
|
||||
}
|
||||
drop(map);
|
||||
|
||||
run_in_thread(channel, callback);
|
||||
|
||||
Ok(cx.undefined())
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
let mut map = THREAD_TRANSACTIONS.lock().unwrap();
|
||||
let new_tx_buffer = new_txs_arg.as_slice(&mut cx);
|
||||
let thread_transactions = ThreadTransaction::batch_from_buffer(new_tx_buffer);
|
||||
for tx in thread_transactions {
|
||||
map.insert(tx.uid, tx);
|
||||
}
|
||||
|
||||
let remove_tx_buffer = remove_txs_arg.as_slice(&mut cx);
|
||||
let remove_ids = utils::txids_from_buffer(remove_tx_buffer);
|
||||
for txid in &remove_ids {
|
||||
map.remove(txid);
|
||||
}
|
||||
drop(map);
|
||||
|
||||
run_in_thread(channel, callback);
|
||||
|
||||
Ok(cx.undefined())
|
||||
}
|
||||
|
||||
fn run_in_thread(channel: Channel, callback: Root<JsFunction>) {
|
||||
std::thread::spawn(move || {
|
||||
let (blocks, rates, clusters) = gbt::gbt(thread_transactions);
|
||||
let mut map = THREAD_TRANSACTIONS.lock().unwrap();
|
||||
let (blocks, rates, clusters) = gbt::gbt(map.deref_mut());
|
||||
drop(map);
|
||||
|
||||
channel.send(move |mut cx| {
|
||||
let result = JsObject::new(&mut cx);
|
||||
@@ -64,12 +113,11 @@ fn go(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
||||
Ok(())
|
||||
});
|
||||
});
|
||||
|
||||
Ok(cx.undefined())
|
||||
}
|
||||
|
||||
#[neon::main]
|
||||
fn main(mut cx: ModuleContext) -> NeonResult<()> {
|
||||
cx.export_function("go", go)?;
|
||||
cx.export_function("make", make)?;
|
||||
cx.export_function("update", update)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
extern crate bytes;
|
||||
use std::io::Cursor;
|
||||
use bytes::buf::Buf;
|
||||
|
||||
pub struct ThreadTransaction {
|
||||
pub uid: u32,
|
||||
pub fee: u64,
|
||||
|
||||
14
backend/rust-gbt/src/utils.rs
Normal file
14
backend/rust-gbt/src/utils.rs
Normal file
@@ -0,0 +1,14 @@
|
||||
extern crate bytes;
|
||||
use std::io::Cursor;
|
||||
use bytes::buf::Buf;
|
||||
|
||||
pub fn txids_from_buffer(buffer: &[u8]) -> Vec<u32> {
|
||||
let mut txids: Vec<u32> = Vec::new();
|
||||
let mut cursor = Cursor::new(buffer);
|
||||
let size = cursor.get_u32();
|
||||
for _ in 0..size {
|
||||
txids.push(cursor.get_u32());
|
||||
}
|
||||
|
||||
return txids;
|
||||
}
|
||||
Reference in New Issue
Block a user