From 784839e8e71ef8b1088676269840e5f3c992f45e Mon Sep 17 00:00:00 2001 From: stasatdaglabs <39559713+stasatdaglabs@users.noreply.github.com> Date: Wed, 18 Jul 2018 11:54:17 +0300 Subject: [PATCH] [DEV-40] Update package mining and cpuminer for DAG (#28) * [DEV-65] Renamed BestState to State and GetSnapshot to GetCurrentState. * [DEV-65] Implemented State and SelectedTip, updated dagState (the serializable version of State), and updated State creations. * [DEV-65] Fixed references to GetCurrentState and fixed tests. * [DEV-40] Created a new method AreEquals for comparing hash slices. Updated mining package to work with primitive DAG. * [DEV-65] Renamed State to DAGState, corrected comments, created a new thread-safe method setDAGState, fixed broken references I missed. * [DEV-65] Converted dagState (the object) to dbDAGState, and made it serialize/deserialize into/out of JSON. * [DEV-65] Renamed Txns to Txs and fixed a couple of comments. * [DEV-65] Renamed some more "Txns" and removed some dead code. * [DEV-40] Fixed formatting errors... * [DEV-40] Reworded confusing test failure messages. * [DEV-40] Fixed merge error. * [DEV-40] Fixed style for AreEqual and TestAreEqual. --- dagconfig/daghash/hash.go | 21 ++++++++++++++ dagconfig/daghash/hash_test.go | 52 ++++++++++++++++++++++++++++++++++ mining/cpuminer/cpuminer.go | 6 ++-- mining/mining.go | 2 +- 4 files changed, 77 insertions(+), 4 deletions(-) diff --git a/dagconfig/daghash/hash.go b/dagconfig/daghash/hash.go index fa6a5efb0..ab5f6e94e 100644 --- a/dagconfig/daghash/hash.go +++ b/dagconfig/daghash/hash.go @@ -69,6 +69,27 @@ func (hash *Hash) IsEqual(target *Hash) bool { return *hash == *target } +// AreEqual returns true if both slices contain the same hashes. +// Either slice must not contain duplicates. +func AreEqual(first []Hash, second []Hash) bool { + if len(first) != len(second) { + return false + } + + hashSet := make(map[Hash]bool) + for _, hash := range first { + hashSet[hash] = true + } + + for _, hash := range second { + if !hashSet[hash] { + return false + } + } + + return true +} + // NewHash returns a new Hash from a byte slice. An error is returned if // the number of bytes passed in is not HashSize. func NewHash(newHash []byte) (*Hash, error) { diff --git a/dagconfig/daghash/hash_test.go b/dagconfig/daghash/hash_test.go index b48a627cd..48f882eb3 100644 --- a/dagconfig/daghash/hash_test.go +++ b/dagconfig/daghash/hash_test.go @@ -194,3 +194,55 @@ func TestNewHashFromStr(t *testing.T) { } } } + +// TestAreEqual executes tests against the AreEqual function. +func TestAreEqual(t *testing.T) { + hash0, _ := NewHashFromStr("0000000000000000000000000000000000000000000000000000000000000000") + hash1, _ := NewHashFromStr("1111111111111111111111111111111111111111111111111111111111111111") + hash2, _ := NewHashFromStr("2222222222222222222222222222222222222222222222222222222222222222") + hash3, _ := NewHashFromStr("3333333333333333333333333333333333333333333333333333333333333333") + hashes0To2 := []Hash{*hash0, *hash1, *hash2} + hashes0To2Shifted := []Hash{*hash2, *hash0, *hash1} + hashes1To3 := []Hash{*hash1, *hash2, *hash3} + hashes0To3 := []Hash{*hash0, *hash1, *hash2, *hash3} + + tests := []struct { + name string + first []Hash + second []Hash + expected bool + }{ + { + name: "self-equality", + first: hashes0To2, + second: hashes0To2, + expected: true, + }, + { + name: "same members, different order", + first: hashes0To2, + second: hashes0To2Shifted, + expected: true, + }, + { + name: "same slice length but only some members are equal", + first: hashes0To2, + second: hashes1To3, + expected: false, + }, + { + name: "different slice lengths, one slice containing all the other's members", + first: hashes0To3, + second: hashes0To2, + expected: false, + }, + } + + for _, test := range tests { + result := AreEqual(test.first, test.second) + if result != test.expected { + t.Errorf("unexpected AreEqual result for"+ + " test \"%s\". Expected: %t, got: %t.", test.name, test.expected, result) + } + } +} diff --git a/mining/cpuminer/cpuminer.go b/mining/cpuminer/cpuminer.go index f3184f293..8fdc0e6f6 100644 --- a/mining/cpuminer/cpuminer.go +++ b/mining/cpuminer/cpuminer.go @@ -162,9 +162,9 @@ func (m *CPUMiner) submitBlock(block *btcutil.Block) bool { // a new block, but the check only happens periodically, so it is // possible a block was found and submitted in between. msgBlock := block.MsgBlock() - if !msgBlock.Header.PrevBlock.IsEqual(&m.g.GetDAGState().SelectedTip.Hash) { + if !daghash.AreEqual(msgBlock.Header.PrevBlocks, m.g.GetDAGState().TipHashes) { log.Debugf("Block submitted via CPU miner with previous "+ - "block %s is stale", msgBlock.Header.PrevBlock) + "blocks %s is stale", msgBlock.Header.PrevBlocks) return false } @@ -248,7 +248,7 @@ func (m *CPUMiner) solveBlock(msgBlock *wire.MsgBlock, blockHeight int32, // The current block is stale if the DAG has changed. dagState := m.g.GetDAGState() - if !header.PrevBlock.IsEqual(&dagState.SelectedTip.Hash) { + if !daghash.AreEqual(header.PrevBlocks, dagState.TipHashes) { return false } diff --git a/mining/mining.go b/mining/mining.go index 36ece3eae..fd7e2b04c 100644 --- a/mining/mining.go +++ b/mining/mining.go @@ -764,7 +764,7 @@ mempoolLoop: var msgBlock wire.MsgBlock msgBlock.Header = wire.BlockHeader{ Version: nextBlockVersion, - PrevBlock: dagState.SelectedTip.Hash, + PrevBlocks: dagState.TipHashes, MerkleRoot: *merkles[len(merkles)-1], Timestamp: ts, Bits: reqDifficulty,