diff --git a/mining/hash_test.go b/mining/hash_test.go index fa02923..971c0b6 100644 --- a/mining/hash_test.go +++ b/mining/hash_test.go @@ -99,3 +99,53 @@ func TestHeaderMiningHash_Good_NonceIgnored(t *testing.T) { block1.Nonce, h1, block2.Nonce, h2) } } + +func TestCheckNonce_Good_LowDifficulty(t *testing.T) { + // Build a genesis block and compute its header hash. + rawTx := testnetGenesisRawTx() + dec := wire.NewDecoder(bytes.NewReader(rawTx)) + minerTx := wire.DecodeTransaction(dec) + if dec.Err() != nil { + t.Fatalf("decode genesis tx: %v", dec.Err()) + } + + block := types.Block{ + BlockHeader: testnetGenesisHeader(), + MinerTx: minerTx, + } + headerHash := HeaderMiningHash(&block) + + // With difficulty=1, any nonce should produce a valid solution. + ok, err := CheckNonce(headerHash, 0, 1) + if err != nil { + t.Fatalf("CheckNonce: %v", err) + } + if !ok { + t.Error("CheckNonce should pass with difficulty=1") + } +} + +func TestCheckNonce_Good_HighDifficulty(t *testing.T) { + // With extremely high difficulty, nonce=0 should NOT produce a valid solution. + rawTx := testnetGenesisRawTx() + dec := wire.NewDecoder(bytes.NewReader(rawTx)) + minerTx := wire.DecodeTransaction(dec) + if dec.Err() != nil { + t.Fatalf("decode genesis tx: %v", dec.Err()) + } + + block := types.Block{ + BlockHeader: testnetGenesisHeader(), + MinerTx: minerTx, + } + headerHash := HeaderMiningHash(&block) + + // With difficulty = max uint64, virtually no hash passes. + ok, err := CheckNonce(headerHash, 0, ^uint64(0)) + if err != nil { + t.Fatalf("CheckNonce: %v", err) + } + if ok { + t.Error("CheckNonce should fail with max difficulty") + } +} diff --git a/mining/miner_test.go b/mining/miner_test.go index ed854da..7e2126e 100644 --- a/mining/miner_test.go +++ b/mining/miner_test.go @@ -290,6 +290,38 @@ func (f *failingSubmitter) SubmitBlock(hexBlob string) error { return fmt.Errorf("connection refused") } +func TestMiner_Start_Good_OnNewTemplate(t *testing.T) { + var tmplHeight uint64 + var tmplDiff uint64 + + mock := &mockProvider{ + templates: []*rpc.BlockTemplateResponse{ + {Difficulty: "42", Height: 300, BlockTemplateBlob: hex.EncodeToString(minimalBlockBlob(t)), Status: "OK"}, + }, + infos: []*rpc.DaemonInfo{{Height: 300}}, + } + + cfg := Config{ + DaemonURL: "http://localhost:46941", + WalletAddr: "iTHNtestaddr", + PollInterval: 100 * time.Millisecond, + Provider: mock, + OnNewTemplate: func(height uint64, difficulty uint64) { + tmplHeight = height + tmplDiff = difficulty + }, + } + m := NewMiner(cfg) + + ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) + defer cancel() + + _ = m.Start(ctx) + + assert.Equal(t, uint64(300), tmplHeight) + assert.Equal(t, uint64(42), tmplDiff) +} + func TestMiner_Start_Bad_SubmitFails(t *testing.T) { mock := &failingSubmitter{ mockProvider: mockProvider{