Parallax 所用的内存难解工作量证明。Ethash 风格的 Hashimoto,结合 Parallax 基于 ASERT 的难度、共识规则与 epoch 处理。
xhash/consensus.go 与 Parallax 链配置。| 项目 | 数值 / 行为 | 说明 |
|---|---|---|
| 哈希函数(seal) | Legacy Keccak-256 | 对特定区块头字段进行 RLP 编码 |
| 目标映射 | target = ⌊(2^256−1)/D⌋ | 结果必须 ≤ target |
| MixDigest | 必须等于计算所得的摘要 | 不一致 ⇒ PoW 无效 |
| MTP | 最近 11 个时间戳的中位数 | 强制:Time > MTP(parent);未来漂移 ≤ 300 秒 |
| Epoch 长度 | 由配置定义(例如 720 区块) | 决定 cache/DAG 重建的频率 |
| 难度算法 | ASERT(基于锚点的逐区块算法) | aserti3-2d;共识负责计算 D,XHash 通过 PoW 强制执行 |
SealHash(header):
enc = [
header.ParentHash,
header.Coinbase,
header.Root,
header.TxHash,
header.ReceiptHash,
header.Bloom,
header.Difficulty,
header.Number,
header.GasLimit,
header.GasUsed,
header.Time,
header.Extra,
header.EpochStartTime,
]
if header.BaseFee != nil:
enc.append(header.BaseFee)
return keccak256(rlp.encode(enc))
mine(header, cacheOrDataset):
target = floor((2^256 - 1) / header.Difficulty)
nonce = random64()
loop:
(mix, res) = hashimoto(cacheOrDataset, SealHash(header), nonce)
if mix == header.MixDigest and Big(res) <= target:
return nonce
nonce = (nonce + 1) mod 2^64
verifySeal(h):
require(h.Difficulty > 0)
if fulldag:
(mix, res) = hashimotoFull(dataset(epoch(h.Number)), SealHash(h), h.Nonce)
else:
(mix, res) = hashimotoLight(datasetSize(h.Number), cache(epoch(h.Number)), SealHash(h), h.Nonce)
require(mix == h.MixDigest)
target = floor((2^256 - 1) / h.Difficulty)
require(Big(res) <= target)
if newEpoch(height):
regenerate cache
if mining full: regenerate dataset
verifyDifficulty(h, parent, anchor):
expected = CalcAsertDifficulty(config, anchor, parent, h)
require(h.Difficulty == expected)