diff --git a/consensus/consensus.go b/consensus/consensus.go index 50323edfa4..e442a2e46c 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -77,6 +77,8 @@ type Engine interface { // DeltaLogS returns the log of the entropy delta for a chain since its prior coincidence DeltaLogS(header *types.Header) *big.Int + ComputePowLight(header *types.Header) (mixHash, powHash common.Hash) + // VerifyHeader checks whether a header conforms to the consensus rules of a // given engine. Verifying the seal may be done optionally here, or explicitly // via the VerifySeal method. @@ -137,6 +139,15 @@ type Engine interface { Close() error } +func TargetToDifficulty(target *big.Int) *big.Int { + big2e256 := new(big.Int).Exp(big.NewInt(2), big.NewInt(256), big.NewInt(0)) // 2^256 + return new(big.Int).Div(big2e256, target) +} + +func DifficultyToTarget(difficulty *big.Int) *big.Int { + return TargetToDifficulty(difficulty) +} + // PoW is a consensus engine based on proof-of-work. type PoW interface { Engine diff --git a/consensus/progpow/consensus.go b/consensus/progpow/consensus.go index 6767e4cbdc..f97864e881 100644 --- a/consensus/progpow/consensus.go +++ b/consensus/progpow/consensus.go @@ -383,6 +383,31 @@ func (progpow *Progpow) IsDomCoincident(chain consensus.ChainHeaderReader, heade return order < common.NodeLocation.Context() } +func (progpow *Progpow) ComputePowLight(header *types.Header) (mixHash, powHash common.Hash) { + powLight := func(size uint64, cache []uint32, hash []byte, nonce uint64, blockNumber uint64) ([]byte, []byte) { + ethashCache := progpow.cache(blockNumber) + if ethashCache.cDag == nil { + cDag := make([]uint32, progpowCacheWords) + generateCDag(cDag, ethashCache.cache, blockNumber/epochLength) + ethashCache.cDag = cDag + } + return progpowLight(size, cache, hash, nonce, blockNumber, ethashCache.cDag) + } + cache := progpow.cache(header.NumberU64()) + size := datasetSize(header.NumberU64()) + digest, result := powLight(size, cache.cache, header.SealHash().Bytes(), header.NonceU64(), header.NumberU64(common.ZONE_CTX)) + mixHash = common.BytesToHash(digest) + powHash = common.BytesToHash(result) + header.PowDigest.Store(mixHash) + header.PowHash.Store(powHash) + + // Caches are unmapped in a finalizer. Ensure that the cache stays alive + // until after the call to hashimotoLight so it's not unmapped while being used. + runtime.KeepAlive(cache) + + return mixHash, powHash +} + // verifySeal checks whether a block satisfies the PoW difficulty requirements, // either using the usual progpow cache for it, or alternatively using a full DAG // to make remote mining fast. @@ -404,28 +429,10 @@ func (progpow *Progpow) verifySeal(header *types.Header) (common.Hash, error) { return common.Hash{}, errInvalidDifficulty } // Check progpow - powHash := header.PowHash.Load() mixHash := header.PowDigest.Load() + powHash := header.PowHash.Load() if powHash == nil || mixHash == nil { - powLight := func(size uint64, cache []uint32, hash []byte, nonce uint64, blockNumber uint64) ([]byte, []byte) { - ethashCache := progpow.cache(blockNumber) - if ethashCache.cDag == nil { - cDag := make([]uint32, progpowCacheWords) - generateCDag(cDag, ethashCache.cache, blockNumber/epochLength) - ethashCache.cDag = cDag - } - return progpowLight(size, cache, hash, nonce, blockNumber, ethashCache.cDag) - } - cache := progpow.cache(header.NumberU64()) - size := datasetSize(header.NumberU64()) - digest, result := powLight(size, cache.cache, header.SealHash().Bytes(), header.NonceU64(), header.NumberU64(common.ZONE_CTX)) - mixHash = common.BytesToHash(digest) - powHash = common.BytesToHash(result) - header.PowDigest.Store(mixHash) - header.PowHash.Store(powHash) - // Caches are unmapped in a finalizer. Ensure that the cache stays alive - // until after the call to hashimotoLight so it's not unmapped while being used. - runtime.KeepAlive(cache) + mixHash, powHash = progpow.ComputePowLight(header) } // Verify the calculated values against the ones provided in the header if !bytes.Equal(header.MixHash().Bytes(), mixHash.(common.Hash).Bytes()) { @@ -519,11 +526,3 @@ func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header } state.AddBalance(coinbase, reward) } - -func TargetToDifficulty(target *big.Int) *big.Int { - return new(big.Int).Div(big2e256, target) -} - -func DifficultyToTarget(difficulty *big.Int) *big.Int { - return TargetToDifficulty(difficulty) -} diff --git a/consensus/progpow/sealer.go b/consensus/progpow/sealer.go index 7137d8551e..1f09504a8e 100644 --- a/consensus/progpow/sealer.go +++ b/consensus/progpow/sealer.go @@ -155,7 +155,7 @@ search: header = types.CopyHeader(header) header.SetNonce(types.EncodeNonce(nonce)) hashBytes := common.BytesToHash(digest) - header.SetMixHash(&hashBytes) + header.SetMixHash(hashBytes) found <- header break search } diff --git a/core/types/block.go b/core/types/block.go index 36a15e0abe..07309a0549 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -478,9 +478,9 @@ func (h *Header) SetExtra(val []byte) { copy(h.extra, val) } } -func (h *Header) SetMixHash(val *common.Hash) { +func (h *Header) SetMixHash(val common.Hash) { h.hash = atomic.Value{} // clear hash cache - h.mixHash = *val + h.mixHash = val } func (h *Header) SetNonce(val BlockNonce) { h.hash = atomic.Value{} // clear hash cache, but NOT sealHash diff --git a/core/types/gen_header_json.go b/core/types/gen_header_json.go index f2c54c3626..5fcdd0860d 100644 --- a/core/types/gen_header_json.go +++ b/core/types/gen_header_json.go @@ -16,28 +16,28 @@ var _ = (*headerMarshaling)(nil) // MarshalJSON marshals as JSON. func (h Header) MarshalJSON() ([]byte, error) { var enc struct { - ParentHash []common.Hash `json:"parentHash" gencodec:"required"` - UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"` - Coinbase common.Address `json:"miner" gencodec:"required"` - Root common.Hash `json:"stateRoot" gencodec:"required"` - TxHash common.Hash `json:"transactionsRoot" gencodec:"required"` - EtxHash common.Hash `json:"extTransactionsRoot" gencodec:"required"` - EtxRollupHash common.Hash `json:"extRollupRoot" gencodec:"required"` - ManifestHash []common.Hash `json:"manifestHash" gencodec:"required"` - ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"` - Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"` - ParentEntropy []*hexutil.Big `json:"parentEntropy" gencodec:"required"` - ParentDeltaS []*hexutil.Big `json:"parentDeltaS" gencodec:"required"` - Number []*hexutil.Big `json:"number" gencodec:"required"` - GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"` - GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"` - BaseFee *hexutil.Big `json:"baseFeePerGas" gencodec:"required"` - Location hexutil.Bytes `json:"location" gencodec:"required"` - Time hexutil.Uint64 `json:"timestamp" gencodec:"required"` - Extra hexutil.Bytes `json:"extraData" gencodec:"required"` - MixHash common.Hash `json:"mixHash" gencodec:"required"` - Nonce BlockNonce `json:"nonce"` - Hash common.Hash `json:"hash"` + ParentHash []common.Hash `json:"parentHash" gencodec:"required"` + UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"` + Coinbase common.Address `json:"miner" gencodec:"required"` + Root common.Hash `json:"stateRoot" gencodec:"required"` + TxHash common.Hash `json:"transactionsRoot" gencodec:"required"` + EtxHash common.Hash `json:"extTransactionsRoot" gencodec:"required"` + EtxRollupHash common.Hash `json:"extRollupRoot" gencodec:"required"` + ManifestHash []common.Hash `json:"manifestHash" gencodec:"required"` + ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"` + Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"` + ParentEntropy []*hexutil.Big `json:"parentEntropy" gencodec:"required"` + ParentDeltaS []*hexutil.Big `json:"parentDeltaS" gencodec:"required"` + Number []*hexutil.Big `json:"number" gencodec:"required"` + GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"` + GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"` + BaseFee *hexutil.Big `json:"baseFeePerGas" gencodec:"required"` + Location hexutil.Bytes `json:"location" gencodec:"required"` + Time hexutil.Uint64 `json:"timestamp" gencodec:"required"` + Extra hexutil.Bytes `json:"extraData" gencodec:"required"` + MixHash common.Hash `json:"mixHash" gencodec:"required"` + Nonce BlockNonce `json:"nonce"` + Hash common.Hash `json:"hash"` } // Initialize the enc struct enc.ParentEntropy = make([]*hexutil.Big, common.HierarchyDepth) @@ -194,7 +194,7 @@ func (h *Header) UnmarshalJSON(input []byte) error { } h.SetTime(uint64(dec.Time)) h.SetExtra(dec.Extra) - h.SetMixHash(dec.MixHash) + h.SetMixHash(*dec.MixHash) h.SetNonce(dec.Nonce) return nil }