OSDN Git Service

refatcor(feaderation): use P2WSHProgram for federation program on sidechain (#233)
[bytom/vapor.git] / blockchain / txbuilder / signing_instruction.go
1 package txbuilder
2
3 import (
4         "encoding/json"
5
6         "github.com/vapor/crypto/ed25519/chainkd"
7         chainjson "github.com/vapor/encoding/json"
8         "github.com/vapor/errors"
9 )
10
11 func (si *SigningInstruction) AddDataWitness(data chainjson.HexBytes) {
12         dw := DataWitness(data)
13         si.WitnessComponents = append(si.WitnessComponents, &dw)
14 }
15
16 // AddWitnessKeys adds a SignatureWitness with the given quorum and
17 // list of keys derived by applying the derivation path to each of the
18 // xpubs.
19 func (si *SigningInstruction) AddWitnessKeys(xpubs []chainkd.XPub, path [][]byte, quorum int) {
20         hexPath := make([]chainjson.HexBytes, 0, len(path))
21         for _, p := range path {
22                 hexPath = append(hexPath, p)
23         }
24
25         keyIDs := make([]keyID, 0, len(xpubs))
26         for _, xpub := range xpubs {
27                 keyIDs = append(keyIDs, keyID{xpub, hexPath})
28         }
29
30         sw := &SignatureWitness{
31                 Quorum: quorum,
32                 Keys:   keyIDs,
33         }
34         si.WitnessComponents = append(si.WitnessComponents, sw)
35 }
36
37 // AddRawWitnessKeys adds a SignatureWitness with the given quorum and
38 // list of keys derived by applying the derivation path to each of the
39 // xpubs.
40 func (si *SigningInstruction) AddRawWitnessKeys(xpubs []chainkd.XPub, path [][]byte, quorum int) {
41         hexPath := make([]chainjson.HexBytes, 0, len(path))
42         for _, p := range path {
43                 hexPath = append(hexPath, p)
44         }
45
46         keyIDs := make([]keyID, 0, len(xpubs))
47         for _, xpub := range xpubs {
48                 keyIDs = append(keyIDs, keyID{xpub, hexPath})
49         }
50
51         sw := &RawTxSigWitness{
52                 Quorum: quorum,
53                 Keys:   keyIDs,
54         }
55         si.WitnessComponents = append(si.WitnessComponents, sw)
56 }
57
58 // SigningInstruction gives directions for signing inputs in a TxTemplate.
59 type SigningInstruction struct {
60         Position          uint32             `json:"position"`
61         WitnessComponents []witnessComponent `json:"witness_components,omitempty"`
62 }
63
64 // witnessComponent is the abstract type for the parts of a
65 // SigningInstruction.  Each witnessComponent produces one or more
66 // arguments for a VM program via its materialize method. Concrete
67 // witnessComponent types include SignatureWitness and dataWitness.
68 type witnessComponent interface {
69         materialize(*[][]byte) error
70 }
71
72 // UnmarshalJSON unmarshal SigningInstruction
73 func (si *SigningInstruction) UnmarshalJSON(b []byte) error {
74         var pre struct {
75                 Position          uint32            `json:"position"`
76                 WitnessComponents []json.RawMessage `json:"witness_components"`
77         }
78         err := json.Unmarshal(b, &pre)
79         if err != nil {
80                 return err
81         }
82
83         si.Position = pre.Position
84         for i, wc := range pre.WitnessComponents {
85                 var t struct {
86                         Type string
87                 }
88                 err = json.Unmarshal(wc, &t)
89                 if err != nil {
90                         return errors.Wrapf(err, "unmarshaling error on witness component %d, input %s", i, wc)
91                 }
92                 switch t.Type {
93                 case "data":
94                         var d struct {
95                                 Value chainjson.HexBytes
96                         }
97                         err = json.Unmarshal(wc, &d)
98                         if err != nil {
99                                 return errors.Wrapf(err, "unmarshaling error on witness component %d, type data, input %s", i, wc)
100                         }
101                         si.WitnessComponents = append(si.WitnessComponents, DataWitness(d.Value))
102
103                 case "signature":
104                         var s SignatureWitness
105                         err = json.Unmarshal(wc, &s)
106                         if err != nil {
107                                 return errors.Wrapf(err, "unmarshaling error on witness component %d, type signature, input %s", i, wc)
108                         }
109                         si.WitnessComponents = append(si.WitnessComponents, &s)
110
111                 case "raw_tx_signature":
112                         var s RawTxSigWitness
113                         err = json.Unmarshal(wc, &s)
114                         if err != nil {
115                                 return errors.Wrapf(err, "unmarshaling error on witness component %d, type raw_signature, input %s", i, wc)
116                         }
117                         si.WitnessComponents = append(si.WitnessComponents, &s)
118
119                 default:
120                         return errors.WithDetailf(ErrBadWitnessComponent, "witness component %d has unknown type '%s'", i, t.Type)
121                 }
122         }
123         return nil
124 }