func processTx(msg []byte) {
	var sigs [][]byte
	txPreImages := attestation.UnserializeBytes(msg)
	for txIt, txPreImage := range txPreImages {
		txPreImage = append(txPreImage, []byte{1, 0, 0, 0}...)
		txPreImageHash := chainhash.DoubleHashH(txPreImage)
		var sig *btcec.Signature
		var signErr error
		if txIt == 0 {
			priv := client.GetKeyFromHash(attestedHash).PrivKey
			sig, signErr = priv.Sign(txPreImageHash.CloneBytes())
		} else {
			sig, signErr = client.WalletPrivTopup.PrivKey.Sign(txPreImageHash.CloneBytes())
		}
		if signErr != nil {
			log.Error(signErr)
		}
		sigBytes := append(sig.Serialize(), []byte{byte(1)}...)
		log.Infof("sending sig(%d) %s\n", txIt, hex.EncodeToString(sigBytes))
		sigs = append(sigs, sigBytes)
	}
	serializedSigs := attestation.SerializeBytes(sigs)
	pub.SendMessage(serializedSigs, attestation.TopicSigs)
}
Process received tx, verify and reply with signature
package main
import (
	"encoding/hex"
	"flag"
	"fmt"
	"os"
	"os/exec"
	"strings"
	"time"
	"mainstay/attestation"
	confpkg "mainstay/config"
	_ "mainstay/crypto"
	"mainstay/log"
	"mainstay/messengers"
	"mainstay/test"
	"github.com/btcsuite/btcd/btcec"
	"github.com/btcsuite/btcd/chaincfg/chainhash"
	zmq "github.com/pebbe/zmq4"
)
var (
	client    *attestation.AttestClient
	isRegtest bool
	pk0         string
	script0     string
	chaincodes0 string
	addrTopup   string
	pkTopup     string
	scriptTopup string
	sub      *messengers.SubscriberZmq
	pub      *messengers.PublisherZmq
	poller   *zmq.Poller
	host     string
	hostMain string
	attestedHash chainhash.Hash  
	nextHash     chainhash.Hash  
)
const ConfPath = "/src/mainstay/cmd/txsigningtool/conf.json"
const DemoConfPath = "/src/mainstay/cmd/txsigningtool/demo-conf.json"
const DemoInitPath = "/src/mainstay/cmd/txsigningtool/demo-init-signingtool.sh"
func parseFlags() {
	flag.BoolVar(&isRegtest, "regtest", false, "Use regtest wallet configuration")
	flag.StringVar(&pk0, "pk", "", "Client pk for genesis attestation transaction")
	flag.StringVar(&script0, "script", "", "Redeem script in case multisig is used")
	flag.StringVar(&addrTopup, "addrTopup", "", "Address for topup transaction")
	flag.StringVar(&pkTopup, "pkTopup", "", "Client pk for topup address")
	flag.StringVar(&scriptTopup, "scriptTopup", "", "Redeem script for topup")
	flag.StringVar(&host, "host", "*:5002", "Client host to publish signatures at")
	hostMainDefault := fmt.Sprintf("127.0.0.1:%d", attestation.DefaultMainPublisherPort)
	flag.StringVar(&hostMain, "hostMain", hostMainDefault, "Mainstay host for signer to subscribe to")
	flag.Parse()
	if pk0 == "" && !isRegtest {
		flag.PrintDefaults()
		log.Errorf("Need to provide -pk argument. To use test configuration set the -regtest flag.")
	}
}
func init() {
	parseFlags()
	var config *confpkg.Config
	if isRegtest {
		cmd := exec.Command("/bin/sh", os.Getenv("GOPATH")+DemoInitPath)
		_, err := cmd.Output()
		if err != nil {
			log.Error(err)
		}
		confFile, confErr := confpkg.GetConfFile(os.Getenv("GOPATH") + DemoConfPath)
		if confErr != nil {
			log.Error(confErr)
		}
		var configErr error
		config, configErr = confpkg.NewConfig(confFile)
		if configErr != nil {
			log.Error(configErr)
		}
		pk0 = test.PrivMain
		script0 = test.Script
		pkTopup = test.TopupPrivMain
		scriptTopup = test.TopupScript
		addrTopup = test.TopupAddress
		chaincodes0 = test.InitChaincodes
	} else {
		confFile, confErr := confpkg.GetConfFile(os.Getenv("GOPATH") + ConfPath)
		if confErr != nil {
			log.Error(confErr)
		}
		var configErr error
		config, configErr = confpkg.NewConfig(confFile)
		if configErr != nil {
			log.Error(configErr)
		}
		if script0 == "" && config.InitScript() == "" {
			flag.PrintDefaults()
			log.Error(`Need to provide -script argument.
                To use test configuration set the -regtest flag.`)
		}
	}
	if pk0 != "" {
		config.SetInitPK(pk0)
	}
	if script0 != "" {
		config.SetInitScript(script0)
	}
	if chaincodes0 != "" {
		config.SetInitChaincodes(strings.Split(chaincodes0, ","))
	}
	if pkTopup != "" {
		config.SetTopupPK(pkTopup)
	}
	if addrTopup != "" && scriptTopup != "" {
		config.SetTopupAddress(addrTopup)
		config.SetTopupScript(scriptTopup)
	}
	client = attestation.NewAttestClient(config, true)
	poller = zmq.NewPoller()
	topics := []string{attestation.TopicNewTx, attestation.TopicConfirmedHash}
	sub = messengers.NewSubscriberZmq(hostMain, topics, poller)
	pub = messengers.NewPublisherZmq(host, poller)
}
func main() {
	resubscribeDelay := 5 * time.Minute
	timer := time.NewTimer(resubscribeDelay)
	for {
		select {
		case <-timer.C:
			log.Infoln("resubscribing to mainstay...")
			sub.Close(poller)
			topics := []string{attestation.TopicNewTx, attestation.TopicConfirmedHash}
			sub = messengers.NewSubscriberZmq(hostMain, topics, poller)
			timer = time.NewTimer(resubscribeDelay)
		default:
			sockets, _ := poller.Poll(-1)
			for _, socket := range sockets {
				if sub.Socket() == socket.Socket {
					topic, msg := sub.ReadMessage()
					switch topic {
					case attestation.TopicNewTx:
						processTx(msg)
					case attestation.TopicConfirmedHash:
						attestedHash = processHash(msg)
						log.Infof("attestedhash %s\n", attestedHash.String())
					}
				}
			}
			time.Sleep(1 * time.Second)
		}
	}
}
func processHash(msg []byte) chainhash.Hash {
	hash, hashErr := chainhash.NewHash(msg)
	if hashErr != nil {
		log.Error(hashErr)
	}
	return *hash
}