Parallax가 사용하는 메모리 하드 작업증명. Parallax의 ASERT 기반 난이도, 합의 규칙, 에포크 처리를 갖춘 Ethash 스타일 Hashimoto입니다.
xhash/consensus.go와 Parallax 체인 설정에 반영된 내용.| 항목 | 값 / 동작 | 비고 |
|---|---|---|
| 해시 함수 (씰) | Legacy Keccak-256 | 특정 헤더 필드에 대한 RLP |
| 타깃 매핑 | target = ⌊(2^256−1)/D⌋ | 결과는 ≤ target 이어야 함 |
| MixDigest | 계산된 digest와 같아야 함 | 불일치 ⇒ 유효하지 않은 PoW |
| MTP | 최근 11개의 중앙값 | 강제: Time > MTP(parent); 미래 드리프트 ≤ 300초 |
| 에포크 길이 | 설정에서 정의 (예: 720 블록) | 캐시/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)