mirror of
https://github.com/mempool/mempool.git
synced 2025-01-19 05:34:03 +01:00
Merge branch 'master' into mononaut/fix-hardcoded-median-weight
This commit is contained in:
commit
6b84dc2be4
@ -13,7 +13,7 @@ const vectorBuffer: Buffer = fs.readFileSync(path.join(__dirname, './', './test-
|
|||||||
|
|
||||||
describe('Rust GBT', () => {
|
describe('Rust GBT', () => {
|
||||||
test('should produce the same template as getBlockTemplate from Bitcoin Core', async () => {
|
test('should produce the same template as getBlockTemplate from Bitcoin Core', async () => {
|
||||||
const rustGbt = new GbtGenerator();
|
const rustGbt = new GbtGenerator(4_000_000, 8);
|
||||||
const { mempool, maxUid } = mempoolFromArrayBuffer(vectorBuffer.buffer);
|
const { mempool, maxUid } = mempoolFromArrayBuffer(vectorBuffer.buffer);
|
||||||
const result = await rustGbt.make(mempool, [], maxUid);
|
const result = await rustGbt.make(mempool, [], maxUid);
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ class MempoolBlocks {
|
|||||||
private mempoolBlockDeltas: MempoolBlockDelta[] = [];
|
private mempoolBlockDeltas: MempoolBlockDelta[] = [];
|
||||||
private txSelectionWorker: Worker | null = null;
|
private txSelectionWorker: Worker | null = null;
|
||||||
private rustInitialized: boolean = false;
|
private rustInitialized: boolean = false;
|
||||||
private rustGbtGenerator: GbtGenerator = new GbtGenerator();
|
private rustGbtGenerator: GbtGenerator = new GbtGenerator(config.MEMPOOL.BLOCK_WEIGHT_UNITS, config.MEMPOOL.MEMPOOL_BLOCKS_AMOUNT);
|
||||||
|
|
||||||
private nextUid: number = 1;
|
private nextUid: number = 1;
|
||||||
private uidMap: Map<number, string> = new Map(); // map short numerical uids to full txids
|
private uidMap: Map<number, string> = new Map(); // map short numerical uids to full txids
|
||||||
@ -230,7 +230,7 @@ class MempoolBlocks {
|
|||||||
|
|
||||||
private resetRustGbt(): void {
|
private resetRustGbt(): void {
|
||||||
this.rustInitialized = false;
|
this.rustInitialized = false;
|
||||||
this.rustGbtGenerator = new GbtGenerator();
|
this.rustGbtGenerator = new GbtGenerator(config.MEMPOOL.BLOCK_WEIGHT_UNITS, config.MEMPOOL.MEMPOOL_BLOCKS_AMOUNT);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async $rustMakeBlockTemplates(txids: string[], newMempool: { [txid: string]: MempoolTransactionExtended }, candidates: GbtCandidates | undefined, saveResults: boolean = false, useAccelerations: boolean = false, accelerationPool?: number): Promise<MempoolBlockWithTransactions[]> {
|
public async $rustMakeBlockTemplates(txids: string[], newMempool: { [txid: string]: MempoolTransactionExtended }, candidates: GbtCandidates | undefined, saveResults: boolean = false, useAccelerations: boolean = false, accelerationPool?: number): Promise<MempoolBlockWithTransactions[]> {
|
||||||
@ -262,7 +262,7 @@ class MempoolBlocks {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// run the block construction algorithm in a separate thread, and wait for a result
|
// run the block construction algorithm in a separate thread, and wait for a result
|
||||||
const rustGbt = saveResults ? this.rustGbtGenerator : new GbtGenerator();
|
const rustGbt = saveResults ? this.rustGbtGenerator : new GbtGenerator(config.MEMPOOL.BLOCK_WEIGHT_UNITS, config.MEMPOOL.MEMPOOL_BLOCKS_AMOUNT);
|
||||||
try {
|
try {
|
||||||
const { blocks, blockWeights, rates, clusters, overflow } = this.convertNapiResultTxids(
|
const { blocks, blockWeights, rates, clusters, overflow } = this.convertNapiResultTxids(
|
||||||
await rustGbt.make(transactions as RustThreadTransaction[], convertedAccelerations as RustThreadAcceleration[], this.nextUid),
|
await rustGbt.make(transactions as RustThreadTransaction[], convertedAccelerations as RustThreadAcceleration[], this.nextUid),
|
||||||
|
@ -8,11 +8,9 @@ use crate::{
|
|||||||
GbtResult, ThreadTransactionsMap, thread_acceleration::ThreadAcceleration,
|
GbtResult, ThreadTransactionsMap, thread_acceleration::ThreadAcceleration,
|
||||||
};
|
};
|
||||||
|
|
||||||
const MAX_BLOCK_WEIGHT_UNITS: u32 = 4_000_000 - 4_000;
|
|
||||||
const BLOCK_SIGOPS: u32 = 80_000;
|
const BLOCK_SIGOPS: u32 = 80_000;
|
||||||
const BLOCK_RESERVED_WEIGHT: u32 = 4_000;
|
const BLOCK_RESERVED_WEIGHT: u32 = 4_000;
|
||||||
const BLOCK_RESERVED_SIGOPS: u32 = 400;
|
const BLOCK_RESERVED_SIGOPS: u32 = 400;
|
||||||
const MAX_BLOCKS: usize = 8;
|
|
||||||
|
|
||||||
type AuditPool = Vec<Option<ManuallyDrop<AuditTransaction>>>;
|
type AuditPool = Vec<Option<ManuallyDrop<AuditTransaction>>>;
|
||||||
type ModifiedQueue = PriorityQueue<u32, TxPriority, U32HasherState>;
|
type ModifiedQueue = PriorityQueue<u32, TxPriority, U32HasherState>;
|
||||||
@ -53,7 +51,13 @@ impl Ord for TxPriority {
|
|||||||
// TODO: Make gbt smaller to fix these lints.
|
// TODO: Make gbt smaller to fix these lints.
|
||||||
#[allow(clippy::too_many_lines)]
|
#[allow(clippy::too_many_lines)]
|
||||||
#[allow(clippy::cognitive_complexity)]
|
#[allow(clippy::cognitive_complexity)]
|
||||||
pub fn gbt(mempool: &mut ThreadTransactionsMap, accelerations: &[ThreadAcceleration], max_uid: usize) -> GbtResult {
|
pub fn gbt(
|
||||||
|
mempool: &mut ThreadTransactionsMap,
|
||||||
|
accelerations: &[ThreadAcceleration],
|
||||||
|
max_uid: usize,
|
||||||
|
max_block_weight: u32,
|
||||||
|
max_blocks: usize,
|
||||||
|
) -> GbtResult {
|
||||||
let mut indexed_accelerations = Vec::with_capacity(max_uid + 1);
|
let mut indexed_accelerations = Vec::with_capacity(max_uid + 1);
|
||||||
indexed_accelerations.resize(max_uid + 1, None);
|
indexed_accelerations.resize(max_uid + 1, None);
|
||||||
for acceleration in accelerations {
|
for acceleration in accelerations {
|
||||||
@ -146,9 +150,9 @@ pub fn gbt(mempool: &mut ThreadTransactionsMap, accelerations: &[ThreadAccelerat
|
|||||||
modified.pop();
|
modified.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
if blocks.len() < (MAX_BLOCKS - 1)
|
if blocks.len() < (max_blocks - 1)
|
||||||
&& ((block_weight + (4 * next_tx.ancestor_sigop_adjusted_vsize())
|
&& ((block_weight + (4 * next_tx.ancestor_sigop_adjusted_vsize())
|
||||||
>= MAX_BLOCK_WEIGHT_UNITS)
|
>= max_block_weight - 4_000)
|
||||||
|| (block_sigops + next_tx.ancestor_sigops() > BLOCK_SIGOPS))
|
|| (block_sigops + next_tx.ancestor_sigops() > BLOCK_SIGOPS))
|
||||||
{
|
{
|
||||||
// hold this package in an overflow list while we check for smaller options
|
// hold this package in an overflow list while we check for smaller options
|
||||||
@ -201,9 +205,9 @@ pub fn gbt(mempool: &mut ThreadTransactionsMap, accelerations: &[ThreadAccelerat
|
|||||||
|
|
||||||
// this block is full
|
// this block is full
|
||||||
let exceeded_package_tries =
|
let exceeded_package_tries =
|
||||||
failures > 1000 && block_weight > (MAX_BLOCK_WEIGHT_UNITS - BLOCK_RESERVED_WEIGHT);
|
failures > 1000 && block_weight > (max_block_weight - 4_000 - BLOCK_RESERVED_WEIGHT);
|
||||||
let queue_is_empty = mempool_stack.is_empty() && modified.is_empty();
|
let queue_is_empty = mempool_stack.is_empty() && modified.is_empty();
|
||||||
if (exceeded_package_tries || queue_is_empty) && blocks.len() < (MAX_BLOCKS - 1) {
|
if (exceeded_package_tries || queue_is_empty) && blocks.len() < (max_blocks - 1) {
|
||||||
// finalize this block
|
// finalize this block
|
||||||
if transactions.is_empty() {
|
if transactions.is_empty() {
|
||||||
info!("trying to push an empty block! breaking loop! mempool {:#?} | modified {:#?} | overflow {:#?}", mempool_stack.len(), modified.len(), overflow.len());
|
info!("trying to push an empty block! breaking loop! mempool {:#?} | modified {:#?} | overflow {:#?}", mempool_stack.len(), modified.len(), overflow.len());
|
||||||
|
@ -35,6 +35,8 @@ type ThreadTransactionsMap = HashMap<u32, ThreadTransaction, U32HasherState>;
|
|||||||
#[napi]
|
#[napi]
|
||||||
pub struct GbtGenerator {
|
pub struct GbtGenerator {
|
||||||
thread_transactions: Arc<Mutex<ThreadTransactionsMap>>,
|
thread_transactions: Arc<Mutex<ThreadTransactionsMap>>,
|
||||||
|
max_block_weight: u32,
|
||||||
|
max_blocks: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[napi::module_init]
|
#[napi::module_init]
|
||||||
@ -65,10 +67,12 @@ impl GbtGenerator {
|
|||||||
#[napi(constructor)]
|
#[napi(constructor)]
|
||||||
#[allow(clippy::new_without_default)]
|
#[allow(clippy::new_without_default)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new() -> Self {
|
pub fn new(max_block_weight: u32, max_blocks: u32) -> Self {
|
||||||
debug!("Created new GbtGenerator");
|
debug!("Created new GbtGenerator");
|
||||||
Self {
|
Self {
|
||||||
thread_transactions: Arc::new(Mutex::new(u32hashmap_with_capacity(STARTING_CAPACITY))),
|
thread_transactions: Arc::new(Mutex::new(u32hashmap_with_capacity(STARTING_CAPACITY))),
|
||||||
|
max_block_weight,
|
||||||
|
max_blocks: max_blocks as usize,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,12 +80,19 @@ impl GbtGenerator {
|
|||||||
///
|
///
|
||||||
/// Rejects if the thread panics or if the Mutex is poisoned.
|
/// Rejects if the thread panics or if the Mutex is poisoned.
|
||||||
#[napi]
|
#[napi]
|
||||||
pub async fn make(&self, mempool: Vec<ThreadTransaction>, accelerations: Vec<ThreadAcceleration>, max_uid: u32) -> Result<GbtResult> {
|
pub async fn make(
|
||||||
|
&self,
|
||||||
|
mempool: Vec<ThreadTransaction>,
|
||||||
|
accelerations: Vec<ThreadAcceleration>,
|
||||||
|
max_uid: u32,
|
||||||
|
) -> Result<GbtResult> {
|
||||||
trace!("make: Current State {:#?}", self.thread_transactions);
|
trace!("make: Current State {:#?}", self.thread_transactions);
|
||||||
run_task(
|
run_task(
|
||||||
Arc::clone(&self.thread_transactions),
|
Arc::clone(&self.thread_transactions),
|
||||||
accelerations,
|
accelerations,
|
||||||
max_uid as usize,
|
max_uid as usize,
|
||||||
|
self.max_block_weight,
|
||||||
|
self.max_blocks,
|
||||||
move |map| {
|
move |map| {
|
||||||
for tx in mempool {
|
for tx in mempool {
|
||||||
map.insert(tx.uid, tx);
|
map.insert(tx.uid, tx);
|
||||||
@ -107,6 +118,8 @@ impl GbtGenerator {
|
|||||||
Arc::clone(&self.thread_transactions),
|
Arc::clone(&self.thread_transactions),
|
||||||
accelerations,
|
accelerations,
|
||||||
max_uid as usize,
|
max_uid as usize,
|
||||||
|
self.max_block_weight,
|
||||||
|
self.max_blocks,
|
||||||
move |map| {
|
move |map| {
|
||||||
for tx in new_txs {
|
for tx in new_txs {
|
||||||
map.insert(tx.uid, tx);
|
map.insert(tx.uid, tx);
|
||||||
@ -149,6 +162,8 @@ async fn run_task<F>(
|
|||||||
thread_transactions: Arc<Mutex<ThreadTransactionsMap>>,
|
thread_transactions: Arc<Mutex<ThreadTransactionsMap>>,
|
||||||
accelerations: Vec<ThreadAcceleration>,
|
accelerations: Vec<ThreadAcceleration>,
|
||||||
max_uid: usize,
|
max_uid: usize,
|
||||||
|
max_block_weight: u32,
|
||||||
|
max_blocks: usize,
|
||||||
callback: F,
|
callback: F,
|
||||||
) -> Result<GbtResult>
|
) -> Result<GbtResult>
|
||||||
where
|
where
|
||||||
@ -166,7 +181,13 @@ where
|
|||||||
callback(&mut map);
|
callback(&mut map);
|
||||||
|
|
||||||
info!("Starting gbt algorithm for {} elements...", map.len());
|
info!("Starting gbt algorithm for {} elements...", map.len());
|
||||||
let result = gbt::gbt(&mut map, &accelerations, max_uid);
|
let result = gbt::gbt(
|
||||||
|
&mut map,
|
||||||
|
&accelerations,
|
||||||
|
max_uid,
|
||||||
|
max_block_weight,
|
||||||
|
max_blocks as usize,
|
||||||
|
);
|
||||||
info!("Finished gbt algorithm for {} elements...", map.len());
|
info!("Finished gbt algorithm for {} elements...", map.len());
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
|
Loading…
Reference in New Issue
Block a user