diff options
Diffstat (limited to 'consensus')
-rw-r--r-- | consensus/clique/clique.go | 5 | ||||
-rw-r--r-- | consensus/consensus.go | 3 | ||||
-rw-r--r-- | consensus/ethash/consensus.go | 29 | ||||
-rw-r--r-- | consensus/ethash/ethash_test.go | 11 | ||||
-rw-r--r-- | consensus/ethash/sealer.go | 4 | ||||
-rw-r--r-- | consensus/ethash/sealer_test.go | 2 |
6 files changed, 45 insertions, 9 deletions
diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index 085944701..3730c91f6 100644 --- a/consensus/clique/clique.go +++ b/consensus/clique/clique.go @@ -673,6 +673,11 @@ func CalcDifficulty(snap *Snapshot, signer common.Address) *big.Int { return new(big.Int).Set(diffNoTurn) } +// SealHash returns the hash of a block prior to it being sealed. +func (c *Clique) SealHash(header *types.Header) common.Hash { + return sigHash(header) +} + // Close implements consensus.Engine. It's a noop for clique as there is are no background threads. func (c *Clique) Close() error { return nil diff --git a/consensus/consensus.go b/consensus/consensus.go index 827175444..27799f13c 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -90,6 +90,9 @@ type Engine interface { // seal place on top. Seal(chain ChainReader, block *types.Block, stop <-chan struct{}) (*types.Block, error) + // SealHash returns the hash of a block prior to it being sealed. + SealHash(header *types.Header) common.Hash + // CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty // that a new block should have. CalcDifficulty(chain ChainReader, time uint64, parent *types.Header) *big.Int diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go index 86fd997ae..259cc5056 100644 --- a/consensus/ethash/consensus.go +++ b/consensus/ethash/consensus.go @@ -31,7 +31,9 @@ import ( "github.com/ethereum/go-ethereum/consensus/misc" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto/sha3" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rlp" ) // Ethash proof-of-work protocol constants. @@ -495,7 +497,7 @@ func (ethash *Ethash) verifySeal(chain consensus.ChainReader, header *types.Head if fulldag { dataset := ethash.dataset(number, true) if dataset.generated() { - digest, result = hashimotoFull(dataset.dataset, header.HashNoNonce().Bytes(), header.Nonce.Uint64()) + digest, result = hashimotoFull(dataset.dataset, ethash.SealHash(header).Bytes(), header.Nonce.Uint64()) // Datasets are unmapped in a finalizer. Ensure that the dataset stays alive // until after the call to hashimotoFull so it's not unmapped while being used. @@ -513,7 +515,7 @@ func (ethash *Ethash) verifySeal(chain consensus.ChainReader, header *types.Head if ethash.config.PowMode == ModeTest { size = 32 * 1024 } - digest, result = hashimotoLight(size, cache.cache, header.HashNoNonce().Bytes(), header.Nonce.Uint64()) + digest, result = hashimotoLight(size, cache.cache, ethash.SealHash(header).Bytes(), header.Nonce.Uint64()) // 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. @@ -552,6 +554,29 @@ func (ethash *Ethash) Finalize(chain consensus.ChainReader, header *types.Header return types.NewBlock(header, txs, uncles, receipts), nil } +// SealHash returns the hash of a block prior to it being sealed. +func (ethash *Ethash) SealHash(header *types.Header) (hash common.Hash) { + hasher := sha3.NewKeccak256() + + rlp.Encode(hasher, []interface{}{ + header.ParentHash, + header.UncleHash, + header.Coinbase, + header.Root, + header.TxHash, + header.ReceiptHash, + header.Bloom, + header.Difficulty, + header.Number, + header.GasLimit, + header.GasUsed, + header.Time, + header.Extra, + }) + hasher.Sum(hash[:0]) + return hash +} + // Some weird constants to avoid constant memory allocs for them. var ( big8 = big.NewInt(8) diff --git a/consensus/ethash/ethash_test.go b/consensus/ethash/ethash_test.go index 87ac17c2b..b190d63d6 100644 --- a/consensus/ethash/ethash_test.go +++ b/consensus/ethash/ethash_test.go @@ -94,6 +94,7 @@ func TestRemoteSealer(t *testing.T) { } header := &types.Header{Number: big.NewInt(1), Difficulty: big.NewInt(100)} block := types.NewBlockWithHeader(header) + sealhash := ethash.SealHash(header) // Push new work. ethash.Seal(nil, block, nil) @@ -102,27 +103,29 @@ func TestRemoteSealer(t *testing.T) { work [3]string err error ) - if work, err = api.GetWork(); err != nil || work[0] != block.HashNoNonce().Hex() { + if work, err = api.GetWork(); err != nil || work[0] != sealhash.Hex() { t.Error("expect to return a mining work has same hash") } - if res := api.SubmitWork(types.BlockNonce{}, block.HashNoNonce(), common.Hash{}); res { + if res := api.SubmitWork(types.BlockNonce{}, sealhash, common.Hash{}); res { t.Error("expect to return false when submit a fake solution") } // Push new block with same block number to replace the original one. header = &types.Header{Number: big.NewInt(1), Difficulty: big.NewInt(1000)} block = types.NewBlockWithHeader(header) + sealhash = ethash.SealHash(header) ethash.Seal(nil, block, nil) - if work, err = api.GetWork(); err != nil || work[0] != block.HashNoNonce().Hex() { + if work, err = api.GetWork(); err != nil || work[0] != sealhash.Hex() { t.Error("expect to return the latest pushed work") } // Push block with higher block number. newHead := &types.Header{Number: big.NewInt(2), Difficulty: big.NewInt(100)} newBlock := types.NewBlockWithHeader(newHead) + newSealhash := ethash.SealHash(newHead) ethash.Seal(nil, newBlock, nil) - if res := api.SubmitWork(types.BlockNonce{}, block.HashNoNonce(), common.Hash{}); res { + if res := api.SubmitWork(types.BlockNonce{}, newSealhash, common.Hash{}); res { t.Error("expect to return false when submit a stale solution") } } diff --git a/consensus/ethash/sealer.go b/consensus/ethash/sealer.go index c3b2c86d1..a458c60f6 100644 --- a/consensus/ethash/sealer.go +++ b/consensus/ethash/sealer.go @@ -111,7 +111,7 @@ func (ethash *Ethash) mine(block *types.Block, id int, seed uint64, abort chan s // Extract some data from the header var ( header = block.Header() - hash = header.HashNoNonce().Bytes() + hash = ethash.SealHash(header).Bytes() target = new(big.Int).Div(two256, header.Difficulty) number = header.Number.Uint64() dataset = ethash.dataset(number, false) @@ -213,7 +213,7 @@ func (ethash *Ethash) remote(notify []string) { // result[1], 32 bytes hex encoded seed hash used for DAG // result[2], 32 bytes hex encoded boundary condition ("target"), 2^256/difficulty makeWork := func(block *types.Block) { - hash := block.HashNoNonce() + hash := ethash.SealHash(block.Header()) currentWork[0] = hash.Hex() currentWork[1] = common.BytesToHash(SeedHash(block.NumberU64())).Hex() diff --git a/consensus/ethash/sealer_test.go b/consensus/ethash/sealer_test.go index 6c7157a5a..d1b66f9cf 100644 --- a/consensus/ethash/sealer_test.go +++ b/consensus/ethash/sealer_test.go @@ -51,7 +51,7 @@ func TestRemoteNotify(t *testing.T) { ethash.Seal(nil, block, nil) select { case work := <-sink: - if want := header.HashNoNonce().Hex(); work[0] != want { + if want := ethash.SealHash(header).Hex(); work[0] != want { t.Errorf("work packet hash mismatch: have %s, want %s", work[0], want) } if want := common.BytesToHash(SeedHash(header.Number.Uint64())).Hex(); work[1] != want { |