github.com/fozzysec/SiaPrime@v0.0.0-20190612043147-66c8e8d11fe3/modules/transactionpool/subscribe.go (about) 1 package transactionpool 2 3 import ( 4 "SiaPrime/build" 5 "SiaPrime/encoding" 6 "SiaPrime/modules" 7 "SiaPrime/types" 8 ) 9 10 // updateSubscribersTransactions sends a new transaction pool update to all 11 // subscribers. 12 func (tp *TransactionPool) updateSubscribersTransactions() { 13 diff := new(modules.TransactionPoolDiff) 14 // Create all of the diffs for reverted sets. 15 for id := range tp.subscriberSets { 16 // The transaction set is still in the transaction pool, no need to 17 // create an update. 18 _, exists := tp.transactionSets[id] 19 if exists { 20 continue 21 } 22 23 // Report that this set has been removed. Negative diffs don't have all 24 // fields filled out. 25 diff.RevertedTransactions = append(diff.RevertedTransactions, modules.TransactionSetID(id)) 26 } 27 28 // Clear the subscriber sets map. 29 for _, revert := range diff.RevertedTransactions { 30 delete(tp.subscriberSets, TransactionSetID(revert)) 31 } 32 33 // Create all of the diffs for sets that have been recently created. 34 for id, set := range tp.transactionSets { 35 _, exists := tp.subscriberSets[id] 36 if exists { 37 // The transaction set has already been sent in an update. 38 continue 39 } 40 41 // Report that this transaction set is new to the transaction pool. 42 ids := make([]types.TransactionID, 0, len(set)) 43 sizes := make([]uint64, 0, len(set)) 44 for i := range set { 45 encodedTxn := encoding.Marshal(set[i]) 46 sizes = append(sizes, uint64(len(encodedTxn))) 47 ids = append(ids, set[i].ID()) 48 } 49 ut := &modules.UnconfirmedTransactionSet{ 50 Change: tp.transactionSetDiffs[id], 51 ID: modules.TransactionSetID(id), 52 53 IDs: ids, 54 Sizes: sizes, 55 Transactions: set, 56 } 57 // Add this diff to our set of subscriber diffs. 58 tp.subscriberSets[id] = ut 59 diff.AppliedTransactions = append(diff.AppliedTransactions, ut) 60 } 61 62 for _, subscriber := range tp.subscribers { 63 subscriber.ReceiveUpdatedUnconfirmedTransactions(diff) 64 } 65 } 66 67 // TransactionPoolSubscribe adds a subscriber to the transaction pool. 68 // Subscribers will receive the full transaction set every time there is a 69 // significant change to the transaction pool. 70 func (tp *TransactionPool) TransactionPoolSubscribe(subscriber modules.TransactionPoolSubscriber) { 71 tp.mu.Lock() 72 defer tp.mu.Unlock() 73 74 // Check that this subscriber is not already subscribed. 75 for _, s := range tp.subscribers { 76 if s == subscriber { 77 build.Critical("refusing to double-subscribe subscriber") 78 } 79 } 80 81 // Add the subscriber to the subscriber list. 82 tp.subscribers = append(tp.subscribers, subscriber) 83 84 // Send the new subscriber the transaction pool set. 85 diff := new(modules.TransactionPoolDiff) 86 diff.AppliedTransactions = make([]*modules.UnconfirmedTransactionSet, 0, len(tp.subscriberSets)) 87 for _, ut := range tp.subscriberSets { 88 diff.AppliedTransactions = append(diff.AppliedTransactions, ut) 89 } 90 subscriber.ReceiveUpdatedUnconfirmedTransactions(diff) 91 } 92 93 // Unsubscribe removes a subscriber from the transaction pool. If the 94 // subscriber is not in tp.subscribers, Unsubscribe does nothing. If the 95 // subscriber occurs more than once in tp.subscribers, only the earliest 96 // occurrence is removed (unsubscription fails). 97 func (tp *TransactionPool) Unsubscribe(subscriber modules.TransactionPoolSubscriber) { 98 tp.mu.Lock() 99 defer tp.mu.Unlock() 100 101 // Search for and remove subscriber from list of subscribers. 102 for i := range tp.subscribers { 103 if tp.subscribers[i] == subscriber { 104 tp.subscribers = append(tp.subscribers[0:i], tp.subscribers[i+1:]...) 105 break 106 } 107 } 108 }