configurable block size & count in rust gbt
This commit is contained in:
		
							parent
							
								
									e1e4e79b68
								
							
						
					
					
						commit
						b44b790e28
					
				@ -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)
 | 
				
			||||||
                    || (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 - 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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user