<commit_before>package miner

import (
	"bytes"
	"math/rand" // We should probably switch to crypto/rand, but we should use benchmarks first.

	"github.com/NebulousLabs/Sia/build"
	"github.com/NebulousLabs/Sia/crypto"
	"github.com/NebulousLabs/Sia/types"
)

// Creates a block that is ready for nonce grinding.
func (m *Miner) blockForWork() (b types.Block) {
	// Fill out the block with potentially ready values.
	b = types.Block{
		ParentID:     m.parent,
		Timestamp:    types.CurrentTimestamp(),
		Nonce:        uint64(rand.Int()),
		Transactions: m.transactions,
	}

	// Calculate the subsidy and create the miner payout.
	height, exists := m.state.HeightOfBlock(m.parent)
	if !exists {
		if build.DEBUG {
			panic("parent is not in state?")
		}
		return
	}
	subsidy := types.CalculateCoinbase(height + 1)
	for _, txn := range m.transactions {
		for _, fee := range txn.MinerFees {
			subsidy = subsidy.Add(fee)
		}
	}
	output := types.SiacoinOutput{Value: subsidy, UnlockHash: m.address}
	b.MinerPayouts = []types.SiacoinOutput{output}

	// If we've got a time earlier than the earliest legal timestamp, set the
	// timestamp equal to the earliest legal timestamp.
	if b.Timestamp < m.earliestTimestamp {
		b.Timestamp = m.earliestTimestamp
	}

	return
}

// mine attempts to generate blocks, and will run until desiredThreads is
// changd to be lower than `myThread`, which is set at the beginning of the
// function.
//
// The threading is fragile. Edit with caution!
func (m *Miner) threadedMine() {
	// Increment the number of threads running, because this thread is spinning
	// up. Also grab a number that will tell us when to shut down.
	m.mu.Lock()
	m.runningThreads++
	myThread := m.runningThreads
	m.mu.Unlock()

	// Try to solve a block repeatedly.
	for {
		// Grab the number of threads that are supposed to be running.
		m.mu.RLock()
		desiredThreads := m.desiredThreads
		m.mu.RUnlock()

		// If we are allowed to be running, mine a block, otherwise shut down.
		if desiredThreads >= myThread {
			// Grab the necessary variables for mining, and then attempt to
			// mine a block.
			m.mu.RLock()
			bfw := m.blockForWork()
			target := m.target
			iterations := m.iterationsPerAttempt
			m.mu.RUnlock()
			m.solveBlock(bfw, target, iterations)
		} else {
			m.mu.Lock()
			// Need to check the mining status again, something might have
			// changed while waiting for the lock.
			if desiredThreads < myThread {
				m.runningThreads--
				m.mu.Unlock()
				return
			}
			m.mu.Unlock()
		}
	}
}

func fastCheckTarget(target types.Target, b types.Block, bRoot crypto.Hash) bool {
	id := crypto.HashAll(
		b.ParentID,
		b.Nonce,
		bRoot,
	)
	return bytes.Compare(target[:], id[:]) >= 0
}

// solveBlock takes a block, target, and number of iterations as input and
// tries to find a block that meets the target. This function can take a long
// time to complete, and should not be called with a lock.
func (m *Miner) solveBlock(blockForWork types.Block, target types.Target, iterations uint64) (b types.Block, solved bool, err error) {
	// solveBlock could operate on a pointer, but it's not strictly necessary
	// and it makes calling weirder/more opaque.
	b = blockForWork
	bRoot := b.MerkleRoot()

	// Iterate through a bunch of nonces (from a random starting point) and try
	// to find a winnning solution.
	for maxNonce := b.Nonce + iterations; b.Nonce != maxNonce; b.Nonce++ {
		if fastCheckTarget(target, b, bRoot) {
			err = m.state.AcceptBlock(b)
			if err != nil {
				print("mined a block, but with an error: ")
				println(err.Error())
				m.tpool.PurgeTransactionPool()
			}
			solved = true
			if build.Release != "testing" {
				println("Found a block! If the block is not orphaned, you will receive the reward after 50 more blocks have been mined. Blocks are only orphaned when two miners find a block at the same time, as only 1 block can be accepted.")
			}

			// Grab a new address for the miner.
			m.mu.Lock()
			var addr types.UnlockHash
			addr, _, err = m.wallet.CoinAddress()
			if err == nil { // Special case: only update the address if there was no error.
				m.address = addr
			}
			m.mu.Unlock()
			return
		}
	}

	return
}

// FindBlock will attempt to solve a block and add it to the state. While less
// efficient than StartMining, it is guaranteed to find at most one block.
func (m *Miner) FindBlock() (types.Block, bool, error) {<commit_msg>nicer miner messages<commit_after>package miner

import (
	"bytes"
	"math/rand" // We should probably switch to crypto/rand, but we should use benchmarks first.

	"github.com/NebulousLabs/Sia/build"
	"github.com/NebulousLabs/Sia/crypto"
	"github.com/NebulousLabs/Sia/types"
)

// Creates a block that is ready for nonce grinding.
func (m *Miner) blockForWork() (b types.Block) {
	// Fill out the block with potentially ready values.
	b = types.Block{
		ParentID:     m.parent,
		Timestamp:    types.CurrentTimestamp(),
		Nonce:        uint64(rand.Int()),
		Transactions: m.transactions,
	}

	// Calculate the subsidy and create the miner payout.
	height, exists := m.state.HeightOfBlock(m.parent)
	if !exists {
		if build.DEBUG {
			panic("parent is not in state?")
		}
		return
	}
	subsidy := types.CalculateCoinbase(height + 1)
	for _, txn := range m.transactions {
		for _, fee := range txn.MinerFees {
			subsidy = subsidy.Add(fee)
		}
	}
	output := types.SiacoinOutput{Value: subsidy, UnlockHash: m.address}
	b.MinerPayouts = []types.SiacoinOutput{output}

	// If we've got a time earlier than the earliest legal timestamp, set the
	// timestamp equal to the earliest legal timestamp.
	if b.Timestamp < m.earliestTimestamp {
		b.Timestamp = m.earliestTimestamp
	}

	return
}

// mine attempts to generate blocks, and will run until desiredThreads is
// changd to be lower than `myThread`, which is set at the beginning of the
// function.
//
// The threading is fragile. Edit with caution!
func (m *Miner) threadedMine() {
	// Increment the number of threads running, because this thread is spinning
	// up. Also grab a number that will tell us when to shut down.
	m.mu.Lock()
	m.runningThreads++
	myThread := m.runningThreads
	m.mu.Unlock()

	// Try to solve a block repeatedly.
	for {
		// Grab the number of threads that are supposed to be running.
		m.mu.RLock()
		desiredThreads := m.desiredThreads
		m.mu.RUnlock()

		// If we are allowed to be running, mine a block, otherwise shut down.
		if desiredThreads >= myThread {
			// Grab the necessary variables for mining, and then attempt to
			// mine a block.
			m.mu.RLock()
			bfw := m.blockForWork()
			target := m.target
			iterations := m.iterationsPerAttempt
			m.mu.RUnlock()
			m.solveBlock(bfw, target, iterations)
		} else {
			m.mu.Lock()
			// Need to check the mining status again, something might have
			// changed while waiting for the lock.
			if desiredThreads < myThread {
				m.runningThreads--
				m.mu.Unlock()
				return
			}
			m.mu.Unlock()
		}
	}
}

func fastCheckTarget(target types.Target, b types.Block, bRoot crypto.Hash) bool {
	id := crypto.HashAll(
		b.ParentID,
		b.Nonce,
		bRoot,
	)
	return bytes.Compare(target[:], id[:]) >= 0
}

// solveBlock takes a block, target, and number of iterations as input and
// tries to find a block that meets the target. This function can take a long
// time to complete, and should not be called with a lock.
func (m *Miner) solveBlock(blockForWork types.Block, target types.Target, iterations uint64) (b types.Block, solved bool, err error) {
	// solveBlock could operate on a pointer, but it's not strictly necessary
	// and it makes calling weirder/more opaque.
	b = blockForWork
	bRoot := b.MerkleRoot()

	// Iterate through a bunch of nonces (from a random starting point) and try
	// to find a winnning solution.
	for maxNonce := b.Nonce + iterations; b.Nonce != maxNonce; b.Nonce++ {
		if fastCheckTarget(target, b, bRoot) {
			err = m.state.AcceptBlock(b)
			if err != nil {
				println("Mined a bad block " + err.Error())
				m.tpool.PurgeTransactionPool()
			}
			solved = true
			if build.Release != "testing" {
				println("Found a block! Reward will be received in 50 blocks.")
			}

			// Grab a new address for the miner.
			m.mu.Lock()
			var addr types.UnlockHash
			addr, _, err = m.wallet.CoinAddress()
			if err == nil { // Special case: only update the address if there was no error.
				m.address = addr
			}
			m.mu.Unlock()
			return
		}
	}

	return
}

// FindBlock will attempt to solve a block and add it to the state. While less
// efficient than StartMining, it is guaranteed to find at most one block.
func (m *Miner) FindBlock() (types.Block, bool, error) {
{'fraction_non_alphanumeric': 0.10653359637925032, 'fraction_numerical': 0.0019728443773935245, 'mean_word_length': 3.183495145631068, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6097447', 'n_tokens_mistral': 3033, 'n_tokens_neox': 2768, 'n_words': 1009}