func calcBip143SignatureHash(subScript []byte, sigHashes *txscript.TxSigHashes,
	hashType txscript.SigHashType, tx *wire.MsgTx, idx int, amt int64) []byte {
	if idx > len(tx.TxIn)-1 {
		fmt.Printf("calcBip143SignatureHash error: idx %d but %d txins",
			idx, len(tx.TxIn))
		return nil
	}
	var sigHash bytes.Buffer
	var bVersion [4]byte
	binary.LittleEndian.PutUint32(bVersion[:], uint32(tx.Version))
	sigHash.Write(bVersion[:])
	var zeroHash chainhash.Hash
	if hashType&txscript.SigHashAnyOneCanPay == 0 {
		sigHash.Write(sigHashes.HashPrevOuts[:])
	} else {
		sigHash.Write(zeroHash[:])
	}
	if hashType&txscript.SigHashAnyOneCanPay == 0 &&
		hashType&sigHashMask != txscript.SigHashSingle &&
		hashType&sigHashMask != txscript.SigHashNone {
		sigHash.Write(sigHashes.HashSequence[:])
	} else {
		sigHash.Write(zeroHash[:])
	}
	sigHash.Write(tx.TxIn[idx].PreviousOutPoint.Hash[:])
	var bIndex [4]byte
	binary.LittleEndian.PutUint32(bIndex[:], tx.TxIn[idx].PreviousOutPoint.Index)
	sigHash.Write(bIndex[:])
	wire.WriteVarBytes(&sigHash, 0, subScript)
	var bAmount [8]byte
	binary.LittleEndian.PutUint64(bAmount[:], uint64(amt))
	sigHash.Write(bAmount[:])
	var bSequence [4]byte
	binary.LittleEndian.PutUint32(bSequence[:], tx.TxIn[idx].Sequence)
	sigHash.Write(bSequence[:])
	if hashType&sigHashMask != txscript.SigHashSingle &&
		hashType&sigHashMask != txscript.SigHashNone {
		sigHash.Write(sigHashes.HashOutputs[:])
	} else if hashType&sigHashMask == txscript.SigHashSingle && idx < len(tx.TxOut) {
		var b bytes.Buffer
		wire.WriteTxOut(&b, 0, 0, tx.TxOut[idx])
		sigHash.Write(chainhash.DoubleHashB(b.Bytes()))
	} else {
		sigHash.Write(zeroHash[:])
	}
	var bLockTime [4]byte
	binary.LittleEndian.PutUint32(bLockTime[:], tx.LockTime)
	sigHash.Write(bLockTime[:])
	var bHashType [4]byte
	binary.LittleEndian.PutUint32(bHashType[:], uint32(hashType|SigHashForkID))
	sigHash.Write(bHashType[:])
	return chainhash.DoubleHashB(sigHash.Bytes())
}
calcBip143SignatureHash computes the sighash digest of a transaction's
input using the new, optimized digest calculation algorithm defined
in BIP0143: https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki.
This function makes use of pre-calculated sighash fragments stored within
the passed HashCache to eliminate duplicate hashing computations when
calculating the final digest, reducing the complexity from O(N^2) to O(N).
Additionally, signatures now cover the input value of the referenced unspent
output. This allows offline, or hardware wallets to compute the exact amount
being spent, in addition to the final transaction fee. In the case the
wallet if fed an invalid input amount, the real sighash will differ causing
the produced signature to be invalid.
package bchutil
import (
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"github.com/btcsuite/btcd/btcec"
	"github.com/btcsuite/btcd/chaincfg"
	"github.com/btcsuite/btcd/chaincfg/chainhash"
	"github.com/btcsuite/btcd/txscript"
	"github.com/btcsuite/btcd/wire"
	"github.com/btcsuite/btcutil"
)
const (
	SigHashForkID txscript.SigHashType = 0x40
	sigHashMask                        = 0x1f
)
func RawTxInSignature(tx *wire.MsgTx, idx int, subScript []byte,
	hashType txscript.SigHashType, key *btcec.PrivateKey, amt int64) ([]byte, error) {
	hash := calcBip143SignatureHash(subScript, txscript.NewTxSigHashes(tx), hashType, tx, idx, amt)
	signature, err := key.Sign(hash)
	if err != nil {
		return nil, fmt.Errorf("cannot sign tx input: %s", err)
	}
	return append(signature.Serialize(), byte(hashType|SigHashForkID)), nil
}
func SignTxOutput(chainParams *chaincfg.Params, tx *wire.MsgTx, idx int,
	pkScript []byte, hashType txscript.SigHashType, kdb txscript.KeyDB, sdb txscript.ScriptDB,
	previousScript []byte, amt int64) ([]byte, error) {
	sigScript, class, addresses, nrequired, err := sign(chainParams, tx,
		idx, pkScript, hashType, kdb, sdb, amt)
	if err != nil {
		return nil, err
	}
	if class == txscript.ScriptHashTy {
		realSigScript, _, _, _, err := sign(chainParams, tx, idx,
			sigScript, hashType, kdb, sdb, amt)
		if err != nil {
			return nil, err
		}
		builder := txscript.NewScriptBuilder()
		builder.AddOps(realSigScript)
		builder.AddData(sigScript)
		sigScript, _ = builder.Script()
	}
	mergedScript := mergeScripts(chainParams, tx, idx, pkScript, class,
		addresses, nrequired, sigScript, previousScript)
	return mergedScript, nil
}