diff --git a/mining/simulator/config.go b/mining/simulator/config.go index 65827307f..7e9ac6f85 100644 --- a/mining/simulator/config.go +++ b/mining/simulator/config.go @@ -28,6 +28,7 @@ type config struct { CertificatePath string `long:"cert" description:"Path to certificate accepted by JSON-RPC endpoint"` DisableTLS bool `long:"notls" description:"Disable TLS"` Verbose bool `long:"verbose" short:"v" description:"Enable logging of RPC requests"` + BlockDelay uint64 `long:"block-delay" description:"Delay for block submission (in milliseconds)"` } func parseConfig() (*config, error) { diff --git a/mining/simulator/main.go b/mining/simulator/main.go index fe48ed61a..272701d56 100644 --- a/mining/simulator/main.go +++ b/mining/simulator/main.go @@ -29,7 +29,7 @@ func main() { defer connManager.close() spawn(func() { - err = mineLoop(connManager) + err = mineLoop(connManager, cfg.BlockDelay) if err != nil { panic(errors.Errorf("Error in main loop: %s", err)) } diff --git a/mining/simulator/mineloop.go b/mining/simulator/mineloop.go index eac0feb4a..0a051319e 100644 --- a/mining/simulator/mineloop.go +++ b/mining/simulator/mineloop.go @@ -50,7 +50,7 @@ func parseBlock(template *btcjson.GetBlockTemplateResult) (*util.Block, error) { // parse rest of block msgBlock := wire.NewMsgBlock( wire.NewBlockHeader(template.Version, parentHashes, &daghash.Hash{}, - acceptedIDMerkleRoot, utxoCommitment, uint32(bits), 0)) + acceptedIDMerkleRoot, utxoCommitment, bits, 0)) for i, txResult := range append([]btcjson.GetBlockTemplateResultTx{*template.CoinbaseTxn}, template.Transactions...) { reader := hex.NewDecoder(strings.NewReader(txResult.Data)) @@ -68,9 +68,9 @@ func parseBlock(template *btcjson.GetBlockTemplateResult) (*util.Block, error) { func solveBlock(block *util.Block, stopChan chan struct{}, foundBlock chan *util.Block) { msgBlock := block.MsgBlock() - maxNonce := ^uint64(0) // 2^64 - 1 targetDifficulty := util.CompactToBig(msgBlock.Header.Bits) - for i := uint64(0); i < maxNonce; i++ { + initialNonce := random.Uint64() + for i := random.Uint64(); i != initialNonce-1; i++ { select { case <-stopChan: return @@ -152,13 +152,12 @@ func mineNextBlock(client *simulatorClient, foundBlock chan *util.Block, templat go solveLoop(newTemplateChan, foundBlock, errChan) } -func handleFoundBlock(client *simulatorClient, block *util.Block, templateStopChan chan struct{}) error { - templateStopChan <- struct{}{} +func handleFoundBlock(client *simulatorClient, block *util.Block) error { log.Infof("Found block %s with parents %s! Submitting to %s", block.Hash(), block.MsgBlock().Header.ParentHashes, client.Host()) err := client.SubmitBlock(block, &btcjson.SubmitBlockOptions{}) if err != nil { - return errors.Errorf("Error submitting block: %s", err) + return errors.Errorf("Error submitting block %s to %s: %s", block.Hash(), client.Host(), err) } return nil } @@ -171,7 +170,7 @@ func getRandomClient(clients []*simulatorClient) *simulatorClient { return clients[random.Int63n(clientsCount)] } -func mineLoop(connManager *connectionManager) error { +func mineLoop(connManager *connectionManager, blockDelay uint64) error { errChan := make(chan error) templateStopChan := make(chan struct{}) @@ -189,11 +188,16 @@ func mineLoop(connManager *connectionManager) error { return } currentClient.notifyForNewBlocks = false - err := handleFoundBlock(currentClient, block, templateStopChan) - if err != nil { - errChan <- err - return - } + templateStopChan <- struct{}{} + spawn(func() { + if blockDelay != 0 { + time.Sleep(time.Duration(blockDelay) * time.Millisecond) + } + err := handleFoundBlock(currentClient, block) + if err != nil { + errChan <- err + } + }) } })