LIVE ISSUANCE · ARBITRUM ONEOPEN TO BUILDERS & MINERS

Mine openly.
Watch it work.

官网不提供封装后的可执行程序。下面是完整、可检查的 CPU 参考实现,运行时会动态展示 nonce、实时哈希、累计计算量和算力,适用于安装 Node.js 的 Windows、macOS 和 Linux 电脑。

Inspect before
you execute.

这是 Arbitrum One 主网。请使用专用钱包并只存入可承受损失的少量 ETH。计算在本地完成;找到候选结果后提交交易会产生真实 Gas,竞争失败或回滚也可能消耗 Gas。

01Prepare

安装 Node.js 20+,新建一个空目录。

02Install
npm install ethers dotenv
03Configure

将专用钱包信息保存在本地 .env。

Configuration.env
CROLL_RPC_URL=https://arb1.arbitrum.io/rpc
CROLL_CONTRACT_ADDRESS=0x09C1E372efc31c97d9A0e4574DDe6321f311088e
CROLL_PRIVATE_KEY=0xYOUR_DEDICATED_WALLET_PRIVATE_KEY
MAINNET SECURITY

Keep signing local.

私钥不应离开你的设备。不要把 .env 上传到网页、聊天或代码仓库,也不要使用持有大量资产的钱包。运行前请自行检查所有代码。

CPU reference implementationminer.js
const { ethers } = require("ethers");
const { randomBytes } = require("node:crypto");
require("dotenv").config();

const abi = [
  "function miningState() view returns (uint256,bytes32,uint256,uint256,uint256,uint256)" ,
  "function mine(uint256 nonce)"
];

const frames = ["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];
const sleep = () => new Promise(resolve => setImmediate(resolve));
const short = value => value.slice(0, 18) + "…" + value.slice(-12);

function draw({ frame, epoch, remaining, attempts, started, nonce, proof }) {
  const rate = attempts / Math.max((Date.now() - started) / 1000, 0.001);
  process.stdout.write("\x1b[2J\x1b[H");
  console.log("  COMPUTE ROLL  " + frames[frame % frames.length] + "  LIVE HASHING");
  console.log("  ─────────────────────────────────────────────");
  console.log("  Status      HASHING");
  console.log("  Epoch       " + (epoch + 1n) + " / 100000");
  console.log("  Remaining   " + remaining);
  console.log("  Hash rate   " + rate.toFixed(0) + " H/s");
  console.log("  Attempts    " + attempts.toLocaleString() + " hashes");
  console.log("");
  console.log("  Nonce       " + nonce);
  console.log("  Live hash   " + short(proof));
  console.log("");
  console.log("  Ctrl+C safely stops local computation");
}

async function main() {
  const provider = new ethers.JsonRpcProvider(process.env.CROLL_RPC_URL);
  const wallet = new ethers.Wallet(process.env.CROLL_PRIVATE_KEY, provider);
  const contract = new ethers.Contract(process.env.CROLL_CONTRACT_ADDRESS, abi, wallet);
  const [epoch, challenge, target, , reward, remaining] = await contract.miningState();
  let nonce = BigInt("0x" + randomBytes(32).toString("hex"));
  let attempts = 0;
  let frame = 0;
  const started = Date.now();

  while (true) {
    let proof;
    for (let batch = 0; batch < 2048; batch++, nonce++, attempts++) {
      proof = ethers.solidityPackedKeccak256(
        ["bytes32", "address", "uint256"],
        [challenge, wallet.address, nonce]
      );
      if (BigInt(proof) < target) {
        process.stdout.write("\x1b[2J\x1b[H");
        console.log("CANDIDATE FOUND · nonce " + nonce);
        const latest = await contract.miningState();
        if (latest[1] !== challenge || latest[2] !== target) return main();
        const tx = await contract.mine(nonce);
        console.log("Submitted:", tx.hash);
        await tx.wait();
        console.log("Accepted:", ethers.formatEther(reward), "CROLL");
        return main();
      }
    }
    draw({ frame: frame++, epoch, remaining, attempts, started, nonce: nonce.toString(), proof });
    await sleep(); // lets the terminal repaint without changing the hash rule
  }
}

main().catch(console.error);
运行方式

将代码保存为 miner.js,然后在同一目录运行 node miner.js。终端动画只抽样显示哈希,不会逐条打印全部结果,以免输出拖慢计算。代码会在每次链上任务变化后重新读取状态;公开 RPC 可能限流,正式参与可替换为自己的 Arbitrum RPC。

需要验证数据?

所有发行记录都在链上公开。

View network →