github.com/fozzysec/SiaPrime@v0.0.0-20190612043147-66c8e8d11fe3/modules/transactionpool.go (about) 1 package modules 2 3 import ( 4 "errors" 5 6 "SiaPrime/crypto" 7 "SiaPrime/encoding" 8 "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 }