X-Git-Url: http://git.osdn.net/view?p=bytom%2Fvapor.git;a=blobdiff_plain;f=account%2Fdpos_builder.go;h=6652a916e933efb29677636e95782af11650ba96;hp=299e5a006ed4ec32786307e2f88e21f3f8306208;hb=ee01d543fdfe1fd0a4d548965c66f7923ea7b062;hpb=ddc7106558f020bde24cc337d51649611dddaba8 diff --git a/account/dpos_builder.go b/account/dpos_builder.go index 299e5a00..6652a916 100644 --- a/account/dpos_builder.go +++ b/account/dpos_builder.go @@ -3,16 +3,19 @@ package account import ( "context" "encoding/json" + "fmt" "github.com/vapor/config" "github.com/vapor/blockchain/txbuilder" "github.com/vapor/common" "github.com/vapor/consensus" + dpos "github.com/vapor/consensus/consensus/dpos" "github.com/vapor/crypto/ed25519/chainkd" "github.com/vapor/errors" "github.com/vapor/protocol/bc" "github.com/vapor/protocol/bc/types" + "github.com/vapor/protocol/vm" "github.com/vapor/protocol/vm/vmutil" ) @@ -25,10 +28,11 @@ func (m *Manager) DecodeDposAction(data []byte) (txbuilder.Action, error) { type DopsAction struct { Accounts *Manager bc.AssetAmount - From string `json:"from"` - To string `json:"to"` - Fee uint64 `json:"fee"` - UseUnconfirmed bool `json:"use_unconfirmed"` + DposType uint32 `json:"dpos_type"` + Address string `json:"address"` + Name string `json:"name"` + Forgers []string `json:"forgers"` + UseUnconfirmed bool `json:"use_unconfirmed"` } func (a *DopsAction) Build(ctx context.Context, b *txbuilder.TemplateBuilder) error { @@ -37,34 +41,94 @@ func (a *DopsAction) Build(ctx context.Context, b *txbuilder.TemplateBuilder) er if a.AssetId.IsZero() { missing = append(missing, "asset_id") } - if a.From == "" { - missing = append(missing, "from") + if a.Address == "" { + missing = append(missing, "address") } - if a.To == "" { - missing = append(missing, "to") - } - if len(missing) > 0 { return txbuilder.MissingFieldsError(missing...) } - res, err := a.Accounts.utxoKeeper.ReserveByAddress(a.From, a.AssetId, a.Amount, a.UseUnconfirmed, false) - if err != nil { - return errors.Wrap(err, "reserving utxos") + if types.TxType(a.DposType) < types.Binary || types.TxType(a.DposType) > types.CancelVote { + return errors.New("tx type of dpos is error") } + var ( + referenceData []byte + data []byte + op vm.Op + err error + ) + + switch types.TxType(a.DposType) { + case types.Binary: + case types.Registe: + if a.Name == "" { + return errors.New("name is null for dpos Registe") + } + if a.Amount < consensus.RegisrerForgerFee { + return errors.New("The transaction fee is 100000000 for dpos Registe") + } - // 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) + if dpos.GDpos.HaveDelegate(a.Name, a.Address) { + return errors.New("Forger name has registe") + } + + data, err = json.Marshal(&dpos.RegisterForgerData{Name: a.Name}) if err != nil { - return errors.Wrap(err, "creating inputs") + return err } - if err = b.AddInput(txInput, sigInst); err != nil { - return errors.Wrap(err, "adding inputs") + op = vm.OP_REGISTE + case types.Vote: + if len(a.Forgers) == 0 { + return errors.New("Forgers is null for dpos Vote") + } + + if a.Amount < consensus.VoteForgerFee { + return errors.New("The transaction fee is 10000000 for dpos Registe") + } + + for _, forger := range a.Forgers { + if dpos.GDpos.HaveVote(a.Address, forger) { + return fmt.Errorf("delegate name: %s is voted", forger) + } } + + data, err = json.Marshal(&dpos.VoteForgerData{Forgers: a.Forgers}) + if err != nil { + return err + } + op = vm.OP_VOTE + case types.CancelVote: + if len(a.Forgers) == 0 { + return errors.New("Forgers is null for dpos CancelVote") + } + if a.Amount < consensus.CancelVoteForgerFee { + return errors.New("The transaction fee is 10000000 for dpos Registe") + } + + for _, forger := range a.Forgers { + if !dpos.GDpos.HaveVote(a.Address, forger) { + return fmt.Errorf("delegate name: %s is not voted", forger) + } + } + + data, err = json.Marshal(&dpos.CancelVoteForgerData{Forgers: a.Forgers}) + if err != nil { + return err + } + op = vm.OP_REVOKE + } + + msg := dpos.DposMsg{ + Type: op, + Data: data, + } + + referenceData, err = json.Marshal(&msg) + if err != nil { + return err } + b.SetReferenceData(referenceData) - res, err = a.Accounts.utxoKeeper.ReserveByAddress(a.From, a.AssetId, a.Fee, a.UseUnconfirmed, true) + res, err := a.Accounts.utxoKeeper.ReserveByAddress(a.Address, a.AssetId, a.Amount, a.UseUnconfirmed, false) if err != nil { return errors.Wrap(err, "reserving utxos") } @@ -82,7 +146,7 @@ func (a *DopsAction) Build(ctx context.Context, b *txbuilder.TemplateBuilder) er } } if res.change >= 0 { - address, err := common.DecodeAddress(a.From, &consensus.ActiveNetParams) + address, err := common.DecodeAddress(a.Address, &consensus.ActiveNetParams) if err != nil { return err } @@ -103,53 +167,13 @@ func (a *DopsAction) ActionType() string { return "dpos" } -// 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) - sigInst := &txbuilder.SigningInstruction{} - var xpubs []chainkd.XPub - var xprv chainkd.XPrv - xprv.UnmarshalText([]byte(config.CommonConfig.Consensus.Dpos.XPrv)) - xpubs = append(xpubs, xprv.XPub()) - quorum := len(xpubs) - if u.Address == "" { - sigInst.AddWitnessKeysWithOutPath(xpubs, quorum) - return txInput, sigInst, nil - } - - address, err := common.DecodeAddress(u.Address, &consensus.ActiveNetParams) - if err != nil { - return nil, nil, err - } - sigInst.AddRawWitnessKeysWithoutPath(xpubs, quorum) - switch address.(type) { - case *common.AddressWitnessPubKeyHash: - derivedPK := xpubs[0].PublicKey() - sigInst.WitnessComponents = append(sigInst.WitnessComponents, txbuilder.DataWitness([]byte(derivedPK))) - - case *common.AddressWitnessScriptHash: - derivedXPubs := xpubs - derivedPKs := chainkd.XPubKeys(derivedXPubs) - script, err := vmutil.P2SPMultiSigProgram(derivedPKs, quorum) - if err != nil { - return nil, nil, err - } - sigInst.WitnessComponents = append(sigInst.WitnessComponents, txbuilder.DataWitness(script)) - - default: - return nil, nil, errors.New("unsupport address type") - } - - return txInput, sigInst, nil -} - // spendInput convert an utxo to the txinput func spendInput(u *UTXO) (*types.TxInput, *txbuilder.SigningInstruction, error) { txSpendInput := types.NewSpendInput(nil, u.SourceID, u.AssetID, u.Amount, u.SourcePos, u.ControlProgram) sigInst := &txbuilder.SigningInstruction{} var xpubs []chainkd.XPub var xprv chainkd.XPrv - xprv.UnmarshalText([]byte(config.CommonConfig.Consensus.Dpos.XPrv)) + xprv.UnmarshalText([]byte(config.CommonConfig.Consensus.XPrv)) xpubs = append(xpubs, xprv.XPub()) quorum := len(xpubs) if u.Address == "" {