172 lines
5.1 KiB
Go
172 lines
5.1 KiB
Go
// Copyright 2017-2021 DERO Project. All rights reserved.
|
|
// Use of this source code in any form is governed by RESEARCH license.
|
|
// license can be found in the LICENSE file.
|
|
// GPG: 0F39 E425 8C65 3947 702A 8234 08B2 0360 A03A 9DE8
|
|
//
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
|
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
package main
|
|
|
|
//import "io"
|
|
//import "os"
|
|
|
|
//import "fmt"
|
|
//import "bytes"
|
|
//import "bufio"
|
|
//import "strings"
|
|
//import "strconv"
|
|
//import "runtime"
|
|
//import "crypto/sha1"
|
|
//import "encoding/hex"
|
|
//import "encoding/json"
|
|
//import "path/filepath"
|
|
|
|
/*
|
|
import "github.com/romana/rlog"
|
|
import "github.com/chzyer/readline"
|
|
import "github.com/docopt/docopt-go"
|
|
import log "github.com/sirupsen/logrus"
|
|
|
|
import "github.com/deroproject/derohe/address"
|
|
//import "github.com/deroproject/derosuite/p2pv2"
|
|
|
|
|
|
import "github.com/deroproject/derohe/config"
|
|
|
|
import "github.com/deroproject/derohe/transaction"
|
|
|
|
//import "github.com/deroproject/derosuite/checkpoints"
|
|
import "github.com/deroproject/derohe/crypto"
|
|
*/
|
|
|
|
import "github.com/deroproject/derohe/astrobwt"
|
|
|
|
//import "github.com/deroproject/derosuite/crypto/ringct"
|
|
//import "github.com/deroproject/derosuite/blockchain/rpcserver"
|
|
|
|
import "time"
|
|
import "sync"
|
|
import "math/big"
|
|
import "crypto/rand"
|
|
import "sync/atomic"
|
|
|
|
//import "encoding/hex"
|
|
import "encoding/binary"
|
|
|
|
import "github.com/deroproject/derohe/block"
|
|
import "github.com/deroproject/derohe/crypto"
|
|
import "github.com/deroproject/derohe/globals"
|
|
import "github.com/deroproject/derohe/address"
|
|
import "github.com/deroproject/derohe/blockchain"
|
|
import "github.com/deroproject/derohe/transaction"
|
|
|
|
// p2p needs to export a varible declaring whether the chain is in syncronising mode
|
|
|
|
var counter uint64 = 0 // used to track speeds of current miner
|
|
|
|
var mining bool // whether system is mining
|
|
|
|
// request block chain template, see if the tip changes, then continously mine
|
|
func start_miner(chain *blockchain.Blockchain, addr *address.Address, tx *transaction.Transaction, threads int) {
|
|
|
|
mining = true
|
|
counter = 0
|
|
//tip_counter := 0
|
|
|
|
for {
|
|
//time.Sleep(50 * time.Millisecond)
|
|
|
|
if !mining {
|
|
break
|
|
}
|
|
|
|
if chain.MINING_BLOCK == true {
|
|
time.Sleep(10 * time.Millisecond)
|
|
continue
|
|
}
|
|
|
|
cbl, bl := chain.Create_new_miner_block(*addr, tx)
|
|
|
|
difficulty := chain.Get_Difficulty_At_Tips(bl.Tips)
|
|
|
|
//globals.Logger.Infof("Difficulty of new block is %s", difficulty.String())
|
|
// calculate difficulty once
|
|
// update job from chain
|
|
wg := sync.WaitGroup{}
|
|
wg.Add(threads) // add total number of tx as work
|
|
|
|
for i := 0; i < threads; i++ {
|
|
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
|
|
}
|
|
wg.Wait()
|
|
}
|
|
|
|
// g
|
|
}
|
|
|
|
// each invoke will be take atleast 250 milliseconds
|
|
func generate_valid_PoW(chain *blockchain.Blockchain, hf_version uint64, cbl *block.Complete_Block, bl *block.Block, current_difficulty *big.Int, wg *sync.WaitGroup) {
|
|
var powhash crypto.Hash
|
|
block_work := bl.GetBlockWork()
|
|
|
|
// extra nonce is always at offset 36 and is of length 32
|
|
var extra_nonce [16]byte
|
|
rand.Read(extra_nonce[:]) // fill extra nonce with random buffer
|
|
|
|
bl.SetExtraNonce(extra_nonce[:])
|
|
|
|
// TODO this time must be replaced by detecting TIP change
|
|
start := time.Now()
|
|
//deadline := time.Now().Add(250*time.Millisecond)
|
|
i := uint32(0)
|
|
|
|
nonce_buf := block_work[39 : 39+4] // take last 8 bytes as nonce counter and bruteforce it, since slices are linked, it modifies parent
|
|
for {
|
|
//time.Sleep(1000 * time.Millisecond)
|
|
|
|
atomic.AddUint64(&counter, 1)
|
|
|
|
binary.BigEndian.PutUint32(nonce_buf, i)
|
|
|
|
//PoW := crypto.Scrypt_1024_1_1_256(block_work)
|
|
//PoW := crypto.Keccak256(block_work)
|
|
//PoW := cryptonight.SlowHash(block_work)
|
|
PoW := astrobwt.POW_0alloc(block_work)
|
|
copy(powhash[:], PoW[:])
|
|
|
|
if blockchain.CheckPowHashBig(powhash, current_difficulty) == true {
|
|
|
|
bl.CopyNonceFromBlockWork(block_work)
|
|
//globals.Logger.Infof("Pow Successfully solved, Submitting block")
|
|
|
|
if _, ok := chain.Add_Complete_Block(cbl); ok {
|
|
globals.Logger.Infof("Block %s successfully accepted diff %s", bl.GetHash(), current_difficulty.String())
|
|
//chain.P2P_Block_Relayer(cbl, 0) // broadcast block to network ASAP
|
|
|
|
mining = false // this line enables single block mining in 1 go
|
|
|
|
break
|
|
}
|
|
|
|
}
|
|
|
|
if time.Now().Sub(start) > 250*time.Millisecond {
|
|
break
|
|
}
|
|
i++
|
|
|
|
}
|
|
|
|
wg.Done()
|
|
|
|
}
|