forked from cerc-io/ipld-eth-server
* Add vendor dir so builds dont require dep * Pin specific version go-eth version
This commit is contained in:
+969
@@ -0,0 +1,969 @@
|
||||
// Copyright (c) 2014-2016 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package mining
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"container/heap"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/blockchain"
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcutil"
|
||||
)
|
||||
|
||||
const (
|
||||
// MinHighPriority is the minimum priority value that allows a
|
||||
// transaction to be considered high priority.
|
||||
MinHighPriority = btcutil.SatoshiPerBitcoin * 144.0 / 250
|
||||
|
||||
// blockHeaderOverhead is the max number of bytes it takes to serialize
|
||||
// a block header and max possible transaction count.
|
||||
blockHeaderOverhead = wire.MaxBlockHeaderPayload + wire.MaxVarIntPayload
|
||||
|
||||
// CoinbaseFlags is added to the coinbase script of a generated block
|
||||
// and is used to monitor BIP16 support as well as blocks that are
|
||||
// generated via btcd.
|
||||
CoinbaseFlags = "/P2SH/btcd/"
|
||||
)
|
||||
|
||||
// TxDesc is a descriptor about a transaction in a transaction source along with
|
||||
// additional metadata.
|
||||
type TxDesc struct {
|
||||
// Tx is the transaction associated with the entry.
|
||||
Tx *btcutil.Tx
|
||||
|
||||
// Added is the time when the entry was added to the source pool.
|
||||
Added time.Time
|
||||
|
||||
// Height is the block height when the entry was added to the the source
|
||||
// pool.
|
||||
Height int32
|
||||
|
||||
// Fee is the total fee the transaction associated with the entry pays.
|
||||
Fee int64
|
||||
|
||||
// FeePerKB is the fee the transaction pays in Satoshi per 1000 bytes.
|
||||
FeePerKB int64
|
||||
}
|
||||
|
||||
// TxSource represents a source of transactions to consider for inclusion in
|
||||
// new blocks.
|
||||
//
|
||||
// The interface contract requires that all of these methods are safe for
|
||||
// concurrent access with respect to the source.
|
||||
type TxSource interface {
|
||||
// LastUpdated returns the last time a transaction was added to or
|
||||
// removed from the source pool.
|
||||
LastUpdated() time.Time
|
||||
|
||||
// MiningDescs returns a slice of mining descriptors for all the
|
||||
// transactions in the source pool.
|
||||
MiningDescs() []*TxDesc
|
||||
|
||||
// HaveTransaction returns whether or not the passed transaction hash
|
||||
// exists in the source pool.
|
||||
HaveTransaction(hash *chainhash.Hash) bool
|
||||
}
|
||||
|
||||
// txPrioItem houses a transaction along with extra information that allows the
|
||||
// transaction to be prioritized and track dependencies on other transactions
|
||||
// which have not been mined into a block yet.
|
||||
type txPrioItem struct {
|
||||
tx *btcutil.Tx
|
||||
fee int64
|
||||
priority float64
|
||||
feePerKB int64
|
||||
|
||||
// dependsOn holds a map of transaction hashes which this one depends
|
||||
// on. It will only be set when the transaction references other
|
||||
// transactions in the source pool and hence must come after them in
|
||||
// a block.
|
||||
dependsOn map[chainhash.Hash]struct{}
|
||||
}
|
||||
|
||||
// txPriorityQueueLessFunc describes a function that can be used as a compare
|
||||
// function for a transaction priority queue (txPriorityQueue).
|
||||
type txPriorityQueueLessFunc func(*txPriorityQueue, int, int) bool
|
||||
|
||||
// txPriorityQueue implements a priority queue of txPrioItem elements that
|
||||
// supports an arbitrary compare function as defined by txPriorityQueueLessFunc.
|
||||
type txPriorityQueue struct {
|
||||
lessFunc txPriorityQueueLessFunc
|
||||
items []*txPrioItem
|
||||
}
|
||||
|
||||
// Len returns the number of items in the priority queue. It is part of the
|
||||
// heap.Interface implementation.
|
||||
func (pq *txPriorityQueue) Len() int {
|
||||
return len(pq.items)
|
||||
}
|
||||
|
||||
// Less returns whether the item in the priority queue with index i should sort
|
||||
// before the item with index j by deferring to the assigned less function. It
|
||||
// is part of the heap.Interface implementation.
|
||||
func (pq *txPriorityQueue) Less(i, j int) bool {
|
||||
return pq.lessFunc(pq, i, j)
|
||||
}
|
||||
|
||||
// Swap swaps the items at the passed indices in the priority queue. It is
|
||||
// part of the heap.Interface implementation.
|
||||
func (pq *txPriorityQueue) Swap(i, j int) {
|
||||
pq.items[i], pq.items[j] = pq.items[j], pq.items[i]
|
||||
}
|
||||
|
||||
// Push pushes the passed item onto the priority queue. It is part of the
|
||||
// heap.Interface implementation.
|
||||
func (pq *txPriorityQueue) Push(x interface{}) {
|
||||
pq.items = append(pq.items, x.(*txPrioItem))
|
||||
}
|
||||
|
||||
// Pop removes the highest priority item (according to Less) from the priority
|
||||
// queue and returns it. It is part of the heap.Interface implementation.
|
||||
func (pq *txPriorityQueue) Pop() interface{} {
|
||||
n := len(pq.items)
|
||||
item := pq.items[n-1]
|
||||
pq.items[n-1] = nil
|
||||
pq.items = pq.items[0 : n-1]
|
||||
return item
|
||||
}
|
||||
|
||||
// SetLessFunc sets the compare function for the priority queue to the provided
|
||||
// function. It also invokes heap.Init on the priority queue using the new
|
||||
// function so it can immediately be used with heap.Push/Pop.
|
||||
func (pq *txPriorityQueue) SetLessFunc(lessFunc txPriorityQueueLessFunc) {
|
||||
pq.lessFunc = lessFunc
|
||||
heap.Init(pq)
|
||||
}
|
||||
|
||||
// txPQByPriority sorts a txPriorityQueue by transaction priority and then fees
|
||||
// per kilobyte.
|
||||
func txPQByPriority(pq *txPriorityQueue, i, j int) bool {
|
||||
// Using > here so that pop gives the highest priority item as opposed
|
||||
// to the lowest. Sort by priority first, then fee.
|
||||
if pq.items[i].priority == pq.items[j].priority {
|
||||
return pq.items[i].feePerKB > pq.items[j].feePerKB
|
||||
}
|
||||
return pq.items[i].priority > pq.items[j].priority
|
||||
|
||||
}
|
||||
|
||||
// txPQByFee sorts a txPriorityQueue by fees per kilobyte and then transaction
|
||||
// priority.
|
||||
func txPQByFee(pq *txPriorityQueue, i, j int) bool {
|
||||
// Using > here so that pop gives the highest fee item as opposed
|
||||
// to the lowest. Sort by fee first, then priority.
|
||||
if pq.items[i].feePerKB == pq.items[j].feePerKB {
|
||||
return pq.items[i].priority > pq.items[j].priority
|
||||
}
|
||||
return pq.items[i].feePerKB > pq.items[j].feePerKB
|
||||
}
|
||||
|
||||
// newTxPriorityQueue returns a new transaction priority queue that reserves the
|
||||
// passed amount of space for the elements. The new priority queue uses either
|
||||
// the txPQByPriority or the txPQByFee compare function depending on the
|
||||
// sortByFee parameter and is already initialized for use with heap.Push/Pop.
|
||||
// The priority queue can grow larger than the reserved space, but extra copies
|
||||
// of the underlying array can be avoided by reserving a sane value.
|
||||
func newTxPriorityQueue(reserve int, sortByFee bool) *txPriorityQueue {
|
||||
pq := &txPriorityQueue{
|
||||
items: make([]*txPrioItem, 0, reserve),
|
||||
}
|
||||
if sortByFee {
|
||||
pq.SetLessFunc(txPQByFee)
|
||||
} else {
|
||||
pq.SetLessFunc(txPQByPriority)
|
||||
}
|
||||
return pq
|
||||
}
|
||||
|
||||
// BlockTemplate houses a block that has yet to be solved along with additional
|
||||
// details about the fees and the number of signature operations for each
|
||||
// transaction in the block.
|
||||
type BlockTemplate struct {
|
||||
// Block is a block that is ready to be solved by miners. Thus, it is
|
||||
// completely valid with the exception of satisfying the proof-of-work
|
||||
// requirement.
|
||||
Block *wire.MsgBlock
|
||||
|
||||
// Fees contains the amount of fees each transaction in the generated
|
||||
// template pays in base units. Since the first transaction is the
|
||||
// coinbase, the first entry (offset 0) will contain the negative of the
|
||||
// sum of the fees of all other transactions.
|
||||
Fees []int64
|
||||
|
||||
// SigOpCosts contains the number of signature operations each
|
||||
// transaction in the generated template performs.
|
||||
SigOpCosts []int64
|
||||
|
||||
// Height is the height at which the block template connects to the main
|
||||
// chain.
|
||||
Height int32
|
||||
|
||||
// ValidPayAddress indicates whether or not the template coinbase pays
|
||||
// to an address or is redeemable by anyone. See the documentation on
|
||||
// NewBlockTemplate for details on which this can be useful to generate
|
||||
// templates without a coinbase payment address.
|
||||
ValidPayAddress bool
|
||||
|
||||
// WitnessCommitment is a commitment to the witness data (if any)
|
||||
// within the block. This field will only be populted once segregated
|
||||
// witness has been activated, and the block contains a transaction
|
||||
// which has witness data.
|
||||
WitnessCommitment []byte
|
||||
}
|
||||
|
||||
// mergeUtxoView adds all of the entries in view to viewA. The result is that
|
||||
// viewA will contain all of its original entries plus all of the entries
|
||||
// in viewB. It will replace any entries in viewB which also exist in viewA
|
||||
// if the entry in viewA is fully spent.
|
||||
func mergeUtxoView(viewA *blockchain.UtxoViewpoint, viewB *blockchain.UtxoViewpoint) {
|
||||
viewAEntries := viewA.Entries()
|
||||
for hash, entryB := range viewB.Entries() {
|
||||
if entryA, exists := viewAEntries[hash]; !exists ||
|
||||
entryA == nil || entryA.IsFullySpent() {
|
||||
|
||||
viewAEntries[hash] = entryB
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// standardCoinbaseScript returns a standard script suitable for use as the
|
||||
// signature script of the coinbase transaction of a new block. In particular,
|
||||
// it starts with the block height that is required by version 2 blocks and adds
|
||||
// the extra nonce as well as additional coinbase flags.
|
||||
func standardCoinbaseScript(nextBlockHeight int32, extraNonce uint64) ([]byte, error) {
|
||||
return txscript.NewScriptBuilder().AddInt64(int64(nextBlockHeight)).
|
||||
AddInt64(int64(extraNonce)).AddData([]byte(CoinbaseFlags)).
|
||||
Script()
|
||||
}
|
||||
|
||||
// createCoinbaseTx returns a coinbase transaction paying an appropriate subsidy
|
||||
// based on the passed block height to the provided address. When the address
|
||||
// is nil, the coinbase transaction will instead be redeemable by anyone.
|
||||
//
|
||||
// See the comment for NewBlockTemplate for more information about why the nil
|
||||
// address handling is useful.
|
||||
func createCoinbaseTx(params *chaincfg.Params, coinbaseScript []byte, nextBlockHeight int32, addr btcutil.Address) (*btcutil.Tx, error) {
|
||||
// Create the script to pay to the provided payment address if one was
|
||||
// specified. Otherwise create a script that allows the coinbase to be
|
||||
// redeemable by anyone.
|
||||
var pkScript []byte
|
||||
if addr != nil {
|
||||
var err error
|
||||
pkScript, err = txscript.PayToAddrScript(addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
var err error
|
||||
scriptBuilder := txscript.NewScriptBuilder()
|
||||
pkScript, err = scriptBuilder.AddOp(txscript.OP_TRUE).Script()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
tx := wire.NewMsgTx(wire.TxVersion)
|
||||
tx.AddTxIn(&wire.TxIn{
|
||||
// Coinbase transactions have no inputs, so previous outpoint is
|
||||
// zero hash and max index.
|
||||
PreviousOutPoint: *wire.NewOutPoint(&chainhash.Hash{},
|
||||
wire.MaxPrevOutIndex),
|
||||
SignatureScript: coinbaseScript,
|
||||
Sequence: wire.MaxTxInSequenceNum,
|
||||
})
|
||||
tx.AddTxOut(&wire.TxOut{
|
||||
Value: blockchain.CalcBlockSubsidy(nextBlockHeight, params),
|
||||
PkScript: pkScript,
|
||||
})
|
||||
return btcutil.NewTx(tx), nil
|
||||
}
|
||||
|
||||
// spendTransaction updates the passed view by marking the inputs to the passed
|
||||
// transaction as spent. It also adds all outputs in the passed transaction
|
||||
// which are not provably unspendable as available unspent transaction outputs.
|
||||
func spendTransaction(utxoView *blockchain.UtxoViewpoint, tx *btcutil.Tx, height int32) error {
|
||||
for _, txIn := range tx.MsgTx().TxIn {
|
||||
originHash := &txIn.PreviousOutPoint.Hash
|
||||
originIndex := txIn.PreviousOutPoint.Index
|
||||
entry := utxoView.LookupEntry(originHash)
|
||||
if entry != nil {
|
||||
entry.SpendOutput(originIndex)
|
||||
}
|
||||
}
|
||||
|
||||
utxoView.AddTxOuts(tx, height)
|
||||
return nil
|
||||
}
|
||||
|
||||
// logSkippedDeps logs any dependencies which are also skipped as a result of
|
||||
// skipping a transaction while generating a block template at the trace level.
|
||||
func logSkippedDeps(tx *btcutil.Tx, deps map[chainhash.Hash]*txPrioItem) {
|
||||
if deps == nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, item := range deps {
|
||||
log.Tracef("Skipping tx %s since it depends on %s\n",
|
||||
item.tx.Hash(), tx.Hash())
|
||||
}
|
||||
}
|
||||
|
||||
// MinimumMedianTime returns the minimum allowed timestamp for a block building
|
||||
// on the end of the provided best chain. In particular, it is one second after
|
||||
// the median timestamp of the last several blocks per the chain consensus
|
||||
// rules.
|
||||
func MinimumMedianTime(chainState *blockchain.BestState) time.Time {
|
||||
return chainState.MedianTime.Add(time.Second)
|
||||
}
|
||||
|
||||
// medianAdjustedTime returns the current time adjusted to ensure it is at least
|
||||
// one second after the median timestamp of the last several blocks per the
|
||||
// chain consensus rules.
|
||||
func medianAdjustedTime(chainState *blockchain.BestState, timeSource blockchain.MedianTimeSource) time.Time {
|
||||
// The timestamp for the block must not be before the median timestamp
|
||||
// of the last several blocks. Thus, choose the maximum between the
|
||||
// current time and one second after the past median time. The current
|
||||
// timestamp is truncated to a second boundary before comparison since a
|
||||
// block timestamp does not supported a precision greater than one
|
||||
// second.
|
||||
newTimestamp := timeSource.AdjustedTime()
|
||||
minTimestamp := MinimumMedianTime(chainState)
|
||||
if newTimestamp.Before(minTimestamp) {
|
||||
newTimestamp = minTimestamp
|
||||
}
|
||||
|
||||
return newTimestamp
|
||||
}
|
||||
|
||||
// BlkTmplGenerator provides a type that can be used to generate block templates
|
||||
// based on a given mining policy and source of transactions to choose from.
|
||||
// It also houses additional state required in order to ensure the templates
|
||||
// are built on top of the current best chain and adhere to the consensus rules.
|
||||
type BlkTmplGenerator struct {
|
||||
policy *Policy
|
||||
chainParams *chaincfg.Params
|
||||
txSource TxSource
|
||||
chain *blockchain.BlockChain
|
||||
timeSource blockchain.MedianTimeSource
|
||||
sigCache *txscript.SigCache
|
||||
hashCache *txscript.HashCache
|
||||
}
|
||||
|
||||
// NewBlkTmplGenerator returns a new block template generator for the given
|
||||
// policy using transactions from the provided transaction source.
|
||||
//
|
||||
// The additional state-related fields are required in order to ensure the
|
||||
// templates are built on top of the current best chain and adhere to the
|
||||
// consensus rules.
|
||||
func NewBlkTmplGenerator(policy *Policy, params *chaincfg.Params,
|
||||
txSource TxSource, chain *blockchain.BlockChain,
|
||||
timeSource blockchain.MedianTimeSource,
|
||||
sigCache *txscript.SigCache,
|
||||
hashCache *txscript.HashCache) *BlkTmplGenerator {
|
||||
|
||||
return &BlkTmplGenerator{
|
||||
policy: policy,
|
||||
chainParams: params,
|
||||
txSource: txSource,
|
||||
chain: chain,
|
||||
timeSource: timeSource,
|
||||
sigCache: sigCache,
|
||||
hashCache: hashCache,
|
||||
}
|
||||
}
|
||||
|
||||
// NewBlockTemplate returns a new block template that is ready to be solved
|
||||
// using the transactions from the passed transaction source pool and a coinbase
|
||||
// that either pays to the passed address if it is not nil, or a coinbase that
|
||||
// is redeemable by anyone if the passed address is nil. The nil address
|
||||
// functionality is useful since there are cases such as the getblocktemplate
|
||||
// RPC where external mining software is responsible for creating their own
|
||||
// coinbase which will replace the one generated for the block template. Thus
|
||||
// the need to have configured address can be avoided.
|
||||
//
|
||||
// The transactions selected and included are prioritized according to several
|
||||
// factors. First, each transaction has a priority calculated based on its
|
||||
// value, age of inputs, and size. Transactions which consist of larger
|
||||
// amounts, older inputs, and small sizes have the highest priority. Second, a
|
||||
// fee per kilobyte is calculated for each transaction. Transactions with a
|
||||
// higher fee per kilobyte are preferred. Finally, the block generation related
|
||||
// policy settings are all taken into account.
|
||||
//
|
||||
// Transactions which only spend outputs from other transactions already in the
|
||||
// block chain are immediately added to a priority queue which either
|
||||
// prioritizes based on the priority (then fee per kilobyte) or the fee per
|
||||
// kilobyte (then priority) depending on whether or not the BlockPrioritySize
|
||||
// policy setting allots space for high-priority transactions. Transactions
|
||||
// which spend outputs from other transactions in the source pool are added to a
|
||||
// dependency map so they can be added to the priority queue once the
|
||||
// transactions they depend on have been included.
|
||||
//
|
||||
// Once the high-priority area (if configured) has been filled with
|
||||
// transactions, or the priority falls below what is considered high-priority,
|
||||
// the priority queue is updated to prioritize by fees per kilobyte (then
|
||||
// priority).
|
||||
//
|
||||
// When the fees per kilobyte drop below the TxMinFreeFee policy setting, the
|
||||
// transaction will be skipped unless the BlockMinSize policy setting is
|
||||
// nonzero, in which case the block will be filled with the low-fee/free
|
||||
// transactions until the block size reaches that minimum size.
|
||||
//
|
||||
// Any transactions which would cause the block to exceed the BlockMaxSize
|
||||
// policy setting, exceed the maximum allowed signature operations per block, or
|
||||
// otherwise cause the block to be invalid are skipped.
|
||||
//
|
||||
// Given the above, a block generated by this function is of the following form:
|
||||
//
|
||||
// ----------------------------------- -- --
|
||||
// | Coinbase Transaction | | |
|
||||
// |-----------------------------------| | |
|
||||
// | | | | ----- policy.BlockPrioritySize
|
||||
// | High-priority Transactions | | |
|
||||
// | | | |
|
||||
// |-----------------------------------| | --
|
||||
// | | |
|
||||
// | | |
|
||||
// | | |--- policy.BlockMaxSize
|
||||
// | Transactions prioritized by fee | |
|
||||
// | until <= policy.TxMinFreeFee | |
|
||||
// | | |
|
||||
// | | |
|
||||
// | | |
|
||||
// |-----------------------------------| |
|
||||
// | Low-fee/Non high-priority (free) | |
|
||||
// | transactions (while block size | |
|
||||
// | <= policy.BlockMinSize) | |
|
||||
// ----------------------------------- --
|
||||
func (g *BlkTmplGenerator) NewBlockTemplate(payToAddress btcutil.Address) (*BlockTemplate, error) {
|
||||
// Extend the most recently known best block.
|
||||
best := g.chain.BestSnapshot()
|
||||
nextBlockHeight := best.Height + 1
|
||||
|
||||
// Create a standard coinbase transaction paying to the provided
|
||||
// address. NOTE: The coinbase value will be updated to include the
|
||||
// fees from the selected transactions later after they have actually
|
||||
// been selected. It is created here to detect any errors early
|
||||
// before potentially doing a lot of work below. The extra nonce helps
|
||||
// ensure the transaction is not a duplicate transaction (paying the
|
||||
// same value to the same public key address would otherwise be an
|
||||
// identical transaction for block version 1).
|
||||
extraNonce := uint64(0)
|
||||
coinbaseScript, err := standardCoinbaseScript(nextBlockHeight, extraNonce)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
coinbaseTx, err := createCoinbaseTx(g.chainParams, coinbaseScript,
|
||||
nextBlockHeight, payToAddress)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
coinbaseSigOpCost := int64(blockchain.CountSigOps(coinbaseTx)) * blockchain.WitnessScaleFactor
|
||||
|
||||
// Get the current source transactions and create a priority queue to
|
||||
// hold the transactions which are ready for inclusion into a block
|
||||
// along with some priority related and fee metadata. Reserve the same
|
||||
// number of items that are available for the priority queue. Also,
|
||||
// choose the initial sort order for the priority queue based on whether
|
||||
// or not there is an area allocated for high-priority transactions.
|
||||
sourceTxns := g.txSource.MiningDescs()
|
||||
sortedByFee := g.policy.BlockPrioritySize == 0
|
||||
priorityQueue := newTxPriorityQueue(len(sourceTxns), sortedByFee)
|
||||
|
||||
// Create a slice to hold the transactions to be included in the
|
||||
// generated block with reserved space. Also create a utxo view to
|
||||
// house all of the input transactions so multiple lookups can be
|
||||
// avoided.
|
||||
blockTxns := make([]*btcutil.Tx, 0, len(sourceTxns))
|
||||
blockTxns = append(blockTxns, coinbaseTx)
|
||||
blockUtxos := blockchain.NewUtxoViewpoint()
|
||||
|
||||
// dependers is used to track transactions which depend on another
|
||||
// transaction in the source pool. This, in conjunction with the
|
||||
// dependsOn map kept with each dependent transaction helps quickly
|
||||
// determine which dependent transactions are now eligible for inclusion
|
||||
// in the block once each transaction has been included.
|
||||
dependers := make(map[chainhash.Hash]map[chainhash.Hash]*txPrioItem)
|
||||
|
||||
// Create slices to hold the fees and number of signature operations
|
||||
// for each of the selected transactions and add an entry for the
|
||||
// coinbase. This allows the code below to simply append details about
|
||||
// a transaction as it is selected for inclusion in the final block.
|
||||
// However, since the total fees aren't known yet, use a dummy value for
|
||||
// the coinbase fee which will be updated later.
|
||||
txFees := make([]int64, 0, len(sourceTxns))
|
||||
txSigOpCosts := make([]int64, 0, len(sourceTxns))
|
||||
txFees = append(txFees, -1) // Updated once known
|
||||
txSigOpCosts = append(txSigOpCosts, coinbaseSigOpCost)
|
||||
|
||||
log.Debugf("Considering %d transactions for inclusion to new block",
|
||||
len(sourceTxns))
|
||||
|
||||
mempoolLoop:
|
||||
for _, txDesc := range sourceTxns {
|
||||
// A block can't have more than one coinbase or contain
|
||||
// non-finalized transactions.
|
||||
tx := txDesc.Tx
|
||||
if blockchain.IsCoinBase(tx) {
|
||||
log.Tracef("Skipping coinbase tx %s", tx.Hash())
|
||||
continue
|
||||
}
|
||||
if !blockchain.IsFinalizedTransaction(tx, nextBlockHeight,
|
||||
g.timeSource.AdjustedTime()) {
|
||||
|
||||
log.Tracef("Skipping non-finalized tx %s", tx.Hash())
|
||||
continue
|
||||
}
|
||||
|
||||
// Fetch all of the utxos referenced by the this transaction.
|
||||
// NOTE: This intentionally does not fetch inputs from the
|
||||
// mempool since a transaction which depends on other
|
||||
// transactions in the mempool must come after those
|
||||
// dependencies in the final generated block.
|
||||
utxos, err := g.chain.FetchUtxoView(tx)
|
||||
if err != nil {
|
||||
log.Warnf("Unable to fetch utxo view for tx %s: %v",
|
||||
tx.Hash(), err)
|
||||
continue
|
||||
}
|
||||
|
||||
// Setup dependencies for any transactions which reference
|
||||
// other transactions in the mempool so they can be properly
|
||||
// ordered below.
|
||||
prioItem := &txPrioItem{tx: tx}
|
||||
for _, txIn := range tx.MsgTx().TxIn {
|
||||
originHash := &txIn.PreviousOutPoint.Hash
|
||||
originIndex := txIn.PreviousOutPoint.Index
|
||||
utxoEntry := utxos.LookupEntry(originHash)
|
||||
if utxoEntry == nil || utxoEntry.IsOutputSpent(originIndex) {
|
||||
if !g.txSource.HaveTransaction(originHash) {
|
||||
log.Tracef("Skipping tx %s because it "+
|
||||
"references unspent output %s "+
|
||||
"which is not available",
|
||||
tx.Hash(), txIn.PreviousOutPoint)
|
||||
continue mempoolLoop
|
||||
}
|
||||
|
||||
// The transaction is referencing another
|
||||
// transaction in the source pool, so setup an
|
||||
// ordering dependency.
|
||||
deps, exists := dependers[*originHash]
|
||||
if !exists {
|
||||
deps = make(map[chainhash.Hash]*txPrioItem)
|
||||
dependers[*originHash] = deps
|
||||
}
|
||||
deps[*prioItem.tx.Hash()] = prioItem
|
||||
if prioItem.dependsOn == nil {
|
||||
prioItem.dependsOn = make(
|
||||
map[chainhash.Hash]struct{})
|
||||
}
|
||||
prioItem.dependsOn[*originHash] = struct{}{}
|
||||
|
||||
// Skip the check below. We already know the
|
||||
// referenced transaction is available.
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the final transaction priority using the input
|
||||
// value age sum as well as the adjusted transaction size. The
|
||||
// formula is: sum(inputValue * inputAge) / adjustedTxSize
|
||||
prioItem.priority = CalcPriority(tx.MsgTx(), utxos,
|
||||
nextBlockHeight)
|
||||
|
||||
// Calculate the fee in Satoshi/kB.
|
||||
prioItem.feePerKB = txDesc.FeePerKB
|
||||
prioItem.fee = txDesc.Fee
|
||||
|
||||
// Add the transaction to the priority queue to mark it ready
|
||||
// for inclusion in the block unless it has dependencies.
|
||||
if prioItem.dependsOn == nil {
|
||||
heap.Push(priorityQueue, prioItem)
|
||||
}
|
||||
|
||||
// Merge the referenced outputs from the input transactions to
|
||||
// this transaction into the block utxo view. This allows the
|
||||
// code below to avoid a second lookup.
|
||||
mergeUtxoView(blockUtxos, utxos)
|
||||
}
|
||||
|
||||
log.Tracef("Priority queue len %d, dependers len %d",
|
||||
priorityQueue.Len(), len(dependers))
|
||||
|
||||
// The starting block size is the size of the block header plus the max
|
||||
// possible transaction count size, plus the size of the coinbase
|
||||
// transaction.
|
||||
blockWeight := uint32((blockHeaderOverhead * blockchain.WitnessScaleFactor) +
|
||||
blockchain.GetTransactionWeight(coinbaseTx))
|
||||
blockSigOpCost := coinbaseSigOpCost
|
||||
totalFees := int64(0)
|
||||
|
||||
// Query the version bits state to see if segwit has been activated, if
|
||||
// so then this means that we'll include any transactions with witness
|
||||
// data in the mempool, and also add the witness commitment as an
|
||||
// OP_RETURN output in the coinbase transaction.
|
||||
segwitState, err := g.chain.ThresholdState(chaincfg.DeploymentSegwit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
segwitActive := segwitState == blockchain.ThresholdActive
|
||||
|
||||
witnessIncluded := false
|
||||
|
||||
// Choose which transactions make it into the block.
|
||||
for priorityQueue.Len() > 0 {
|
||||
// Grab the highest priority (or highest fee per kilobyte
|
||||
// depending on the sort order) transaction.
|
||||
prioItem := heap.Pop(priorityQueue).(*txPrioItem)
|
||||
tx := prioItem.tx
|
||||
|
||||
switch {
|
||||
// If segregated witness has not been activated yet, then we
|
||||
// shouldn't include any witness transactions in the block.
|
||||
case !segwitActive && tx.HasWitness():
|
||||
continue
|
||||
|
||||
// Otherwise, Keep track of if we've included a transaction
|
||||
// with witness data or not. If so, then we'll need to include
|
||||
// the witness commitment as the last output in the coinbase
|
||||
// transaction.
|
||||
case segwitActive && !witnessIncluded && tx.HasWitness():
|
||||
// If we're about to include a transaction bearing
|
||||
// witness data, then we'll also need to include a
|
||||
// witness commitment in the coinbase transaction.
|
||||
// Therefore, we account for the additional weight
|
||||
// within the block with a model coinbase tx with a
|
||||
// witness commitment.
|
||||
coinbaseCopy := btcutil.NewTx(coinbaseTx.MsgTx().Copy())
|
||||
coinbaseCopy.MsgTx().TxIn[0].Witness = [][]byte{
|
||||
bytes.Repeat([]byte("a"),
|
||||
blockchain.CoinbaseWitnessDataLen),
|
||||
}
|
||||
coinbaseCopy.MsgTx().AddTxOut(&wire.TxOut{
|
||||
PkScript: bytes.Repeat([]byte("a"),
|
||||
blockchain.CoinbaseWitnessPkScriptLength),
|
||||
})
|
||||
|
||||
// In order to accurately account for the weight
|
||||
// addition due to this coinbase transaction, we'll add
|
||||
// the difference of the transaction before and after
|
||||
// the addition of the commitment to the block weight.
|
||||
weightDiff := blockchain.GetTransactionWeight(coinbaseCopy) -
|
||||
blockchain.GetTransactionWeight(coinbaseTx)
|
||||
|
||||
blockWeight += uint32(weightDiff)
|
||||
|
||||
witnessIncluded = true
|
||||
}
|
||||
|
||||
// Grab any transactions which depend on this one.
|
||||
deps := dependers[*tx.Hash()]
|
||||
|
||||
// Enforce maximum block size. Also check for overflow.
|
||||
txWeight := uint32(blockchain.GetTransactionWeight(tx))
|
||||
blockPlusTxWeight := blockWeight + txWeight
|
||||
if blockPlusTxWeight < blockWeight ||
|
||||
blockPlusTxWeight >= g.policy.BlockMaxWeight {
|
||||
|
||||
log.Tracef("Skipping tx %s because it would exceed "+
|
||||
"the max block weight", tx.Hash())
|
||||
logSkippedDeps(tx, deps)
|
||||
continue
|
||||
}
|
||||
|
||||
// Enforce maximum signature operation cost per block. Also
|
||||
// check for overflow.
|
||||
sigOpCost, err := blockchain.GetSigOpCost(tx, false,
|
||||
blockUtxos, true, segwitActive)
|
||||
if err != nil {
|
||||
log.Tracef("Skipping tx %s due to error in "+
|
||||
"GetSigOpCost: %v", tx.Hash(), err)
|
||||
logSkippedDeps(tx, deps)
|
||||
continue
|
||||
}
|
||||
if blockSigOpCost+int64(sigOpCost) < blockSigOpCost ||
|
||||
blockSigOpCost+int64(sigOpCost) > blockchain.MaxBlockSigOpsCost {
|
||||
log.Tracef("Skipping tx %s because it would "+
|
||||
"exceed the maximum sigops per block", tx.Hash())
|
||||
logSkippedDeps(tx, deps)
|
||||
continue
|
||||
}
|
||||
|
||||
// Skip free transactions once the block is larger than the
|
||||
// minimum block size.
|
||||
if sortedByFee &&
|
||||
prioItem.feePerKB < int64(g.policy.TxMinFreeFee) &&
|
||||
blockPlusTxWeight >= g.policy.BlockMinWeight {
|
||||
|
||||
log.Tracef("Skipping tx %s with feePerKB %d "+
|
||||
"< TxMinFreeFee %d and block weight %d >= "+
|
||||
"minBlockWeight %d", tx.Hash(), prioItem.feePerKB,
|
||||
g.policy.TxMinFreeFee, blockPlusTxWeight,
|
||||
g.policy.BlockMinWeight)
|
||||
logSkippedDeps(tx, deps)
|
||||
continue
|
||||
}
|
||||
|
||||
// Prioritize by fee per kilobyte once the block is larger than
|
||||
// the priority size or there are no more high-priority
|
||||
// transactions.
|
||||
if !sortedByFee && (blockPlusTxWeight >= g.policy.BlockPrioritySize ||
|
||||
prioItem.priority <= MinHighPriority) {
|
||||
|
||||
log.Tracef("Switching to sort by fees per "+
|
||||
"kilobyte blockSize %d >= BlockPrioritySize "+
|
||||
"%d || priority %.2f <= minHighPriority %.2f",
|
||||
blockPlusTxWeight, g.policy.BlockPrioritySize,
|
||||
prioItem.priority, MinHighPriority)
|
||||
|
||||
sortedByFee = true
|
||||
priorityQueue.SetLessFunc(txPQByFee)
|
||||
|
||||
// Put the transaction back into the priority queue and
|
||||
// skip it so it is re-priortized by fees if it won't
|
||||
// fit into the high-priority section or the priority
|
||||
// is too low. Otherwise this transaction will be the
|
||||
// final one in the high-priority section, so just fall
|
||||
// though to the code below so it is added now.
|
||||
if blockPlusTxWeight > g.policy.BlockPrioritySize ||
|
||||
prioItem.priority < MinHighPriority {
|
||||
|
||||
heap.Push(priorityQueue, prioItem)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the transaction inputs pass all of the necessary
|
||||
// preconditions before allowing it to be added to the block.
|
||||
_, err = blockchain.CheckTransactionInputs(tx, nextBlockHeight,
|
||||
blockUtxos, g.chainParams)
|
||||
if err != nil {
|
||||
log.Tracef("Skipping tx %s due to error in "+
|
||||
"CheckTransactionInputs: %v", tx.Hash(), err)
|
||||
logSkippedDeps(tx, deps)
|
||||
continue
|
||||
}
|
||||
err = blockchain.ValidateTransactionScripts(tx, blockUtxos,
|
||||
txscript.StandardVerifyFlags, g.sigCache,
|
||||
g.hashCache)
|
||||
if err != nil {
|
||||
log.Tracef("Skipping tx %s due to error in "+
|
||||
"ValidateTransactionScripts: %v", tx.Hash(), err)
|
||||
logSkippedDeps(tx, deps)
|
||||
continue
|
||||
}
|
||||
|
||||
// Spend the transaction inputs in the block utxo view and add
|
||||
// an entry for it to ensure any transactions which reference
|
||||
// this one have it available as an input and can ensure they
|
||||
// aren't double spending.
|
||||
spendTransaction(blockUtxos, tx, nextBlockHeight)
|
||||
|
||||
// Add the transaction to the block, increment counters, and
|
||||
// save the fees and signature operation counts to the block
|
||||
// template.
|
||||
blockTxns = append(blockTxns, tx)
|
||||
blockWeight += txWeight
|
||||
blockSigOpCost += int64(sigOpCost)
|
||||
totalFees += prioItem.fee
|
||||
txFees = append(txFees, prioItem.fee)
|
||||
txSigOpCosts = append(txSigOpCosts, int64(sigOpCost))
|
||||
|
||||
log.Tracef("Adding tx %s (priority %.2f, feePerKB %.2f)",
|
||||
prioItem.tx.Hash(), prioItem.priority, prioItem.feePerKB)
|
||||
|
||||
// Add transactions which depend on this one (and also do not
|
||||
// have any other unsatisified dependencies) to the priority
|
||||
// queue.
|
||||
for _, item := range deps {
|
||||
// Add the transaction to the priority queue if there
|
||||
// are no more dependencies after this one.
|
||||
delete(item.dependsOn, *tx.Hash())
|
||||
if len(item.dependsOn) == 0 {
|
||||
heap.Push(priorityQueue, item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now that the actual transactions have been selected, update the
|
||||
// block weight for the real transaction count and coinbase value with
|
||||
// the total fees accordingly.
|
||||
blockWeight -= wire.MaxVarIntPayload -
|
||||
(uint32(wire.VarIntSerializeSize(uint64(len(blockTxns)))) *
|
||||
blockchain.WitnessScaleFactor)
|
||||
coinbaseTx.MsgTx().TxOut[0].Value += totalFees
|
||||
txFees[0] = -totalFees
|
||||
|
||||
// If segwit is active and we included transactions with witness data,
|
||||
// then we'll need to include a commitment to the witness data in an
|
||||
// OP_RETURN output within the coinbase transaction.
|
||||
var witnessCommitment []byte
|
||||
if witnessIncluded {
|
||||
// The witness of the coinbase transaction MUST be exactly 32-bytes
|
||||
// of all zeroes.
|
||||
var witnessNonce [blockchain.CoinbaseWitnessDataLen]byte
|
||||
coinbaseTx.MsgTx().TxIn[0].Witness = wire.TxWitness{witnessNonce[:]}
|
||||
|
||||
// Next, obtain the merkle root of a tree which consists of the
|
||||
// wtxid of all transactions in the block. The coinbase
|
||||
// transaction will have a special wtxid of all zeroes.
|
||||
witnessMerkleTree := blockchain.BuildMerkleTreeStore(blockTxns,
|
||||
true)
|
||||
witnessMerkleRoot := witnessMerkleTree[len(witnessMerkleTree)-1]
|
||||
|
||||
// The preimage to the witness commitment is:
|
||||
// witnessRoot || coinbaseWitness
|
||||
var witnessPreimage [64]byte
|
||||
copy(witnessPreimage[:32], witnessMerkleRoot[:])
|
||||
copy(witnessPreimage[32:], witnessNonce[:])
|
||||
|
||||
// The witness commitment itself is the double-sha256 of the
|
||||
// witness preimage generated above. With the commitment
|
||||
// generated, the witness script for the output is: OP_RETURN
|
||||
// OP_DATA_36 {0xaa21a9ed || witnessCommitment}. The leading
|
||||
// prefix is refered to as the "witness magic bytes".
|
||||
witnessCommitment = chainhash.DoubleHashB(witnessPreimage[:])
|
||||
witnessScript := append(blockchain.WitnessMagicBytes, witnessCommitment...)
|
||||
|
||||
// Finally, create the OP_RETURN carrying witness commitment
|
||||
// output as an additional output within the coinbase.
|
||||
commitmentOutput := &wire.TxOut{
|
||||
Value: 0,
|
||||
PkScript: witnessScript,
|
||||
}
|
||||
coinbaseTx.MsgTx().TxOut = append(coinbaseTx.MsgTx().TxOut,
|
||||
commitmentOutput)
|
||||
}
|
||||
|
||||
// Calculate the required difficulty for the block. The timestamp
|
||||
// is potentially adjusted to ensure it comes after the median time of
|
||||
// the last several blocks per the chain consensus rules.
|
||||
ts := medianAdjustedTime(best, g.timeSource)
|
||||
reqDifficulty, err := g.chain.CalcNextRequiredDifficulty(ts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Calculate the next expected block version based on the state of the
|
||||
// rule change deployments.
|
||||
nextBlockVersion, err := g.chain.CalcNextBlockVersion()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Create a new block ready to be solved.
|
||||
merkles := blockchain.BuildMerkleTreeStore(blockTxns, false)
|
||||
var msgBlock wire.MsgBlock
|
||||
msgBlock.Header = wire.BlockHeader{
|
||||
Version: nextBlockVersion,
|
||||
PrevBlock: best.Hash,
|
||||
MerkleRoot: *merkles[len(merkles)-1],
|
||||
Timestamp: ts,
|
||||
Bits: reqDifficulty,
|
||||
}
|
||||
for _, tx := range blockTxns {
|
||||
if err := msgBlock.AddTransaction(tx.MsgTx()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, perform a full check on the created block against the chain
|
||||
// consensus rules to ensure it properly connects to the current best
|
||||
// chain with no issues.
|
||||
block := btcutil.NewBlock(&msgBlock)
|
||||
block.SetHeight(nextBlockHeight)
|
||||
if err := g.chain.CheckConnectBlockTemplate(block); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Debugf("Created new block template (%d transactions, %d in "+
|
||||
"fees, %d signature operations cost, %d weight, target difficulty "+
|
||||
"%064x)", len(msgBlock.Transactions), totalFees, blockSigOpCost,
|
||||
blockWeight, blockchain.CompactToBig(msgBlock.Header.Bits))
|
||||
|
||||
return &BlockTemplate{
|
||||
Block: &msgBlock,
|
||||
Fees: txFees,
|
||||
SigOpCosts: txSigOpCosts,
|
||||
Height: nextBlockHeight,
|
||||
ValidPayAddress: payToAddress != nil,
|
||||
WitnessCommitment: witnessCommitment,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UpdateBlockTime updates the timestamp in the header of the passed block to
|
||||
// the current time while taking into account the median time of the last
|
||||
// several blocks to ensure the new time is after that time per the chain
|
||||
// consensus rules. Finally, it will update the target difficulty if needed
|
||||
// based on the new time for the test networks since their target difficulty can
|
||||
// change based upon time.
|
||||
func (g *BlkTmplGenerator) UpdateBlockTime(msgBlock *wire.MsgBlock) error {
|
||||
// The new timestamp is potentially adjusted to ensure it comes after
|
||||
// the median time of the last several blocks per the chain consensus
|
||||
// rules.
|
||||
newTime := medianAdjustedTime(g.chain.BestSnapshot(), g.timeSource)
|
||||
msgBlock.Header.Timestamp = newTime
|
||||
|
||||
// Recalculate the difficulty if running on a network that requires it.
|
||||
if g.chainParams.ReduceMinDifficulty {
|
||||
difficulty, err := g.chain.CalcNextRequiredDifficulty(newTime)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
msgBlock.Header.Bits = difficulty
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateExtraNonce updates the extra nonce in the coinbase script of the passed
|
||||
// block by regenerating the coinbase script with the passed value and block
|
||||
// height. It also recalculates and updates the new merkle root that results
|
||||
// from changing the coinbase script.
|
||||
func (g *BlkTmplGenerator) UpdateExtraNonce(msgBlock *wire.MsgBlock, blockHeight int32, extraNonce uint64) error {
|
||||
coinbaseScript, err := standardCoinbaseScript(blockHeight, extraNonce)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(coinbaseScript) > blockchain.MaxCoinbaseScriptLen {
|
||||
return fmt.Errorf("coinbase transaction script length "+
|
||||
"of %d is out of range (min: %d, max: %d)",
|
||||
len(coinbaseScript), blockchain.MinCoinbaseScriptLen,
|
||||
blockchain.MaxCoinbaseScriptLen)
|
||||
}
|
||||
msgBlock.Transactions[0].TxIn[0].SignatureScript = coinbaseScript
|
||||
|
||||
// TODO(davec): A btcutil.Block should use saved in the state to avoid
|
||||
// recalculating all of the other transaction hashes.
|
||||
// block.Transactions[0].InvalidateCache()
|
||||
|
||||
// Recalculate the merkle root with the updated extra nonce.
|
||||
block := btcutil.NewBlock(msgBlock)
|
||||
merkles := blockchain.BuildMerkleTreeStore(block.Transactions(), false)
|
||||
msgBlock.Header.MerkleRoot = *merkles[len(merkles)-1]
|
||||
return nil
|
||||
}
|
||||
|
||||
// BestSnapshot returns information about the current best chain block and
|
||||
// related state as of the current point in time using the chain instance
|
||||
// associated with the block template generator. The returned state must be
|
||||
// treated as immutable since it is shared by all callers.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (g *BlkTmplGenerator) BestSnapshot() *blockchain.BestState {
|
||||
return g.chain.BestSnapshot()
|
||||
}
|
||||
|
||||
// TxSource returns the associated transaction source.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (g *BlkTmplGenerator) TxSource() TxSource {
|
||||
return g.txSource
|
||||
}
|
||||
Reference in New Issue
Block a user