diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 68ffa840a..976fe5a7a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ jobs: if: "(github.event_name == 'pull_request' && !contains(github.event.pull_request.labels.*.name, 'ops') && !contains(github.head_ref, 'ops/')) || github.event_name == 'push'" strategy: matrix: - node: ["22"] + node: ["22.14.0"] flavor: ["dev", "prod"] fail-fast: false runs-on: ubuntu-latest @@ -163,7 +163,7 @@ jobs: if: "(github.event_name == 'pull_request' && !contains(github.event.pull_request.labels.*.name, 'ops') && !contains(github.head_ref, 'ops/')) || github.event_name == 'push'" strategy: matrix: - node: ["22"] + node: ["22.14.0"] flavor: ["dev", "prod"] fail-fast: false runs-on: ubuntu-latest diff --git a/.github/workflows/e2e_parameterized.yml b/.github/workflows/e2e_parameterized.yml index a53677a80..8b07ffe82 100644 --- a/.github/workflows/e2e_parameterized.yml +++ b/.github/workflows/e2e_parameterized.yml @@ -43,7 +43,7 @@ jobs: - name: Setup Node uses: actions/setup-node@v3 with: - node-version: ${{ matrix.node }} + node-version: 22.14.0 registry-url: "https://registry.npmjs.org" - name: Install (Prod dependencies only) @@ -151,7 +151,7 @@ jobs: - name: Setup node uses: actions/setup-node@v3 with: - node-version: 22 + node-version: 22.14.0 cache: "npm" cache-dependency-path: ${{ matrix.module }}/frontend/package-lock.json diff --git a/.github/workflows/on-tag.yml b/.github/workflows/on-tag.yml index 1447ec4ab..4a6882b81 100644 --- a/.github/workflows/on-tag.yml +++ b/.github/workflows/on-tag.yml @@ -105,8 +105,9 @@ jobs: --cache-to "type=local,dest=/tmp/.buildx-cache,mode=max" \ --platform linux/amd64,linux/arm64 \ --tag ${{ secrets.DOCKER_HUB_USER }}/${{ matrix.service }}:$TAG \ + --tag ${{ secrets.DOCKER_HUB_USER }}/${{ matrix.service }}:latest \ --build-context rustgbt=./rust \ --build-context backend=./backend \ --output "type=registry,push=true" \ --build-arg commitHash=$SHORT_SHA \ - ./${{ matrix.service }}/ \ No newline at end of file + ./${{ matrix.service }}/ diff --git a/backend/package-lock.json b/backend/package-lock.json index a4963d6f0..aa10a1a11 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -1,12 +1,12 @@ { "name": "mempool-backend", - "version": "3.1.0-dev", + "version": "3.3-dev", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mempool-backend", - "version": "3.1.0-dev", + "version": "3.2.0-dev", "hasInstallScript": true, "license": "GNU Affero General Public License v3.0", "dependencies": { diff --git a/backend/package.json b/backend/package.json index bcbc0f256..ab24e9596 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "mempool-backend", - "version": "3.1.0-dev", + "version": "3.3-dev", "description": "Bitcoin mempool visualizer and blockchain explorer backend", "license": "GNU Affero General Public License v3.0", "homepage": "https://mempool.space", diff --git a/backend/src/api/bitcoin/esplora-api.ts b/backend/src/api/bitcoin/esplora-api.ts index 8035d92c0..6ee51fda4 100644 --- a/backend/src/api/bitcoin/esplora-api.ts +++ b/backend/src/api/bitcoin/esplora-api.ts @@ -36,7 +36,7 @@ class FailoverRouter { maxHeight: number = 0; hosts: FailoverHost[]; multihost: boolean; - gitHashInterval: number = 600000; // 10 minutes + gitHashInterval: number = 60000; // 1 minute pollInterval: number = 60000; // 1 minute pollTimer: NodeJS.Timeout | null = null; pollConnection = axios.create(); @@ -111,7 +111,7 @@ class FailoverRouter { for (const host of this.hosts) { try { const result = await (host.socket - ? this.pollConnection.get('/blocks/tip/height', { socketPath: host.host, timeout: config.ESPLORA.FALLBACK_TIMEOUT }) + ? this.pollConnection.get('http://api/blocks/tip/height', { socketPath: host.host, timeout: config.ESPLORA.FALLBACK_TIMEOUT }) : this.pollConnection.get(host.host + '/blocks/tip/height', { timeout: config.ESPLORA.FALLBACK_TIMEOUT }) ); if (result) { @@ -288,7 +288,7 @@ class FailoverRouter { let url; if (host.socket) { axiosConfig = { socketPath: host.host, timeout: config.ESPLORA.REQUEST_TIMEOUT, responseType }; - url = path; + url = 'http://api' + path; } else { axiosConfig = { timeout: config.ESPLORA.REQUEST_TIMEOUT, responseType }; url = host.host + path; diff --git a/backend/src/api/blocks.ts b/backend/src/api/blocks.ts index beefc825b..d475470db 100644 --- a/backend/src/api/blocks.ts +++ b/backend/src/api/blocks.ts @@ -1391,7 +1391,7 @@ class Blocks { } public async $getBlockAuditSummary(hash: string): Promise { - if (['mainnet', 'testnet', 'signet'].includes(config.MEMPOOL.NETWORK)) { + if (['mainnet', 'testnet', 'signet'].includes(config.MEMPOOL.NETWORK) && Common.auditIndexingEnabled()) { return BlocksAuditsRepository.$getBlockAudit(hash); } else { return null; @@ -1399,7 +1399,7 @@ class Blocks { } public async $getBlockTxAuditSummary(hash: string, txid: string): Promise { - if (['mainnet', 'testnet', 'signet'].includes(config.MEMPOOL.NETWORK)) { + if (['mainnet', 'testnet', 'signet'].includes(config.MEMPOOL.NETWORK) && Common.auditIndexingEnabled()) { return BlocksAuditsRepository.$getBlockTxAudit(hash, txid); } else { return null; diff --git a/backend/src/api/common.ts b/backend/src/api/common.ts index 50de63afc..f3569c44c 100644 --- a/backend/src/api/common.ts +++ b/backend/src/api/common.ts @@ -722,6 +722,13 @@ export class Common { ); } + static auditIndexingEnabled(): boolean { + return ( + Common.indexingEnabled() && + config.MEMPOOL.AUDIT === true + ); + } + static gogglesIndexingEnabled(): boolean { return ( Common.blocksSummariesIndexingEnabled() && diff --git a/backend/src/api/pools-parser.ts b/backend/src/api/pools-parser.ts index 2fd55d6c5..2895da5a5 100644 --- a/backend/src/api/pools-parser.ts +++ b/backend/src/api/pools-parser.ts @@ -8,6 +8,7 @@ import mining from './mining/mining'; import transactionUtils from './transaction-utils'; import BlocksRepository from '../repositories/BlocksRepository'; import redisCache from './redis-cache'; +import blocks from './blocks'; class PoolsParser { miningPools: any[] = []; @@ -42,6 +43,8 @@ class PoolsParser { await this.$insertUnknownPool(); let reindexUnknown = false; + let clearCache = false; + for (const pool of this.miningPools) { if (!pool.id) { @@ -78,17 +81,20 @@ class PoolsParser { logger.debug(`Inserting new mining pool ${pool.name}`); await PoolsRepository.$insertNewMiningPool(pool, slug); reindexUnknown = true; + clearCache = true; } else { if (poolDB.name !== pool.name) { // Pool has been renamed const newSlug = pool.name.replace(/[^a-z0-9]/gi, '').toLowerCase(); logger.warn(`Renaming ${poolDB.name} mining pool to ${pool.name}. Slug has been updated. Maybe you want to make a redirection from 'https://mempool.space/mining/pool/${poolDB.slug}' to 'https://mempool.space/mining/pool/${newSlug}`); await PoolsRepository.$renameMiningPool(poolDB.id, newSlug, pool.name); + clearCache = true; } if (poolDB.link !== pool.link) { // Pool link has changed logger.debug(`Updating link for ${pool.name} mining pool`); await PoolsRepository.$updateMiningPoolLink(poolDB.id, pool.link); + clearCache = true; } if (JSON.stringify(pool.addresses) !== poolDB.addresses || JSON.stringify(pool.regexes) !== poolDB.regexes) { @@ -96,6 +102,7 @@ class PoolsParser { logger.notice(`Updating addresses and/or coinbase tags for ${pool.name} mining pool.`); await PoolsRepository.$updateMiningPoolTags(poolDB.id, pool.addresses, pool.regexes); reindexUnknown = true; + clearCache = true; await this.$reindexBlocksForPool(poolDB.id); } } @@ -111,6 +118,19 @@ class PoolsParser { } await this.$reindexBlocksForPool(unknownPool.id); } + + // refresh the in-memory block cache with the reindexed data + if (clearCache) { + for (const block of blocks.getBlocks()) { + const reindexedBlock = await blocks.$indexBlock(block.height); + if (reindexedBlock.id === block.id) { + block.extras.pool = reindexedBlock.extras.pool; + } + } + // update persistent cache with the reindexed data + diskCache.$saveCacheToDisk(); + redisCache.$updateBlocks(blocks.getBlocks()); + } } public matchBlockMiner(scriptsig: string, addresses: string[], pools: PoolTag[]): PoolTag | undefined { diff --git a/backend/src/api/websocket-handler.ts b/backend/src/api/websocket-handler.ts index 390896caa..09e56630a 100644 --- a/backend/src/api/websocket-handler.ts +++ b/backend/src/api/websocket-handler.ts @@ -1011,15 +1011,19 @@ class WebsocketHandler { const blockTransactions = structuredClone(transactions); this.printLogs(); - await statistics.runStatistics(); + if (config.STATISTICS.ENABLED && config.DATABASE.ENABLED) { + await statistics.runStatistics(); + } const _memPool = memPool.getMempool(); const candidateTxs = await memPool.getMempoolCandidates(); let candidates: GbtCandidates | undefined = (memPool.limitGBT && candidateTxs) ? { txs: candidateTxs, added: [], removed: [] } : undefined; let transactionIds: string[] = (memPool.limitGBT) ? Object.keys(candidates?.txs || {}) : Object.keys(_memPool); - const accelerations = Object.values(mempool.getAccelerations()); - await accelerationRepository.$indexAccelerationsForBlock(block, accelerations, structuredClone(transactions)); + if (config.DATABASE.ENABLED) { + const accelerations = Object.values(mempool.getAccelerations()); + await accelerationRepository.$indexAccelerationsForBlock(block, accelerations, structuredClone(transactions)); + } const rbfTransactions = Common.findMinedRbfTransactions(transactions, memPool.getSpendMap()); memPool.handleRbfTransactions(rbfTransactions); @@ -1095,7 +1099,9 @@ class WebsocketHandler { if (config.CORE_RPC.DEBUG_LOG_PATH && block.extras) { const firstSeen = getRecentFirstSeen(block.id); if (firstSeen) { - BlocksRepository.$saveFirstSeenTime(block.id, firstSeen); + if (config.DATABASE.ENABLED) { + BlocksRepository.$saveFirstSeenTime(block.id, firstSeen); + } block.extras.firstSeen = firstSeen; } } @@ -1392,7 +1398,9 @@ class WebsocketHandler { }); } - await statistics.runStatistics(); + if (config.STATISTICS.ENABLED && config.DATABASE.ENABLED) { + await statistics.runStatistics(); + } } public handleNewStratumJob(job: StratumJob): void { diff --git a/backend/src/index.ts b/backend/src/index.ts index 3cc73afb7..d8fc90f4a 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -156,7 +156,9 @@ class Server { await poolsUpdater.updatePoolsJson(); // Needs to be done before loading the disk cache because we sometimes wipe it await syncAssets.syncAssets$(); - await mempoolBlocks.updatePools$(); + if (config.DATABASE.ENABLED) { + await mempoolBlocks.updatePools$(); + } if (config.MEMPOOL.ENABLED) { if (config.MEMPOOL.CACHE_ENABLED) { await diskCache.$loadMempoolCache(); diff --git a/backend/src/tasks/pools-updater.ts b/backend/src/tasks/pools-updater.ts index 38e816d74..8a1a779a1 100644 --- a/backend/src/tasks/pools-updater.ts +++ b/backend/src/tasks/pools-updater.ts @@ -98,7 +98,8 @@ class PoolsUpdater { logger.info(`Mining pools-v2.json (${githubSha}) import completed`, this.tag); } catch (e) { - this.lastRun = now - 600; // Try again in 10 minutes + // fast-forward lastRun to 10 minutes before the next scheduled update + this.lastRun = now - Math.max(config.MEMPOOL.POOLS_UPDATE_DELAY - 600, 600); logger.err(`PoolsUpdater failed. Will try again in 10 minutes. Exception: ${JSON.stringify(e)}`, this.tag); } } diff --git a/docker/backend/Dockerfile b/docker/backend/Dockerfile index e56b07da3..942a8f9c8 100644 --- a/docker/backend/Dockerfile +++ b/docker/backend/Dockerfile @@ -8,7 +8,7 @@ WORKDIR /build RUN apt-get update && \ apt-get install -y curl ca-certificates && \ curl -fsSL https://deb.nodesource.com/setup_22.x | bash - && \ - apt-get install -y nodejs build-essential python3 pkg-config && \ + apt-get install -y nodejs=22.14.0-1nodesource1 build-essential python3 pkg-config && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* @@ -29,7 +29,7 @@ FROM rust:1.84-bookworm AS runtime RUN apt-get update && \ apt-get install -y curl ca-certificates && \ curl -fsSL https://deb.nodesource.com/setup_22.x | bash - && \ - apt-get install -y nodejs && \ + apt-get install -y nodejs=22.14.0-1nodesource1 && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* diff --git a/docker/backend/start.sh b/docker/backend/start.sh index 8adb631da..ae0bc616f 100755 --- a/docker/backend/start.sh +++ b/docker/backend/start.sh @@ -26,7 +26,7 @@ __MEMPOOL_EXTERNAL_MAX_RETRY__=${MEMPOOL_EXTERNAL_MAX_RETRY:=1} __MEMPOOL_EXTERNAL_RETRY_INTERVAL__=${MEMPOOL_EXTERNAL_RETRY_INTERVAL:=0} __MEMPOOL_USER_AGENT__=${MEMPOOL_USER_AGENT:=mempool} __MEMPOOL_STDOUT_LOG_MIN_PRIORITY__=${MEMPOOL_STDOUT_LOG_MIN_PRIORITY:=info} -__MEMPOOL_AUTOMATIC_POOLS_UPDATE__=${MEMPOOL_AUTOMATIC_POOLS_UPDATE:=false} +__MEMPOOL_AUTOMATIC_POOLS_UPDATE__=${MEMPOOL_AUTOMATIC_POOLS_UPDATE:=true} __MEMPOOL_POOLS_JSON_URL__=${MEMPOOL_POOLS_JSON_URL:=https://raw.githubusercontent.com/mempool/mining-pools/master/pools-v2.json} __MEMPOOL_POOLS_JSON_TREE_URL__=${MEMPOOL_POOLS_JSON_TREE_URL:=https://api.github.com/repos/mempool/mining-pools/git/trees/master} __MEMPOOL_POOLS_UPDATE_DELAY__=${MEMPOOL_POOLS_UPDATE_DELAY:=604800} diff --git a/docker/frontend/Dockerfile b/docker/frontend/Dockerfile index 8d97c9dc6..23c1da3d4 100644 --- a/docker/frontend/Dockerfile +++ b/docker/frontend/Dockerfile @@ -1,4 +1,4 @@ -FROM node:22-bookworm-slim AS builder +FROM node:22.14.0-bookworm-slim AS builder ARG commitHash ENV DOCKER_COMMIT_HASH=${commitHash} diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 932979e2b..26c4d8358 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1,12 +1,12 @@ { "name": "mempool-frontend", - "version": "3.1.0-dev", + "version": "3.3-dev", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mempool-frontend", - "version": "3.1.0-dev", + "version": "3.2.0-dev", "license": "GNU Affero General Public License v3.0", "dependencies": { "@angular-devkit/build-angular": "^17.3.1", diff --git a/frontend/package.json b/frontend/package.json index 8d4ee6e27..efca14cdd 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "mempool-frontend", - "version": "3.1.0-dev", + "version": "3.3-dev", "description": "Bitcoin mempool visualizer and blockchain explorer backend", "license": "GNU Affero General Public License v3.0", "homepage": "https://mempool.space", @@ -121,4 +121,4 @@ "scarfSettings": { "enabled": false } -} \ No newline at end of file +} diff --git a/frontend/src/app/components/pool/pool.component.scss b/frontend/src/app/components/pool/pool.component.scss index 26e6008b6..f09ac0d65 100644 --- a/frontend/src/app/components/pool/pool.component.scss +++ b/frontend/src/app/components/pool/pool.component.scss @@ -84,74 +84,79 @@ div.scrollable { text-align: right; } } +} - .progress { - background-color: var(--secondary); +.progress { + background-color: var(--secondary); +} + +.coinbase { + width: 20%; + @media (max-width: 875px) { + display: none; } +} - .coinbase { - width: 20%; - @media (max-width: 875px) { - display: none; - } +.health { + @media (max-width: 1150px) { + display: none; } +} - .height { - width: 10%; +.height { + width: 10%; +} + +.timestamp { + @media (max-width: 875px) { + padding-left: 50px; } - - .timestamp { - @media (max-width: 875px) { - padding-left: 50px; - } - @media (max-width: 685px) { - display: none; - } + @media (max-width: 625px) { + display: none; } +} - .mined { - width: 13%; - @media (max-width: 1100px) { - display: none; - } +.mined { + width: 13%; +} + +.txs { + @media (max-width: 938px) { + display: none; } - - .txs { - padding-right: 40px; - @media (max-width: 1100px) { - padding-right: 10px; - } - @media (max-width: 875px) { - padding-right: 20px; - } - @media (max-width: 567px) { - padding-right: 10px; - } + padding-right: 40px; + @media (max-width: 1100px) { + padding-right: 10px; } - - .size { - width: 12%; - @media (max-width: 1000px) { - width: 15%; - } - @media (max-width: 875px) { - width: 20%; - } - @media (max-width: 650px) { - width: 20%; - } - @media (max-width: 450px) { - display: none; - } + @media (max-width: 875px) { + padding-right: 20px; } + @media (max-width: 567px) { + padding-right: 10px; + } +} - .scriptmessage { - overflow: hidden; - display: inline-block; - text-overflow: ellipsis; - vertical-align: middle; - width: auto; - text-align: left; +.size { + min-width: 80px; + width: 12%; + @media (max-width: 1000px) { + width: 15%; + } +} + +.scriptmessage { + max-width: 340px; + overflow: hidden; + display: inline-block; + text-overflow: ellipsis; + vertical-align: middle; + width: auto; + text-align: left; +} + +.reward { + @media (max-width: 1035px) { + display: none; } } diff --git a/frontend/src/app/components/transactions-list/transactions-list.component.ts b/frontend/src/app/components/transactions-list/transactions-list.component.ts index 6f01a6e59..e52d1ba82 100644 --- a/frontend/src/app/components/transactions-list/transactions-list.component.ts +++ b/frontend/src/app/components/transactions-list/transactions-list.component.ts @@ -194,7 +194,7 @@ export class TransactionsListComponent implements OnInit, OnChanges { } this.transactionsLength = this.transactions.length; - + if (!this.txPreview) { this.cacheService.setTxCache(this.transactions); } @@ -316,10 +316,7 @@ export class TransactionsListComponent implements OnInit, OnChanges { // Check for address poisoning similarity matches this.similarityMatches.set(tx.txid, new Map()); - const comparableVouts = [ - ...tx.vout.slice(0, 20), - ...this.addresses.map(addr => ({ scriptpubkey_address: addr, scriptpubkey_type: detectAddressType(addr, this.stateService.network) })) - ].filter(v => ['p2pkh', 'p2sh', 'v0_p2wpkh', 'v0_p2wsh', 'v1_p2tr'].includes(v.scriptpubkey_type)); + const comparableVouts = tx.vout.slice(0, 20).filter(v => ['p2pkh', 'p2sh', 'v0_p2wpkh', 'v0_p2wsh', 'v1_p2tr'].includes(v.scriptpubkey_type)); const comparableVins = tx.vin.slice(0, 20).map(v => v.prevout).filter(v => ['p2pkh', 'p2sh', 'v0_p2wpkh', 'v0_p2wsh', 'v1_p2tr'].includes(v?.scriptpubkey_type)); for (const vout of comparableVouts) { const address = vout.scriptpubkey_address; diff --git a/frontend/src/app/services/state.service.ts b/frontend/src/app/services/state.service.ts index 7f8f81744..ed9728ec0 100644 --- a/frontend/src/app/services/state.service.ts +++ b/frontend/src/app/services/state.service.ts @@ -327,6 +327,8 @@ export class StateService { this.networkChanged$.subscribe((network) => { this.transactions$ = new BehaviorSubject(null); + this.stratumJobs$ = new BehaviorSubject>({}); + this.stratumJobUpdate$.next({ state: {} }); this.blocksSubject$.next([]); }); diff --git a/nginx-mempool.conf b/nginx-mempool.conf index 2532a7082..4b12ed714 100644 --- a/nginx-mempool.conf +++ b/nginx-mempool.conf @@ -58,6 +58,9 @@ proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; } + location /api/v1/services { + proxy_pass https://mempool.space; + } location /api/v1 { proxy_pass http://127.0.0.1:8999/api/v1; } diff --git a/production/install b/production/install index aadb8005e..d243b45f4 100755 --- a/production/install +++ b/production/install @@ -43,6 +43,9 @@ CLN_INSTALL=ON # install UNFURL UNFURL_INSTALL=ON +# install CKPOOL +CKPOOL_MAINNET_INSTALL=ON + # configure 4 network instances BITCOIN_MAINNET_ENABLE=ON BITCOIN_MAINNET_MINFEE_ENABLE=ON @@ -56,6 +59,11 @@ BISQ_MAINNET_ENABLE=ON ELEMENTS_LIQUID_ENABLE=ON ELEMENTS_LIQUIDTESTNET_ENABLE=ON +# configure 3 CKPool instances +BITCOIN_MAINNET_CKPOOL=ON +BITCOIN_TESTNET_CKPOOL=ON +BITCOIN_TESTNET4_CKPOOL=ON + # enable lightmode and disable compaction to fit on 1TB SSD drive BITCOIN_ELECTRS_INSTALL=ON BITCOIN_ELECTRS_LIGHT_MODE=ON @@ -197,6 +205,18 @@ MEMPOOL_SIGNET_HTTP_PORT=8995 MEMPOOL_LIQUIDTESTNET_HTTP_HOST=127.0.0.1 MEMPOOL_LIQUIDTESTNET_HTTP_PORT=8994 +# set CKPool bitcoin mainnet port +CKPOOL_MAINNET_STRATUM_HOST=127.0.0.1 +CKPOOL_MAINNET_STRATUM_PORT=3333 + +# set CKPool bitcoin mainnet port +CKPOOL_TESTNET_STRATUM_HOST=127.0.0.1 +CKPOOL_TESTNET_STRATUM_PORT=3334 + +# set CKPool bitcoin mainnet port +CKPOOL_TESTNET4_STRATUM_HOST=127.0.0.1 +CKPOOL_TESTNET4_STRATUM_PORT=3335 + ##### OS options, should be automatically detected case $OS in @@ -283,6 +303,11 @@ BITCOIN_GROUP=bitcoin # bitcoin core data folder, needs about 300GB BITCOIN_HOME=/bitcoin +# ckpool user/group +CKPOOL_HOME=/ckpool +CKPOOL_USER=ckpool +CKPOOL_GROUP=ckpool + # bitcoin testnet data BITCOIN_TESTNET_DATA=${BITCOIN_HOME}/testnet3 # bitcoin testnet4 data @@ -367,6 +392,12 @@ BISQ_REPO_BRANCH=master BISQ_LATEST_RELEASE=master echo -n '.' +CKPOOL_URL=https://github.com/mempool/ckpool +CKPOOL_REPO_NAME=ckpool +CKPOOL_REPO_BRANCH=master +CKPOOL_LATEST_RELEASE=$(curl -s https://api.github.com/repos/mempool/ckpool/releases/latest|grep tag_name|head -1|cut -d '"' -f4) +echo -n '.' + UNFURL_REPO_URL=https://github.com/mempool/mempool UNFURL_REPO_NAME=unfurl UNFURL_REPO_BRANCH=master @@ -418,9 +449,10 @@ DEBIAN_UNFURL_PKG+=(libxdamage-dev libxrandr-dev libgbm-dev libpango1.0-dev liba FREEBSD_PKG=() FREEBSD_PKG+=(zsh sudo git git-lfs screen curl wget calc neovim) FREEBSD_PKG+=(openssh-portable py311-pip rust llvm17 jq base64 libzmq4) -FREEBSD_PKG+=(boost-libs autoconf automake gmake gcc libevent libtool pkgconf) +FREEBSD_PKG+=(boost-libs autoconf automake gmake gcc13 libevent libtool pkgconf) FREEBSD_PKG+=(nginx rsync py311-certbot-nginx mariadb1011-server) FREEBSD_PKG+=(geoipupdate redis) +FREEBSD_PKG+=(libepoll-shim) FREEBSD_UNFURL_PKG=() FREEBSD_UNFURL_PKG+=(nvidia-driver-470 chromium xinit xterm twm ja-sourcehansans-otf) @@ -1113,10 +1145,10 @@ echo "[*] Installing Mempool crontab" osSudo "${ROOT_USER}" crontab -u "${MEMPOOL_USER}" "${MEMPOOL_HOME}/${MEMPOOL_REPO_NAME}/production/mempool.crontab" echo "[*] Installing nvm.sh from GitHub" -osSudo "${MEMPOOL_USER}" sh -c 'curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | zsh' +osSudo "${MEMPOOL_USER}" sh -c 'curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.2/install.sh | bash' echo "[*] Building NodeJS via nvm.sh" -osSudo "${MEMPOOL_USER}" zsh -c 'source ~/.zshrc ; nvm install v22.14.0 --shared-zlib' +osSudo "${MEMPOOL_USER}" zsh -c 'source ~/.zshrc ; CC=gcc CXX=g++ nvm install v22.14.0 --shared-zlib' osSudo "${MEMPOOL_USER}" zsh -c 'source ~/.zshrc ; nvm alias default 22.14.0' #################### @@ -1223,6 +1255,76 @@ if [ "${BITCOIN_INSTALL}" = ON ];then osSudo "${ROOT_USER}" sed -i.orig "s/__BITCOIN_RPC_PASS__/${BITCOIN_RPC_PASS}/" "${MINFEE_HOME}/bitcoin.conf" fi +####################### +# CKPool Installation # +####################### + +#CKPool cronjob installer +install_ckpool_cron() { + local network=$1 + local network_label=$2 + local network_cmd=$3 + local port=$4 + + echo "[*] Installing CKPool ${network_label} Cron for 'ckpool' user" + case $OS in + FreeBSD) + osSudo "${CKPOOL_USER}" sh -c "cd ${CKPOOL_HOME} && (crontab -l > ${TEMP_CRON_FILE} 2>/dev/null || echo \"\" > ${TEMP_CRON_FILE})" + osSudo "${CKPOOL_USER}" sh -c "cd ${CKPOOL_HOME} && echo '@reboot screen -dmS ckpool-${network} sh -c \"while true; do ${CKPOOL_HOME}/${CKPOOL_REPO_NAME}/start ${network_cmd} ${port}; sleep 1; done\"' >> ${TEMP_CRON_FILE}" + osSudo "${CKPOOL_USER}" sh -c "cd ${CKPOOL_HOME} && crontab ${TEMP_CRON_FILE}" + osSudo "${CKPOOL_USER}" sh -c "cd ${CKPOOL_HOME} && rm -f ${TEMP_CRON_FILE}" + ;; + Debian) + ;; + esac +} + +#CKPool binary Installer +if [ "${CKPOOL_INSTALL}" = ON ]; then + echo "[*] Creating 'ckpool' user" + osGroupCreate "${CKPOOL_GROUP}" + osUserCreate "${CKPOOL_USER}" "${CKPOOL_HOME}" "${CKPOOL_GROUP}" + osSudo "${ROOT_USER}" chsh -s `which zsh` "${CKPOOL_USER}" + + echo "[*] Creating 'ckpool' data folder" + osSudo "${ROOT_USER}" mkdir -p "${CKPOOL_HOME}" + osSudo "${ROOT_USER}" chown -R "${CKPOOL_USER}:${CKPOOL_GROUP}" "${CKPOOL_HOME}" + osSudo "${CKPOOL_USER}" touch "${CKPOOL_HOME}/.zshrc" + + echo "[*] Creating '.ckpool' directory in ckpool user's home to store config files" + osSudo "${ROOT_USER}" mkdir -p "${CKPOOL_HOME}/.ckpool" + osSudo "${ROOT_USER}" chown "${CKPOOL_USER}:${CKPOOL_GROUP}" "${CKPOOL_HOME}/.ckpool" + + echo "[*] Cloning Mempool CKPool repo from ${CKPOOL_REPO_URL}" + osSudo "${CKPOOL_USER}" git config --global advice.detachedHead false + osSudo "${CKPOOL_USER}" git clone --branch "${CKPOOL_REPO_BRANCH}" "${CKPOOL_REPO_URL}" "${CKPOOL_HOME}/${CKPOOL_REPO_NAME}" + + echo "[*] Checking out CKPOOL ${CKPOOL_LATEST_RELEASE}" + osSudo "${CKPOOL_USER}" sh -c "cd ${CKPOOL_HOME}/${CKPOOL_REPO_NAME} && git checkout ${CKPOOL_LATEST_RELEASE}" + + echo "[*] Building CKPool from source repo" + osSudo "${CKPOOL_USER}" sh -c "cd ${CKPOOL_REPO_NAME} && ./autogen.sh --quiet" + osSudo "${CKPOOL_USER}" sh -c "cd ${CKPOOL_REPO_NAME} && ./configure CFLAGS='-O3 -march=native -flto -Wall -I/usr/local/include/libepoll-shim' LDFLAGS='-L/usr/local/lib -lepoll-shim -lpthread'" + osSudo "${CKPOOL_USER}" sh -c "cd ${CKPOOL_REPO_NAME} && gmake -j${NPROC}" + + echo "[*] Copy CKPool binarary into OS" + osSudo "${ROOT_USER}" sh -c "cd ${CKPOOL_HOME}/${CKPOOL_REPO_NAME} && cp src/ckpool /usr/local/bin" + + TEMP_CRON_FILE="tmp_cron" + + if [ "${BITCOIN_MAINNET_CKPOOL}" = ON ]; then + install_ckpool_cron "mainnet" "Mainnet" "bitcoin" 2333 + fi + + if [ "${BITCOIN_TESTNET_CKPOOL}" = ON ]; then + install_ckpool_cron "testnet" "Testnet" "testnet" 2334 + fi + + if [ "${BITCOIN_TESTNET4_CKPOOL}" = ON ]; then + install_ckpool_cron "testnet4" "Testnet4" "testnet4" 2335 + fi +fi + ######################### # Elements installation # ######################### @@ -1314,7 +1416,7 @@ if [ "${BITCOIN_ELECTRS_INSTALL}" = ON ];then case $OS in FreeBSD) echo "[*] Patching Bitcoin Electrs code for FreeBSD" - osSudo "${BITCOIN_USER}" sh -c "cd \"${BITCOIN_HOME}/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sysconf-0.3.4\" && patch -p1 < \"${MEMPOOL_HOME}/${MEMPOOL_REPO_NAME}/production/freebsd/sysconf.patch\"" + osSudo "${BITCOIN_USER}" sh -c "cd \"${BITCOIN_HOME}/.cargo/registry/src/index.crates.io-6f17d22bba15001f/sysconf-0.3.4\" && patch -p1 < \"${MEMPOOL_HOME}/${MEMPOOL_REPO_NAME}/production/freebsd/sysconf.patch\"" #osSudo "${BITCOIN_USER}" sh -c "cd \"${BITCOIN_ELECTRS_HOME}/src/new_index/\" && sed -i.bak -e s/Snappy/None/ db.rs && rm db.rs.bak" #osSudo "${BITCOIN_USER}" sh -c "cd \"${BITCOIN_ELECTRS_HOME}/src/bin/\" && sed -i.bak -e 's/from_secs(5)/from_secs(1)/' electrs.rs && rm electrs.rs.bak" ;; diff --git a/unfurler/package-lock.json b/unfurler/package-lock.json index 799148486..8f8373a36 100644 --- a/unfurler/package-lock.json +++ b/unfurler/package-lock.json @@ -1,12 +1,12 @@ { "name": "mempool-unfurl", - "version": "3.1.0-dev", + "version": "3.2.0-dev", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mempool-unfurl", - "version": "3.0.0", + "version": "3.2.0-dev", "dependencies": { "@types/node": "^16.11.41", "ejs": "^3.1.10", diff --git a/unfurler/package.json b/unfurler/package.json index bf3dad55b..968334f22 100644 --- a/unfurler/package.json +++ b/unfurler/package.json @@ -1,6 +1,6 @@ { "name": "mempool-unfurl", - "version": "3.1.0-dev", + "version": "3.2.0-dev", "description": "Renderer for mempool open graph link preview images", "repository": { "type": "git", @@ -32,4 +32,4 @@ "eslint-config-prettier": "^8.5.0", "prettier": "^2.7.1" } -} +} \ No newline at end of file