From 7a6ac7a3ec28e9238fe2e4726913ca0f165338be Mon Sep 17 00:00:00 2001 From: mars Date: Fri, 15 Mar 2019 16:15:54 +0800 Subject: [PATCH] Add confirm tx --- account/dpos_builder.go | 14 +++++++-- api/dpos_vote.go | 58 +++-------------------------------- blockchain/pseudohsm/sign_with_key.go | 56 +++++++++++++++++++++++++++++++++ mining/miner/miner.go | 35 +++++++++++++++++++++ protocol/bc/types/dpos.go | 16 +++------- protocol/bc/types/spend.go | 1 + protocol/bc/types/txinput.go | 6 ---- 7 files changed, 112 insertions(+), 74 deletions(-) create mode 100644 blockchain/pseudohsm/sign_with_key.go diff --git a/account/dpos_builder.go b/account/dpos_builder.go index 299e5a00..572183e5 100644 --- a/account/dpos_builder.go +++ b/account/dpos_builder.go @@ -29,6 +29,8 @@ type DopsAction struct { To string `json:"to"` Fee uint64 `json:"fee"` UseUnconfirmed bool `json:"use_unconfirmed"` + TxType uint32 `json:"tx_type"` + Height uint64 `json:"height"` } func (a *DopsAction) Build(ctx context.Context, b *txbuilder.TemplateBuilder) error { @@ -44,6 +46,12 @@ func (a *DopsAction) Build(ctx context.Context, b *txbuilder.TemplateBuilder) er missing = append(missing, "to") } + if types.TxType(a.TxType) < types.Binary || types.TxType(a.TxType) > types.ConfirmTx { + return errors.New("tx type of dpos is error") + } + + txType := types.TxType(a.TxType) + if len(missing) > 0 { return txbuilder.MissingFieldsError(missing...) } @@ -55,7 +63,7 @@ func (a *DopsAction) Build(ctx context.Context, b *txbuilder.TemplateBuilder) er // Cancel the reservation if the build gets rolled back. b.OnRollback(func() { a.Accounts.utxoKeeper.Cancel(res.id) }) for _, r := range res.utxos { - txInput, sigInst, err := DposTx(a.From, a.To, a.Amount, r) + txInput, sigInst, err := DposTx(a.From, a.To, a.Amount, r, txType, a.Height) if err != nil { return errors.Wrap(err, "creating inputs") } @@ -104,8 +112,8 @@ func (a *DopsAction) ActionType() string { } // DposInputs convert an utxo to the txinput -func DposTx(from, to string, stake uint64, u *UTXO) (*types.TxInput, *txbuilder.SigningInstruction, error) { - txInput := types.NewDpos(nil, from, to, u.SourceID, u.AssetID, stake, u.Amount, u.SourcePos, u.ControlProgram, types.Delegate) +func DposTx(from, to string, stake uint64, u *UTXO, txType types.TxType, h uint64) (*types.TxInput, *txbuilder.SigningInstruction, error) { + txInput := types.NewDpos(nil, from, to, u.SourceID, u.AssetID, stake, u.Amount, u.SourcePos, u.ControlProgram, txType, h) sigInst := &txbuilder.SigningInstruction{} var xpubs []chainkd.XPub var xprv chainkd.XPrv diff --git a/api/dpos_vote.go b/api/dpos_vote.go index e2379e10..43741129 100644 --- a/api/dpos_vote.go +++ b/api/dpos_vote.go @@ -6,10 +6,10 @@ import ( log "github.com/sirupsen/logrus" "github.com/vapor/account" + "github.com/vapor/blockchain/pseudohsm" "github.com/vapor/blockchain/txbuilder" "github.com/vapor/config" "github.com/vapor/crypto/ed25519/chainkd" - "github.com/vapor/errors" "github.com/vapor/protocol/bc" ) @@ -17,7 +17,7 @@ func (a *API) dpos(ctx context.Context, ins struct { To string `json:"to"` Fee uint64 `json:"fee"` Stake uint64 `json:"stake"` - TxType uint8 `json:"tx_type"` + TxType uint32 `json:"tx_type"` }) Response { // 找到utxo var assetID bc.AssetID @@ -28,6 +28,7 @@ func (a *API) dpos(ctx context.Context, ins struct { From: config.CommonConfig.Consensus.Dpos.Coinbase, To: ins.To, Fee: ins.Fee, + TxType: ins.TxType, } dpos.Amount = ins.Stake dpos.AssetId = &assetID @@ -43,7 +44,7 @@ func (a *API) dpos(ctx context.Context, ins struct { } var xprv chainkd.XPrv xprv.UnmarshalText([]byte(config.CommonConfig.Consensus.Dpos.XPrv)) - if err := signWithKey(tmpl, xprv); err != nil { + if err := pseudohsm.SignWithKey(tmpl, xprv); err != nil { return NewErrorResponse(err) } log.Info("Sign Transaction complete.") @@ -57,55 +58,4 @@ func (a *API) dpos(ctx context.Context, ins struct { log.WithField("tx_id", tmpl.Transaction.ID.String()).Info("submit single tx") return NewSuccessResponse(&submitTxResp{TxID: &tmpl.Transaction.ID}) - - //return NewSuccessResponse(nil) -} - -func signWithKey(tmpl *txbuilder.Template, xprv chainkd.XPrv) error { - for i, sigInst := range tmpl.SigningInstructions { - for j, wc := range sigInst.WitnessComponents { - switch sw := wc.(type) { - case *txbuilder.SignatureWitness: - err := sw.Sign(tmpl, uint32(i), xprv) - if err != nil { - return errors.WithDetailf(err, "adding signature(s) to signature witness component %d of input %d", j, i) - } - case *txbuilder.RawTxSigWitness: - err := sw.Sign(tmpl, uint32(i), xprv) - if err != nil { - return errors.WithDetailf(err, "adding signature(s) to raw-signature witness component %d of input %d", j, i) - } - } - } - } - return materializeWitnessesWithKey(tmpl) -} - -func materializeWitnessesWithKey(txTemplate *txbuilder.Template) error { - msg := txTemplate.Transaction - - if msg == nil { - return errors.Wrap(txbuilder.ErrMissingRawTx) - } - - if len(txTemplate.SigningInstructions) > len(msg.Inputs) { - return errors.Wrap(txbuilder.ErrBadInstructionCount) - } - - for i, sigInst := range txTemplate.SigningInstructions { - if msg.Inputs[sigInst.Position] == nil { - return errors.WithDetailf(txbuilder.ErrBadTxInputIdx, "signing instruction %d references missing tx input %d", i, sigInst.Position) - } - - var witness [][]byte - for j, wc := range sigInst.WitnessComponents { - err := wc.Materialize(&witness) - if err != nil { - return errors.WithDetailf(err, "error in witness component %d of input %d", j, i) - } - } - msg.SetInputArguments(sigInst.Position, witness) - } - - return nil } diff --git a/blockchain/pseudohsm/sign_with_key.go b/blockchain/pseudohsm/sign_with_key.go new file mode 100644 index 00000000..707f2d55 --- /dev/null +++ b/blockchain/pseudohsm/sign_with_key.go @@ -0,0 +1,56 @@ +package pseudohsm + +import ( + "github.com/vapor/blockchain/txbuilder" + "github.com/vapor/crypto/ed25519/chainkd" + "github.com/vapor/errors" +) + +func SignWithKey(tmpl *txbuilder.Template, xprv chainkd.XPrv) error { + for i, sigInst := range tmpl.SigningInstructions { + for j, wc := range sigInst.WitnessComponents { + switch sw := wc.(type) { + case *txbuilder.SignatureWitness: + err := sw.Sign(tmpl, uint32(i), xprv) + if err != nil { + return errors.WithDetailf(err, "adding signature(s) to signature witness component %d of input %d", j, i) + } + case *txbuilder.RawTxSigWitness: + err := sw.Sign(tmpl, uint32(i), xprv) + if err != nil { + return errors.WithDetailf(err, "adding signature(s) to raw-signature witness component %d of input %d", j, i) + } + } + } + } + return materializeWitnessesWithKey(tmpl) +} + +func materializeWitnessesWithKey(txTemplate *txbuilder.Template) error { + msg := txTemplate.Transaction + + if msg == nil { + return errors.Wrap(txbuilder.ErrMissingRawTx) + } + + if len(txTemplate.SigningInstructions) > len(msg.Inputs) { + return errors.Wrap(txbuilder.ErrBadInstructionCount) + } + + for i, sigInst := range txTemplate.SigningInstructions { + if msg.Inputs[sigInst.Position] == nil { + return errors.WithDetailf(txbuilder.ErrBadTxInputIdx, "signing instruction %d references missing tx input %d", i, sigInst.Position) + } + + var witness [][]byte + for j, wc := range sigInst.WitnessComponents { + err := wc.Materialize(&witness) + if err != nil { + return errors.WithDetailf(err, "error in witness component %d of input %d", j, i) + } + } + msg.SetInputArguments(sigInst.Position, witness) + } + + return nil +} diff --git a/mining/miner/miner.go b/mining/miner/miner.go index 518d33fc..6e0e25d8 100644 --- a/mining/miner/miner.go +++ b/mining/miner/miner.go @@ -5,6 +5,9 @@ import ( "sync" "time" + "github.com/vapor/blockchain/pseudohsm" + + "github.com/vapor/blockchain/txbuilder" "github.com/vapor/config" log "github.com/sirupsen/logrus" @@ -139,6 +142,38 @@ out: } func (m *Miner) sendConfirmTx(height uint64) error { + // 找到utxo + var assetID bc.AssetID + assetID.UnmarshalText([]byte("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")) + // 生成dpos交易 + dpos := account.DopsAction{ + Accounts: m.accountManager, + From: config.CommonConfig.Consensus.Dpos.Coinbase, + Fee: 100000000, + TxType: 6, + Height: height, + } + dpos.AssetId = &assetID + builder := txbuilder.NewBuilder(time.Now()) + if err := dpos.Build(nil, builder); err != nil { + return err + } + // 签名 + tmpl, _, err := builder.Build() + if err != nil { + return err + } + + var xprv chainkd.XPrv + xprv.UnmarshalText([]byte(config.CommonConfig.Consensus.Dpos.XPrv)) + if err := pseudohsm.SignWithKey(tmpl, xprv); err != nil { + return err + } + + if err := txbuilder.FinalizeTx(nil, m.chain, tmpl.Transaction); err != nil { + return err + } + return nil } diff --git a/protocol/bc/types/dpos.go b/protocol/bc/types/dpos.go index 9646db93..276d9e55 100644 --- a/protocol/bc/types/dpos.go +++ b/protocol/bc/types/dpos.go @@ -1,17 +1,10 @@ package types import ( - "github.com/vapor/protocol/bc" -) + "fmt" -/* -const ( - LoginCandidate DposType = iota - LogoutCandidate - Delegate - UnDelegate + "github.com/vapor/protocol/bc" ) -*/ type DposTx struct { SpendCommitmentSuffix []byte @@ -20,13 +13,12 @@ type DposTx struct { To string Amount uint64 Stake uint64 - PaymentAmount uint64 Arguments [][]byte Info string SpendCommitment } -func NewDpos(arguments [][]byte, from, to string, sourceID bc.Hash, assetID bc.AssetID, stake, amount, sourcePos uint64, controlProgram []byte, t TxType) *TxInput { +func NewDpos(arguments [][]byte, from, to string, sourceID bc.Hash, assetID bc.AssetID, stake, amount, sourcePos uint64, controlProgram []byte, t TxType, height uint64) *TxInput { var vote string switch t { case LoginCandidate: @@ -34,6 +26,8 @@ func NewDpos(arguments [][]byte, from, to string, sourceID bc.Hash, assetID bc.A case Delegate: vote = "vapor:1:event:vote" case UnDelegate: + case ConfirmTx: + vote = fmt.Sprintf("vapor:1:event:confirm:%d", height) } sc := SpendCommitment{ AssetAmount: bc.AssetAmount{ diff --git a/protocol/bc/types/spend.go b/protocol/bc/types/spend.go index 01d00f37..01d60c3c 100644 --- a/protocol/bc/types/spend.go +++ b/protocol/bc/types/spend.go @@ -12,6 +12,7 @@ const ( LogoutCandidate Delegate UnDelegate + ConfirmTx ) // SpendInput satisfies the TypedInput interface and represents a spend transaction. diff --git a/protocol/bc/types/txinput.go b/protocol/bc/types/txinput.go index 4fbcd188..58d01d63 100644 --- a/protocol/bc/types/txinput.go +++ b/protocol/bc/types/txinput.go @@ -265,9 +265,6 @@ func (t *TxInput) readFrom(r *blockchain.Reader) (err error) { if inp.Stake, err = blockchain.ReadVarint63(r); err != nil { return err } - if inp.PaymentAmount, err = blockchain.ReadVarint63(r); err != nil { - return err - } if inp.Arguments, err = blockchain.ReadVarstrList(r); err != nil { return err } @@ -387,9 +384,6 @@ func (t *TxInput) writeInputWitness(w io.Writer) error { if _, err := blockchain.WriteVarint63(w, inp.Stake); err != nil { return err } - if _, err := blockchain.WriteVarint63(w, inp.PaymentAmount); err != nil { - return err - } if _, err := blockchain.WriteVarstrList(w, inp.Arguments); err != nil { return err } -- 2.11.0