[NOD-491] Withhold blocks in mining simulator (#517)

This commit is contained in:
Ori Newman 2019-12-04 17:36:27 +02:00 committed by Svarog
parent 0842778c2c
commit 3f94f8ca4c
3 changed files with 18 additions and 13 deletions

View File

@ -28,6 +28,7 @@ type config struct {
CertificatePath string `long:"cert" description:"Path to certificate accepted by JSON-RPC endpoint"` CertificatePath string `long:"cert" description:"Path to certificate accepted by JSON-RPC endpoint"`
DisableTLS bool `long:"notls" description:"Disable TLS"` DisableTLS bool `long:"notls" description:"Disable TLS"`
Verbose bool `long:"verbose" short:"v" description:"Enable logging of RPC requests"` 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) { func parseConfig() (*config, error) {

View File

@ -29,7 +29,7 @@ func main() {
defer connManager.close() defer connManager.close()
spawn(func() { spawn(func() {
err = mineLoop(connManager) err = mineLoop(connManager, cfg.BlockDelay)
if err != nil { if err != nil {
panic(errors.Errorf("Error in main loop: %s", err)) panic(errors.Errorf("Error in main loop: %s", err))
} }

View File

@ -50,7 +50,7 @@ func parseBlock(template *btcjson.GetBlockTemplateResult) (*util.Block, error) {
// parse rest of block // parse rest of block
msgBlock := wire.NewMsgBlock( msgBlock := wire.NewMsgBlock(
wire.NewBlockHeader(template.Version, parentHashes, &daghash.Hash{}, 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...) { for i, txResult := range append([]btcjson.GetBlockTemplateResultTx{*template.CoinbaseTxn}, template.Transactions...) {
reader := hex.NewDecoder(strings.NewReader(txResult.Data)) 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) { func solveBlock(block *util.Block, stopChan chan struct{}, foundBlock chan *util.Block) {
msgBlock := block.MsgBlock() msgBlock := block.MsgBlock()
maxNonce := ^uint64(0) // 2^64 - 1
targetDifficulty := util.CompactToBig(msgBlock.Header.Bits) 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 { select {
case <-stopChan: case <-stopChan:
return return
@ -152,13 +152,12 @@ func mineNextBlock(client *simulatorClient, foundBlock chan *util.Block, templat
go solveLoop(newTemplateChan, foundBlock, errChan) go solveLoop(newTemplateChan, foundBlock, errChan)
} }
func handleFoundBlock(client *simulatorClient, block *util.Block, templateStopChan chan struct{}) error { func handleFoundBlock(client *simulatorClient, block *util.Block) error {
templateStopChan <- struct{}{}
log.Infof("Found block %s with parents %s! Submitting to %s", block.Hash(), block.MsgBlock().Header.ParentHashes, client.Host()) 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{}) err := client.SubmitBlock(block, &btcjson.SubmitBlockOptions{})
if err != nil { 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 return nil
} }
@ -171,7 +170,7 @@ func getRandomClient(clients []*simulatorClient) *simulatorClient {
return clients[random.Int63n(clientsCount)] return clients[random.Int63n(clientsCount)]
} }
func mineLoop(connManager *connectionManager) error { func mineLoop(connManager *connectionManager, blockDelay uint64) error {
errChan := make(chan error) errChan := make(chan error)
templateStopChan := make(chan struct{}) templateStopChan := make(chan struct{})
@ -189,11 +188,16 @@ func mineLoop(connManager *connectionManager) error {
return return
} }
currentClient.notifyForNewBlocks = false currentClient.notifyForNewBlocks = false
err := handleFoundBlock(currentClient, block, templateStopChan) templateStopChan <- struct{}{}
if err != nil { spawn(func() {
errChan <- err if blockDelay != 0 {
return time.Sleep(time.Duration(blockDelay) * time.Millisecond)
} }
err := handleFoundBlock(currentClient, block)
if err != nil {
errChan <- err
}
})
} }
}) })