2020-12-19 10:01:29 +00:00
// 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"
2021-02-22 17:48:14 +00:00
import "github.com/deroproject/derohe/cryptography/crypto"
2020-12-19 10:01:29 +00:00
import "github.com/deroproject/derohe/globals"
2021-02-22 17:48:14 +00:00
import "github.com/deroproject/derohe/rpc"
2020-12-19 10:01:29 +00:00
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
2021-02-22 17:48:14 +00:00
func start_miner ( chain * blockchain . Blockchain , addr * rpc . Address , tx * transaction . Transaction , threads int ) {
2020-12-19 10:01:29 +00:00
//tip_counter := 0
2021-02-22 17:48:14 +00:00
for { // once started keep generating blocks after every 10 secs
mining = true
counter = 0
for {
//time.Sleep(50 * time.Millisecond)
2020-12-19 10:01:29 +00:00
2021-02-22 17:48:14 +00:00
if ! mining {
break
}
2020-12-19 10:01:29 +00:00
2021-02-22 17:48:14 +00:00
if chain . MINING_BLOCK == true {
time . Sleep ( 10 * time . Millisecond )
continue
}
2020-12-19 10:01:29 +00:00
2021-02-22 17:48:14 +00:00
cbl , bl := chain . Create_new_miner_block ( * addr , tx )
2020-12-19 10:01:29 +00:00
2021-02-22 17:48:14 +00:00
difficulty := chain . Get_Difficulty_At_Tips ( bl . Tips )
2020-12-19 10:01:29 +00:00
2021-02-22 17:48:14 +00:00
//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
2020-12-19 10:01:29 +00:00
2021-02-22 17:48:14 +00:00
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 ( )
2020-12-19 10:01:29 +00:00
}
2021-02-22 17:48:14 +00:00
time . Sleep ( 10 * time . Second )
2020-12-19 10:01:29 +00:00
}
// 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 ( ) )
2021-02-22 17:48:14 +00:00
chain . P2P_Block_Relayer ( cbl , 0 ) // broadcast block to network ASAP
2020-12-19 10:01:29 +00:00
mining = false // this line enables single block mining in 1 go
break
}
}
if time . Now ( ) . Sub ( start ) > 250 * time . Millisecond {
break
}
i ++
}
wg . Done ( )
}