Skip to content

Repository files navigation

Polygon Gateway

polygon-gateway is a bounded Polygon PoS P2P relay. It connects trusted upstream Bor peers and one explicitly configured local Bor target, receives eth block announcements, and sends complete NewBlock payloads to the target.

Current implementation:

  • Amoy and Polygon Mainnet chain IDs, genesis data, EIP-2124 fork IDs, and live-head status.
  • Bor 0x7f StateSyncTx and receipt wire decoding, hashing, limits, and trie-root support.
  • eth/68 RLPx sessions with explicit source and target roles.
  • Bounded candidate-window selection with conflict freezing and source-quorum reorg resolution.
  • Retried, session-aware delivery with target P2P observations or optional RPC confirmation.
  • Header/body fetch from the announcing peer after a trusted TD anchor is available, with fallback to another connected source.
  • Bounded exponential retries for transient header/body fetch failures.
  • Header hash, block number, and transaction-root verification before fetched blocks are sent.
  • A bounded, target-only proxy for header, body, node-data, and receipt requests to source peers.
  • Bounded ingress/fetch queues, eight concurrent hash fetches, inflight deduplication, and TD cache.
  • A 256-block full-body cache covering twice the configured maximum reorg depth.
  • Periodic structured health logs and feature-gated hotpath profiling.

Bor 2.10.0 retains TD in its eth/69 Status packet, while upstream Reth 1.11.4 omits it. The gateway therefore advertises only eth/68 until a Bor-specific eth/69 handshake codec is added.

Build and test

cargo build --release -p polygon-gateway
cargo test -p polygon-protocol -p polygon-gateway-core -p polygon-gateway

Run against Polygon Mainnet

The target and every source are explicit enode URLs. Discovery is disabled so an unclassified peer cannot become a relay source or target.

./target/release/polygon-gateway \
  --network mainnet \
  --rpc-url https://YOUR_POLYGON_MAINNET_RPC \
  --total-difficulty EXACT_TD_AT_ANCHOR \
  --total-difficulty-block-hash 0xANCHOR_BLOCK_HASH \
  --target-node 'enode://TARGET_PUBLIC_KEY@TARGET_IP:30303' \
  --source-node 'enode://SOURCE_PUBLIC_KEY@SOURCE_IP:30303' \
  --source-quorum 1 \
  --listen-addr 0.0.0.0:30313

Repeat --source-node for redundancy and set --source-quorum to the number of independent peers required to resolve a same-height conflict. Mainnet is the default network. --total-difficulty is mandatory because Bor HTTP RPC commonly omits it. With --total-difficulty-block-hash, the gateway verifies that anchor and derives the current TD over at most 2,048 RPC blocks. Without an anchor hash, the supplied TD must exactly match the RPC head sampled at startup. The gateway fails closed instead of substituting block height when TD is unavailable. Use --network amoy for Amoy. --receipt-probe-hash optionally verifies the live Polygon receipt decoder against a configured source and logs both the receipt count and the number of 0x7f receipts.

The default --confirmation-mode p2p treats a matching block announcement from the target session as evidence that the target knows the block. Use --confirmation-mode rpc only when --rpc-url points at that exact target Bor. Reth's send API does not expose its bounded session-queue result, so an enqueued log is a send attempt, not an import acknowledgement; unacknowledged candidates remain pending and are retried after reconnect.

Successful data-plane logs contain:

P2P session established ... role="source"
P2P session established ... role="target"
enqueued full block for local Bor delivery ... number=... hash=... td=... attempt=...
target acknowledged relay candidate ... evidence=p2p number=... hash=...
relay health ... pending_delivery=... send_retries=... p2p_acknowledged=... fetch_errors=...

Health logs also report first_send_latency_us_avg and first_send_latency_us_max. These measure validated-block storage to first target-session enqueue time; they do not claim remote import or end-to-end acceleration without a target observation.

Profiling and soak tests

The default build keeps hotpath instrumentation disabled. Build timing, allocation, custom gauge, thread, and Tokio runtime profiling with:

make profile

Run a monitored soak test by passing the upstream enodes as positional arguments:

TARGET_NODE='enode://TARGET_PUBLIC_KEY@127.0.0.1:30303' \
TOTAL_DIFFICULTY=EXACT_TD_OF_RPC_HEAD \
TOTAL_DIFFICULTY_BLOCK_HASH=0xANCHOR_BLOCK_HASH \
RPC_URL=https://YOUR_POLYGON_MAINNET_RPC \
DURATION_SECONDS=3600 \
scripts/soak-test.sh \
  'enode://SOURCE_1_PUBLIC_KEY@SOURCE_1_IP:30303' \
  'enode://SOURCE_2_PUBLIC_KEY@SOURCE_2_IP:30303'

Each run writes gateway.log, process.csv, tokio-runtime.jsonl, hotpath.json, and summary.txt below artifacts/soak-<timestamp>/. The relay queue is deliberately not wrapped with hotpath::channel!: the hotpath proxy adds one slot and can change try_send backpressure semantics. Queue depth and drops are recorded directly instead.

This is an early implementation of the reviewed design. Historical requests are proxied on demand; the gateway does not maintain a complete local history, so catch-up availability still depends on the configured sources. It does not implement Bor's eth/69 Status variant or claim consensus/finality validation.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages