kaspad/mining/policy.go
stasatdaglabs 37cd482db3 [DEV-75] Update UTXO model to work with Diffs (#53)
* [DEV-75] Removed fetchEntryByHash, which was no longer used.

* [DEV-75] Removed a few functions in manager.go that weren't used by anything.

* [DEV-75] checkConnectBlock will soon not accept a utxoViewpoint, so removed the call to view.Tip() so that it could be deleted.

* [DEV-75] Got rid of tips in UtxoViewpoint.

* [DEV-75] Added the full UTXO set to the virtual block.

* [DEV-75] Implemented UTXO-wrangling when adding a new block.

* [DEV-75] Added isCoinbase to utxoEntry creation.

* [DEV-75] Added blockHeight to utxoEntry creation.

* Implemented fetching the fullUTXOSet from the database.

* [DEV-75] Simplified DAGState because almost all of the state in it was unnecessary. Also got rid of dbDAGState.

* [DEV-75] Made the process around adding a new block, UTXO-wise, much safer.

* [DEV-75] Implemented melding the virtual UTXO diff to the database.

* [DEV-75] Fixed utxoSet loading from the wrong bucket.

* [DEV-75] Began pruning utxoviewpoint.go. Replaced FetchUtxoEntry with a fullUTXOSet-based GetUTXOEntry.

* [DEV-75] Removed fetchUtxos.

* [DEV-75] Moved GetUTXOEntry into the virtual block.

* [DEV-75] Updated IndexManager to not use utxoViewpoints.

* [DEV-75] Fixed some bad login in restoreUTXO involving nodeDiffs.

* [DEV-75] Got rid of the UTXO spend journal, which wasn't used anywhere.

* [DEV-75] Moved some STXO-related validation logic out of connectToDAG and into checkConnectBlock.

* [DEV-75] Renamed UtxoXxx to UTXOXxx. Removed a bunch of methods that were no longer used by anything.

* [DEV-75] Another Utxo -> UTXO rename.

* [DEV-75] Removed IsModified from UTXOView, which was not used anywhere.

* [DEV-75] Renamed nodeDiff to provisionalNode. Added a bunch of comments.

* [DEV-75] Removed the test for genesis in pastUTXO, since it can never happen.

* [DEV-75] Wrote tests for errors in pastUTXO.

* [DEV-75] Wrote tests for errors in restoreUTXO.

* [DEV-75] Improved testErrorThroughPatching.

* [DEV-75] Wrote tests for errors in verifyAndBuildUTXO.

* [DEV-75] Used TipHashes instead of tips().hashes(), fixed comments in a few places, and brought back an error return that I erroneously removed.

* [DEV-75] Removed UTXO set logs.

* [DEV-75] Recreated add/remove/contains functions for utxoCollection.

* [DEV-75] Changed newUTXOEntry to use an object initializer.

* [DEV-75] Changed the UTXO bucket version to 1.

* Added a comment that clarifies that the index is not initialized before initDAGState is called.

* [DEV-75] Renamed GetVirtualBlock to VirtualBlock.

* [DEV-75] Removed superfluous variables.

* [DEV-75] Combined connectBlockToParents with updateParentsDiffs.

* [DEV-75] Removed another superfluous variable.

* [DEV-75] In pastUTXO, first fetch transactions from the database and only then add them.

* [DEV-75] Reworded the comment for commit().

* [DEV-75] Made all the connectUTXO subfunctions not BlockDAG methods.

* [DEV-75] Updated the comment for connectUTXO.

* [DEV-75] Updated the comment explaining why we're creating provisionalNodes.

* [DEV-75] Removed a couple of unnecessary calls to toProvisionalNode.

* [DEV-75] Renamed connectUTXO to applyUTXOChanges.

* [DEV-75] Replaced allProvisionalNodes with provisionalNodeSet, an object that holds provisionalNodes for this particular call to applyUTXOChanges.

* [DEV-75] Changed createProvisionalNode to accept a boolean "withParents" instead of relying on the caller to supply the node's parents or an empty set.

* [DEV-75] Made most applyUTXOChanges subfunctions be methods on provisionalNode.

* [DEV-75] Fixed a couple of bad comments.

* [DEV-75] Added descriptive error messages to callers of applyUTXOChanges.

* [DEV-75] Fixed weird English.

* [DEV-75] Replaced DAGState with a slice of DAG tip hashes.

* [DEV-75] In createProvisionalNode, changed withParents to withRelatives to avoid certain kinds of attacks.

* [DEV-75] Renamed createdProvisionalNode to newProvisionalNode.

* [DEV-75] Added precalculating the amount of transactions inside a new block's blue set.

* [DEV-75] Pruned unnecessary variable.
2018-08-30 16:00:03 +03:00

124 lines
4.5 KiB
Go

// 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 (
"github.com/daglabs/btcd/blockdag"
"github.com/daglabs/btcd/wire"
"github.com/daglabs/btcd/util"
)
const (
// UnminedHeight is the height used for the "block" height field of the
// contextual transaction information provided in a transaction store
// when it has not yet been mined into a block.
UnminedHeight = 0x7fffffff
)
// Policy houses the policy (configuration parameters) which is used to control
// the generation of block templates. See the documentation for
// NewBlockTemplate for more details on each of these parameters are used.
type Policy struct {
// BlockMinSize is the minimum block size to be used when generating
// a block template.
BlockMinSize uint32
// BlockMaxSize is the maximum block size to be used when generating a
// block template.
BlockMaxSize uint32
// BlockPrioritySize is the size in bytes for high-priority / low-fee
// transactions to be used when generating a block template.
BlockPrioritySize uint32
// TxMinFreeFee is the minimum fee in Satoshi/1000 bytes that is
// required for a transaction to be treated as free for mining purposes
// (block template generation).
TxMinFreeFee util.Amount
}
// minInt is a helper function to return the minimum of two ints. This avoids
// a math import and the need to cast to floats.
func minInt(a, b int) int {
if a < b {
return a
}
return b
}
// calcInputValueAge is a helper function used to calculate the input age of
// a transaction. The input age for a txin is the number of confirmations
// since the referenced txout multiplied by its output value. The total input
// age is the sum of this value for each txin. Any inputs to the transaction
// which are currently in the mempool and hence not mined into a block yet,
// contribute no additional input age to the transaction.
func calcInputValueAge(tx *wire.MsgTx, utxoView *blockdag.UTXOView, nextBlockHeight int32) float64 {
var totalInputAge float64
for _, txIn := range tx.TxIn {
// Don't attempt to accumulate the total input age if the
// referenced transaction output doesn't exist.
entry := utxoView.LookupEntry(txIn.PreviousOutPoint)
if entry != nil && !entry.IsSpent() {
// Inputs with dependencies currently in the mempool
// have their block height set to a special constant.
// Their input age should computed as zero since their
// parent hasn't made it into a block yet.
var inputAge int32
originHeight := entry.BlockHeight()
if originHeight == UnminedHeight {
inputAge = 0
} else {
inputAge = nextBlockHeight - originHeight
}
// Sum the input value times age.
inputValue := entry.Amount()
totalInputAge += float64(inputValue * int64(inputAge))
}
}
return totalInputAge
}
// CalcPriority returns a transaction priority given a transaction and the sum
// of each of its input values multiplied by their age (# of confirmations).
// Thus, the final formula for the priority is:
// sum(inputValue * inputAge) / adjustedTxSize
func CalcPriority(tx *wire.MsgTx, utxoView *blockdag.UTXOView, nextBlockHeight int32) float64 {
// In order to encourage spending multiple old unspent transaction
// outputs thereby reducing the total set, don't count the constant
// overhead for each input as well as enough bytes of the signature
// script to cover a pay-to-script-hash redemption with a compressed
// pubkey. This makes additional inputs free by boosting the priority
// of the transaction accordingly. No more incentive is given to avoid
// encouraging gaming future transactions through the use of junk
// outputs. This is the same logic used in the reference
// implementation.
//
// The constant overhead for a txin is 41 bytes since the previous
// outpoint is 36 bytes + 4 bytes for the sequence + 1 byte the
// signature script length.
//
// A compressed pubkey pay-to-script-hash redemption with a maximum len
// signature is of the form:
// [OP_DATA_73 <73-byte sig> + OP_DATA_35 + {OP_DATA_33
// <33 byte compresed pubkey> + OP_CHECKSIG}]
//
// Thus 1 + 73 + 1 + 1 + 33 + 1 = 110
overhead := 0
for _, txIn := range tx.TxIn {
// Max inputs + size can't possibly overflow here.
overhead += 41 + minInt(110, len(txIn.SignatureScript))
}
serializedTxSize := tx.SerializeSize()
if overhead >= serializedTxSize {
return 0.0
}
inputValueAge := calcInputValueAge(tx, utxoView, nextBlockHeight)
return inputValueAge / float64(serializedTxSize-overhead)
}