kaspad/mining/simulator/mineloop.go
Ori Newman 254eab96cd [NOD-55] Change daghash hash to pointer in most places (#239)
* [NOD-55] Change daghash.Hash to pointer in most places

* [NOD-55] Fixed format error

* [NOD-55] Fixed merge error

* [NOD-55] Cancel copying hash in blockSet.hashes()
2019-04-02 13:49:47 +03:00

108 lines
2.9 KiB
Go

package main
import (
"encoding/hex"
"fmt"
"log"
"math/rand"
"strconv"
"strings"
"sync/atomic"
"time"
"github.com/daglabs/btcd/blockdag"
"github.com/daglabs/btcd/btcjson"
"github.com/daglabs/btcd/dagconfig/daghash"
"github.com/daglabs/btcd/rpcclient"
"github.com/daglabs/btcd/util"
"github.com/daglabs/btcd/wire"
)
var random = rand.New(rand.NewSource(time.Now().UnixNano()))
func parseBlock(template *btcjson.GetBlockTemplateResult) (*util.Block, error) {
// parse parent hashes
parentHashes := make([]*daghash.Hash, len(template.ParentHashes))
for i, parentHash := range template.ParentHashes {
hash, err := daghash.NewHashFromStr(parentHash)
if err != nil {
return nil, fmt.Errorf("Error decoding hash %s: %s", parentHash, err)
}
parentHashes[i] = hash
}
// parse Bits
bitsInt64, err := strconv.ParseInt(template.Bits, 16, 32)
if err != nil {
return nil, fmt.Errorf("Error decoding bits %s: %s", template.Bits, err)
}
bits := uint32(bitsInt64)
// parse rest of block
msgBlock := wire.NewMsgBlock(wire.NewBlockHeader(template.Version, parentHashes, &daghash.Hash{}, &daghash.Hash{}, uint32(bits), 0))
for i, txResult := range append([]btcjson.GetBlockTemplateResultTx{*template.CoinbaseTxn}, template.Transactions...) {
reader := hex.NewDecoder(strings.NewReader(txResult.Data))
tx := &wire.MsgTx{}
if err := tx.BtcDecode(reader, 0); err != nil {
return nil, fmt.Errorf("Error decoding tx #%d: %s", i, err)
}
msgBlock.AddTransaction(tx)
}
return util.NewBlock(msgBlock), nil
}
func solveBlock(msgBlock *wire.MsgBlock) {
maxNonce := ^uint64(0) // 2^64 - 1
targetDifficulty := util.CompactToBig(msgBlock.Header.Bits)
for i := uint64(0); i < maxNonce; i++ {
msgBlock.Header.Nonce = i
hash := msgBlock.BlockHash()
if daghash.HashToBig(hash).Cmp(targetDifficulty) <= 0 {
break
}
}
}
func mineLoop(clients []*rpcclient.Client) error {
clientsCount := int64(len(clients))
for atomic.LoadInt32(&isRunning) == 1 {
var currentClient *rpcclient.Client
if clientsCount == 1 {
currentClient = clients[0]
} else {
currentClient = clients[random.Int63n(clientsCount)]
}
log.Printf("Next block will be mined by: %s", currentClient.Host())
template, err := currentClient.GetBlockTemplate([]string{"coinbasetxn"})
if err != nil {
return fmt.Errorf("Error getting block template: %s", err)
}
block, err := parseBlock(template)
if err != nil {
return fmt.Errorf("Error parsing block: %s", err)
}
msgBlock := block.MsgBlock()
msgBlock.Header.HashMerkleRoot = blockdag.BuildHashMerkleTreeStore(block.Transactions()).Root()
msgBlock.Header.IDMerkleRoot = blockdag.BuildIDMerkleTreeStore(block.Transactions()).Root()
solveBlock(msgBlock)
log.Printf("Found block %s! Submitting", block.Hash())
err = currentClient.SubmitBlock(block, &btcjson.SubmitBlockOptions{})
if err != nil {
return fmt.Errorf("Error submitting block: %s", err)
}
}
return nil
}