func (tx *Transaction) SignIndex(idx int, compressed bool, hashType SigHashType, keys ...*xcrypto.PrvKey) error {
	txIn := tx.inputs[idx]
	signs := make([]PubKeySign, 0)
	if len(keys) > 1 && txIn.RedeemScript == nil {
		return xerror.NewError(Errors, ER_TRANSACTION_SIGN_REDEEM_EMPTY, idx, len(keys))
	}
	for _, key := range keys {
		var err error
		var pubkey []byte
		var signature []byte
		if compressed {
			pubkey = key.PubKey().SerializeCompressed()
		} else {
			pubkey = key.PubKey().SerializeUncompressed()
		}
		if txIn.HasWitness() {
			if signature, err = tx.WitnessSignature(idx, hashType, key); err != nil {
				return err
			}
		} else {
			if signature, err = tx.RawSignature(idx, hashType, key); err != nil {
				return err
			}
		}
		signs = append(signs, PubKeySign{
			PubKey:    pubkey,
			Signature: signature,
		})
	}
	return tx.EmbedIdxSignature(idx, signs)
}
SignIndex -- sign specified transaction input with pubkey format.
package xcore
import (
	"fmt"
	"strings"
	"github.com/keyfuse/tokucore/xbase"
	"github.com/keyfuse/tokucore/xcrypto"
	"github.com/keyfuse/tokucore/xerror"
	"github.com/keyfuse/tokucore/xvm"
)
const (
	hashSize        = 32          
	witnessMarker   = byte(0x00)  
	witnessFlag     = byte(0x01)  
	defaultSequence = 0xffffffff  
	witnessScaleFactor = 4
)
type SigHashType uint32
const (
	SigHashOld          SigHashType = 0x0
	SigHashAll          SigHashType = 0x1
	SigHashNone         SigHashType = 0x2
	SigHashSingle       SigHashType = 0x3
	SigTypeMask         SigHashType = 0x1f
	SigHashAnyOneCanPay SigHashType = 0x80
	sigHashMask = 0x1f
)
type TxIn struct {
	Hash               []byte  
	Index              uint32  
	Value              uint64  
	Sequence           uint32
	SignatureHash      []byte    
	RedeemScript       []byte    
	Witness            [][]byte  
	WitnessScriptCode  []byte    
	RawLockingScript   []byte    
	FinalLockingScript []byte    
	RawUnlockingScript []byte    
}
func NewTxIn(txHash []byte, n uint32, value uint64, script []byte, redeemScript []byte) (*TxIn, error) {
	scriptInstance, err := ParseLockingScript(script)
	if err != nil {
		return nil, err
	}
	witnessScriptCode, err := scriptInstance.GetWitnessScriptCode(redeemScript)
	if err != nil {
		return nil, err
	}
	rawLocking, err := scriptInstance.GetRawLockingScriptBytes()
	if err != nil {
		return nil, err
	}
	finalLocking, err := scriptInstance.GetFinalLockingScriptBytes(redeemScript)
	if err != nil {
		return nil, err
	}
	return &TxIn{
		Hash:               txHash,
		Index:              n,
		Value:              value,
		Sequence:           defaultSequence,
		RedeemScript:       redeemScript,
		WitnessScriptCode:  witnessScriptCode,
		RawLockingScript:   rawLocking,
		FinalLockingScript: finalLocking,
	}, nil
}
func (txin *TxIn) HasWitness() bool {
	return txin.WitnessScriptCode != nil
}
type TxOut struct {
	Value  uint64
	Script []byte
}
func NewTxOut(value uint64, script []byte) *TxOut {
	return &TxOut{
		Value:  value,
		Script: script,
	}
}
type Transaction struct {
	version      uint32
	lockTime     uint32
	inputs       []*TxIn
	outputs      []*TxOut
	hashPrevouts []byte
	hashSequence []byte
	hashOutputs  []byte
}
func NewTransaction() *Transaction {
	return &Transaction{
		version: 1,
	}
}
func (tx *Transaction) SetVersion(ver uint32) {
	tx.version = ver
}
func (tx *Transaction) SetLockTime(time uint32) {
	tx.lockTime = time
}
func (tx *Transaction) SetTxIn(idx int, amount uint64, script []byte, redeemScript []byte) error {
	txIn := tx.inputs[idx]
	scriptInstance, err := ParseLockingScript(script)
	if err != nil {
		return err
	}
	witnessScriptCode, err := scriptInstance.GetWitnessScriptCode(redeemScript)
	if err != nil {
		return err
	}
	rawLocking, err := scriptInstance.GetRawLockingScriptBytes()
	if err != nil {
		return err
	}
	finalLocking, err := scriptInstance.GetFinalLockingScriptBytes(redeemScript)
	if err != nil {
		return err
	}
	rawUnlocking, err := scriptInstance.WitnessToUnlockingScriptBytes(txIn.Witness)
	if err != nil {
		return err
	}
	if rawUnlocking != nil {
		txIn.RawUnlockingScript = rawUnlocking
	}
	txIn.Value = amount
	txIn.RedeemScript = redeemScript
	txIn.WitnessScriptCode = witnessScriptCode
	txIn.RawLockingScript = rawLocking
	txIn.FinalLockingScript = finalLocking
	return nil
}
func (tx *Transaction) AddInput(in *TxIn) {
	tx.inputs = append(tx.inputs, in)
}
func (tx *Transaction) AddOutput(out *TxOut) {
	tx.outputs = append(tx.outputs, out)
}
func (tx *Transaction) Hash() []byte {
	return xcrypto.DoubleSha256(tx.SerializeNoWitness())
}
func (tx *Transaction) ID() string {
	return xbase.NewIDToString(tx.Hash())
}
func (tx *Transaction) WitnessHash() []byte {
	return xcrypto.DoubleSha256(tx.Serialize())
}
func (tx *Transaction) WitnessID() string {
	return xbase.NewIDToString(tx.WitnessHash())
}