func (b *Blinder) validate() error {
	for _, input := range b.pset.Inputs {
		if input.NonWitnessUtxo == nil && input.WitnessUtxo == nil {
			return errors.New(
				"all inputs must contain a non witness utxo or a witness utxo",
			)
		}
		if len(input.PartialSigs) > 0 {
			return errors.New("inputs must not contain signatures")
		}
	}
	if len(b.inputsBlindingData) != len(b.pset.Inputs) {
		return errors.New(
			"inputs blinding data do not match the number of inputs",
		)
	}
	return nil
}
validate checks that the all the required Blinder's fields are valid and
that the partial transaction provided is valid and ready to be blinded
package pset
import (
	"bytes"
	"crypto/rand"
	"errors"
	"sort"
	"github.com/btcsuite/btcd/btcec"
	"github.com/vulpemventures/go-elements/confidential"
	"github.com/vulpemventures/go-elements/elementsutil"
	"github.com/vulpemventures/go-elements/transaction"
)
var (
	ErrGenerateSurjectionProof = errors.New(
		"failed to generate surjection proof, please retry",
	)
	ErrNeedPrevout = errors.New(
		"need prevout to get blinding data",
	)
)
type randomNumberGenerator func() ([]byte, error)
type Blinder struct {
	pset                        *Pset
	inputsBlindingData          []confidential.UnblindOutputResult
	blindingPubKeyByOutputIndex map[int][]byte
	issuanceBlindingPrivateKeys []IssuanceBlindingPrivateKeys
	rng                         randomNumberGenerator
}
type BlindingDataLike interface {
	GetUnblindOutputResult(prevout *transaction.TxOutput) (*confidential.UnblindOutputResult, error)
}
type PrivateBlindingKey []byte
type BlindingData confidential.UnblindOutputResult
func (privKey PrivateBlindingKey) GetUnblindOutputResult(prevout *transaction.TxOutput) (*confidential.UnblindOutputResult, error) {
	if prevout == nil {
		return nil, ErrNeedPrevout
	}
	if prevout.IsConfidential() {
		return confidential.UnblindOutputWithKey(prevout, privKey)
	}
	satoshiValue, err := elementsutil.ElementsToSatoshiValue(prevout.Value)
	if err != nil {
		return nil, err
	}
	blindingData := &confidential.UnblindOutputResult{
		Value:               satoshiValue,
		Asset:               prevout.Asset[1:],
		ValueBlindingFactor: make([]byte, 32),
		AssetBlindingFactor: make([]byte, 32),
	}
	return blindingData, nil
}
func (blindingData BlindingData) GetUnblindOutputResult(prevout *transaction.TxOutput) (*confidential.UnblindOutputResult, error) {
	return &confidential.UnblindOutputResult{
		Value:               blindingData.Value,
		Asset:               blindingData.Asset,
		ValueBlindingFactor: blindingData.ValueBlindingFactor,
		AssetBlindingFactor: blindingData.AssetBlindingFactor,
	}, nil
}
type IssuanceBlindingPrivateKeys struct {
	AssetKey []byte
	TokenKey []byte
}
func (ik IssuanceBlindingPrivateKeys) ToSlice() [][]byte {
	keys := [][]byte{ik.AssetKey}
	if len(ik.TokenKey) > 0 {
		keys = append(keys, ik.TokenKey)
	}
	return keys
}
func VerifyBlinding(
	pset *Pset,
	blindingDataLikes []BlindingDataLike,
	outBlindKeysByIndex map[int][]byte,
	inIssuanceKeys []IssuanceBlindingPrivateKeys,
) (bool, error) {
	inputsBlindingData, err := blindingDataLikeToUnblindResult(blindingDataLikes, pset)
	if err != nil {
		return false, err
	}
	return verifyBlinding(pset, inputsBlindingData, outBlindKeysByIndex, inIssuanceKeys), nil
}
func NewBlinder(
	pset *Pset,
	blindingDataLikes []BlindingDataLike,
	outputsPubKeyByIndex map[int][]byte,
	issuanceBlindingPrivateKeys []IssuanceBlindingPrivateKeys,
	rng randomNumberGenerator,
) (*Blinder, error) {
	if err := pset.SanityCheck(); err != nil {
		return nil, err
	}
	var gen randomNumberGenerator
	if rng == nil {
		gen = generateRandomNumber
	} else {
		gen = rng
	}
	inputsBlindingData, err := blindingDataLikeToUnblindResult(blindingDataLikes, pset)
	if err != nil {
		return nil, err
	}
	return &Blinder{
		pset:                        pset,
		inputsBlindingData:          inputsBlindingData,
		issuanceBlindingPrivateKeys: issuanceBlindingPrivateKeys,
		blindingPubKeyByOutputIndex: outputsPubKeyByIndex,
		rng:                         gen,
	}, nil
}
func (b *Blinder) Blind() error {
	err := b.validate()
	if err != nil {
		return err
	}
	issuanceBlindingData, err := b.unblindInputsToIssuanceBlindingData()
	if err != nil {
		return err
	}
	totalUnblinded := append(b.inputsBlindingData, issuanceBlindingData...)
	err = b.blindOutputs(totalUnblinded)
	if err != nil {
		return err
	}
	return b.blindInputs(issuanceBlindingData)
}