func makeRequestPreparer(clientID uint32, authenticator api.Authenticator, seq sequenceGenerator, logger logger.Logger) requestPreparer {
	constructor := makeRequestConstructor(clientID, seq)
	signer := makeRequestSigner(authenticator)
	return func(operation []byte) messages.Request {
		return prepareRequest(operation, constructor, signer, logger)
	}
}
makeRequestPreparer constructs a requestPreparer using the supplied
client ID, authenticator, and sequence number generator.
package client
import (
	"crypto/sha256"
	"time"
	"github.com/hyperledger-labs/minbft/api"
	"github.com/hyperledger-labs/minbft/client/internal/requestbuffer"
	"github.com/hyperledger-labs/minbft/common/logger"
	"github.com/hyperledger-labs/minbft/messages"
)
type requestHandler func(operation []byte) <-chan []byte
func makeRequestHandler(clientID uint32, seq sequenceGenerator, authen api.Authenticator, buf *requestbuffer.T, f uint32, logger logger.Logger) requestHandler {
	submitter := makeRequestSubmitter(clientID, seq, authen, buf, logger)
	collector := makeReplyCollector(f, buf)
	return func(operation []byte) <-chan []byte {
		return handleRequest(operation, submitter, collector)
	}
}
type requestSubmitter func(operation []byte) <-chan messages.Reply
type replyCollector func(in <-chan messages.Reply, out chan<- []byte)
func handleRequest(operation []byte, submitter requestSubmitter, collector replyCollector) <-chan []byte {
	resultChan := make(chan []byte, 1)
	replyChan := submitter(operation)
	go collector(replyChan, resultChan)
	return resultChan
}
func makeReplyCollector(f uint32, buf *requestbuffer.T) replyCollector {
	remover := makeRequestRemover(buf)
	return func(in <-chan messages.Reply, out chan<- []byte) {
		collectReplies(f, in, remover, out)
	}
}
type requestRemover func(seq uint64)
func collectReplies(f uint32, replyChan <-chan messages.Reply, remover requestRemover, resultChan chan<- []byte) {
	type resultHashType [sha256.Size]byte
	matchingResults := make(map[resultHashType]uint32)
	for reply := range replyChan {
		result := reply.Result()
		hash := sha256.Sum256(result)
		matchingResults[hash]++
		if matchingResults[hash] > f {
			remover(reply.Sequence())
			resultChan <- result
			break
		}
	}
}
func makeRequestRemover(buf *requestbuffer.T) requestRemover {
	return func(seq uint64) {
		buf.RemoveRequest(seq)
	}
}
type sequenceGenerator func() uint64
func makeRequestSubmitter(clientID uint32, seq sequenceGenerator, authen api.Authenticator, buf *requestbuffer.T, logger logger.Logger) requestSubmitter {
	preparer := makeRequestPreparer(clientID, authen, seq, logger)
	consumer := makeRequestConsumer(buf)
	return func(operation []byte) <-chan messages.Reply {
		return submitRequest(operation, preparer, consumer)
	}
}
type requestPreparer func(operation []byte) messages.Request
type requestConsumer func(request messages.Request) (<-chan messages.Reply, bool)
func submitRequest(operation []byte, preparer requestPreparer, consumer requestConsumer) <-chan messages.Reply {
	request := preparer(operation)
	replyChan, ok := consumer(request)
	if !ok {
		panic("Request message rejected")
	}
	return replyChan
}