func doMain() {
	if nKeys <= 0 || nKeys > 15 || nSigs <= 0 || nSigs > 15 || nSigs > nKeys {
		log.Errorf("invalid nSigs(%d) or nKeys(%d)", nSigs, nKeys)
	}
	if keys == "" && keysX == "" && keysY == "" {
		log.Error("Keys missing. Either provide -keys or -keysX and -keysY.")
	}
	if keys == "" {
		keysXSplit := strings.Split(keysX, ",")
		keysYSplit := strings.Split(keysY, ",")
		if len(keysXSplit) != nKeys && len(keysYSplit) != nKeys {
			log.Errorf("nKeys(%d) but %d keysX and %d keysY provided",
				nKeys, len(keysXSplit), len(keysYSplit))
		}
		pubs := make([]string, nKeys)
		for i := 0; i < nKeys; i++ {
			pub := pubFromCoordinates(keysXSplit[i], keysYSplit[i])
			pubs[i] = hex.EncodeToString(pub.SerializeCompressed())
		}
		infoFromPubs(pubs, nKeys, nSigs)
	} else {
		keysSplit := strings.Split(keys, ",")
		if len(keysSplit) != nKeys {
			log.Errorf("nKeys(%d) but %d keys provided", nKeys, len(keysSplit))
		}
		infoFromPubs(keysSplit, nKeys, nSigs)
	}
}
Generate multisig script and p2sh address for mainstay
from a list of pubkeys or pubX/pubY coordinates
package main
import (
	"crypto/ecdsa"
	"encoding/hex"
	"flag"
	"fmt"
	"math/big"
	"strings"
	"mainstay/crypto"
	"mainstay/log"
	"github.com/btcsuite/btcd/btcec"
	"github.com/btcsuite/btcd/chaincfg"
	"github.com/btcsuite/btcutil"
)
var (
	chain    string
	chainCfg chaincfg.Params
	nKeys int
	nSigs int
	keysX string
	keysY string
	keys  string
)
func init() {
	flag.StringVar(&chain, "chain", "", "Bitcoin chain configuration (regtest, testnet or mainnet)")
	flag.IntVar(&nKeys, "nKeys", 0, "Number of keys")
	flag.IntVar(&nSigs, "nSigs", 0, "Number of signatures")
	flag.StringVar(&keysX, "keysX", "", "List of pubkey X coordinates")
	flag.StringVar(&keysY, "keysY", "", "List of pubkey Y coordinates")
	flag.StringVar(&keys, "keys", "", "List of pubkeys")
	flag.Parse()
}
func main() {
	if chain == "regtest" {
		log.Infoln("REGTEST")
		chainCfg = chaincfg.RegressionNetParams
		doRegtest()
	} else {
		if chain == "testnet" {
			log.Infoln("TESTNET")
			chainCfg = chaincfg.TestNet3Params
		} else {
			log.Infoln("MAINNET")
			chainCfg = chaincfg.MainNetParams
		}
		doMain()
	}
}
func infoFromPubs(pubs []string, nKeys int, nSigs int) {
	pubmultistr := fmt.Sprintf("5%d", nSigs)
	for _, pub := range pubs {
		pubBytes, pubBytesErr := hex.DecodeString(pub)
		if pubBytesErr != nil {
			log.Errorf("failed decoding pub %s %v", pub, pubBytesErr)
		}
		pubP2pkh, pubP2pkhErr := btcutil.NewAddressPubKeyHash(btcutil.Hash160(pubBytes), &chainCfg)
		if pubP2pkhErr != nil {
			log.Errorf("failed generating addr from pub %s %v", pub, pubP2pkhErr)
		}
		log.Infof("pub P2PKH:\t%s\n", pubP2pkh)
		pubmultistr += "21" + pub
	}
	pubmultistr += fmt.Sprintf("5%d", nKeys)
	pubmultistr += "ae"
	log.Infof("%d-of-%d MULTISIG script: %s\n", nSigs, nKeys, pubmultistr)
	pubmultibytes, _ := hex.DecodeString(pubmultistr)
	addr, err := btcutil.NewAddressScriptHash(pubmultibytes, &chainCfg)
	if err != nil {
		log.Infoln(err)
	}
	log.Infof("%d-of-%d P2SH address: %s\n", nSigs, nKeys, addr.String())
}