Example #1
0
// Exists returns true if an existing entry of 'sig' over 'sigHash' for public
// key 'pubKey' is found within the SigCache. Otherwise, false is returned.
//
// NOTE: This function is safe for concurrent access. Readers won't be blocked
// unless there exists a writer, adding an entry to the SigCache.
func (s *SigCache) Exists(sigHash wire.ShaHash, sig *btcec.Signature, pubKey *btcec.PublicKey) bool {
	info := sigInfo{sigHash, string(sig.Serialize()),
		string(pubKey.SerializeCompressed())}

	s.RLock()
	_, ok := s.validSigs[info]
	s.RUnlock()
	return ok
}
Example #2
0
// Add adds an entry for a signature over 'sigHash' under public key 'pubKey'
// to the signature cache. In the event that the SigCache is 'full', an
// existing entry is randomly chosen to be evicted in order to make space for
// the new entry.
//
// NOTE: This function is safe for concurrent access. Writers will block
// simultaneous readers until function execution has concluded.
func (s *SigCache) Add(sigHash wire.ShaHash, sig *btcec.Signature, pubKey *btcec.PublicKey) {
	s.Lock()
	defer s.Unlock()

	if s.maxEntries <= 0 {
		return
	}

	// If adding this new entry will put us over the max number of allowed
	// entries, then evict an entry.
	if uint(len(s.validSigs)+1) > s.maxEntries {
		// Generate a cryptographically random hash.
		randHashBytes := make([]byte, wire.HashSize)
		_, err := rand.Read(randHashBytes)
		if err != nil {
			// Failure to read a random hash results in the proposed
			// entry not being added to the cache since we are
			// unable to evict any existing entries.
			return
		}

		// Try to find the first entry that is greater than the random
		// hash. Use the first entry (which is already pseudo random due
		// to Go's range statement over maps) as a fall back if none of
		// the hashes in the rejected transactions pool are larger than
		// the random hash.
		var foundEntry sigInfo
		for sigEntry := range s.validSigs {
			if foundEntry.sig == "" {
				foundEntry = sigEntry
			}
			if bytes.Compare(sigEntry.sigHash.Bytes(), randHashBytes) > 0 {
				foundEntry = sigEntry
				break
			}
		}
		delete(s.validSigs, foundEntry)
	}

	info := sigInfo{sigHash, string(sig.Serialize()),
		string(pubKey.SerializeCompressed())}
	s.validSigs[info] = struct{}{}
}