Select Git revision
Forked from
NebulousLabs / Sia
14871 commits behind, 5 commits ahead of the upstream repository.
-
David Vorick authored
The thread group now has support for pausing. The thread group also distinctly distinguishes between BeforeStop and AfterStop, which can have key implications depending on the function that is being called.
David Vorick authoredThe thread group now has support for pausing. The thread group also distinctly distinguishes between BeforeStop and AfterStop, which can have key implications depending on the function that is being called.
testminer.go 2.83 KiB
package miner
// testminer.go implements the TestMiner interface, whose primary purpose is
// integration testing.
import (
"bytes"
"encoding/binary"
"errors"
"unsafe"
"github.com/NebulousLabs/Sia/crypto"
"github.com/NebulousLabs/Sia/modules"
"github.com/NebulousLabs/Sia/types"
)
const (
// solveAttempts is the number of times that SolveBlock will try to solve a
// block before giving up.
solveAttempts = 16e3
)
// solveBlock takes a block and a target and tries to solve the block for the
// target. A bool is returned indicating whether the block was successfully
// solved.
func solveBlock(b types.Block, target types.Target) (types.Block, bool) {
// Assemble the header.
merkleRoot := b.MerkleRoot()
header := make([]byte, 80)
copy(header, b.ParentID[:])
binary.LittleEndian.PutUint64(header[40:48], uint64(b.Timestamp))
copy(header[48:], merkleRoot[:])
var nonce uint64
for i := 0; i < solveAttempts; i++ {
id := crypto.HashBytes(header)
if bytes.Compare(target[:], id[:]) >= 0 {
copy(b.Nonce[:], header[32:40])
return b, true
}
*(*uint64)(unsafe.Pointer(&header[32])) = nonce
nonce++
}
return b, false
}
// BlockForWork returns a block that is ready for nonce grinding, along with
// the root hash of the block.
func (m *Miner) BlockForWork() (b types.Block, t types.Target, err error) {
// Check if the wallet is unlocked. If the wallet is unlocked, make sure
// that the miner has a recent address.
if !m.wallet.Unlocked() {
err = modules.ErrLockedWallet
return
}
m.mu.Lock()
defer m.mu.Unlock()
err = m.checkAddress()
if err != nil {
return
}
b = m.blockForWork()
return b, m.persist.Target, nil
}
// AddBlock adds a block to the consensus set.
func (m *Miner) AddBlock() (types.Block, error) {
block, err := m.FindBlock()
if err != nil {
return types.Block{}, err
}
err = m.cs.AcceptBlock(block)
if err != nil {
return types.Block{}, err
}
return block, nil
}
// FindBlock finds at most one block that extends the current blockchain.
func (m *Miner) FindBlock() (types.Block, error) {
var bfw types.Block
var target types.Target
err := func() error {
m.mu.Lock()
defer m.mu.Unlock()
if !m.wallet.Unlocked() {
return modules.ErrLockedWallet
}
err := m.checkAddress()
if err != nil {
return err
}
// Get a block for work.
bfw = m.blockForWork()
target = m.persist.Target
return nil
}()
if err != nil {
return types.Block{}, err
}
block, ok := m.SolveBlock(bfw, target)
if !ok {
return types.Block{}, errors.New("could not solve block using limited hashing power")
}
return block, nil
}
// SolveBlock takes a block and a target and tries to solve the block for the
// target. A bool is returned indicating whether the block was successfully
// solved.
func (m *Miner) SolveBlock(b types.Block, target types.Target) (types.Block, bool) {
return solveBlock(b, target)
}