github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/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 }