7 log "github.com/sirupsen/logrus"
9 "github.com/vapor/crypto/ed25519/chainkd"
10 chainjson "github.com/vapor/encoding/json"
13 // TODO(bobg): most of the code here is duplicated from
14 // signature_witness.go and needs refactoring.
16 // RawTxSigWitness is like SignatureWitness but doesn't involve
17 // signature programs.
18 type RawTxSigWitness struct {
19 Quorum int `json:"quorum"`
20 Keys []keyID `json:"keys"`
21 Sigs []chainjson.HexBytes `json:"signatures"`
24 func (sw *RawTxSigWitness) sign(ctx context.Context, tpl *Template, index uint32, auth string, signFn SignFunc) error {
25 if len(sw.Sigs) < len(sw.Keys) {
26 // Each key in sw.Keys may produce a signature in sw.Sigs. Make
27 // sure there are enough slots in sw.Sigs and that we preserve any
28 // sigs already present.
29 newSigs := make([]chainjson.HexBytes, len(sw.Keys))
30 copy(newSigs, sw.Sigs)
33 for i, keyID := range sw.Keys {
34 if len(sw.Sigs[i]) > 0 {
35 // Already have a signature for this key
38 path := make([][]byte, len(keyID.DerivationPath))
39 for i, p := range keyID.DerivationPath {
42 sigBytes, err := signFn(ctx, keyID.XPub, path, tpl.Hash(index).Byte32(), auth)
44 log.WithField("err", err).Warningf("computing signature %d", i)
48 // This break is ordered to avoid signing transaction successfully only once for a multiple-sign account
49 // that consist of different keys by the same password. Exit immediately when the signature is success,
50 // it means that only one signature will be successful in the loop for this multiple-sign account.
57 func (sw *RawTxSigWitness) Sign(tpl *Template, index uint32, xprv chainkd.XPrv) error {
58 if len(sw.Sigs) < len(sw.Keys) {
59 // Each key in sw.Keys may produce a signature in sw.Sigs. Make
60 // sure there are enough slots in sw.Sigs and that we preserve any
61 // sigs already present.
62 newSigs := make([]chainjson.HexBytes, len(sw.Keys))
63 copy(newSigs, sw.Sigs)
66 for i, keyID := range sw.Keys {
67 if len(sw.Sigs[i]) > 0 {
68 // Already have a signature for this key
71 if keyID.XPub.String() != xprv.XPub().String() {
74 data := tpl.Hash(index).Byte32()
75 sigBytes := xprv.Sign(data[:])
76 // This break is ordered to avoid signing transaction successfully only once for a multiple-sign account
77 // that consist of different keys by the same password. Exit immediately when the signature is success,
78 // it means that only one signature will be successful in the loop for this multiple-sign account.
85 func (sw RawTxSigWitness) Materialize(args *[][]byte) error {
87 for i := 0; i < len(sw.Sigs) && nsigs < sw.Quorum; i++ {
88 if len(sw.Sigs[i]) > 0 {
89 *args = append(*args, sw.Sigs[i])
96 // MarshalJSON convert struct to json
97 func (sw RawTxSigWitness) MarshalJSON() ([]byte, error) {
99 Type string `json:"type"`
100 Quorum int `json:"quorum"`
101 Keys []keyID `json:"keys"`
102 Sigs []chainjson.HexBytes `json:"signatures"`
104 Type: "raw_tx_signature",
109 return json.Marshal(obj)