OSDN Git Service

Merge pull request #41 from Bytom/dev
[bytom/vapor.git] / blockchain / txbuilder / witness.go
1 package txbuilder
2
3 import (
4         "context"
5
6         "github.com/vapor/crypto/ed25519/chainkd"
7         chainjson "github.com/vapor/encoding/json"
8         "github.com/vapor/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 }