github.com/bytom/bytom@v1.1.2-0.20221014091027-bbcba3df6075/blockchain/txbuilder/witness.go (about)

     1  package txbuilder
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/bytom/bytom/crypto/ed25519/chainkd"
     7  	chainjson "github.com/bytom/bytom/encoding/json"
     8  	"github.com/bytom/bytom/errors"
     9  )
    10  
    11  // SignFunc is the function passed into Sign that produces
    12  // a signature for a given xpub, derivation path, and hash.
    13  type SignFunc func(context.Context, chainkd.XPub, [][]byte, [32]byte, string) ([]byte, error)
    14  
    15  // MaterializeWitnesses takes a filled in Template and "materializes"
    16  // each witness component, turning it into a vector of arguments for
    17  // the tx's input witness, creating a fully-signed transaction.
    18  func materializeWitnesses(txTemplate *Template) error {
    19  	msg := txTemplate.Transaction
    20  
    21  	if msg == nil {
    22  		return errors.Wrap(ErrMissingRawTx)
    23  	}
    24  
    25  	if len(txTemplate.SigningInstructions) > len(msg.Inputs) {
    26  		return errors.Wrap(ErrBadInstructionCount)
    27  	}
    28  
    29  	for i, sigInst := range txTemplate.SigningInstructions {
    30  		if msg.Inputs[sigInst.Position] == nil {
    31  			return errors.WithDetailf(ErrBadTxInputIdx, "signing instruction %d references missing tx input %d", i, sigInst.Position)
    32  		}
    33  
    34  		var witness [][]byte
    35  		for j, wc := range sigInst.WitnessComponents {
    36  			err := wc.materialize(&witness)
    37  			if err != nil {
    38  				return errors.WithDetailf(err, "error in witness component %d of input %d", j, i)
    39  			}
    40  		}
    41  		msg.SetInputArguments(sigInst.Position, witness)
    42  	}
    43  
    44  	return nil
    45  }
    46  
    47  func signedCount(signs []chainjson.HexBytes) (count int) {
    48  	for _, sign := range signs {
    49  		if len(sign) > 0 {
    50  			count++
    51  		}
    52  	}
    53  	return
    54  }
    55  
    56  // SignProgress check is all the sign requirement are satisfy
    57  func SignProgress(txTemplate *Template) bool {
    58  	for _, sigInst := range txTemplate.SigningInstructions {
    59  		for _, wc := range sigInst.WitnessComponents {
    60  			switch sw := wc.(type) {
    61  			case *SignatureWitness:
    62  				if signedCount(sw.Sigs) < sw.Quorum {
    63  					return false
    64  				}
    65  			case *RawTxSigWitness:
    66  				if signedCount(sw.Sigs) < sw.Quorum {
    67  					return false
    68  				}
    69  			}
    70  		}
    71  	}
    72  	return true
    73  }