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

     1  package modules
     2  
     3  import (
     4  	"errors"
     5  
     6  	"gitlab.com/SiaPrime/SiaPrime/crypto"
     7  	"gitlab.com/SiaPrime/SiaPrime/encoding"
     8  	"gitlab.com/SiaPrime/SiaPrime/types"
     9  )
    10  
    11  const (
    12  	// TransactionSetSizeLimit defines the largest set of dependent unconfirmed
    13  	// transactions that will be accepted by the transaction pool.
    14  	TransactionSetSizeLimit = 250e3
    15  
    16  	// TransactionSizeLimit defines the size of the largest transaction that
    17  	// will be accepted by the transaction pool according to the IsStandard
    18  	// rules.
    19  	TransactionSizeLimit = 32e3
    20  )
    21  
    22  var (
    23  	// ErrDuplicateTransactionSet is the error that gets returned if a
    24  	// duplicate transaction set is given to the transaction pool.
    25  	ErrDuplicateTransactionSet = errors.New("transaction set contains only duplicate transactions")
    26  
    27  	// ErrInvalidArbPrefix is the error that gets returned if a transaction is
    28  	// submitted to the transaction pool which contains a prefix that is not
    29  	// recognized. This helps prevent miners on old versions from mining
    30  	// potentially illegal transactions in the event of a soft-fork.
    31  	ErrInvalidArbPrefix = errors.New("transaction contains non-standard arbitrary data")
    32  
    33  	// ErrLargeTransaction is the error that gets returned if a transaction
    34  	// provided to the transaction pool is larger than what is allowed by the
    35  	// IsStandard rules.
    36  	ErrLargeTransaction = errors.New("transaction is too large for this transaction pool")
    37  
    38  	// ErrLargeTransactionSet is the error that gets returned if a transaction
    39  	// set given to the transaction pool is larger than the limit placed by the
    40  	// IsStandard rules of the transaction pool.
    41  	ErrLargeTransactionSet = errors.New("transaction set is too large for this transaction pool")
    42  
    43  	// PrefixNonSia defines the prefix that should be appended to any
    44  	// transactions that use the arbitrary data for reasons outside of the
    45  	// standard Sia protocol. This will prevent these transactions from being
    46  	// rejected by the IsStandard set of rules, but also means that the data
    47  	// will never be used within the formal Sia protocol.
    48  	PrefixNonSia = types.Specifier{'N', 'o', 'n', 'S', 'i', 'a'}
    49  
    50  	// TransactionPoolDir is the name of the directory that is used to store
    51  	// the transaction pool's persistent data.
    52  	TransactionPoolDir = "transactionpool"
    53  )
    54  
    55  type (
    56  	// ConsensusConflict implements the error interface, and indicates that a
    57  	// transaction was rejected due to being incompatible with the current
    58  	// consensus set, meaning either a double spend or a consensus rule violation -
    59  	// it is unlikely that the transaction will ever be valid.
    60  	ConsensusConflict string
    61  
    62  	// TransactionSetID is a type-safe wrapper for a crypto.Hash that represents
    63  	// the ID of an entire transaction set.
    64  	TransactionSetID crypto.Hash
    65  
    66  	// A TransactionPoolDiff indicates the adding or removal of a transaction set to
    67  	// the transaction pool. The transactions in the pool are not persisted, so at
    68  	// startup modules should assume an empty transaction pool.
    69  	TransactionPoolDiff struct {
    70  		AppliedTransactions  []*UnconfirmedTransactionSet
    71  		RevertedTransactions []TransactionSetID
    72  	}
    73  
    74  	// UnconfirmedTransactionSet defines a new unconfirmed transaction that has
    75  	// been added to the transaction pool. ID is the ID of the set, IDs contains
    76  	// an ID for each transaction, eliminating the need to recompute it (because
    77  	// that's an expensive operation).
    78  	UnconfirmedTransactionSet struct {
    79  		Change *ConsensusChange
    80  		ID     TransactionSetID
    81  
    82  		IDs          []types.TransactionID
    83  		Sizes        []uint64
    84  		Transactions []types.Transaction
    85  	}
    86  )
    87  
    88  type (
    89  	// A TransactionPoolSubscriber receives updates about the confirmed and
    90  	// unconfirmed set from the transaction pool. Generally, there is no need to
    91  	// subscribe to both the consensus set and the transaction pool.
    92  	TransactionPoolSubscriber interface {
    93  		// ReceiveTransactionPoolUpdate notifies subscribers of a change to the
    94  		// consensus set and/or unconfirmed set, and includes the consensus change
    95  		// that would result if all of the transactions made it into a block.
    96  		ReceiveUpdatedUnconfirmedTransactions(*TransactionPoolDiff)
    97  	}
    98  
    99  	// A TransactionPool manages unconfirmed transactions.
   100  	TransactionPool interface {
   101  		// AcceptTransactionSet accepts a set of potentially interdependent
   102  		// transactions.
   103  		AcceptTransactionSet([]types.Transaction) error
   104  
   105  		// Broadcast broadcasts a transaction set to all of the transaction pool's
   106  		// peers.
   107  		Broadcast(ts []types.Transaction)
   108  
   109  		// Close is necessary for clean shutdown (e.g. during testing).
   110  		Close() error
   111  
   112  		// FeeEstimation returns an estimation for how high the transaction fee
   113  		// needs to be per byte. The minimum recommended targets getting accepted
   114  		// in ~3 blocks, and the maximum recommended targets getting accepted
   115  		// immediately. Taking the average has a moderate chance of being accepted
   116  		// within one block. The minimum has a strong chance of getting accepted
   117  		// within 10 blocks.
   118  		FeeEstimation() (minimumRecommended, maximumRecommended types.Currency)
   119  
   120  		// PurgeTransactionPool is a temporary function available to the miner. In
   121  		// the event that a miner mines an unacceptable block, the transaction pool
   122  		// will be purged to clear out the transaction pool and get rid of the
   123  		// illegal transaction. This should never happen, however there are bugs
   124  		// that make this condition necessary.
   125  		PurgeTransactionPool()
   126  
   127  		// Transaction returns the transaction and unconfirmed parents
   128  		// corresponding to the provided transaction id.
   129  		Transaction(id types.TransactionID) (txn types.Transaction, unconfirmedParents []types.Transaction, exists bool)
   130  
   131  		// TransactionConfirmed returns true if the transaction has been seen on the
   132  		// blockchain. Note, however, that the block containing the transaction may
   133  		// later be invalidated by a reorg.
   134  		TransactionConfirmed(id types.TransactionID) (bool, error)
   135  
   136  		// TransactionList returns a list of all transactions in the transaction
   137  		// pool. The transactions are provided in an order that can acceptably be
   138  		// put into a block.
   139  		TransactionList() []types.Transaction
   140  
   141  		// TransactionPoolSubscribe adds a subscriber to the transaction pool.
   142  		// Subscribers will receive all consensus set changes as well as
   143  		// transaction pool changes, and should not subscribe to both.
   144  		TransactionPoolSubscribe(TransactionPoolSubscriber)
   145  
   146  		// TransactionSet returns the transaction set the provided object
   147  		// appears in.
   148  		TransactionSet(crypto.Hash) []types.Transaction
   149  
   150  		// Unsubscribe removes a subscriber from the transaction pool.
   151  		// This is necessary for clean shutdown of the miner.
   152  		Unsubscribe(TransactionPoolSubscriber)
   153  	}
   154  )
   155  
   156  // NewConsensusConflict returns a consensus conflict, which implements the
   157  // error interface.
   158  func NewConsensusConflict(s string) ConsensusConflict {
   159  	return ConsensusConflict("consensus conflict: " + s)
   160  }
   161  
   162  // Error implements the error interface, turning the consensus conflict into an
   163  // acceptable error type.
   164  func (cc ConsensusConflict) Error() string {
   165  	return string(cc)
   166  }
   167  
   168  // CalculateFee returns the fee-per-byte of a transaction set.
   169  func CalculateFee(ts []types.Transaction) types.Currency {
   170  	var sum types.Currency
   171  	for _, t := range ts {
   172  		for _, fee := range t.MinerFees {
   173  			sum = sum.Add(fee)
   174  		}
   175  	}
   176  	size := len(encoding.Marshal(ts))
   177  	return sum.Div64(uint64(size))
   178  }