github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/blockchain/txbuilder/rawtxsig_witness.go (about) 1 package txbuilder 2 3 import ( 4 "context" 5 "encoding/json" 6 7 log "github.com/sirupsen/logrus" 8 9 chainjson "github.com/bytom/bytom/encoding/json" 10 ) 11 12 // TODO(bobg): most of the code here is duplicated from 13 // signature_witness.go and needs refactoring. 14 15 // RawTxSigWitness is like SignatureWitness but doesn't involve 16 // signature programs. 17 type RawTxSigWitness struct { 18 Quorum int `json:"quorum"` 19 Keys []keyID `json:"keys"` 20 Sigs []chainjson.HexBytes `json:"signatures"` 21 } 22 23 func (sw *RawTxSigWitness) sign(ctx context.Context, tpl *Template, index uint32, auth string, signFn SignFunc) error { 24 if len(sw.Sigs) < len(sw.Keys) { 25 // Each key in sw.Keys may produce a signature in sw.Sigs. Make 26 // sure there are enough slots in sw.Sigs and that we preserve any 27 // sigs already present. 28 newSigs := make([]chainjson.HexBytes, len(sw.Keys)) 29 copy(newSigs, sw.Sigs) 30 sw.Sigs = newSigs 31 } 32 for i, keyID := range sw.Keys { 33 if len(sw.Sigs[i]) > 0 { 34 // Already have a signature for this key 35 continue 36 } 37 path := make([][]byte, len(keyID.DerivationPath)) 38 for i, p := range keyID.DerivationPath { 39 path[i] = p 40 } 41 sigBytes, err := signFn(ctx, keyID.XPub, path, tpl.Hash(index).Byte32(), auth) 42 if err != nil { 43 log.WithFields(log.Fields{"module": logModule, "err": err}).Warningf("computing signature %d", i) 44 continue 45 } 46 47 // This break is ordered to avoid signing transaction successfully only once for a multiple-sign account 48 // that consist of different keys by the same password. Exit immediately when the signature is success, 49 // it means that only one signature will be successful in the loop for this multiple-sign account. 50 sw.Sigs[i] = sigBytes 51 break 52 } 53 return nil 54 } 55 56 func (sw RawTxSigWitness) materialize(args *[][]byte) error { 57 var nsigs int 58 for i := 0; i < len(sw.Sigs) && nsigs < sw.Quorum; i++ { 59 if len(sw.Sigs[i]) > 0 { 60 *args = append(*args, sw.Sigs[i]) 61 nsigs++ 62 } 63 } 64 return nil 65 } 66 67 // MarshalJSON convert struct to json 68 func (sw RawTxSigWitness) MarshalJSON() ([]byte, error) { 69 obj := struct { 70 Type string `json:"type"` 71 Quorum int `json:"quorum"` 72 Keys []keyID `json:"keys"` 73 Sigs []chainjson.HexBytes `json:"signatures"` 74 }{ 75 Type: "raw_tx_signature", 76 Quorum: sw.Quorum, 77 Keys: sw.Keys, 78 Sigs: sw.Sigs, 79 } 80 return json.Marshal(obj) 81 }