github.com/deroproject/derosuite@v2.1.6-1.0.20200307070847-0f2e589c7a2b+incompatible/cmd/derod/miner.go (about) 1 // Copyright 2017-2018 DERO Project. All rights reserved. 2 // Use of this source code in any form is governed by RESEARCH license. 3 // license can be found in the LICENSE file. 4 // GPG: 0F39 E425 8C65 3947 702A 8234 08B2 0360 A03A 9DE8 5 // 6 // 7 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 8 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 9 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 10 // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 11 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 12 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 13 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 14 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 15 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 16 17 package main 18 19 /* 20 import "io" 21 import "os" 22 23 import "fmt" 24 import "bytes" 25 import "bufio" 26 import "strings" 27 import "strconv" 28 import "runtime" 29 import "crypto/sha1" 30 import "encoding/hex" 31 import "encoding/json" 32 import "path/filepath" 33 34 import "github.com/romana/rlog" 35 import "github.com/chzyer/readline" 36 import "github.com/docopt/docopt-go" 37 import log "github.com/sirupsen/logrus" 38 39 import "github.com/deroproject/derosuite/address" 40 import "github.com/deroproject/derosuite/p2pv2" 41 42 43 import "github.com/deroproject/derosuite/config" 44 45 import "github.com/deroproject/derosuite/transaction" 46 47 //import "github.com/deroproject/derosuite/checkpoints" 48 import "github.com/deroproject/derosuite/crypto" 49 import "github.com/deroproject/derosuite/crypto/ringct" 50 import "github.com/deroproject/derosuite/blockchain/rpcserver" 51 */ 52 53 import "time" 54 import "sync" 55 import "math/big" 56 import "crypto/rand" 57 import "sync/atomic" 58 59 //import "encoding/hex" 60 import "encoding/binary" 61 62 import "github.com/deroproject/derosuite/block" 63 import "github.com/deroproject/derosuite/crypto" 64 import "github.com/deroproject/derosuite/globals" 65 import "github.com/deroproject/derosuite/address" 66 import "github.com/deroproject/derosuite/blockchain" 67 import "github.com/deroproject/derosuite/cryptonight" 68 69 // p2p needs to export a varible declaring whether the chain is in syncronising mode 70 71 var counter uint64 = 0 // used to track speeds of current miner 72 73 var mining bool // whether system is mining 74 75 // request block chain template, see if the tip changes, then continously mine 76 func start_miner(chain *blockchain.Blockchain, addr *address.Address, threads int) { 77 78 mining = true 79 counter = 0 80 //tip_counter := 0 81 82 for { 83 //time.Sleep(50 * time.Millisecond) 84 85 if !mining { 86 break 87 } 88 89 if chain.MINING_BLOCK == true { 90 time.Sleep(10 * time.Millisecond) 91 continue 92 } 93 94 cbl, bl := chain.Create_new_miner_block(*addr) 95 96 difficulty := chain.Get_Difficulty_At_Tips(nil, bl.Tips) 97 98 //globals.Logger.Infof("Difficulty of new block is %s", difficulty.String()) 99 // calculate difficulty once 100 // update job from chain 101 wg := sync.WaitGroup{} 102 wg.Add(threads) // add total number of tx as work 103 104 for i := 0; i < threads; i++ { 105 go generate_valid_PoW(chain, 0, cbl, cbl.Bl, difficulty, &wg) // work should be complete in approx 100 ms, on a 12 cpu system, this would add cost of launching 12 g routine per second 106 } 107 wg.Wait() 108 } 109 110 // g 111 } 112 113 // each invoke will be take atleast 250 milliseconds 114 func generate_valid_PoW(chain *blockchain.Blockchain, hf_version uint64, cbl *block.Complete_Block, bl *block.Block, current_difficulty *big.Int, wg *sync.WaitGroup) { 115 var powhash crypto.Hash 116 block_work := bl.GetBlockWork() 117 118 // extra nonce is always at offset 36 and is of length 32 119 var extra_nonce [16]byte 120 rand.Read(extra_nonce[:]) // fill extra nonce with random buffer 121 122 bl.SetExtraNonce(extra_nonce[:]) 123 124 // TODO this time must be replaced by detecting TIP change 125 start := time.Now() 126 //deadline := time.Now().Add(250*time.Millisecond) 127 i := uint32(0) 128 129 nonce_buf := block_work[39 : 39+4] // take last 8 bytes as nonce counter and bruteforce it, since slices are linked, it modifies parent 130 for { 131 //time.Sleep(1000 * time.Millisecond) 132 133 atomic.AddUint64(&counter, 1) 134 135 binary.BigEndian.PutUint32(nonce_buf, i) 136 137 //PoW := crypto.Scrypt_1024_1_1_256(block_work) 138 //PoW := crypto.Keccak256(block_work) 139 PoW := cryptonight.SlowHash(block_work) 140 copy(powhash[:], PoW[:]) 141 142 if blockchain.CheckPowHashBig(powhash, current_difficulty) == true { 143 144 bl.CopyNonceFromBlockWork(block_work) 145 //globals.Logger.Infof("Pow Successfully solved, Submitting block") 146 147 if _, ok := chain.Add_Complete_Block(cbl); ok { 148 globals.Logger.Infof("Block %s successfully accepted diff %s", bl.GetHash(), current_difficulty.String()) 149 chain.P2P_Block_Relayer(cbl, 0) // broadcast block to network ASAP 150 151 break 152 } 153 154 } 155 156 if time.Now().Sub(start) > 250*time.Millisecond { 157 break 158 } 159 i++ 160 161 } 162 163 wg.Done() 164 165 }