Pool Hashrate
0.0 H/s
0 miners connected
Network Share
— %
of total network hashrate
Blocks Found
0
by this pool
Last Block
—
found by the pool
Current Block #—
—
since last block
⟳
Pool is resyncing the blockchain — 0%
The pool restarted and is re-verifying the chain (block 0
of …). Mining resumes automatically when it finishes —
usually within a few minutes. Your balance and shares are safe.
Mine
Negotiated mode always on — this pool
never builds your blocks. Your browser verifies the blockchain itself, picks the parent block
and transactions, and builds its own blocks; the pool only checks them and aggregates payouts.
That way the pool cannot use your hashpower for 51%-style attacks, no matter how big
it gets. Rewards work exactly as before. When you start mining, your browser first downloads
& verifies the chain (~1 minute; repeats after a page reload).
Learn more ↓
Hashrate
0.0 H/s
0 workers
Your Share
0.0 %
of recent pool work
Est. Reward
0.00 BRC
per block, at your current share
Pending
0.00 BRC
auto-paid at 1 BRC
Last Payout
—
no payouts yet
Total Paid
0.00 BRC
lifetime
⏳
Your share is still building up — about a few minutes until it's fully ramped. It climbs as your shares fill the pool's rolling payout window; you're earning from your very first share.
Blocks Found
| Height |
Hash |
Found By |
Reward |
Effort |
Time |
| No blocks found yet. |
How It Works
BrowserCoin uses Sandglass v3 proof-of-work — a memory-latency-bound
algorithm designed to be ASIC-resistant and to keep browsers competitive with GPUs. Mining
happens entirely inside your browser using Web Workers, so there is nothing to install. Each
worker chases dependent reads through a small 512 KiB buffer in a loop, searching for
valid proofs.
Shares
The pool gives every miner a personal share target that is far easier than the real
network difficulty, auto-tuned (vardiff) so you find a share roughly every
20 seconds — whether you mine on a phone or a 32-core rig.
Each share is credited by its difficulty, so your round score stays exactly proportional to
your real work.
Rounds & Blocks
A round is the work on one block height. Your shares aren't discarded when a
round ends — they stay in a rolling PPLNS window that spans rounds, so every
block the pool finds pays out the most recent shares regardless of which round they
landed in.
Reward Distribution & Fee
Rewards use PPLNS (pay-per-last-N-shares): each block is split by your
weight in a rolling window of the most recent shares, so your earnings track your real
work instead of swinging with single-round luck — and work done during rounds the pool
loses to other miners still gets paid. The pool keeps a fee of
2% of each block reward to cover server and
operating costs — the rest goes entirely to the miners.
Payouts
Your earned BRC accumulates as a pending balance. Once it reaches the minimum threshold
(1 BRC), the pool automatically sends a transaction to your payout address. You can track your
pending and paid balances in the stats section above.
Tip: Use the power slider to balance mining speed against system load. Each thread
uses one CPU core and only a few MB of RAM (Sandglass works in a 512 KiB buffer). Leave at
least one core free so your browser stays responsive. Want the full technical details? Read the
deep-dive — switching pages won't interrupt your mining.
Pool Address
loading…
How This Pool Works
A technical walkthrough of everything that happens between the moment you press
Start Mining and the moment BRC lands in your wallet — with the actual
code that runs on both sides.
1 · Architecture
Three components talk to each other. Your browser verifies the chain,
builds block templates and does the hashing, the pool server validates
templates & shares and aggregates payouts, and the BrowserCoin network
helpers connect both to the rest of the network.
Your Browser
verifies chain · builds blocks
Web Workers hash Sandglass
⇄
Pool Server
full chain node · validates templates
& shares · pays out
⇄
BRC Network
API helpers + P2P miners
accept blocks & transactions
The pool keeps its own validated copy of the chain. It checks the network tip every
~3 seconds (with a full re-sync every 30) so stale work is kept to a minimum.
When it finds a block, it pushes it to the helpers; when other miners find one first,
the pool picks it up within seconds and starts a fresh round.
2 · The Proof-of-Work: Sandglass v3
Since block 33,550 BrowserCoin uses Sandglass v3, a
memory-latency-bound hash designed to keep browsers competitive with GPUs. Each
hash fills a 512 KiB buffer and then performs about
2 million serial memory-dependent steps through it (4 interleaved
chains): every read address depends on the previous read's value, so the work can't be
parallelized inside one hash and raw compute barely helps — the bottleneck is memory
latency, which is roughly the same on a laptop as on a datacenter GPU. One hash
takes ~5–15 ms in a browser. (Blocks before 33,550 used Argon2id; miners and
validators switch automatically at the fork height.)
What gets hashed is the 148-byte block header. The miner's job is to find a
nonce (bytes 112–115) that makes the hash smaller than the target:
// The mining loop — what each Web Worker runs.
// The nonce is a 32-bit big-endian integer at byte offset 112 of the header.
header[112] = (nonce >>> 24) & 0xff;
header[113] = (nonce >>> 16) & 0xff;
header[114] = (nonce >>> 8) & 0xff;
header[115] = nonce & 0xff;
const hash = await powHash(header); // Sandglass v3, 512 KiB, ~5–15 ms
// Interpret the 32-byte hash as a 256-bit number…
let hashNum = 0n;
for (let i = 0; i < hash.length; i++) hashNum = (hashNum << 8n) | BigInt(hash[i]);
// …a hash "wins" when it is below the target.
if (hashNum < poolTarget) submitShare(nonce, hash);
Lower target = harder puzzle. The network adjusts the target after every block
(ASERT difficulty adjustment) so that one block is found every
150 seconds on average, no matter how much hashrate joins or leaves.
3 · Work Distribution
Note: this section describes the classic pool protocol. On this pool the block header
is now built by your own browser instead of the server — see
section 9 (Negotiated Mode) below. The share and reward mechanics that follow are
unchanged.
When you start mining, your browser opens a WebSocket to the pool and authenticates
with your payout address. In the classic protocol the pool answers with a job —
a ready-to-mine block header it assembled from the current chain tip and pending
transactions:
// → browser sends (this pool: mode "negotiated" — see section 9)
{ "type": "auth", "address": "04df6bb9…", "mode": "negotiated" }
// ← classic pools respond with ready-made work (here: your browser builds it instead)
{
"type": "work",
"jobId": "57-mq9o3ygr", // height + unique id, rotates every block
"headerHex": "0000003a…", // 148-byte header, nonce zeroed
"poolTargetHex": "0000ff…", // your personal share target (vardiff)
"networkTargetHex": "000000ff…", // real target — solves the block
"height": 57
}
The header already contains the pool's address as the block miner, the transaction
root, and the resulting state root — your browser only has to grind nonces. Each
worker thread starts from a different random nonce so they never duplicate work:
// The 2^32 nonce space is sliced between workers.
const slice = Math.floor(0x1_0000_0000 / workers.length);
const base = Math.floor(Math.random() * 0xffff_ffff);
workers[i].postMessage({
type: 'start',
headerBytes,
targetHex: poolTargetHex,
startNonce: (base + i * slice) >>> 0,
});
4 · Shares — Proving Your Work
A solo miner only gets rewarded when they solve an entire block, which can take a very
long time on a single machine. A pool fixes that with shares: it hands
each miner a personal target that is much easier than the real network
target. The difficulty is tuned automatically per connection — classic
vardiff, the same mechanism stratum pools use — aiming for roughly
one share every 20 seconds no
matter how fast your hardware is.
// Per-miner pool target (vardiff, server side). More bits = easier.
// Every 60s the pool compares your share rate to the ideal (~1 per 20s)
// and steps your difficulty up or down — like classic stratum vardiff.
const networkTarget = compactToTarget(difficulty);
let poolTarget = networkTarget << BigInt(conn.shareBits); // 4–24 bits per miner
if (poolTarget > FLOOR_TARGET) poolTarget = FLOOR_TARGET;
Every hash that beats your target is a share. Since targets differ between
miners, each share is credited with a weight proportional to its difficulty:
a share from a 2× harder target counts exactly 2× more score. Fast rigs submit rare,
heavy shares; slow laptops submit frequent, light ones — everyone sees steady progress,
and payouts stay precisely hashrate-proportional. And because any share can also beat
the network target, shares and block solutions come from the same stream of
work — nothing is wasted.
The pool re-verifies every share server-side. Trust, but verify:
// Server-side share validation (abridged from the real code).
async function validateShare(job, nonce, claimedHashHex) {
const headerBytes = new Uint8Array(job.headerBytes);
writeNonce(headerBytes, nonce);
const hash = await powHash(headerBytes); // recompute Sandglass ourselves
if (bytesToHex(hash) !== claimedHashHex)
return { valid: false, reason: 'hash mismatch' };
// compared against YOUR personal vardiff target:
if (toBigInt(hash) >= targetForBits(networkTarget, conn.shareBits))
return { valid: false, reason: 'does not meet your share target' };
return { valid: true, meetsNetwork: toBigInt(hash) < networkTarget };
}
Cheating is also blocked at the protocol level: duplicate nonces are rejected
(submittedNonces set per job), submissions are rate-limited per
connection, and a share for an outdated job ("stale job") counts for
nothing.
5 · Reward Distribution (PPLNS)
Every accepted share adds its difficulty weight to a rolling window of
the most recent N weight of shares — the last
2× a block's worth of work. When the pool seals a
block, the reward is split proportionally to each miner's weight in that
window, not to a single round:
// PPLNS payout — straight from the pool server.
const reward = blockReward(height); // e.g. 50 BRC
const poolCut = BigInt(Math.floor(Number(reward) * POOL_FEE)); // 2%
const minerReward = reward - poolCut;
// pplns = rolling window of the last N share-weight (spans rounds)
for (const [addr, weight] of pplns.byAddr) {
const payout = (minerReward * BigInt(weight)) / BigInt(pplns.totalWeight);
pendingBalances.set(addr, (pendingBalances.get(addr) ?? 0n) + payout);
}
your payout = (block reward − 2% fee) ×
your weight in the windowtotal window weight
Because the window spans block boundaries, single-round luck stops
mattering and work you did during rounds the pool loses to another miner is still
paid on the pool's next block — PROP throws that work away. It also removes any
pool-hopping advantage. The window is sized so it only holds a couple of blocks' worth of
work, so a new miner reaches their steady share within a few minutes of joining, and keeps
earning briefly after they stop as their shares age out.
6 · Payouts
Earnings accumulate as a pending balance on the pool. Once a balance
reaches 1 BRC, the next payout cycle (every 60 seconds)
signs a regular on-chain transaction from the pool's wallet to your address:
// Automatic payout loop (every 60 s).
for (const [addr, amount] of pendingBalances) {
if (amount < MIN_PAYOUT) continue; // 1 BRC threshold
const tx = signTx(
{ from: poolKey.publicKey, to: hexToBytes(addr), amount, fee: 200n, nonce },
poolKey.privateKey,
);
await broadcastToHelpers(tx); // enters the mempool…
} // …and confirms in the next block
The payout is a normal BrowserCoin transaction — you can verify it on-chain. Since the
pool mines blocks itself, payout transactions are usually included in one of the pool's
own next blocks. The transaction fee (200 base units) is paid by the pool, not deducted
from you.
7 · Mining in a Browser — Why It Works
Sandglass v3 was designed for exactly this environment: because each hash is a long
chain of serial, latency-bound memory reads, a JavaScript Web Worker chasing
pointers through a 512 KiB typed array runs at nearly the same speed as native
code — the CPU is waiting on memory either way. Hashing happens in
Web Workers — background threads that can't block the page — so the tab
stays responsive while mining.
Each worker owns its own small Sandglass buffer (512 KiB, plus JS overhead). The
auto power setting uses every logical core except one (kept free so your system
stays smooth) — the same full-speed default as the official BrowserCoin miner:
// Auto thread selection (runs on page load).
const logicalCores = navigator.hardwareConcurrency || 4;
// All cores minus one — full speed while the OS + browser stay responsive.
const optimalThreads = Math.max(1, logicalCores - 1);
The 512 KiB working set fits in most CPUs' L2 cache, so hashrate scales close to
linearly with cores until the shared L3/memory system saturates. If you care about
efficiency (hashes per watt), drag the slider down manually; the last few threads on
small-cache CPUs can add little.
Note: some browsers deliberately report a lower hardwareConcurrency for
fingerprinting protection (Safari caps it at 8, Brave randomizes it), so the detected
value can differ between browsers on the same machine.
8 · Fairness & Trust
- Every share is re-verified — the server recomputes the full proof-of-work hash (Sandglass); fake or wrong hashes are rejected.
- No duplicate counting — nonces are tracked per job (and globally per template in negotiated mode); replaying a share does nothing, not even across connections.
- Rate limiting — connections submitting impossibly fast get throttled, protecting honest miners' relative weight.
- Transparent math — round shares, share percentages and estimated rewards are visible live on the dashboard for every miner.
- On-chain payouts — every payout is an ordinary transaction you can verify against the public chain.
- Fee — the pool keeps 2% of each block reward; everything else is distributed.
Pool Address (the block miner / payout sender)
loading…
9 · Negotiated Mode — Pooled Payouts Without Pooled Power
A classic pool has a structural problem: it builds the blocks, so it decides which parent to
extend and which transactions to include. If one pool grows past ~50% of the network it could
— even accidentally — reorganize the chain or censor transactions. Negotiated mode
(inspired by Bitcoin's Stratum V2 job negotiation) removes that power while keeping the
steady pooled payouts:
- Your browser is a full node — on start it downloads all block headers,
spot-checks their proof-of-work, verifies a state snapshot and validates the recent blocks
in full (~1 minute). From then on it follows the chain itself.
- You build the block — your machine picks the parent block and the
transactions from the public mempool and assembles its own candidate block. The pool never
tells you what to mine.
- The pool only checks and pays — the only requirement is that the block
reward goes to the pool address, which is what makes shared payouts possible. The pool fully
validates your template (difficulty, timestamps, every transaction, resulting state) and then
credits your shares exactly like classic ones: same PPLNS window, same rewards, same fee.
- Why the pool's size doesn't matter anymore — a classic pool with a huge
network share is dangerous because it controls what all that hashpower mines. Here that
control stays with each miner, so the pool's share of the network no longer measures anyone's
power over consensus. This is also why the old per-address hashrate cap and the
high-network-share warning are gone.
- No extra trust needed — you verify the chain yourself instead of trusting
the pool's view of it; the pool re-verifies every template and share, so neither side can
cheat the other.
Negotiated mode is mandatory on this pool — the server rejects classic
(pool-built-work) connections. Browser miners get it automatically; if you run a headless
miner, see Connect a Miner for the full protocol.
Connect an External Miner
Everything you need to point a headless or custom miner at this pool: the ready-made
clients, and the full negotiated mining protocol if you want to build
your own. This pool does not serve pool-built work — every miner builds its own blocks.
1 · The easy ways
- Browser — just mine on the dashboard.
Negotiated mode is built in: press Start, the page syncs the chain (~1 minute) and mines.
- FulgurMiner (headless / CLI) — the popular terminal miner supports this
pool's negotiated mode out of the box since v0.7.0 (older versions stop
with an upgrade hint — run
npm run update). It detects the mode automatically:
set MINER_POOL=https://brcpool.cryptec.tech and run. Requires Node 22+.
github.com/alpenmilch411/FulgurMiner
- Your own client — implement the protocol below. It's a single WebSocket
with JSON messages plus the public helper APIs for chain data.
2 · Protocol overview
Your miner keeps its own validated copy of the chain (synced from the
public helper APIs), builds its own block template whose coinbase pays
the pool address, registers that template with the pool, and then grinds nonces against a
personal (vardiff) share target. The pool validates the template once, then credits every
share against it. When a share also meets the network target, the pool assembles the full
block from your registered template and broadcasts it.
Your Miner
syncs chain from helpers
builds template · grinds nonces
⇄
Pool Server
validates templates & shares
aggregates PPLNS payouts
⇄
BRC Network
helper APIs serve blocks
accept found blocks
Chain data comes from the public helpers (any of them; they serve the same chain):
https://api1.cryptec.tech, https://api1.browsercoin.org,
https://api2.browsercoin.org, https://api1.taitech.eu —
GET /tip and GET /blocks?fromHeight=N&max=200 are all you
need. Validate every block yourself; heavy reads are rate-limited (~60/min per IP), so
pace your initial sync. The pool itself serves the same two endpoints
(https://brcpool.cryptec.tech/tip and /blocks, up to 120
requests/min per IP) — syncing from the pool has the nice property that your chain view
and the pool's announced tip can't disagree for long.
3 · Connect & authenticate
Open a WebSocket to wss://brcpool.cryptec.tech/ws and send one auth message.
address is your 64-hex payout address; mode must be
"negotiated" (classic auth is rejected with an error).
// → you send
{ "type": "auth", "address": "<your 64-hex address>", "mode": "negotiated" }
// ← the pool replies with the chain state (also re-sent on every tip change
// and periodically as the mempool refreshes)
{
"type": "chain_info",
"height": 35144, // pool's current tip height
"tipHash": "d4554bd7…", // pool's tip hash — your template's parent
"nextHeight": 35145,
"nextDifficulty": 503371455, // compact bits for a timestamp of "now"
"blockMtp": 1784812000, // median-time-past — timestamp must exceed it
"scriptsActive": true,
"poolAddress": "ff811ae0…", // your template's header.miner must be this
"reward": "2500000000",
"mempool": ["<tx hex>", "…"] // pending txs you may include (re-validate them!)
}
4 · Build & register a template
Assemble a full BrowserCoin block (canonical binary encoding, hex-encoded) and register
it. The pool validates it exactly like a real block, so it must satisfy all of:
prevHash = the pool's current tip (from chain_info) — anything else is rejected as stale parent;
height = tip height + 1;
header.miner = the pool address (that's the whole coinbase constraint — parent and transaction choice stay yours);
difficulty = the consensus expected difficulty for your header's timestamp (ASERT, fork-aware);
timestamp > median-time-past and not more than a few minutes in the future;
- valid
txRoot and stateRoot for the included transactions (the pool dry-runs them against its tip state);
- encoded block ≤ 256 KB; header
nonce = 0 (shares carry the nonce).
// → you send (max 1 registration per 2 s per connection)
// clientId is optional (≤64 chars): the pool echoes it on the result so you
// can match answers to in-flight registrations — recommended.
{ "type": "template", "blockHex": "<full encoded block, hex>", "clientId": "r7-x1k2q9" }
// ← accepted: grind this header against poolTargetHex
{
"type": "template_result",
"accepted": true,
"clientId": "r7-x1k2q9", // echoed if you sent one
"templateId": "t-83aa51…", // job id for your shares
"headerHex": "<148-byte header, hex, nonce zeroed>",
"poolTargetHex": "0000f0…", // your personal vardiff share target
"networkTargetHex": "000004…", // the real block target
"height": 35145
}
// ← rejected: fix and re-register
{ "type": "template_result", "accepted": false, "clientId": "r7-x1k2q9", "reason": "stale parent (pool tip d4554bd7…)" }
Verify the returned header. headerHex must be byte-for-byte
the header you registered (with nonce zeroed) — check it before grinding. That check is
what makes negotiated mode trustless: a pool can never substitute a template you didn't
build.
5 · Grind & submit shares
The proof-of-work is Sandglass v3 (since block 33,550; Argon2id
before that). Write the nonce into bytes 112–115 (big-endian u32) of the
148-byte header, hash it, and compare the 32-byte digest as a big-endian 256-bit integer
against your poolTargetHex. Every hash at or below the target is a share:
// → you send, per hit
{ "type": "share", "jobId": "t-83aa51…", "nonce": 194835, "hashHex": "<32-byte digest, hex>" }
// ← the pool re-hashes and credits it (jobId echoed from your submission)
{ "type": "share_result", "accepted": true, "weight": 4096, "roundScore": 123456, "jobId": "t-83aa51…" }
// ← or rejects it — use jobId to tell a late verdict for an OLD template
// from one for your current template before reacting
{ "type": "share_result", "accepted": false, "reason": "duplicate nonce", "jobId": "t-83aa51…" }
- Vardiff — the pool retunes your share target for ~1 share / 20 s and
pushes
{ "type": "share_target", "templateId", "poolTargetHex" }; keep the same
header, apply the new target.
- Nonces are deduplicated per template (across all connections) — never
submit the same nonce twice for one
templateId.
- Rate limit — max 30 shares / 10 s per connection; vardiff keeps an
honest miner far below it.
- Blocks — a share that also meets
networkTargetHex is a full
block: the pool assembles it from your registered template, broadcasts it, and everyone in the
PPLNS window gets paid. Nothing extra to do on your side.
6 · Staying current
- Tip changes — every new block triggers a fresh
chain_info.
Your registered template is now stale: sync your chain to the new tip, rebuild, re-register.
Shares for the old template are rejected with stale template.
- Hashrate heartbeat — send
{ "type": "hashrate", "hashesPerSecond": 512 } every ~5–10 s; after 15 s
of silence the dashboard falls back to estimating you from accepted shares.
- Reconnects — on disconnect just reconnect and re-auth; you'll get a fresh
chain_info. Registered templates don't survive a disconnect.
- Connection limits — max 8 connections per IP; one connection per machine is
plenty (grind on many threads behind it).
Payouts are identical to browser mining: PPLNS window, 2%
fee, automatic payout at 1 BRC pending — details in
How It Works.
Total Paid Out
— BRC
to — miners, lifetime
Paid Last 24h
— BRC
on-chain payouts
Avg Block Time
—
last — pool blocks
Next Block Est.
—
at current hashrate
Pool Luck
—
avg effort, last — blocks
Pool vs Network Hashrate last 24h
Connected Miners last 24h
Recent Share Split PPLNS window
No shares in the window yet.
Blocks Found Per Hour last 24h
BRC Paid Per Hour last 24h
Time Between Pool Blocks recent blocks
Need at least 2 blocks for this chart.
Recent Payouts
| Address |
Amount |
Time |
| No payouts yet. |