// HeaderForWork returns a block that is ready for nonce grinding, along with // the root hash of the block. func (m *Miner) HeaderForWork() (types.BlockHeader, types.Target, error) { if !m.wallet.Unlocked() { return types.BlockHeader{}, types.Target{}, modules.ErrLockedWallet } lockID := m.mu.Lock() defer m.mu.Unlock(lockID) err := m.checkAddress() if err != nil { return types.BlockHeader{}, types.Target{}, err } if time.Since(m.lastBlock).Seconds() > secondsBetweenBlocks { m.prepareNewBlock() } // The header that will be returned for nonce grinding. // The header is constructed from a block and some arbitrary data. The // arbitrary data allows for multiple unique blocks to be generated from // a single block in memory. A block pointer is used in order to avoid // storing multiple copies of the same block in memory var header types.BlockHeader var arbData []byte var block *types.Block if m.memProgress%(headerForWorkMemory/blockForWorkMemory) == 0 { // Grab a new block. Allocate space for the pointer to store it as well block = new(types.Block) *block, _ = m.blockForWork() header = block.Header() arbData = block.Transactions[0].ArbitraryData[0] m.lastBlock = time.Now() } else { // Set block to previous block, but create new arbData block = m.blockMem[m.headerMem[m.memProgress-1]] arbData, _ = crypto.RandBytes(types.SpecifierLen) block.Transactions[0].ArbitraryData[0] = arbData header = block.Header() } // Save a mapping from the header to its block as well as from the // header to its arbitrary data, replacing the block that was // stored 'headerForWorkMemory' requests ago. delete(m.blockMem, m.headerMem[m.memProgress]) delete(m.arbDataMem, m.headerMem[m.memProgress]) m.blockMem[header] = block m.arbDataMem[header] = arbData m.headerMem[m.memProgress] = header m.memProgress++ if m.memProgress == headerForWorkMemory { m.memProgress = 0 } // Return the header and target. return header, m.target, nil }
// managedBroadcastBlock will broadcast a block to the consensus set's peers. func (cs *ConsensusSet) managedBroadcastBlock(b types.Block) { // COMPATv0.5.1 - broadcast the block to all peers <= v0.5.1 and block header to all peers > v0.5.1. var relayBlockPeers, relayHeaderPeers []modules.Peer for _, p := range cs.gateway.Peers() { if build.VersionCmp(p.Version, "0.5.1") <= 0 { relayBlockPeers = append(relayBlockPeers, p) } else { relayHeaderPeers = append(relayHeaderPeers, p) } } go cs.gateway.Broadcast("RelayBlock", b, relayBlockPeers) go cs.gateway.Broadcast("RelayHeader", b.Header(), relayHeaderPeers) }