mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-06-06 06:06:49 +00:00

* [NOD-1319] Create the protorpc package. * [NOD-1319] Use a general ClientStream in closeSend. * [NOD-1319] Decouple p2pServer from gRPCServer. * [NOD-1319] Begin implementing rpcServer. * [NOD-1319] Move grpcStream to grpc_connection.go. * [NOD-1319] Fold the rpc messages.proto into a common message.proto. * [NOD-1319] Remove code duplication in MessageStream. * [NOD-1319] Rename methods in netadapter. * [NOD-1319] Rename message_xxx to p2p_xxx. * [NOD-1319] Section off p2p messages from rpc messages in messages.proto. * [NOD-1319] Split toPayload to a p2p part and and rpc part. * [NOD-1319] Rename msgxxx.go to p2p_msgxx.go in the appmessage package. * [NOD-1319] Implement GetCurrentVersionRequestMessage and GetCurrentVersionResponseMessage. * [NOD-1319] Implement toAppMessage and fromAppMessage for getCurrentNetwork * [NOD-1319] Make a temporary workaround so that tests pass. * [NOD-1319] Begin implementing the rpc manager. * [NOD-1319] Implement an initial routerInitializer for rpc. * [NOD-1319] Rename the spawn in routerInitializer. * [NOD-1319] Implement an RPC context. * [NOD-1319] Move the actual handlers to a separate package. * [NOD-1319] Use the correct value for the GetCurrentNetwork response. * [NOD-1319] Fix some names. * [NOD-1319] Begin implementing a cli rpc client. * [NOD-1319] Implement connecting to the RPC server. * [NOD-1319] Make sure that connecting to the server and sending/receiving messages works. * [NOD-1319] Make kaspactl2 speak in json strings. * [NOD-1319] Finish implementing kaspactl2. * [NOD-1319] Remove debug messages. * [NOD-1319] Properly handle errors in rpc.go. * [NOD-1319] Move the grpc client to a separate package. * [NOD-1319] Extract Post out of PostString. * [NOD-1319] Implement PostAppMessage. * [NOD-1319] Stub out submitBlock. * [NOD-1319] Stub out getBlockTemplate. * [NOD-1319] Combine request and reponse files. * [NOD-1319] Implement submitBlock. * [NOD-1319] Implement returning errors from RPC. * [NOD-1319] Begin implementing getBlockTemplate. * [NOD-1319] Add missing field in GetBlockTemplateRequestMessage. * [NOD-1319] Implement a minimal getBlockTemplate. * [NOD-1319] Add getBlockTemplate stuff to grpc. * [NOD-1319] Implement the rest of getBlockTemplate. * [NOD-1319] Add block/transaction added handlers to the protocol manager. * [NOD-1319] Implement NotifyTransactionAddedToMempool. * [NOD-1319] Implement NotifyBlockAddedToDAG. * [NOD-1319] Connect block/transaction added handlers. * [NOD-1319] Add notifyBlockAdded. * [NOD-1319] Add a notification system. * [NOD-1319] Improve the notification system. * [NOD-1319] Add a block added listener stub. * [NOD-1319] Add BlockAddedNotificationMessage. * [NOD-1319] Finish implementing HandleNotifyBlockAdded. * [NOD-1319] Println instead of Print in kaspactl2. * [NOD-1319] Remove unused flags in kaspactl2. * [NOD-1319] Make kaspaminer work with the new RPC. * [NOD-1319] Fix a bad log. * [NOD-1319] Make kaspaminer work. * [NOD-1319] Disconnect the old RPC. * [NOD-1319] Move grpcclient.go. * [NOD-1319] Begin generalizing the rpcClient. * [NOD-1319] Move errors to the side of the payload. * [NOD-1319] Add errors to appmessage. * [NOD-1319] Move AttachRouter to grpcclient. * [NOD-1319] Fix kaspaminer not handling responses. * [NOD-1319] Properly handle blockAddedNotifications. * [NOD-1319] Move errors into individual response objects. * [NOD-1319] Begin replacing the RPC client in the integration tests. * [NOD-1319] Implement GetPeerAddresses. * [NOD-1319] Implement GetPeerAddresses. * [NOD-1319] Fix setOnBlockAddedHandler. * [NOD-1319] Remove the old kaspactl. * [NOD-1319] Move ConvertGetBlockTemplateResultToBlock to the mining package. * [NOD-1319] Implement getSelectedTipHash. * [NOD-1319] Simplify testRPCRouter. * [NOD-1319] Write stubs for the required test RPC commands. * [NOD-1319] Implement a minimal getMempoolEntry. * [NOD-1319] Implement a minimal getMempoolEntry. * [NOD-1319] Implement getConnectedPeerInfo. * [NOD-1319] Delete the old RPC. * [NOD-1319] Fix a fromAppMessage. * [NOD-1319] Implement connectToPeer. * [NOD-1319] Fix a bug in registerForBlockAddedNotifications. * [NOD-1319] Fix a deadlock in closing notification listeners. * [NOD-1319] Fix merge errors. * [NOD-1319] Fix an import. * [NOD-1319] Properly handle errors in grpcclient. * [NOD-1319] Fix TestIBD. * [NOD-1319] Prevent kaspaminer from running when not connected. * [NOD-1319] Implement sendRawTransaction. * [NOD-1319] Implement sendRawTransaction in the client. * [NOD-1319] Extract a general RPC client from the integration test RPC client. * [NOD-1319] Use the general RPC client for the miner. * [NOD-1319] Move the rpcclient package out of netadapter. * [NOD-1319] Normalize onBlockAdded. * [NOD-1319] Begin implementing notifyChainChanged. * [NOD-1319] Implement the model for notifyChainChanged. * [NOD-1319] Implement conversions for notifyChainChanged. * [NOD-1319] Implement HandleNotifyChainChanged. * [NOD-1319] Normalize notifications. * [NOD-1319] Implement RegisterForChainChangedNotifications. * [NOD-1319] Begin connecting blockdag's chain-changed notification with the RPC. * [NOD-1319] Finish implementing notifyChainChanged. * [NOD-1319] Implement getBlockHex. * [NOD-1319] Rename getBlockHex to getBlock. * [NOD-1319] Implement the verbose model for getBlock. * [NOD-1319] Implement buildBlockVerboseData. * [NOD-1319] Implement buildTransactionVerboseData. * [NOD-1319] Move verboseData stuff to verbosedata.go. * [NOD-1319] Add includeTransactionVerboseData. * [NOD-1319] Begin implementing getSubnetwork. * [NOD-1319] Finish implementing getSubnetwork. * [NOD-1319] Begin implementing getChainFromBlock. * [NOD-1319] Finish implementing getChainFromBlock. * [NOD-1319] Begin implementing getBlocks. * [NOD-1319] Finish implementing getBlocks. * [NOD-1319] Fix bad responses in HandleNotifyChainChanged. * [NOD-1319] Fix bugs in verbosedata.go. * [NOD-1319] Fix more bugs in verbosedata.go. * [NOD-1319] Make go vet happy. * [NOD-1319] Extract handleBlockDAGNotifications to a method. * [NOD-1319] Add a newline. * [NOD-1319] Use peers instead of connections to check if connected. * [NOD-1319] Add a comment. * [NOD-1319] Lock the dag lock in getBlock. * [NOD-1319] Rename netAdapter.connections to p2pConnections. * [NOD-1319] In protowire, rename wireXXX to protoXXX. * [NOD-1319] Rename PostString to PostJSON. * [NOD-1319] Disallow empty transactions in SendRawTransaction. * [NOD-1319] Disallow empty blocks in SubmitBlocks. * [NOD-1319] Add SetLogger. * [NOD-1319] Fix an error message. * [NOD-1319] Fix an error message. * [NOD-1319] Rename testTimeout to rpcTimeout. * [NOD-1319] Rename SendRawTransaction to SubmitTransaction. * [NOD-1319] Rename ConnectToPeer to AddPeer. * [NOD-1319] Add missing longPollID to request. * [NOD-1319] Rename ChainChangedChainBlock to ChainBlock. * [NOD-1319] Rename Vin and Vout. * [NOD-1319] Implement RPCErrorf. * [NOD-1319] Fix RPCErrorf's comment. * [NOD-1319] Remove unused flags in kaspaminer.
196 lines
5.5 KiB
Go
196 lines
5.5 KiB
Go
package main
|
|
|
|
import (
|
|
nativeerrors "errors"
|
|
"github.com/kaspanet/kaspad/app/appmessage"
|
|
"github.com/kaspanet/kaspad/domain/mining"
|
|
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
|
"math/rand"
|
|
"sync"
|
|
"sync/atomic"
|
|
"time"
|
|
|
|
"github.com/kaspanet/kaspad/util"
|
|
"github.com/kaspanet/kaspad/util/daghash"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
var random = rand.New(rand.NewSource(time.Now().UnixNano()))
|
|
var hashesTried uint64
|
|
|
|
const logHashRateInterval = 10 * time.Second
|
|
|
|
func mineLoop(client *minerClient, numberOfBlocks uint64, blockDelay uint64, mineWhenNotSynced bool,
|
|
miningAddr util.Address) error {
|
|
|
|
errChan := make(chan error)
|
|
|
|
templateStopChan := make(chan struct{})
|
|
|
|
doneChan := make(chan struct{})
|
|
spawn("mineLoop-internalLoop", func() {
|
|
wg := sync.WaitGroup{}
|
|
for i := uint64(0); numberOfBlocks == 0 || i < numberOfBlocks; i++ {
|
|
foundBlock := make(chan *util.Block)
|
|
mineNextBlock(client, miningAddr, foundBlock, mineWhenNotSynced, templateStopChan, errChan)
|
|
block := <-foundBlock
|
|
templateStopChan <- struct{}{}
|
|
wg.Add(1)
|
|
spawn("mineLoop-handleFoundBlock", func() {
|
|
if blockDelay != 0 {
|
|
time.Sleep(time.Duration(blockDelay) * time.Millisecond)
|
|
}
|
|
err := handleFoundBlock(client, block)
|
|
if err != nil {
|
|
errChan <- err
|
|
}
|
|
wg.Done()
|
|
})
|
|
}
|
|
wg.Wait()
|
|
doneChan <- struct{}{}
|
|
})
|
|
|
|
logHashRate()
|
|
|
|
select {
|
|
case err := <-errChan:
|
|
return err
|
|
case <-doneChan:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func logHashRate() {
|
|
spawn("logHashRate", func() {
|
|
lastCheck := time.Now()
|
|
for range time.Tick(logHashRateInterval) {
|
|
currentHashesTried := hashesTried
|
|
currentTime := time.Now()
|
|
kiloHashesTried := float64(currentHashesTried) / 1000.0
|
|
hashRate := kiloHashesTried / currentTime.Sub(lastCheck).Seconds()
|
|
log.Infof("Current hash rate is %.2f Khash/s", hashRate)
|
|
lastCheck = currentTime
|
|
// subtract from hashesTried the hashes we already sampled
|
|
atomic.AddUint64(&hashesTried, -currentHashesTried)
|
|
}
|
|
})
|
|
}
|
|
|
|
func mineNextBlock(client *minerClient, miningAddr util.Address, foundBlock chan *util.Block, mineWhenNotSynced bool,
|
|
templateStopChan chan struct{}, errChan chan error) {
|
|
|
|
newTemplateChan := make(chan *appmessage.GetBlockTemplateResponseMessage)
|
|
spawn("templatesLoop", func() {
|
|
templatesLoop(client, miningAddr, newTemplateChan, errChan, templateStopChan)
|
|
})
|
|
spawn("solveLoop", func() {
|
|
solveLoop(newTemplateChan, foundBlock, mineWhenNotSynced, errChan)
|
|
})
|
|
}
|
|
|
|
func handleFoundBlock(client *minerClient, block *util.Block) error {
|
|
log.Infof("Found block %s with parents %s. Submitting to %s", block.Hash(), block.MsgBlock().Header.ParentHashes, client.Address())
|
|
|
|
err := client.SubmitBlock(block)
|
|
if err != nil {
|
|
return errors.Errorf("Error submitting block %s to %s: %s", block.Hash(), client.Address(), err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func solveBlock(block *util.Block, stopChan chan struct{}, foundBlock chan *util.Block) {
|
|
msgBlock := block.MsgBlock()
|
|
targetDifficulty := util.CompactToBig(msgBlock.Header.Bits)
|
|
initialNonce := random.Uint64()
|
|
for i := initialNonce; i != initialNonce-1; i++ {
|
|
select {
|
|
case <-stopChan:
|
|
return
|
|
default:
|
|
msgBlock.Header.Nonce = i
|
|
hash := msgBlock.BlockHash()
|
|
atomic.AddUint64(&hashesTried, 1)
|
|
if daghash.HashToBig(hash).Cmp(targetDifficulty) <= 0 {
|
|
foundBlock <- block
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func templatesLoop(client *minerClient, miningAddr util.Address,
|
|
newTemplateChan chan *appmessage.GetBlockTemplateResponseMessage, errChan chan error, stopChan chan struct{}) {
|
|
|
|
longPollID := ""
|
|
getBlockTemplateLongPoll := func() {
|
|
if longPollID != "" {
|
|
log.Infof("Requesting template with longPollID '%s' from %s", longPollID, client.Address())
|
|
} else {
|
|
log.Infof("Requesting template without longPollID from %s", client.Address())
|
|
}
|
|
template, err := client.GetBlockTemplate(miningAddr.String(), longPollID)
|
|
if nativeerrors.Is(err, router.ErrTimeout) {
|
|
log.Infof("Got timeout while requesting template '%s' from %s", longPollID, client.Address())
|
|
return
|
|
} else if err != nil {
|
|
errChan <- errors.Errorf("Error getting block template from %s: %s", client.Address(), err)
|
|
return
|
|
}
|
|
if !template.IsConnected {
|
|
errChan <- errors.Errorf("Kaspad is not connected for %s", client.Address())
|
|
return
|
|
}
|
|
if template.LongPollID != longPollID {
|
|
log.Infof("Got new long poll template: %s", template.LongPollID)
|
|
longPollID = template.LongPollID
|
|
newTemplateChan <- template
|
|
}
|
|
}
|
|
getBlockTemplateLongPoll()
|
|
for {
|
|
select {
|
|
case <-stopChan:
|
|
close(newTemplateChan)
|
|
return
|
|
case <-client.blockAddedNotificationChan:
|
|
getBlockTemplateLongPoll()
|
|
case <-time.Tick(500 * time.Millisecond):
|
|
getBlockTemplateLongPoll()
|
|
}
|
|
}
|
|
}
|
|
|
|
func solveLoop(newTemplateChan chan *appmessage.GetBlockTemplateResponseMessage, foundBlock chan *util.Block,
|
|
mineWhenNotSynced bool, errChan chan error) {
|
|
|
|
var stopOldTemplateSolving chan struct{}
|
|
for template := range newTemplateChan {
|
|
if stopOldTemplateSolving != nil {
|
|
close(stopOldTemplateSolving)
|
|
}
|
|
|
|
if !template.IsSynced {
|
|
if !mineWhenNotSynced {
|
|
errChan <- errors.Errorf("got template with isSynced=false")
|
|
return
|
|
}
|
|
log.Warnf("Got template with isSynced=false")
|
|
}
|
|
|
|
stopOldTemplateSolving = make(chan struct{})
|
|
block, err := mining.ConvertGetBlockTemplateResultToBlock(template)
|
|
if err != nil {
|
|
errChan <- errors.Errorf("Error parsing block: %s", err)
|
|
return
|
|
}
|
|
|
|
spawn("solveBlock", func() {
|
|
solveBlock(block, stopOldTemplateSolving, foundBlock)
|
|
})
|
|
}
|
|
if stopOldTemplateSolving != nil {
|
|
close(stopOldTemplateSolving)
|
|
}
|
|
}
|