diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 51ddb7855..1a140dd59 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,7 +29,7 @@ jobs: - name: Read rust-toolchain file from repository id: gettoolchain - run: echo "::set-output name=toolchain::$(cat rust-toolchain)" + run: echo "::set-output name=toolchain::$(cat ./rust/gbt/rust-toolchain)" working-directory: ${{ matrix.node }}/${{ matrix.flavor }} - name: Install ${{ steps.gettoolchain.outputs.toolchain }} Rust toolchain diff --git a/Cargo.toml b/Cargo.toml deleted file mode 100644 index 2f70699f4..000000000 --- a/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[workspace] -resolver = "2" -members = [ - "./backend/rust-gbt", -] - -[profile.release] -lto = true -codegen-units = 1 diff --git a/backend/.gitignore b/backend/.gitignore index 5cefd4bab..23380b731 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -54,3 +54,6 @@ Thumbs.db # package folder (npm run package output) /package + +# Rust GBT folder (We build externally first) +/rust-gbt diff --git a/backend/npm_package_rm_build_deps.sh b/backend/npm_package_rm_build_deps.sh index 6b260d84d..692ba24eb 100755 --- a/backend/npm_package_rm_build_deps.sh +++ b/backend/npm_package_rm_build_deps.sh @@ -6,7 +6,4 @@ cd package/node_modules rm -r \ typescript \ @typescript-eslint \ - @napi-rs \ - ./rust-gbt/src \ - ./rust-gbt/Cargo.toml \ - ./rust-gbt/build.rs + @napi-rs diff --git a/backend/package-lock.json b/backend/package-lock.json index 706290470..a5d94d4c4 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -7,6 +7,7 @@ "": { "name": "mempool-backend", "version": "3.0.0-dev", + "hasInstallScript": true, "license": "GNU Affero General Public License v3.0", "dependencies": { "@babel/core": "^7.24.0", @@ -42,6 +43,13 @@ "ts-node": "^10.9.1" } }, + "../rust/gbt": { + "version": "3.0.1", + "extraneous": true, + "engines": { + "node": ">= 12" + } + }, "node_modules/@aashutoshrathi/word-wrap": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", @@ -1499,21 +1507,6 @@ "node": ">=6" } }, - "node_modules/@napi-rs/cli": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/@napi-rs/cli/-/cli-2.18.0.tgz", - "integrity": "sha512-lfSRT7cs3iC4L+kv9suGYQEezn5Nii7Kpu+THsYVI0tA1Vh59LH45p4QADaD7hvIkmOz79eEGtoKQ9nAkAPkzA==", - "bin": { - "napi": "scripts/index.js" - }, - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - } - }, "node_modules/@noble/hashes": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.0.tgz", @@ -7668,10 +7661,6 @@ "rust-gbt": { "name": "gbt", "version": "3.0.1", - "hasInstallScript": true, - "dependencies": { - "@napi-rs/cli": "2.18.0" - }, "engines": { "node": ">= 12" } @@ -8774,11 +8763,6 @@ "resolved": "https://registry.npmjs.org/@mempool/electrum-client/-/electrum-client-1.1.9.tgz", "integrity": "sha512-mlvPiCzUlaETpYW3i6V87A24jjMYgsebaXtUo3WQyyLnYUuxs0KiXQ2mnKh3h15j8Xg/hfxeGIi+5OC9u0nftQ==" }, - "@napi-rs/cli": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/@napi-rs/cli/-/cli-2.18.0.tgz", - "integrity": "sha512-lfSRT7cs3iC4L+kv9suGYQEezn5Nii7Kpu+THsYVI0tA1Vh59LH45p4QADaD7hvIkmOz79eEGtoKQ9nAkAPkzA==" - }, "@noble/hashes": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.0.tgz", @@ -12701,10 +12685,7 @@ } }, "rust-gbt": { - "version": "file:rust-gbt", - "requires": { - "@napi-rs/cli": "2.18.0" - } + "version": "file:rust-gbt" }, "safe-buffer": { "version": "5.2.1", diff --git a/backend/package.json b/backend/package.json index 640250a1f..5710745f7 100644 --- a/backend/package.json +++ b/backend/package.json @@ -22,10 +22,12 @@ "main": "index.ts", "scripts": { "tsc": "./node_modules/typescript/bin/tsc -p tsconfig.build.json", - "build": "npm run rust-build && npm run tsc && npm run create-resources", + "build": "npm run tsc && npm run create-resources", + "clean": "rm -rf ./dist/ ./node_modules/ ./package/ ./rust-gbt/", "create-resources": "cp ./src/tasks/price-feeds/mtgox-weekly.json ./dist/tasks && node dist/api/fetch-version.js", "package": "./npm_package.sh", "package-rm-build-deps": "./npm_package_rm_build_deps.sh", + "preinstall": "cd ../rust/gbt && npm run build-release && npm run to-backend", "start": "node --max-old-space-size=2048 dist/index.js", "start-production": "node --max-old-space-size=16384 dist/index.js", "reindex-updated-pools": "npm run start-production --update-pools", @@ -34,9 +36,7 @@ "test:ci": "CI=true ./node_modules/.bin/jest --coverage", "lint": "./node_modules/.bin/eslint . --ext .ts", "lint:fix": "./node_modules/.bin/eslint . --ext .ts --fix", - "prettier": "./node_modules/.bin/prettier --write \"src/**/*.{js,ts}\"", - "rust-clean": "cd rust-gbt && rm -f *.node index.d.ts index.js && rm -rf target && cd ../", - "rust-build": "npm run rust-clean && cd rust-gbt && npm run build-release" + "prettier": "./node_modules/.bin/prettier --write \"src/**/*.{js,ts}\"" }, "dependencies": { "@babel/core": "^7.24.0", diff --git a/backend/rust-gbt/index.d.ts b/backend/rust-gbt/index.d.ts deleted file mode 100644 index d1cb85b92..000000000 --- a/backend/rust-gbt/index.d.ts +++ /dev/null @@ -1,50 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ - -/* auto-generated by NAPI-RS */ - -export interface ThreadTransaction { - uid: number - order: number - fee: number - weight: number - sigops: number - effectiveFeePerVsize: number - inputs: Array -} -export interface ThreadAcceleration { - uid: number - delta: number -} -export class GbtGenerator { - constructor() - /** - * # Errors - * - * Rejects if the thread panics or if the Mutex is poisoned. - */ - make(mempool: Array, accelerations: Array, maxUid: number): Promise - /** - * # Errors - * - * Rejects if the thread panics or if the Mutex is poisoned. - */ - update(newTxs: Array, removeTxs: Array, accelerations: Array, maxUid: number): Promise -} -/** - * 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. - * block_weights: A Vector of total weights per 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) - */ -export class GbtResult { - blocks: Array> - blockWeights: Array - clusters: Array> - rates: Array> - overflow: Array - constructor(blocks: Array>, blockWeights: Array, clusters: Array>, rates: Array>, overflow: Array) -} diff --git a/backend/rust-gbt/index.js b/backend/rust-gbt/index.js deleted file mode 100644 index dd58a8b76..000000000 --- a/backend/rust-gbt/index.js +++ /dev/null @@ -1,301 +0,0 @@ -/* 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 - case 'riscv64': - if (isMusl()) { - localFileExisted = existsSync( - join(__dirname, 'gbt.linux-riscv64-musl.node') - ) - try { - if (localFileExisted) { - nativeBinding = require('./gbt.linux-riscv64-musl.node') - } else { - nativeBinding = require('gbt-linux-riscv64-musl') - } - } catch (e) { - loadError = e - } - } else { - localFileExisted = existsSync( - join(__dirname, 'gbt.linux-riscv64-gnu.node') - ) - try { - if (localFileExisted) { - nativeBinding = require('./gbt.linux-riscv64-gnu.node') - } else { - nativeBinding = require('gbt-linux-riscv64-gnu') - } - } catch (e) { - loadError = e - } - } - break - case 's390x': - localFileExisted = existsSync( - join(__dirname, 'gbt.linux-s390x-gnu.node') - ) - try { - if (localFileExisted) { - nativeBinding = require('./gbt.linux-s390x-gnu.node') - } else { - nativeBinding = require('gbt-linux-s390x-gnu') - } - } 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 { GbtGenerator, GbtResult } = nativeBinding - -module.exports.GbtGenerator = GbtGenerator -module.exports.GbtResult = GbtResult diff --git a/backend/rust-gbt/package-lock.json b/backend/rust-gbt/package-lock.json deleted file mode 100644 index e351c82f8..000000000 --- a/backend/rust-gbt/package-lock.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "gbt", - "version": "3.0.1", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "gbt", - "version": "3.0.1", - "hasInstallScript": true, - "dependencies": { - "@napi-rs/cli": "2.18.0" - }, - "engines": { - "node": ">= 12" - } - }, - "node_modules/@napi-rs/cli": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/@napi-rs/cli/-/cli-2.18.0.tgz", - "integrity": "sha512-lfSRT7cs3iC4L+kv9suGYQEezn5Nii7Kpu+THsYVI0tA1Vh59LH45p4QADaD7hvIkmOz79eEGtoKQ9nAkAPkzA==", - "bin": { - "napi": "scripts/index.js" - }, - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - } - } - } -} diff --git a/backend/src/api/acceleration.ts b/backend/src/api/acceleration.ts index fff8ffd3f..20c0e3b31 100644 --- a/backend/src/api/acceleration.ts +++ b/backend/src/api/acceleration.ts @@ -238,7 +238,7 @@ class AccelerationCosts { private convertToGraphTx(tx: MempoolTransactionExtended): GraphTx { return { txid: tx.txid, - vsize: tx.vsize, + vsize: Math.ceil(tx.weight / 4), weight: tx.weight, fees: { base: 0, // dummy @@ -256,7 +256,7 @@ class AccelerationCosts { ancestor: tx.fees.base, }, ancestorcount: 1, - ancestorsize: tx.vsize, + ancestorsize: Math.ceil(tx.weight / 4), ancestors: new Map(), ancestorRate: 0, individualRate: 0, @@ -493,7 +493,7 @@ interface MinerTransaction extends TemplateTransaction { * Build a block 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) */ -function makeBlockTemplate(candidates: IEsploraApi.Transaction[], accelerations: Acceleration[], maxBlocks: number = 8, weightLimit: number = BLOCK_WEIGHT_UNITS, sigopLimit: number = BLOCK_SIGOPS): TemplateTransaction[] { +export function makeBlockTemplate(candidates: IEsploraApi.Transaction[], accelerations: Acceleration[], maxBlocks: number = 8, weightLimit: number = BLOCK_WEIGHT_UNITS, sigopLimit: number = BLOCK_SIGOPS): TemplateTransaction[] { const auditPool: Map = new Map(); const mempoolArray: MinerTransaction[] = []; diff --git a/backend/src/api/database-migration.ts b/backend/src/api/database-migration.ts index a32845594..cf9acbc53 100644 --- a/backend/src/api/database-migration.ts +++ b/backend/src/api/database-migration.ts @@ -7,7 +7,7 @@ import cpfpRepository from '../repositories/CpfpRepository'; import { RowDataPacket } from 'mysql2'; class DatabaseMigration { - private static currentVersion = 74; + private static currentVersion = 75; private queryTimeout = 3600_000; private statisticsAddedIndexed = false; private uniqueLogs: string[] = []; @@ -620,7 +620,12 @@ class DatabaseMigration { await this.updateToSchemaVersion(73); } - if (databaseSchemaVersion < 74) { + if (databaseSchemaVersion < 74 && config.MEMPOOL.NETWORK === 'mainnet') { + await this.$executeQuery(`INSERT INTO state(name, number) VALUE ('last_acceleration_block', 0);`); + await this.updateToSchemaVersion(74); + } + + if (databaseSchemaVersion < 75) { await this.$executeQuery('ALTER TABLE `prices` ADD `BGN` float DEFAULT "-1"'); await this.$executeQuery('ALTER TABLE `prices` ADD `BRL` float DEFAULT "-1"'); await this.$executeQuery('ALTER TABLE `prices` ADD `CNY` float DEFAULT "-1"'); @@ -647,7 +652,7 @@ class DatabaseMigration { await this.$executeQuery('ALTER TABLE `prices` ADD `THB` float DEFAULT "-1"'); await this.$executeQuery('ALTER TABLE `prices` ADD `TRY` float DEFAULT "-1"'); await this.$executeQuery('ALTER TABLE `prices` ADD `ZAR` float DEFAULT "-1"'); - await this.updateToSchemaVersion(74); + await this.updateToSchemaVersion(75); } } diff --git a/backend/src/api/services/acceleration.ts b/backend/src/api/services/acceleration.ts index 99bb963ee..f22959f3f 100644 --- a/backend/src/api/services/acceleration.ts +++ b/backend/src/api/services/acceleration.ts @@ -7,7 +7,26 @@ export interface Acceleration { txid: string, feeDelta: number, pools: number[], -} +}; + +export interface AccelerationHistory { + txid: string, + status: string, + feePaid: number, + added: number, + lastUpdated: number, + baseFee: number, + vsizeFee: number, + effectiveFee: number, + effectiveVsize: number, + feeDelta: number, + blockHash: string, + blockHeight: number, + pools: { + pool_unique_id: number, + username: string, + }[], +}; class AccelerationApi { public async $fetchAccelerations(): Promise { @@ -24,6 +43,27 @@ class AccelerationApi { } } + public async $fetchAccelerationHistory(page?: number, status?: string): Promise { + if (config.MEMPOOL_SERVICES.ACCELERATIONS) { + try { + const response = await axios.get(`${config.MEMPOOL_SERVICES.API}/accelerator/accelerations/history`, { + responseType: 'json', + timeout: 10000, + params: { + page, + status, + } + }); + return response.data as AccelerationHistory[]; + } catch (e) { + logger.warn('Failed to fetch acceleration history from the mempool services backend: ' + (e instanceof Error ? e.message : e)); + return null; + } + } else { + return []; + } + } + public isAcceleratedBlock(block: BlockExtended, accelerations: Acceleration[]): boolean { let anyAccelerated = false; for (let i = 0; i < accelerations.length && !anyAccelerated; i++) { diff --git a/backend/src/api/websocket-handler.ts b/backend/src/api/websocket-handler.ts index 6711c88fb..925b676f1 100644 --- a/backend/src/api/websocket-handler.ts +++ b/backend/src/api/websocket-handler.ts @@ -24,7 +24,6 @@ import { ApiPrice } from '../repositories/PricesRepository'; import accelerationApi from './services/acceleration'; import mempool from './mempool'; import statistics from './statistics/statistics'; -import accelerationCosts from './acceleration'; import accelerationRepository from '../repositories/AccelerationRepository'; import bitcoinApi from './bitcoin/bitcoin-api-factory'; @@ -742,25 +741,8 @@ class WebsocketHandler { const isAccelerated = config.MEMPOOL_SERVICES.ACCELERATIONS && accelerationApi.isAcceleratedBlock(block, Object.values(mempool.getAccelerations())); - - if (isAccelerated) { - const blockTxs: { [txid: string]: MempoolTransactionExtended } = {}; - for (const tx of transactions) { - blockTxs[tx.txid] = tx; - } - const accelerations = Object.values(mempool.getAccelerations()); - const boostRate = accelerationCosts.calculateBoostRate( - accelerations.map(acc => ({ txid: acc.txid, max_bid: acc.feeDelta })), - transactions - ); - for (const acc of accelerations) { - if (blockTxs[acc.txid]) { - const tx = blockTxs[acc.txid]; - const accelerationInfo = accelerationCosts.getAccelerationInfo(tx, boostRate, transactions); - accelerationRepository.$saveAcceleration(accelerationInfo, block, block.extras.pool.id); - } - } - } + const accelerations = Object.values(mempool.getAccelerations()); + await accelerationRepository.$indexAccelerationsForBlock(block, accelerations, transactions); const rbfTransactions = Common.findMinedRbfTransactions(transactions, memPool.getSpendMap()); memPool.handleMinedRbfTransactions(rbfTransactions); diff --git a/backend/src/indexer.ts b/backend/src/indexer.ts index 663a64c6d..bc169630f 100644 --- a/backend/src/indexer.ts +++ b/backend/src/indexer.ts @@ -8,6 +8,7 @@ import priceUpdater from './tasks/price-updater'; import PricesRepository from './repositories/PricesRepository'; import config from './config'; import auditReplicator from './replication/AuditReplication'; +import AccelerationRepository from './repositories/AccelerationRepository'; export interface CoreIndex { name: string; @@ -187,6 +188,7 @@ class Indexer { await blocks.$generateCPFPDatabase(); await blocks.$generateAuditStats(); await auditReplicator.$sync(); + await AccelerationRepository.$indexPastAccelerations(); // do not wait for classify blocks to finish blocks.$classifyBlocks(); } catch (e) { diff --git a/backend/src/repositories/AccelerationRepository.ts b/backend/src/repositories/AccelerationRepository.ts index c98d007c5..f16a3dfd6 100644 --- a/backend/src/repositories/AccelerationRepository.ts +++ b/backend/src/repositories/AccelerationRepository.ts @@ -1,10 +1,16 @@ -import { AccelerationInfo } from '../api/acceleration'; -import { ResultSetHeader, RowDataPacket } from 'mysql2'; +import { AccelerationInfo, makeBlockTemplate } from '../api/acceleration'; +import { RowDataPacket } from 'mysql2'; import DB from '../database'; import logger from '../logger'; import { IEsploraApi } from '../api/bitcoin/esplora-api.interface'; import { Common } from '../api/common'; import config from '../config'; +import blocks from '../api/blocks'; +import accelerationApi, { Acceleration } from '../api/services/acceleration'; +import accelerationCosts from '../api/acceleration'; +import bitcoinApi from '../api/bitcoin/bitcoin-api-factory'; +import transactionUtils from '../api/transaction-utils'; +import { BlockExtended, MempoolTransactionExtended } from '../mempool.interfaces'; export interface PublicAcceleration { txid: string, @@ -21,19 +27,15 @@ export interface PublicAcceleration { } class AccelerationRepository { + private bidBoostV2Activated = 831580; + public async $saveAcceleration(acceleration: AccelerationInfo, block: IEsploraApi.Block, pool_id: number): Promise { try { await DB.query(` INSERT INTO accelerations(txid, added, height, pool, effective_vsize, effective_fee, boost_rate, boost_cost) VALUE (?, FROM_UNIXTIME(?), ?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE - added = FROM_UNIXTIME(?), - height = ?, - pool = ?, - effective_vsize = ?, - effective_fee = ?, - boost_rate = ?, - boost_cost = ? + height = ? `, [ acceleration.txSummary.txid, block.timestamp, @@ -41,13 +43,9 @@ class AccelerationRepository { pool_id, acceleration.txSummary.effectiveVsize, acceleration.txSummary.effectiveFee, - acceleration.targetFeeRate, acceleration.cost, - block.timestamp, + acceleration.targetFeeRate, + acceleration.cost, block.height, - pool_id, - acceleration.txSummary.effectiveVsize, - acceleration.txSummary.effectiveFee, - acceleration.targetFeeRate, acceleration.cost, ]); } catch (e: any) { logger.err(`Cannot save acceleration (${acceleration.txSummary.txid}) into db. Reason: ` + (e instanceof Error ? e.message : e)); @@ -72,7 +70,7 @@ class AccelerationRepository { let params: any[] = []; let hasFilter = false; - if (interval) { + if (interval && height === null) { query += ` WHERE accelerations.added BETWEEN DATE_SUB(NOW(), INTERVAL ${interval}) AND NOW() `; hasFilter = true; } @@ -119,6 +117,167 @@ class AccelerationRepository { throw e; } } + + public async $getLastSyncedHeight(): Promise { + try { + const [rows] = await DB.query(` + SELECT * FROM state + WHERE name = 'last_acceleration_block' + `); + if (rows?.['length']) { + return rows[0].number; + } + } catch (e: any) { + logger.err(`Cannot find last acceleration sync height. Reason: ` + (e instanceof Error ? e.message : e)); + } + return 0; + } + + private async $setLastSyncedHeight(height: number): Promise { + try { + await DB.query(` + UPDATE state + SET number = ? + WHERE name = 'last_acceleration_block' + `, [height]); + } catch (e: any) { + logger.err(`Cannot update last acceleration sync height. Reason: ` + (e instanceof Error ? e.message : e)); + } + } + + public async $indexAccelerationsForBlock(block: BlockExtended, accelerations: Acceleration[], transactions: MempoolTransactionExtended[]): Promise { + const blockTxs: { [txid: string]: MempoolTransactionExtended } = {}; + for (const tx of transactions) { + blockTxs[tx.txid] = tx; + } + const successfulAccelerations = accelerations.filter(acc => acc.pools.includes(block.extras.pool.id)); + let boostRate: number | null = null; + for (const acc of successfulAccelerations) { + if (boostRate === null) { + boostRate = accelerationCosts.calculateBoostRate( + accelerations.map(acc => ({ txid: acc.txid, max_bid: acc.feeDelta })), + transactions + ); + } + if (blockTxs[acc.txid]) { + const tx = blockTxs[acc.txid]; + const accelerationInfo = accelerationCosts.getAccelerationInfo(tx, boostRate, transactions); + accelerationInfo.cost = Math.max(0, Math.min(acc.feeDelta, accelerationInfo.cost)); + this.$saveAcceleration(accelerationInfo, block, block.extras.pool.id); + } + } + const lastSyncedHeight = await this.$getLastSyncedHeight(); + // if we've missed any blocks, let the indexer catch up from the last synced height on the next run + if (block.height === lastSyncedHeight + 1) { + await this.$setLastSyncedHeight(block.height); + } + } + + /** + * [INDEXING] Backfill missing acceleration data + */ + async $indexPastAccelerations(): Promise { + if (config.MEMPOOL.NETWORK !== 'mainnet' || !config.MEMPOOL_SERVICES.ACCELERATIONS) { + // acceleration history disabled + return; + } + const lastSyncedHeight = await this.$getLastSyncedHeight(); + const currentHeight = blocks.getCurrentBlockHeight(); + if (currentHeight <= lastSyncedHeight) { + // already in sync + return; + } + + logger.debug(`Fetching accelerations between block ${lastSyncedHeight} and ${currentHeight}`); + + // Fetch accelerations from mempool.space since the last synced block; + const accelerationsByBlock = {}; + const blockHashes = {}; + let done = false; + let page = 1; + let count = 0; + try { + while (!done) { + const accelerations = await accelerationApi.$fetchAccelerationHistory(page); + page++; + if (!accelerations?.length) { + done = true; + break; + } + for (const acc of accelerations) { + if (acc.status !== 'mined' && acc.status !== 'completed') { + continue; + } + if (!lastSyncedHeight || acc.blockHeight > lastSyncedHeight) { + if (!accelerationsByBlock[acc.blockHeight]) { + accelerationsByBlock[acc.blockHeight] = []; + blockHashes[acc.blockHeight] = acc.blockHash; + } + accelerationsByBlock[acc.blockHeight].push(acc); + count++; + } else { + done = true; + } + } + } + } catch (e) { + logger.err(`Failed to fetch full acceleration history. Reason: ` + (e instanceof Error ? e.message : e)); + } + + logger.debug(`Indexing ${count} accelerations between block ${lastSyncedHeight} and ${currentHeight}`); + + // process accelerated blocks in order + const heights = Object.keys(accelerationsByBlock).map(key => parseInt(key)).sort((a,b) => a - b); + for (const height of heights) { + const accelerations = accelerationsByBlock[height]; + try { + const block = await blocks.$getBlock(blockHashes[height]) as BlockExtended; + const transactions = (await bitcoinApi.$getTxsForBlock(blockHashes[height])).map(tx => transactionUtils.extendMempoolTransaction(tx)); + + const blockTxs = {}; + for (const tx of transactions) { + blockTxs[tx.txid] = tx; + } + + let boostRate = 0; + // use Bid Boost V2 if active + if (height > this.bidBoostV2Activated) { + boostRate = accelerationCosts.calculateBoostRate( + accelerations.map(acc => ({ txid: acc.txid, max_bid: acc.feeDelta })), + transactions + ); + } else { + // default to Bid Boost V1 (median block fee rate) + const template = makeBlockTemplate( + transactions, + accelerations.map(acc => ({ txid: acc.txid, max_bid: acc.feeDelta })), + 1, + Infinity, + Infinity + ); + const feeStats = Common.calcEffectiveFeeStatistics(template); + boostRate = feeStats.medianFee; + } + for (const acc of accelerations) { + if (blockTxs[acc.txid]) { + const tx = blockTxs[acc.txid]; + const accelerationInfo = accelerationCosts.getAccelerationInfo(tx, boostRate, transactions); + accelerationInfo.cost = Math.max(0, Math.min(acc.feeDelta, accelerationInfo.cost)); + await this.$saveAcceleration(accelerationInfo, block, block.extras.pool.id); + } + } + await this.$setLastSyncedHeight(height); + } catch (e) { + logger.err(`Failed to process accelerations for block ${height}. Reason: ` + (e instanceof Error ? e.message : e)); + return; + } + logger.debug(`Indexed ${accelerations.length} accelerations in block ${height}`); + } + + await this.$setLastSyncedHeight(currentHeight); + + logger.debug(`Indexing accelerations completed`); + } } export default new AccelerationRepository(); diff --git a/contributors/russeree.txt b/contributors/russeree.txt new file mode 100644 index 000000000..0aaef47e5 --- /dev/null +++ b/contributors/russeree.txt @@ -0,0 +1,3 @@ +I hereby accept the terms of the Contributor License Agreement in the CONTRIBUTING.md file of the mempool/mempool git repository as of March 8, 2024. + +Signed: PortlandHODL diff --git a/frontend/src/app/components/block/block.component.scss b/frontend/src/app/components/block/block.component.scss index 4dd079eb8..a76737c4d 100644 --- a/frontend/src/app/components/block/block.component.scss +++ b/frontend/src/app/components/block/block.component.scss @@ -290,7 +290,7 @@ h1 { } .oobFees { - color: #653b9c; + color: #905cf4; } } diff --git a/frontend/src/app/components/block/block.component.ts b/frontend/src/app/components/block/block.component.ts index 3cb60e048..c61fd0e12 100644 --- a/frontend/src/app/components/block/block.component.ts +++ b/frontend/src/app/components/block/block.component.ts @@ -61,6 +61,7 @@ export class BlockComponent implements OnInit, OnDestroy { transactionsError: any = null; overviewError: any = null; webGlEnabled = true; + auditParamEnabled: boolean = false; auditSupported: boolean = this.stateService.env.AUDIT && this.stateService.env.BASE_MODULE === 'mempool' && this.stateService.env.MINING_DASHBOARD === true; auditModeEnabled: boolean = !this.stateService.hideAudit.value; auditAvailable = true; @@ -124,9 +125,15 @@ export class BlockComponent implements OnInit, OnDestroy { this.setAuditAvailable(this.auditSupported); if (this.auditSupported) { - this.auditPrefSubscription = this.stateService.hideAudit.subscribe((hide) => { - this.auditModeEnabled = !hide; - this.showAudit = this.auditAvailable && this.auditModeEnabled; + this.isAuditEnabledFromParam().subscribe(auditParam => { + if (this.auditParamEnabled) { + this.auditModeEnabled = auditParam; + } else { + this.auditPrefSubscription = this.stateService.hideAudit.subscribe(hide => { + this.auditModeEnabled = !hide; + this.showAudit = this.auditAvailable && this.auditModeEnabled; + }); + } }); } @@ -723,6 +730,24 @@ export class BlockComponent implements OnInit, OnDestroy { toggleAuditMode(): void { this.stateService.hideAudit.next(this.auditModeEnabled); + + this.route.queryParams.subscribe(params => { + let queryParams = { ...params }; + delete queryParams['audit']; + + let newUrl = this.router.url.split('?')[0]; + let queryString = new URLSearchParams(queryParams).toString(); + if (queryString) { + newUrl += '?' + queryString; + } + + this.location.replaceState(newUrl); + }); + + this.auditPrefSubscription = this.stateService.hideAudit.subscribe((hide) => { + this.auditModeEnabled = !hide; + this.showAudit = this.auditAvailable && this.auditModeEnabled; + }); } updateAuditAvailableFromBlockHeight(blockHeight: number): void { @@ -731,6 +756,16 @@ export class BlockComponent implements OnInit, OnDestroy { } } + isAuditEnabledFromParam(): Observable { + return this.route.queryParams.pipe( + map(params => { + this.auditParamEnabled = 'audit' in params; + + return this.auditParamEnabled ? !(params['audit'] === 'false') : true; + }) + ); + } + isAuditAvailableFromBlockHeight(blockHeight: number): boolean { if (!this.auditSupported) { return false; @@ -779,4 +814,4 @@ export class BlockComponent implements OnInit, OnDestroy { this.block.canonical = block.id; } } -} +} \ No newline at end of file diff --git a/frontend/src/resources/previews/enterprise.jpg b/frontend/src/resources/previews/enterprise.jpg new file mode 100644 index 000000000..293f39e0b Binary files /dev/null and b/frontend/src/resources/previews/enterprise.jpg differ diff --git a/frontend/src/resources/previews/sponsor.jpg b/frontend/src/resources/previews/sponsor.jpg new file mode 100644 index 000000000..a27f7af73 Binary files /dev/null and b/frontend/src/resources/previews/sponsor.jpg differ diff --git a/backend/rust-gbt/.gitignore b/rust/gbt/.gitignore similarity index 51% rename from backend/rust-gbt/.gitignore rename to rust/gbt/.gitignore index 6b0a536a0..90261c365 100644 --- a/backend/rust-gbt/.gitignore +++ b/rust/gbt/.gitignore @@ -1,4 +1,8 @@ +package-lock.json +index.js +index.d.ts *.node **/node_modules +**/target **/.DS_Store npm-debug.log* diff --git a/Cargo.lock b/rust/gbt/Cargo.lock similarity index 66% rename from Cargo.lock rename to rust/gbt/Cargo.lock index 0b51ea544..d7ac48ec7 100644 --- a/Cargo.lock +++ b/rust/gbt/Cargo.lock @@ -3,10 +3,25 @@ version = 3 [[package]] -name = "aho-corasick" -version = "1.0.1" +name = "addr2line" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] @@ -18,22 +33,43 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] -name = "bitflags" -version = "2.3.2" +name = "backtrace" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbe3c979c178231552ecba20214a8272df4e09f232a87aef4320cf06539aded" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "bitflags" +version = "2.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" [[package]] name = "bytemuck" -version = "1.13.1" +version = "1.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" +checksum = "a2ef034f05691a48569bd920a96c81b9d91bbad1ab5ac7c4616c1f6ef36cb79f" [[package]] name = "bytes" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" + +[[package]] +name = "cc" +version = "1.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" [[package]] name = "cfg-if" @@ -52,9 +88,9 @@ dependencies = [ [[package]] name = "ctor" -version = "0.2.2" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1586fa608b1dab41f667475b4a41faec5ba680aee428bfa5de4ea520fdc6e901" +checksum = "ad291aa74992b9b7a7e88c38acbbf6ad7e107f1d90ee8775b7bc1fc3394f485c" dependencies = [ "quote", "syn", @@ -77,10 +113,16 @@ dependencies = [ "napi-derive", "priority-queue", "tracing", - "tracing-log 0.2.0", + "tracing-log", "tracing-subscriber", ] +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + [[package]] name = "hashbrown" version = "0.14.3" @@ -89,12 +131,9 @@ checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" [[package]] name = "hermit-abi" -version = "0.2.6" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "indexmap" @@ -114,15 +153,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.146" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libloading" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2caa5afb8bf9f3a2652760ce7d4f62d21c4d5a423e68466fca30df82f2330164" +checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", "windows-targets", @@ -130,9 +169,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.19" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "matchers" @@ -140,14 +179,23 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" dependencies = [ - "regex-automata", + "regex-automata 0.1.10", ] [[package]] name = "memchr" -version = "2.5.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +dependencies = [ + "adler", +] [[package]] name = "napi" @@ -219,14 +267,23 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ "hermit-abi", "libc", ] +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.19.0" @@ -241,9 +298,9 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "priority-queue" @@ -258,31 +315,32 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.60" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.28" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] [[package]] name = "regex" -version = "1.8.3" +version = "1.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81ca098a9821bd52d6b24fd8b10bd081f47d39c22778cafaa75a2857a62c6390" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.2", + "regex-automata 0.4.6", + "regex-syntax 0.8.2", ] [[package]] @@ -294,6 +352,17 @@ dependencies = [ "regex-syntax 0.6.29", ] +[[package]] +name = "regex-automata" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.2", +] + [[package]] name = "regex-syntax" version = "0.6.29" @@ -302,36 +371,42 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.2" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "semver" -version = "1.0.17" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "sharded-slab" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ "lazy_static", ] [[package]] name = "smallvec" -version = "1.10.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "syn" -version = "2.0.20" +version = "2.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb8d4cebc40aa517dfb69618fa647a346562e67228e2236ae0042ee6ac14775" +checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" dependencies = [ "proc-macro2", "quote", @@ -340,9 +415,9 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ "cfg-if", "once_cell", @@ -350,23 +425,21 @@ dependencies = [ [[package]] name = "tokio" -version = "1.28.2" +version = "1.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2" +checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" dependencies = [ - "autocfg", + "backtrace", "num_cpus", "pin-project-lite", - "windows-sys", ] [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -374,9 +447,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", @@ -385,25 +458,14 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", ] -[[package]] -name = "tracing-log" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" -dependencies = [ - "lazy_static", - "log", - "tracing-core", -] - [[package]] name = "tracing-log" version = "0.2.0" @@ -417,9 +479,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ "matchers", "nu-ansi-term", @@ -430,20 +492,20 @@ dependencies = [ "thread_local", "tracing", "tracing-core", - "tracing-log 0.1.3", + "tracing-log", ] [[package]] name = "unicode-ident" -version = "1.0.9" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-segmentation" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "valuable" @@ -473,20 +535,11 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets", -] - [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -499,42 +552,42 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" diff --git a/backend/rust-gbt/Cargo.toml b/rust/gbt/Cargo.toml similarity index 92% rename from backend/rust-gbt/Cargo.toml rename to rust/gbt/Cargo.toml index 10c572bf9..c6e736762 100644 --- a/backend/rust-gbt/Cargo.toml +++ b/rust/gbt/Cargo.toml @@ -23,3 +23,7 @@ tracing-subscriber = { version = "0.3.15", features = ["env-filter"]} [build-dependencies] napi-build = "2.1.2" + +[profile.release] +lto = true +codegen-units = 1 diff --git a/backend/rust-gbt/README.md b/rust/gbt/README.md similarity index 100% rename from backend/rust-gbt/README.md rename to rust/gbt/README.md diff --git a/backend/rust-gbt/build.rs b/rust/gbt/build.rs similarity index 100% rename from backend/rust-gbt/build.rs rename to rust/gbt/build.rs diff --git a/backend/rust-gbt/package.json b/rust/gbt/package.json similarity index 54% rename from backend/rust-gbt/package.json rename to rust/gbt/package.json index b0dd96698..90497fe9c 100644 --- a/backend/rust-gbt/package.json +++ b/rust/gbt/package.json @@ -6,10 +6,12 @@ "types": "index.d.ts", "scripts": { "artifacts": "napi artifacts", - "build": "napi build --platform", + "build": "npm install --no-save @napi-rs/cli@2.18.0 && npm run check-cargo-version && napi build --platform", "build-debug": "npm run build", "build-release": "npm run build -- --release --strip", - "install": "npm run build-release", + "check-cargo-version": "VER=$(cat rust-toolchain) ; if ! cargo version | grep \"cargo $VER\" >/dev/null ; then echo -e \"\\033[1;35m[[[[WARNING]]]]: cargo version mismatch with ./rust-toolchain version ($VER)!!!\\033[0m\" >&2; fi", + "clean": "rm -rf ./target/ ./node_modules/ *.node package-lock.json", + "to-backend": "FD=../../backend/rust-gbt/ ; rm -rf $FD && mkdir $FD && cp index.js index.d.ts package.json *.node $FD", "prepublishOnly": "napi prepublish -t npm", "test": "cargo test" }, @@ -24,9 +26,6 @@ ] } }, - "dependencies": { - "@napi-rs/cli": "2.18.0" - }, "engines": { "node": ">= 12" } diff --git a/rust-toolchain b/rust/gbt/rust-toolchain similarity index 100% rename from rust-toolchain rename to rust/gbt/rust-toolchain diff --git a/backend/rust-gbt/src/audit_transaction.rs b/rust/gbt/src/audit_transaction.rs similarity index 100% rename from backend/rust-gbt/src/audit_transaction.rs rename to rust/gbt/src/audit_transaction.rs diff --git a/backend/rust-gbt/src/gbt.rs b/rust/gbt/src/gbt.rs similarity index 100% rename from backend/rust-gbt/src/gbt.rs rename to rust/gbt/src/gbt.rs diff --git a/backend/rust-gbt/src/lib.rs b/rust/gbt/src/lib.rs similarity index 100% rename from backend/rust-gbt/src/lib.rs rename to rust/gbt/src/lib.rs diff --git a/backend/rust-gbt/src/thread_acceleration.rs b/rust/gbt/src/thread_acceleration.rs similarity index 100% rename from backend/rust-gbt/src/thread_acceleration.rs rename to rust/gbt/src/thread_acceleration.rs diff --git a/backend/rust-gbt/src/thread_transaction.rs b/rust/gbt/src/thread_transaction.rs similarity index 100% rename from backend/rust-gbt/src/thread_transaction.rs rename to rust/gbt/src/thread_transaction.rs diff --git a/backend/rust-gbt/src/u32_hasher_types.rs b/rust/gbt/src/u32_hasher_types.rs similarity index 100% rename from backend/rust-gbt/src/u32_hasher_types.rs rename to rust/gbt/src/u32_hasher_types.rs diff --git a/unfurler/src/routes.ts b/unfurler/src/routes.ts index c266217c8..e7dce9398 100644 --- a/unfurler/src/routes.ts +++ b/unfurler/src/routes.ts @@ -19,6 +19,13 @@ const routes = { title: "Mempool Accelerator", fallbackImg: '/resources/previews/accelerator.jpg', }, + address: { + render: true, + params: 1, + getTitle(path) { + return `Address: ${path[0]}`; + } + }, block: { render: true, params: 1, @@ -40,25 +47,9 @@ const routes = { } } }, - address: { - render: true, - params: 1, - getTitle(path) { - return `Address: ${path[0]}`; - } - }, - tx: { - render: true, - params: 1, - getTitle(path) { - return `Transaction: ${path[0]}`; - }, - routes: { - push: { - title: "Push Transaction", - fallbackImg: '/resources/previews/tx-push.jpg', - } - } + enterprise: { + title: "Mempool Enterprise", + fallbackImg: '/resources/previews/enterprise.jpg', }, lightning: { title: "Lightning", @@ -119,6 +110,10 @@ const routes = { title: "RBF", fallbackImg: '/resources/previews/rbf.jpg', }, + sponsor: { + title: "Community Sponsors", + fallbackImg: '/resources/previews/sponsor.jpg', + }, "terms-of-service": { title: "Terms of Service", fallbackImg: '/resources/previews/terms-of-service.jpg', @@ -127,6 +122,19 @@ const routes = { title: "Trademark Policy", fallbackImg: '/resources/previews/trademark-policy.jpg', }, + tx: { + render: true, + params: 1, + getTitle(path) { + return `Transaction: ${path[0]}`; + }, + routes: { + push: { + title: "Push Transaction", + fallbackImg: '/resources/previews/tx-push.jpg', + } + } + } }; const networks = {