OSDN Git Service

Add the implementation for dppos
authormars <mars@bytom.io>
Wed, 20 Mar 2019 09:10:21 +0000 (17:10 +0800)
committermars <mars@bytom.io>
Fri, 22 Mar 2019 05:12:12 +0000 (13:12 +0800)
53 files changed:
account/accounts_test.go
account/dpos_builder.go
api/api.go
api/api_test.go
api/dpos.go [new file with mode: 0644]
api/dpos_vote.go [deleted file]
api/hsm.go
api/transact.go
asset/asset_test.go
blockchain/txbuilder/builder.go
cmd/vapor/consensus.json
cmd/vapor/side_chain/config.toml
config/config.go
config/genesis.go
consensus/consensus/consensus.go
consensus/consensus/dpos.go [deleted file]
consensus/consensus/dpos/custom_tx.go [deleted file]
consensus/consensus/dpos/dpos.go
consensus/consensus/dpos/signer_queue.go [deleted file]
consensus/consensus/dpos/snapshot.go [deleted file]
consensus/consensus/dpos/vote.go [moved from consensus/consensus/vote.go with 51% similarity]
consensus/consensus/dpos/vote_type.go [moved from consensus/consensus/vote_type.go with 71% similarity]
consensus/consensus/errors.go [deleted file]
consensus/general.go
database/leveldb/store_test.go
mining/miner/miner.go
mining/mining.go
node/node.go
protocol/bc/bc.pb.go
protocol/bc/bc.proto
protocol/bc/blockheader.go
protocol/bc/entry_test.go
protocol/bc/txheader.go
protocol/bc/types/block_header.go
protocol/bc/types/bytom/types/map.go
protocol/bc/types/dpos.go
protocol/bc/types/map.go
protocol/bc/types/merkle_test.go
protocol/bc/types/spend.go
protocol/bc/types/transaction.go
protocol/block.go
protocol/block_test.go
protocol/protocol.go
protocol/state/blockindex.go
protocol/validation/block.go
protocol/vm/ops.go
test/bench_blockchain_test.go
test/block_test_util.go
test/util.go
test/wallet_test_util.go
vendor/github.com/tendermint/tmlibs/common/os.go
wallet/unconfirmed_test.go
wallet/wallet_test.go

index f94c51c..b1710df 100644 (file)
@@ -14,6 +14,8 @@ import (
        "github.com/vapor/common"
        "github.com/vapor/config"
        "github.com/vapor/consensus"
+       engine "github.com/vapor/consensus/consensus"
+       dpos "github.com/vapor/consensus/consensus/dpos"
        "github.com/vapor/crypto/ed25519/chainkd"
        "github.com/vapor/database/leveldb"
        "github.com/vapor/errors"
@@ -211,14 +213,14 @@ func mockAccountManager(t *testing.T) *Manager {
 
        config.CommonConfig = config.DefaultConfig()
        consensus.SoloNetParams.Signer = "78673764e0ba91a4c5ba9ec0c8c23c69e3d73bf27970e05e0a977e81e13bde475264d3b177a96646bc0ce517ae7fd63504c183ab6d330dea184331a4cf5912d5"
-       config.CommonConfig.Consensus.Dpos.SelfVoteSigners = append(config.CommonConfig.Consensus.Dpos.SelfVoteSigners, "vsm1qkm743xmgnvh84pmjchq2s4tnfpgu9ae2f9slep")
-       config.CommonConfig.Consensus.Dpos.XPrv = "a8e281b615809046698fb0b0f2804a36d824d48fa443350f10f1b80649d39e5f1e85cf9855548915e36137345910606cbc8e7dd8497c831dce899ee6ac112445"
-       for _, v := range config.CommonConfig.Consensus.Dpos.SelfVoteSigners {
+       config.CommonConfig.Consensus.SelfVoteSigners = append(config.CommonConfig.Consensus.SelfVoteSigners, "vsm1qkm743xmgnvh84pmjchq2s4tnfpgu9ae2f9slep")
+       config.CommonConfig.Consensus.XPrv = "a8e281b615809046698fb0b0f2804a36d824d48fa443350f10f1b80649d39e5f1e85cf9855548915e36137345910606cbc8e7dd8497c831dce899ee6ac112445"
+       for _, v := range config.CommonConfig.Consensus.SelfVoteSigners {
                address, err := common.DecodeAddress(v, &consensus.SoloNetParams)
                if err != nil {
                        t.Fatal(err)
                }
-               config.CommonConfig.Consensus.Dpos.Signers = append(config.CommonConfig.Consensus.Dpos.Signers, address)
+               config.CommonConfig.Consensus.Signers = append(config.CommonConfig.Consensus.Signers, address)
        }
        dirPath, err := ioutil.TempDir(".", "")
        if err != nil {
@@ -231,7 +233,12 @@ func mockAccountManager(t *testing.T) *Manager {
 
        store := leveldb.NewStore(testDB)
        txPool := protocol.NewTxPool(store)
-       chain, err := protocol.NewChain(store, txPool)
+       var engine engine.Engine
+       switch config.CommonConfig.Consensus.Type {
+       case "dpos":
+               engine = dpos.GDpos
+       }
+       chain, err := protocol.NewChain(store, txPool, engine)
        if err != nil {
                t.Fatal(err)
        }
index 572183e..64f5061 100644 (file)
@@ -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,12 +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"`
-       TxType         uint32 `json:"tx_type"`
-       Height         uint64 `json:"height"`
+       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 {
@@ -39,40 +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...)
        }
-
-       if types.TxType(a.TxType) < types.Binary || types.TxType(a.TxType) > types.ConfirmTx {
+       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")
+               }
 
-       txType := types.TxType(a.TxType)
+               if dpos.GDpos.HaveDelegate(a.Name, a.Address) {
+                       return errors.New("Forger name has registe")
+               }
 
-       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")
-       }
+               data, err = json.Marshal(&dpos.RegisterForgerData{Name: a.Name})
+               if err != nil {
+                       return err
+               }
+               op = vm.OP_REGISTE
+       case types.Vote:
+               if len(a.Forgers) == 0 {
+                       return errors.New("Forgers is null for dpos Vote")
+               }
 
-       // 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, txType, a.Height)
+               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 errors.Wrap(err, "creating inputs")
+                       return err
                }
-               if err = b.AddInput(txInput, sigInst); err != nil {
-                       return errors.Wrap(err, "adding inputs")
+               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")
        }
@@ -90,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
                }
@@ -117,7 +173,7 @@ func DposTx(from, to string, stake uint64, u *UTXO, txType types.TxType, h uint6
        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 == "" {
@@ -157,7 +213,7 @@ func spendInput(u *UTXO) (*types.TxInput, *txbuilder.SigningInstruction, error)
        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 == "" {
index af242a6..1e0d303 100644 (file)
@@ -253,16 +253,17 @@ func (a *API) buildHandler() {
                m.Handle("/get-side-raw-transaction", jsonHandler(a.getSideRawTransaction))
                m.Handle("/build-mainchain-tx", jsonHandler(a.buildMainChainTxForContract))
                m.Handle("/sign-with-key", jsonHandler(a.signWithKey))
-               m.Handle("/dpos", jsonHandler(a.dpos))
-               // registe
-               // vote
-               // cancelvote
+               m.Handle("/sign-with-xprv", jsonHandler(a.signWithPriKey))
                // listdelegates
+               m.Handle("/list-delegates", jsonHandler(a.listDelegates))
                // getdelegatevotes
-               // getdelegatefunds
+               m.Handle("/get-delegate-votes", jsonHandler(a.getDelegateVotes))
                // listvoteddelegates
+               m.Handle("/list-voted-delegates", jsonHandler(a.listVotedDelegates))
                // listreceivedvotes
-               // getirreversibleblock
+               m.Handle("/list-received-votes", jsonHandler(a.listReceivedVotes))
+
+               m.Handle("/get-address-balance", jsonHandler(a.getAddressBalance))
        } else {
                log.Warn("Please enable wallet")
        }
index c33e053..bc7627c 100644 (file)
@@ -102,7 +102,7 @@ func TestAPIHandler(t *testing.T) {
 }
 
 func TestEstimateTxGas(t *testing.T) {
-       tmplStr := `{"allow_additional_actions":false,"raw_transaction":"0701a8d30201010060015ef39ac9f5a6b0db3eb4b2a54a8d012ef5626c1da5462bc97c7a0a1c11bd8e39bdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0d6e0ce120001160014b29b9e1b31018d5161e33d0c465bbb6dd1df1556010002013dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffacfc9bc512011600142a38b1e022d42414b76a11b7b63075d08fe90b77000139ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14011600145427f2318811979c908eb2f06d439d134aa156fe00","signing_instructions":[{"position":0,"witness_components":[{"type":"raw_tx_signature","quorum":1,"keys":[{"xpub":"6c420aa025610d323a55c29a8692e2f909b176e88c3bfc8b78cb64ead1bd5db2c6d8492346d12acea177ed0fa4a4579c4bdf020c8cf10fa99cad72f3d5b7de04","derivation_path":["010100000000000000","0e00000000000000"]}],"signatures":null},{"type":"data","value":"512d84b99c93d51729215de3d796390f762f74692306863e3f3bcb0090b399f4"}]}]}`
+       tmplStr := `{"raw_transaction":"0701a8d30201010060015e7e8cf2b20c310f7a8197d598f04a04470eda4d59470661d124b688b507525a9dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80c8afa0250101160014b6fd589b689b2e7a8772c5c0a855734851c2f72a010001013dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8086d8f02401160014b6fd589b689b2e7a8772c5c0a855734851c2f72a00667b2254797065223a3231302c2244617461223a2265794a6d62334a6e5a584a7a496a7062496e5a7a625446784d32316d625752324e6a52714d6e70684d4755326548646c64475a77634745304e326833633368325a7a6b7a5a6e5635655730695858303d227d","signing_instructions":[{"position":0,"witness_components":[{"type":"raw_tx_signature","quorum":1,"keys":[{"xpub":"67e1a63e43dbd7148aa3ffe5a8e869ff5d89f687d1d29f6224a95bd0ce3b3eb61e85cf9855548915e36137345910606cbc8e7dd8497c831dce899ee6ac112445","derivation_path":null}],"signatures":null},{"type":"data","value":"67e1a63e43dbd7148aa3ffe5a8e869ff5d89f687d1d29f6224a95bd0ce3b3eb6"}]}],"fee":100000000,"allow_additional_actions":false}`
        template := txbuilder.Template{}
        err := json.Unmarshal([]byte(tmplStr), &template)
        if err != nil {
@@ -133,7 +133,7 @@ func TestEstimateTxGasRange(t *testing.T) {
        }{
                {
                        path:    "/estimate-transaction-gas",
-                       tmplStr: `{"allow_additional_actions":false,"raw_transaction":"0701a8d30201010060015ef39ac9f5a6b0db3eb4b2a54a8d012ef5626c1da5462bc97c7a0a1c11bd8e39bdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0d6e0ce120001160014b29b9e1b31018d5161e33d0c465bbb6dd1df1556010002013dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffacfc9bc512011600142a38b1e022d42414b76a11b7b63075d08fe90b77000139ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14011600145427f2318811979c908eb2f06d439d134aa156fe00","signing_instructions":[{"position":0,"witness_components":[{"type":"raw_tx_signature","quorum":1,"keys":[{"xpub":"6c420aa025610d323a55c29a8692e2f909b176e88c3bfc8b78cb64ead1bd5db2c6d8492346d12acea177ed0fa4a4579c4bdf020c8cf10fa99cad72f3d5b7de04","derivation_path":["010100000000000000","0e00000000000000"]}],"signatures":null},{"type":"data","value":"512d84b99c93d51729215de3d796390f762f74692306863e3f3bcb0090b399f4"}]}]}`,
+                       tmplStr: `{"raw_transaction":"0701a8d30201010060015e7e8cf2b20c310f7a8197d598f04a04470eda4d59470661d124b688b507525a9dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80c8afa0250101160014b6fd589b689b2e7a8772c5c0a855734851c2f72a010001013dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8086d8f02401160014b6fd589b689b2e7a8772c5c0a855734851c2f72a00667b2254797065223a3231302c2244617461223a2265794a6d62334a6e5a584a7a496a7062496e5a7a625446784d32316d625752324e6a52714d6e70684d4755326548646c64475a77634745304e326833633368325a7a6b7a5a6e5635655730695858303d227d","signing_instructions":[{"position":0,"witness_components":[{"type":"raw_tx_signature","quorum":1,"keys":[{"xpub":"67e1a63e43dbd7148aa3ffe5a8e869ff5d89f687d1d29f6224a95bd0ce3b3eb61e85cf9855548915e36137345910606cbc8e7dd8497c831dce899ee6ac112445","derivation_path":null}],"signatures":null},{"type":"data","value":"67e1a63e43dbd7148aa3ffe5a8e869ff5d89f687d1d29f6224a95bd0ce3b3eb6"}]}],"fee":100000000,"allow_additional_actions":false}`,
                        respWant: &EstimateTxGasResp{
                                TotalNeu: (flexibleGas + 2095) * consensus.VMGasRate,
                        },
diff --git a/api/dpos.go b/api/dpos.go
new file mode 100644 (file)
index 0000000..7ea75c0
--- /dev/null
@@ -0,0 +1,40 @@
+package api
+
+import (
+       "context"
+
+       dpos "github.com/vapor/consensus/consensus/dpos"
+)
+
+func (a *API) listDelegates(ctx context.Context) Response {
+       return NewSuccessResponse(dpos.GDpos.ListDelegates())
+}
+
+func (a *API) getDelegateVotes(ctx context.Context, ins struct {
+       DelegateAddress string `json:"delegate_address"`
+}) Response {
+       votes := map[string]uint64{"votes": dpos.GDpos.GetDelegateVotes(ins.DelegateAddress)}
+       return NewSuccessResponse(votes)
+}
+
+func (a *API) listVotedDelegates(ctx context.Context, ins struct {
+       Voter string `json:"voter"`
+}) Response {
+       delegates := make(map[string]string)
+       for _, delegate := range dpos.GDpos.GetVotedDelegates(ins.Voter) {
+               delegates[dpos.GDpos.GetDelegateName(delegate)] = delegate
+       }
+       return NewSuccessResponse(delegates)
+}
+
+func (a *API) listReceivedVotes(ctx context.Context, ins struct {
+       DelegateAddress string `json:"delegate_address"`
+}) Response {
+       return NewSuccessResponse(dpos.GDpos.GetDelegateVoters(ins.DelegateAddress))
+}
+
+func (a *API) getAddressBalance(ctx context.Context, ins struct {
+       Address string `json:"address"`
+}) Response {
+       return NewSuccessResponse(dpos.GDpos.GetAddressBalance(ins.Address))
+}
diff --git a/api/dpos_vote.go b/api/dpos_vote.go
deleted file mode 100644 (file)
index a7333ee..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-package api
-
-import (
-       "context"
-       "time"
-
-       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/protocol/bc"
-)
-
-func (a *API) registe(ctx context.Context, ins struct {
-       DelegateAddress string `json:"delegate_address"`
-       DelegateName    string `json:"delegate_name"`
-}) Response {
-
-       
-
-       return NewSuccessResponse("")
-}
-
-func (a *API) dpos(ctx context.Context, ins struct {
-       From   string `json:"from"`
-       To     string `json:"to"`
-       Fee    uint64 `json:"fee"`
-       Stake  uint64 `json:"stake"`
-       TxType uint32 `json:"tx_type"`
-}) Response {
-       // 找到utxo
-       var assetID bc.AssetID
-       assetID.UnmarshalText([]byte("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"))
-       // 生成dpos交易
-       dpos := account.DopsAction{
-               Accounts: a.wallet.AccountMgr,
-               From:     ins.From,
-               To:       ins.To,
-               Fee:      ins.Fee,
-               TxType:   ins.TxType,
-       }
-       dpos.Amount = ins.Stake
-       dpos.AssetId = &assetID
-       builder := txbuilder.NewBuilder(time.Now())
-       if err := dpos.Build(ctx, builder); err != nil {
-               return NewErrorResponse(err)
-       }
-
-       // 签名
-       tmpl, _, err := builder.Build()
-       if err != nil {
-               return NewErrorResponse(err)
-       }
-       var xprv chainkd.XPrv
-       xprv.UnmarshalText([]byte(config.CommonConfig.Consensus.Dpos.XPrv))
-       if err := pseudohsm.SignWithKey(tmpl, xprv); err != nil {
-               return NewErrorResponse(err)
-       }
-       log.Info("Sign Transaction complete.")
-       log.Info(txbuilder.SignProgress(tmpl))
-       //return NewSuccessResponse(&signTemplateResp{Tx: tmpl, SignComplete: txbuilder.SignProgress(tmpl)})
-       // 提交
-
-       if err := txbuilder.FinalizeTx(ctx, a.chain, tmpl.Transaction); err != nil {
-               return NewErrorResponse(err)
-       }
-
-       log.WithField("tx_id", tmpl.Transaction.ID.String()).Info("submit single tx")
-       return NewSuccessResponse(&submitTxResp{TxID: &tmpl.Transaction.ID})
-}
index 96b968e..100db72 100644 (file)
@@ -5,6 +5,7 @@ import (
 
        log "github.com/sirupsen/logrus"
 
+       "github.com/vapor/blockchain/pseudohsm"
        "github.com/vapor/blockchain/txbuilder"
        "github.com/vapor/common"
        "github.com/vapor/consensus"
@@ -83,6 +84,21 @@ func (a *API) signTemplate(ctx context.Context, x struct {
        return NewSuccessResponse(&signTemplateResp{Tx: &x.Txs, SignComplete: txbuilder.SignProgress(&x.Txs)})
 }
 
+func (a *API) signWithPriKey(ins struct {
+       Xprv string             `json:"xprv"`
+       Tx   txbuilder.Template `json:"transaction"`
+}) Response {
+       xprv := &chainkd.XPrv{}
+       if err := xprv.UnmarshalText([]byte(ins.Xprv)); err != nil {
+               return NewErrorResponse(err)
+       }
+       if err := pseudohsm.SignWithKey(&ins.Tx, *xprv); err != nil {
+               return NewErrorResponse(err)
+       }
+       log.Info("Sign Transaction complete.")
+       return NewSuccessResponse(&signTemplateResp{Tx: &ins.Tx, SignComplete: txbuilder.SignProgress(&ins.Tx)})
+}
+
 type signTemplatesResp struct {
        Tx           []*txbuilder.Template `json:"transaction"`
        SignComplete bool                  `json:"sign_complete"`
index a4acb34..2b11215 100644 (file)
@@ -34,7 +34,7 @@ func (a *API) actionDecoder(action string) (func([]byte) (txbuilder.Action, erro
                "retire":                       txbuilder.DecodeRetireAction,
                "spend_account":                a.wallet.AccountMgr.DecodeSpendAction,
                "spend_account_unspent_output": a.wallet.AccountMgr.DecodeSpendUTXOAction,
-               "dpos_address":                 a.wallet.AccountMgr.DecodeDposAction,
+               "dpos":                         a.wallet.AccountMgr.DecodeDposAction,
                "ipfs_data":                    txbuilder.DecodeIpfsDataAction,
        }
        decoder, ok := decoders[action]
@@ -49,7 +49,7 @@ func onlyHaveInputActions(req *BuildRequest) (bool, error) {
                if !ok {
                        return false, errors.WithDetailf(ErrBadActionType, "no action type provided on action %d", i)
                }
-               if strings.HasPrefix(actionType, "dpos_address") {
+               if strings.HasPrefix(actionType, "dpos") {
                        dpos = true
                }
                if strings.HasPrefix(actionType, "spend") || actionType == "issue" {
index f0127ee..fe85e21 100644 (file)
@@ -14,6 +14,8 @@ import (
        "github.com/vapor/common"
        "github.com/vapor/config"
        "github.com/vapor/consensus"
+       engine "github.com/vapor/consensus/consensus"
+       "github.com/vapor/consensus/consensus/dpos"
        "github.com/vapor/crypto/ed25519/chainkd"
        "github.com/vapor/database/leveldb"
        "github.com/vapor/protocol"
@@ -153,9 +155,14 @@ func TestListAssets(t *testing.T) {
 }
 
 func mockChain(testDB dbm.DB) (*protocol.Chain, error) {
+       var engine engine.Engine
+       switch config.CommonConfig.Consensus.Type {
+       case "dpos":
+               engine = dpos.GDpos
+       }
        store := leveldb.NewStore(testDB)
        txPool := protocol.NewTxPool(store)
-       chain, err := protocol.NewChain(store, txPool)
+       chain, err := protocol.NewChain(store, txPool, engine)
        if err != nil {
                return nil, err
        }
@@ -165,14 +172,14 @@ func mockChain(testDB dbm.DB) (*protocol.Chain, error) {
 func mockNewRegistry(t *testing.T) *Registry {
        config.CommonConfig = config.DefaultConfig()
        consensus.SoloNetParams.Signer = "78673764e0ba91a4c5ba9ec0c8c23c69e3d73bf27970e05e0a977e81e13bde475264d3b177a96646bc0ce517ae7fd63504c183ab6d330dea184331a4cf5912d5"
-       config.CommonConfig.Consensus.Dpos.SelfVoteSigners = append(config.CommonConfig.Consensus.Dpos.SelfVoteSigners, "vsm1qkm743xmgnvh84pmjchq2s4tnfpgu9ae2f9slep")
-       config.CommonConfig.Consensus.Dpos.XPrv = "a8e281b615809046698fb0b0f2804a36d824d48fa443350f10f1b80649d39e5f1e85cf9855548915e36137345910606cbc8e7dd8497c831dce899ee6ac112445"
-       for _, v := range config.CommonConfig.Consensus.Dpos.SelfVoteSigners {
+       config.CommonConfig.Consensus.SelfVoteSigners = append(config.CommonConfig.Consensus.SelfVoteSigners, "vsm1qkm743xmgnvh84pmjchq2s4tnfpgu9ae2f9slep")
+       config.CommonConfig.Consensus.XPrv = "a8e281b615809046698fb0b0f2804a36d824d48fa443350f10f1b80649d39e5f1e85cf9855548915e36137345910606cbc8e7dd8497c831dce899ee6ac112445"
+       for _, v := range config.CommonConfig.Consensus.SelfVoteSigners {
                address, err := common.DecodeAddress(v, &consensus.SoloNetParams)
                if err != nil {
                        t.Fatal(err)
                }
-               config.CommonConfig.Consensus.Dpos.Signers = append(config.CommonConfig.Consensus.Dpos.Signers, address)
+               config.CommonConfig.Consensus.Signers = append(config.CommonConfig.Consensus.Signers, address)
        }
        dirPath, err := ioutil.TempDir(".", "")
        if err != nil {
index b93b6db..a9f5e06 100644 (file)
@@ -24,6 +24,7 @@ type TemplateBuilder struct {
        timeRange           uint64
        rollbacks           []func()
        callbacks           []func() error
+       referenceData       []byte
 }
 
 // AddInput add inputs of transactions
@@ -45,6 +46,10 @@ func (b *TemplateBuilder) AddOutput(o *types.TxOutput) error {
        return nil
 }
 
+func (b *TemplateBuilder) SetReferenceData(referenceData []byte) {
+       b.referenceData = referenceData
+}
+
 // InputCount return number of input in the template builder
 func (b *TemplateBuilder) InputCount() int {
        return len(b.inputs)
@@ -131,6 +136,8 @@ func (b *TemplateBuilder) Build() (*Template, *types.TxData, error) {
                tx.Inputs = append(tx.Inputs, in)
        }
 
+       tx.ReferenceData = b.referenceData
+
        tpl.Transaction = types.NewTx(*tx)
        tpl.Fee = CalculateTxFee(tpl.Transaction)
        return tpl, tx, nil
index ee17437..7ed772f 100644 (file)
@@ -1,16 +1,14 @@
 {
     "consensus":{
-        "dpos": {
+        "consensus_type": "dpos" ,
         "period": 3,
-        "epoch": 300,
-        "maxSignersCount": 1,
-        "minVoterBalance": 0,
-        "genesisTimestamp": 1524549600,
+        "max_signers_count": 2,
+        "min_boter_balance": 10,
+        "genesis_timestamp": 1524549600,
         "coinbase": "vsm1qkm743xmgnvh84pmjchq2s4tnfpgu9ae2f9slep",
         "xprv": "a8e281b615809046698fb0b0f2804a36d824d48fa443350f10f1b80649d39e5f1e85cf9855548915e36137345910606cbc8e7dd8497c831dce899ee6ac112445",
         "signers": [
             "vsm1qkm743xmgnvh84pmjchq2s4tnfpgu9ae2f9slep"
         ]
-        }
     }
 }
\ No newline at end of file
index 56122e2..4ec6cb7 100644 (file)
@@ -6,4 +6,4 @@ api_addr = "0.0.0.0:8888"
 chain_id = "solonet"
 [p2p]
 laddr = "tcp://0.0.0.0:56658"
-seeds = ""
+seeds = "127.0.0.1:56659"
index 7e38217..be5dce6 100644 (file)
@@ -178,12 +178,19 @@ type WebsocketConfig struct {
 }
 
 type ConsensusConfig struct {
-       Dpos *DposConfig `mapstructure:"dpos"`
+       Type             string   `mapstructure:"consensus_type"`
+       Period           uint64   `json:"period"`            // Number of seconds between blocks to enforce
+       MaxSignerCount   uint64   `json:"max_signers_count"` // Max count of signers
+       MinVoterBalance  uint64   `json:"min_boter_balance"` // Min voter balance to valid this vote
+       GenesisTimestamp uint64   `json:"genesis_timestamp"` // The LoopStartTime of first Block
+       Coinbase         string   `json:"coinbase"`
+       XPrv             string   `json:"xprv"`
+       SelfVoteSigners  []string `json:"signers"` // Signers vote by themselves to seal the block, make sure the signer accounts are pre-funded
+       Signers          []common.Address
 }
 
 type DposConfig struct {
        Period           uint64   `json:"period"`            // Number of seconds between blocks to enforce
-       Epoch            uint64   `json:"epoch"`             // Epoch length to reset votes and checkpoint
        MaxSignerCount   uint64   `json:"max_signers_count"` // Max count of signers
        MinVoterBalance  uint64   `json:"min_boter_balance"` // Min voter balance to valid this vote
        GenesisTimestamp uint64   `json:"genesis_timestamp"` // The LoopStartTime of first Block
@@ -241,7 +248,6 @@ func DefaultWebsocketConfig() *WebsocketConfig {
 func DefaultDposConfig() *DposConfig {
        return &DposConfig{
                Period:           1,
-               Epoch:            300,
                MaxSignerCount:   1,
                MinVoterBalance:  0,
                GenesisTimestamp: 1524549600,
@@ -249,7 +255,12 @@ func DefaultDposConfig() *DposConfig {
 }
 
 func DefaultConsensusCOnfig() *ConsensusConfig {
-       return &ConsensusConfig{Dpos: DefaultDposConfig()}
+       return &ConsensusConfig{
+               Type:             "dpos",
+               Period:           1,
+               MaxSignerCount:   1,
+               MinVoterBalance:  0,
+               GenesisTimestamp: 1524549600}
 }
 
 //-----------------------------------------------------------------------------
index 1443862..3a10ded 100644 (file)
@@ -9,7 +9,6 @@ import (
 
        "github.com/vapor/consensus"
        "github.com/vapor/crypto/ed25519"
-       "github.com/vapor/crypto/ed25519/chainkd"
        "github.com/vapor/protocol/bc"
        "github.com/vapor/protocol/bc/types"
        "github.com/vapor/protocol/vm/vmutil"
@@ -23,7 +22,7 @@ func commitToArguments() (res *[32]byte) {
        fedpegScript, _ := vmutil.P2SPMultiSigProgram(fedpegPubkeys, len(fedpegPubkeys))
 
        var buffer bytes.Buffer
-       for _, address := range CommonConfig.Consensus.Dpos.Signers {
+       for _, address := range CommonConfig.Consensus.Signers {
                redeemContract := address.ScriptAddress()
                buffer.Write(redeemContract)
        }
@@ -76,13 +75,6 @@ func mainNetGenesisBlock() *types.Block {
                log.Panicf("fail on calc genesis tx merkel root")
        }
 
-       var xPrv chainkd.XPrv
-       if CommonConfig.Consensus.Dpos.XPrv == "" {
-               log.Panicf("Signer is empty")
-       }
-       xPrv.UnmarshalText([]byte(CommonConfig.Consensus.Dpos.XPrv))
-       b, _ := xPrv.XPub().MarshalText()
-
        block := &types.Block{
                BlockHeader: types.BlockHeader{
                        Version:   1,
@@ -92,7 +84,6 @@ func mainNetGenesisBlock() *types.Block {
                                TransactionsMerkleRoot: merkleRoot,
                                TransactionStatusHash:  txStatusHash,
                        },
-                       Coinbase: b,
                },
                Transactions: []*types.Tx{tx},
        }
@@ -114,14 +105,6 @@ func testNetGenesisBlock() *types.Block {
        if err != nil {
                log.Panicf("fail on calc genesis tx merkel root")
        }
-
-       var xPrv chainkd.XPrv
-       if CommonConfig.Consensus.Dpos.XPrv == "" {
-               log.Panicf("Signer is empty")
-       }
-       xPrv.UnmarshalText([]byte(CommonConfig.Consensus.Dpos.XPrv))
-       b, _ := xPrv.XPub().MarshalText()
-
        block := &types.Block{
                BlockHeader: types.BlockHeader{
                        Version:   1,
@@ -131,7 +114,6 @@ func testNetGenesisBlock() *types.Block {
                                TransactionsMerkleRoot: merkleRoot,
                                TransactionStatusHash:  txStatusHash,
                        },
-                       Coinbase: b,
                },
                Transactions: []*types.Tx{tx},
        }
@@ -154,23 +136,15 @@ func soloNetGenesisBlock() *types.Block {
                log.Panicf("fail on calc genesis tx merkel root")
        }
 
-       var xPrv chainkd.XPrv
-       if CommonConfig.Consensus.Dpos.XPrv == "" {
-               log.Panicf("Signer is empty")
-       }
-       xPrv.UnmarshalText([]byte(CommonConfig.Consensus.Dpos.XPrv))
-       b, _ := xPrv.XPub().MarshalText()
-
        block := &types.Block{
                BlockHeader: types.BlockHeader{
                        Version:   1,
                        Height:    0,
-                       Timestamp: 1528945000,
+                       Timestamp: CommonConfig.Consensus.GenesisTimestamp,
                        BlockCommitment: types.BlockCommitment{
                                TransactionsMerkleRoot: merkleRoot,
                                TransactionStatusHash:  txStatusHash,
                        },
-                       Coinbase: b,
                },
                Transactions: []*types.Tx{tx},
        }
index 61c2dfc..9c50658 100644 (file)
@@ -2,28 +2,32 @@ package consensus
 
 import (
        "github.com/vapor/chain"
+       "github.com/vapor/common"
        "github.com/vapor/protocol/bc"
        "github.com/vapor/protocol/bc/types"
 )
 
-// Engine is an algorithm agnostic consensus engine.
-type Engine interface {
-
-       // VerifySeal checks whether the crypto seal on a header is valid according to
-       // the consensus rules of the given engine.
-       VerifySeal(c chain.Chain, header *types.BlockHeader) error
-
-       // Prepare initializes the consensus fields of a block header according to the
-       // rules of a particular engine. The changes are executed inline.
-       Prepare(c chain.Chain, header *types.BlockHeader) error
+type AddressBalance struct {
+       Address string
+       Balance int64
+}
 
-       // Finalize runs any post-transaction state modifications (e.g. block rewards)
-       // and assembles the final block.
-       // Note: The block header and state database might be updated to reflect any
-       // consensus rules that happen at finalization (e.g. block rewards).
-       Finalize(c chain.Chain, header *types.BlockHeader, txs []*bc.Tx) error
+type DelegateInterface interface {
+       ConsensusName() string
+}
 
-       // Seal generates a new block for the given input block with the local miner's
-       // seal place on top.
-       Seal(c chain.Chain, block *types.Block) (*types.Block, error)
+// Engine is an algorithm agnostic consensus engine.
+type Engine interface {
+       Init(c chain.Chain, delegateNumber, intervalTime, blockHeight uint64, blockHash bc.Hash) error
+       Finish() error
+       IsMining(address common.Address, t uint64) (interface{}, error)
+       ProcessRegister(delegateAddress string, delegateName string, hash bc.Hash, height uint64) bool
+       ProcessVote(voterAddress string, delegates []string, hash bc.Hash, height uint64) bool
+       ProcessCancelVote(voterAddress string, delegates []string, hash bc.Hash, height uint64) bool
+       UpdateAddressBalance(addressBalance []AddressBalance)
+       CheckBlockHeader(header types.BlockHeader) error
+       CheckBlock(block types.Block, fIsCheckDelegateInfo bool) error
+       IsValidBlockCheckIrreversibleBlock(height uint64, hash bc.Hash) error
+       GetOldBlockHeight() uint64
+       GetOldBlockHash() bc.Hash
 }
diff --git a/consensus/consensus/dpos.go b/consensus/consensus/dpos.go
deleted file mode 100644 (file)
index 0036e8d..0000000
+++ /dev/null
@@ -1,312 +0,0 @@
-package consensus
-
-import (
-       "encoding/json"
-       "errors"
-       "fmt"
-       "math/rand"
-       "path/filepath"
-       "sync"
-       "time"
-
-       "github.com/vapor/crypto/ed25519/chainkd"
-
-       "github.com/vapor/consensus"
-
-       "github.com/vapor/chain"
-       "github.com/vapor/common"
-       "github.com/vapor/config"
-       "github.com/vapor/protocol/bc"
-       "github.com/vapor/protocol/bc/types"
-)
-
-type Delegate struct {
-       DelegateAddress string `json:"delegate_address"`
-       Votes           uint64 `json:"votes"`
-}
-
-type DelegateInfo struct {
-       Delegates []Delegate `json:"delegates"`
-}
-
-//OP_FAIL PUBKEY SIG(block.time) DELEGATE_IDS
-func DelegateInfoToScript(delegateInfo DelegateInfo, xpub chainkd.XPub, h bc.Hash) {
-
-}
-
-//ScriptToDelegateInfo
-
-const maxConfirmBlockCount = 2
-
-type IrreversibleBlockInfo struct {
-       heights    []int64
-       hashs      []bc.Hash
-       HeightHash map[int64]bc.Hash
-}
-
-func newIrreversibleBlockInfo() *IrreversibleBlockInfo {
-       o := &IrreversibleBlockInfo{}
-       for i := 0; i < maxConfirmBlockCount; i++ {
-               o.heights = append(o.heights, -1)
-       }
-       return o
-}
-
-type DposType struct {
-       c                         chain.Chain
-       MaxDelegateNumber         uint64
-       BlockIntervalTime         uint64
-       DposStartHeight           uint64
-       DposStartTime             uint64
-       cSuperForgerAddress       common.Address
-       irreversibleBlockFileName string
-       cIrreversibleBlockInfo    IrreversibleBlockInfo
-       lockIrreversibleBlockInfo sync.Mutex
-}
-
-var GDpos = &DposType{}
-
-func init() {
-       GDpos.irreversibleBlockFileName = filepath.Join(config.DefaultDataDir(), "dpos", "irreversible_block.dat")
-       GDpos.ReadIrreversibleBlockInfo(&GDpos.cIrreversibleBlockInfo)
-
-}
-
-func (d *DposType) ReadIrreversibleBlockInfo(info *IrreversibleBlockInfo) error {
-       return nil
-}
-
-func (d *DposType) IsMining(cDelegateInfo *DelegateInfo, address common.Address, t uint64) error {
-
-       header := d.c.BestBlockHeader()
-       currentLoopIndex := d.GetLoopIndex(t)
-       currentDelegateIndex := d.GetDelegateIndex(t)
-       prevLoopIndex := d.GetLoopIndex(header.Timestamp)
-       prevDelegateIndex := d.GetDelegateIndex(header.Timestamp)
-
-       if currentLoopIndex > prevLoopIndex {
-               *cDelegateInfo = d.GetNextDelegates(t)
-               if cDelegateInfo.Delegates[currentLoopIndex].DelegateAddress == address.EncodeAddress() {
-                       return nil
-               }
-               return errors.New("Is not the current mining node")
-       } else if currentLoopIndex == prevLoopIndex && currentDelegateIndex > prevDelegateIndex {
-               //currentDelegateInfo := DelegateInfo{}
-               currentDelegateInfo, err := d.GetBlockDelegates(header)
-               if err != nil {
-                       return err
-               }
-               if currentDelegateIndex+1 > uint64(len(currentDelegateInfo.Delegates)) {
-                       return errors.New("Out of the block node list")
-               } else if currentDelegateInfo.Delegates[currentDelegateIndex].DelegateAddress == address.EncodeAddress() {
-                       return nil
-               } else {
-                       return errors.New("Is not the current mining node")
-               }
-       } else {
-               return errors.New("Time anomaly")
-       }
-}
-
-func (d *DposType) GetLoopIndex(time uint64) uint64 {
-       if time < d.DposStartTime {
-               return 0
-       }
-
-       return (time - d.DposStartTime) / (d.MaxDelegateNumber * d.BlockIntervalTime)
-}
-
-func (d *DposType) GetDelegateIndex(time uint64) uint64 {
-       if time < d.DposStartTime {
-               return 0
-       }
-
-       return (time - d.DposStartTime) % (d.MaxDelegateNumber * d.BlockIntervalTime) / d.BlockIntervalTime
-}
-
-func (d *DposType) GetNextDelegates(t uint64) DelegateInfo {
-       delegates := DposVote.GetTopDelegateInfo(consensus.MinHoldBalance, d.MaxDelegateNumber-1)
-       delegate := Delegate{
-               DelegateAddress: d.cSuperForgerAddress.EncodeAddress(),
-               Votes:           7,
-       }
-       delegates = append(delegates, delegate)
-       delegateInfo := DelegateInfo{}
-       delegateInfo.Delegates = SortDelegate(delegates, t)
-       return delegateInfo
-}
-
-func (d *DposType) GetBlockDelegates(header *types.BlockHeader) (*DelegateInfo, error) {
-       loopIndex := d.GetLoopIndex(header.Timestamp)
-       for {
-               preHeader, err := d.c.GetHeaderByHash(&header.PreviousBlockHash)
-               if err != nil {
-                       return nil, err
-               }
-               if header.Height == d.DposStartHeight || d.GetLoopIndex(preHeader.Timestamp) < loopIndex {
-                       block, err := d.c.GetBlockByHeight(header.Height)
-                       if err != nil {
-                               return nil, err
-                       }
-                       delegateInfo, err := d.GetBlockDelegate(block)
-                       if err != nil {
-                               return nil, err
-                       }
-                       return delegateInfo, nil
-               }
-               header = preHeader
-       }
-}
-
-func (d *DposType) GetBlockDelegate(block *types.Block) (*DelegateInfo, error) {
-       tx := block.Transactions[0]
-       var delegate TypedData
-       if len(tx.TxData.Inputs) == 1 && tx.TxData.Inputs[0].InputType() == types.CoinbaseInputType {
-               if err := json.Unmarshal(tx.TxData.ReferenceData, delegate); err != nil {
-                       return nil, err
-               }
-               if delegateInfo, ok := delegate.(*DelegateInfoList); ok {
-                       return &delegateInfo.Delegate, nil
-               }
-       }
-       return nil, errors.New("The first transaction is not a coinbase transaction")
-}
-
-func (d *DposType) CheckCoinbase(tx types.TxData, t uint64, Height uint64) error {
-
-       return nil
-}
-
-func (d *DposType) CheckBlockHeader(header types.BlockHeader) error {
-       blockT := time.Unix(int64(header.Timestamp), 0)
-
-       if blockT.Sub(time.Now()).Seconds() > 3 {
-               return errors.New("block time is error")
-       }
-
-       return nil
-}
-
-func (d *DposType) CheckBlock(block types.Block, fIsCheckDelegateInfo bool) error {
-       blockT := time.Unix(int64(block.Timestamp), 0)
-
-       if blockT.Sub(time.Now()).Seconds() > 3 {
-               return errors.New("block time is error")
-       }
-
-       if err := d.CheckCoinbase(block.Transactions[0].TxData, block.Timestamp, block.Height); err != nil {
-               return err
-       }
-
-       preBlock, err := d.c.GetBlockByHash(&block.PreviousBlockHash)
-       if err != nil {
-               return err
-       }
-
-       currentLoopIndex := d.GetLoopIndex(block.Timestamp)
-       currentDelegateIndex := d.GetDelegateIndex(block.Timestamp)
-       prevLoopIndex := d.GetLoopIndex(preBlock.Timestamp)
-       prevDelegateIndex := d.GetDelegateIndex(preBlock.Timestamp)
-
-       delegateInfo := &DelegateInfo{}
-
-       if currentLoopIndex < prevLoopIndex {
-               return errors.New("Block time exception")
-       } else if currentLoopIndex > prevLoopIndex {
-               if fIsCheckDelegateInfo {
-                       if err := d.CheckBlockDelegate(block); err != nil {
-                               return err
-                       }
-                       d.ProcessIrreversibleBlock(block.Height, block.Hash())
-               }
-               delegateInfo, err = d.GetBlockDelegate(&block)
-               if err != nil {
-                       return err
-               }
-       } else {
-               if currentDelegateIndex < prevDelegateIndex {
-                       return errors.New("Block time exception")
-               }
-
-               delegateInfo, err = d.GetBlockDelegates(&preBlock.BlockHeader)
-               if err != nil {
-                       return err
-               }
-       }
-
-       delegateAddress := d.getBlockForgerAddress(block)
-       if currentDelegateIndex < uint64(len(delegateInfo.Delegates)) &&
-               delegateInfo.Delegates[currentDelegateIndex].DelegateAddress == delegateAddress.EncodeAddress() {
-               return nil
-       }
-       h := block.Hash()
-       return fmt.Errorf("CheckBlock GetDelegateID blockhash:%s error", h.String())
-}
-
-func (d *DposType) CheckBlockDelegate(block types.Block) error {
-       return nil
-}
-
-func (d *DposType) ProcessIrreversibleBlock(height uint64, hash bc.Hash) {
-
-}
-
-func (d *DposType) getBlockForgerAddress(block types.Block) common.Address {
-       tx := block.Transactions[0].TxData
-
-       if len(tx.Inputs) == 1 && tx.Inputs[0].InputType() == types.CoinbaseInputType {
-               address, err := common.NewAddressWitnessPubKeyHash(tx.Outputs[0].ControlProgram[2:], &consensus.ActiveNetParams)
-               if err != nil {
-                       address, err := common.NewAddressWitnessScriptHash(tx.Outputs[0].ControlProgram[2:], &consensus.ActiveNetParams)
-                       if err != nil {
-                               return nil
-                       }
-                       return address
-               }
-               return address
-       }
-
-       return nil
-}
-
-func (d *DposType) IsValidBlockCheckIrreversibleBlock(height uint64, hash bc.Hash) error {
-       d.lockIrreversibleBlockInfo.Lock()
-       defer d.lockIrreversibleBlockInfo.Unlock()
-
-       if h, ok := d.cIrreversibleBlockInfo.HeightHash[int64(height)]; ok {
-               if h != hash {
-                       return fmt.Errorf("invalid block[%d:%s]", height, hash.String())
-               }
-       }
-
-       return nil
-}
-
-func SortDelegate(delegates []Delegate, t uint64) []Delegate {
-       var result []Delegate
-       r := getRand(uint64(len(delegates)), int64(t))
-       for _, i := range r {
-               result = append(result, delegates[i])
-       }
-       return result
-}
-
-func getRand(num uint64, seed int64) []uint64 {
-       rand.Seed(seed)
-       var r []uint64
-       s := make(map[uint64]bool)
-       for {
-               v := rand.Uint64()
-               v %= num
-               if _, ok := s[v]; ok {
-                       continue
-               }
-               s[v] = true
-               r = append(r, v)
-               if uint64(len(r)) >= num {
-                       break
-               }
-       }
-
-       return r
-}
diff --git a/consensus/consensus/dpos/custom_tx.go b/consensus/consensus/dpos/custom_tx.go
deleted file mode 100644 (file)
index 586abea..0000000
+++ /dev/null
@@ -1,322 +0,0 @@
-package dpos
-
-import (
-       "encoding/json"
-       "strconv"
-       "strings"
-
-       log "github.com/sirupsen/logrus"
-       "github.com/vapor/chain"
-       "github.com/vapor/protocol/bc"
-       "github.com/vapor/protocol/bc/types"
-)
-
-const (
-       /*
-        *  vapor:version:category:action/data
-        */
-       vaporPrefix        = "vapor"
-       vaporVersion       = "1"
-       vaporCategoryEvent = "event"
-       vaporCategoryLog   = "oplog"
-       vaporCategorySC    = "sc"
-       vaporEventVote     = "vote"
-       vaporEventConfirm  = "confirm"
-       vaporEventPorposal = "proposal"
-       vaporEventDeclare  = "declare"
-
-       vaporMinSplitLen      = 3
-       posPrefix             = 0
-       posVersion            = 1
-       posCategory           = 2
-       posEventVote          = 3
-       posEventConfirm       = 3
-       posEventProposal      = 3
-       posEventDeclare       = 3
-       posEventConfirmNumber = 4
-
-       /*
-        *  proposal type
-        */
-       proposalTypeCandidateAdd                  = 1
-       proposalTypeCandidateRemove               = 2
-       proposalTypeMinerRewardDistributionModify = 3 // count in one thousand
-
-       /*
-        * proposal related
-        */
-       maxValidationLoopCnt     = 123500 // About one month if seal each block per second & 21 super nodes
-       minValidationLoopCnt     = 12350  // About three days if seal each block per second & 21 super nodes
-       defaultValidationLoopCnt = 30875  // About one week if seal each block per second & 21 super nodes
-)
-
-// Vote :
-// vote come from custom tx which data like "vapor:1:event:vote"
-// Sender of tx is Voter, the tx.to is Candidate
-// Stake is the balance of Voter when create this vote
-type Vote struct {
-       Voter     string `json:"Voter"`
-       Candidate string `json:"Candidate"`
-       Stake     uint64 `json:"Stake"`
-}
-
-// Confirmation :
-// confirmation come  from custom tx which data like "vapor:1:event:confirm:123"
-// 123 is the block number be confirmed
-// Sender of tx is Signer only if the signer in the SignerQueue for block number 123
-type Confirmation struct {
-       Signer      string `json:"signer"`
-       BlockNumber uint64 `json:"block_number"`
-}
-
-// Proposal :
-// proposal come from  custom tx which data like "vapor:1:event:proposal:candidate:add:address" or "vapor:1:event:proposal:percentage:60"
-// proposal only come from the current candidates
-// not only candidate add/remove , current signer can proposal for params modify like percentage of reward distribution ...
-type Proposal struct {
-       Hash                   bc.Hash    `json:"hash"`              // tx hash
-       ValidationLoopCnt      uint64     `json:"ValidationLoopCnt"` // validation block number length of this proposal from the received block number
-       ImplementNumber        uint64     `json:"ImplementNumber"`   // block number to implement modification in this proposal
-       ProposalType           uint64     `json:"ProposalType"`      // type of proposal 1 - add candidate 2 - remove candidate ...
-       Proposer               string     `json:"Proposer"`          //
-       Candidate              string     `json:"Candidate"`
-       MinerRewardPerThousand uint64     `json:"MinerRewardPerThousand"`
-       Declares               []*Declare `json:"Declares"`       // Declare this proposal received
-       ReceivedNumber         uint64     `json:"ReceivedNumber"` // block number of proposal received
-}
-
-func (p *Proposal) copy() *Proposal {
-       cpy := &Proposal{
-               Hash:                   p.Hash,
-               ValidationLoopCnt:      p.ValidationLoopCnt,
-               ImplementNumber:        p.ImplementNumber,
-               ProposalType:           p.ProposalType,
-               Proposer:               p.Proposer,
-               Candidate:              p.Candidate,
-               MinerRewardPerThousand: p.MinerRewardPerThousand,
-               Declares:               make([]*Declare, len(p.Declares)),
-               ReceivedNumber:         p.ReceivedNumber,
-       }
-
-       copy(cpy.Declares, p.Declares)
-       return cpy
-}
-
-// Declare :
-// declare come from custom tx which data like "vapor:1:event:declare:hash:yes"
-// proposal only come from the current candidates
-// hash is the hash of proposal tx
-type Declare struct {
-       ProposalHash bc.Hash `json:"ProposalHash"`
-       Declarer     string  `json:"Declarer"`
-       Decision     bool    `json:"Decision"`
-}
-
-// HeaderExtra is the struct of info in header.Extra[extraVanity:len(header.extra)-extraSeal]
-type HeaderExtra struct {
-       CurrentBlockConfirmations []Confirmation `json:"current_block_confirmations"`
-       CurrentBlockVotes         []Vote         `json:"CurrentBlockVotes"`
-       CurrentBlockProposals     []Proposal     `json:"CurrentBlockProposals"`
-       CurrentBlockDeclares      []Declare      `json:"CurrentBlockDeclares"`
-       ModifyPredecessorVotes    []Vote         `json:"ModifyPredecessorVotes"`
-       LoopStartTime             uint64         `json:"LoopStartTime"`
-       SignerQueue               []string       `json:"SignerQueue"`
-       SignerMissing             []string       `json:"SignerMissing"`
-       ConfirmedBlockNumber      uint64         `json:"ConfirmedBlockNumber"`
-}
-
-// Calculate Votes from transaction in this block, write into header.Extra
-func (d *Dpos) processCustomTx(headerExtra HeaderExtra, c chain.Chain, header *types.BlockHeader, txs []*bc.Tx) (HeaderExtra, error) {
-
-       var (
-               snap   *Snapshot
-               err    error
-               height uint64
-       )
-       height = header.Height
-       if height > 1 {
-               snap, err = d.snapshot(c, height-1, header.PreviousBlockHash, nil, nil, defaultLoopCntRecalculateSigners)
-               if err != nil {
-                       return headerExtra, err
-               }
-       }
-
-       for _, tx := range txs {
-               var (
-                       from string
-                       to   string
-               )
-               dpos := new(bc.Dpos)
-               stake := uint64(0)
-               for _, value := range tx.Entries {
-                       switch d := value.(type) {
-                       case *bc.Dpos:
-                               from = d.From
-                               to = d.To
-                               dpos = d
-                               stake = d.Stake
-                       default:
-                               continue
-                       }
-
-                       if len(dpos.Data) >= len(vaporPrefix) {
-                               txData := dpos.Data
-                               txDataInfo := strings.Split(txData, ":")
-                               if len(txDataInfo) >= vaporMinSplitLen && txDataInfo[posPrefix] == vaporPrefix && txDataInfo[posVersion] == vaporVersion {
-                                       switch txDataInfo[posCategory] {
-                                       case vaporCategoryEvent:
-                                               if len(txDataInfo) > vaporMinSplitLen {
-                                                       if txDataInfo[posEventVote] == vaporEventVote && (!candidateNeedPD || snap.isCandidate(to)) {
-                                                               headerExtra.CurrentBlockVotes = d.processEventVote(headerExtra.CurrentBlockVotes, stake, from, to)
-                                                       } else if txDataInfo[posEventConfirm] == vaporEventConfirm {
-                                                               headerExtra.CurrentBlockConfirmations = d.processEventConfirm(headerExtra.CurrentBlockConfirmations, c, txDataInfo, height, tx, from)
-                                                       } else if txDataInfo[posEventProposal] == vaporEventPorposal && snap.isCandidate(from) {
-                                                               headerExtra.CurrentBlockProposals = d.processEventProposal(headerExtra.CurrentBlockProposals, txDataInfo, tx, from)
-                                                       } else if txDataInfo[posEventDeclare] == vaporEventDeclare && snap.isCandidate(from) {
-                                                               headerExtra.CurrentBlockDeclares = d.processEventDeclare(headerExtra.CurrentBlockDeclares, txDataInfo, tx, from)
-
-                                                       }
-                                               } else {
-                                                       // todo : something wrong, leave this transaction to process as normal transaction
-                                               }
-
-                                       case vaporCategoryLog:
-                                               // todo :
-                                       case vaporCategorySC:
-                                               // todo :
-                                       }
-                               }
-                       }
-               }
-       }
-
-       return headerExtra, nil
-}
-
-func (d *Dpos) processEventProposal(currentBlockProposals []Proposal, txDataInfo []string, tx *bc.Tx, proposer string) []Proposal {
-       proposal := Proposal{
-               Hash:                   tx.ID,
-               ValidationLoopCnt:      defaultValidationLoopCnt,
-               ImplementNumber:        uint64(1),
-               ProposalType:           proposalTypeCandidateAdd,
-               Proposer:               proposer,
-               MinerRewardPerThousand: minerRewardPerThousand,
-               Declares:               []*Declare{},
-               ReceivedNumber:         uint64(0),
-       }
-
-       for i := 0; i < len(txDataInfo[posEventProposal+1:])/2; i++ {
-               k, v := txDataInfo[posEventProposal+1+i*2], txDataInfo[posEventProposal+2+i*2]
-               switch k {
-               case "vlcnt":
-                       // If vlcnt is missing then user default value, but if the vlcnt is beyond the min/max value then ignore this proposal
-                       if validationLoopCnt, err := strconv.Atoi(v); err != nil || validationLoopCnt < minValidationLoopCnt || validationLoopCnt > maxValidationLoopCnt {
-                               return currentBlockProposals
-                       } else {
-                               proposal.ValidationLoopCnt = uint64(validationLoopCnt)
-                       }
-               case "implement_number":
-                       if implementNumber, err := strconv.Atoi(v); err != nil || implementNumber <= 0 {
-                               return currentBlockProposals
-                       } else {
-                               proposal.ImplementNumber = uint64(implementNumber)
-                       }
-               case "proposal_type":
-                       if proposalType, err := strconv.Atoi(v); err != nil || (proposalType != proposalTypeCandidateAdd && proposalType != proposalTypeCandidateRemove && proposalType != proposalTypeMinerRewardDistributionModify) {
-                               return currentBlockProposals
-                       } else {
-                               proposal.ProposalType = uint64(proposalType)
-                       }
-               case "candidate":
-                       // not check here
-                       //proposal.Candidate.UnmarshalText([]byte(v))
-                       /*
-                               address, err := common.DecodeAddress(v, &consensus.ActiveNetParams)
-                               if err != nil {
-                                       return currentBlockProposals
-                               }
-                       */
-                       proposal.Candidate = v
-               case "mrpt":
-                       // miner reward per thousand
-                       if mrpt, err := strconv.Atoi(v); err != nil || mrpt < 0 || mrpt > 1000 {
-                               return currentBlockProposals
-                       } else {
-                               proposal.MinerRewardPerThousand = uint64(mrpt)
-                       }
-
-               }
-       }
-
-       return append(currentBlockProposals, proposal)
-}
-
-func (d *Dpos) processEventDeclare(currentBlockDeclares []Declare, txDataInfo []string, tx *bc.Tx, declarer string) []Declare {
-       declare := Declare{
-               ProposalHash: bc.Hash{},
-               Declarer:     declarer,
-               Decision:     true,
-       }
-
-       for i := 0; i < len(txDataInfo[posEventDeclare+1:])/2; i++ {
-               k, v := txDataInfo[posEventDeclare+1+i*2], txDataInfo[posEventDeclare+2+i*2]
-               switch k {
-               case "hash":
-                       declare.ProposalHash.UnmarshalText([]byte(v))
-               case "decision":
-                       if v == "yes" {
-                               declare.Decision = true
-                       } else if v == "no" {
-                               declare.Decision = false
-                       } else {
-                               return currentBlockDeclares
-                       }
-               }
-       }
-
-       return append(currentBlockDeclares, declare)
-}
-
-func (d *Dpos) processEventVote(currentBlockVotes []Vote, stake uint64, voter, to string) []Vote {
-       if stake >= d.config.MinVoterBalance {
-               currentBlockVotes = append(currentBlockVotes, Vote{
-                       Voter:     voter,
-                       Candidate: to,
-                       Stake:     stake,
-               })
-       }
-       return currentBlockVotes
-}
-
-func (d *Dpos) processEventConfirm(currentBlockConfirmations []Confirmation, c chain.Chain, txDataInfo []string, number uint64, tx *bc.Tx, confirmer string) []Confirmation {
-       if len(txDataInfo) > posEventConfirmNumber {
-               confirmedBlockNumber, err := strconv.Atoi(txDataInfo[posEventConfirmNumber])
-               if err != nil || number-uint64(confirmedBlockNumber) > d.config.MaxSignerCount || number-uint64(confirmedBlockNumber) < 0 {
-                       return currentBlockConfirmations
-               }
-               confirmedHeader, err := c.GetBlockByHeight(uint64(confirmedBlockNumber))
-               if confirmedHeader == nil {
-                       log.Info("Fail to get confirmedHeader")
-                       return currentBlockConfirmations
-               }
-               confirmedHeaderExtra := HeaderExtra{}
-               if extraVanity+extraSeal > len(confirmedHeader.Extra) {
-                       return currentBlockConfirmations
-               }
-               if err := json.Unmarshal(confirmedHeader.Extra[extraVanity:len(confirmedHeader.Extra)-extraSeal], &confirmedHeaderExtra); err != nil {
-                       log.Info("Fail to decode parent header", "err", err)
-                       return currentBlockConfirmations
-               }
-               for _, s := range confirmedHeaderExtra.SignerQueue {
-                       if s == confirmer {
-                               currentBlockConfirmations = append(currentBlockConfirmations, Confirmation{
-                                       Signer:      confirmer,
-                                       BlockNumber: uint64(confirmedBlockNumber),
-                               })
-                               break
-                       }
-               }
-       }
-
-       return currentBlockConfirmations
-}
index 5eaf632..de0ed2e 100644 (file)
 package dpos
 
 import (
-       "bytes"
+       "bufio"
+       "encoding/binary"
        "encoding/json"
        "errors"
-       "math/big"
+       "fmt"
+       "io"
+       "math/rand"
+       "os"
+       "path/filepath"
+       "sort"
+       "strings"
        "sync"
        "time"
 
-       lru "github.com/hashicorp/golang-lru"
-       log "github.com/sirupsen/logrus"
        "github.com/vapor/chain"
        "github.com/vapor/common"
        "github.com/vapor/config"
        "github.com/vapor/consensus"
+       engine "github.com/vapor/consensus/consensus"
        "github.com/vapor/crypto"
-       "github.com/vapor/crypto/ed25519/chainkd"
-       "github.com/vapor/protocol"
        "github.com/vapor/protocol/bc"
        "github.com/vapor/protocol/bc/types"
-       "github.com/vapor/protocol/vm/vmutil"
+       "github.com/vapor/protocol/vm"
 )
 
-const (
-       inMemorySnapshots  = 128             // Number of recent vote snapshots to keep in memory
-       inMemorySignatures = 4096            // Number of recent block signatures to keep in memory
-       secondsPerYear     = 365 * 24 * 3600 // Number of seconds for one year
-       checkpointInterval = 360             // About N hours if config.period is N
-       module             = "dpos"
-)
+type Delegate struct {
+       DelegateAddress string `json:"delegate_address"`
+       Votes           uint64 `json:"votes"`
+}
 
-//delegated-proof-of-stake protocol constants.
-var (
-       SignerBlockReward     = big.NewInt(5e+18) // Block reward in wei for successfully mining a block first year
-       defaultEpochLength    = uint64(3000000)   // Default number of blocks after which vote's period of validity
-       defaultBlockPeriod    = uint64(3)         // Default minimum difference between two consecutive block's timestamps
-       defaultMaxSignerCount = uint64(21)        //
-       //defaultMinVoterBalance           = new(big.Int).Mul(big.NewInt(10000), big.NewInt(1e+18))
-       defaultMinVoterBalance           = uint64(0)
-       extraVanity                      = 32            // Fixed number of extra-data prefix bytes reserved for signer vanity
-       extraSeal                        = 65            // Fixed number of extra-data suffix bytes reserved for signer seal
-       defaultDifficulty                = big.NewInt(1) // Default difficulty
-       defaultLoopCntRecalculateSigners = uint64(10)    // Default loop count to recreate signers from top tally
-       minerRewardPerThousand           = uint64(618)   // Default reward for miner in each block from block reward (618/1000)
-       candidateNeedPD                  = false         // is new candidate need Proposal & Declare process
-)
+type DelegateWrapper struct {
+       delegate []Delegate
+       by       func(p, q *Delegate) bool
+}
 
-var (
-       // errUnknownBlock is returned when the list of signers is requested for a block
-       // that is not part of the local blockchain.
-       errUnknownBlock = errors.New("unknown block")
+func (dw DelegateWrapper) Len() int {
+       return len(dw.delegate)
+}
+func (dw DelegateWrapper) Swap(i, j int) {
+       dw.delegate[i], dw.delegate[j] = dw.delegate[j], dw.delegate[i]
+}
+func (dw DelegateWrapper) Less(i, j int) bool {
+       return dw.by(&dw.delegate[i], &dw.delegate[j])
+}
 
-       // errMissingVanity is returned if a block's extra-data section is shorter than
-       // 32 bytes, which is required to store the signer vanity.
-       errMissingVanity = errors.New("extra-data 32 byte vanity prefix missing")
+type DelegateInfo struct {
+       Delegates []Delegate `json:"delegates"`
+}
 
-       // errMissingSignature is returned if a block's extra-data section doesn't seem
-       // to contain a 65 byte secp256k1 signature.
-       errMissingSignature = errors.New("extra-data 65 byte suffix signature missing")
+func (d *DelegateInfo) ConsensusName() string {
+       return "dpos"
+}
 
-       // errInvalidMixDigest is returned if a block's mix digest is non-zero.
-       errInvalidMixDigest = errors.New("non-zero mix digest")
+const maxConfirmBlockCount = 2
 
-       // errInvalidUncleHash is returned if a block contains an non-empty uncle list.
-       errInvalidUncleHash = errors.New("non empty uncle hash")
+type IrreversibleBlockInfo struct {
+       heights    []int64
+       hashs      []bc.Hash
+       HeightHash map[int64]bc.Hash
+}
 
-       // ErrInvalidTimestamp is returned if the timestamp of a block is lower than
-       // the previous block's timestamp + the minimum block period.
-       ErrInvalidTimestamp = errors.New("invalid timestamp")
+func newIrreversibleBlockInfo() *IrreversibleBlockInfo {
+       o := &IrreversibleBlockInfo{}
+       for i := 0; i < maxConfirmBlockCount; i++ {
+               o.heights = append(o.heights, -1)
+               o.hashs = append(o.hashs, bc.Hash{})
+       }
+       o.HeightHash = make(map[int64]bc.Hash)
+       return o
+}
 
-       // errInvalidVotingChain is returned if an authorization list is attempted to
-       // be modified via out-of-range or non-contiguous headers.
-       errInvalidVotingChain = errors.New("invalid voting chain")
+type DposType struct {
+       c                           chain.Chain
+       vote                        *Vote
+       MaxDelegateNumber           uint64
+       BlockIntervalTime           uint64
+       DposStartHeight             uint64
+       DposStartTime               uint64
+       superForgerAddress          common.Address
+       irreversibleBlockFileName   string
+       irreversibleBlockInfo       IrreversibleBlockInfo
+       lockIrreversibleBlockInfo   sync.Mutex
+       maxIrreversibleCount        int
+       firstIrreversibleThreshold  uint64
+       secondIrreversibleThreshold uint64
+}
 
-       // errUnauthorized is returned if a header is signed by a non-authorized entity.
-       errUnauthorized = errors.New("unauthorized")
+var GDpos = &DposType{
+       maxIrreversibleCount:        10000,
+       firstIrreversibleThreshold:  90,
+       secondIrreversibleThreshold: 67,
+}
 
-       // errPunishedMissing is returned if a header calculate punished signer is wrong.
-       errPunishedMissing = errors.New("punished signer missing")
+func (d *DposType) Init(c chain.Chain, delegateNumber, intervalTime, blockHeight uint64, blockHash bc.Hash) error {
+       d.c = c
+       vote, err := newVote(blockHeight, blockHash)
+       if err != nil {
+               return err
+       }
+       d.vote = vote
+       d.MaxDelegateNumber = delegateNumber
+       d.BlockIntervalTime = intervalTime
+       d.DposStartHeight = 0
+       address, _ := common.DecodeAddress("vsm1qkm743xmgnvh84pmjchq2s4tnfpgu9ae2f9slep", &consensus.ActiveNetParams)
+       d.superForgerAddress = address
 
-       // errWaitTransactions is returned if an empty block is attempted to be sealed
-       // on an instant chain (0 second period). It's important to refuse these as the
-       // block reward is zero, so an empty block just bloats the chain... fast.
-       errWaitTransactions = errors.New("waiting for transactions")
+       GDpos.irreversibleBlockFileName = filepath.Join(config.CommonConfig.RootDir, "dpos", "irreversible_block.dat")
+       GDpos.irreversibleBlockInfo = *newIrreversibleBlockInfo()
+       if err := GDpos.ReadIrreversibleBlockInfo(&GDpos.irreversibleBlockInfo); err != nil {
+               return err
+       }
 
-       // errUnclesNotAllowed is returned if uncles exists
-       errUnclesNotAllowed = errors.New("uncles not allowed")
+       header, _ := c.GetHeaderByHeight(d.DposStartHeight)
+       d.setStartTime(header.Timestamp)
+       return nil
+}
 
-       // errCreateSignerQueueNotAllowed is returned if called in (block number + 1) % maxSignerCount != 0
-       errCreateSignerQueueNotAllowed = errors.New("create signer queue not allowed")
+func (d *DposType) setStartTime(t uint64) {
+       d.DposStartTime = t
+}
 
-       // errInvalidSignerQueue is returned if verify SignerQueue fail
-       errInvalidSignerQueue = errors.New("invalid signer queue")
+func (d *DposType) IsMining(address common.Address, t uint64) (interface{}, error) {
+
+       header := d.c.BestBlockHeader()
+       currentLoopIndex := d.GetLoopIndex(t)
+       currentDelegateIndex := d.GetDelegateIndex(t)
+       prevLoopIndex := d.GetLoopIndex(header.Timestamp)
+       prevDelegateIndex := d.GetDelegateIndex(header.Timestamp)
+       if currentLoopIndex > prevLoopIndex {
+               delegateInfo := d.GetNextDelegates(t)
+               cDelegateInfo := delegateInfo.(*DelegateInfo)
+               if cDelegateInfo.Delegates[currentDelegateIndex].DelegateAddress == address.EncodeAddress() {
+                       return delegateInfo, nil
+               }
+               return nil, errors.New("Is not the current mining node")
+       } else if currentLoopIndex == prevLoopIndex && currentDelegateIndex > prevDelegateIndex {
+               currentDelegateInfo, err := d.GetBlockDelegates(header)
+               if err != nil {
+                       return nil, err
+               }
+               if currentDelegateIndex+1 > uint64(len(currentDelegateInfo.Delegates)) {
+                       return nil, errors.New("Out of the block node list")
+               } else if currentDelegateInfo.Delegates[currentDelegateIndex].DelegateAddress == address.EncodeAddress() {
+                       return nil, nil
+               } else {
+                       return nil, errors.New("Is not the current mining node")
+               }
+       } else {
+               return nil, errors.New("Time anomaly")
+       }
+}
 
-       // errSignerQueueEmpty is returned if no signer when calculate
-       errSignerQueueEmpty = errors.New("signer queue is empty")
-)
+func (d *DposType) ProcessRegister(delegateAddress string, delegateName string, hash bc.Hash, height uint64) bool {
+       return d.vote.ProcessRegister(delegateAddress, delegateName, hash, height)
+}
 
-type Dpos struct {
-       config     *config.DposConfig // Consensus engine configuration parameters
-       store      protocol.Store     // Database to store and retrieve snapshot checkpoints
-       recents    *lru.ARCCache      // Snapshots for recent block to speed up reorgs
-       signatures *lru.ARCCache      // Signatures of recent blocks to speed up mining
-       signer     string             // Ethereum address of the signing key
-       lock       sync.RWMutex       // Protects the signer fields
-       lcsc       uint64             // Last confirmed side chain
-}
-
-//
-func ecrecover(header *types.BlockHeader, sigcache *lru.ARCCache, c chain.Chain) (string, error) {
-       xpub := &chainkd.XPub{}
-       xpub.UnmarshalText(header.Coinbase)
-       derivedPK := xpub.PublicKey()
-       pubHash := crypto.Ripemd160(derivedPK)
-       address, err := common.NewAddressWitnessPubKeyHash(pubHash, &consensus.ActiveNetParams)
-       if err != nil {
-               return "", err
-       }
+func (d *DposType) ProcessVote(voterAddress string, delegates []string, hash bc.Hash, height uint64) bool {
+       return d.vote.ProcessVote(voterAddress, delegates, hash, height)
+}
 
-       return address.EncodeAddress(), nil
+func (d *DposType) ProcessCancelVote(voterAddress string, delegates []string, hash bc.Hash, height uint64) bool {
+       return d.vote.ProcessCancelVote(voterAddress, delegates, hash, height)
 }
 
-//
-func New(config *config.DposConfig, store protocol.Store) *Dpos {
-       conf := *config
-       if conf.Epoch == 0 {
-               conf.Epoch = defaultEpochLength
-       }
-       if conf.Period == 0 {
-               conf.Period = defaultBlockPeriod
-       }
-       if conf.MaxSignerCount == 0 {
-               conf.MaxSignerCount = defaultMaxSignerCount
+func (d *DposType) UpdateAddressBalance(addressBalance []engine.AddressBalance) {
+       d.vote.UpdateAddressBalance(addressBalance)
+}
+
+func (d *DposType) GetLoopIndex(time uint64) uint64 {
+       if time < d.DposStartTime {
+               return 0
        }
-       if conf.MinVoterBalance == 0 {
-               conf.MinVoterBalance = defaultMinVoterBalance
+       return (time - d.DposStartTime) / (d.MaxDelegateNumber * d.BlockIntervalTime)
+}
+
+func (d *DposType) GetDelegateIndex(time uint64) uint64 {
+       if time < d.DposStartTime {
+               return 0
        }
-       // Allocate the snapshot caches and create the engine
-       recents, _ := lru.NewARC(inMemorySnapshots)
-       signatures, _ := lru.NewARC(inMemorySignatures)
-       return &Dpos{
-               config:     &conf,
-               store:      store,
-               recents:    recents,
-               signatures: signatures,
+       return (time - d.DposStartTime) % (d.MaxDelegateNumber * d.BlockIntervalTime) / d.BlockIntervalTime
+}
+
+func (d *DposType) GetNextDelegates(t uint64) interface{} {
+       delegates := d.vote.GetTopDelegateInfo(config.CommonConfig.Consensus.MinVoterBalance, d.MaxDelegateNumber-1)
+       delegate := Delegate{
+               DelegateAddress: d.superForgerAddress.EncodeAddress(),
+               Votes:           7,
        }
+       delegates = append(delegates, delegate)
+       delegateInfo := DelegateInfo{}
+       delegateInfo.Delegates = SortDelegate(delegates, t)
+       return &delegateInfo
 }
 
-// Authorize injects a private key into the consensus engine to mint new blocks with.
-func (d *Dpos) Authorize(signer string) {
-       d.lock.Lock()
-       defer d.lock.Unlock()
-       d.signer = signer
+func (d *DposType) GetBlockDelegates(header *types.BlockHeader) (*DelegateInfo, error) {
+       loopIndex := d.GetLoopIndex(header.Timestamp)
+       for {
+               preHeader, err := d.c.GetHeaderByHash(&header.PreviousBlockHash)
+               if err != nil {
+                       return nil, err
+               }
+               if header.Height == d.DposStartHeight || d.GetLoopIndex(preHeader.Timestamp) < loopIndex {
+                       block, err := d.c.GetBlockByHeight(header.Height)
+                       if err != nil {
+                               return nil, err
+                       }
+                       delegateInfo, err := d.GetBlockDelegate(block)
+                       if err != nil {
+                               return nil, err
+                       }
+                       return delegateInfo, nil
+               }
+               header = preHeader
+       }
 }
 
-func (d *Dpos) VerifySeal(c chain.Chain, header *types.BlockHeader) error {
-       return d.verifyCascadingFields(c, header, nil)
+func (d *DposType) GetBlockDelegate(block *types.Block) (*DelegateInfo, error) {
+       tx := block.Transactions[0]
+       if len(tx.TxData.Inputs) == 1 && tx.TxData.Inputs[0].InputType() == types.CoinbaseInputType {
+               msg := &DposMsg{}
+               if err := json.Unmarshal(tx.TxData.ReferenceData, msg); err != nil {
+                       return nil, err
+               }
+               if msg.Type == vm.OP_DELEGATE {
+                       delegateInfo := &DelegateInfoList{}
+                       if err := json.Unmarshal(msg.Data, delegateInfo); err != nil {
+                               return nil, err
+                       }
+                       return &delegateInfo.Delegate, nil
+               }
+
+       }
+       return nil, errors.New("The first transaction is not a coinbase transaction")
 }
 
-func (d *Dpos) verifyCascadingFields(c chain.Chain, header *types.BlockHeader, parents []*types.BlockHeader) error {
-       // The genesis block is the always valid dead-end
-       height := header.Height
-       if height == 0 {
-               return nil
+func (d *DposType) CheckCoinbase(tx types.TxData, t uint64, Height uint64) error {
+       msg := &DposMsg{}
+       if err := json.Unmarshal(tx.ReferenceData, msg); err != nil {
+               return err
        }
+       if msg.Type == vm.OP_DELEGATE {
+               delegateInfo := &DelegateInfoList{}
+               if err := json.Unmarshal(msg.Data, delegateInfo); err != nil {
+                       return err
+               }
+               buf := [8]byte{}
+               binary.LittleEndian.PutUint64(buf[:], t)
 
-       var (
-               parent *types.BlockHeader
-               err    error
-       )
+               if !delegateInfo.Xpub.Verify(buf[:], delegateInfo.SigTime) {
+                       return errors.New("CheckBlock CheckCoinbase: Verification signature error")
+               }
+               var (
+                       address common.Address
+                       err     error
+               )
+               address, err = common.NewAddressWitnessPubKeyHash(tx.Outputs[0].ControlProgram[2:], &consensus.ActiveNetParams)
+               if err != nil {
+                       return err
+               }
+               derivedPK := delegateInfo.Xpub.PublicKey()
+               pubHash := crypto.Ripemd160(derivedPK)
 
-       if len(parents) > 0 {
-               parent = parents[len(parents)-1]
-       } else {
-               parent, err = c.GetHeaderByHeight(height - 1)
+               addressDet, err := common.NewAddressWitnessPubKeyHash(pubHash, &consensus.ActiveNetParams)
                if err != nil {
                        return err
                }
+
+               if addressDet.EncodeAddress() == address.EncodeAddress() {
+                       return nil
+               }
        }
+       return errors.New("CheckBlock CheckCoinbase error")
+}
+
+func (d *DposType) CheckBlockHeader(header types.BlockHeader) error {
+       blockT := time.Unix(int64(header.Timestamp), 0)
 
-       if parent == nil {
-               return errors.New("unknown ancestor")
+       if blockT.Sub(time.Now()).Seconds() > float64(d.BlockIntervalTime) {
+               return errors.New("block time is error")
        }
 
-       if _, err = d.snapshot(c, height-1, header.PreviousBlockHash, parents, nil, defaultLoopCntRecalculateSigners); err != nil {
+       if header.Height > d.DposStartHeight {
+               header, _ := d.c.GetHeaderByHeight(d.DposStartHeight)
+               d.setStartTime(header.Timestamp)
+       }
+
+       preHeader, err := d.c.GetHeaderByHash(&header.PreviousBlockHash)
+       if err != nil {
                return err
        }
 
-       return d.verifySeal(c, header, parents)
+       currentLoopIndex := d.GetLoopIndex(header.Timestamp)
+       currentDelegateIndex := d.GetDelegateIndex(header.Timestamp)
+       prevLoopIndex := d.GetLoopIndex(preHeader.Timestamp)
+       prevDelegateIndex := d.GetDelegateIndex(preHeader.Timestamp)
+       if currentLoopIndex > prevLoopIndex ||
+               (currentLoopIndex == prevLoopIndex && currentDelegateIndex > prevDelegateIndex) {
+               return nil
+       }
+
+       return errors.New("DPoS CheckBlockHeader error")
 }
 
-// verifySeal checks whether the signature contained in the header satisfies the
-// consensus protocol requirements. The method accepts an optional list of parent
-// headers that aren't yet part of the local blockchain to generate the snapshots
-// from.
-func (d *Dpos) verifySeal(c chain.Chain, header *types.BlockHeader, parents []*types.BlockHeader) error {
-       height := header.Height
-       if height == 0 {
-               return errUnknownBlock
+func (d *DposType) CheckBlock(block types.Block, fIsCheckDelegateInfo bool) error {
+       if block.Height > d.DposStartHeight {
+               header, _ := d.c.GetHeaderByHeight(d.DposStartHeight)
+               d.setStartTime(header.Timestamp)
+       }
+
+       blockT := time.Unix(int64(block.Timestamp), 0)
+       if blockT.Sub(time.Now()).Seconds() > float64(d.BlockIntervalTime) {
+               return errors.New("block time is error")
+       }
+       if err := d.CheckCoinbase(block.Transactions[0].TxData, block.Timestamp, block.Height); err != nil {
+               return err
        }
-       // Retrieve the snapshot needed to verify this header and cache it
-       snap, err := d.snapshot(c, height-1, header.PreviousBlockHash, parents, nil, defaultLoopCntRecalculateSigners)
+
+       preBlock, err := d.c.GetBlockByHash(&block.PreviousBlockHash)
        if err != nil {
                return err
        }
 
-       signer := ""
+       currentLoopIndex := d.GetLoopIndex(block.Timestamp)
+       currentDelegateIndex := d.GetDelegateIndex(block.Timestamp)
+       prevLoopIndex := d.GetLoopIndex(preBlock.Timestamp)
+       prevDelegateIndex := d.GetDelegateIndex(preBlock.Timestamp)
 
-       if height > d.config.MaxSignerCount {
-               var (
-                       parent *types.BlockHeader
-                       err    error
-               )
-               if len(parents) > 0 {
-                       parent = parents[len(parents)-1]
-               } else {
-                       if parent, err = c.GetHeaderByHeight(height - 1); err != nil {
+       delegateInfo := &DelegateInfo{}
+
+       if currentLoopIndex < prevLoopIndex {
+               return errors.New("Block time exception")
+       } else if currentLoopIndex > prevLoopIndex {
+               if fIsCheckDelegateInfo {
+                       if err := d.CheckBlockDelegate(block); err != nil {
                                return err
                        }
+                       d.ProcessIrreversibleBlock(block.Height, block.Hash())
                }
-
-               //parent
-               xpub := &chainkd.XPub{}
-               xpub.UnmarshalText(parent.Coinbase)
-               derivedPK := xpub.PublicKey()
-               pubHash := crypto.Ripemd160(derivedPK)
-               parentCoinbase, err := common.NewAddressWitnessPubKeyHash(pubHash, &consensus.ActiveNetParams)
+               delegateInfo, err = d.GetBlockDelegate(&block)
                if err != nil {
                        return err
                }
+       } else {
+               if currentDelegateIndex < prevDelegateIndex {
+                       return errors.New("Block time exception")
+               }
 
-               //current
-               xpub.UnmarshalText(header.Coinbase)
-               derivedPK = xpub.PublicKey()
-               pubHash = crypto.Ripemd160(derivedPK)
-               currentCoinbase, err := common.NewAddressWitnessPubKeyHash(pubHash, &consensus.ActiveNetParams)
+               delegateInfo, err = d.GetBlockDelegates(&preBlock.BlockHeader)
                if err != nil {
                        return err
                }
-               signer = currentCoinbase.EncodeAddress()
+       }
 
-               parentHeaderExtra := HeaderExtra{}
-               if err = json.Unmarshal(parent.Extra[extraVanity:len(parent.Extra)-extraSeal], &parentHeaderExtra); err != nil {
-                       return err
-               }
+       delegateAddress := d.getBlockForgerAddress(block)
+       if currentDelegateIndex < uint64(len(delegateInfo.Delegates)) &&
+               delegateInfo.Delegates[currentDelegateIndex].DelegateAddress == delegateAddress.EncodeAddress() {
+               return nil
+       }
+       h := block.Hash()
+       return fmt.Errorf("CheckBlock GetDelegateID blockhash:%s error", h.String())
+}
 
-               currentHeaderExtra := HeaderExtra{}
-               if err = json.Unmarshal(header.Extra[extraVanity:len(header.Extra)-extraSeal], &currentHeaderExtra); err != nil {
-                       return err
+func (d *DposType) CheckBlockDelegate(block types.Block) error {
+       delegateInfo, err := d.GetBlockDelegate(&block)
+       if err != nil {
+               return err
+       }
+       nextDelegateInfoInterface := d.GetNextDelegates(block.Timestamp)
+       nextDelegateInfo := nextDelegateInfoInterface.(*DelegateInfo)
+       if len(delegateInfo.Delegates) != len(nextDelegateInfo.Delegates) {
+               return errors.New("The delegates num is not correct in block")
+       }
+       for index, v := range delegateInfo.Delegates {
+               if v.DelegateAddress != nextDelegateInfo.Delegates[index].DelegateAddress {
+                       return errors.New("The delegates address is not correct in block")
                }
+       }
 
-               // verify signerqueue
-               if height%d.config.MaxSignerCount == 0 {
-                       err := snap.verifySignerQueue(currentHeaderExtra.SignerQueue)
-                       if err != nil {
-                               return err
-                       }
+       return nil
+}
 
+func (d *DposType) ProcessIrreversibleBlock(height uint64, hash bc.Hash) {
+       d.lockIrreversibleBlockInfo.Lock()
+       defer d.lockIrreversibleBlockInfo.Unlock()
+       i := 0
+       for i = maxConfirmBlockCount - 1; i >= 0; i-- {
+               if d.irreversibleBlockInfo.heights[i] < 0 || int64(height) < d.irreversibleBlockInfo.heights[i] {
+                       d.irreversibleBlockInfo.heights[i] = -1
                } else {
-                       for i := 0; i < int(d.config.MaxSignerCount); i++ {
-                               if parentHeaderExtra.SignerQueue[i] != currentHeaderExtra.SignerQueue[i] {
-                                       return errInvalidSignerQueue
+                       level := (height - uint64(d.irreversibleBlockInfo.heights[i])) * 100
+                       if level >= d.MaxDelegateNumber*d.firstIrreversibleThreshold {
+                               d.AddIrreversibleBlock(int64(height), hash)
+                       } else if level >= d.MaxDelegateNumber*d.secondIrreversibleThreshold {
+                               if i == maxConfirmBlockCount-1 {
+                                       d.AddIrreversibleBlock(int64(height), hash)
+                                       for k := 0; k < maxConfirmBlockCount-1; k++ {
+                                               d.irreversibleBlockInfo.heights[k] = d.irreversibleBlockInfo.heights[k+1]
+                                               d.irreversibleBlockInfo.hashs[k] = d.irreversibleBlockInfo.hashs[k+1]
+                                       }
+                                       d.irreversibleBlockInfo.heights[i] = int64(height)
+                                       d.irreversibleBlockInfo.hashs[i] = hash
+                                       return
+                               } else {
+                                       d.irreversibleBlockInfo.heights[i+1] = int64(height)
+                                       d.irreversibleBlockInfo.hashs[i+1] = hash
+                                       return
                                }
+
                        }
-               }
-               // verify missing signer for punish
-               parentSignerMissing := getSignerMissing(parentCoinbase.EncodeAddress(), currentCoinbase.EncodeAddress(), parentHeaderExtra)
-               if len(parentSignerMissing) != len(currentHeaderExtra.SignerMissing) {
-                       return errPunishedMissing
-               }
-               for i, signerMissing := range currentHeaderExtra.SignerMissing {
-                       if parentSignerMissing[i] != signerMissing {
-                               return errPunishedMissing
+                       for k := 0; k < maxConfirmBlockCount; k++ {
+                               d.irreversibleBlockInfo.heights[k] = -1
                        }
-               }
+                       d.irreversibleBlockInfo.heights[0] = int64(height)
+                       d.irreversibleBlockInfo.hashs[0] = hash
+                       return
 
+               }
        }
-
-       if !snap.inturn(signer, header.Timestamp) {
-               return errUnauthorized
+       if i < 0 {
+               d.irreversibleBlockInfo.heights[0] = int64(height)
+               d.irreversibleBlockInfo.hashs[0] = hash
        }
-
-       return nil
 }
 
-// Prepare implements consensus.Engine, preparing all the consensus fields of the header for running the transactions on top.
-func (d *Dpos) Prepare(c chain.Chain, header *types.BlockHeader) error {
-       if d.config.GenesisTimestamp < uint64(time.Now().Unix()) {
-               return nil
-       }
+func (d *DposType) getBlockForgerAddress(block types.Block) common.Address {
+       tx := block.Transactions[0].TxData
 
-       if header.Height == 1 {
-               for {
-                       delay := time.Unix(int64(d.config.GenesisTimestamp-2), 0).Sub(time.Now())
-                       if delay <= time.Duration(0) {
-                               log.WithFields(log.Fields{"module": module, "time": time.Now()}).Info("Ready for seal block")
-                               break
-                       } else if delay > time.Duration(d.config.Period)*time.Second {
-                               delay = time.Duration(d.config.Period) * time.Second
-                       }
-                       log.WithFields(log.Fields{"module": module, "delay": time.Duration(time.Unix(int64(d.config.GenesisTimestamp-2), 0).Sub(time.Now()))}).Info("Waiting for seal block")
-                       select {
-                       case <-time.After(delay):
-                               continue
+       if len(tx.Inputs) == 1 && tx.Inputs[0].InputType() == types.CoinbaseInputType {
+               address, err := common.NewAddressWitnessPubKeyHash(tx.Outputs[0].ControlProgram[2:], &consensus.ActiveNetParams)
+               if err != nil {
+                       address, err := common.NewAddressWitnessScriptHash(tx.Outputs[0].ControlProgram[2:], &consensus.ActiveNetParams)
+                       if err != nil {
+                               return nil
                        }
+                       return address
                }
+               return address
        }
+
        return nil
 }
 
-func (d *Dpos) Finalize(c chain.Chain, header *types.BlockHeader, txs []*bc.Tx) error {
-       height := header.Height
-       parent, err := c.GetHeaderByHeight(height - 1)
-       if parent == nil {
-               return err
-       }
-       //parent
-       var xpub chainkd.XPub
-       xpub.UnmarshalText(parent.Coinbase)
-       pubHash := crypto.Ripemd160(xpub.PublicKey())
-       parentCoinbase, err := common.NewAddressWitnessPubKeyHash(pubHash, &consensus.ActiveNetParams)
-       if err != nil {
-               return err
-       }
+func (d *DposType) IsValidBlockCheckIrreversibleBlock(height uint64, hash bc.Hash) error {
+       d.lockIrreversibleBlockInfo.Lock()
+       defer d.lockIrreversibleBlockInfo.Unlock()
 
-       //current
-       xpub.UnmarshalText(header.Coinbase)
-       pubHash = crypto.Ripemd160(xpub.PublicKey())
-       currentCoinbase, err := common.NewAddressWitnessPubKeyHash(pubHash, &consensus.ActiveNetParams)
-       if err != nil {
-               return err
+       if h, ok := d.irreversibleBlockInfo.HeightHash[int64(height)]; ok {
+               if h != hash {
+                       return fmt.Errorf("invalid block[%d:%s]", height, hash.String())
+               }
        }
 
-       //header.Timestamp
-       t := new(big.Int).Add(new(big.Int).SetUint64(parent.Timestamp), new(big.Int).SetUint64(d.config.Period))
-       header.Timestamp = t.Uint64()
-
-       if header.Timestamp < uint64(time.Now().Unix()) {
-               header.Timestamp = uint64(time.Now().Unix())
-       }
+       return nil
+}
 
-       if len(header.Extra) < extraVanity {
-               header.Extra = append(header.Extra, bytes.Repeat([]byte{0x00}, extraVanity-len(header.Extra))...)
+func (d *DposType) ReadIrreversibleBlockInfo(info *IrreversibleBlockInfo) error {
+       f, err := os.Open(d.irreversibleBlockFileName)
+       if err != nil {
+               return err
        }
-
-       header.Extra = header.Extra[:extraVanity]
-       // genesisVotes write direct into snapshot, which number is 1
-       var genesisVotes []*Vote
-       parentHeaderExtra := HeaderExtra{}
-       currentHeaderExtra := HeaderExtra{}
-       if height == 1 {
-               alreadyVote := make(map[string]struct{})
-               for _, voter := range d.config.SelfVoteSigners {
-                       if _, ok := alreadyVote[voter]; !ok {
-                               genesisVotes = append(genesisVotes, &Vote{
-                                       Voter:     voter,
-                                       Candidate: voter,
-                                       Stake:     0,
-                                       //Stake:     state.GetBalance(voter),
-                               })
-                               alreadyVote[voter] = struct{}{}
+       defer f.Close()
+       buf := bufio.NewReader(f)
+       for {
+               line, err := buf.ReadString('\n')
+               if err != nil {
+                       if err == io.EOF {
+                               return nil
                        }
+                       return err
                }
-       } else {
-               parentHeaderExtraByte := parent.Extra[extraVanity : len(parent.Extra)-extraSeal]
-               if err := json.Unmarshal(parentHeaderExtraByte, &parentHeaderExtra); err != nil {
+               line = strings.TrimSpace(line)
+               var height int64
+               var hashString string
+               n, err := fmt.Sscanf(line, "%d;%s\n", &height, &hashString)
+               if err != nil || n != 2 {
+                       return errors.New("parse error for ReadIrreversibleBlockInfo ")
+               }
+               var hash bc.Hash
+               if err := hash.UnmarshalText([]byte(hashString)); err != nil {
                        return err
                }
-               currentHeaderExtra.ConfirmedBlockNumber = parentHeaderExtra.ConfirmedBlockNumber
-               currentHeaderExtra.SignerQueue = parentHeaderExtra.SignerQueue
-               currentHeaderExtra.LoopStartTime = parentHeaderExtra.LoopStartTime
-               currentHeaderExtra.SignerMissing = getSignerMissing(parentCoinbase.EncodeAddress(), currentCoinbase.EncodeAddress(), parentHeaderExtra)
+               d.AddIrreversibleBlock(height, hash)
        }
+}
 
-       // calculate votes write into header.extra
-       currentHeaderExtra, err = d.processCustomTx(currentHeaderExtra, c, header, txs)
-       if err != nil {
-               return err
+type Int64Slice []int64
+
+func (a Int64Slice) Len() int {
+       return len(a)
+}
+func (a Int64Slice) Swap(i, j int) {
+       a[i], a[j] = a[j], a[i]
+}
+func (a Int64Slice) Less(i, j int) bool {
+       return a[i] < a[j]
+}
+
+func (d *DposType) WriteIrreversibleBlockInfo() error {
+       if len(d.irreversibleBlockInfo.HeightHash) == 0 {
+               return nil
        }
-       // Assemble the voting snapshot to check which votes make sense
-       snap, err := d.snapshot(c, height-1, header.PreviousBlockHash, nil, genesisVotes, defaultLoopCntRecalculateSigners)
+
+       f, err := os.Create(d.irreversibleBlockFileName)
        if err != nil {
                return err
        }
-
-       currentHeaderExtra.ConfirmedBlockNumber = snap.getLastConfirmedBlockNumber(currentHeaderExtra.CurrentBlockConfirmations).Uint64()
-       // write signerQueue in first header, from self vote signers in genesis block
-       if height == 1 {
-               currentHeaderExtra.LoopStartTime = d.config.GenesisTimestamp
-               for i := 0; i < int(d.config.MaxSignerCount); i++ {
-                       currentHeaderExtra.SignerQueue = append(currentHeaderExtra.SignerQueue, d.config.SelfVoteSigners[i%len(d.config.SelfVoteSigners)])
-               }
+       defer f.Close()
+       w := bufio.NewWriter(f)
+       var keys []int64
+       for k := range d.irreversibleBlockInfo.HeightHash {
+               keys = append(keys, k)
        }
-       if height%d.config.MaxSignerCount == 0 {
-               currentHeaderExtra.LoopStartTime = currentHeaderExtra.LoopStartTime + d.config.Period*d.config.MaxSignerCount
-               // create random signersQueue in currentHeaderExtra by snapshot.Tally
-               currentHeaderExtra.SignerQueue = []string{}
-               newSignerQueue, err := snap.createSignerQueue()
-               if err != nil {
-                       return err
-               }
 
-               currentHeaderExtra.SignerQueue = newSignerQueue
+       sort.Sort(Int64Slice(keys))
 
+       for _, k := range keys {
+               data, _ := d.irreversibleBlockInfo.HeightHash[k].MarshalText()
+               line := fmt.Sprintf("%d;%s\n", k, string(data))
+               w.WriteString(line)
        }
-       // encode header.extra
-       currentHeaderExtraEnc, err := json.Marshal(currentHeaderExtra)
-       if err != nil {
+
+       if err := w.Flush(); err != nil {
                return err
        }
-       header.Extra = append(header.Extra, currentHeaderExtraEnc...)
-       header.Extra = append(header.Extra, make([]byte, extraSeal)...)
+
        return nil
 }
 
-func (d *Dpos) Seal(c chain.Chain, block *types.Block) (*types.Block, error) {
-       header := block.BlockHeader
-       height := header.Height
-       if height == 0 {
-               return nil, errUnknownBlock
+func (d *DposType) AddIrreversibleBlock(height int64, hash bc.Hash) {
+       for k, _ := range d.irreversibleBlockInfo.HeightHash {
+               if len(d.irreversibleBlockInfo.HeightHash) > d.maxIrreversibleCount {
+                       delete(d.irreversibleBlockInfo.HeightHash, k)
+               } else {
+                       break
+               }
        }
+       d.irreversibleBlockInfo.HeightHash[height] = hash
+       d.vote.DeleteInvalidVote(uint64(height))
+}
 
-       if d.config.Period == 0 && len(block.Transactions) == 0 {
-               return nil, errWaitTransactions
-       }
-       // Bail out if we're unauthorized to sign a block
-       snap, err := d.snapshot(c, height-1, header.PreviousBlockHash, nil, nil, defaultLoopCntRecalculateSigners)
-       if err != nil {
-               return nil, err
-       }
-       if !snap.inturn(d.signer, header.Timestamp) {
-               return nil, errUnauthorized
-       }
+func (d *DposType) GetSuperForgerAddress() common.Address {
+       return d.superForgerAddress
+}
 
-       var xPrv chainkd.XPrv
-       if config.CommonConfig.Consensus.Dpos.XPrv == "" {
-               return nil, errors.New("Signer is empty")
-       }
-       xPrv.UnmarshalText([]byte(config.CommonConfig.Consensus.Dpos.XPrv))
-       sign := xPrv.Sign(block.BlockCommitment.TransactionsMerkleRoot.Bytes())
-       pubHash := crypto.Ripemd160(xPrv.XPub().PublicKey())
+func (d *DposType) GetIrreversibleBlock() {
 
-       control, err := vmutil.P2WPKHProgram([]byte(pubHash))
-       if err != nil {
-               return nil, err
-       }
+}
 
-       block.Proof = types.Proof{Sign: sign, ControlProgram: control}
-       return block, nil
+func (d *DposType) GetOldBlockHeight() uint64 {
+       return d.vote.GetOldBlockHeight()
 }
 
-func (d *Dpos) IsSealer(c chain.Chain, hash bc.Hash, header *types.BlockHeader, headerTime uint64) (bool, error) {
-       var (
-               snap    *Snapshot
-               headers []*types.BlockHeader
-       )
-       h := hash
-       height := header.Height
-       for snap == nil {
-               // If an in-memory snapshot was found, use that
-               if s, ok := d.recents.Get(h); ok {
-                       snap = s.(*Snapshot)
-                       break
-               }
-               // If an on-disk checkpoint snapshot can be found, use that
-               if height%checkpointInterval == 0 {
-                       if s, err := loadSnapshot(d.config, d.signatures, d.store, h); err == nil {
-                               log.WithFields(log.Fields{"func": "IsSealer", "number": height, "hash": h}).Warn("Loaded voting snapshot from disk")
-                               snap = s
-                               break
-                       } else {
-                               log.Warn("loadSnapshot:", err)
-                       }
-               }
+func (d *DposType) GetOldBlockHash() bc.Hash {
+       return d.vote.GetOldBlockHash()
+}
 
-               if height == 0 {
-                       genesis, err := c.GetHeaderByHeight(0)
-                       if err != nil {
-                               return false, err
-                       }
-                       var genesisVotes []*Vote
-                       alreadyVote := make(map[string]struct{})
-                       for _, voter := range d.config.SelfVoteSigners {
-                               if _, ok := alreadyVote[voter]; !ok {
-                                       genesisVotes = append(genesisVotes, &Vote{
-                                               Voter:     voter,
-                                               Candidate: voter,
-                                               Stake:     0,
-                                               //Stake:     state.GetBalance(voter),
-                                       })
-                                       alreadyVote[voter] = struct{}{}
-                               }
-                       }
-                       snap = newSnapshot(d.config, d.signatures, genesis.Hash(), genesisVotes, defaultLoopCntRecalculateSigners)
-                       if err := snap.store(d.store); err != nil {
-                               return false, err
-                       }
-                       log.Info("Stored genesis voting snapshot to disk")
-                       break
-               }
+func (d *DposType) ListDelegates() map[string]string {
+       return d.vote.ListDelegates()
+}
 
-               header, err := c.GetHeaderByHeight(height)
-               if header == nil || err != nil {
-                       return false, errors.New("unknown ancestor")
-               }
+func (d *DposType) GetDelegateVotes(delegate string) uint64 {
+       return d.vote.GetDelegateVotes(delegate)
+}
 
-               height, h = height-1, header.PreviousBlockHash
-       }
+func (d *DposType) GetDelegateVoters(delegate string) []string {
+       return d.vote.GetDelegateVoters(delegate)
+}
 
-       snap, err := snap.apply(headers)
-       if err != nil {
-               return false, err
-       }
+func (d *DposType) GetDelegate(name string) string {
+       return d.vote.GetDelegate(name)
 
-       d.recents.Add(snap.Hash, snap)
+}
 
-       if snap != nil {
-               loopIndex := int((headerTime-snap.LoopStartTime)/snap.config.Period) % len(snap.Signers)
-               if loopIndex >= len(snap.Signers) {
-                       return false, nil
-               } else if *snap.Signers[loopIndex] != d.signer {
-                       return false, nil
+func (d *DposType) GetDelegateName(address string) string {
+       return d.vote.GetDelegateName(address)
+}
 
-               }
-               return true, nil
-       } else {
-               return false, nil
-       }
+func (d *DposType) GetAddressBalance(address string) uint64 {
+       return d.vote.GetAddressBalance(address)
 }
 
-// snapshot retrieves the authorization snapshot at a given point in time.
-func (d *Dpos) snapshot(c chain.Chain, number uint64, hash bc.Hash, parents []*types.BlockHeader, genesisVotes []*Vote, lcrs uint64) (*Snapshot, error) {
+func (d *DposType) GetVotedDelegates(voter string) []string {
+       return d.vote.GetVotedDelegates(voter)
+}
 
-       var (
-               headers []*types.BlockHeader
-               snap    *Snapshot
-       )
-       h := hash
+func (d *DposType) HaveVote(voter, delegate string) bool {
+       return d.vote.HaveVote(voter, delegate)
+}
 
-       for snap == nil {
-               // If an in-memory snapshot was found, use that
-               if s, ok := d.recents.Get(h); ok {
-                       snap = s.(*Snapshot)
-                       break
-               }
-               // If an on-disk checkpoint snapshot can be found, use that
-               if number%checkpointInterval == 0 {
-                       if s, err := loadSnapshot(d.config, d.signatures, d.store, h); err == nil {
-                               log.WithFields(log.Fields{"number": number, "hash": h}).Warn("Loaded voting snapshot from disk")
-                               snap = s
-                               break
-                       }
-               }
-               if number == 0 {
-                       genesis, err := c.GetHeaderByHeight(0)
-                       if err != nil {
-                               return nil, err
-                       }
-                       if err := d.VerifySeal(c, genesis); err != nil {
-                               return nil, err
-                       }
+func (d *DposType) HaveDelegate(name, delegate string) bool {
+       return d.vote.HaveDelegate(name, delegate)
+}
 
-                       snap = newSnapshot(d.config, d.signatures, genesis.Hash(), genesisVotes, lcrs)
-                       if err := snap.store(d.store); err != nil {
-                               return nil, err
-                       }
-                       log.Info("Stored genesis voting snapshot to disk")
-                       break
-               }
-               var header *types.BlockHeader
-               if len(parents) > 0 {
-                       header = parents[len(parents)-1]
-                       if header.Hash() != h || header.Height != number {
-                               return nil, errors.New("unknown ancestor")
-                       }
-                       parents = parents[:len(parents)-1]
-               } else {
-                       var err error
-                       header, err = c.GetHeaderByHeight(number)
-                       if header == nil || err != nil {
-                               return nil, errors.New("unknown ancestor")
-                       }
-               }
-               headers = append(headers, header)
-               number, h = number-1, header.PreviousBlockHash
+func (d *DposType) Finish() error {
+       header := d.c.BestBlockHeader()
+       if err := d.vote.Store(header.Height, header.Hash()); err != nil {
+               return err
        }
 
-       // Previous snapshot found, apply any pending headers on top of it
-       for i := 0; i < len(headers)/2; i++ {
-               headers[i], headers[len(headers)-1-i] = headers[len(headers)-1-i], headers[i]
-       }
-       snap, err := snap.apply(headers)
-       if err != nil {
-               return nil, err
+       if err := d.WriteIrreversibleBlockInfo(); err != nil {
+               return err
        }
-       d.recents.Add(snap.Hash, snap)
 
-       // If we've generated a new checkpoint snapshot, save to disk
-       if snap.Number%checkpointInterval == 0 && len(headers) > 0 {
-               if err = snap.store(d.store); err != nil {
-                       return nil, err
-               }
-               log.Info("Stored voting snapshot to disk", "number", snap.Number, "hash", snap.Hash)
-       }
-       return snap, err
+       return nil
 }
 
-// Get the signer missing from last signer till header.Coinbase
-func getSignerMissing(lastSigner string, currentSigner string, extra HeaderExtra) []string {
+func SortDelegate(delegates []Delegate, t uint64) []Delegate {
+       var result []Delegate
+       r := getRand(uint64(len(delegates)), int64(t))
+       for _, i := range r {
+               result = append(result, delegates[i])
+       }
+       return result
+}
 
-       var signerMissing []string
-       recordMissing := false
-       for _, signer := range extra.SignerQueue {
-               if signer == lastSigner {
-                       recordMissing = true
+func getRand(num uint64, seed int64) []uint64 {
+       rand.Seed(seed)
+       var r []uint64
+       s := make(map[uint64]bool)
+       for {
+               v := rand.Uint64()
+               v %= num
+               if _, ok := s[v]; ok {
                        continue
                }
-               if signer == currentSigner {
+               s[v] = true
+               r = append(r, v)
+               if uint64(len(r)) >= num {
                        break
                }
-               if recordMissing {
-                       signerMissing = append(signerMissing, signer)
-               }
        }
-       return signerMissing
+
+       return r
 }
diff --git a/consensus/consensus/dpos/signer_queue.go b/consensus/consensus/dpos/signer_queue.go
deleted file mode 100644 (file)
index 0b07001..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-package dpos
-
-import (
-       "bytes"
-       "sort"
-
-       "github.com/vapor/protocol/bc"
-)
-
-type TallyItem struct {
-       addr  string
-       stake uint64
-}
-
-type TallySlice []TallyItem
-
-func (s TallySlice) Len() int      { return len(s) }
-func (s TallySlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
-func (s TallySlice) Less(i, j int) bool {
-       //we need sort reverse, so ...
-       if s[i].stake > s[j].stake {
-               return true
-
-       } else if s[i].stake < s[j].stake {
-               return false
-       }
-       // if the stake equal
-       //return bytes.Compare(s[i].addr.ScriptAddress(), s[j].addr.ScriptAddress()) > 0
-       return s[i].addr > s[j].addr
-}
-
-type SignerItem struct {
-       addr string
-       hash bc.Hash
-}
-
-type SignerSlice []SignerItem
-
-func (s SignerSlice) Len() int      { return len(s) }
-func (s SignerSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
-func (s SignerSlice) Less(i, j int) bool {
-       return bytes.Compare(s[i].hash.Bytes(), s[j].hash.Bytes()) > 0
-}
-
-// verify the SignerQueue base on block hash
-func (s *Snapshot) verifySignerQueue(signerQueue []string) error {
-
-       if len(signerQueue) > int(s.config.MaxSignerCount) {
-               return errInvalidSignerQueue
-       }
-       sq, err := s.createSignerQueue()
-       if err != nil {
-               return err
-       }
-       if len(sq) == 0 || len(sq) != len(signerQueue) {
-               return errInvalidSignerQueue
-       }
-       for i, signer := range signerQueue {
-               if signer != sq[i] {
-                       return errInvalidSignerQueue
-               }
-       }
-
-       return nil
-}
-
-func (s *Snapshot) buildTallySlice() TallySlice {
-       var tallySlice TallySlice
-       for address, stake := range s.Tally {
-               if !candidateNeedPD || s.isCandidate(address) {
-                       if _, ok := s.Punished[address]; ok {
-                               var creditWeight uint64
-                               if s.Punished[address] > defaultFullCredit-minCalSignerQueueCredit {
-                                       creditWeight = minCalSignerQueueCredit
-                               } else {
-                                       creditWeight = defaultFullCredit - s.Punished[address]
-                               }
-                               tallySlice = append(tallySlice, TallyItem{address, stake * creditWeight})
-                       } else {
-                               tallySlice = append(tallySlice, TallyItem{address, stake * defaultFullCredit})
-                       }
-               }
-       }
-       return tallySlice
-}
-
-func (s *Snapshot) createSignerQueue() ([]string, error) {
-       if (s.Number+1)%s.config.MaxSignerCount != 0 || s.Hash != s.HistoryHash[len(s.HistoryHash)-1] {
-               return nil, errCreateSignerQueueNotAllowed
-       }
-
-       var signerSlice SignerSlice
-       var topStakeAddress []string
-       if (s.Number+1)%(s.config.MaxSignerCount*s.LCRS) == 0 {
-               // before recalculate the signers, clear the candidate is not in snap.Candidates
-
-               // only recalculate signers from to tally per 10 loop,
-               // other loop end just reset the order of signers by block hash (nearly random)
-               tallySlice := s.buildTallySlice()
-               sort.Sort(TallySlice(tallySlice))
-               queueLength := int(s.config.MaxSignerCount)
-               if queueLength > len(tallySlice) {
-                       queueLength = len(tallySlice)
-               }
-               if queueLength == defaultOfficialMaxSignerCount && len(tallySlice) > defaultOfficialThirdLevelCount {
-                       for i, tallyItem := range tallySlice[:defaultOfficialFirstLevelCount] {
-                               signerSlice = append(signerSlice, SignerItem{tallyItem.addr, s.HistoryHash[len(s.HistoryHash)-1-i]})
-                       }
-                       var signerSecondLevelSlice, signerThirdLevelSlice, signerLastLevelSlice SignerSlice
-                       // 60%
-                       for i, tallyItem := range tallySlice[defaultOfficialFirstLevelCount:defaultOfficialSecondLevelCount] {
-                               signerSecondLevelSlice = append(signerSecondLevelSlice, SignerItem{tallyItem.addr, s.HistoryHash[len(s.HistoryHash)-1-i]})
-                       }
-                       sort.Sort(SignerSlice(signerSecondLevelSlice))
-                       signerSlice = append(signerSlice, signerSecondLevelSlice[:6]...)
-                       // 40%
-                       for i, tallyItem := range tallySlice[defaultOfficialSecondLevelCount:defaultOfficialThirdLevelCount] {
-                               signerThirdLevelSlice = append(signerThirdLevelSlice, SignerItem{tallyItem.addr, s.HistoryHash[len(s.HistoryHash)-1-i]})
-                       }
-                       sort.Sort(SignerSlice(signerThirdLevelSlice))
-                       signerSlice = append(signerSlice, signerThirdLevelSlice[:4]...)
-                       // choose 1 from last
-                       for i, tallyItem := range tallySlice[defaultOfficialThirdLevelCount:] {
-                               signerLastLevelSlice = append(signerLastLevelSlice, SignerItem{tallyItem.addr, s.HistoryHash[len(s.HistoryHash)-1-i]})
-                       }
-                       sort.Sort(SignerSlice(signerLastLevelSlice))
-                       signerSlice = append(signerSlice, signerLastLevelSlice[0])
-
-               } else {
-                       for i, tallyItem := range tallySlice[:queueLength] {
-                               signerSlice = append(signerSlice, SignerItem{tallyItem.addr, s.HistoryHash[len(s.HistoryHash)-1-i]})
-                       }
-
-               }
-
-       } else {
-               for i, signer := range s.Signers {
-                       signerSlice = append(signerSlice, SignerItem{*signer, s.HistoryHash[len(s.HistoryHash)-1-i]})
-               }
-       }
-
-       sort.Sort(SignerSlice(signerSlice))
-       // Set the top candidates in random order base on block hash
-       if len(signerSlice) == 0 {
-               return nil, errSignerQueueEmpty
-       }
-       for i := 0; i < int(s.config.MaxSignerCount); i++ {
-               topStakeAddress = append(topStakeAddress, signerSlice[i%len(signerSlice)].addr)
-       }
-
-       return topStakeAddress, nil
-
-}
diff --git a/consensus/consensus/dpos/snapshot.go b/consensus/consensus/dpos/snapshot.go
deleted file mode 100644 (file)
index 43a6a7a..0000000
+++ /dev/null
@@ -1,549 +0,0 @@
-package dpos
-
-import (
-       "encoding/json"
-       "errors"
-       "math/big"
-       "sort"
-       "time"
-
-       lru "github.com/hashicorp/golang-lru"
-       "github.com/vapor/config"
-       "github.com/vapor/protocol"
-       "github.com/vapor/protocol/bc"
-       "github.com/vapor/protocol/bc/types"
-)
-
-const (
-       defaultFullCredit               = 1000 // no punished
-       missingPublishCredit            = 100  // punished for missing one block seal
-       signRewardCredit                = 10   // seal one block
-       autoRewardCredit                = 1    // credit auto recover for each block
-       minCalSignerQueueCredit         = 300  // when calculate the signerQueue
-       defaultOfficialMaxSignerCount   = 21   // official max signer count
-       defaultOfficialFirstLevelCount  = 10   // official first level , 100% in signer queue
-       defaultOfficialSecondLevelCount = 20   // official second level, 60% in signer queue
-       defaultOfficialThirdLevelCount  = 30   // official third level, 40% in signer queue
-       // the credit of one signer is at least minCalSignerQueueCredit
-       candidateStateNormal = 1
-       candidateMaxLen      = 500 // if candidateNeedPD is false and candidate is more than candidateMaxLen, then minimum tickets candidates will be remove in each LCRS*loop
-)
-
-var errIncorrectTallyCount = errors.New("incorrect tally count")
-
-type Snapshot struct {
-       config          *config.DposConfig    // Consensus engine configuration parameters
-       sigcache        *lru.ARCCache         // Cache of recent block signatures to speed up ecrecover
-       LCRS            uint64                // Loop count to recreate signers from top tally
-       Period          uint64                `json:"period"`           // Period of seal each block
-       Number          uint64                `json:"number"`           // Block Number where the snapshot was created
-       ConfirmedNumber uint64                `json:"confirmed_number"` // Block Number confirmed when the snapshot was created
-       Hash            bc.Hash               `json:"hash"`             // Block hash where the snapshot was created
-       HistoryHash     []bc.Hash             `json:"historyHash"`      // Block hash list for two recent loop
-       Signers         []*string             `json:"signers"`          // Signers queue in current header
-       Votes           map[string]*Vote      `json:"votes"`            // All validate votes from genesis block
-       Tally           map[string]uint64     `json:"tally"`            // Stake for each candidate address
-       Voters          map[string]uint64     `json:"voters"`           // Block height for each voter address
-       Candidates      map[string]uint64     `json:"candidates"`       // Candidates for Signers (0- adding procedure 1- normal 2- removing procedure)
-       Punished        map[string]uint64     `json:"punished"`         // The signer be punished count cause of missing seal
-       Confirmations   map[uint64][]string   `json:"confirms"`         // The signer confirm given block height
-       Proposals       map[bc.Hash]*Proposal `json:"proposals"`        // The Proposals going or success (failed proposal will be removed)
-       HeaderTime      uint64                `json:"headerTime"`       // Time of the current header
-       LoopStartTime   uint64                `json:"loopStartTime"`    // Start Time of the current loop
-}
-
-// newSnapshot creates a new snapshot with the specified startup parameters. only ever use if for
-// the genesis block.
-func newSnapshot(config *config.DposConfig, sigcache *lru.ARCCache, hash bc.Hash, votes []*Vote, lcrs uint64) *Snapshot {
-
-       snap := &Snapshot{
-               config:          config,
-               sigcache:        sigcache,
-               LCRS:            lcrs,
-               Period:          config.Period,
-               Number:          0,
-               ConfirmedNumber: 0,
-               Hash:            hash,
-               HistoryHash:     []bc.Hash{},
-               Signers:         []*string{},
-               Votes:           make(map[string]*Vote),
-               Tally:           make(map[string]uint64),
-               Voters:          make(map[string]uint64),
-               Punished:        make(map[string]uint64),
-               Candidates:      make(map[string]uint64),
-               Confirmations:   make(map[uint64][]string),
-               Proposals:       make(map[bc.Hash]*Proposal),
-               HeaderTime:      uint64(time.Now().Unix()) - 1,
-               LoopStartTime:   config.GenesisTimestamp,
-       }
-       snap.HistoryHash = append(snap.HistoryHash, hash)
-       for _, vote := range votes {
-               // init Votes from each vote
-               snap.Votes[vote.Voter] = vote
-               // init Tally
-               _, ok := snap.Tally[vote.Candidate]
-               if !ok {
-                       snap.Tally[vote.Candidate] = 0
-               }
-               snap.Tally[vote.Candidate] += vote.Stake
-               // init Voters
-               snap.Voters[vote.Voter] = 0 // block height is 0 , vote in genesis block
-               // init Candidates
-               snap.Candidates[vote.Voter] = candidateStateNormal
-       }
-
-       for i := 0; i < int(config.MaxSignerCount); i++ {
-               snap.Signers = append(snap.Signers, &config.SelfVoteSigners[i%len(config.SelfVoteSigners)])
-       }
-
-       return snap
-}
-
-// loadSnapshot loads an existing snapshot from the database.
-func loadSnapshot(config *config.DposConfig, sigcache *lru.ARCCache, store protocol.Store, hash bc.Hash) (*Snapshot, error) {
-       data, err := store.Get(&hash)
-       if err != nil {
-               return nil, err
-       }
-       snap := new(Snapshot)
-       if err := json.Unmarshal(data, snap); err != nil {
-               return nil, err
-       }
-       snap.config = config
-       snap.sigcache = sigcache
-       return snap, nil
-}
-
-// store inserts the snapshot into the database.
-func (s *Snapshot) store(store protocol.Store) error {
-       data, err := json.Marshal(s)
-       if err != nil {
-               return err
-       }
-       return store.Set(&s.Hash, data)
-}
-
-// copy creates a deep copy of the snapshot, though not the individual votes.
-func (s *Snapshot) copy() *Snapshot {
-       cpy := &Snapshot{
-               config:          s.config,
-               sigcache:        s.sigcache,
-               LCRS:            s.LCRS,
-               Period:          s.Period,
-               Number:          s.Number,
-               ConfirmedNumber: s.ConfirmedNumber,
-               Hash:            s.Hash,
-               HistoryHash:     make([]bc.Hash, len(s.HistoryHash)),
-
-               Signers:       make([]*string, len(s.Signers)),
-               Votes:         make(map[string]*Vote),
-               Tally:         make(map[string]uint64),
-               Voters:        make(map[string]uint64),
-               Candidates:    make(map[string]uint64),
-               Punished:      make(map[string]uint64),
-               Proposals:     make(map[bc.Hash]*Proposal),
-               Confirmations: make(map[uint64][]string),
-
-               HeaderTime:    s.HeaderTime,
-               LoopStartTime: s.LoopStartTime,
-       }
-       copy(cpy.HistoryHash, s.HistoryHash)
-       copy(cpy.Signers, s.Signers)
-       for voter, vote := range s.Votes {
-               cpy.Votes[voter] = &Vote{
-                       Voter:     vote.Voter,
-                       Candidate: vote.Candidate,
-                       Stake:     vote.Stake,
-               }
-       }
-       for candidate, tally := range s.Tally {
-               cpy.Tally[candidate] = tally
-       }
-       for voter, number := range s.Voters {
-               cpy.Voters[voter] = number
-       }
-       for candidate, state := range s.Candidates {
-               cpy.Candidates[candidate] = state
-       }
-       for signer, cnt := range s.Punished {
-               cpy.Punished[signer] = cnt
-       }
-       for blockNumber, confirmers := range s.Confirmations {
-               cpy.Confirmations[blockNumber] = make([]string, len(confirmers))
-               copy(cpy.Confirmations[blockNumber], confirmers)
-       }
-       for txHash, proposal := range s.Proposals {
-               cpy.Proposals[txHash] = proposal.copy()
-       }
-
-       return cpy
-}
-
-// apply creates a new authorization snapshot by applying the given headers to
-// the original one.
-func (s *Snapshot) apply(headers []*types.BlockHeader) (*Snapshot, error) {
-       // Allow passing in no headers for cleaner code
-       if len(headers) == 0 {
-               return s, nil
-       }
-       // Sanity check that the headers can be applied
-       for i := 0; i < len(headers)-1; i++ {
-               if headers[i+1].Height != headers[i].Height+1 {
-                       return nil, errInvalidVotingChain
-               }
-       }
-       if headers[0].Height != s.Number+1 {
-               return nil, errInvalidVotingChain
-       }
-       // Iterate through the headers and create a new snapshot
-       snap := s.copy()
-       for _, header := range headers {
-
-               // Resolve the authorization key and check against signers
-               coinbase, err := ecrecover(header, s.sigcache, nil)
-               if err != nil {
-                       return nil, err
-               }
-
-               headerExtra := HeaderExtra{}
-               if err := json.Unmarshal(header.Extra[extraVanity:len(header.Extra)-extraSeal], &headerExtra); err != nil {
-                       return nil, err
-               }
-
-               snap.HeaderTime = header.Timestamp
-               snap.LoopStartTime = headerExtra.LoopStartTime
-               snap.Signers = nil
-               for i := range headerExtra.SignerQueue {
-                       snap.Signers = append(snap.Signers, &headerExtra.SignerQueue[i])
-               }
-
-               snap.ConfirmedNumber = headerExtra.ConfirmedBlockNumber
-
-               if len(snap.HistoryHash) >= int(s.config.MaxSignerCount)*2 {
-                       snap.HistoryHash = snap.HistoryHash[1 : int(s.config.MaxSignerCount)*2]
-               }
-
-               snap.HistoryHash = append(snap.HistoryHash, header.Hash())
-
-               // deal the new confirmation in this block
-               snap.updateSnapshotByConfirmations(headerExtra.CurrentBlockConfirmations)
-
-               // deal the new vote from voter
-               snap.updateSnapshotByVotes(headerExtra.CurrentBlockVotes, header.Height)
-
-               // deal the snap related with punished
-               snap.updateSnapshotForPunish(headerExtra.SignerMissing, header.Height, coinbase)
-
-               // deal proposals
-               snap.updateSnapshotByProposals(headerExtra.CurrentBlockProposals, header.Height)
-
-               // deal declares
-               snap.updateSnapshotByDeclares(headerExtra.CurrentBlockDeclares, header.Height)
-
-               // calculate proposal result
-               snap.calculateProposalResult(header.Height)
-
-               // check the len of candidate if not candidateNeedPD
-               if !candidateNeedPD && (snap.Number+1)%(snap.config.MaxSignerCount*snap.LCRS) == 0 && len(snap.Candidates) > candidateMaxLen {
-                       snap.removeExtraCandidate()
-               }
-
-       }
-       snap.Number += uint64(len(headers))
-       snap.Hash = headers[len(headers)-1].Hash()
-       snap.updateSnapshotForExpired()
-       err := snap.verifyTallyCnt()
-       if err != nil {
-               return nil, err
-       }
-       return snap, nil
-}
-
-func (s *Snapshot) removeExtraCandidate() {
-       // remove minimum tickets tally beyond candidateMaxLen
-       tallySlice := s.buildTallySlice()
-       sort.Sort(TallySlice(tallySlice))
-       if len(tallySlice) > candidateMaxLen {
-               removeNeedTally := tallySlice[candidateMaxLen:]
-               for _, tallySlice := range removeNeedTally {
-                       delete(s.Candidates, tallySlice.addr)
-               }
-       }
-}
-
-func (s *Snapshot) verifyTallyCnt() error {
-
-       tallyTarget := make(map[string]uint64)
-       for _, v := range s.Votes {
-               if _, ok := tallyTarget[v.Candidate]; ok {
-                       tallyTarget[v.Candidate] = tallyTarget[v.Candidate] + v.Stake
-               } else {
-                       tallyTarget[v.Candidate] = v.Stake
-               }
-       }
-       for address, tally := range s.Tally {
-               if targetTally, ok := tallyTarget[address]; ok && targetTally == tally {
-                       continue
-               } else {
-                       return errIncorrectTallyCount
-               }
-       }
-
-       return nil
-}
-
-func (s *Snapshot) updateSnapshotByDeclares(declares []Declare, headerHeight uint64) {
-       for _, declare := range declares {
-               if proposal, ok := s.Proposals[declare.ProposalHash]; ok {
-                       // check the proposal enable status and valid block number
-                       if proposal.ReceivedNumber+proposal.ValidationLoopCnt*s.config.MaxSignerCount < headerHeight || !s.isCandidate(declare.Declarer) {
-                               continue
-                       }
-                       // check if this signer already declare on this proposal
-                       alreadyDeclare := false
-                       for _, v := range proposal.Declares {
-                               if v.Declarer == declare.Declarer {
-                                       // this declarer already declare for this proposal
-                                       alreadyDeclare = true
-                                       break
-                               }
-                       }
-                       if alreadyDeclare {
-                               continue
-                       }
-                       // add declare to proposal
-                       s.Proposals[declare.ProposalHash].Declares = append(s.Proposals[declare.ProposalHash].Declares,
-                               &Declare{declare.ProposalHash, declare.Declarer, declare.Decision})
-
-               }
-       }
-}
-
-func (s *Snapshot) calculateProposalResult(headerHeight uint64) {
-
-       for hashKey, proposal := range s.Proposals {
-               // the result will be calculate at receiverdNumber + vlcnt + 1
-               if proposal.ReceivedNumber+proposal.ValidationLoopCnt*s.config.MaxSignerCount+1 == headerHeight {
-                       // calculate the current stake of this proposal
-                       judegmentStake := big.NewInt(0)
-                       for _, tally := range s.Tally {
-                               judegmentStake.Add(judegmentStake, new(big.Int).SetUint64(tally))
-                       }
-                       judegmentStake.Mul(judegmentStake, big.NewInt(2))
-                       judegmentStake.Div(judegmentStake, big.NewInt(3))
-                       // calculate declare stake
-                       yesDeclareStake := big.NewInt(0)
-                       for _, declare := range proposal.Declares {
-                               if declare.Decision {
-                                       if _, ok := s.Tally[declare.Declarer]; ok {
-                                               yesDeclareStake.Add(yesDeclareStake, new(big.Int).SetUint64(s.Tally[declare.Declarer]))
-                                       }
-                               }
-                       }
-                       if yesDeclareStake.Cmp(judegmentStake) > 0 {
-                               // process add candidate
-                               switch proposal.ProposalType {
-                               case proposalTypeCandidateAdd:
-                                       if candidateNeedPD {
-                                               s.Candidates[s.Proposals[hashKey].Candidate] = candidateStateNormal
-                                       }
-                               case proposalTypeCandidateRemove:
-                                       if _, ok := s.Candidates[proposal.Candidate]; ok && candidateNeedPD {
-                                               delete(s.Candidates, proposal.Candidate)
-                                       }
-                               case proposalTypeMinerRewardDistributionModify:
-                                       minerRewardPerThousand = s.Proposals[hashKey].MinerRewardPerThousand
-                               }
-                       }
-               }
-       }
-}
-
-func (s *Snapshot) updateSnapshotByProposals(proposals []Proposal, headerHeight uint64) {
-       for _, proposal := range proposals {
-               proposal.ReceivedNumber = headerHeight
-               s.Proposals[proposal.Hash] = &proposal
-       }
-}
-
-func (s *Snapshot) updateSnapshotForExpired() {
-       // deal the expired vote
-       var expiredVotes []*Vote
-       for voterAddress, voteNumber := range s.Voters {
-               if s.Number-voteNumber > s.config.Epoch {
-                       // clear the vote
-                       if expiredVote, ok := s.Votes[voterAddress]; ok {
-                               expiredVotes = append(expiredVotes, expiredVote)
-                       }
-               }
-       }
-       // remove expiredVotes only enough voters left
-       if uint64(len(s.Voters)-len(expiredVotes)) >= s.config.MaxSignerCount {
-               for _, expiredVote := range expiredVotes {
-                       s.Tally[expiredVote.Candidate] -= expiredVote.Stake
-                       // TODO
-                       if s.Tally[expiredVote.Candidate] == 0 {
-                               delete(s.Tally, expiredVote.Candidate)
-                       }
-                       delete(s.Votes, expiredVote.Voter)
-                       delete(s.Voters, expiredVote.Voter)
-               }
-       }
-
-       // deal the expired confirmation
-       for blockNumber := range s.Confirmations {
-               if s.Number-blockNumber > s.config.MaxSignerCount {
-                       delete(s.Confirmations, blockNumber)
-               }
-       }
-
-       // TODO
-       // remove 0 stake tally
-
-       for address, tally := range s.Tally {
-               if tally <= 0 && uint64(len(s.Tally)) > s.config.MaxSignerCount {
-                       delete(s.Tally, address)
-               }
-       }
-}
-
-func (s *Snapshot) updateSnapshotByConfirmations(confirmations []Confirmation) {
-       for _, confirmation := range confirmations {
-               _, ok := s.Confirmations[confirmation.BlockNumber]
-               if !ok {
-                       s.Confirmations[confirmation.BlockNumber] = []string{}
-               }
-               addConfirmation := true
-               for _, address := range s.Confirmations[confirmation.BlockNumber] {
-                       if confirmation.Signer == address {
-                               addConfirmation = false
-                               break
-                       }
-               }
-               if addConfirmation == true {
-                       s.Confirmations[confirmation.BlockNumber] = append(s.Confirmations[confirmation.BlockNumber], confirmation.Signer)
-               }
-       }
-}
-
-func (s *Snapshot) updateSnapshotByVotes(votes []Vote, headerHeight uint64) {
-       for _, vote := range votes {
-               // update Votes, Tally, Voters data
-               if lastVote, ok := s.Votes[vote.Voter]; ok {
-                       s.Tally[lastVote.Candidate] = s.Tally[lastVote.Candidate] - lastVote.Stake
-               }
-               if _, ok := s.Tally[vote.Candidate]; ok {
-                       s.Tally[vote.Candidate] = s.Tally[vote.Candidate] + vote.Stake
-               } else {
-                       s.Tally[vote.Candidate] = vote.Stake
-                       if !candidateNeedPD {
-                               s.Candidates[vote.Candidate] = candidateStateNormal
-                       }
-               }
-               s.Votes[vote.Voter] = &Vote{vote.Voter, vote.Candidate, vote.Stake}
-               s.Voters[vote.Voter] = headerHeight
-       }
-}
-
-func (s *Snapshot) updateSnapshotByMPVotes(votes []Vote) {
-       for _, txVote := range votes {
-               if lastVote, ok := s.Votes[txVote.Voter]; ok {
-                       s.Tally[lastVote.Candidate] = s.Tally[lastVote.Candidate] - lastVote.Stake
-                       s.Tally[lastVote.Candidate] = s.Tally[lastVote.Candidate] + txVote.Stake
-                       s.Votes[txVote.Voter] = &Vote{Voter: txVote.Voter, Candidate: lastVote.Candidate, Stake: txVote.Stake}
-               }
-       }
-}
-
-func (s *Snapshot) updateSnapshotForPunish(signerMissing []string, headerNumber uint64, coinbase string) {
-       // punish the missing signer
-       for _, signerMissing := range signerMissing {
-               if _, ok := s.Punished[signerMissing]; ok {
-                       s.Punished[signerMissing] += missingPublishCredit
-               } else {
-                       s.Punished[signerMissing] = missingPublishCredit
-               }
-       }
-       // reduce the punish of sign signer
-       if _, ok := s.Punished[coinbase]; ok {
-
-               if s.Punished[coinbase] > signRewardCredit {
-                       s.Punished[coinbase] -= signRewardCredit
-               } else {
-                       delete(s.Punished, coinbase)
-               }
-       }
-       // reduce the punish for all punished
-       for signerEach := range s.Punished {
-               if s.Punished[signerEach] > autoRewardCredit {
-                       s.Punished[signerEach] -= autoRewardCredit
-               } else {
-                       delete(s.Punished, signerEach)
-               }
-       }
-}
-
-// inturn returns if a signer at a given block height is in-turn or not.
-func (s *Snapshot) inturn(signer string, headerTime uint64) bool {
-       // if all node stop more than period of one loop
-       loopIndex := int((headerTime-s.LoopStartTime)/s.config.Period) % len(s.Signers)
-       if loopIndex >= len(s.Signers) {
-               return false
-       } else if *s.Signers[loopIndex] != signer {
-               return false
-
-       }
-       return true
-}
-
-// check if address belong to voter
-func (s *Snapshot) isVoter(address string) bool {
-       if _, ok := s.Voters[address]; ok {
-               return true
-       }
-       return false
-}
-
-// check if address belong to candidate
-func (s *Snapshot) isCandidate(address string) bool {
-       if _, ok := s.Candidates[address]; ok {
-               return true
-       }
-       return false
-}
-
-// get last block number meet the confirm condition
-func (s *Snapshot) getLastConfirmedBlockNumber(confirmations []Confirmation) *big.Int {
-       cpyConfirmations := make(map[uint64][]string)
-       for blockNumber, confirmers := range s.Confirmations {
-               cpyConfirmations[blockNumber] = make([]string, len(confirmers))
-               copy(cpyConfirmations[blockNumber], confirmers)
-       }
-       // update confirmation into snapshot
-       for _, confirmation := range confirmations {
-               _, ok := cpyConfirmations[confirmation.BlockNumber]
-               if !ok {
-                       cpyConfirmations[confirmation.BlockNumber] = []string{}
-               }
-               addConfirmation := true
-               for _, address := range cpyConfirmations[confirmation.BlockNumber] {
-                       if confirmation.Signer == address {
-                               addConfirmation = false
-                               break
-                       }
-               }
-               if addConfirmation == true {
-                       cpyConfirmations[confirmation.BlockNumber] = append(cpyConfirmations[confirmation.BlockNumber], confirmation.Signer)
-               }
-       }
-
-       i := s.Number
-       for ; i > s.Number-s.config.MaxSignerCount*2/3+1; i-- {
-               if confirmers, ok := cpyConfirmations[i]; ok {
-                       if len(confirmers) > int(s.config.MaxSignerCount*2/3) {
-                               return big.NewInt(int64(i))
-                       }
-               }
-       }
-       return big.NewInt(int64(i))
-}
similarity index 51%
rename from consensus/consensus/vote.go
rename to consensus/consensus/dpos/vote.go
index 65ce001..7daa793 100644 (file)
@@ -1,14 +1,20 @@
-package consensus
+package dpos
 
 import (
        "encoding/json"
+       "fmt"
+       "io/ioutil"
        "os"
        "path/filepath"
+       "sort"
+       "strings"
        "sync"
 
-       "github.com/vapor/config"
+       cmn "github.com/tendermint/tmlibs/common"
 
+       "github.com/vapor/config"
        "github.com/vapor/consensus"
+       engine "github.com/vapor/consensus/consensus"
        "github.com/vapor/protocol/bc"
 )
 
@@ -23,11 +29,6 @@ const (
        ForgerFile = "forger.data"
 )
 
-type AddressBalance struct {
-       Address string
-       Balance int64
-}
-
 type Vote struct {
        DelegateVoters            map[string]map[string]bool
        VoterDelegates            map[string]map[string]bool
@@ -54,11 +55,37 @@ type Vote struct {
        oldBlockHash   bc.Hash
 }
 
-var DposVote = Vote{}
+/*
+var DposVote = Vote{
+       DelegateVoters:        make(map[string]map[string]bool),
+       VoterDelegates:        make(map[string]map[string]bool),
+       DelegateName:          make(map[string]string),
+       NameDelegate:          make(map[string]string),
+       HashHeightInvalidVote: make(map[bc.Hash]uint64),
+       AddressBalances:       make(map[string]uint64),
+       DelegateMultiaddress:  make(map[string]uint64),
+}
+*/
+func newVote(blockHeight uint64, blockHash bc.Hash) (*Vote, error) {
+       vote := &Vote{
+               DelegateVoters:        make(map[string]map[string]bool),
+               VoterDelegates:        make(map[string]map[string]bool),
+               DelegateName:          make(map[string]string),
+               NameDelegate:          make(map[string]string),
+               HashHeightInvalidVote: make(map[bc.Hash]uint64),
+               AddressBalances:       make(map[string]uint64),
+               DelegateMultiaddress:  make(map[string]uint64),
+       }
 
-func (v *Vote) new(blockHeight uint64, blockHash bc.Hash) error {
-       //DefaultDataDir
-       v.filePath = filepath.Join(config.DefaultDataDir(), "dpos")
+       if err := vote.New(blockHeight, blockHash); err != nil {
+               return nil, err
+       }
+
+       return vote, nil
+}
+
+func (v *Vote) New(blockHeight uint64, blockHash bc.Hash) error {
+       v.filePath = filepath.Join(config.CommonConfig.RootDir, "dpos")
        v.delegateFileName = filepath.Join(v.filePath, DelegateFile)
        v.balanceFileName = filepath.Join(v.filePath, BalanceFile)
        v.controlFileName = filepath.Join(v.filePath, ControlFile)
@@ -66,12 +93,8 @@ func (v *Vote) new(blockHeight uint64, blockHash bc.Hash) error {
        v.delegateMultiaddressName = filepath.Join(v.filePath, DelegateMultiAddressFile)
        v.forgerFileName = filepath.Join(v.filePath, ForgerFile)
        if blockHeight == 0 {
-               if _, err := os.Stat(v.filePath); os.IsNotExist(err) {
-                       err := os.MkdirAll(v.filePath, 0700)
-                       if err != nil {
-                               //return fmt.Errorf("Could not create directory %v. %v", dir, err)
-                               return err
-                       }
+               if err := cmn.EnsureDir(v.filePath, 0700); err != nil {
+                       return err
                }
        } else {
                if err := v.load(blockHeight, blockHash); err != nil {
@@ -84,16 +107,15 @@ func (v *Vote) new(blockHeight uint64, blockHash bc.Hash) error {
 func (v *Vote) ProcessRegister(delegateAddress string, delegateName string, hash bc.Hash, height uint64) bool {
        v.lockRegister.Lock()
        defer v.lockRegister.Unlock()
-       if _, ok := v.DelegateName[delegateAddress]; !ok {
+
+       if _, ok := v.DelegateName[delegateAddress]; ok {
                v.AddInvalidVote(hash, height)
                return false
        }
-
-       if _, ok := v.NameDelegate[delegateName]; !ok {
+       if _, ok := v.NameDelegate[delegateName]; ok {
                v.AddInvalidVote(hash, height)
                return false
        }
-
        v.DelegateName[delegateAddress] = delegateName
        v.NameDelegate[delegateName] = delegateAddress
        return true
@@ -124,14 +146,23 @@ func (v *Vote) ProcessVote(voterAddress string, delegates []string, hash bc.Hash
                                v.AddInvalidVote(hash, height)
                                return false
                        } else {
-                               v.DelegateVoters[delegate][voterAddress] = true
+                               voters[voterAddress] = true
+                               v.DelegateVoters[delegate] = voters
                        }
                } else {
-                       v.DelegateVoters[delegate][voterAddress] = true
+                       voters := make(map[string]bool)
+                       voters[voterAddress] = true
+                       v.DelegateVoters[delegate] = voters
+               }
+               if dg, ok := v.VoterDelegates[voterAddress]; ok {
+                       dg[delegate] = true
+                       v.VoterDelegates[voterAddress] = dg
+               } else {
+                       dg := make(map[string]bool)
+                       dg[delegate] = true
+                       v.VoterDelegates[voterAddress] = dg
                }
-               v.VoterDelegates[voterAddress][delegate] = true
        }
-
        return true
 }
 
@@ -169,12 +200,6 @@ func (v *Vote) ProcessCancelVote(voterAddress string, delegates []string, hash b
        return true
 }
 
-func (v *Vote) AddInvalidVote(hash bc.Hash, height uint64) {
-       v.lockHashHeightInvalidVote.Lock()
-       defer v.lockHashHeightInvalidVote.Unlock()
-       v.HashHeightInvalidVote[hash] = height
-}
-
 func (v *Vote) load(blockHeight uint64, blockHash bc.Hash) error {
        if err := v.repairFile(blockHeight, blockHash); err != nil {
                return err
@@ -197,6 +222,7 @@ func (v *Vote) Store(blockHeight uint64, blockHash bc.Hash) error {
        }
 
        if err := v.WriteControlFile(blockHeight, blockHash, v.controlFileName+"-temp"); err != nil {
+               v.Delete(blockHash)
                return err
        }
 
@@ -206,13 +232,13 @@ func (v *Vote) Store(blockHeight uint64, blockHash bc.Hash) error {
        )
 
        if err := v.ReadControlFile(&blockHeightTemp, &blockHashTemp, v.controlFileName); err != nil {
-               return err
+               os.Rename(v.controlFileName, v.controlFileName+"-old")
+               os.Rename(v.controlFileName+"-temp", v.controlFileName)
+               os.Remove(v.controlFileName + "-old")
+       } else {
+               v.Delete(blockHashTemp)
        }
 
-       os.Rename(v.controlFileName, v.controlFileName+"-old")
-       os.Rename(v.controlFileName+"-temp", v.controlFileName)
-       os.Remove(v.controlFileName + "-old")
-
        return nil
 }
 
@@ -237,7 +263,6 @@ func (v *Vote) Write(blockHash bc.Hash) error {
                AddressBalances:       v.AddressBalances,
                DelegateMultiaddress:  v.DelegateMultiaddress,
        }
-
        fileObj, err := os.OpenFile(v.forgerFileName+"-"+blockHash.String(), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
        if err != nil {
                return err
@@ -263,17 +288,11 @@ func (v *Vote) read() error {
                return err
        }
 
-       fileObj, err := os.OpenFile(v.forgerFileName+"-"+v.oldBlockHash.String(), os.O_RDONLY, 0644)
+       data, err := ioutil.ReadFile(v.forgerFileName + "-" + v.oldBlockHash.String())
        if err != nil {
                return err
        }
 
-       var data []byte
-
-       if _, err = fileObj.Read(data); err != nil {
-               return err
-       }
-
        f := &forger{}
 
        if err = json.Unmarshal(data, f); err != nil {
@@ -292,33 +311,115 @@ func (v *Vote) read() error {
 }
 
 func (v *Vote) repairFile(blockHeight uint64, blockHash bc.Hash) error {
-       return nil
+
+       cmn.EnsureDir(v.filePath, 0700)
+
+       fileName := v.controlFileName + "-temp"
+
+       var (
+               blockHeightTmp uint64
+               blockHashTmp   bc.Hash
+       )
+
+       if cmn.FileExists(fileName) {
+               if err := v.ReadControlFile(&blockHeightTmp, &blockHashTmp, fileName); err != nil {
+                       return err
+               }
+               if cmn.FileExists(v.forgerFileName + "-" + blockHashTmp.String()) {
+                       os.Rename(fileName, v.controlFileName)
+                       return nil
+               }
+               os.Remove(fileName)
+       }
+
+       fileName = v.controlFileName + "-old"
+
+       if cmn.FileExists(fileName) {
+               if err := v.ReadControlFile(&blockHeightTmp, &blockHashTmp, fileName); err != nil {
+                       return err
+               }
+               if cmn.FileExists(v.forgerFileName + "-" + blockHashTmp.String()) {
+                       os.Rename(fileName, v.controlFileName)
+                       return nil
+               }
+               os.Remove(fileName)
+       }
+
+       fileName = v.controlFileName
+       if cmn.FileExists(fileName) {
+               if err := v.ReadControlFile(&blockHeightTmp, &blockHashTmp, fileName); err != nil {
+                       return err
+               }
+               if cmn.FileExists(v.forgerFileName + "-" + blockHashTmp.String()) {
+                       return nil
+               }
+       }
+
+       return fmt.Errorf("repairFile fail in %d height", blockHeightTmp)
 }
 
 func (v *Vote) GetTopDelegateInfo(minHoldBalance uint64, delegateNum uint64) []Delegate {
+       v.lockVoter.Lock()
+       defer v.lockVoter.Unlock()
+
        var result []Delegate
+       for k, value := range v.DelegateVoters {
+               votes := uint64(0)
+               for address := range value {
+                       votes += v.GetAddressBalance(address)
+               }
+               if v.GetAddressBalance(k) >= minHoldBalance {
+                       result = append(result, Delegate{k, votes})
+               }
+       }
+       sort.Sort(DelegateWrapper{result, func(p, q *Delegate) bool {
+               if p.Votes < q.Votes {
+                       return false
+               } else if p.Votes > q.Votes {
+                       return true
+               } else {
+                       if strings.Compare(p.DelegateAddress, p.DelegateAddress) >= 0 {
+                               return false
+                       }
+               }
+               return true
+       }})
+
+       for k := range v.DelegateName {
+               if uint64(len(result)) >= delegateNum {
+                       break
+               }
+               if v.GetAddressBalance(k) < consensus.MinHoldBalance {
+                       continue
+               }
+               if _, ok := v.DelegateVoters[k]; !ok {
+                       result = append(result, Delegate{k, 0})
+               }
+       }
 
+       result = result[:delegateNum]
        return result
 }
 
+func (v *Vote) GetAddressBalance(address string) uint64 {
+
+       if votes, ok := v.AddressBalances[address]; ok {
+               return votes
+       }
+
+       return 0
+}
+
 type control struct {
        BlockHeight uint64  `json:"block_height"`
        BlockHash   bc.Hash `json:"block_hash"`
 }
 
 func (v *Vote) ReadControlFile(blockHeight *uint64, blockHash *bc.Hash, fileName string) error {
-
-       fileObj, err := os.OpenFile(fileName, os.O_RDONLY, 0644)
+       data, err := ioutil.ReadFile(fileName)
        if err != nil {
                return err
        }
-
-       var data []byte
-
-       if _, err = fileObj.Read(data); err != nil {
-               return err
-       }
-
        c := &control{}
 
        if err = json.Unmarshal(data, c); err != nil {
@@ -356,6 +457,151 @@ func (v *Vote) WriteControlFile(blockHeight uint64, blockHash bc.Hash, fileName
        return nil
 }
 
-func (v *Vote) UpdateAddressBalance(AddressBalance []AddressBalance) {
+func (v *Vote) UpdateAddressBalance(addressBalance []engine.AddressBalance) {
+       v.lockVoter.Lock()
+       defer v.lockVoter.Unlock()
+
+       mapBalance := make(map[string]int64)
+
+       for _, value := range addressBalance {
+               if value.Balance == 0 {
+                       continue
+               }
+               mapBalance[value.Address] += value.Balance
+       }
+       for addr, balance := range mapBalance {
+               v.updateAddressBalance(addr, balance)
+       }
+}
+
+func (v *Vote) updateAddressBalance(address string, value int64) {
+       if val, ok := v.AddressBalances[address]; ok {
+               banlance := int64(val) + value
+               if banlance < 0 {
+                       cmn.Exit("The balance was negative")
+               }
+               if banlance == 0 {
+                       delete(v.AddressBalances, address)
+               } else {
+                       v.AddressBalances[address] = uint64(banlance)
+               }
+       } else {
+               if value < 0 {
+                       cmn.Exit("The balance was negative")
+               }
+               if value > 0 {
+                       v.AddressBalances[address] = uint64(value)
+               }
+       }
+}
+
+func (v *Vote) AddInvalidVote(hash bc.Hash, height uint64) {
+       v.lockHashHeightInvalidVote.Lock()
+       defer v.lockHashHeightInvalidVote.Unlock()
+       v.HashHeightInvalidVote[hash] = height
+}
+func (v *Vote) DeleteInvalidVote(height uint64) {
+       v.lockHashHeightInvalidVote.Lock()
+       defer v.lockHashHeightInvalidVote.Unlock()
+       for k, value := range v.HashHeightInvalidVote {
+               if value <= height {
+                       delete(v.HashHeightInvalidVote, k)
+               }
+       }
+}
+
+func (v *Vote) GetOldBlockHeight() uint64 {
+       return v.oldBlockHeight
+}
+
+func (v *Vote) GetOldBlockHash() bc.Hash {
+       return v.oldBlockHash
+}
+
+func (v *Vote) GetDelegate(name string) string {
+       v.lockVoter.Lock()
+       defer v.lockVoter.Unlock()
+
+       if delegate, ok := v.NameDelegate[name]; ok {
+               return delegate
+       }
+       return ""
+}
+
+func (v *Vote) GetDelegateName(address string) string {
+       v.lockVoter.Lock()
+       defer v.lockVoter.Unlock()
+       if name, ok := v.DelegateName[address]; ok {
+               return name
+       }
+       return ""
+}
+
+func (v *Vote) HaveVote(voter string, delegate string) bool {
+       v.lockVoter.Lock()
+       defer v.lockVoter.Unlock()
+
+       if voters, ok := v.DelegateVoters[delegate]; ok {
+               if _, ok := voters[voter]; ok {
+                       return true
+               }
+       }
+
+       return false
+}
 
+func (v *Vote) HaveDelegate(name string, delegate string) bool {
+       v.lockVoter.Lock()
+       defer v.lockVoter.Unlock()
+
+       if n, ok := v.DelegateName[delegate]; ok {
+               if n == name {
+                       return true
+               }
+       }
+
+       return false
+}
+
+func (v *Vote) GetVotedDelegates(voter string) []string {
+       v.lockVoter.Lock()
+       defer v.lockVoter.Unlock()
+       var results []string
+       if delegates, ok := v.VoterDelegates[voter]; ok {
+               for delegate, _ := range delegates {
+                       results = append(results, delegate)
+               }
+       }
+       return results
+}
+
+func (v *Vote) ListDelegates() map[string]string {
+       v.lockVoter.Lock()
+       defer v.lockVoter.Unlock()
+       return v.NameDelegate
+}
+
+func (v *Vote) GetDelegateVotes(delegate string) uint64 {
+       votes := uint64(0)
+       if voters, ok := v.DelegateVoters[delegate]; ok {
+               for voter := range voters {
+                       votes += v.GetAddressBalance(voter)
+               }
+       }
+       return votes
+}
+
+func (v *Vote) GetDelegateVoters(delegate string) []string {
+       v.lockVoter.Lock()
+       defer v.lockVoter.Unlock()
+
+       var result []string
+
+       if voters, ok := v.DelegateVoters[delegate]; ok {
+               for voter := range voters {
+                       result = append(result, voter)
+               }
+       }
+
+       return result
 }
similarity index 71%
rename from consensus/consensus/vote_type.go
rename to consensus/consensus/dpos/vote_type.go
index d25a0aa..1dec1fb 100644 (file)
@@ -1,8 +1,9 @@
-package consensus
+package dpos
 
 import (
        "github.com/vapor/crypto/ed25519/chainkd"
        chainjson "github.com/vapor/encoding/json"
+       "github.com/vapor/protocol/vm"
 )
 
 // serflag variables for input types.
@@ -17,11 +18,16 @@ type TypedData interface {
        DataType() uint8
 }
 
+type DposMsg struct {
+       Type vm.Op
+       Data []byte
+}
+
 // DELEGATE_IDS PUBKEY SIG(block.time)
 type DelegateInfoList struct {
-       Delegate DelegateInfo
-       Xpub     chainkd.XPub
-       SigTime  []chainjson.HexBytes `json:"sig_time"`
+       Delegate DelegateInfo       `json:"delegate"`
+       Xpub     chainkd.XPub       `json:"xpub"`
+       SigTime  chainjson.HexBytes `json:"sig_time"`
 }
 
 func (d *DelegateInfoList) DataType() uint8 { return DelegateInfoType }
@@ -33,13 +39,13 @@ type RegisterForgerData struct {
 func (d *RegisterForgerData) DataType() uint8 { return RegisterType }
 
 type VoteForgerData struct {
-       Forgers []string `json:"Forgers"`
+       Forgers []string `json:"forgers"`
 }
 
 func (d *VoteForgerData) DataType() uint8 { return VoteType }
 
 type CancelVoteForgerData struct {
-       Forgers []string `json:"Forgers"`
+       Forgers []string `json:"forgers"`
 }
 
 func (d *CancelVoteForgerData) DataType() uint8 { return CancelVoteType }
diff --git a/consensus/consensus/errors.go b/consensus/consensus/errors.go
deleted file mode 100644 (file)
index b9cb359..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-package consensus
-
-import "errors"
-
-var (
-       // ErrUnknownAncestor is returned when validating a block requires an ancestor
-       // that is unknown.
-       ErrUnknownAncestor = errors.New("unknown ancestor")
-
-       // ErrPrunedAncestor is returned when validating a block requires an ancestor
-       // that is known, but the state of which is not available.
-       ErrPrunedAncestor = errors.New("pruned ancestor")
-
-       // ErrFutureBlock is returned when a block's timestamp is in the future according
-       // to the current node.
-       ErrFutureBlock = errors.New("block in the future")
-
-       // ErrInvalidNumber is returned if a block's number doesn't equal it's parent's
-       // plus one.
-       ErrInvalidNumber = errors.New("invalid block number")
-)
index 8db576d..81af2f1 100644 (file)
@@ -72,7 +72,7 @@ const (
        VoteForgerFee       = 1000000 // 0.0.1 * Coin
        CancelVoteForgerFee = 1000000 // 0.0.1 * Coin
        MaxNumberOfVotes    = 51
-       MinHoldBalance      = 500000000000
+       MinHoldBalance      = 50000000000
 )
 
 func MoneyRange(nValue uint64) bool { return nValue >= 0 && nValue <= MaxMoney }
index ddad037..a126447 100644 (file)
@@ -18,14 +18,14 @@ func TestLoadBlockIndex(t *testing.T) {
        testDB := dbm.NewDB("testdb", "leveldb", "temp")
        store := NewStore(testDB)
        config.CommonConfig = config.DefaultConfig()
-       config.CommonConfig.Consensus.Dpos.SelfVoteSigners = append(config.CommonConfig.Consensus.Dpos.SelfVoteSigners, "vsm1qkm743xmgnvh84pmjchq2s4tnfpgu9ae2f9slep")
-       config.CommonConfig.Consensus.Dpos.XPrv = "a8e281b615809046698fb0b0f2804a36d824d48fa443350f10f1b80649d39e5f1e85cf9855548915e36137345910606cbc8e7dd8497c831dce899ee6ac112445"
-       for _, v := range config.CommonConfig.Consensus.Dpos.SelfVoteSigners {
+       config.CommonConfig.Consensus.SelfVoteSigners = append(config.CommonConfig.Consensus.SelfVoteSigners, "vsm1qkm743xmgnvh84pmjchq2s4tnfpgu9ae2f9slep")
+       config.CommonConfig.Consensus.XPrv = "a8e281b615809046698fb0b0f2804a36d824d48fa443350f10f1b80649d39e5f1e85cf9855548915e36137345910606cbc8e7dd8497c831dce899ee6ac112445"
+       for _, v := range config.CommonConfig.Consensus.SelfVoteSigners {
                address, err := common.DecodeAddress(v, &consensus.SoloNetParams)
                if err != nil {
                        t.Fatal(err)
                }
-               config.CommonConfig.Consensus.Dpos.Signers = append(config.CommonConfig.Consensus.Dpos.Signers, address)
+               config.CommonConfig.Consensus.Signers = append(config.CommonConfig.Consensus.Signers, address)
        }
        block := config.GenesisBlock()
        txStatus := bc.NewTransactionStatus()
@@ -82,14 +82,14 @@ func TestLoadBlockIndexBestHeight(t *testing.T) {
        store := NewStore(testDB)
        var savedBlocks []types.Block
        config.CommonConfig = config.DefaultConfig()
-       config.CommonConfig.Consensus.Dpos.SelfVoteSigners = append(config.CommonConfig.Consensus.Dpos.SelfVoteSigners, "vsm1qkm743xmgnvh84pmjchq2s4tnfpgu9ae2f9slep")
-       config.CommonConfig.Consensus.Dpos.XPrv = "a8e281b615809046698fb0b0f2804a36d824d48fa443350f10f1b80649d39e5f1e85cf9855548915e36137345910606cbc8e7dd8497c831dce899ee6ac112445"
-       for _, v := range config.CommonConfig.Consensus.Dpos.SelfVoteSigners {
+       config.CommonConfig.Consensus.SelfVoteSigners = append(config.CommonConfig.Consensus.SelfVoteSigners, "vsm1qkm743xmgnvh84pmjchq2s4tnfpgu9ae2f9slep")
+       config.CommonConfig.Consensus.XPrv = "a8e281b615809046698fb0b0f2804a36d824d48fa443350f10f1b80649d39e5f1e85cf9855548915e36137345910606cbc8e7dd8497c831dce899ee6ac112445"
+       for _, v := range config.CommonConfig.Consensus.SelfVoteSigners {
                address, err := common.DecodeAddress(v, &consensus.SoloNetParams)
                if err != nil {
                        t.Fatal(err)
                }
-               config.CommonConfig.Consensus.Dpos.Signers = append(config.CommonConfig.Consensus.Dpos.Signers, address)
+               config.CommonConfig.Consensus.Signers = append(config.CommonConfig.Consensus.Signers, address)
        }
 
        for _, c := range cases {
index 9b3f29d..378a78e 100644 (file)
@@ -1,13 +1,9 @@
 package miner
 
 import (
-       "errors"
        "sync"
        "time"
 
-       "github.com/vapor/blockchain/pseudohsm"
-
-       "github.com/vapor/blockchain/txbuilder"
        "github.com/vapor/config"
 
        log "github.com/sirupsen/logrus"
@@ -16,14 +12,9 @@ import (
        "github.com/vapor/common"
        "github.com/vapor/consensus"
        engine "github.com/vapor/consensus/consensus"
-       "github.com/vapor/consensus/consensus/dpos"
-       "github.com/vapor/crypto"
-       "github.com/vapor/crypto/ed25519/chainkd"
        "github.com/vapor/mining"
        "github.com/vapor/protocol"
        "github.com/vapor/protocol/bc"
-       "github.com/vapor/protocol/bc/types"
-       "github.com/vapor/protocol/vm/vmutil"
 )
 
 const (
@@ -33,8 +24,6 @@ const (
        module            = "miner"
 )
 
-var ConsensusEngine engine.Engine
-
 // Miner creates blocks and searches for proof-of-work values.
 type Miner struct {
        sync.Mutex
@@ -52,14 +41,6 @@ type Miner struct {
 }
 
 func NewMiner(c *protocol.Chain, accountManager *account.Manager, txPool *protocol.TxPool, newBlockCh chan *bc.Hash, engine engine.Engine) *Miner {
-       dpos, ok := engine.(*dpos.Dpos)
-       if !ok {
-               log.Error("Only the dpos engine was allowed")
-               return nil
-       }
-       dpos.Authorize(config.CommonConfig.Consensus.Dpos.Coinbase)
-       c.SetConsensusEngine(dpos)
-       ConsensusEngine = dpos
        return &Miner{
                chain:            c,
                accountManager:   accountManager,
@@ -67,27 +48,10 @@ func NewMiner(c *protocol.Chain, accountManager *account.Manager, txPool *protoc
                numWorkers:       defaultNumWorkers,
                updateNumWorkers: make(chan struct{}),
                newBlockCh:       newBlockCh,
-               engine:           dpos,
+               engine:           engine,
        }
 }
 
-func (m *Miner) generateProof(block types.Block) (types.Proof, error) {
-       var xPrv chainkd.XPrv
-       if consensus.ActiveNetParams.Signer == "" {
-               return types.Proof{}, errors.New("Signer is empty")
-       }
-       xPrv.UnmarshalText([]byte(consensus.ActiveNetParams.Signer))
-       sign := xPrv.Sign(block.BlockCommitment.TransactionsMerkleRoot.Bytes())
-       pubHash := crypto.Ripemd160(xPrv.XPub().PublicKey())
-
-       address, _ := common.NewPeginAddressWitnessScriptHash(pubHash, &consensus.ActiveNetParams)
-       control, err := vmutil.P2WPKHProgram([]byte(pubHash))
-       if err != nil {
-               return types.Proof{}, err
-       }
-       return types.Proof{Sign: sign, ControlProgram: control, Address: address.ScriptAddress()}, nil
-}
-
 // generateBlocks is a worker that is controlled by the miningWorkerController.
 // It is self contained in that it creates block templates and attempts to solve
 // them while detecting when it is performing stale work and reacting
@@ -104,9 +68,12 @@ out:
                        break out
                default:
                }
-               delegateInfo := engine.DelegateInfo{}
-               address, _ := common.DecodeAddress(config.CommonConfig.Consensus.Dpos.Coinbase, &consensus.ActiveNetParams)
-               if err := engine.GDpos.IsMining(&delegateInfo, address, uint64(time.Now().Unix())); err != nil {
+               var (
+                       delegateInfo interface{}
+                       err          error
+               )
+               address, _ := common.DecodeAddress(config.CommonConfig.Consensus.Coinbase, &consensus.ActiveNetParams)
+               if delegateInfo, err = m.engine.IsMining(address, uint64(time.Now().Unix())); err != nil {
                        time.Sleep(1 * time.Second)
                        continue
                }
@@ -121,12 +88,7 @@ out:
                        time.Sleep(1 * time.Second)
                        continue
                }
-               block, err = m.engine.Seal(m.chain, block)
-               if err != nil {
-                       log.Errorf("Seal, %v", err)
-                       continue
-               }
-               m.chain.SetConsensusEngine(m.engine)
+
                if isOrphan, err := m.chain.ProcessBlock(block); err == nil {
                        log.WithFields(log.Fields{
                                "height":   block.BlockHeader.Height,
@@ -139,50 +101,12 @@ out:
                } else {
                        log.WithField("height", block.BlockHeader.Height).Errorf("Miner fail on ProcessBlock, %v", err)
                }
-               // confirm block
-               //m.sendConfirmTx(block.Height - 1)
-               time.Sleep(time.Duration(config.CommonConfig.Consensus.Dpos.Period) * time.Second)
+               time.Sleep(time.Duration(config.CommonConfig.Consensus.Period) * time.Second)
        }
 
        m.workerWg.Done()
 }
 
-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
-}
-
 // miningWorkerController launches the worker goroutines that are used to
 // generate block templates and solve them.  It also provides the ability to
 // dynamically adjust the number of running worker goroutines.
index dc47aaa..97590f5 100644 (file)
@@ -7,6 +7,8 @@ import (
        "strconv"
        "time"
 
+       "github.com/vapor/protocol/vm"
+
        "github.com/vapor/common"
 
        log "github.com/sirupsen/logrus"
@@ -16,6 +18,7 @@ import (
        "github.com/vapor/config"
        "github.com/vapor/consensus"
        engine "github.com/vapor/consensus/consensus"
+       dpos "github.com/vapor/consensus/consensus/dpos"
        "github.com/vapor/crypto/ed25519/chainkd"
        "github.com/vapor/errors"
        "github.com/vapor/protocol"
@@ -29,12 +32,12 @@ import (
 // createCoinbaseTx returns a coinbase transaction paying an appropriate subsidy
 // based on the passed block height to the provided address.  When the address
 // is nil, the coinbase transaction will instead be redeemable by anyone.
-func createCoinbaseTx(accountManager *account.Manager, amount uint64, blockHeight uint64, delegateInfo engine.DelegateInfo, timestamp uint64) (tx *types.Tx, err error) {
+func createCoinbaseTx(accountManager *account.Manager, amount uint64, blockHeight uint64, delegateInfo interface{}, timestamp uint64) (tx *types.Tx, err error) {
        //amount += consensus.BlockSubsidy(blockHeight)
        arbitrary := append([]byte{0x00}, []byte(strconv.FormatUint(blockHeight, 10))...)
 
        var script []byte
-       address, _ := common.DecodeAddress(config.CommonConfig.Consensus.Dpos.Coinbase, &consensus.ActiveNetParams)
+       address, _ := common.DecodeAddress(config.CommonConfig.Consensus.Coinbase, &consensus.ActiveNetParams)
        redeemContract := address.ScriptAddress()
        script, _ = vmutil.P2WPKHProgram(redeemContract)
 
@@ -64,19 +67,21 @@ func createCoinbaseTx(accountManager *account.Manager, amount uint64, blockHeigh
                return nil, err
        }
        txData.SerializedSize = uint64(len(byteData))
-
-       delegates := engine.DelegateInfoList{}
-       delegates.Delegate = delegateInfo
+       delegates := dpos.DelegateInfoList{}
+       if delegateInfo != nil {
+               tmp := delegateInfo.(*dpos.DelegateInfo)
+               delegates.Delegate = *tmp
+       }
 
        var xPrv chainkd.XPrv
-       if config.CommonConfig.Consensus.Dpos.XPrv == "" {
+       if config.CommonConfig.Consensus.XPrv == "" {
                return nil, errors.New("Signer is empty")
        }
-       xPrv.UnmarshalText([]byte(config.CommonConfig.Consensus.Dpos.XPrv))
+       xPrv.UnmarshalText([]byte(config.CommonConfig.Consensus.XPrv))
 
        buf := [8]byte{}
        binary.LittleEndian.PutUint64(buf[:], timestamp)
-       delegates.SigTime = xPrv.Sign(buf)
+       delegates.SigTime = xPrv.Sign(buf[:])
        delegates.Xpub = xPrv.XPub()
 
        data, err := json.Marshal(&delegates)
@@ -84,6 +89,15 @@ func createCoinbaseTx(accountManager *account.Manager, amount uint64, blockHeigh
                return nil, err
        }
 
+       msg := dpos.DposMsg{
+               Type: vm.OP_DELEGATE,
+               Data: data,
+       }
+
+       data, err = json.Marshal(&msg)
+       if err != nil {
+               return nil, err
+       }
        txData.ReferenceData = data
 
        tx = &types.Tx{
@@ -94,7 +108,7 @@ func createCoinbaseTx(accountManager *account.Manager, amount uint64, blockHeigh
 }
 
 // NewBlockTemplate returns a new block template that is ready to be solved
-func NewBlockTemplate(c *protocol.Chain, txPool *protocol.TxPool, accountManager *account.Manager, engine engine.Engine, delegateInfo engine.DelegateInfo) (b *types.Block, err error) {
+func NewBlockTemplate(c *protocol.Chain, txPool *protocol.TxPool, accountManager *account.Manager, engine engine.Engine, delegateInfo interface{}) (b *types.Block, err error) {
        view := state.NewUtxoViewpoint()
        txStatus := bc.NewTransactionStatus()
        if err := txStatus.SetStatus(0, false); err != nil {
@@ -109,25 +123,12 @@ func NewBlockTemplate(c *protocol.Chain, txPool *protocol.TxPool, accountManager
        preBlockHash := preBlockHeader.Hash()
        nextBlockHeight := preBlockHeader.Height + 1
 
-       var xPrv chainkd.XPrv
-       if config.CommonConfig.Consensus.Dpos.XPrv == "" {
-               return nil, errors.New("Signer is empty")
-       }
-       xPrv.UnmarshalText([]byte(config.CommonConfig.Consensus.Dpos.XPrv))
-       xpub, _ := xPrv.XPub().MarshalText()
-
        header := types.BlockHeader{
                Version:           1,
                Height:            nextBlockHeight,
                PreviousBlockHash: preBlockHash,
                Timestamp:         uint64(time.Now().Unix()),
                BlockCommitment:   types.BlockCommitment{},
-               Coinbase:          xpub,
-       }
-
-       if err := engine.Prepare(c, &header); err != nil {
-               log.Error("Failed to prepare header for mining", "err", err)
-               return nil, err
        }
 
        b = &types.Block{}
@@ -175,13 +176,9 @@ func NewBlockTemplate(c *protocol.Chain, txPool *protocol.TxPool, accountManager
                }
        }
 
-       if err := engine.Finalize(c, &header, txEntries[1:]); err != nil {
-               return nil, err
-       }
-
        b.BlockHeader = header
        // creater coinbase transaction
-       b.Transactions[0], err = createCoinbaseTx(accountManager, txFee, nextBlockHeight, delegateInfo, bcBlock.Timestamp)
+       b.Transactions[0], err = createCoinbaseTx(accountManager, txFee, nextBlockHeight, delegateInfo, b.Timestamp)
        if err != nil {
                return nil, errors.Wrap(err, "fail on createCoinbaseTx")
        }
index 8021a66..61176c2 100644 (file)
@@ -28,7 +28,7 @@ import (
        cfg "github.com/vapor/config"
        "github.com/vapor/consensus"
        engine "github.com/vapor/consensus/consensus"
-       "github.com/vapor/consensus/consensus/dpos"
+       dpos "github.com/vapor/consensus/consensus/dpos"
        "github.com/vapor/crypto/ed25519/chainkd"
        "github.com/vapor/database/leveldb"
        "github.com/vapor/env"
@@ -46,8 +46,6 @@ const (
        maxNewBlockChSize = 1024
 )
 
-var consensusEngine engine.Engine
-
 type Node struct {
        cmn.BaseService
 
@@ -69,6 +67,8 @@ type Node struct {
        miningEnable bool
 
        newBlockCh chan *bc.Hash
+
+       engine engine.Engine
 }
 
 func NewNode(config *cfg.Config) *Node {
@@ -93,8 +93,14 @@ func NewNode(config *cfg.Config) *Node {
        tokenDB := dbm.NewDB("accesstoken", config.DBBackend, config.DBDir())
        accessTokens := accesstoken.NewStore(tokenDB)
 
+       var engine engine.Engine
+       switch config.Consensus.Type {
+       case "dpos":
+               engine = dpos.GDpos
+       }
+
        txPool := protocol.NewTxPool(store)
-       chain, err := protocol.NewChain(store, txPool)
+       chain, err := protocol.NewChain(store, txPool, engine)
        if err != nil {
                cmn.Exit(cmn.Fmt("Failed to create chain structure: %v", err))
        }
@@ -118,7 +124,7 @@ func NewNode(config *cfg.Config) *Node {
        }
 
        if !config.Wallet.Disable {
-               address, err := common.DecodeAddress(config.Consensus.Dpos.Coinbase, &consensus.ActiveNetParams)
+               address, err := common.DecodeAddress(config.Consensus.Coinbase, &consensus.ActiveNetParams)
                if err != nil {
                        cmn.Exit(cmn.Fmt("DecodeAddress: %v", err))
                }
@@ -156,6 +162,11 @@ func NewNode(config *cfg.Config) *Node {
                }()
        }
 
+       switch config.Consensus.Type {
+       case "dpos":
+               initDpos(chain, config)
+       }
+
        node := &Node{
                config:       config,
                syncManager:  syncManager,
@@ -167,12 +178,10 @@ func NewNode(config *cfg.Config) *Node {
 
                newBlockCh:      newBlockCh,
                notificationMgr: notificationMgr,
+               engine:          engine,
        }
 
-       //node.cpuMiner = cpuminer.NewCPUMiner(chain, accounts, txPool, newBlockCh)
-       consensusEngine = createConsensusEngine(config, store)
-       node.miner = miner.NewMiner(chain, accounts, txPool, newBlockCh, consensusEngine)
-
+       node.miner = miner.NewMiner(chain, accounts, txPool, newBlockCh, engine)
        node.BaseService = *cmn.NewBaseService(nil, "Node", node)
 
        return node
@@ -297,6 +306,10 @@ func (n *Node) OnStart() error {
 }
 
 func (n *Node) OnStop() {
+       if err := n.engine.Finish(); err != nil {
+               log.Errorf("OnStop: %v", err)
+       }
+
        n.notificationMgr.Shutdown()
        n.notificationMgr.WaitForShutdown()
        n.BaseService.OnStop()
@@ -362,24 +375,31 @@ func initConsensusConfig(config *cfg.Config) {
                        cmn.Exit(cmn.Fmt("invalid consensus file: %v", err))
                }
 
-               for _, v := range config.Consensus.Dpos.SelfVoteSigners {
+               for _, v := range config.Consensus.SelfVoteSigners {
                        address, err := common.DecodeAddress(v, &consensus.ActiveNetParams)
                        if err != nil {
                                cmn.Exit(cmn.Fmt("Address resolution failed: %v", err))
                        }
-                       config.Consensus.Dpos.Signers = append(config.Consensus.Dpos.Signers, address)
+                       config.Consensus.Signers = append(config.Consensus.Signers, address)
                }
        }
 }
 
-func createConsensusEngine(config *cfg.Config, store protocol.Store) engine.Engine {
-       if config.Consensus.Dpos != nil {
-               return dpos.New(config.Consensus.Dpos, store)
-       } else {
-               return nil
+func initDpos(chain *protocol.Chain, config *cfg.Config) {
+       header := chain.BestBlockHeader()
+       height := header.Height
+       hash := header.Hash()
+       maxSignerCount := config.Consensus.MaxSignerCount
+       period := config.Consensus.Period
+       if err := dpos.GDpos.Init(chain, maxSignerCount, period, height, hash); err != nil {
+               cmn.Exit(cmn.Fmt("initVote: Dpos new: %v", err))
        }
-}
 
-func GetConsensusEngine() engine.Engine {
-       return consensusEngine
+       if height > 0 {
+               oldBlockHeight := dpos.GDpos.GetOldBlockHeight()
+               oldBlockHash := dpos.GDpos.GetOldBlockHash()
+               if err := chain.RepairDPoSData(oldBlockHeight, oldBlockHash); err != nil {
+                       cmn.Exit(cmn.Fmt("initVote failed: %v", err))
+               }
+       }
 }
index b346614..984df23 100644 (file)
@@ -390,9 +390,6 @@ type BlockHeader struct {
        Nonce                 uint64             `protobuf:"varint,7,opt,name=nonce" json:"nonce,omitempty"`
        Bits                  uint64             `protobuf:"varint,8,opt,name=bits" json:"bits,omitempty"`
        TransactionStatus     *TransactionStatus `protobuf:"bytes,9,opt,name=transaction_status,json=transactionStatus" json:"transaction_status,omitempty"`
-       Proof                 *Proof             `protobuf:"bytes,10,opt,name=Proof" json:"Proof,omitempty"`
-       Extra                 []byte             `protobuf:"bytes,11,opt,name=extra,proto3" json:"extra,omitempty"`
-       Coinbase              []byte             `protobuf:"bytes,12,opt,name=coinbase,proto3" json:"coinbase,omitempty"`
 }
 
 func (m *BlockHeader) Reset()                    { *m = BlockHeader{} }
@@ -463,33 +460,13 @@ func (m *BlockHeader) GetTransactionStatus() *TransactionStatus {
        return nil
 }
 
-func (m *BlockHeader) GetProof() *Proof {
-       if m != nil {
-               return m.Proof
-       }
-       return nil
-}
-
-func (m *BlockHeader) GetExtra() []byte {
-       if m != nil {
-               return m.Extra
-       }
-       return nil
-}
-
-func (m *BlockHeader) GetCoinbase() []byte {
-       if m != nil {
-               return m.Coinbase
-       }
-       return nil
-}
-
 type TxHeader struct {
        Version        uint64  `protobuf:"varint,1,opt,name=version" json:"version,omitempty"`
        SerializedSize uint64  `protobuf:"varint,2,opt,name=serialized_size,json=serializedSize" json:"serialized_size,omitempty"`
        Data           *Hash   `protobuf:"bytes,3,opt,name=data" json:"data,omitempty"`
        TimeRange      uint64  `protobuf:"varint,4,opt,name=time_range,json=timeRange" json:"time_range,omitempty"`
        ResultIds      []*Hash `protobuf:"bytes,5,rep,name=result_ids,json=resultIds" json:"result_ids,omitempty"`
+       Side           bool    `protobuf:"varint,6,opt,name=side" json:"side,omitempty"`
 }
 
 func (m *TxHeader) Reset()                    { *m = TxHeader{} }
@@ -532,6 +509,13 @@ func (m *TxHeader) GetResultIds() []*Hash {
        return nil
 }
 
+func (m *TxHeader) GetSide() bool {
+       if m != nil {
+               return m.Side
+       }
+       return false
+}
+
 type TxVerifyResult struct {
        StatusFail bool `protobuf:"varint,1,opt,name=status_fail,json=statusFail" json:"status_fail,omitempty"`
 }
@@ -943,74 +927,72 @@ func init() {
 func init() { proto.RegisterFile("bc.proto", fileDescriptor0) }
 
 var fileDescriptor0 = []byte{
-       // 1098 bytes of a gzipped FileDescriptorProto
-       0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x57, 0xcd, 0x6e, 0xdb, 0x46,
-       0x10, 0x86, 0x24, 0xea, 0x6f, 0xa4, 0x58, 0xf6, 0xda, 0x49, 0x89, 0x20, 0x45, 0x0c, 0x02, 0x89,
-       0x53, 0x14, 0x30, 0xfc, 0x93, 0xb6, 0x97, 0x1e, 0xea, 0xc4, 0x4d, 0xa3, 0x83, 0x11, 0x63, 0x6d,
-       0xf8, 0x56, 0x10, 0x2b, 0x72, 0x25, 0x2f, 0x22, 0x71, 0xd9, 0xdd, 0xa5, 0x6a, 0xfb, 0x96, 0xb7,
-       0xe9, 0xbd, 0x87, 0x3e, 0x42, 0x4f, 0x45, 0x1f, 0xa4, 0x2f, 0x51, 0xec, 0x70, 0x29, 0x51, 0xb2,
-       0xf2, 0x87, 0xa2, 0x28, 0x02, 0xf4, 0xc6, 0x99, 0x9d, 0x9d, 0x9f, 0x6f, 0x66, 0x67, 0x86, 0xd0,
-       0x1a, 0x44, 0xbb, 0xa9, 0x92, 0x46, 0x92, 0xea, 0x20, 0x0a, 0x5e, 0x80, 0xf7, 0x92, 0xe9, 0x4b,
-       0xb2, 0x06, 0xd5, 0xe9, 0x9e, 0x5f, 0xd9, 0xae, 0x3c, 0x69, 0xd0, 0xea, 0x74, 0x0f, 0xe9, 0x7d,
-       0xbf, 0xea, 0xe8, 0x7d, 0xa4, 0x0f, 0xfc, 0x9a, 0xa3, 0x0f, 0x90, 0x3e, 0xf4, 0x3d, 0x47, 0x1f,
-       0x06, 0xdf, 0x42, 0xf3, 0x54, 0xc9, 0x91, 0x62, 0x13, 0xf2, 0x39, 0xc0, 0x74, 0x12, 0x4e, 0xb9,
-       0xd2, 0x42, 0x26, 0xa8, 0xd2, 0xa3, 0xed, 0xe9, 0xe4, 0x22, 0x67, 0x10, 0x02, 0x5e, 0x24, 0x63,
-       0x8e, 0xba, 0xbb, 0x14, 0xbf, 0x83, 0x3e, 0x34, 0x8f, 0xb4, 0xe6, 0xa6, 0x7f, 0xfc, 0x8f, 0x1d,
-       0x39, 0x81, 0x0e, 0xaa, 0x3a, 0x9a, 0xc8, 0x2c, 0x31, 0xe4, 0x31, 0xb4, 0x98, 0x25, 0x43, 0x11,
-       0xa3, 0xd2, 0xce, 0x41, 0x67, 0x77, 0x10, 0xed, 0x3a, 0x6b, 0xb4, 0x89, 0x87, 0xfd, 0x98, 0xdc,
-       0x83, 0x06, 0xc3, 0x1b, 0x68, 0xca, 0xa3, 0x8e, 0x0a, 0x46, 0xd0, 0x43, 0xd9, 0x63, 0x3e, 0x14,
-       0x89, 0x30, 0x36, 0x80, 0xaf, 0x61, 0x5d, 0x68, 0x9d, 0xb1, 0x24, 0xe2, 0x61, 0x9a, 0xc7, 0x5c,
-       0x56, 0xed, 0x60, 0xa0, 0xbd, 0x42, 0xa8, 0xc0, 0xe5, 0x01, 0x78, 0x31, 0x33, 0x0c, 0x0d, 0x74,
-       0x0e, 0x5a, 0x56, 0xd6, 0x42, 0x4f, 0x91, 0x1b, 0x8c, 0xa1, 0x73, 0xc1, 0xc6, 0x19, 0x3f, 0x93,
-       0x99, 0x8a, 0x38, 0xb9, 0x0f, 0x35, 0xc5, 0x87, 0x4e, 0xef, 0x5c, 0xd6, 0x32, 0xc9, 0x23, 0xa8,
-       0x4f, 0xad, 0xa8, 0xd3, 0xd4, 0x9b, 0x05, 0x94, 0xc7, 0x4c, 0xf3, 0x53, 0x72, 0x1f, 0x5a, 0xa9,
-       0xd4, 0xe8, 0x33, 0xe2, 0xe5, 0xd1, 0x19, 0x1d, 0xfc, 0x04, 0xeb, 0x68, 0xed, 0x98, 0x6b, 0x23,
-       0x12, 0x86, 0x71, 0xfd, 0xcb, 0x26, 0x7f, 0x84, 0xfa, 0xa9, 0x92, 0x72, 0x68, 0x0b, 0x40, 0x8b,
-       0x51, 0x5e, 0x19, 0x5d, 0x8a, 0xdf, 0xe4, 0x31, 0xac, 0x45, 0x32, 0x31, 0x4a, 0x8e, 0x1d, 0x5a,
-       0xae, 0x3c, 0x96, 0xb8, 0xc4, 0x87, 0x26, 0x8b, 0x63, 0xc5, 0xb5, 0x46, 0xfd, 0x5d, 0x5a, 0x90,
-       0xc1, 0x9b, 0x1a, 0xac, 0x3f, 0xbb, 0x36, 0x72, 0xf2, 0x6c, 0x2c, 0xa3, 0xd7, 0x2f, 0x39, 0x8b,
-       0xb9, 0xb2, 0xe2, 0x8b, 0x75, 0x58, 0x90, 0x36, 0xdf, 0x97, 0x5c, 0x8c, 0x2e, 0x67, 0xf9, 0xce,
-       0x29, 0xf2, 0x14, 0x36, 0x52, 0xc5, 0xa7, 0x42, 0x66, 0x3a, 0x1c, 0x58, 0x4d, 0xb6, 0x70, 0x6a,
-       0x4b, 0x90, 0xf4, 0x0a, 0x11, 0xb4, 0xd5, 0x8f, 0xc9, 0x03, 0x68, 0x1b, 0x31, 0xe1, 0xda, 0xb0,
-       0x49, 0x8a, 0xb5, 0xe8, 0xd1, 0x39, 0x83, 0x7c, 0x05, 0x1b, 0x46, 0xb1, 0x44, 0xb3, 0xc8, 0x02,
-       0xa1, 0x43, 0x25, 0xa5, 0xf1, 0xeb, 0x4b, 0x3a, 0xd7, 0xcb, 0x22, 0x54, 0x4a, 0x43, 0xbe, 0x83,
-       0xcf, 0x4a, 0xbc, 0x50, 0x1b, 0x66, 0x32, 0x1d, 0x5e, 0x32, 0x7d, 0xe9, 0x37, 0x96, 0x2e, 0xdf,
-       0x2d, 0x09, 0x9e, 0xa1, 0x1c, 0x3e, 0xea, 0x2d, 0xa8, 0x27, 0x32, 0x89, 0xb8, 0xdf, 0x44, 0x97,
-       0x72, 0xc2, 0xe2, 0x3f, 0x10, 0x46, 0xfb, 0x2d, 0x64, 0xe2, 0x37, 0x39, 0x06, 0x72, 0xdb, 0x96,
-       0xdf, 0x46, 0x33, 0x77, 0xad, 0x99, 0xf3, 0x65, 0x03, 0x74, 0xe3, 0x96, 0xcd, 0xe0, 0xcf, 0x1a,
-       0x74, 0xfe, 0x87, 0xff, 0xbf, 0x82, 0x9f, 0x3c, 0x74, 0x2f, 0xcc, 0x07, 0xbc, 0xd8, 0x76, 0xdd,
-       0x48, 0x0e, 0xa9, 0x7b, 0x79, 0x5b, 0x50, 0xe7, 0x57, 0x46, 0x31, 0xbf, 0x83, 0x6f, 0x27, 0x27,
-       0xec, 0xa3, 0x8d, 0xa4, 0x48, 0x06, 0x4c, 0x73, 0xbf, 0x8b, 0x07, 0x33, 0x3a, 0xf8, 0xb5, 0x02,
-       0xad, 0xf3, 0xab, 0xf7, 0xa6, 0x73, 0x07, 0x7a, 0x9a, 0x2b, 0xc1, 0xc6, 0xe2, 0x86, 0xc7, 0xa1,
-       0x16, 0x37, 0xdc, 0xe5, 0x75, 0x6d, 0xce, 0x3e, 0x13, 0x37, 0x7c, 0xd6, 0x03, 0x6b, 0xab, 0x7a,
-       0xa0, 0x9d, 0x1c, 0x36, 0x6d, 0xa1, 0x62, 0xc9, 0x88, 0x97, 0x13, 0x49, 0x2d, 0x83, 0xec, 0x00,
-       0x28, 0xae, 0xb3, 0xb1, 0x6d, 0xe6, 0xda, 0xaf, 0x6f, 0xd7, 0x16, 0x54, 0xb4, 0xf3, 0xb3, 0x7e,
-       0xac, 0x83, 0x7d, 0x58, 0x3b, 0xbf, 0xba, 0xe0, 0x4a, 0x0c, 0xaf, 0x29, 0x32, 0xc9, 0x43, 0xe8,
-       0xb8, 0x04, 0x0e, 0x99, 0x18, 0xa3, 0xfb, 0x2d, 0x0a, 0x39, 0xeb, 0x05, 0x13, 0xe3, 0x60, 0x08,
-       0x1b, 0xb7, 0x30, 0x7e, 0x47, 0xc0, 0xdf, 0xc0, 0x9d, 0x29, 0xea, 0x2f, 0x72, 0x55, 0x45, 0x6f,
-       0x08, 0xe6, 0x6a, 0xc1, 0x34, 0xed, 0xe6, 0x82, 0xee, 0x89, 0xfc, 0x51, 0x81, 0xda, 0x49, 0x76,
-       0x45, 0xbe, 0x80, 0xa6, 0xc6, 0x4e, 0xaf, 0xfd, 0x0a, 0x5e, 0xc5, 0x96, 0x5a, 0x9a, 0x00, 0xb4,
-       0x38, 0x27, 0x8f, 0xa0, 0x99, 0x96, 0x9a, 0xe2, 0xd2, 0x98, 0x29, 0xce, 0xc8, 0x0f, 0xb0, 0xf5,
-       0xb3, 0x30, 0x09, 0xd7, 0x3a, 0x8c, 0xe7, 0x5d, 0xdd, 0xf6, 0x49, 0xab, 0x7e, 0x6b, 0xa6, 0xbe,
-       0xd4, 0xf2, 0xe9, 0xa6, 0xbb, 0x51, 0xe2, 0x69, 0xf2, 0x25, 0x6c, 0x14, 0x8a, 0x98, 0x1a, 0x65,
-       0x13, 0x9e, 0x18, 0xed, 0x7b, 0xdb, 0xb5, 0x27, 0x5d, 0xba, 0xee, 0x0e, 0x8e, 0x0a, 0x7e, 0x20,
-       0xa1, 0xf5, 0xdc, 0x15, 0x0b, 0xf9, 0x1e, 0x36, 0x57, 0x78, 0xe0, 0x06, 0xca, 0x6a, 0x07, 0xc8,
-       0x6d, 0x07, 0xec, 0x6b, 0x66, 0x6a, 0x20, 0x8c, 0x62, 0xea, 0xda, 0x8d, 0x81, 0x39, 0x23, 0x78,
-       0x53, 0x81, 0xc6, 0xab, 0xcc, 0xa4, 0x99, 0x21, 0x3b, 0xd0, 0xc8, 0x31, 0x72, 0x26, 0x6e, 0x41,
-       0xe8, 0x8e, 0xc9, 0x53, 0xe8, 0xb9, 0x39, 0x12, 0xbe, 0x03, 0xc9, 0x15, 0xb3, 0x46, 0xaa, 0x58,
-       0x24, 0x6c, 0xec, 0x66, 0x59, 0x41, 0x06, 0xaf, 0x00, 0x28, 0x37, 0x42, 0x71, 0x8b, 0xc1, 0x87,
-       0xbb, 0x51, 0x52, 0x58, 0x5d, 0x54, 0xf8, 0x5b, 0x15, 0x5a, 0x7d, 0xb7, 0x2e, 0xd8, 0x32, 0xc7,
-       0x4e, 0x91, 0xf7, 0x9a, 0xe5, 0x71, 0xdc, 0xc6, 0x33, 0xec, 0x2f, 0x1f, 0x38, 0x94, 0xdf, 0x92,
-       0x96, 0xda, 0x47, 0xa6, 0xe5, 0x04, 0xfc, 0x59, 0x59, 0xe0, 0x46, 0x15, 0xcf, 0x56, 0x22, 0x7c,
-       0xaa, 0x9d, 0x83, 0xcd, 0x99, 0x03, 0xf3, 0x6d, 0x89, 0xde, 0x2b, 0x4a, 0x66, 0x69, 0x8b, 0x5a,
-       0x59, 0x65, 0xf5, 0xd5, 0x55, 0x56, 0x46, 0xae, 0xb1, 0x88, 0xdc, 0xef, 0x15, 0xa8, 0x9f, 0xa5,
-       0x3c, 0x89, 0xc9, 0x1e, 0xf4, 0x74, 0xca, 0x13, 0x13, 0x4a, 0xac, 0x8e, 0xf9, 0xc2, 0x37, 0xc7,
-       0xee, 0x0e, 0x0a, 0xe4, 0xd5, 0xd3, 0x8f, 0xdf, 0x06, 0x4c, 0xf5, 0x23, 0x81, 0x59, 0x19, 0x49,
-       0xed, 0xfd, 0x91, 0x78, 0x8b, 0x91, 0xfc, 0x55, 0x81, 0xfa, 0xf3, 0x31, 0x13, 0x93, 0x4f, 0x3d,
-       0x12, 0x12, 0x40, 0xf7, 0x94, 0x8f, 0x44, 0xe2, 0xae, 0xb8, 0xac, 0x2e, 0xf0, 0x82, 0x5f, 0xaa,
-       0xe0, 0x1d, 0xa7, 0x52, 0x7f, 0xf2, 0xc1, 0x12, 0xf0, 0xcc, 0x75, 0xca, 0x71, 0xa1, 0xb8, 0x43,
-       0xf1, 0xdb, 0xf2, 0x86, 0x4a, 0x4e, 0xb0, 0x56, 0xdb, 0x14, 0xbf, 0xed, 0x7f, 0x8a, 0x91, 0xb8,
-       0x09, 0xb4, 0x69, 0xd5, 0x48, 0x3b, 0x8b, 0xb5, 0x61, 0xaf, 0xb9, 0xdb, 0x03, 0x72, 0xc2, 0xde,
-       0xc4, 0xf9, 0xd8, 0xce, 0x6f, 0xda, 0xef, 0x41, 0x03, 0xff, 0xd6, 0x0e, 0xff, 0x0e, 0x00, 0x00,
-       0xff, 0xff, 0xbc, 0x6e, 0xdc, 0xf9, 0xb9, 0x0d, 0x00, 0x00,
+       // 1070 bytes of a gzipped FileDescriptorProto
+       0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x57, 0xcd, 0x6e, 0x1b, 0xb7,
+       0x13, 0x87, 0x56, 0xab, 0xaf, 0x91, 0x6c, 0xd9, 0xb4, 0x93, 0xff, 0x22, 0xc8, 0x1f, 0x35, 0x16,
+       0x48, 0x9c, 0xa2, 0x80, 0xe1, 0x8f, 0xb4, 0xbd, 0xf4, 0x50, 0x27, 0x6e, 0x1a, 0x1d, 0x8c, 0x18,
+       0xb4, 0xe1, 0x5b, 0xb1, 0xa0, 0xb4, 0x94, 0x4c, 0x44, 0x5a, 0x6e, 0x49, 0xae, 0x6a, 0xfb, 0x96,
+       0xb7, 0xe9, 0x1b, 0xf4, 0x11, 0x72, 0xea, 0x93, 0xf4, 0x15, 0x7a, 0x28, 0x38, 0xcb, 0x95, 0x56,
+       0xb2, 0xf2, 0x85, 0xa2, 0x28, 0x02, 0xf4, 0xc6, 0x19, 0x0e, 0x7f, 0x33, 0xf3, 0xe3, 0xec, 0x0c,
+       0x17, 0x9a, 0xfd, 0xc1, 0x5e, 0xaa, 0xa4, 0x91, 0xc4, 0xeb, 0x0f, 0xc2, 0x17, 0xe0, 0xbf, 0x64,
+       0xfa, 0x8a, 0xac, 0x83, 0x37, 0xdd, 0x0f, 0x2a, 0x3b, 0x95, 0x27, 0x75, 0xea, 0x4d, 0xf7, 0x51,
+       0x3e, 0x08, 0x3c, 0x27, 0x1f, 0xa0, 0x7c, 0x18, 0x54, 0x9d, 0x7c, 0x88, 0xf2, 0x51, 0xe0, 0x3b,
+       0xf9, 0x28, 0xfc, 0x0e, 0x1a, 0x67, 0x4a, 0x8e, 0x14, 0x9b, 0x90, 0xff, 0x03, 0x4c, 0x27, 0xd1,
+       0x94, 0x2b, 0x2d, 0x64, 0x82, 0x90, 0x3e, 0x6d, 0x4d, 0x27, 0x97, 0xb9, 0x82, 0x10, 0xf0, 0x07,
+       0x32, 0xe6, 0x88, 0xdd, 0xa1, 0xb8, 0x0e, 0x7b, 0xd0, 0x38, 0xd6, 0x9a, 0x9b, 0xde, 0xc9, 0xdf,
+       0x0e, 0xe4, 0x14, 0xda, 0x08, 0x75, 0x3c, 0x91, 0x59, 0x62, 0xc8, 0x63, 0x68, 0x32, 0x2b, 0x46,
+       0x22, 0x46, 0xd0, 0xf6, 0x61, 0x7b, 0xaf, 0x3f, 0xd8, 0x73, 0xde, 0x68, 0x03, 0x37, 0x7b, 0x31,
+       0xb9, 0x0f, 0x75, 0x86, 0x27, 0xd0, 0x95, 0x4f, 0x9d, 0x14, 0x8e, 0xa0, 0x8b, 0xb6, 0x27, 0x7c,
+       0x28, 0x12, 0x61, 0x6c, 0x02, 0xdf, 0xc0, 0x86, 0xd0, 0x3a, 0x63, 0xc9, 0x80, 0x47, 0x69, 0x9e,
+       0x73, 0x19, 0xda, 0xd1, 0x40, 0xbb, 0x85, 0x51, 0xc1, 0xcb, 0x43, 0xf0, 0x63, 0x66, 0x18, 0x3a,
+       0x68, 0x1f, 0x36, 0xad, 0xad, 0xa5, 0x9e, 0xa2, 0x36, 0x1c, 0x43, 0xfb, 0x92, 0x8d, 0x33, 0x7e,
+       0x2e, 0x33, 0x35, 0xe0, 0xe4, 0x01, 0x54, 0x15, 0x1f, 0x3a, 0xdc, 0xb9, 0xad, 0x55, 0x92, 0x47,
+       0x50, 0x9b, 0x5a, 0x53, 0x87, 0xd4, 0x9d, 0x25, 0x94, 0xe7, 0x4c, 0xf3, 0x5d, 0xf2, 0x00, 0x9a,
+       0xa9, 0xd4, 0x18, 0x33, 0xf2, 0xe5, 0xd3, 0x99, 0x1c, 0xfe, 0x0c, 0x1b, 0xe8, 0xed, 0x84, 0x6b,
+       0x23, 0x12, 0x86, 0x79, 0xfd, 0xc3, 0x2e, 0x7f, 0x82, 0xda, 0x99, 0x92, 0x72, 0x68, 0x0b, 0x40,
+       0x8b, 0x51, 0x5e, 0x19, 0x1d, 0x8a, 0x6b, 0xf2, 0x18, 0xd6, 0x07, 0x32, 0x31, 0x4a, 0x8e, 0x1d,
+       0x5b, 0xae, 0x3c, 0x96, 0xb4, 0x24, 0x80, 0x06, 0x8b, 0x63, 0xc5, 0xb5, 0x46, 0xfc, 0x0e, 0x2d,
+       0xc4, 0xf0, 0x4d, 0x15, 0x36, 0x9e, 0xdd, 0x18, 0x39, 0x79, 0x36, 0x96, 0x83, 0xd7, 0x2f, 0x39,
+       0x8b, 0xb9, 0xb2, 0xe6, 0x8b, 0x75, 0x58, 0x88, 0xf6, 0xbe, 0xaf, 0xb8, 0x18, 0x5d, 0xcd, 0xee,
+       0x3b, 0x97, 0xc8, 0x53, 0xd8, 0x4c, 0x15, 0x9f, 0x0a, 0x99, 0xe9, 0xa8, 0x6f, 0x91, 0x6c, 0xe1,
+       0x54, 0x97, 0x28, 0xe9, 0x16, 0x26, 0xe8, 0xab, 0x17, 0x93, 0x87, 0xd0, 0x32, 0x62, 0xc2, 0xb5,
+       0x61, 0x93, 0x14, 0x6b, 0xd1, 0xa7, 0x73, 0x05, 0xf9, 0x1a, 0x36, 0x8d, 0x62, 0x89, 0x66, 0x03,
+       0x4b, 0x84, 0x8e, 0x94, 0x94, 0x26, 0xa8, 0x2d, 0x61, 0x6e, 0x94, 0x4d, 0xa8, 0x94, 0x86, 0x7c,
+       0x0f, 0xff, 0x2b, 0xe9, 0x22, 0x6d, 0x98, 0xc9, 0x74, 0x74, 0xc5, 0xf4, 0x55, 0x50, 0x5f, 0x3a,
+       0x7c, 0xaf, 0x64, 0x78, 0x8e, 0x76, 0xf8, 0x51, 0x6f, 0x43, 0x2d, 0x91, 0xc9, 0x80, 0x07, 0x0d,
+       0x0c, 0x29, 0x17, 0x2c, 0xff, 0x7d, 0x61, 0x74, 0xd0, 0x44, 0x25, 0xae, 0xc9, 0x09, 0x90, 0xbb,
+       0xbe, 0x82, 0x16, 0xba, 0xb9, 0x67, 0xdd, 0x5c, 0x2c, 0x3b, 0xa0, 0x9b, 0x77, 0x7c, 0x86, 0x7f,
+       0x7a, 0xd0, 0xfe, 0x8f, 0xfe, 0x7f, 0x8d, 0xfe, 0xb7, 0x15, 0x68, 0x5e, 0x5c, 0x7f, 0x90, 0xfb,
+       0x5d, 0xe8, 0x6a, 0xae, 0x04, 0x1b, 0x8b, 0x5b, 0x1e, 0x47, 0x5a, 0xdc, 0x72, 0x77, 0x09, 0xeb,
+       0x73, 0xf5, 0xb9, 0xb8, 0xe5, 0xb3, 0x86, 0x55, 0x5d, 0xd5, 0xb0, 0x6c, 0x9b, 0xb7, 0x1c, 0x47,
+       0x8a, 0x25, 0x23, 0x5e, 0x66, 0x9d, 0x5a, 0x05, 0xd9, 0x05, 0x50, 0x5c, 0x67, 0x63, 0xdb, 0x79,
+       0x75, 0x50, 0xdb, 0xa9, 0x2e, 0x40, 0xb4, 0xf2, 0xbd, 0x5e, 0xac, 0xf3, 0x76, 0x10, 0x73, 0x24,
+       0xb5, 0x49, 0x71, 0x1d, 0x1e, 0xc0, 0xfa, 0xc5, 0xf5, 0x25, 0x57, 0x62, 0x78, 0x43, 0xd1, 0x90,
+       0x7c, 0x01, 0x6d, 0x77, 0x03, 0x43, 0x26, 0xc6, 0x98, 0x52, 0x93, 0x42, 0xae, 0x7a, 0xc1, 0xc4,
+       0x38, 0x1c, 0xc2, 0xe6, 0x1d, 0x92, 0xde, 0x43, 0xc2, 0xb7, 0xb0, 0x36, 0x45, 0xfc, 0x82, 0x6c,
+       0x0f, 0x23, 0x24, 0x48, 0xf6, 0x82, 0x6b, 0xda, 0xc9, 0x0d, 0x1d, 0xc9, 0xbf, 0x57, 0xa0, 0x7a,
+       0x9a, 0x5d, 0x93, 0x2f, 0xa1, 0xa1, 0xb1, 0x55, 0xeb, 0xa0, 0x82, 0x47, 0xb1, 0x27, 0x96, 0x5a,
+       0x38, 0x2d, 0xf6, 0xc9, 0x23, 0x68, 0xa4, 0xa5, 0xae, 0xb6, 0x34, 0x27, 0x8a, 0x3d, 0xf2, 0x23,
+       0x6c, 0xff, 0x22, 0x4c, 0xc2, 0xb5, 0x8e, 0xe2, 0x79, 0x5b, 0xb6, 0x8d, 0xce, 0xc2, 0x6f, 0xcf,
+       0xe0, 0x4b, 0x3d, 0x9b, 0x6e, 0xb9, 0x13, 0x25, 0x9d, 0x26, 0x5f, 0xc1, 0x66, 0x01, 0xc4, 0xd4,
+       0x28, 0x9b, 0xf0, 0xc4, 0xe8, 0xc0, 0xdf, 0xa9, 0x3e, 0xe9, 0xd0, 0x0d, 0xb7, 0x71, 0x5c, 0xe8,
+       0x43, 0x09, 0xcd, 0xe7, 0x52, 0x24, 0x7d, 0xa6, 0x39, 0xf9, 0x01, 0xb6, 0x56, 0x44, 0xe0, 0x26,
+       0xc2, 0xea, 0x00, 0xc8, 0xdd, 0x00, 0xec, 0xe7, 0xc8, 0x54, 0x5f, 0x18, 0xc5, 0xd4, 0x8d, 0xeb,
+       0xe3, 0x73, 0x45, 0xf8, 0xa6, 0x02, 0xf5, 0x57, 0x99, 0x49, 0x33, 0x43, 0x76, 0xa1, 0x9e, 0x73,
+       0xe4, 0x5c, 0xdc, 0xa1, 0xd0, 0x6d, 0x93, 0xa7, 0xd0, 0x75, 0x83, 0x20, 0x7a, 0x0f, 0x93, 0x2b,
+       0x86, 0x85, 0x54, 0xb1, 0x48, 0xd8, 0xd8, 0x0d, 0xa3, 0x42, 0x0c, 0x5f, 0x01, 0x50, 0x6e, 0x84,
+       0xe2, 0x96, 0x83, 0x8f, 0x0f, 0xa3, 0x04, 0xe8, 0x2d, 0x02, 0xfe, 0xe6, 0x41, 0xb3, 0xe7, 0xe6,
+       0xbd, 0x2d, 0x7d, 0xfc, 0xd4, 0xf3, 0x66, 0xb1, 0x3c, 0x4f, 0x5b, 0xb8, 0x87, 0x0d, 0xe2, 0x23,
+       0xa7, 0xea, 0x3b, 0xae, 0xa5, 0xfa, 0x89, 0xd7, 0x72, 0x0a, 0xc1, 0xac, 0x2c, 0xf0, 0x49, 0x14,
+       0xcf, 0xde, 0x34, 0xf8, 0xf9, 0xb6, 0x0f, 0xb7, 0x66, 0x01, 0xcc, 0x9f, 0x3b, 0xf4, 0x7e, 0x51,
+       0x32, 0x4b, 0xcf, 0xa0, 0x95, 0x55, 0x56, 0x5b, 0x5d, 0x65, 0x65, 0xe6, 0xea, 0x8b, 0xcc, 0xbd,
+       0xad, 0x40, 0xed, 0x3c, 0xe5, 0x49, 0x4c, 0xf6, 0xa1, 0xab, 0x53, 0x9e, 0x98, 0x48, 0x62, 0x75,
+       0xcc, 0x5f, 0x6c, 0x73, 0xee, 0xd6, 0xd0, 0x20, 0xaf, 0x9e, 0x5e, 0xfc, 0x2e, 0x62, 0xbc, 0x4f,
+       0x24, 0x66, 0x65, 0x26, 0xd5, 0x0f, 0x67, 0xe2, 0x2f, 0x66, 0xf2, 0x47, 0x05, 0x6a, 0xcf, 0xc7,
+       0x4c, 0x4c, 0x3e, 0xf7, 0x4c, 0x48, 0x08, 0x9d, 0x33, 0x3e, 0x12, 0x89, 0x3b, 0xe2, 0x6e, 0x75,
+       0x41, 0x17, 0xfe, 0xea, 0x81, 0x7f, 0x92, 0x4a, 0xfd, 0xd9, 0x27, 0x4b, 0xc0, 0x37, 0x37, 0x29,
+       0xc7, 0x17, 0xc1, 0x1a, 0xc5, 0xb5, 0xd5, 0x0d, 0x95, 0x9c, 0x60, 0xad, 0xb6, 0x28, 0xae, 0xed,
+       0x8f, 0x86, 0x91, 0x38, 0xca, 0x5b, 0xd4, 0x33, 0xd2, 0x4e, 0x77, 0x6d, 0xd8, 0x6b, 0xee, 0x06,
+       0x79, 0x2e, 0xd8, 0x93, 0x38, 0x33, 0x5b, 0xf9, 0x49, 0xbb, 0xee, 0xd7, 0xf1, 0x77, 0xeb, 0xe8,
+       0xaf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x94, 0x81, 0x10, 0xfb, 0x7a, 0x0d, 0x00, 0x00,
 }
index e45143a..0ee23f8 100644 (file)
@@ -76,9 +76,6 @@ message BlockHeader {
   uint64            nonce                   = 7;
   uint64            bits                    = 8;
   TransactionStatus transaction_status      = 9;
-  Proof             Proof                   = 10;
-  bytes             extra                   = 11;
-  bytes             coinbase                = 12;
 }
 
 message TxHeader {
@@ -87,6 +84,7 @@ message TxHeader {
   Hash          data            = 3;
   uint64        time_range      = 4;
   repeated Hash result_ids      = 5;
+  bool          side            = 6;
 }
 
 message TxVerifyResult {
index 4517755..2d912bd 100644 (file)
@@ -11,17 +11,13 @@ func (bh *BlockHeader) writeForHash(w io.Writer) {
        mustWriteForHash(w, bh.Height)
        mustWriteForHash(w, bh.PreviousBlockId)
        mustWriteForHash(w, bh.Timestamp)
-       //mustWriteForHash(w, bh.Coinbase)
        mustWriteForHash(w, bh.TransactionsRoot)
        mustWriteForHash(w, bh.TransactionStatusHash)
-       mustWriteForHash(w, bh.Proof.Sign)
-       mustWriteForHash(w, bh.Proof.ControlProgram)
-       mustWriteForHash(w, bh.Extra)
 }
 
 // NewBlockHeader creates a new BlockHeader and populates
 // its body.
-func NewBlockHeader(version, height uint64, previousBlockID *Hash, timestamp uint64, transactionsRoot, transactionStatusHash *Hash, proof *Proof, extra []byte, coinbase []byte) *BlockHeader {
+func NewBlockHeader(version, height uint64, previousBlockID *Hash, timestamp uint64, transactionsRoot, transactionStatusHash *Hash) *BlockHeader {
        return &BlockHeader{
                Version:               version,
                Height:                height,
@@ -30,8 +26,5 @@ func NewBlockHeader(version, height uint64, previousBlockID *Hash, timestamp uin
                TransactionsRoot:      transactionsRoot,
                TransactionStatusHash: transactionStatusHash,
                TransactionStatus:     nil,
-               Proof:                 proof,
-               Extra:                 extra,
-               Coinbase:              coinbase,
        }
 }
index 1ab9151..ab9e810 100644 (file)
@@ -11,7 +11,7 @@ func BenchmarkEntryID(b *testing.B) {
        entries := []Entry{
                NewIssuance(nil, &AssetAmount{}, 0),
                m,
-               NewTxHeader(1, 1, 0, nil),
+               NewTxHeader(1, 1, nil, 0, nil, true),
                NewOutput(&ValueSource{}, &Program{Code: []byte{1}, VmVersion: 1}, 0),
                NewRetirement(&ValueSource{}, 1),
                NewSpend(&Hash{}, 0),
index 048ef73..888ce31 100644 (file)
@@ -12,16 +12,19 @@ func (h *TxHeader) writeForHash(w io.Writer) {
        mustWriteForHash(w, h.Version)
        mustWriteForHash(w, h.TimeRange)
        mustWriteForHash(w, h.ResultIds)
-       mustWriteForHash(w, h.Data)
+       if h.Side {
+               mustWriteForHash(w, h.Data)
+       }
 }
 
 // NewTxHeader creates an new TxHeader.
-func NewTxHeader(version, serializedSize uint64, data *Hash, timeRange uint64, resultIDs []*Hash) *TxHeader {
+func NewTxHeader(version, serializedSize uint64, data *Hash, timeRange uint64, resultIDs []*Hash, side bool) *TxHeader {
        return &TxHeader{
                Version:        version,
                SerializedSize: serializedSize,
                Data:           data,
                TimeRange:      timeRange,
                ResultIds:      resultIDs,
+               Side:           side,
        }
 }
index ab47019..ab53157 100644 (file)
@@ -12,48 +12,12 @@ import (
        "github.com/vapor/protocol/bc"
 )
 
-type Proof struct {
-       Sign           []byte
-       ControlProgram []byte
-       Address        []byte
-}
-
-func (p *Proof) readFrom(r *blockchain.Reader) (err error) {
-       if p.Sign, err = blockchain.ReadVarstr31(r); err != nil {
-               return err
-       }
-       if p.ControlProgram, err = blockchain.ReadVarstr31(r); err != nil {
-               return err
-       }
-       if p.Address, err = blockchain.ReadVarstr31(r); err != nil {
-               return err
-       }
-       return nil
-}
-
-func (p *Proof) writeTo(w io.Writer) error {
-       if _, err := blockchain.WriteVarstr31(w, p.Sign); err != nil {
-               return err
-       }
-
-       if _, err := blockchain.WriteVarstr31(w, p.ControlProgram); err != nil {
-               return err
-       }
-       if _, err := blockchain.WriteVarstr31(w, p.Address); err != nil {
-               return err
-       }
-       return nil
-}
-
 // BlockHeader defines information about a block and is used in the Bytom
 type BlockHeader struct {
        Version           uint64  // The version of the block.
        Height            uint64  // The height of the block.
        PreviousBlockHash bc.Hash // The hash of the previous block.
        Timestamp         uint64  // The time of the block in seconds.
-       Coinbase          []byte
-       Proof             Proof
-       Extra             []byte
        BlockCommitment
 }
 
@@ -117,18 +81,9 @@ func (bh *BlockHeader) readFrom(r *blockchain.Reader) (serflag uint8, err error)
        if bh.Timestamp, err = blockchain.ReadVarint63(r); err != nil {
                return 0, err
        }
-       if bh.Coinbase, err = blockchain.ReadVarstr31(r); err != nil {
-               return 0, err
-       }
        if _, err = blockchain.ReadExtensibleString(r, bh.BlockCommitment.readFrom); err != nil {
                return 0, err
        }
-       if _, err = blockchain.ReadExtensibleString(r, bh.Proof.readFrom); err != nil {
-               return 0, err
-       }
-       if bh.Extra, err = blockchain.ReadVarstr31(r); err != nil {
-               return 0, err
-       }
        return
 }
 
@@ -155,17 +110,8 @@ func (bh *BlockHeader) writeTo(w io.Writer, serflags uint8) (err error) {
        if _, err = blockchain.WriteVarint63(w, bh.Timestamp); err != nil {
                return err
        }
-       if _, err := blockchain.WriteVarstr31(w, bh.Coinbase); err != nil {
-               return err
-       }
        if _, err = blockchain.WriteExtensibleString(w, nil, bh.BlockCommitment.writeTo); err != nil {
                return err
        }
-       if _, err = blockchain.WriteExtensibleString(w, nil, bh.Proof.writeTo); err != nil {
-               return err
-       }
-       if _, err = blockchain.WriteVarstr31(w, bh.Extra); err != nil {
-               return err
-       }
        return nil
 }
index 09e1fa4..4892c19 100644 (file)
@@ -170,7 +170,7 @@ func mapTx(tx *TxData) (headerID bc.Hash, hdr *bc.TxHeader, entryMap map[bc.Hash
                mux.WitnessDestinations = append(mux.WitnessDestinations, dest)
        }
 
-       h := bc.NewTxHeader(tx.Version, tx.SerializedSize, &bc.Hash{}, tx.TimeRange, resultIDs)
+       h := bc.NewTxHeader(tx.Version, tx.SerializedSize, &bc.Hash{}, tx.TimeRange, resultIDs, false)
        return addEntry(h), h, entryMap
 }
 
index 276d9e5..73a600d 100644 (file)
@@ -1,8 +1,6 @@
 package types
 
 import (
-       "fmt"
-
        "github.com/vapor/protocol/bc"
 )
 
@@ -20,15 +18,7 @@ type DposTx struct {
 
 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:
-       case LogoutCandidate:
-       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{
                        AssetId: &assetID,
index 8dd10a4..9ad4037 100644 (file)
@@ -229,13 +229,12 @@ func mapTx(tx *TxData) (headerID bc.Hash, hdr *bc.TxHeader, entryMap map[bc.Hash
                mux.WitnessDestinations = append(mux.WitnessDestinations, dest)
        }
        refdatahash := hashData(tx.ReferenceData)
-       h := bc.NewTxHeader(tx.Version, tx.SerializedSize, &refdatahash, tx.TimeRange, resultIDs)
+       h := bc.NewTxHeader(tx.Version, tx.SerializedSize, &refdatahash, tx.TimeRange, resultIDs, true)
        return addEntry(h), h, entryMap
 }
 
 func mapBlockHeader(old *BlockHeader) (bc.Hash, *bc.BlockHeader) {
-       proof := &bc.Proof{Sign: old.Proof.Sign, ControlProgram: old.Proof.ControlProgram}
-       bh := bc.NewBlockHeader(old.Version, old.Height, &old.PreviousBlockHash, old.Timestamp, &old.TransactionsMerkleRoot, &old.TransactionStatusHash, proof, old.Extra, old.Coinbase)
+       bh := bc.NewBlockHeader(old.Version, old.Height, &old.PreviousBlockHash, old.Timestamp, &old.TransactionsMerkleRoot, &old.TransactionStatusHash)
        return bc.EntryID(bh), bh
 }
 
index 05d8c0c..2f22c55 100644 (file)
@@ -23,7 +23,7 @@ func TestMerkleRoot(t *testing.T) {
                                []byte("00000"),
                        },
                },
-               want: testutil.MustDecodeHash("fe34dbd5da0ce3656f423fd7aad7fc7e879353174d33a6446c2ed0e3f3512101"),
+               want: testutil.MustDecodeHash("011a6b552cc8eced01c403b138c51f906d0ccd0bbdf986d2b3e0cc69a4291737"),
        }, {
                witnesses: [][][]byte{
                        {
@@ -35,7 +35,7 @@ func TestMerkleRoot(t *testing.T) {
                                []byte("111111"),
                        },
                },
-               want: testutil.MustDecodeHash("0e4b4c1af18b8f59997804d69f8f66879ad5e30027346ee003ff7c7a512e5554"),
+               want: testutil.MustDecodeHash("64cef8abecac041b87110309dd9068d4935a31fb1bd1572144d11ead9da91dba"),
        }, {
                witnesses: [][][]byte{
                        {
@@ -48,7 +48,7 @@ func TestMerkleRoot(t *testing.T) {
                                []byte("222222"),
                        },
                },
-               want: testutil.MustDecodeHash("0e4b4c1af18b8f59997804d69f8f66879ad5e30027346ee003ff7c7a512e5554"),
+               want: testutil.MustDecodeHash("64cef8abecac041b87110309dd9068d4935a31fb1bd1572144d11ead9da91dba"),
        }}
 
        for _, c := range cases {
index 01d60c3..5342cde 100644 (file)
@@ -8,11 +8,9 @@ type TxType uint8
 
 const (
        Binary TxType = iota
-       LoginCandidate
-       LogoutCandidate
-       Delegate
-       UnDelegate
-       ConfirmTx
+       Registe
+       Vote
+       CancelVote
 )
 
 // SpendInput satisfies the TypedInput interface and represents a spend transaction.
index c98e673..b8b83c2 100644 (file)
@@ -139,6 +139,11 @@ func (tx *TxData) readFrom(r *blockchain.Reader) (err error) {
                tx.Outputs = append(tx.Outputs, to)
        }
        tx.SerializedSize = uint64(startSerializedSize - r.Len())
+
+       if tx.ReferenceData, err = blockchain.ReadVarstr31(r); err != nil {
+               return errors.Wrap(err, "reading transaction referenceData")
+       }
+
        return nil
 }
 
@@ -181,5 +186,10 @@ func (tx *TxData) writeTo(w io.Writer, serflags byte) error {
                        return errors.Wrapf(err, "writing tx output %d", i)
                }
        }
+
+       if _, err := blockchain.WriteVarstr31(w, tx.ReferenceData); err != nil {
+               return errors.Wrap(err, "writing tx ReferenceData")
+       }
+
        return nil
 }
index 1771a99..f91c33d 100644 (file)
@@ -2,13 +2,15 @@ package protocol
 
 import (
        "encoding/json"
-       "fmt"
+
+       "github.com/vapor/protocol/vm"
 
        log "github.com/sirupsen/logrus"
 
        "github.com/vapor/common"
        "github.com/vapor/consensus"
        engine "github.com/vapor/consensus/consensus"
+       dpos "github.com/vapor/consensus/consensus/dpos"
        "github.com/vapor/errors"
        "github.com/vapor/protocol/bc"
        "github.com/vapor/protocol/bc/types"
@@ -159,15 +161,38 @@ func (c *Chain) reorganizeChain(node *state.BlockNode) error {
        return c.setState(node, utxoView)
 }
 
+func (c *Chain) consensusCheck(block *types.Block) error {
+       if err := dpos.GDpos.CheckBlockHeader(block.BlockHeader); err != nil {
+               return err
+       }
+
+       if err := dpos.GDpos.IsValidBlockCheckIrreversibleBlock(block.Height, block.Hash()); err != nil {
+               return err
+       }
+
+       if err := dpos.GDpos.CheckBlock(*block, true); err != nil {
+               return err
+       }
+       return nil
+}
+
 // SaveBlock will validate and save block into storage
 func (c *Chain) saveBlock(block *types.Block) error {
        bcBlock := types.MapBlock(block)
        parent := c.index.GetNode(&block.PreviousBlockHash)
 
-       if err := validation.ValidateBlock(bcBlock, parent, block, c); err != nil {
+       if err := c.consensusCheck(block); err != nil {
+               return err
+       }
+
+       if err := validation.ValidateBlock(bcBlock, parent, block); err != nil {
                return errors.Sub(ErrBadBlock, err)
        }
 
+       if err := c.ProcessDPoSConnectBlock(block); err != nil {
+               return err
+       }
+
        if err := c.store.SaveBlock(block, bcBlock.TransactionStatus); err != nil {
                return err
        }
@@ -259,24 +284,27 @@ func (c *Chain) processBlock(block *types.Block) (bool, error) {
                return false, c.connectBlock(bestBlock)
        }
 
-       if bestNode.Height > c.bestNode.Height && bestNode.WorkSum.Cmp(c.bestNode.WorkSum) >= 0 {
+       if bestNode.Height > c.bestNode.Height {
                log.Debug("start to reorganize chain")
                return false, c.reorganizeChain(bestNode)
        }
        return false, nil
 }
 
-func (c *Chain) ProcessDPoSConnectBlock(block *types.Block) {
+func (c *Chain) ProcessDPoSConnectBlock(block *types.Block) error {
        mapTxFee := c.CalculateBalance(block, true)
-       fmt.Println(mapTxFee)
+       if err := c.DoVoting(block, mapTxFee); err != nil {
+               return err
+       }
+       return nil
 }
 
-func DoVoting(block *types.Block, mapTxFee map[bc.Hash]uint64) error {
+func (c *Chain) DoVoting(block *types.Block, mapTxFee map[bc.Hash]uint64) error {
        for _, tx := range block.Transactions {
                to := tx.Outputs[0]
-               var delegate engine.TypedData
+               msg := &dpos.DposMsg{}
 
-               if err := json.Unmarshal(tx.TxData.ReferenceData, delegate); err != nil && to.Amount > 0 {
+               if err := json.Unmarshal(tx.TxData.ReferenceData, &msg); err != nil {
                        continue
                }
                var (
@@ -292,20 +320,32 @@ func DoVoting(block *types.Block, mapTxFee map[bc.Hash]uint64) error {
                }
                hash := block.Hash()
                height := block.Height
-               switch data := delegate.(type) {
-               case *engine.DelegateInfoList:
+               switch msg.Type {
+               case vm.OP_DELEGATE:
                        continue
-               case *engine.RegisterForgerData:
+               case vm.OP_REGISTE:
                        if mapTxFee[tx.Tx.ID] >= consensus.RegisrerForgerFee {
-                               engine.DposVote.ProcessRegister(address.EncodeAddress(), data.Name, hash, height)
+                               data := &dpos.RegisterForgerData{}
+                               if err := json.Unmarshal(msg.Data, data); err != nil {
+                                       return err
+                               }
+                               c.engine.ProcessRegister(address.EncodeAddress(), data.Name, hash, height)
                        }
-               case *engine.VoteForgerData:
+               case vm.OP_VOTE:
                        if mapTxFee[tx.Tx.ID] >= consensus.VoteForgerFee {
-                               engine.DposVote.ProcessVote(address.EncodeAddress(), data.Forgers, hash, height)
+                               data := &dpos.VoteForgerData{}
+                               if err := json.Unmarshal(msg.Data, data); err != nil {
+                                       return err
+                               }
+                               c.engine.ProcessVote(address.EncodeAddress(), data.Forgers, hash, height)
                        }
-               case *engine.CancelVoteForgerData:
+               case vm.OP_REVOKE:
                        if mapTxFee[tx.Tx.ID] >= consensus.CancelVoteForgerFee {
-                               engine.DposVote.ProcessCancelVote(address.EncodeAddress(), data.Forgers, hash, height)
+                               data := &dpos.CancelVoteForgerData{}
+                               if err := json.Unmarshal(msg.Data, data); err != nil {
+                                       return err
+                               }
+                               c.engine.ProcessCancelVote(address.EncodeAddress(), data.Forgers, hash, height)
                        }
                }
        }
@@ -324,6 +364,13 @@ func (c *Chain) CalculateBalance(block *types.Block, fIsAdd bool) map[bc.Hash]ui
        for _, tx := range block.Transactions {
                fee := uint64(0)
                for _, input := range tx.Inputs {
+
+                       if len(tx.TxData.Inputs) == 1 &&
+                               (tx.TxData.Inputs[0].InputType() == types.CoinbaseInputType ||
+                                       tx.TxData.Inputs[0].InputType() == types.ClainPeginInputType) {
+                               continue
+                       }
+
                        fee += input.Amount()
                        value := int64(input.Amount())
                        address, err = common.NewAddressWitnessPubKeyHash(input.ControlProgram()[2:], &consensus.ActiveNetParams)
@@ -348,7 +395,7 @@ func (c *Chain) CalculateBalance(block *types.Block, fIsAdd bool) map[bc.Hash]ui
                                        continue
                                }
                        }
-                       if fIsAdd {
+                       if !fIsAdd {
                                value = 0 - value
                        }
                        addressBalances = append(addressBalances, engine.AddressBalance{address.EncodeAddress(), value})
@@ -356,6 +403,27 @@ func (c *Chain) CalculateBalance(block *types.Block, fIsAdd bool) map[bc.Hash]ui
                mapTxFee[tx.Tx.ID] = fee
        }
 
-       engine.DposVote.UpdateAddressBalance(addressBalances)
+       c.engine.UpdateAddressBalance(addressBalances)
        return mapTxFee
 }
+
+func (c *Chain) RepairDPoSData(oldBlockHeight uint64, oldBlockHash bc.Hash) error {
+       block, err := c.GetBlockByHash(&oldBlockHash)
+       if err != nil {
+               return err
+       }
+       if block.Height != oldBlockHeight {
+               return errors.New("The module vote records data with a problem")
+       }
+       for i := block.Height + 1; i < c.bestNode.Height; i++ {
+               b, err := c.GetBlockByHeight(i)
+               if err != nil {
+                       return err
+               }
+               if err := c.ProcessDPoSConnectBlock(b); err != nil {
+                       return err
+               }
+
+       }
+       return nil
+}
index f60d439..5153437 100644 (file)
@@ -13,14 +13,14 @@ import (
 func TestCalcReorganizeNodes(t *testing.T) {
        c := &Chain{index: state.NewBlockIndex()}
        config.CommonConfig = config.DefaultConfig()
-       config.CommonConfig.Consensus.Dpos.SelfVoteSigners = append(config.CommonConfig.Consensus.Dpos.SelfVoteSigners, "vsm1qkm743xmgnvh84pmjchq2s4tnfpgu9ae2f9slep")
-       config.CommonConfig.Consensus.Dpos.XPrv = "a8e281b615809046698fb0b0f2804a36d824d48fa443350f10f1b80649d39e5f1e85cf9855548915e36137345910606cbc8e7dd8497c831dce899ee6ac112445"
-       for _, v := range config.CommonConfig.Consensus.Dpos.SelfVoteSigners {
+       config.CommonConfig.Consensus.SelfVoteSigners = append(config.CommonConfig.Consensus.SelfVoteSigners, "vsm1qkm743xmgnvh84pmjchq2s4tnfpgu9ae2f9slep")
+       config.CommonConfig.Consensus.XPrv = "a8e281b615809046698fb0b0f2804a36d824d48fa443350f10f1b80649d39e5f1e85cf9855548915e36137345910606cbc8e7dd8497c831dce899ee6ac112445"
+       for _, v := range config.CommonConfig.Consensus.SelfVoteSigners {
                address, err := common.DecodeAddress(v, &consensus.SoloNetParams)
                if err != nil {
                        t.Fatal(err)
                }
-               config.CommonConfig.Consensus.Dpos.Signers = append(config.CommonConfig.Consensus.Dpos.Signers, address)
+               config.CommonConfig.Consensus.Signers = append(config.CommonConfig.Consensus.Signers, address)
        }
        header := config.GenesisBlock().BlockHeader
        initNode, err := state.NewBlockNode(&header, nil)
index 7bd8518..ba60e08 100644 (file)
@@ -29,12 +29,13 @@ type Chain struct {
 }
 
 // NewChain returns a new Chain using store as the underlying storage.
-func NewChain(store Store, txPool *TxPool) (*Chain, error) {
+func NewChain(store Store, txPool *TxPool, engine engine.Engine) (*Chain, error) {
        c := &Chain{
                orphanManage:   NewOrphanManage(),
                txPool:         txPool,
                store:          store,
                processBlockCh: make(chan *processBlockMsg, maxProcessBlockChSize),
+               engine:         engine,
        }
        c.cond.L = new(sync.Mutex)
 
index 0a610f2..4a3ed2a 100644 (file)
@@ -32,9 +32,6 @@ type BlockNode struct {
        Bits                   uint64
        TransactionsMerkleRoot bc.Hash
        TransactionStatusHash  bc.Hash
-       Proof                  bc.Proof
-       Coinbase               []byte
-       Extra                  []byte
 }
 
 func NewBlockNode(bh *types.BlockHeader, parent *BlockNode) (*BlockNode, error) {
@@ -53,12 +50,6 @@ func NewBlockNode(bh *types.BlockHeader, parent *BlockNode) (*BlockNode, error)
                //Bits:      bh.Bits,
                TransactionsMerkleRoot: bh.TransactionsMerkleRoot,
                TransactionStatusHash:  bh.TransactionStatusHash,
-               Proof: bc.Proof{
-                       Sign:           bh.Proof.Sign,
-                       ControlProgram: bh.Proof.ControlProgram,
-               },
-               Coinbase: bh.Coinbase,
-               Extra:    bh.Extra,
        }
        /*
                if bh.Height == 0 {
@@ -82,16 +73,10 @@ func (node *BlockNode) BlockHeader() *types.BlockHeader {
                Height:            node.Height,
                PreviousBlockHash: previousBlockHash,
                Timestamp:         node.Timestamp,
-               Proof: types.Proof{
-                       Sign:           node.Proof.Sign,
-                       ControlProgram: node.Proof.ControlProgram,
-               },
                BlockCommitment: types.BlockCommitment{
                        TransactionsMerkleRoot: node.TransactionsMerkleRoot,
                        TransactionStatusHash:  node.TransactionStatusHash,
                },
-               Coinbase: node.Coinbase,
-               Extra:    node.Extra,
        }
 }
 
index aa18b55..17aff8a 100644 (file)
@@ -5,9 +5,7 @@ import (
 
        log "github.com/sirupsen/logrus"
 
-       "github.com/vapor/chain"
        "github.com/vapor/consensus"
-       engine "github.com/vapor/consensus/consensus"
        "github.com/vapor/errors"
        "github.com/vapor/protocol/bc"
        "github.com/vapor/protocol/bc/types"
@@ -56,7 +54,7 @@ func checkCoinbaseAmount(b *bc.Block, amount uint64) error {
 }
 
 // ValidateBlockHeader check the block's header
-func ValidateBlockHeader(b *bc.Block, block *types.Block, parent *state.BlockNode, c chain.Chain) error {
+func ValidateBlockHeader(b *bc.Block, block *types.Block, parent *state.BlockNode) error {
        if b.Version < parent.Version {
                return errors.WithDetailf(errVersionRegression, "previous block verson %d, current block version %d", parent.Version, b.Version)
        }
@@ -70,25 +68,13 @@ func ValidateBlockHeader(b *bc.Block, block *types.Block, parent *state.BlockNod
                return err
        }
 
-       if err := engine.GDpos.CheckBlockHeader(block.BlockHeader); err != nil {
-               return err
-       }
-
-       if err := engine.GDpos.IsValidBlockCheckIrreversibleBlock(block.Height, block.Hash()); err != nil {
-               return err
-       }
-
        return nil
 }
 
 // ValidateBlock validates a block and the transactions within.
-func ValidateBlock(b *bc.Block, parent *state.BlockNode, block *types.Block, c chain.Chain) error {
+func ValidateBlock(b *bc.Block, parent *state.BlockNode, block *types.Block) error {
        startTime := time.Now()
-       if err := ValidateBlockHeader(b, block, parent, c); err != nil {
-               return err
-       }
-
-       if err := engine.GDpos.CheckBlock(*block, true); err != nil {
+       if err := ValidateBlockHeader(b, block, parent); err != nil {
                return err
        }
 
index 5052c62..2038748 100644 (file)
@@ -210,6 +210,11 @@ const (
        OP_ENTRYID     Op = 0xca
        OP_OUTPUTID    Op = 0xcb
        OP_BLOCKHEIGHT Op = 0xcd
+
+       OP_DELEGATE Op = 0xd0
+       OP_REGISTE  Op = 0xd1
+       OP_VOTE     Op = 0xd2
+       OP_REVOKE   Op = 0xd3
 )
 
 type opInfo struct {
index abdb2e0..8ccb36b 100644 (file)
@@ -13,7 +13,10 @@ import (
        "github.com/vapor/blockchain/pseudohsm"
        "github.com/vapor/blockchain/signers"
        "github.com/vapor/blockchain/txbuilder"
+       "github.com/vapor/config"
        "github.com/vapor/consensus"
+       engine "github.com/vapor/consensus/consensus"
+       "github.com/vapor/consensus/consensus/dpos"
        "github.com/vapor/crypto/ed25519/chainkd"
        "github.com/vapor/database/leveldb"
        "github.com/vapor/database/storage"
@@ -136,10 +139,15 @@ func GenerateChainData(dirPath string, testDB dbm.DB, txNumber, otherAssetNum in
        if err := SetUtxoView(testDB, utxoView); err != nil {
                return nil, nil, nil, err
        }
+       var engine engine.Engine
+       switch config.CommonConfig.Consensus.Type {
+       case "dpos":
+               engine = dpos.GDpos
+       }
 
        store := leveldb.NewStore(testDB)
        txPool := protocol.NewTxPool(store)
-       chain, err := protocol.NewChain(store, txPool)
+       chain, err := protocol.NewChain(store, txPool, engine)
        if err != nil {
                return nil, nil, nil, err
        }
@@ -156,7 +164,7 @@ func InsertChain(chain *protocol.Chain, txPool *protocol.TxPool, txs []*types.Tx
                }
        }
 
-       block, err := mining.NewBlockTemplate(chain, txPool, nil, nil)
+       block, err := mining.NewBlockTemplate(chain, txPool, nil, nil, nil)
        if err != nil {
                return err
        }
index e609d85..6915653 100644 (file)
@@ -1,16 +1,11 @@
 package test
 
 import (
-       "github.com/vapor/consensus"
-       "github.com/vapor/crypto"
-       "github.com/vapor/crypto/ed25519/chainkd"
-       "github.com/vapor/errors"
        "github.com/vapor/protocol"
        "github.com/vapor/protocol/bc"
        "github.com/vapor/protocol/bc/types"
        "github.com/vapor/protocol/validation"
        "github.com/vapor/protocol/vm"
-       "github.com/vapor/protocol/vm/vmutil"
 )
 
 // NewBlock create block according to the current status of chain
@@ -67,29 +62,9 @@ func NewBlock(chain *protocol.Chain, txs []*types.Tx, controlProgram []byte) (*t
        }
 
        b.TransactionStatusHash, err = types.TxStatusMerkleRoot(txStatus.VerifyStatus)
-       proof, err := generateProof(*b)
-       if err != nil {
-               return nil, err
-       }
-       b.Proof = proof
        return b, err
 }
 
-func generateProof(block types.Block) (types.Proof, error) {
-       var xPrv chainkd.XPrv
-       if consensus.ActiveNetParams.Signer == "" {
-               return types.Proof{}, errors.New("Signer is empty")
-       }
-       xPrv.UnmarshalText([]byte(consensus.ActiveNetParams.Signer))
-       sign := xPrv.Sign(block.BlockCommitment.TransactionsMerkleRoot.Bytes())
-       pubHash := crypto.Ripemd160(xPrv.XPub().PublicKey())
-       control, err := vmutil.P2WPKHProgram([]byte(pubHash))
-       if err != nil {
-               return types.Proof{}, err
-       }
-       return types.Proof{Sign: sign, ControlProgram: control}, nil
-}
-
 // ReplaceCoinbase replace the coinbase tx of block with coinbaseTx
 func ReplaceCoinbase(block *types.Block, coinbaseTx *types.Tx) (err error) {
        block.Transactions[0] = coinbaseTx
index 3377f12..1cfa781 100644 (file)
@@ -12,6 +12,8 @@ import (
        "github.com/vapor/common"
        "github.com/vapor/config"
        "github.com/vapor/consensus"
+       engine "github.com/vapor/consensus/consensus"
+       "github.com/vapor/consensus/consensus/dpos"
        "github.com/vapor/crypto/ed25519/chainkd"
        "github.com/vapor/database/leveldb"
        "github.com/vapor/protocol"
@@ -29,19 +31,25 @@ const (
 func MockChain(testDB dbm.DB) (*protocol.Chain, *leveldb.Store, *protocol.TxPool, error) {
        config.CommonConfig = config.DefaultConfig()
        consensus.SoloNetParams.Signer = "78673764e0ba91a4c5ba9ec0c8c23c69e3d73bf27970e05e0a977e81e13bde475264d3b177a96646bc0ce517ae7fd63504c183ab6d330dea184331a4cf5912d5"
-       config.CommonConfig.Consensus.Dpos.SelfVoteSigners = append(config.CommonConfig.Consensus.Dpos.SelfVoteSigners, "vsm1qkm743xmgnvh84pmjchq2s4tnfpgu9ae2f9slep")
-       config.CommonConfig.Consensus.Dpos.XPrv = "a8e281b615809046698fb0b0f2804a36d824d48fa443350f10f1b80649d39e5f1e85cf9855548915e36137345910606cbc8e7dd8497c831dce899ee6ac112445"
-       for _, v := range config.CommonConfig.Consensus.Dpos.SelfVoteSigners {
+       config.CommonConfig.Consensus.SelfVoteSigners = append(config.CommonConfig.Consensus.SelfVoteSigners, "vsm1qkm743xmgnvh84pmjchq2s4tnfpgu9ae2f9slep")
+       config.CommonConfig.Consensus.XPrv = "a8e281b615809046698fb0b0f2804a36d824d48fa443350f10f1b80649d39e5f1e85cf9855548915e36137345910606cbc8e7dd8497c831dce899ee6ac112445"
+       for _, v := range config.CommonConfig.Consensus.SelfVoteSigners {
                address, err := common.DecodeAddress(v, &consensus.SoloNetParams)
                if err != nil {
                        return nil, nil, nil, err
                }
-               config.CommonConfig.Consensus.Dpos.Signers = append(config.CommonConfig.Consensus.Dpos.Signers, address)
+               config.CommonConfig.Consensus.Signers = append(config.CommonConfig.Consensus.Signers, address)
        }
 
        store := leveldb.NewStore(testDB)
        txPool := protocol.NewTxPool(store)
-       chain, err := protocol.NewChain(store, txPool)
+       var engine engine.Engine
+       switch config.CommonConfig.Consensus.Type {
+       case "dpos":
+               engine = dpos.GDpos
+       }
+
+       chain, err := protocol.NewChain(store, txPool, engine)
        consensus.ActiveNetParams.Signer = "78673764e0ba91a4c5ba9ec0c8c23c69e3d73bf27970e05e0a977e81e13bde475264d3b177a96646bc0ce517ae7fd63504c183ab6d330dea184331a4cf5912d5"
        return chain, store, txPool, err
 }
index 261c087..1ef1dc2 100644 (file)
@@ -259,8 +259,8 @@ func (cfg *walletTestConfig) Run() error {
        if err != nil {
                return err
        }
-       config.CommonConfig.Consensus.Dpos.Coinbase = "vsm1qkm743xmgnvh84pmjchq2s4tnfpgu9ae2f9slep"
-       address, err := common.DecodeAddress(config.CommonConfig.Consensus.Dpos.Coinbase, &consensus.SoloNetParams)
+       config.CommonConfig.Consensus.Coinbase = "vsm1qkm743xmgnvh84pmjchq2s4tnfpgu9ae2f9slep"
+       address, err := common.DecodeAddress(config.CommonConfig.Consensus.Coinbase, &consensus.SoloNetParams)
        if err != nil {
                return err
        }
index 36fc969..4a9f340 100644 (file)
@@ -39,7 +39,7 @@ func GoPath() string {
 // with code 1.
 func TrapSignal(cb func()) {
        c := make(chan os.Signal, 1)
-       signal.Notify(c, os.Interrupt, syscall.SIGTERM)
+       signal.Notify(c, os.Interrupt, os.Kill, syscall.SIGHUP, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGKILL)
        go func() {
                for sig := range c {
                        fmt.Printf("captured %v, exiting...\n", sig)
index 047e412..310b405 100644 (file)
@@ -23,17 +23,17 @@ import (
 func TestWalletUnconfirmedTxs(t *testing.T) {
        config.CommonConfig = config.DefaultConfig()
        consensus.SoloNetParams.Signer = "78673764e0ba91a4c5ba9ec0c8c23c69e3d73bf27970e05e0a977e81e13bde475264d3b177a96646bc0ce517ae7fd63504c183ab6d330dea184331a4cf5912d5"
-       config.CommonConfig.Consensus.Dpos.SelfVoteSigners = append(config.CommonConfig.Consensus.Dpos.SelfVoteSigners, "vsm1qkm743xmgnvh84pmjchq2s4tnfpgu9ae2f9slep")
-       config.CommonConfig.Consensus.Dpos.XPrv = "a8e281b615809046698fb0b0f2804a36d824d48fa443350f10f1b80649d39e5f1e85cf9855548915e36137345910606cbc8e7dd8497c831dce899ee6ac112445"
-       for _, v := range config.CommonConfig.Consensus.Dpos.SelfVoteSigners {
+       config.CommonConfig.Consensus.SelfVoteSigners = append(config.CommonConfig.Consensus.SelfVoteSigners, "vsm1qkm743xmgnvh84pmjchq2s4tnfpgu9ae2f9slep")
+       config.CommonConfig.Consensus.XPrv = "a8e281b615809046698fb0b0f2804a36d824d48fa443350f10f1b80649d39e5f1e85cf9855548915e36137345910606cbc8e7dd8497c831dce899ee6ac112445"
+       for _, v := range config.CommonConfig.Consensus.SelfVoteSigners {
                address, err := common.DecodeAddress(v, &consensus.SoloNetParams)
                if err != nil {
                        t.Fatal(err)
                }
-               config.CommonConfig.Consensus.Dpos.Signers = append(config.CommonConfig.Consensus.Dpos.Signers, address)
+               config.CommonConfig.Consensus.Signers = append(config.CommonConfig.Consensus.Signers, address)
        }
-       config.CommonConfig.Consensus.Dpos.Coinbase = "vsm1qkm743xmgnvh84pmjchq2s4tnfpgu9ae2f9slep"
-       address, err := common.DecodeAddress(config.CommonConfig.Consensus.Dpos.Coinbase, &consensus.SoloNetParams)
+       config.CommonConfig.Consensus.Coinbase = "vsm1qkm743xmgnvh84pmjchq2s4tnfpgu9ae2f9slep"
+       address, err := common.DecodeAddress(config.CommonConfig.Consensus.Coinbase, &consensus.SoloNetParams)
        if err != nil {
                t.Fatal(err)
        }
index 519a6b7..c9f8b4a 100644 (file)
@@ -7,15 +7,16 @@ import (
        "time"
 
        dbm "github.com/tendermint/tmlibs/db"
-       "github.com/vapor/blockchain/signers"
-       "github.com/vapor/common"
-       "github.com/vapor/config"
-
        "github.com/vapor/account"
        "github.com/vapor/asset"
        "github.com/vapor/blockchain/pseudohsm"
+       "github.com/vapor/blockchain/signers"
        "github.com/vapor/blockchain/txbuilder"
+       "github.com/vapor/common"
+       "github.com/vapor/config"
        "github.com/vapor/consensus"
+       engine "github.com/vapor/consensus/consensus"
+       "github.com/vapor/consensus/consensus/dpos"
        "github.com/vapor/crypto/ed25519/chainkd"
        "github.com/vapor/database/leveldb"
        "github.com/vapor/protocol"
@@ -26,17 +27,17 @@ import (
 func TestWalletUpdate(t *testing.T) {
        config.CommonConfig = config.DefaultConfig()
        consensus.SoloNetParams.Signer = "78673764e0ba91a4c5ba9ec0c8c23c69e3d73bf27970e05e0a977e81e13bde475264d3b177a96646bc0ce517ae7fd63504c183ab6d330dea184331a4cf5912d5"
-       config.CommonConfig.Consensus.Dpos.SelfVoteSigners = append(config.CommonConfig.Consensus.Dpos.SelfVoteSigners, "vsm1qkm743xmgnvh84pmjchq2s4tnfpgu9ae2f9slep")
-       config.CommonConfig.Consensus.Dpos.XPrv = "a8e281b615809046698fb0b0f2804a36d824d48fa443350f10f1b80649d39e5f1e85cf9855548915e36137345910606cbc8e7dd8497c831dce899ee6ac112445"
-       for _, v := range config.CommonConfig.Consensus.Dpos.SelfVoteSigners {
+       config.CommonConfig.Consensus.SelfVoteSigners = append(config.CommonConfig.Consensus.SelfVoteSigners, "vsm1qkm743xmgnvh84pmjchq2s4tnfpgu9ae2f9slep")
+       config.CommonConfig.Consensus.XPrv = "a8e281b615809046698fb0b0f2804a36d824d48fa443350f10f1b80649d39e5f1e85cf9855548915e36137345910606cbc8e7dd8497c831dce899ee6ac112445"
+       for _, v := range config.CommonConfig.Consensus.SelfVoteSigners {
                address, err := common.DecodeAddress(v, &consensus.SoloNetParams)
                if err != nil {
                        t.Fatal(err)
                }
-               config.CommonConfig.Consensus.Dpos.Signers = append(config.CommonConfig.Consensus.Dpos.Signers, address)
+               config.CommonConfig.Consensus.Signers = append(config.CommonConfig.Consensus.Signers, address)
        }
-       config.CommonConfig.Consensus.Dpos.Coinbase = "vsm1qkm743xmgnvh84pmjchq2s4tnfpgu9ae2f9slep"
-       address, err := common.DecodeAddress(config.CommonConfig.Consensus.Dpos.Coinbase, &consensus.SoloNetParams)
+       config.CommonConfig.Consensus.Coinbase = "vsm1qkm743xmgnvh84pmjchq2s4tnfpgu9ae2f9slep"
+       address, err := common.DecodeAddress(config.CommonConfig.Consensus.Coinbase, &consensus.SoloNetParams)
        if err != nil {
                t.Fatal(err)
        }
@@ -53,7 +54,12 @@ func TestWalletUpdate(t *testing.T) {
        store := leveldb.NewStore(testDB)
        txPool := protocol.NewTxPool(store)
 
-       chain, err := protocol.NewChain(store, txPool)
+       var engine engine.Engine
+       switch config.CommonConfig.Consensus.Type {
+       case "dpos":
+               engine = dpos.GDpos
+       }
+       chain, err := protocol.NewChain(store, txPool, engine)
        if err != nil {
                t.Fatal(err)
        }