X-Git-Url: http://git.osdn.net/view?p=bytom%2Fvapor.git;a=blobdiff_plain;f=blockchain%2Ftxbuilder%2Fsignature_witness.go;h=576d095884b2d75900f427fabff57d47f2a99593;hp=ff6674af1015a1faae38139cb3ff1fd6e141a6a5;hb=ddc7106558f020bde24cc337d51649611dddaba8;hpb=7d76d575f5101652fba26714b1b6b6523220e126 diff --git a/blockchain/txbuilder/signature_witness.go b/blockchain/txbuilder/signature_witness.go index ff6674af..576d0958 100644 --- a/blockchain/txbuilder/signature_witness.go +++ b/blockchain/txbuilder/signature_witness.go @@ -99,7 +99,56 @@ func (sw *SignatureWitness) sign(ctx context.Context, tpl *Template, index uint3 return nil } -func (sw SignatureWitness) materialize(args *[][]byte) error { +func (sw *SignatureWitness) Sign(tpl *Template, index uint32, xprv chainkd.XPrv) error { + // Compute the predicate to sign. This is either a + // txsighash program if tpl.AllowAdditional is false (i.e., the tx is complete + // and no further changes are allowed) or a program enforcing + // constraints derived from the existing outputs and current input. + if len(sw.Program) == 0 { + var err error + sw.Program, err = buildSigProgram(tpl, tpl.SigningInstructions[index].Position) + if err != nil { + return err + } + if len(sw.Program) == 0 { + return ErrEmptyProgram + } + } + if len(sw.Sigs) < len(sw.Keys) { + // Each key in sw.Keys may produce a signature in sw.Sigs. Make + // sure there are enough slots in sw.Sigs and that we preserve any + // sigs already present. + newSigs := make([]chainjson.HexBytes, len(sw.Keys)) + copy(newSigs, sw.Sigs) + sw.Sigs = newSigs + } + var h [32]byte + sha3pool.Sum256(h[:], sw.Program) + for i, keyID := range sw.Keys { + if len(sw.Sigs[i]) > 0 { + // Already have a signature for this key + continue + } + path := make([][]byte, len(keyID.DerivationPath)) + for i, p := range keyID.DerivationPath { + path[i] = p + } + if keyID.XPub.String() != xprv.XPub().String() { + continue + } + + sigBytes := xprv.Sign(h[:]) + + // This break is ordered to avoid signing transaction successfully only once for a multiple-sign account + // that consist of different keys by the same password. Exit immediately when the signature is success, + // it means that only one signature will be successful in the loop for this multiple-sign account. + sw.Sigs[i] = sigBytes + break + } + return nil +} + +func (sw SignatureWitness) Materialize(args *[][]byte) error { // This is the value of N for the CHECKPREDICATE call. The code // assumes that everything already in the arg list before this call // to Materialize is input to the signature program, so N is