func (tr *Transcript) Solve() (solvedOrders []AuctionOrder, invalidResponses []CommitResponse, err error) {
	hasher := sha3.New256()
	var pzMap map[[32]byte]EncryptedSolutionOrder = make(map[[32]byte]EncryptedSolutionOrder)
	var tempNSum [32]byte = [32]byte{}
	var zeroBuf [32]byte = [32]byte{}
	for _, pzOrder := range tr.PuzzledOrders {
		hasher.Reset()
		copy(tempNSum[:], zeroBuf[:])
		hasher.Write(pzOrder.EncSolOrder.OrderPuzzle.N.Bytes())
		copy(tempNSum[:], hasher.Sum(nil))
		pzMap[tempNSum] = pzOrder.EncSolOrder
	}
	NBuf := make([][]byte, len(tr.Responses))
	var groupComputeN sync.WaitGroup
	groupComputeN.Add(len(tr.Responses))
	for i, ans := range tr.Responses {
		go func(j int, answer CommitResponse) {
			pgmp := new(gmpbig.Int).SetBytes(answer.PuzzleAnswerReveal.P.Bytes())
			qgmp := new(gmpbig.Int).SetBytes(answer.PuzzleAnswerReveal.Q.Bytes())
			NBuf[j] = new(gmpbig.Int).Mul(pgmp, qgmp).Bytes()
			groupComputeN.Done()
		}(i, ans)
	}
	groupComputeN.Wait()
	var solutionMap map[CommitResponse]EncryptedSolutionOrder = make(map[CommitResponse]EncryptedSolutionOrder)
	var currEnc EncryptedSolutionOrder
	var ok bool
	for j, answer := range tr.Responses {
		ok = false
		hasher.Reset()
		copy(tempNSum[:], zeroBuf[:])
		hasher.Write(NBuf[j])
		copy(tempNSum[:], hasher.Sum(nil))
		if currEnc, ok = pzMap[tempNSum]; ok {
			solutionMap[answer] = currEnc
		} else {
			invalidResponses = append(invalidResponses, answer)
		}
	}
	solvedOrders = make([]AuctionOrder, len(solutionMap))
	errChan := make(chan error, len(solutionMap))
	var solveWg sync.WaitGroup
	solveWg.Add(len(solutionMap))
	i := 0
	for response, encOrder := range solutionMap {
		go func(j int, p, q *big.Int, currEncOrder EncryptedSolutionOrder) {
			var currAuctionOrder AuctionOrder
			var currErr error
			if currAuctionOrder, currErr = trapdoor(p, q, currEncOrder); currErr != nil {
				errChan <- fmt.Errorf("Error running %dth trapdoor for revealed answer: %s", j, currErr)
			}
			solvedOrders[j] = currAuctionOrder
			solveWg.Done()
		}(i, response.PuzzleAnswerReveal.P, response.PuzzleAnswerReveal.Q, encOrder)
		i++
	}
	solveWg.Wait()
	select {
	case nonNilErr := <-errChan:
		err = fmt.Errorf("Error with parallel trapdoor: %s", nonNilErr)
		return
	default:
	}
	return
}
Solve processes the encrypted solution orders and the commitment
Responses to partition the encrypted orders into those solvable by
Responses and those that are unsolvable.
package match
import (
	"bytes"
	"encoding/gob"
	"fmt"
	"math/big"
	"sync"
	gmpbig "github.com/Rjected/gmp"
	"github.com/mit-dci/lit/crypto/koblitz"
	"github.com/mit-dci/opencx/crypto/timelockencoders"
	"github.com/mit-dci/opencx/logging"
	"golang.org/x/crypto/sha3"
)
type Transcript struct {
	BatchId       AuctionID           `json:batchid`
	BatchIdSig    []byte              `json:"signature"`
	PuzzledOrders []SignedEncSolOrder `json:"puzzledorders"`
	Commitment    [32]byte            `json:"commitment"`
	CommitSig     []byte              `json:"commitsig"`
	Responses     []CommitResponse    `json:"responses"`
	Solutions     []AuctionOrder      `json:"solutions"`
}
func (tr *Transcript) Verify() (valid bool, err error) {
	hasher := sha3.New256()
	if _, err = hasher.Write(tr.BatchId[:]); err != nil {
		err = fmt.Errorf("Error writing batch id to hasher: %s", err)
		return
	}
	e := hasher.Sum(nil)
	hasher.Reset()
	var exchangePubKey *koblitz.PublicKey
	if exchangePubKey, _, err = koblitz.RecoverCompact(koblitz.S256(), tr.BatchIdSig, e); err != nil {
		err = fmt.Errorf("Error recovering pubkey from batch sig: %s", err)
		return
	}
	var pubkeyMap map[[32]byte]SignedEncSolOrder = make(map[[32]byte]SignedEncSolOrder)
	var tempPKH [32]byte = [32]byte{}
	var zeroBuf [32]byte = [32]byte{}
	var bufForCommitment []byte
	for _, pzOrder := range tr.PuzzledOrders {
		hasher.Reset()
		copy(tempPKH[:], zeroBuf[:])
		var pzBuf []byte
		if pzBuf, err = pzOrder.Serialize(); err != nil {
			err = fmt.Errorf("Error serializing puzzle order for transcript verification: %s", err)
			return
		}
		var notSignedPzBuf []byte
		if notSignedPzBuf, err = pzOrder.EncSolOrder.Serialize(); err != nil {
			err = fmt.Errorf("Error serializing unsigned part of puzzle order: %s", err)
			return
		}
		if _, err = hasher.Write(notSignedPzBuf); err != nil {
			err = fmt.Errorf("Error writing puzzle order to hasher: %s", err)
			return
		}
		hashOrder := hasher.Sum(nil)
		var firstUserPubKey *koblitz.PublicKey
		if firstUserPubKey, _, err = koblitz.RecoverCompact(koblitz.S256(), pzOrder.Signature, hashOrder); err != nil {
			err = fmt.Errorf("Error recovering user pubkey from sig: %s", err)
			return
		}
		hasher.Reset()
		hasher.Write(firstUserPubKey.SerializeCompressed())
		copy(tempPKH[:], hasher.Sum(nil))
		pubkeyMap[tempPKH] = pzOrder
		bufForCommitment = append(bufForCommitment, pzBuf...)
	}
	hasher.Reset()
	if _, err = hasher.Write(bufForCommitment); err != nil {
		err = fmt.Errorf("Error writing puzzles for commitment to hasher: %s", err)
		return
	}
	e2 := hasher.Sum(nil)
	hasher.Reset()
	var otherExchangePubkey *koblitz.PublicKey
	if otherExchangePubkey, _, err = koblitz.RecoverCompact(koblitz.S256(), tr.CommitSig, tr.Commitment[:]); err != nil {
		err = fmt.Errorf("Error recovering pubkey for commit signature: %s", err)
		return
	}
	if !otherExchangePubkey.IsEqual(exchangePubKey) {
		err = fmt.Errorf("Exchange used different pubkey for signing commitment versus batchid")
		return
	}
	if bytes.Compare(e2, tr.Commitment[:]) != 0 {
		err = fmt.Errorf("Commitment is not equal to hash of orders - invalid transcript")
		return
	}
	var e3Buf [][32]byte = make([][32]byte, len(tr.Responses))
	var errChan chan error = make(chan error, len(tr.Responses))
	var hashCommWg sync.WaitGroup
	hashCommWg.Add(len(tr.Responses))
	for i, response := range tr.Responses {
		go func(j int, comm [32]byte, commSig []byte, res CommitResponse) {
			var cErr error
			e3Buf[j] = [32]byte{}
			currHasher := sha3.New256()
			if _, cErr = currHasher.Write(comm[:]); cErr != nil {
				errChan <- fmt.Errorf("Error writing commitment to hasher: %s", cErr)
				hashCommWg.Done()
				return
			}
			if _, cErr = currHasher.Write(commSig); cErr != nil {
				errChan <- fmt.Errorf("Error writing commitment sig to hasher: %s", cErr)
				hashCommWg.Done()
				return
			}
			var answerBytes []byte
			if answerBytes, cErr = res.PuzzleAnswerReveal.Serialize(); cErr != nil {
				errChan <- fmt.Errorf("Error serializing answer: %s", cErr)
				hashCommWg.Done()
				return
			}
			if _, cErr = currHasher.Write(answerBytes); cErr != nil {
				errChan <- fmt.Errorf("Error writing answerBytes to hasher: %s", cErr)
				hashCommWg.Done()
				return
			}
			copy(e3Buf[j][:], currHasher.Sum(nil))
			hashCommWg.Done()
		}(i, tr.Commitment, tr.CommitSig, response)
	}
	hashCommWg.Wait()
	select {
	case nonNilErr := <-errChan:
		err = fmt.Errorf("Error with goroutine for hashing: %s", nonNilErr)
		return
	default:
	}
	var ok bool
	for _, response := range tr.Responses {
		ok = false
		copy(tempPKH[:], zeroBuf[:])
		hasher.Reset()
		if _, err = hasher.Write(tr.Commitment[:]); err != nil {
			err = fmt.Errorf("Error writing commitment to hasher: %s", err)
			return
		}
		if _, err = hasher.Write(tr.CommitSig); err != nil {
			err = fmt.Errorf("Error writing commit sig to hasher: %s", err)
			return
		}
		var answerBytes []byte
		if answerBytes, err = response.PuzzleAnswerReveal.Serialize(); err != nil {
			err = fmt.Errorf("Error serializing answer: %s", err)
			return
		}
		if _, err = hasher.Write(answerBytes); err != nil {
			err = fmt.Errorf("Error writing answer bytes to hasher: %s", err)
			return
		}
		e3 := hasher.Sum(nil)
		var userPubKey *koblitz.PublicKey
		if userPubKey, _, err = koblitz.RecoverCompact(koblitz.S256(), response.CommResponseSig[:], e3); err != nil {
			err = fmt.Errorf("Error recovering user pubkey from signature: %s", err)
			return
		}
		hasher.Reset()
		hasher.Write(userPubKey.SerializeCompressed())
		copy(tempPKH[:], hasher.Sum(nil))
		var currEnc SignedEncSolOrder
		if currEnc, ok = pubkeyMap[tempPKH]; !ok {
			err = fmt.Errorf("Error, user pubkey not in previous map, so it's a signature without an order")
			return
		}
		tempN := new(big.Int).Mul(response.PuzzleAnswerReveal.Q, response.PuzzleAnswerReveal.P)
		if tempN.Cmp(currEnc.EncSolOrder.OrderPuzzle.N) != 0 {
			logging.Warnf("User included incorrect factors in order, this order will require some solving")
		}
	}
	valid = true
	return
}