From a67a074eaf6a761c8874e92e581228293d267090 Mon Sep 17 00:00:00 2001 From: Aroooba Date: Tue, 7 Feb 2023 05:12:44 +0900 Subject: [PATCH 1/8] Add contributor license agreement --- contributors/Arooba-git.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 contributors/Arooba-git.txt diff --git a/contributors/Arooba-git.txt b/contributors/Arooba-git.txt new file mode 100644 index 000000000..833d78ff4 --- /dev/null +++ b/contributors/Arooba-git.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 January 25, 2022. + +Signed: Arooba-git \ No newline at end of file From d66921938c672493996f0da1232a74686121a71e Mon Sep 17 00:00:00 2001 From: Aroooba Date: Tue, 7 Feb 2023 05:13:19 +0900 Subject: [PATCH 2/8] Unsubscribe subscription in component destructor to avoid memory leak --- frontend/src/app/docs/api-docs/api-docs.component.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/frontend/src/app/docs/api-docs/api-docs.component.ts b/frontend/src/app/docs/api-docs/api-docs.component.ts index 7b78d187b..0bffd5b2a 100644 --- a/frontend/src/app/docs/api-docs/api-docs.component.ts +++ b/frontend/src/app/docs/api-docs/api-docs.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit, Input, QueryList, AfterViewInit, ViewChildren } from '@angular/core'; import { Env, StateService } from '../../services/state.service'; -import { Observable, merge, of } from 'rxjs'; -import { tap } from 'rxjs/operators'; +import { Observable, merge, of, Subject } from 'rxjs'; +import { tap, takeUntil } from 'rxjs/operators'; import { ActivatedRoute } from "@angular/router"; import { faqData, restApiDocsData, wsApiDocsData } from './api-docs-data'; import { FaqTemplateDirective } from '../faq-template/faq-template.component'; @@ -12,6 +12,7 @@ import { FaqTemplateDirective } from '../faq-template/faq-template.component'; styleUrls: ['./api-docs.component.scss'] }) export class ApiDocsComponent implements OnInit, AfterViewInit { + private destroy$: Subject = new Subject(); plainHostname = document.location.hostname; electrsPort = 0; hostname = document.location.hostname; @@ -82,7 +83,7 @@ export class ApiDocsComponent implements OnInit, AfterViewInit { this.restDocs = restApiDocsData; this.wsDocs = wsApiDocsData; - this.network$.subscribe((network) => { + this.network$.pipe(takeUntil(this.destroy$)).subscribe((network) => { this.active = (network === 'liquid' || network === 'liquidtestnet') ? 2 : 0; switch( network ) { case "": @@ -102,6 +103,8 @@ export class ApiDocsComponent implements OnInit, AfterViewInit { } ngOnDestroy(): void { + this.destroy$.next(true); + this.destroy$.complete(); window.removeEventListener('scroll', this.onDocScroll); } From c85d8cd29d6ff2e5b2da4be753eacbb363f40ca9 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Sun, 12 Feb 2023 21:42:33 -0600 Subject: [PATCH 3/8] Fix firefox blockchain scroll reset bug --- frontend/src/app/components/start/start.component.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontend/src/app/components/start/start.component.ts b/frontend/src/app/components/start/start.component.ts index d29372d97..ff66e7b97 100644 --- a/frontend/src/app/components/start/start.component.ts +++ b/frontend/src/app/components/start/start.component.ts @@ -298,6 +298,10 @@ export class StartComponent implements OnInit, OnDestroy { } ngOnDestroy() { + if (this.blockchainContainer?.nativeElement) { + // clean up scroll position to prevent caching wrong scroll in Firefox + this.blockchainContainer.nativeElement.scrollLeft = 0; + } this.timeLtrSubscription.unsubscribe(); this.chainTipSubscription.unsubscribe(); this.markBlockSubscription.unsubscribe(); From 198f85af2d8d1b10635079ef0a45aab9537475d0 Mon Sep 17 00:00:00 2001 From: hunicus <93150691+hunicus@users.noreply.github.com> Date: Mon, 13 Feb 2023 04:08:12 -0500 Subject: [PATCH 4/8] Add block audit faq --- .../src/app/docs/api-docs/api-docs-data.ts | 7 ++++ .../app/docs/api-docs/api-docs.component.html | 34 ++++++++++++--- .../app/docs/api-docs/api-docs.component.scss | 42 +++++++++++++++++++ 3 files changed, 78 insertions(+), 5 deletions(-) diff --git a/frontend/src/app/docs/api-docs/api-docs-data.ts b/frontend/src/app/docs/api-docs/api-docs-data.ts index f4b4602ad..069dabacf 100644 --- a/frontend/src/app/docs/api-docs/api-docs-data.ts +++ b/frontend/src/app/docs/api-docs/api-docs-data.ts @@ -8667,6 +8667,13 @@ export const faqData = [ fragment: "why-dont-fee-ranges-match", title: "Why doesn't the fee range shown for a block match the feerates of transactions within the block?", }, + { + type: "endpoint", + category: "advanced", + showConditions: bitcoinNetworks, + fragment: "how-do-block-audits-work", + title: "How do block audits work?", + }, { type: "endpoint", category: "advanced", diff --git a/frontend/src/app/docs/api-docs/api-docs.component.html b/frontend/src/app/docs/api-docs/api-docs.component.html index 48e9b48eb..445b2c102 100644 --- a/frontend/src/app/docs/api-docs/api-docs.component.html +++ b/frontend/src/app/docs/api-docs/api-docs.component.html @@ -218,17 +218,41 @@

For unconfirmed CPFP transactions, Mempool will show the effective feerate (along with descendent & ancestor transaction information) on the transaction page. For confirmed transactions, CPFP relationships are not stored, so this additional information is not shown.

+ +

A block audit visually compares Mempool's expected block to the actual block for a particular block height.

+

How is the expected block determined? Mempool monitors its view of the mempool and runs a re-implementation of Bitcoin Core's transaction selection algorithm to determine the transactions it expects to see in upcoming blocks (source code here). Since there is a continual flow of new transactions, this algorithm runs every 2 seconds, and as a result, you will see the transactions projected to be in upcoming blocks change in near real-time.

+

At the moment a new block is mined, Mempool saves a snapshot of its projected block template for the next block. We call this snapshot the expected block for the block height in question, and it serves as the basis for the block audit.

+

When details for an expected block and actual block are available, we can compare them. The purpose of block audits is to deduce when miners intentionally include or exclude transactions from blocks they mine. Since this information cannot be precisely known, Mempool uses a handful of heuristics to accomplish this.

+

Block audits highlight transactions in different colors to convey these heuristics:

+
    +
  • Added

    A transaction is highlighted blue if it is not present in the expected block, present in the actual block, and also either:

    +
      +
    • far out of the expected feerate range, meaning the miner may have intentionally prioritized the transaction
    • +
    • not in the mempool at all, meaning the miner may have accepted the transaction out-of-band
    • +
    +

    Added transactions do not negatively affect block health.

  • +
  • Recently broadcasted

    A transaction is highlighted dark pink if it is present in the expected block, not present in the actual block, and was first seen by Mempool's Bitcoin node within 3 minutes of the block being mined.

    Due to network latency and other factors, it can take time for a miner's Bitcoin nodes to receive a transaction, so we do not assume a miner has intentionally excluded such a transaction from a block.

    Recently-broadcasted transactions do not negatively affect block health.

  • +
  • Marginal fee +

    A transaction is darkened if it is in the low end of the expected feerate range and missing in either the expected block or the actual block.

    Such a transaction may have been displaced by an added transaction, or it may have been displaced by another transaction from the mempool that was also at the low end of the expected feerate range for the block. In either case, the deviation is not considered notable.

    +

    Marginal fee transactions do not negatively affect block health.

  • +
  • Removed

    A transaction is highlighted bright pink if it is present in the expected block, not present in the actual block, and qualifies as neither recently-broadcasted nor marginal-fee. In other words, it has been in the mempool long enough to be widely propagated and has a feerate that is well within the range expected for the block. There is a chance such a transaction may have been intentionally excluded from the block.

    Removed transactions do negatively affect block health.

  • +
+

See how results of the block audit are used to devise the block health score below.

+
+ -

Block health indicates the extent of potential censorship in a block. This is determined by counting how many expected transactions a block is missing—a block that is not missing any expected transactions will have 100% health, while a block missing 1 or more expected transactions will have sub-100% health.

-

How does this work? Let sexpected be the set of all transactions Mempool expected to be in a block and let sactual be the set of all transactions actually in a block. Let n be the number of all transactions in both sexpected and sactual.

-

Then let r be the number of removed transactions—all transactions expected to be in sactual but not actually in it (excluding those that have been recently broadcast; see below).

+

Block health is a measure of how many transactions appear to be intentionally excluded from a block—a block without any transactions that appear intentionally excluded will have 100% health, while a block with 1 or more transactions that appear intentionally excluded will have sub-100% health.

+

As a result, block health is not intended to be a measure of how closely an expected block resembles an actual block.

+

How is it calculated? Let sexpected be the set of all transactions in Mempool's expected block and let sactual be the set of all transactions in the actual block. Then let n be the number of all transactions in both sexpected and sactual.

+

Furthermore, let r be the number of transactions Mempool deduces were intentionally excluded from sactual.

Block health is calculated as n / ( n + r ).

-

Transactions appearing in both sexpected and sactual are used (instead of a block's full transaction count) in order to minimize chances that block health is impacted by missing transactions that don't imply censorship:

+

The number of transactions appearing in both sexpected and sactual is used (instead of a block's full transaction count) in order to minimize chances that block health is inadvertently impacted by transactions that were most likely not intentionally excluded:

  • recently-broadcast transactions, since the miner may simply not have received them
  • certain low-feerate transactions, since the miner may have opted to replace them with more profitable out-of-band transactions
-

Mempool uses a re-implementation of Bitcoin Core's transaction selection algorithm to determine the transactions it expects to see in the next block.

+

As a result, block health is not intended to be a measure of how closely an expected block resembles an actual block. The actual block can be vastly different from the expected block, but if no transactions appear to be intentionally excluded, it will have a high health rating (extreme example).

+

See more context in our FAQ on block audits.

diff --git a/frontend/src/app/docs/api-docs/api-docs.component.scss b/frontend/src/app/docs/api-docs/api-docs.component.scss index db6d51cf2..92e78bc55 100644 --- a/frontend/src/app/docs/api-docs/api-docs.component.scss +++ b/frontend/src/app/docs/api-docs/api-docs.component.scss @@ -42,6 +42,48 @@ li.nav-item { } } +ul.no-bull { + list-style: none; +} + +ul.no-bull.block-audit li code { + text-transform: uppercase; +} + +ul.no-bull.block-audit li span { + margin-right: 10px; +} + +ul.no-bull.block-audit li span.block-audit-highlight-color.added { + color: #0099ff; +} + +ul.no-bull.block-audit li span.block-audit-highlight-color.removed { + color: #f344df; +} + +ul.no-bull.block-audit li span.block-audit-highlight-color.recent { + color: #8a3480; +} + +ul.no-bull.block-audit li span.block-audit-highlight-color.marginal { + color: #414127; +} + +ul.no-bull.block-audit li p { + margin-left: 25px; + margin-top: 5px; +} + +ul.no-bull.block-audit li ul { + margin-left: 15px; + margin-bottom: 15px; +} + +ul.no-bull.block-audit code{ + background-color: inherit; +} + .doc-welcome-note { margin-bottom: 0; } From 1c7698eb36a7bd92413b22c0352fa9969c237af1 Mon Sep 17 00:00:00 2001 From: hunicus <93150691+hunicus@users.noreply.github.com> Date: Mon, 13 Feb 2023 18:45:29 -0500 Subject: [PATCH 5/8] Remove repeated line --- frontend/src/app/docs/api-docs/api-docs.component.html | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/src/app/docs/api-docs/api-docs.component.html b/frontend/src/app/docs/api-docs/api-docs.component.html index 445b2c102..161e17ce8 100644 --- a/frontend/src/app/docs/api-docs/api-docs.component.html +++ b/frontend/src/app/docs/api-docs/api-docs.component.html @@ -242,7 +242,6 @@

Block health is a measure of how many transactions appear to be intentionally excluded from a block—a block without any transactions that appear intentionally excluded will have 100% health, while a block with 1 or more transactions that appear intentionally excluded will have sub-100% health.

-

As a result, block health is not intended to be a measure of how closely an expected block resembles an actual block.

How is it calculated? Let sexpected be the set of all transactions in Mempool's expected block and let sactual be the set of all transactions in the actual block. Then let n be the number of all transactions in both sexpected and sactual.

Furthermore, let r be the number of transactions Mempool deduces were intentionally excluded from sactual.

Block health is calculated as n / ( n + r ).

From 38ce8b8dc1835ea8642ff83d434c88d44c0d3ed9 Mon Sep 17 00:00:00 2001 From: hunicus <93150691+hunicus@users.noreply.github.com> Date: Mon, 13 Feb 2023 19:39:46 -0500 Subject: [PATCH 6/8] Add note about audit/health availability Not available on non-official instances. --- frontend/src/app/docs/api-docs/api-docs.component.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/src/app/docs/api-docs/api-docs.component.html b/frontend/src/app/docs/api-docs/api-docs.component.html index 161e17ce8..7a7b9b416 100644 --- a/frontend/src/app/docs/api-docs/api-docs.component.html +++ b/frontend/src/app/docs/api-docs/api-docs.component.html @@ -238,6 +238,7 @@
  • Removed

    A transaction is highlighted bright pink if it is present in the expected block, not present in the actual block, and qualifies as neither recently-broadcasted nor marginal-fee. In other words, it has been in the mempool long enough to be widely propagated and has a feerate that is well within the range expected for the block. There is a chance such a transaction may have been intentionally excluded from the block.

    Removed transactions do negatively affect block health.

  • See how results of the block audit are used to devise the block health score below.

    +

    Because of this feature's resource usage and availability requirements, it is only supported on official mempool.space instances.

    @@ -252,6 +253,7 @@

    As a result, block health is not intended to be a measure of how closely an expected block resembles an actual block. The actual block can be vastly different from the expected block, but if no transactions appear to be intentionally excluded, it will have a high health rating (extreme example).

    See more context in our FAQ on block audits.

    +

    Because of this feature's resource usage and availability requirements, it is only supported on official mempool.space instances.

    From d8ebc5a92c68724d56c1b4fb49431af9803f6f3e Mon Sep 17 00:00:00 2001 From: hunicus <93150691+hunicus@users.noreply.github.com> Date: Mon, 13 Feb 2023 20:12:31 -0500 Subject: [PATCH 7/8] Only show audit and health faqs on official --- frontend/src/app/docs/api-docs/api-docs-data.ts | 2 ++ .../app/docs/api-docs/api-docs-nav.component.html | 2 +- .../src/app/docs/api-docs/api-docs-nav.component.ts | 9 ++++++++- .../src/app/docs/api-docs/api-docs.component.html | 12 +++++++----- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/frontend/src/app/docs/api-docs/api-docs-data.ts b/frontend/src/app/docs/api-docs/api-docs-data.ts index 069dabacf..5cc5ca3aa 100644 --- a/frontend/src/app/docs/api-docs/api-docs-data.ts +++ b/frontend/src/app/docs/api-docs/api-docs-data.ts @@ -8671,6 +8671,7 @@ export const faqData = [ type: "endpoint", category: "advanced", showConditions: bitcoinNetworks, + options: { officialOnly: true }, fragment: "how-do-block-audits-work", title: "How do block audits work?", }, @@ -8678,6 +8679,7 @@ export const faqData = [ type: "endpoint", category: "advanced", showConditions: bitcoinNetworks, + options: { officialOnly: true }, fragment: "what-is-block-health", title: "What is block health?", }, diff --git a/frontend/src/app/docs/api-docs/api-docs-nav.component.html b/frontend/src/app/docs/api-docs/api-docs-nav.component.html index c8460ada4..cbfe8a170 100644 --- a/frontend/src/app/docs/api-docs/api-docs-nav.component.html +++ b/frontend/src/app/docs/api-docs/api-docs-nav.component.html @@ -1,4 +1,4 @@

    {{ item.title }}

    - {{ item.title }} + {{ item.title }}
    diff --git a/frontend/src/app/docs/api-docs/api-docs-nav.component.ts b/frontend/src/app/docs/api-docs/api-docs-nav.component.ts index df73030c9..ad9d0b9a5 100644 --- a/frontend/src/app/docs/api-docs/api-docs-nav.component.ts +++ b/frontend/src/app/docs/api-docs/api-docs-nav.component.ts @@ -1,4 +1,5 @@ import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; +import { Env, StateService } from '../../services/state.service'; import { restApiDocsData } from './api-docs-data'; import { faqData } from './api-docs-data'; @@ -12,11 +13,17 @@ export class ApiDocsNavComponent implements OnInit { @Input() network: any; @Input() whichTab: string; @Output() navLinkClickEvent: EventEmitter = new EventEmitter(); + env: Env; tabData: any[]; + officialMempoolInstance: boolean; - constructor() { } + constructor( + private stateService: StateService + ) { } ngOnInit(): void { + this.env = this.stateService.env; + this.officialMempoolInstance = this.env.OFFICIAL_MEMPOOL_SPACE; if (this.whichTab === 'rest') { this.tabData = restApiDocsData; } else if (this.whichTab === 'faq') { diff --git a/frontend/src/app/docs/api-docs/api-docs.component.html b/frontend/src/app/docs/api-docs/api-docs.component.html index 7a7b9b416..be3fd2f42 100644 --- a/frontend/src/app/docs/api-docs/api-docs.component.html +++ b/frontend/src/app/docs/api-docs/api-docs.component.html @@ -15,11 +15,13 @@
    -

    {{ item.title }}

    -
    -
    {{ item.title }}{{ item.category }}
    -
    - +
    +

    {{ item.title }}

    +
    From 7aca0450801225f4b873ddec64d8cd209357f156 Mon Sep 17 00:00:00 2001 From: hunicus <93150691+hunicus@users.noreply.github.com> Date: Tue, 14 Feb 2023 03:01:37 -0500 Subject: [PATCH 8/8] Fix error in logic for official_mempool_space --- frontend/src/app/docs/api-docs/api-docs-nav.component.html | 2 +- frontend/src/app/docs/api-docs/api-docs.component.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/docs/api-docs/api-docs-nav.component.html b/frontend/src/app/docs/api-docs/api-docs-nav.component.html index cbfe8a170..3abdc91be 100644 --- a/frontend/src/app/docs/api-docs/api-docs-nav.component.html +++ b/frontend/src/app/docs/api-docs/api-docs-nav.component.html @@ -1,4 +1,4 @@

    {{ item.title }}

    - {{ item.title }} + {{ item.title }}
    diff --git a/frontend/src/app/docs/api-docs/api-docs.component.html b/frontend/src/app/docs/api-docs/api-docs.component.html index be3fd2f42..c984c2b77 100644 --- a/frontend/src/app/docs/api-docs/api-docs.component.html +++ b/frontend/src/app/docs/api-docs/api-docs.component.html @@ -15,7 +15,7 @@