gitlab.com/jokerrs1/Sia@v1.3.2/modules/miner/testminer.go (about) 1 package miner 2 3 // testminer.go implements the TestMiner interface, whose primary purpose is 4 // integration testing. 5 6 import ( 7 "bytes" 8 "encoding/binary" 9 "errors" 10 "unsafe" 11 12 "github.com/NebulousLabs/Sia/crypto" 13 "github.com/NebulousLabs/Sia/modules" 14 "github.com/NebulousLabs/Sia/types" 15 ) 16 17 const ( 18 // solveAttempts is the number of times that SolveBlock will try to solve a 19 // block before giving up. 20 solveAttempts = 16e3 21 ) 22 23 // solveBlock takes a block and a target and tries to solve the block for the 24 // target. A bool is returned indicating whether the block was successfully 25 // solved. 26 func solveBlock(b types.Block, target types.Target) (types.Block, bool) { 27 // Assemble the header. 28 merkleRoot := b.MerkleRoot() 29 header := make([]byte, 80) 30 copy(header, b.ParentID[:]) 31 binary.LittleEndian.PutUint64(header[40:48], uint64(b.Timestamp)) 32 copy(header[48:], merkleRoot[:]) 33 34 var nonce uint64 35 for i := 0; i < solveAttempts; i++ { 36 id := crypto.HashBytes(header) 37 if bytes.Compare(target[:], id[:]) >= 0 { 38 copy(b.Nonce[:], header[32:40]) 39 return b, true 40 } 41 *(*uint64)(unsafe.Pointer(&header[32])) = nonce 42 nonce++ 43 } 44 return b, false 45 } 46 47 // BlockForWork returns a block that is ready for nonce grinding, along with 48 // the root hash of the block. 49 func (m *Miner) BlockForWork() (b types.Block, t types.Target, err error) { 50 // Check if the wallet is unlocked. If the wallet is unlocked, make sure 51 // that the miner has a recent address. 52 if !m.wallet.Unlocked() { 53 err = modules.ErrLockedWallet 54 return 55 } 56 m.mu.Lock() 57 defer m.mu.Unlock() 58 err = m.checkAddress() 59 if err != nil { 60 return 61 } 62 63 b = m.blockForWork() 64 return b, m.persist.Target, nil 65 } 66 67 // AddBlock adds a block to the consensus set. 68 func (m *Miner) AddBlock() (types.Block, error) { 69 block, err := m.FindBlock() 70 if err != nil { 71 return types.Block{}, err 72 } 73 err = m.cs.AcceptBlock(block) 74 if err != nil { 75 return types.Block{}, err 76 } 77 return block, nil 78 } 79 80 // FindBlock finds at most one block that extends the current blockchain. 81 func (m *Miner) FindBlock() (types.Block, error) { 82 var bfw types.Block 83 var target types.Target 84 err := func() error { 85 m.mu.Lock() 86 defer m.mu.Unlock() 87 88 if !m.wallet.Unlocked() { 89 return modules.ErrLockedWallet 90 } 91 err := m.checkAddress() 92 if err != nil { 93 return err 94 } 95 96 // Get a block for work. 97 bfw = m.blockForWork() 98 target = m.persist.Target 99 return nil 100 }() 101 if err != nil { 102 return types.Block{}, err 103 } 104 105 block, ok := m.SolveBlock(bfw, target) 106 if !ok { 107 return types.Block{}, errors.New("could not solve block using limited hashing power") 108 } 109 return block, nil 110 } 111 112 // SolveBlock takes a block and a target and tries to solve the block for the 113 // target. A bool is returned indicating whether the block was successfully 114 // solved. 115 func (m *Miner) SolveBlock(b types.Block, target types.Target) (types.Block, bool) { 116 return solveBlock(b, target) 117 }