Example #1
0
// RawTxInSignatureAlt returns the serialized ECDSA signature for the input idx of
// the given transaction, with hashType appended to it.
func RawTxInSignatureAlt(tx *wire.MsgTx, idx int, subScript []byte,
	hashType SigHashType, key chainec.PrivateKey, sigType sigTypes) ([]byte,
	error) {

	parsedScript, err := parseScript(subScript)
	if err != nil {
		return nil, fmt.Errorf("cannot parse output script: %v", err)
	}
	hash, err := calcSignatureHash(parsedScript, hashType, tx, idx, nil)
	if err != nil {
		return nil, err
	}

	var sig chainec.Signature
	switch sigType {
	case edwards:
		r, s, err := chainec.Edwards.Sign(key, hash)
		if err != nil {
			return nil, fmt.Errorf("cannot sign tx input: %s", err)
		}
		sig = chainec.Edwards.NewSignature(r, s)
	case secSchnorr:
		r, s, err := chainec.SecSchnorr.Sign(key, hash)
		if err != nil {
			return nil, fmt.Errorf("cannot sign tx input: %s", err)
		}
		sig = chainec.SecSchnorr.NewSignature(r, s)
	default:
		return nil, fmt.Errorf("unknown alt sig type %v", sigType)
	}

	return append(sig.Serialize(), byte(hashType)), nil
}
Example #2
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 chainhash.Hash, sig chainec.Signature, pubKey chainec.PublicKey) bool {
	info := sigInfo{sigHash, string(sig.Serialize()),
		string(pubKey.SerializeCompressed())}

	s.RLock()
	_, ok := s.validSigs[info]
	s.RUnlock()
	return ok
}
Example #3
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 chainhash.Hash, sig chainec.Signature, pubKey chainec.PublicKey) bool {
	s.RLock()
	defer s.RUnlock()

	if entry, ok := s.validSigs[sigHash]; ok {
		pkEqual := bytes.Equal(entry.pubKey.SerializeCompressed(),
			pubKey.SerializeCompressed())
		sigEqual := bytes.Equal(entry.sig.Serialize(), sig.Serialize())
		return pkEqual && sigEqual
	}

	return false
}
Example #4
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 it 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 chainhash.Hash, sig chainec.Signature, pubKey chainec.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, chainhash.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{}{}
}