OSDN Git Service

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