ZMQ-emner

TensorCash arver ZMQ-pub/sub-grensesnittet fra Bitcoin Core uendret. Utgiveren binder (som standard tcp://127.0.0.1:28332); abonnenter kobler til og abonnerer på emneprefikser. Hver varsling er en flerdelt melding med tre rammer, og innholdsoppsettet for hvert emne står nedenfor.

5 emner · opprinnelse: inherit

Denne siden dekker pub/sub-mekanismen som er arvet fra Bitcoin Core. Valideringskanalen mellom node og verifikator er en separat ZMQ PUSH/PULL-strøm med nyttelaster som bruker FlatBuffer-skjemaer: proof.fbs, validation.fbs og blockheader.fbs.

Rammekonvolutt

Publisher binds; subscribers connect and SUBSCRIBE to topic prefixes. Topic strings are matched as byte prefixes — SUBSCRIBE "hash" receives both hashblock and hashtx.

RammeFeltTypeBeskrivelse
0topicutf-8 stringOne of the topic names below.
1bodyper-topicDefined by the topic. See frames[1] per topic.
2sequence_counteruint32 little-endianMonotonically increasing per-topic counter. Subscribers detect dropped messages by checking for gaps. Resets on bcore restart.

Emner

hashblock

-zmqpubhashblock=<address>

Best-block-tip changed (new block connected to the active chain).

A block is connected to the main chain. Fires once per UpdatedBlockTip callback.

RammeFeltTypeBeskrivelse
1block_hash32 bytes, little-endian (display-reversed)The connecting block's hash. Note Bitcoin Core's display convention reverses byte order — the wire bytes are little-endian; tooling that prints hex usually reverses them for display.

Kilde: services/core-node/bcore/src/zmq/zmqpublishnotifier.cpp:228

hashtx

-zmqpubhashtx=<address>

Transaction entered the mempool or was confirmed in a block.

Fires for every TransactionAddedToMempool and BlockConnected event; may emit duplicates for the same hash if a tx is re-broadcast or re-mined after a reorg.

RammeFeltTypeBeskrivelse
1tx_hash32 bytes, little-endian (display-reversed)The transaction hash (txid).

Kilde: services/core-node/bcore/src/zmq/zmqpublishnotifier.cpp:239

rawblock

-zmqpubrawblock=<address>

Full serialized block on best-tip change.

Same trigger as hashblock — but the body is the full block, not just its hash. Heavier; only enable if a subscriber actually needs full block bytes (e.g. an indexer that does not have its own bcore peer).

RammeFeltTypeBeskrivelse
1block_serializedvariable-length bytesThe block, serialized using Bitcoin Core's standard block serialization (CBlock::Serialize). Includes the header, tx count (var_int), and all transactions in order.

Kilde: services/core-node/bcore/src/zmq/zmqpublishnotifier.cpp:252

rawtx

-zmqpubrawtx=<address>

Full serialized transaction.

Same trigger as hashtx — body is the full serialized transaction (CTransaction::Serialize). Subscribers can fully decode without round-tripping to JSON-RPC.

RammeFeltTypeBeskrivelse
1tx_serializedvariable-length bytesThe transaction, serialized with Bitcoin Core's standard transaction serialization. Witness data included when present.

Kilde: services/core-node/bcore/src/zmq/zmqpublishnotifier.cpp:261

sequence

-zmqpubsequence=<address>

Mempool + block connect/disconnect event stream.

Block-connect, block-disconnect, mempool-accept, and mempool-remove events. The body's event byte tells subscribers which type. Useful for indexers that need a single ordered event stream rather than the separate hashblock/hashtx topics.

RammeFeltTypeBeskrivelse
1hash + event_byte (+ optional mempool_seq)32-byte hash || 1-byte event || optional 8-byte LE mempool_sequenceBody layout depends on the event: • 'C' (block connect) — hash || 'C' • 'D' (block disconnect) — hash || 'D' • 'A' (mempool accept) — hash || 'A' || mempool_sequence (uint64 LE) • 'R' (mempool remove) — hash || 'R' || mempool_sequence (uint64 LE) The 32-byte hash is little-endian on the wire (same convention as the hash topics). mempool_sequence is a separate per-mempool counter — distinct from the topic-level sequence_counter in frame 2.

Kilde: services/core-node/bcore/src/zmq/zmqpublishnotifier.cpp:264

Abonnenteksempler

Python (pyzmq)

import struct
import zmq

ctx = zmq.Context()
sock = ctx.socket(zmq.SUB)
sock.connect("tcp://127.0.0.1:28332")
sock.setsockopt(zmq.SUBSCRIBE, b"hashblock")
while True:
    topic, body, seq_le = sock.recv_multipart()
    (seq,) = struct.unpack("<I", seq_le)
    # block_hash bytes are little-endian; reverse for display hex
    display_hash = body[::-1].hex()
    print(f"seq={seq} {topic.decode()}: {display_hash}")

Node.js (zeromq.js)

import zmq from "zeromq";

const sock = new zmq.Subscriber();
sock.connect("tcp://127.0.0.1:28332");
sock.subscribe("rawtx");
for await (const [topic, body, seqLe] of sock) {
  const seq = seqLe.readUInt32LE(0);
  console.log(`seq=${seq} ${topic.toString()} ${body.length} bytes`);
}