Token导航 LogoToken导航TokenDH.com
开发需要联网github未标认证来源可访问许可证需确认审计提醒

stratum-v1v1 层

Agent Skill

stratum-v1 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

442

周安装

19

GitHub Stars

2

下载量

155
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:stratum-v1(v1 层)
来源仓库:https://github.com/b-open-io/bsv-skills
仓库路径:skills/stratum-v1
安装命令:
npx skills add https://github.com/b-open-io/bsv-skills --skill stratum-v1
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/b-open-io/bsv-skills --skill stratum-v1

简介

用于处理 GitHub 仓库、Issue、Pull Request 等协作信息,适合在多种宿主环境中整理代码变更事项。

  • 支持围绕仓库状态、代码协作流程进行信息组织与分类。
  • 通过 npx skills add 命令从指定 GitHub 仓库安装使用。
  • 安装前需确认权限范围、维护状态及是否触发联网或文件操作。
  • stratum-v1 属于开发类 Skill,可作为该场景下的辅助能力补充。

SKILL.md

Stratum v1 Mining Protocol

Stratum v1 is the standard protocol for communication between mining pools and mining hardware (ASICs). It uses JSON-RPC 2.0 over TCP with newline-delimited messages.

When to Use

  • Implementing a BSV mining pool server
  • Building mining proxy software
  • Creating ASIC firmware/software
  • Debugging miner-pool communication
  • Understanding pool share validation

Protocol Overview

Transport Layer

  • Plain TCP socket connection
  • JSON-RPC messages terminated by newline (\n)
  • Persistent connection (not HTTP request/response)
  • Optional TLS encryption on separate port

Message Format

Request:

{"id": 1, "method": "mining.subscribe", "params": ["UserAgent/1.0"]}

Response:

{"id": 1, "result": [...], "error": null}

Notification (no response expected):

{"id": null, "method": "mining.notify", "params": [...]}

Core Methods

1. mining.subscribe

Initial handshake from miner to pool.

Request:

{
  "id": 1,
  "method": "mining.subscribe",
  "params": ["UserAgent/1.0.0"]
}

Response:

{
  "id": 1,
  "result": [
    [["mining.set_difficulty", "subscription_id"], ["mining.notify", "subscription_id"]],
    "extranonce1",
    4
  ],
  "error": null
}

Response fields:

  • result[0]: Array of subscription tuples [method, subscription_id]
  • result[1]: Extranonce1 (hex string, typically 8 chars/4 bytes)
  • result[2]: Extranonce2 size in bytes (typically 4)

2. mining.authorize

Authenticate a worker with the pool.

Request:

{
  "id": 2,
  "method": "mining.authorize",
  "params": ["ADDRESS.workerName", "password"]
}

For BSV pools like GorillaPool, the username format is BSV_ADDRESS.workerName where:

  • BSV_ADDRESS is a valid BSV address (validated at connection)
  • workerName is an optional identifier for the specific mining device

Response:

{"id": 2, "result": true, "error": null}

3. mining.set_difficulty

Server notification to adjust share difficulty.

Notification:

{
  "id": null,
  "method": "mining.set_difficulty",
  "params": [65536]
}

The difficulty value represents the minimum share difficulty the pool will accept. Shares below this difficulty are rejected.

4. mining.notify

Server sends a new job to miners.

Notification:

{
  "id": null,
  "method": "mining.notify",
  "params": [
    "job_id",
    "prevhash",
    "coinb1",
    "coinb2",
    ["merkle_branch_1", "merkle_branch_2"],
    "version",
    "nbits",
    "ntime",
    true
  ]
}

Parameters:

IndexNameDescription
0job_idUnique job identifier (8-char hex)
1prevhashPrevious block hash (word-reversed hex)
2coinb1First part of coinbase transaction
3coinb2Second part of coinbase transaction
4merkle_branchArray of merkle tree hashes
5versionBlock version (big-endian hex)
6nbitsEncoded network difficulty target
7ntimeBlock timestamp (big-endian hex)
8clean_jobsIf true, discard previous jobs

5. mining.submit

Miner submits a share (potential block solution).

Request:

{
  "id": 3,
  "method": "mining.submit",
  "params": [
    "ADDRESS.workerName",
    "job_id",
    "extranonce2",
    "ntime",
    "nonce",
    "version_bits"
  ]
}

Parameters:

IndexNameDescription
0workerWorker name (ADDRESS.worker)
1job_idJob ID from mining.notify
2extranonce2Miner's extranonce2 (hex, length = extranonce2_size * 2)
3ntimeBlock timestamp (8-char hex)
4nonce32-bit nonce (8-char hex)
5version_bitsVersion rolling bits (optional, 8-char hex)

Response:

{"id": 3, "result": true, "error": null}

6. mining.configure

Extension negotiation (BIP310-style).

Request:

{
  "id": 4,
  "method": "mining.configure",
  "params": [
    ["version-rolling", "minimum-difficulty"],
    {"version-rolling.mask": "1fffe000", "minimum-difficulty.value": 2048}
  ]
}

Response:

{
  "id": 4,
  "result": [true, {
    "version-rolling": true,
    "version-rolling.mask": "1fffe000",
    "minimum-difficulty": true
  }],
  "error": null
}

Byte Order Reference (CRITICAL)

Byte order is the #1 source of bugs in Stratum implementations. This section documents the exact byte order at each stage.

Terminology

  • BE (Big-Endian): Most significant byte first (human-readable, "natural" order)
  • LE (Little-Endian): Least significant byte first (Bitcoin internal format)
  • Byte-reversed: Simple reversal of all bytes
  • Word-reversed: Reverse 4-byte chunks, then reverse the whole thing (Stratum-specific)

mining.notify Field Byte Orders

FieldStratum JSON HexTransformation for Header
prevhashWord-reversedUse separate byte-reversed version
versionBE hex stringReverse to LE bytes
nbitsBE hex stringReverse to LE bytes
ntimeBE hex stringReverse to LE bytes
merkle_branch[]LE (byte-reversed from node)Use as-is
coinb1, coinb2Raw tx bytesUse as-is

Prevhash Transformation (Most Complex)

The prevhash undergoes TWO different transformations:

From Node (getminingcandidate):

Original: 000000000000000001a2b3c4d5e6f7...  (BE, 64 hex chars)

For Stratum Protocol (mining.notify):

// Word-reverse: split into 8 4-byte words, reverse each word, then reverse word order
// This is what miners receive in mining.notify params[1]
stratumPrevhash := wordReverse(original)

func wordReverse(hash string) string {
    // Decode to bytes
    bytes, _ := hex.DecodeString(hash)  // 32 bytes

    // Split into 8 words of 4 bytes each
    words := make([][]byte, 8)
    for i := 0; i < 8; i++ {
        words[i] = bytes[i*4 : (i+1)*4]
    }

    // Reverse each word
    for i := range words {
        reverse(words[i])
    }

    // Reverse word order
    reverseSlice(words)

    // Concatenate back
    return hex.EncodeToString(flatten(words))
}

For Block Header Construction:

// Simple byte-reverse (NOT word-reverse)
// This goes into the actual 80-byte block header
headerPrevhash := reverseBytes(original)

Example:

Node returns:      00000000000000000452b3f2a1c4d5e6f7890abcdef1234567890abcdef12345
Stratum sends:     e6d5c4a1f2b35204000000000000000045123fcdab0987654321fedcab0987...
Header uses:       4523f1cdab0987654321fedcab0987f6e5d4c1a2f3b25400000000000000...

Version, Bits, Time, Nonce

In Stratum JSON (mining.notify):

version: "20000000"  <- BE hex, 4 bytes
nbits:   "1d00ffff"  <- BE hex, 4 bytes
ntime:   "5f4a3b2c"  <- BE hex, 4 bytes

In Block Header (80 bytes):

All fields stored as LE bytes

version "20000000" -> bytes [0x00, 0x00, 0x00, 0x20]  (reversed)
nbits   "1d00ffff" -> bytes [0xff, 0xff, 0x00, 0x1d]  (reversed)
ntime   "5f4a3b2c" -> bytes [0x2c, 0x3b, 0x4a, 0x5f]  (reversed)
nonce   "12345678" -> bytes [0x78, 0x56, 0x34, 0x12]  (reversed)

Go code:

// Stratum hex -> header bytes
func stratumHexToHeaderBytes(hexStr string) []byte {
    bytes, _ := hex.DecodeString(hexStr)  // Decode BE hex
    reverseInPlace(bytes)                  // Convert to LE
    return bytes
}

Merkle Branch Byte Order

From Node (getminingcandidate.merkleProof):

Node returns hashes in BE (natural) order

For Stratum (mining.notify params[4]):

// Pool must byte-reverse each merkle proof element before sending
for i, proof := range node.MerkleProof {
    proofBytes, _ := hex.DecodeString(proof)
    reverseInPlace(proofBytes)  // Convert to LE
    branches[i] = hex.EncodeToString(proofBytes)
}

When applying branches (share validation):

// Branches are already LE, use directly
func applyMerkleBranches(coinbaseHash []byte, branches []string) []byte {
    root := coinbaseHash  // Already LE from SHA256d
    for _, branch := range branches {
        branchBytes, _ := hex.DecodeString(branch)  // Already LE
        combined := append(root, branchBytes...)
        root = sha256d(combined)  // Result is LE
    }
    return root  // LE, ready for header
}

Block Hash Byte Order

After hashing header:

headerHash := sha256d(header80bytes)  // Returns LE bytes

For display (block explorer, logs):

displayHash := reverseBytes(headerHash)  // Convert to BE for display
hashString := hex.EncodeToString(displayHash)

For difficulty comparison:

// Convert LE hash to big.Int (SetBytes expects BE)
hashBE := reverseBytes(headerHash)
hashInt := new(big.Int).SetBytes(hashBE)

// Compare against target
isBlock := hashInt.Cmp(networkTarget) <= 0

Complete Byte Order Flow

┌─────────────────────────────────────────────────────────────────┐
│                    NODE (getminingcandidate)                     │
├─────────────────────────────────────────────────────────────────┤
│ prevhash:     BE (64 hex chars)                                 │
│ merkleProof:  BE (array of 64-char hex)                         │
│ version:      uint32                                            │
│ nBits:        BE hex string                                     │
│ time:         uint32                                            │
└─────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                    POOL (transforms for Stratum)                 │
├─────────────────────────────────────────────────────────────────┤
│ prevhash:     Word-reverse for mining.notify                    │
│               Byte-reverse for header validation (store both)   │
│ merkleProof:  Byte-reverse each element                         │
│ version:      uint32 -> BE hex string (8 chars)                 │
│ nBits:        Already BE hex                                    │
│ ntime:        uint32 -> BE hex string (8 chars)                 │
└─────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                    STRATUM JSON (mining.notify)                  │
├─────────────────────────────────────────────────────────────────┤
│ params[1] prevhash:  Word-reversed hex (64 chars)               │
│ params[4] branches:  LE hex strings                             │
│ params[5] version:   BE hex (8 chars)                           │
│ params[6] nbits:     BE hex (8 chars)                           │
│ params[7] ntime:     BE hex (8 chars)                           │
└─────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                    MINER (mining.submit)                         │
├─────────────────────────────────────────────────────────────────┤
│ extranonce2: Hex string (length = extranonce2_size * 2)         │
│ ntime:       BE hex (8 chars) - may differ from job             │
│ nonce:       BE hex (8 chars)                                   │
│ versionBits: BE hex (8 chars) - optional                        │
└─────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                    POOL (share validation)                       │
├─────────────────────────────────────────────────────────────────┤
│ 1. Coinbase: concat(coinb1, en1, en2, coinb2) - raw bytes       │
│ 2. cbHash:   SHA256d(coinbase) -> LE bytes                      │
│ 3. Root:     Apply LE branches -> LE bytes                      │
│ 4. Header:   [ver_LE, prev_LE, root_LE, time_LE, bits_LE, nonce_LE] │
│ 5. Hash:     SHA256d(header) -> LE bytes                        │
│ 6. Display:  Reverse hash for BE display                        │
└─────────────────────────────────────────────────────────────────┘

Common Byte Order Bugs

  1. Using word-reversed prevhash in header - Must use simple byte-reversed
  2. Not reversing version/time/bits/nonce - Stratum sends BE, header needs LE
  3. Reversing merkle branches twice - They're pre-reversed by pool
  4. Wrong hash comparison endianness - big.Int.SetBytes expects BE
  5. Displaying hash without reversal - Internal is LE, display is BE

Coinbase Construction

The coinbase transaction is built by concatenating:

coinbase = coinb1 + extranonce1 + extranonce2 + coinb2

Where:

  • coinb1: Version + input count + prevout + scriptSig length + scriptSig prefix (height, timestamp)
  • extranonce1: Pool-assigned unique value per connection
  • extranonce2: Miner-controlled value for nonce space expansion
  • coinb2: ScriptSig suffix + sequence + outputs + locktime

All coinbase parts are raw transaction bytes - no byte order transformation needed.

Block Header Construction

80-byte header structure (all fields little-endian in final header):

Offset  Size  Field       Source                    Transformation
------  ----  ----------  ------------------------  -------------------------
0       4     version     mining.notify params[5]   Decode BE hex, reverse to LE
4       32    prevhash    Store byte-reversed       Use byte-reversed (NOT word-reversed)
36      32    merkleroot  SHA256d of merkle tree    Already LE from hashing
68      4     time        mining.submit params[3]   Decode BE hex, reverse to LE
72      4     bits        mining.notify params[6]   Decode BE hex, reverse to LE
76      4     nonce       mining.submit params[4]   Decode BE hex, reverse to LE
------  ----
        80 bytes total

Go implementation:

func buildHeader(job *Job, ntime, nonce string, versionMask *uint32, versionBits string) []byte {
    header := make([]byte, 80)

    // Version: BE hex -> LE bytes
    version, _ := hex.DecodeString(job.VersionHex)
    reverseInPlace(version)
    copy(header[0:4], version)

    // Prevhash: Use pre-computed byte-reversed (NOT the word-reversed Stratum format)
    prev, _ := hex.DecodeString(job.PrevHashForHeader)
    copy(header[4:36], prev)

    // Merkle root: Already LE from ApplyMerkleBranches
    copy(header[36:68], merkleRoot)

    // Time: BE hex -> LE bytes
    time, _ := hex.DecodeString(ntime)
    reverseInPlace(time)
    copy(header[68:72], time)

    // Bits: BE hex -> LE bytes
    bits, _ := hex.DecodeString(job.BitsHex)
    reverseInPlace(bits)
    copy(header[72:76], bits)

    // Nonce: BE hex -> LE bytes
    nonceBytes, _ := hex.DecodeString(nonce)
    reverseInPlace(nonceBytes)
    copy(header[76:80], nonceBytes)

    return header
}

Share Validation

// Pseudocode for share validation
func validateShare(job, extranonce1, extranonce2, ntime, nonce, versionBits) bool {
    // 1. Build coinbase
    coinbase := job.Coinb1 + extranonce1 + extranonce2 + job.Coinb2

    // 2. Hash coinbase
    coinbaseHash := SHA256d(coinbase)

    // 3. Calculate merkle root
    merkleRoot := applyMerkleBranches(coinbaseHash, job.Branches)

    // 4. Build 80-byte header
    header := buildHeader(job.Version, job.PrevHash, merkleRoot, ntime, job.Bits, nonce)

    // 5. Apply version rolling if enabled
    if versionBits != "" {
        header.version = (header.version & ~mask) | (versionBits & mask)
    }

    // 6. Hash header
    blockHash := SHA256d(header)

    // 7. Calculate share difficulty
    shareDiff := diff1Target / hashToInt(blockHash)

    // 8. Check against stratum difficulty
    return shareDiff >= session.difficulty
}

Variable Difficulty (VarDiff)

VarDiff dynamically adjusts share difficulty to maintain target share rate.

Configuration:

{
  "varDiff": {
    "minDiff": 512,
    "maxDiff": 1000000000,
    "targetTime": 15,
    "retargetTime": 90,
    "variancePercent": 30,
    "maxDelta": 500
  }
}

Algorithm:

  1. Track time between shares in circular buffer
  2. Every retargetTime seconds, calculate average share time
  3. If average outside targetTime +/- variancePercent, adjust: newDiff = currentDiff * targetTime / averageTime
  4. Apply maxDelta limit and clamp to [minDiff, maxDiff]

Version Rolling (BIP310)

Allows miners to use bits in the version field as additional nonce space.

Mask: 0x1fffe000 (bits 13-28, 16 bits = 65536x nonce space)

Protocol flow:

  1. Miner sends mining.configure with version-rolling extension
  2. Pool responds with allowed mask
  3. Miner includes version_bits parameter in mining.submit
  4. Pool validates: (version_bits & ~mask) == 0

Error Codes

CodeMessageDescription
20Other/UnknownGeneric error
21Job not foundInvalid job_id
22Duplicate shareShare already submitted
23Low difficultyShare below target
24UnauthorizedWorker not authorized
25Not subscribedmining.subscribe not called

Implementation Example (Go)

See GorillaNode's implementation at:

  • backend/internal/services/stratum/server.go - Stratum server
  • backend/internal/services/stratum/templates/gbt.go - Job construction
  • backend/internal/services/vardiff/manager.go - VarDiff logic

Key patterns:

// Session handling
type session struct {
    conn            net.Conn
    extranonce1     string      // Unique per connection
    extranonce2Size int         // Typically 4 bytes
    difficulty      float64     // Current share difficulty
    authorized      bool        // Has mining.authorize succeeded
    submits         map[string]struct{} // Duplicate detection
}

// Job management
type Job struct {
    Id       string   // Short 8-char hex ID
    Height   int64
    Coinb1   string
    Coinb2   string
    Branches []string
    // ... block header fields
}

Testing

Connect with netcat:

nc pool.example.com 3333
{"id":1,"method":"mining.subscribe","params":["test/1.0"]}
{"id":2,"method":"mining.authorize","params":["1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa.worker1",""]}

Tools:

  • cpuminer-multi - CPU miner for testing
  • cgminer / bfgminer - Full-featured miners
  • Wireshark with Stratum dissector

References

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

31.46%
按下载量换算49

Claude

29.73%
按下载量换算46

Cursor

19.57%
按下载量换算30

Gemini CLI

9.99%
按下载量换算15

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

可疑

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。来源安全扫描存在 warning/failed 结果,不能写成本站确认安全。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills