OSDN Git Service

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