func verifyIssueByNonce(payId pay.PayId, nonce []byte) bool {
	if nil == nonce || 0 == len(nonce) {
		globalData.log.Warn("nonce nil or empty")
		return false
	}
	globalData.log.Infof("nonce: %x", nonce)
	globalData.Lock()
	defer globalData.Unlock()
	entry, ok := globalData.pendingFreeIssues[payId]
	if ok {
		copy(entry.nonce[:], nonce[:])
		for _, tx := range entry.txs {
			if issue, ok := tx.transaction.(*transactionrecord.AssetData); ok {
				asset.DecrementTTL(issue.AssetId())
			}
			delete(globalData.pendingIndex, tx.txId)
			globalData.verifiedIndex[tx.txId] = payId
		}
		globalData.pendingFreeCount -= len(entry.txs)
		delete(globalData.pendingFreeIssues, payId)
		globalData.verifiedFreeIssues[payId] = entry
	}
	return ok
}
move transaction(s) to verified cache
package reservoir
import (
	"bytes"
	"encoding/binary"
	"math/big"
	"time"
	"golang.org/x/crypto/sha3"
	"github.com/bitmark-inc/bitmarkd/asset"
	"github.com/bitmark-inc/bitmarkd/constants"
	"github.com/bitmark-inc/bitmarkd/difficulty"
	"github.com/bitmark-inc/bitmarkd/fault"
	"github.com/bitmark-inc/bitmarkd/genesis"
	"github.com/bitmark-inc/bitmarkd/merkle"
	"github.com/bitmark-inc/bitmarkd/mode"
	"github.com/bitmark-inc/bitmarkd/pay"
	"github.com/bitmark-inc/bitmarkd/storage"
	"github.com/bitmark-inc/bitmarkd/transactionrecord"
)
type IssueInfo struct {
	TxIds      []merkle.Digest
	Packed     []byte
	Id         pay.PayId
	Nonce      PayNonce
	Difficulty *difficulty.Difficulty
	Payments   []transactionrecord.PaymentAlternative
}
func storeIssues(issues []*transactionrecord.BitmarkIssue, assetHandle storage.Handle, blockOwnerPaymentHandle storage.Handle) (*IssueInfo, bool, error) {
	if nil == assetHandle || nil == blockOwnerPaymentHandle {
		return nil, false, fault.NilPointer
	}
	count := len(issues)
	if count > MaximumIssues {
		return nil, false, fault.TooManyItemsToProcess
	} else if 0 == count {
		return nil, false, fault.MissingParameters
	}
	separated := make([][]byte, count)
	txIds := make([]merkle.Digest, count)
	uniqueAssetId := issues[0].AssetId
	unique := true
	duplicate := false
	freeIssueAllowed := true
	for i, issue := range issues {
		if nil == issue || nil == issue.Owner {
			return nil, false, fault.InvalidItem
		}
		if issue.Owner.IsTesting() != mode.IsTesting() {
			return nil, false, fault.WrongNetworkForPublicKey
		}
		if 0 != issue.Nonce {
			freeIssueAllowed = false
		}
		packedIssue, err := issue.Pack(issue.Owner)
		if nil != err {
			return nil, false, err
		}
		if !asset.Exists(issue.AssetId, assetHandle) {
			return nil, false, fault.AssetNotFound
		}
		txId := packedIssue.MakeLink()
		globalData.RLock()
		_, ok := globalData.pendingIndex[txId]
		if ok {
			duplicate = true
		}
		_, ok = globalData.verifiedIndex[txId]
		globalData.RUnlock()
		if ok {
			return nil, false, fault.TransactionAlreadyExists
		}
		if storage.Pool.Transactions.Has(txId[:]) {
			return nil, false, fault.TransactionAlreadyExists
		}
		txIds[i] = txId
		if uniqueAssetId != issue.AssetId {
			unique = false
		}
		separated[i] = packedIssue
	}
	payId := pay.NewPayId(separated)
	result := &IssueInfo{
		Id:     payId,
		TxIds:  txIds,
		Packed: bytes.Join(separated, []byte{}),
		Difficulty: nil,
		Payments:   nil,
	}
	globalData.RLock()
	if entry, ok := globalData.pendingFreeIssues[payId]; ok {
		globalData.log.Debugf("duplicate free issue pay id: %s", payId)
		result.Nonce = entry.nonce
		result.Difficulty = entry.difficulty
		globalData.RUnlock()
		return result, true, nil
	}
	if entry, ok := globalData.pendingPaidIssues[payId]; ok {
		globalData.log.Debugf("duplicate free issue pay id: %s", payId)
		result.Payments = entry.payments
		globalData.RUnlock()
		return result, true, nil
	}
	globalData.RUnlock()
	if duplicate {
		globalData.log.Debugf("overlapping pay id: %s", payId)
		return nil, false, fault.TransactionAlreadyExists
	}
	globalData.log.Infof("creating pay id: %s", payId)
	if freeIssueAllowed {
		result.Nonce = NewPayNonce()
		result.Difficulty = ScaledDifficulty(count)
	} else {
		if !unique {
			return nil, false, fault.AssetNotFound
		}
		assetBlockNumber, t := assetHandle.GetNB(uniqueAssetId[:])
		if nil == t || assetBlockNumber <= genesis.BlockNumber {
			return nil, false, fault.AssetNotFound
		}
		blockNumberKey := make([]byte, 8)
		binary.BigEndian.PutUint64(blockNumberKey, assetBlockNumber)
		p := getPayment(blockNumberKey, blockOwnerPaymentHandle)
		if nil == p {  
			globalData.log.Errorf("missing payment for asset id: %s", issues[0].AssetId)
			return nil, false, fault.AssetNotFound
		}
		result.Payments = make([]transactionrecord.PaymentAlternative, 0, len(p))
		for _, r := range p {
			total := r.Amount * uint64(len(txIds))
			pa := transactionrecord.PaymentAlternative{
				&transactionrecord.Payment{
					Currency: r.Currency,
					Address:  r.Address,
					Amount:   total,
				},
			}
			result.Payments = append(result.Payments, pa)
		}
	}
	txs := make([]*transactionData, len(txIds))
	for i, txId := range txIds {
		txs[i] = &transactionData{
			txId:        txId,
			transaction: issues[i],
			packed:      separated[i],
		}
	}
	entry := &issuePaymentData{
		payId:     payId,
		txs:       txs,
		payments:  result.Payments,
		expiresAt: time.Now().Add(constants.ReservoirTimeout),
	}
	globalData.Lock()
	defer globalData.Unlock()
	detail, ok := globalData.orphanPayments[payId]
	if ok {
		if acceptablePayment(detail, result.Payments) {
			for _, txId := range txIds {
				globalData.verifiedIndex[txId] = payId
				delete(globalData.pendingIndex, txId)
			}
			globalData.verifiedPaidIssues[payId] = entry
			delete(globalData.orphanPayments, payId)
			return result, false, nil
		}
	}
	if freeIssueAllowed && globalData.pendingFreeCount+len(txs) > maximumPendingFreeIssues ||
		!freeIssueAllowed && globalData.pendingPaidCount+len(txs) >= maximumPendingPaidIssues {
		return nil, false, fault.BufferCapacityLimit
	}
	for _, txId := range txIds {
		globalData.pendingIndex[txId] = payId
	}
	if freeIssueAllowed {
		globalData.pendingFreeIssues[payId] = &issueFreeData{
			payId:      payId,
			txs:        txs,
			nonce:      result.Nonce,
			difficulty: result.Difficulty,
			expiresAt:  time.Now().Add(constants.ReservoirTimeout),
		}
		for _, issue := range issues {
			asset.IncrementTTL(issue.AssetId)
		}
		globalData.pendingFreeCount += len(txs)
	} else {
		globalData.pendingPaidIssues[payId] = entry
		globalData.pendingPaidCount += len(txs)
	}
	return result, false, nil
}
func tryProof(payId pay.PayId, clientNonce []byte) TrackingStatus {
	globalData.RLock()
	r, ok := globalData.pendingFreeIssues[payId]
	globalData.RUnlock()
	if !ok {
		globalData.log.Debugf("tryProof: issue item not found")
		return TrackingNotFound
	}
	if nil == r.difficulty {  
		globalData.log.Debugf("tryProof: item with out a difficulty")
		return TrackingInvalid
	}
	bigDifficulty := r.difficulty.BigInt()
	globalData.log.Infof("tryProof: difficulty: 0x%064x", bigDifficulty)
	h := sha3.New256()
	height := PayNonceRoundedHeight()
try_loop:
	for i := uint64(0); i < 6; i += 1 {
		payNonce := PayNonceFromBlock(height)
		globalData.log.Debugf("tryProof: payNonce[%d]@%d: %x", i, height, payNonce)
		h.Reset()
		h.Write(payId[:])
		h.Write(payNonce[:])
		h.Write(clientNonce)
		var digest [32]byte
		h.Sum(digest[:0])
		bigDigest := new(big.Int).SetBytes(digest[:])
		globalData.log.Debugf("tryProof: digest: 0x%064x", bigDigest)
		if bigDigest.Cmp(bigDifficulty) <= 0 {
			globalData.log.Debugf("tryProof: success: pay id: %s", payId)
			verifyIssueByNonce(payId, clientNonce)
			return TrackingAccepted
		}
		if height < PayNonceHeightDelta {
			break try_loop
		}
		height -= PayNonceHeightDelta
	}
	return TrackingInvalid
}