gitlab.com/SiaPrime/SiaPrime@v1.4.1/modules/miningpool/blockmanager.go (about)

     1  package pool
     2  
     3  import (
     4  	"errors"
     5  	"time"
     6  
     7  	"gitlab.com/SiaPrime/SiaPrime/modules"
     8  	"gitlab.com/SiaPrime/SiaPrime/types"
     9  )
    10  
    11  var (
    12  	errLateHeader = errors.New("header is old, block could not be recovered")
    13  )
    14  
    15  func (p *Pool) blockForWorkWithoutDevFund() types.Block {
    16  	p.persist.mu.Lock()
    17  	defer p.persist.mu.Unlock()
    18  
    19  	b := p.sourceBlock
    20  	b.Transactions = p.blockTxns.transactions()
    21  
    22  	// Update the timestamp.
    23  	if b.Timestamp < types.CurrentTimestamp() {
    24  		b.Timestamp = types.CurrentTimestamp()
    25  	}
    26  
    27  	payoutVal := b.CalculateSubsidy(p.persist.BlockHeight + 1)
    28  	p.log.Printf("building a new source block, block id is: %s\n", b.ID())
    29  	p.log.Printf("miner fees cost: %s", b.CalculateMinerFees().String())
    30  	p.log.Printf("# transactions: %d", len(b.Transactions))
    31  	p.log.Printf("payout value is: %s", payoutVal.String())
    32  	b.MinerPayouts = []types.SiacoinOutput{{
    33  		Value:      payoutVal,
    34  		UnlockHash: p.persist.Settings.PoolWallet,
    35  	}}
    36  
    37  	return b
    38  }
    39  
    40  func (p *Pool) blockForWorkWithDevFund() types.Block {
    41  	p.persist.mu.Lock()
    42  	defer p.persist.mu.Unlock()
    43  
    44  	b := p.sourceBlock
    45  	b.Transactions = p.blockTxns.transactions()
    46  
    47  	// Update the timestamp.
    48  	if b.Timestamp < types.CurrentTimestamp() {
    49  		b.Timestamp = types.CurrentTimestamp()
    50  	}
    51  
    52  	minerPayoutVal, subsidyPayoutVal := b.CalculateSubsidies(p.persist.BlockHeight + 1)
    53  	subsidyUnlockHash := types.DevFundUnlockHash
    54  	if types.BurnAddressBlockHeight != types.BlockHeight(0) && (p.persist.BlockHeight+1) >= types.BurnAddressBlockHeight {
    55  		subsidyUnlockHash = types.BurnAddressUnlockHash
    56  	}
    57  	p.log.Printf("building a new source block, block id is: %s\n", b.ID())
    58  	p.log.Printf("miner fees cost: %s", b.CalculateMinerFees().String())
    59  	p.log.Printf("# transactions: %d", len(b.Transactions))
    60  	p.log.Printf("payout value is: %s", minerPayoutVal.String())
    61  	b.MinerPayouts = []types.SiacoinOutput{{
    62  		Value:      minerPayoutVal,
    63  		UnlockHash: p.persist.Settings.PoolWallet,
    64  	}, {
    65  		Value:      subsidyPayoutVal,
    66  		UnlockHash: subsidyUnlockHash,
    67  	}}
    68  
    69  	return b
    70  }
    71  
    72  // blockForWork returns a block that is ready for nonce grinding, including
    73  // correct miner payouts.
    74  func (p *Pool) blockForWork() types.Block {
    75  	if types.DevFundEnabled && p.persist.BlockHeight+1 >= types.DevFundInitialBlockHeight {
    76  		return p.blockForWorkWithDevFund()
    77  	}
    78  	return p.blockForWorkWithoutDevFund()
    79  }
    80  
    81  // newSourceBlock creates a new source block for the block manager so that new
    82  // headers will use the updated source block.
    83  func (p *Pool) newSourceBlock() {
    84  	// To guarantee garbage collection of old blocks, delete all header entries
    85  	// that have not been reached for the current block.
    86  	for p.memProgress%(HeaderMemory/BlockMemory) != 0 {
    87  		delete(p.blockMem, p.headerMem[p.memProgress])
    88  		delete(p.arbDataMem, p.headerMem[p.memProgress])
    89  		p.memProgress++
    90  		if p.memProgress == HeaderMemory {
    91  			p.memProgress = 0
    92  		}
    93  	}
    94  
    95  	// Update the source block.
    96  	block := p.blockForWork()
    97  	p.saveSync()
    98  	p.sourceBlock = block
    99  	p.sourceBlockTime = time.Now()
   100  }
   101  
   102  // managedSubmitBlock takes a solved block and submits it to the blockchain.
   103  func (p *Pool) managedSubmitBlock(b types.Block) error {
   104  	p.log.Printf("managedSubmitBlock called on block id: %s, block has %d txs\n", b.ID(), len(b.Transactions))
   105  	// Give the block to the consensus set.
   106  	err := p.cs.AcceptBlock(b)
   107  	// Add the miner to the blocks list if the only problem is that it's stale.
   108  	if err == modules.ErrNonExtendingBlock {
   109  		// p.log.Debugf("Waiting to lock pool\n")
   110  		p.mu.Lock()
   111  		p.persist.SetBlocksFound(append(p.persist.GetBlocksFound(), b.ID()))
   112  		// p.log.Debugf("Unlocking pool\n")
   113  		p.mu.Unlock()
   114  		p.log.Println("Mined a stale block - block appears valid but does not extend the blockchain")
   115  		return err
   116  	}
   117  	if err == modules.ErrBlockUnsolved {
   118  		// p.log.Println("Mined an unsolved block - header submission appears to be incorrect")
   119  		return err
   120  	}
   121  	if err != nil {
   122  		p.tpool.PurgeTransactionPool()
   123  		p.log.Println("ERROR: an invalid block was submitted:", err)
   124  		return err
   125  	}
   126  	// p.log.Debugf("Waiting to lock pool\n")
   127  	p.mu.Lock()
   128  	defer func() {
   129  		// p.log.Debugf("Unlocking pool\n")
   130  		p.mu.Unlock()
   131  	}()
   132  
   133  	// Grab a new address for the miner. Call may fail if the wallet is locked
   134  	// or if the wallet addresses have been exhausted.
   135  	p.persist.SetBlocksFound(append(p.persist.GetBlocksFound(), b.ID()))
   136  	// var uc types.UnlockConditions
   137  	// uc, err = p.wallet.NextAddress()
   138  	// if err != nil {
   139  	// 	return err
   140  	// }
   141  	// p.persist.Address = uc.UnlockHash()
   142  	return p.saveSync()
   143  }