OSDN Git Service

Merge pull request #32 from Bytom/dev
[bytom/vapor.git] / api / dpos_vote.go
1 package api
2
3 import (
4         "context"
5         "time"
6
7         log "github.com/sirupsen/logrus"
8         "github.com/vapor/account"
9         "github.com/vapor/blockchain/txbuilder"
10         "github.com/vapor/config"
11         "github.com/vapor/crypto/ed25519/chainkd"
12         "github.com/vapor/errors"
13         "github.com/vapor/protocol/bc"
14 )
15
16 func (a *API) dpos(ctx context.Context, ins struct {
17         To     string `json:"to"`
18         Fee    uint64 `json:"fee"`
19         Stake  uint64 `json:"stake"`
20         TxType uint8  `json:"tx_type"`
21 }) Response {
22         // 找到utxo
23         var assetID bc.AssetID
24         assetID.UnmarshalText([]byte("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"))
25         // 生成dpos交易
26         dpos := account.DopsAction{
27                 Accounts: a.wallet.AccountMgr,
28                 From:     config.CommonConfig.Consensus.Dpos.Coinbase,
29                 To:       ins.To,
30                 Fee:      ins.Fee,
31         }
32         dpos.Amount = ins.Stake
33         dpos.AssetId = &assetID
34         builder := txbuilder.NewBuilder(time.Now())
35         if err := dpos.Build(ctx, builder); err != nil {
36                 return NewErrorResponse(err)
37         }
38
39         // 签名
40         tmpl, _, err := builder.Build()
41         if err != nil {
42                 return NewErrorResponse(err)
43         }
44         var xprv chainkd.XPrv
45         xprv.UnmarshalText([]byte(config.CommonConfig.Consensus.Dpos.XPrv))
46         if err := signWithKey(tmpl, xprv); err != nil {
47                 return NewErrorResponse(err)
48         }
49         log.Info("Sign Transaction complete.")
50         log.Info(txbuilder.SignProgress(tmpl))
51         //return NewSuccessResponse(&signTemplateResp{Tx: tmpl, SignComplete: txbuilder.SignProgress(tmpl)})
52         // 提交
53
54         if err := txbuilder.FinalizeTx(ctx, a.chain, tmpl.Transaction); err != nil {
55                 return NewErrorResponse(err)
56         }
57
58         log.WithField("tx_id", tmpl.Transaction.ID.String()).Info("submit single tx")
59         return NewSuccessResponse(&submitTxResp{TxID: &tmpl.Transaction.ID})
60
61         //return NewSuccessResponse(nil)
62 }
63
64 func signWithKey(tmpl *txbuilder.Template, xprv chainkd.XPrv) error {
65         for i, sigInst := range tmpl.SigningInstructions {
66                 for j, wc := range sigInst.WitnessComponents {
67                         switch sw := wc.(type) {
68                         case *txbuilder.SignatureWitness:
69                                 err := sw.Sign(tmpl, uint32(i), xprv)
70                                 if err != nil {
71                                         return errors.WithDetailf(err, "adding signature(s) to signature witness component %d of input %d", j, i)
72                                 }
73                         case *txbuilder.RawTxSigWitness:
74                                 err := sw.Sign(tmpl, uint32(i), xprv)
75                                 if err != nil {
76                                         return errors.WithDetailf(err, "adding signature(s) to raw-signature witness component %d of input %d", j, i)
77                                 }
78                         }
79                 }
80         }
81         return materializeWitnessesWithKey(tmpl)
82 }
83
84 func materializeWitnessesWithKey(txTemplate *txbuilder.Template) error {
85         msg := txTemplate.Transaction
86
87         if msg == nil {
88                 return errors.Wrap(txbuilder.ErrMissingRawTx)
89         }
90
91         if len(txTemplate.SigningInstructions) > len(msg.Inputs) {
92                 return errors.Wrap(txbuilder.ErrBadInstructionCount)
93         }
94
95         for i, sigInst := range txTemplate.SigningInstructions {
96                 if msg.Inputs[sigInst.Position] == nil {
97                         return errors.WithDetailf(txbuilder.ErrBadTxInputIdx, "signing instruction %d references missing tx input %d", i, sigInst.Position)
98                 }
99
100                 var witness [][]byte
101                 for j, wc := range sigInst.WitnessComponents {
102                         err := wc.Materialize(&witness)
103                         if err != nil {
104                                 return errors.WithDetailf(err, "error in witness component %d of input %d", j, i)
105                         }
106                 }
107                 msg.SetInputArguments(sigInst.Position, witness)
108         }
109
110         return nil
111 }