github.com/Night-mk/quorum@v21.1.0+incompatible/raft/minter.go (about)

     1  // Copyright 2015 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package raft
    18  
    19  import (
    20  	"fmt"
    21  	"sync"
    22  	"sync/atomic"
    23  	"time"
    24  
    25  	"github.com/eapache/channels"
    26  	"github.com/ethereum/go-ethereum/common"
    27  	"github.com/ethereum/go-ethereum/common/hexutil"
    28  	"github.com/ethereum/go-ethereum/consensus/ethash"
    29  	"github.com/ethereum/go-ethereum/core"
    30  	"github.com/ethereum/go-ethereum/core/state"
    31  	"github.com/ethereum/go-ethereum/core/types"
    32  	"github.com/ethereum/go-ethereum/core/vm"
    33  	"github.com/ethereum/go-ethereum/crypto"
    34  	"github.com/ethereum/go-ethereum/ethdb"
    35  	"github.com/ethereum/go-ethereum/event"
    36  	"github.com/ethereum/go-ethereum/log"
    37  	"github.com/ethereum/go-ethereum/params"
    38  	"github.com/ethereum/go-ethereum/rlp"
    39  )
    40  
    41  var (
    42  	extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for arbitrary signer vanity
    43  )
    44  
    45  // Current state information for building the next block
    46  type work struct {
    47  	config       *params.ChainConfig
    48  	publicState  *state.StateDB
    49  	privateState *state.StateDB
    50  	Block        *types.Block
    51  	header       *types.Header
    52  }
    53  
    54  type minter struct {
    55  	config           *params.ChainConfig
    56  	mu               sync.Mutex
    57  	mux              *event.TypeMux
    58  	eth              *RaftService
    59  	chain            *core.BlockChain
    60  	chainDb          ethdb.Database
    61  	coinbase         common.Address
    62  	minting          int32 // Atomic status counter
    63  	shouldMine       *channels.RingChannel
    64  	blockTime        time.Duration
    65  	speculativeChain *speculativeChain
    66  
    67  	invalidRaftOrderingChan chan InvalidRaftOrdering
    68  	chainHeadChan           chan core.ChainHeadEvent
    69  	chainHeadSub            event.Subscription
    70  	txPreChan               chan core.NewTxsEvent
    71  	txPreSub                event.Subscription
    72  }
    73  
    74  type extraSeal struct {
    75  	RaftId    []byte // RaftID of the block minter
    76  	Signature []byte // Signature of the block minter
    77  }
    78  
    79  func newMinter(config *params.ChainConfig, eth *RaftService, blockTime time.Duration) *minter {
    80  	minter := &minter{
    81  		config:           config,
    82  		eth:              eth,
    83  		mux:              eth.EventMux(),
    84  		chainDb:          eth.ChainDb(),
    85  		chain:            eth.BlockChain(),
    86  		shouldMine:       channels.NewRingChannel(1),
    87  		blockTime:        blockTime,
    88  		speculativeChain: newSpeculativeChain(),
    89  
    90  		invalidRaftOrderingChan: make(chan InvalidRaftOrdering, 1),
    91  		chainHeadChan:           make(chan core.ChainHeadEvent, core.GetChainHeadChannleSize()),
    92  		txPreChan:               make(chan core.NewTxsEvent, 4096),
    93  	}
    94  
    95  	minter.chainHeadSub = eth.BlockChain().SubscribeChainHeadEvent(minter.chainHeadChan)
    96  	minter.txPreSub = eth.TxPool().SubscribeNewTxsEvent(minter.txPreChan)
    97  
    98  	minter.speculativeChain.clear(minter.chain.CurrentBlock())
    99  
   100  	go minter.eventLoop()
   101  	go minter.mintingLoop()
   102  
   103  	return minter
   104  }
   105  
   106  func (minter *minter) start() {
   107  	atomic.StoreInt32(&minter.minting, 1)
   108  	minter.requestMinting()
   109  }
   110  
   111  func (minter *minter) stop() {
   112  	minter.mu.Lock()
   113  	defer minter.mu.Unlock()
   114  
   115  	minter.speculativeChain.clear(minter.chain.CurrentBlock())
   116  	atomic.StoreInt32(&minter.minting, 0)
   117  }
   118  
   119  // Notify the minting loop that minting should occur, if it's not already been
   120  // requested. Due to the use of a RingChannel, this function is idempotent if
   121  // called multiple times before the minting occurs.
   122  func (minter *minter) requestMinting() {
   123  	minter.shouldMine.In() <- struct{}{}
   124  }
   125  
   126  type AddressTxes map[common.Address]types.Transactions
   127  
   128  func (minter *minter) updateSpeculativeChainPerNewHead(newHeadBlock *types.Block) {
   129  	minter.mu.Lock()
   130  	defer minter.mu.Unlock()
   131  
   132  	minter.speculativeChain.accept(newHeadBlock)
   133  }
   134  
   135  func (minter *minter) updateSpeculativeChainPerInvalidOrdering(headBlock *types.Block, invalidBlock *types.Block) {
   136  	invalidHash := invalidBlock.Hash()
   137  
   138  	log.Info("Handling InvalidRaftOrdering", "invalid block", invalidHash, "current head", headBlock.Hash())
   139  
   140  	minter.mu.Lock()
   141  	defer minter.mu.Unlock()
   142  
   143  	// 1. if the block is not in our db, exit. someone else mined this.
   144  	if !minter.chain.HasBlock(invalidHash, invalidBlock.NumberU64()) {
   145  		log.Info("Someone else mined invalid block; ignoring", "block", invalidHash)
   146  
   147  		return
   148  	}
   149  
   150  	minter.speculativeChain.unwindFrom(invalidHash, headBlock)
   151  }
   152  
   153  func (minter *minter) eventLoop() {
   154  	defer minter.chainHeadSub.Unsubscribe()
   155  	defer minter.txPreSub.Unsubscribe()
   156  
   157  	for {
   158  		select {
   159  		case ev := <-minter.chainHeadChan:
   160  			newHeadBlock := ev.Block
   161  
   162  			if atomic.LoadInt32(&minter.minting) == 1 {
   163  				minter.updateSpeculativeChainPerNewHead(newHeadBlock)
   164  
   165  				//
   166  				// TODO(bts): not sure if this is the place, but we're going to
   167  				// want to put an upper limit on our speculative mining chain
   168  				// length.
   169  				//
   170  
   171  				minter.requestMinting()
   172  			} else {
   173  				minter.mu.Lock()
   174  				minter.speculativeChain.setHead(newHeadBlock)
   175  				minter.mu.Unlock()
   176  			}
   177  
   178  		case <-minter.txPreChan:
   179  			if atomic.LoadInt32(&minter.minting) == 1 {
   180  				minter.requestMinting()
   181  			}
   182  
   183  		case ev := <-minter.invalidRaftOrderingChan:
   184  			headBlock := ev.headBlock
   185  			invalidBlock := ev.invalidBlock
   186  
   187  			minter.updateSpeculativeChainPerInvalidOrdering(headBlock, invalidBlock)
   188  
   189  		// system stopped
   190  		case <-minter.chainHeadSub.Err():
   191  			return
   192  		case <-minter.txPreSub.Err():
   193  			return
   194  		}
   195  	}
   196  }
   197  
   198  // Returns a wrapper around no-arg func `f` which can be called without limit
   199  // and returns immediately: this will call the underlying func `f` at most once
   200  // every `rate`. If this function is called more than once before the underlying
   201  // `f` is invoked (per this rate limiting), `f` will only be called *once*.
   202  //
   203  // TODO(joel): this has a small bug in that you can't call it *immediately* when
   204  // first allocated.
   205  func throttle(rate time.Duration, f func()) func() {
   206  	request := channels.NewRingChannel(1)
   207  
   208  	// every tick, block waiting for another request. then serve it immediately
   209  	go func() {
   210  		ticker := time.NewTicker(rate)
   211  		defer ticker.Stop()
   212  
   213  		for range ticker.C {
   214  			<-request.Out()
   215  			f()
   216  		}
   217  	}()
   218  
   219  	return func() {
   220  		request.In() <- struct{}{}
   221  	}
   222  }
   223  
   224  // This function spins continuously, blocking until a block should be created
   225  // (via requestMinting()). This is throttled by `minter.blockTime`:
   226  //
   227  //   1. A block is guaranteed to be minted within `blockTime` of being
   228  //      requested.
   229  //   2. We never mint a block more frequently than `blockTime`.
   230  func (minter *minter) mintingLoop() {
   231  	throttledMintNewBlock := throttle(minter.blockTime, func() {
   232  		if atomic.LoadInt32(&minter.minting) == 1 {
   233  			minter.mintNewBlock()
   234  		}
   235  	})
   236  
   237  	for range minter.shouldMine.Out() {
   238  		throttledMintNewBlock()
   239  	}
   240  }
   241  
   242  func generateNanoTimestamp(parent *types.Block) (tstamp int64) {
   243  	parentTime := int64(parent.Time())
   244  	tstamp = time.Now().UnixNano()
   245  
   246  	if parentTime >= tstamp {
   247  		// Each successive block needs to be after its predecessor.
   248  		tstamp = parentTime + 1
   249  	}
   250  
   251  	return
   252  }
   253  
   254  // Assumes mu is held.
   255  func (minter *minter) createWork() *work {
   256  	parent := minter.speculativeChain.head
   257  	parentNumber := parent.Number()
   258  	tstamp := generateNanoTimestamp(parent)
   259  
   260  	header := &types.Header{
   261  		ParentHash: parent.Hash(),
   262  		Number:     parentNumber.Add(parentNumber, common.Big1),
   263  		Difficulty: ethash.CalcDifficulty(minter.config, uint64(tstamp), parent.Header()),
   264  		GasLimit:   minter.eth.calcGasLimitFunc(parent),
   265  		GasUsed:    0,
   266  		Coinbase:   minter.coinbase,
   267  		Time:       uint64(tstamp),
   268  	}
   269  
   270  	publicState, privateState, err := minter.chain.StateAt(parent.Root())
   271  	if err != nil {
   272  		panic(fmt.Sprint("failed to get parent state: ", err))
   273  	}
   274  
   275  	return &work{
   276  		config:       minter.config,
   277  		publicState:  publicState,
   278  		privateState: privateState,
   279  		header:       header,
   280  	}
   281  }
   282  
   283  func (minter *minter) getTransactions() *types.TransactionsByPriceAndNonce {
   284  	allAddrTxes, err := minter.eth.TxPool().Pending()
   285  	if err != nil { // TODO: handle
   286  		panic(err)
   287  	}
   288  	addrTxes := minter.speculativeChain.withoutProposedTxes(allAddrTxes)
   289  	signer := types.MakeSigner(minter.chain.Config(), minter.chain.CurrentBlock().Number())
   290  	return types.NewTransactionsByPriceAndNonce(signer, addrTxes)
   291  }
   292  
   293  // Sends-off events asynchronously.
   294  func (minter *minter) firePendingBlockEvents(logs []*types.Log) {
   295  	// Copy logs before we mutate them, adding a block hash.
   296  	copiedLogs := make([]*types.Log, len(logs))
   297  	for i, l := range logs {
   298  		copiedLogs[i] = new(types.Log)
   299  		*copiedLogs[i] = *l
   300  	}
   301  
   302  	go func() {
   303  		minter.mux.Post(core.PendingLogsEvent{Logs: copiedLogs})
   304  		minter.mux.Post(core.PendingStateEvent{})
   305  	}()
   306  }
   307  
   308  func (minter *minter) mintNewBlock() {
   309  	minter.mu.Lock()
   310  	defer minter.mu.Unlock()
   311  
   312  	work := minter.createWork()
   313  	transactions := minter.getTransactions()
   314  
   315  	committedTxes, publicReceipts, _, logs := work.commitTransactions(transactions, minter.chain)
   316  	txCount := len(committedTxes)
   317  
   318  	if txCount == 0 {
   319  		log.Info("Not minting a new block since there are no pending transactions")
   320  		return
   321  	}
   322  
   323  	minter.firePendingBlockEvents(logs)
   324  
   325  	header := work.header
   326  
   327  	// commit state root after all state transitions.
   328  	ethash.AccumulateRewards(minter.chain.Config(), work.publicState, header, nil)
   329  	header.Root = work.publicState.IntermediateRoot(minter.chain.Config().IsEIP158(work.header.Number))
   330  
   331  	// update block hash since it is now available, but was not when the
   332  	// receipt/log of individual transactions were created:
   333  	headerHash := header.Hash()
   334  	for _, l := range logs {
   335  		l.BlockHash = headerHash
   336  	}
   337  
   338  	//Sign the block and build the extraSeal struct
   339  	extraSealBytes := minter.buildExtraSeal(headerHash)
   340  
   341  	// add vanity and seal to header
   342  	// NOTE: leaving vanity blank for now as a space for any future data
   343  	header.Extra = make([]byte, extraVanity+len(extraSealBytes))
   344  	copy(header.Extra[extraVanity:], extraSealBytes)
   345  
   346  	block := types.NewBlock(header, committedTxes, nil, publicReceipts)
   347  
   348  	log.Info("Generated next block", "block num", block.Number(), "num txes", txCount)
   349  
   350  	deleteEmptyObjects := minter.chain.Config().IsEIP158(block.Number())
   351  	if err := minter.chain.CommitBlockWithState(deleteEmptyObjects, work.publicState, work.privateState); err != nil {
   352  		panic(err)
   353  	}
   354  
   355  	minter.speculativeChain.extend(block)
   356  
   357  	minter.mux.Post(core.NewMinedBlockEvent{Block: block})
   358  
   359  	elapsed := time.Since(time.Unix(0, int64(header.Time)))
   360  	log.Info("🔨  Mined block", "number", block.Number(), "hash", fmt.Sprintf("%x", block.Hash().Bytes()[:4]), "elapsed", elapsed)
   361  }
   362  
   363  func (env *work) commitTransactions(txes *types.TransactionsByPriceAndNonce, bc *core.BlockChain) (types.Transactions, types.Receipts, types.Receipts, []*types.Log) {
   364  	var allLogs []*types.Log
   365  	var committedTxes types.Transactions
   366  	var publicReceipts types.Receipts
   367  	var privateReceipts types.Receipts
   368  
   369  	gp := new(core.GasPool).AddGas(env.header.GasLimit)
   370  	txCount := 0
   371  
   372  	for {
   373  		tx := txes.Peek()
   374  		if tx == nil {
   375  			break
   376  		}
   377  
   378  		env.publicState.Prepare(tx.Hash(), common.Hash{}, txCount)
   379  
   380  		publicReceipt, privateReceipt, err := env.commitTransaction(tx, bc, gp)
   381  		switch {
   382  		case err != nil:
   383  			log.Info("TX failed, will be removed", "hash", tx.Hash(), "err", err)
   384  			txes.Pop() // skip rest of txes from this account
   385  		default:
   386  			txCount++
   387  			committedTxes = append(committedTxes, tx)
   388  
   389  			publicReceipts = append(publicReceipts, publicReceipt)
   390  			allLogs = append(allLogs, publicReceipt.Logs...)
   391  
   392  			if privateReceipt != nil {
   393  				privateReceipts = append(privateReceipts, privateReceipt)
   394  				allLogs = append(allLogs, privateReceipt.Logs...)
   395  			}
   396  
   397  			txes.Shift()
   398  		}
   399  	}
   400  
   401  	return committedTxes, publicReceipts, privateReceipts, allLogs
   402  }
   403  
   404  func (env *work) commitTransaction(tx *types.Transaction, bc *core.BlockChain, gp *core.GasPool) (*types.Receipt, *types.Receipt, error) {
   405  	publicSnapshot := env.publicState.Snapshot()
   406  	privateSnapshot := env.privateState.Snapshot()
   407  
   408  	var author *common.Address
   409  	var vmConf vm.Config
   410  	txnStart := time.Now()
   411  	publicReceipt, privateReceipt, err := core.ApplyTransaction(env.config, bc, author, gp, env.publicState, env.privateState, env.header, tx, &env.header.GasUsed, vmConf)
   412  	if err != nil {
   413  		env.publicState.RevertToSnapshot(publicSnapshot)
   414  		env.privateState.RevertToSnapshot(privateSnapshot)
   415  
   416  		return nil, nil, err
   417  	}
   418  	log.EmitCheckpoint(log.TxCompleted, "tx", tx.Hash().Hex(), "time", time.Since(txnStart))
   419  
   420  	return publicReceipt, privateReceipt, nil
   421  }
   422  
   423  func (minter *minter) buildExtraSeal(headerHash common.Hash) []byte {
   424  	//Sign the headerHash
   425  	nodeKey := minter.eth.nodeKey
   426  	sig, err := crypto.Sign(headerHash.Bytes(), nodeKey)
   427  	if err != nil {
   428  		log.Warn("Block sealing failed", "err", err)
   429  	}
   430  
   431  	//build the extraSeal struct
   432  	raftIdString := hexutil.EncodeUint64(uint64(minter.eth.raftProtocolManager.raftId))
   433  
   434  	extra := extraSeal{
   435  		RaftId:    []byte(raftIdString[2:]), //remove the 0x prefix
   436  		Signature: sig,
   437  	}
   438  
   439  	//encode to byte array for storage
   440  	extraDataBytes, err := rlp.EncodeToBytes(extra)
   441  	if err != nil {
   442  		log.Warn("Header.Extra Data Encoding failed", "err", err)
   443  	}
   444  
   445  	return extraDataBytes
   446  }