From: mars Date: Wed, 20 Mar 2019 03:14:54 +0000 (+0800) Subject: Add the basic framework for voting processing for dpos X-Git-Tag: v1.0.5~219^2~1 X-Git-Url: http://git.osdn.net/view?p=bytom%2Fvapor.git;a=commitdiff_plain;h=620deabb3a00c7995b190b5ed47a224826165ecf Add the basic framework for voting processing for dpos --- diff --git a/api/api.go b/api/api.go index 937f8f86..af242a6c 100644 --- a/api/api.go +++ b/api/api.go @@ -254,6 +254,15 @@ func (a *API) buildHandler() { 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 + // listdelegates + // getdelegatevotes + // getdelegatefunds + // listvoteddelegates + // listreceivedvotes + // getirreversibleblock } else { log.Warn("Please enable wallet") } diff --git a/api/dpos_vote.go b/api/dpos_vote.go index 43741129..a7333eef 100644 --- a/api/dpos_vote.go +++ b/api/dpos_vote.go @@ -13,7 +13,18 @@ import ( "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"` @@ -25,7 +36,7 @@ func (a *API) dpos(ctx context.Context, ins struct { // 生成dpos交易 dpos := account.DopsAction{ Accounts: a.wallet.AccountMgr, - From: config.CommonConfig.Consensus.Dpos.Coinbase, + From: ins.From, To: ins.To, Fee: ins.Fee, TxType: ins.TxType, diff --git a/api/transact.go b/api/transact.go index 7f8b9863..a4acb346 100644 --- a/api/transact.go +++ b/api/transact.go @@ -43,19 +43,24 @@ func (a *API) actionDecoder(action string) (func([]byte) (txbuilder.Action, erro func onlyHaveInputActions(req *BuildRequest) (bool, error) { count := 0 + dpos := false for i, act := range req.Actions { actionType, ok := act["type"].(string) if !ok { return false, errors.WithDetailf(ErrBadActionType, "no action type provided on action %d", i) } if strings.HasPrefix(actionType, "dpos_address") { - return false, nil + dpos = true } if strings.HasPrefix(actionType, "spend") || actionType == "issue" { count++ } } + if dpos == true && count == 0 { + return false, nil + } + return count == len(req.Actions), nil } diff --git a/consensus/consensus/dpos.go b/consensus/consensus/dpos.go new file mode 100644 index 00000000..0036e8dc --- /dev/null +++ b/consensus/consensus/dpos.go @@ -0,0 +1,312 @@ +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/vote.go b/consensus/consensus/vote.go new file mode 100644 index 00000000..65ce0019 --- /dev/null +++ b/consensus/consensus/vote.go @@ -0,0 +1,361 @@ +package consensus + +import ( + "encoding/json" + "os" + "path/filepath" + "sync" + + "github.com/vapor/config" + + "github.com/vapor/consensus" + "github.com/vapor/protocol/bc" +) + +const ( + VoteFile = "vote.dat" + DelegateFile = "delegate.dat" + BalanceFile = "balance.dat" + ControlFile = "control.dat" + InvalidVoteTxFile = "invalidvotetx.dat" + DelegateMultiAddressFile = "delegatemultiaddress.dat" + + 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 + lockVoter sync.Mutex + DelegateName map[string]string + NameDelegate map[string]string + lockRegister sync.Mutex + HashHeightInvalidVote map[bc.Hash]uint64 + lockHashHeightInvalidVote sync.Mutex + AddressBalances map[string]uint64 + DelegateMultiaddress map[string]uint64 + + filePath string + delegateFileName string + voteFileName string + balanceFileName string + controlFileName string + invalidVoteTxFileName string + delegateMultiaddressName string + + forgerFileName string + + oldBlockHeight uint64 + oldBlockHash bc.Hash +} + +var DposVote = Vote{} + +func (v *Vote) new(blockHeight uint64, blockHash bc.Hash) error { + //DefaultDataDir + v.filePath = filepath.Join(config.DefaultDataDir(), "dpos") + v.delegateFileName = filepath.Join(v.filePath, DelegateFile) + v.balanceFileName = filepath.Join(v.filePath, BalanceFile) + v.controlFileName = filepath.Join(v.filePath, ControlFile) + v.invalidVoteTxFileName = filepath.Join(v.filePath, InvalidVoteTxFile) + 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 + } + } + } else { + if err := v.load(blockHeight, blockHash); err != nil { + return err + } + } + return nil +} + +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 { + v.AddInvalidVote(hash, height) + return false + } + + if _, ok := v.NameDelegate[delegateName]; !ok { + v.AddInvalidVote(hash, height) + return false + } + + v.DelegateName[delegateAddress] = delegateName + v.NameDelegate[delegateName] = delegateAddress + return true +} + +func (v *Vote) ProcessVote(voterAddress string, delegates []string, hash bc.Hash, height uint64) bool { + v.lockVoter.Lock() + defer v.lockVoter.Unlock() + + votes := 0 + + if delegates, ok := v.VoterDelegates[voterAddress]; ok { + votes = len(delegates) + } + + if votes+len(delegates) > consensus.MaxNumberOfVotes { + v.AddInvalidVote(hash, height) + return false + } + + for _, delegate := range delegates { + if _, ok := v.DelegateName[delegate]; !ok { + v.AddInvalidVote(hash, height) + return false + } + if voters, ok := v.DelegateVoters[delegate]; ok { + if _, ok = voters[voterAddress]; ok { + v.AddInvalidVote(hash, height) + return false + } else { + v.DelegateVoters[delegate][voterAddress] = true + } + } else { + v.DelegateVoters[delegate][voterAddress] = true + } + v.VoterDelegates[voterAddress][delegate] = true + } + + return true +} + +func (v *Vote) ProcessCancelVote(voterAddress string, delegates []string, hash bc.Hash, height uint64) bool { + v.lockVoter.Lock() + defer v.lockVoter.Unlock() + + for _, delegate := range delegates { + if voters, ok := v.DelegateVoters[delegate]; ok { + if _, ok = voters[voterAddress]; !ok { + v.AddInvalidVote(hash, height) + return false + } else { + if len(voters) == 1 { + delete(v.DelegateVoters, delegate) + } else { + delete(v.DelegateVoters[delegate], voterAddress) + } + } + } else { + v.AddInvalidVote(hash, height) + return false + } + } + + if item, ok := v.VoterDelegates[voterAddress]; ok { + for _, delegate := range delegates { + delete(v.VoterDelegates[voterAddress], delegate) + } + if len(item) == 0 { + delete(v.VoterDelegates, voterAddress) + } + } + + 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 + } + return v.read() +} + +func (v *Vote) Delete(blockHash bc.Hash) { + os.Remove(v.delegateFileName + "-" + blockHash.String()) + os.Remove(v.voteFileName + "-" + blockHash.String()) + os.Remove(v.balanceFileName + "-" + blockHash.String()) +} + +func (v *Vote) Store(blockHeight uint64, blockHash bc.Hash) error { + if blockHeight == 0 { + return nil + } + if err := v.Write(blockHash); err != nil { + return err + } + + if err := v.WriteControlFile(blockHeight, blockHash, v.controlFileName+"-temp"); err != nil { + return err + } + + var ( + blockHeightTemp uint64 + blockHashTemp bc.Hash + ) + + 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") + + return nil +} + +type forger struct { + DelegateVoters map[string]map[string]bool `json:"delegate_voters"` + VoterDelegates map[string]map[string]bool `json:"voter_delegates"` + DelegateName map[string]string `json:"delegate_name"` + NameDelegate map[string]string `json:"name_delegate"` + HashHeightInvalidVote map[bc.Hash]uint64 `json:"hash_height_invalid_vote"` + AddressBalances map[string]uint64 `json:"address_balance"` + DelegateMultiaddress map[string]uint64 `json:"delegate_multiaddress"` +} + +func (v *Vote) Write(blockHash bc.Hash) error { + + f := forger{ + DelegateVoters: v.DelegateVoters, + VoterDelegates: v.VoterDelegates, + DelegateName: v.DelegateName, + NameDelegate: v.NameDelegate, + HashHeightInvalidVote: v.HashHeightInvalidVote, + 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 + } + defer fileObj.Close() + + var data []byte + + if data, err = json.Marshal(&f); err != nil { + return err + } + + if _, err = fileObj.Write(data); err != nil { + return err + } + + return nil +} + +func (v *Vote) read() error { + + if err := v.ReadControlFile(&v.oldBlockHeight, &v.oldBlockHash, v.controlFileName); err != nil { + return err + } + + fileObj, err := os.OpenFile(v.forgerFileName+"-"+v.oldBlockHash.String(), os.O_RDONLY, 0644) + 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 { + return err + } + + v.DelegateVoters = f.DelegateVoters + v.VoterDelegates = f.VoterDelegates + v.DelegateName = f.DelegateName + v.NameDelegate = f.NameDelegate + v.HashHeightInvalidVote = f.HashHeightInvalidVote + v.AddressBalances = f.AddressBalances + v.DelegateMultiaddress = f.DelegateMultiaddress + + return nil +} + +func (v *Vote) repairFile(blockHeight uint64, blockHash bc.Hash) error { + return nil +} + +func (v *Vote) GetTopDelegateInfo(minHoldBalance uint64, delegateNum uint64) []Delegate { + var result []Delegate + + return result +} + +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) + 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 { + return err + } + + *blockHash = c.BlockHash + *blockHeight = c.BlockHeight + return nil +} + +func (v *Vote) WriteControlFile(blockHeight uint64, blockHash bc.Hash, fileName string) error { + + fileObj, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) + if err != nil { + return err + } + defer fileObj.Close() + + c := control{ + BlockHeight: blockHeight, + BlockHash: blockHash, + } + + var data []byte + + if data, err = json.Marshal(&c); err != nil { + return err + } + + if _, err = fileObj.Write(data); err != nil { + return err + } + + return nil +} + +func (v *Vote) UpdateAddressBalance(AddressBalance []AddressBalance) { + +} diff --git a/consensus/consensus/vote_type.go b/consensus/consensus/vote_type.go new file mode 100644 index 00000000..d25a0aaa --- /dev/null +++ b/consensus/consensus/vote_type.go @@ -0,0 +1,45 @@ +package consensus + +import ( + "github.com/vapor/crypto/ed25519/chainkd" + chainjson "github.com/vapor/encoding/json" +) + +// serflag variables for input types. +const ( + DelegateInfoType uint8 = iota + RegisterType + VoteType + CancelVoteType +) + +type TypedData interface { + DataType() uint8 +} + +// DELEGATE_IDS PUBKEY SIG(block.time) +type DelegateInfoList struct { + Delegate DelegateInfo + Xpub chainkd.XPub + SigTime []chainjson.HexBytes `json:"sig_time"` +} + +func (d *DelegateInfoList) DataType() uint8 { return DelegateInfoType } + +type RegisterForgerData struct { + Name string `json:"name"` +} + +func (d *RegisterForgerData) DataType() uint8 { return RegisterType } + +type VoteForgerData struct { + Forgers []string `json:"Forgers"` +} + +func (d *VoteForgerData) DataType() uint8 { return VoteType } + +type CancelVoteForgerData struct { + Forgers []string `json:"Forgers"` +} + +func (d *CancelVoteForgerData) DataType() uint8 { return CancelVoteType } diff --git a/consensus/general.go b/consensus/general.go index aad4c781..8db576d1 100644 --- a/consensus/general.go +++ b/consensus/general.go @@ -66,8 +66,13 @@ var BTMDefinitionMap = map[string]interface{}{ } const ( - Coin = 100000000 - MaxMoney = 2100000000 * Coin + Coin = 100000000 + MaxMoney = 2100000000 * Coin + RegisrerForgerFee = 1 * Coin + VoteForgerFee = 1000000 // 0.0.1 * Coin + CancelVoteForgerFee = 1000000 // 0.0.1 * Coin + MaxNumberOfVotes = 51 + MinHoldBalance = 500000000000 ) func MoneyRange(nValue uint64) bool { return nValue >= 0 && nValue <= MaxMoney } diff --git a/mining/miner/miner.go b/mining/miner/miner.go index 6e0e25d8..9b3f29da 100644 --- a/mining/miner/miner.go +++ b/mining/miner/miner.go @@ -104,8 +104,14 @@ 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 { + time.Sleep(1 * time.Second) + continue + } - block, err := mining.NewBlockTemplate(m.chain, m.txPool, m.accountManager, m.engine) + block, err := mining.NewBlockTemplate(m.chain, m.txPool, m.accountManager, m.engine, delegateInfo) if err != nil { log.Errorf("Mining: failed on create NewBlockTemplate: %v", err) time.Sleep(1 * time.Second) @@ -134,7 +140,7 @@ out: log.WithField("height", block.BlockHeader.Height).Errorf("Miner fail on ProcessBlock, %v", err) } // confirm block - m.sendConfirmTx(block.Height - 1) + //m.sendConfirmTx(block.Height - 1) time.Sleep(time.Duration(config.CommonConfig.Consensus.Dpos.Period) * time.Second) } diff --git a/mining/mining.go b/mining/mining.go index e2a6e671..dc47aaa6 100644 --- a/mining/mining.go +++ b/mining/mining.go @@ -1,6 +1,8 @@ package mining import ( + "encoding/binary" + "encoding/json" "sort" "strconv" "time" @@ -27,7 +29,7 @@ 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) (tx *types.Tx, err error) { +func createCoinbaseTx(accountManager *account.Manager, amount uint64, blockHeight uint64, delegateInfo engine.DelegateInfo, timestamp uint64) (tx *types.Tx, err error) { //amount += consensus.BlockSubsidy(blockHeight) arbitrary := append([]byte{0x00}, []byte(strconv.FormatUint(blockHeight, 10))...) @@ -48,6 +50,7 @@ func createCoinbaseTx(accountManager *account.Manager, amount uint64, blockHeigh if err = builder.AddInput(types.NewCoinbaseInput(arbitrary), &txbuilder.SigningInstruction{}); err != nil { return nil, err } + if err = builder.AddOutput(types.NewTxOutput(*consensus.BTMAssetID, amount, script)); err != nil { return nil, err } @@ -62,6 +65,27 @@ func createCoinbaseTx(accountManager *account.Manager, amount uint64, blockHeigh } txData.SerializedSize = uint64(len(byteData)) + delegates := engine.DelegateInfoList{} + delegates.Delegate = delegateInfo + + 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)) + + buf := [8]byte{} + binary.LittleEndian.PutUint64(buf[:], timestamp) + delegates.SigTime = xPrv.Sign(buf) + delegates.Xpub = xPrv.XPub() + + data, err := json.Marshal(&delegates) + if err != nil { + return nil, err + } + + txData.ReferenceData = data + tx = &types.Tx{ TxData: *txData, Tx: types.MapTx(txData), @@ -70,7 +94,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) (b *types.Block, err error) { +func NewBlockTemplate(c *protocol.Chain, txPool *protocol.TxPool, accountManager *account.Manager, engine engine.Engine, delegateInfo engine.DelegateInfo) (b *types.Block, err error) { view := state.NewUtxoViewpoint() txStatus := bc.NewTransactionStatus() if err := txStatus.SetStatus(0, false); err != nil { @@ -157,7 +181,7 @@ func NewBlockTemplate(c *protocol.Chain, txPool *protocol.TxPool, accountManager b.BlockHeader = header // creater coinbase transaction - b.Transactions[0], err = createCoinbaseTx(accountManager, txFee, nextBlockHeight) + b.Transactions[0], err = createCoinbaseTx(accountManager, txFee, nextBlockHeight, delegateInfo, bcBlock.Timestamp) if err != nil { return nil, errors.Wrap(err, "fail on createCoinbaseTx") } diff --git a/protocol/bc/bc.pb.go b/protocol/bc/bc.pb.go index 628ba87e..b3466143 100644 --- a/protocol/bc/bc.pb.go +++ b/protocol/bc/bc.pb.go @@ -487,8 +487,9 @@ func (m *BlockHeader) GetCoinbase() []byte { 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"` - TimeRange uint64 `protobuf:"varint,3,opt,name=time_range,json=timeRange" json:"time_range,omitempty"` - ResultIds []*Hash `protobuf:"bytes,4,rep,name=result_ids,json=resultIds" json:"result_ids,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"` } func (m *TxHeader) Reset() { *m = TxHeader{} } @@ -510,6 +511,13 @@ func (m *TxHeader) GetSerializedSize() uint64 { return 0 } +func (m *TxHeader) GetData() *Hash { + if m != nil { + return m.Data + } + return nil +} + func (m *TxHeader) GetTimeRange() uint64 { if m != nil { return m.TimeRange @@ -935,74 +943,74 @@ func init() { func init() { proto.RegisterFile("bc.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1091 bytes of a gzipped FileDescriptorProto + // 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, 0x24, 0x5b, 0xf6, 0xda, 0x49, 0x89, 0x20, 0x45, 0x02, 0x02, 0x89, - 0x5b, 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, 0x87, - 0xe8, 0x3b, 0xf4, 0x0d, 0xfa, 0x08, 0x3d, 0x15, 0x7d, 0x90, 0xbe, 0x44, 0xb1, 0xc3, 0xa5, 0x44, - 0xc9, 0xca, 0x1f, 0x8a, 0xa2, 0x08, 0x90, 0x1b, 0xe7, 0x67, 0xe7, 0xe7, 0x9b, 0xd9, 0x99, 0x25, - 0xb4, 0x06, 0xd1, 0x6e, 0xaa, 0xa4, 0x91, 0xa4, 0x3a, 0x88, 0x82, 0xe7, 0xe0, 0xbd, 0x60, 0xfa, - 0x92, 0xac, 0x43, 0x75, 0xba, 0xe7, 0x57, 0x1e, 0x56, 0xbe, 0x68, 0xd0, 0xea, 0x74, 0x0f, 0xe9, - 0x7d, 0xbf, 0xea, 0xe8, 0x7d, 0xa4, 0x0f, 0xfc, 0x9a, 0xa3, 0x0f, 0x90, 0x3e, 0xf4, 0x3d, 0x47, - 0x1f, 0x06, 0xdf, 0x41, 0xf3, 0x54, 0xc9, 0x91, 0x62, 0x13, 0xf2, 0x39, 0xc0, 0x74, 0x12, 0x4e, - 0xb9, 0xd2, 0x42, 0x26, 0x68, 0xd2, 0xa3, 0xed, 0xe9, 0xe4, 0x22, 0x67, 0x10, 0x02, 0x5e, 0x24, - 0x63, 0x8e, 0xb6, 0xbb, 0x14, 0xbf, 0x83, 0x3e, 0x34, 0x8f, 0xb4, 0xe6, 0xa6, 0x7f, 0xfc, 0xaf, - 0x03, 0x39, 0x81, 0x0e, 0x9a, 0x3a, 0x9a, 0xc8, 0x2c, 0x31, 0xe4, 0x31, 0xb4, 0x98, 0x25, 0x43, - 0x11, 0xa3, 0xd1, 0xce, 0x41, 0x67, 0x77, 0x10, 0xed, 0x3a, 0x6f, 0xb4, 0x89, 0xc2, 0x7e, 0x4c, - 0xee, 0x42, 0x83, 0xe1, 0x09, 0x74, 0xe5, 0x51, 0x47, 0x05, 0x23, 0xe8, 0xa1, 0xee, 0x31, 0x1f, - 0x8a, 0x44, 0x18, 0x9b, 0xc0, 0x37, 0xb0, 0x21, 0xb4, 0xce, 0x58, 0x12, 0xf1, 0x30, 0xcd, 0x73, - 0x2e, 0x9b, 0x76, 0x30, 0xd0, 0x5e, 0xa1, 0x54, 0xe0, 0x72, 0x1f, 0xbc, 0x98, 0x19, 0x86, 0x0e, - 0x3a, 0x07, 0x2d, 0xab, 0x6b, 0xa1, 0xa7, 0xc8, 0x0d, 0xc6, 0xd0, 0xb9, 0x60, 0xe3, 0x8c, 0x9f, - 0xc9, 0x4c, 0x45, 0x9c, 0xdc, 0x83, 0x9a, 0xe2, 0x43, 0x67, 0x77, 0xae, 0x6b, 0x99, 0xe4, 0x11, - 0xd4, 0xa7, 0x56, 0xd5, 0x59, 0xea, 0xcd, 0x12, 0xca, 0x73, 0xa6, 0xb9, 0x94, 0xdc, 0x83, 0x56, - 0x2a, 0x35, 0xc6, 0x8c, 0x78, 0x79, 0x74, 0x46, 0x07, 0x3f, 0xc3, 0x06, 0x7a, 0x3b, 0xe6, 0xda, - 0x88, 0x84, 0x61, 0x5e, 0xff, 0xb1, 0xcb, 0x9f, 0xa0, 0x7e, 0xaa, 0xa4, 0x1c, 0xda, 0x06, 0xd0, - 0x62, 0x94, 0x77, 0x46, 0x97, 0xe2, 0x37, 0x79, 0x0c, 0xeb, 0x91, 0x4c, 0x8c, 0x92, 0x63, 0x87, - 0x96, 0x6b, 0x8f, 0x25, 0x2e, 0xf1, 0xa1, 0xc9, 0xe2, 0x58, 0x71, 0xad, 0xd1, 0x7e, 0x97, 0x16, - 0x64, 0xf0, 0xba, 0x06, 0x1b, 0x4f, 0xaf, 0x8d, 0x9c, 0x3c, 0x1d, 0xcb, 0xe8, 0xd5, 0x0b, 0xce, - 0x62, 0xae, 0xac, 0xfa, 0x62, 0x1f, 0x16, 0xa4, 0xad, 0xf7, 0x25, 0x17, 0xa3, 0xcb, 0x59, 0xbd, - 0x73, 0x8a, 0x3c, 0x81, 0xcd, 0x54, 0xf1, 0xa9, 0x90, 0x99, 0x0e, 0x07, 0xd6, 0x92, 0x6d, 0x9c, - 0xda, 0x12, 0x24, 0xbd, 0x42, 0x05, 0x7d, 0xf5, 0x63, 0x72, 0x1f, 0xda, 0x46, 0x4c, 0xb8, 0x36, - 0x6c, 0x92, 0x62, 0x2f, 0x7a, 0x74, 0xce, 0x20, 0x5f, 0xc3, 0xa6, 0x51, 0x2c, 0xd1, 0x2c, 0xb2, - 0x40, 0xe8, 0x50, 0x49, 0x69, 0xfc, 0xfa, 0x92, 0xcd, 0x8d, 0xb2, 0x0a, 0x95, 0xd2, 0x90, 0xef, - 0xe1, 0xb3, 0x12, 0x2f, 0xd4, 0x86, 0x99, 0x4c, 0x87, 0x97, 0x4c, 0x5f, 0xfa, 0x8d, 0xa5, 0xc3, - 0x77, 0x4a, 0x8a, 0x67, 0xa8, 0x87, 0x97, 0x7a, 0x1b, 0xea, 0x89, 0x4c, 0x22, 0xee, 0x37, 0x31, - 0xa4, 0x9c, 0xb0, 0xf8, 0x0f, 0x84, 0xd1, 0x7e, 0x0b, 0x99, 0xf8, 0x4d, 0x8e, 0x81, 0xdc, 0xf6, - 0xe5, 0xb7, 0xd1, 0xcd, 0x1d, 0xeb, 0xe6, 0x7c, 0xd9, 0x01, 0xdd, 0xbc, 0xe5, 0x33, 0xf8, 0xab, - 0x06, 0x9d, 0x4f, 0xf0, 0xff, 0x5f, 0xf0, 0x93, 0x07, 0xee, 0x86, 0xf9, 0x80, 0x07, 0xdb, 0x6e, - 0x1a, 0xc9, 0x21, 0x75, 0x37, 0x6f, 0x1b, 0xea, 0xfc, 0xca, 0x28, 0xe6, 0x77, 0xf0, 0xee, 0xe4, - 0x84, 0xbd, 0xb4, 0x91, 0x14, 0xc9, 0x80, 0x69, 0xee, 0x77, 0x51, 0x30, 0xa3, 0x83, 0x5f, 0x2b, - 0xd0, 0x3a, 0xbf, 0x7a, 0x67, 0x39, 0x77, 0xa0, 0xa7, 0xb9, 0x12, 0x6c, 0x2c, 0x6e, 0x78, 0x1c, - 0x6a, 0x71, 0xc3, 0x5d, 0x5d, 0xd7, 0xe7, 0xec, 0x33, 0x71, 0xc3, 0xed, 0x6e, 0xb0, 0x85, 0x09, - 0x15, 0x4b, 0x46, 0xdc, 0x8d, 0x08, 0x2c, 0x15, 0xb5, 0x0c, 0xb2, 0x03, 0xa0, 0xb8, 0xce, 0xc6, - 0x76, 0x5c, 0x6b, 0xdf, 0x7b, 0x58, 0x5b, 0x80, 0xb9, 0x9d, 0xcb, 0xfa, 0xb1, 0x0e, 0xf6, 0x61, - 0xfd, 0xfc, 0xea, 0x82, 0x2b, 0x31, 0xbc, 0xa6, 0xc8, 0x24, 0x0f, 0xa0, 0xe3, 0x4a, 0x34, 0x64, - 0x62, 0x8c, 0x01, 0xb6, 0x28, 0xe4, 0xac, 0xe7, 0x4c, 0x8c, 0x83, 0x21, 0x6c, 0xde, 0x42, 0xf1, - 0x2d, 0x29, 0x7d, 0x0b, 0x6b, 0x53, 0xb4, 0x5f, 0x54, 0xa3, 0x8a, 0xd1, 0x10, 0xac, 0xc6, 0x82, - 0x6b, 0xda, 0xcd, 0x15, 0xdd, 0x25, 0xf8, 0xb3, 0x02, 0xb5, 0x93, 0xec, 0x8a, 0x7c, 0x09, 0x4d, - 0x8d, 0xb3, 0x5c, 0xfb, 0x15, 0x3c, 0x8a, 0x43, 0xb3, 0x34, 0xe3, 0x69, 0x21, 0x27, 0x8f, 0xa0, - 0x99, 0x96, 0xc6, 0xde, 0xd2, 0x22, 0x29, 0x64, 0xe4, 0x47, 0xd8, 0xfe, 0x45, 0x98, 0x84, 0x6b, - 0x1d, 0xc6, 0xf3, 0xb9, 0x6d, 0x27, 0xa1, 0x35, 0xbf, 0x3d, 0x33, 0x5f, 0x1a, 0xea, 0x74, 0xcb, - 0x9d, 0x28, 0xf1, 0x34, 0xf9, 0x0a, 0x36, 0x0b, 0x43, 0x4c, 0x8d, 0xb2, 0x09, 0x4f, 0x4c, 0x8e, - 0x76, 0x97, 0x6e, 0x38, 0xc1, 0x51, 0xc1, 0x0f, 0x24, 0xb4, 0x9e, 0xb9, 0x76, 0x20, 0x3f, 0xc0, - 0xd6, 0x8a, 0x08, 0xdc, 0xca, 0x58, 0x1d, 0x00, 0xb9, 0x1d, 0x80, 0xbd, 0xaf, 0x4c, 0x0d, 0x84, - 0x51, 0x4c, 0x5d, 0xbb, 0x41, 0x3f, 0x67, 0x04, 0xaf, 0x2b, 0xd0, 0x78, 0x99, 0x99, 0x34, 0x33, - 0x64, 0x07, 0x1a, 0x39, 0x46, 0xce, 0xc5, 0x2d, 0x08, 0x9d, 0x98, 0x3c, 0x81, 0x9e, 0xdb, 0x14, - 0xe1, 0x5b, 0x90, 0x5c, 0xb1, 0x4d, 0xa4, 0x8a, 0x45, 0xc2, 0xc6, 0xae, 0x15, 0x0b, 0x32, 0x78, - 0x09, 0x40, 0xb9, 0x11, 0x8a, 0x5b, 0x0c, 0xde, 0x3f, 0x8c, 0x92, 0xc1, 0xea, 0xa2, 0xc1, 0xdf, - 0xab, 0xd0, 0xea, 0xbb, 0x07, 0x81, 0x6d, 0x73, 0x9c, 0x05, 0xf9, 0x34, 0x59, 0x5e, 0xb8, 0x6d, - 0x94, 0xe1, 0x04, 0x79, 0xcf, 0xb5, 0xfb, 0x86, 0xb2, 0xd4, 0x3e, 0xb0, 0x2c, 0x27, 0xe0, 0xcf, - 0xda, 0x02, 0xdf, 0x4c, 0xf1, 0xec, 0xd1, 0x83, 0x53, 0xb5, 0x73, 0xb0, 0x35, 0x0b, 0x60, 0xfe, - 0x1e, 0xa2, 0x77, 0x8b, 0x96, 0x59, 0x7a, 0x27, 0xad, 0xec, 0xb2, 0xfa, 0xea, 0x2e, 0x2b, 0x23, - 0xd7, 0x58, 0x44, 0xee, 0x8f, 0x0a, 0xd4, 0xcf, 0x52, 0x9e, 0xc4, 0x64, 0x0f, 0x7a, 0x3a, 0xe5, - 0x89, 0x09, 0x25, 0x76, 0xc7, 0xfc, 0x49, 0x37, 0xc7, 0x6e, 0x0d, 0x15, 0xf2, 0xee, 0xe9, 0xc7, - 0x6f, 0x02, 0xa6, 0xfa, 0x81, 0xc0, 0xac, 0xcc, 0xa4, 0xf6, 0xee, 0x4c, 0xbc, 0xc5, 0x4c, 0xfe, - 0xae, 0x40, 0xfd, 0xd9, 0x98, 0x89, 0xc9, 0xc7, 0x9e, 0x09, 0x09, 0xa0, 0x7b, 0xca, 0x47, 0x22, - 0x71, 0x47, 0x5c, 0x55, 0x17, 0x78, 0xc1, 0x6f, 0x55, 0xf0, 0x8e, 0x53, 0xa9, 0x3f, 0xfa, 0x64, - 0x09, 0x78, 0xe6, 0x3a, 0xe5, 0xf8, 0x64, 0x58, 0xa3, 0xf8, 0x6d, 0x79, 0x43, 0x25, 0x27, 0xd8, - 0xab, 0x6d, 0x8a, 0xdf, 0xf6, 0x4f, 0xc4, 0x48, 0xdc, 0xf5, 0x6d, 0x5a, 0x35, 0xd2, 0x6e, 0x5b, - 0x6d, 0xd8, 0x2b, 0xee, 0x36, 0x7d, 0x4e, 0xd8, 0x93, 0xf8, 0x17, 0xd0, 0xce, 0x4f, 0xda, 0xef, - 0x41, 0x03, 0xff, 0xc7, 0x0e, 0xff, 0x09, 0x00, 0x00, 0xff, 0xff, 0x3a, 0x3c, 0x20, 0xe3, 0x9b, - 0x0d, 0x00, 0x00, + 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, } diff --git a/protocol/bc/bc.proto b/protocol/bc/bc.proto index 59d70c22..e45143a4 100644 --- a/protocol/bc/bc.proto +++ b/protocol/bc/bc.proto @@ -84,8 +84,9 @@ message BlockHeader { message TxHeader { uint64 version = 1; uint64 serialized_size = 2; - uint64 time_range = 3; - repeated Hash result_ids = 4; + Hash data = 3; + uint64 time_range = 4; + repeated Hash result_ids = 5; } message TxVerifyResult { diff --git a/protocol/bc/txheader.go b/protocol/bc/txheader.go index ab247282..048ef73b 100644 --- a/protocol/bc/txheader.go +++ b/protocol/bc/txheader.go @@ -12,13 +12,15 @@ func (h *TxHeader) writeForHash(w io.Writer) { mustWriteForHash(w, h.Version) mustWriteForHash(w, h.TimeRange) mustWriteForHash(w, h.ResultIds) + mustWriteForHash(w, h.Data) } // NewTxHeader creates an new TxHeader. -func NewTxHeader(version, serializedSize, timeRange uint64, resultIDs []*Hash) *TxHeader { +func NewTxHeader(version, serializedSize uint64, data *Hash, timeRange uint64, resultIDs []*Hash) *TxHeader { return &TxHeader{ Version: version, SerializedSize: serializedSize, + Data: data, TimeRange: timeRange, ResultIds: resultIDs, } diff --git a/protocol/bc/types/bytom/types/map.go b/protocol/bc/types/bytom/types/map.go index a878259e..09e1fa4a 100644 --- a/protocol/bc/types/bytom/types/map.go +++ b/protocol/bc/types/bytom/types/map.go @@ -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, tx.TimeRange, resultIDs) + h := bc.NewTxHeader(tx.Version, tx.SerializedSize, &bc.Hash{}, tx.TimeRange, resultIDs) return addEntry(h), h, entryMap } diff --git a/protocol/bc/types/map.go b/protocol/bc/types/map.go index e68f17ab..8dd10a49 100644 --- a/protocol/bc/types/map.go +++ b/protocol/bc/types/map.go @@ -2,6 +2,7 @@ package types import ( "github.com/vapor/consensus" + "github.com/vapor/crypto/sha3pool" "github.com/vapor/protocol/bc" "github.com/vapor/protocol/vm" "github.com/vapor/protocol/vm/vmutil" @@ -213,7 +214,6 @@ func mapTx(tx *TxData) (headerID bc.Hash, hdr *bc.TxHeader, entryMap map[bc.Hash r := bc.NewRetirement(src, uint64(i)) resultID = addEntry(r) } else { - // non-retirement prog := &bc.Program{out.VMVersion, out.ControlProgram} o := bc.NewOutput(src, prog, uint64(i)) @@ -228,7 +228,8 @@ func mapTx(tx *TxData) (headerID bc.Hash, hdr *bc.TxHeader, entryMap map[bc.Hash resultIDs = append(resultIDs, &resultID) mux.WitnessDestinations = append(mux.WitnessDestinations, dest) } - h := bc.NewTxHeader(tx.Version, tx.SerializedSize, tx.TimeRange, resultIDs) + refdatahash := hashData(tx.ReferenceData) + h := bc.NewTxHeader(tx.Version, tx.SerializedSize, &refdatahash, tx.TimeRange, resultIDs) return addEntry(h), h, entryMap } @@ -251,3 +252,9 @@ func MapBlock(old *Block) *bc.Block { } return b } + +func hashData(data []byte) bc.Hash { + var b32 [32]byte + sha3pool.Sum256(b32[:], data) + return bc.NewHash(b32) +} diff --git a/protocol/bc/types/transaction.go b/protocol/bc/types/transaction.go index a862762a..c98e673e 100644 --- a/protocol/bc/types/transaction.go +++ b/protocol/bc/types/transaction.go @@ -63,6 +63,7 @@ type TxData struct { TimeRange uint64 Inputs []*TxInput Outputs []*TxOutput + ReferenceData []byte } // MarshalText fulfills the json.Marshaler interface. diff --git a/protocol/block.go b/protocol/block.go index d263754f..1771a990 100644 --- a/protocol/block.go +++ b/protocol/block.go @@ -1,8 +1,14 @@ package protocol import ( + "encoding/json" + "fmt" + log "github.com/sirupsen/logrus" + "github.com/vapor/common" + "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" @@ -158,9 +164,10 @@ 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, c.engine); err != nil { + if err := validation.ValidateBlock(bcBlock, parent, block, c); err != nil { return errors.Sub(ErrBadBlock, err) } + if err := c.store.SaveBlock(block, bcBlock.TransactionStatus); err != nil { return err } @@ -258,3 +265,97 @@ func (c *Chain) processBlock(block *types.Block) (bool, error) { } return false, nil } + +func (c *Chain) ProcessDPoSConnectBlock(block *types.Block) { + mapTxFee := c.CalculateBalance(block, true) + fmt.Println(mapTxFee) +} + +func DoVoting(block *types.Block, mapTxFee map[bc.Hash]uint64) error { + for _, tx := range block.Transactions { + to := tx.Outputs[0] + var delegate engine.TypedData + + if err := json.Unmarshal(tx.TxData.ReferenceData, delegate); err != nil && to.Amount > 0 { + continue + } + var ( + address common.Address + err error + ) + address, err = common.NewAddressWitnessPubKeyHash(to.ControlProgram[2:], &consensus.ActiveNetParams) + if err != nil { + address, err = common.NewAddressWitnessScriptHash(to.ControlProgram[2:], &consensus.ActiveNetParams) + if err != nil { + return errors.New("ControlProgram cannot be converted to address") + } + } + hash := block.Hash() + height := block.Height + switch data := delegate.(type) { + case *engine.DelegateInfoList: + continue + case *engine.RegisterForgerData: + if mapTxFee[tx.Tx.ID] >= consensus.RegisrerForgerFee { + engine.DposVote.ProcessRegister(address.EncodeAddress(), data.Name, hash, height) + } + case *engine.VoteForgerData: + if mapTxFee[tx.Tx.ID] >= consensus.VoteForgerFee { + engine.DposVote.ProcessVote(address.EncodeAddress(), data.Forgers, hash, height) + } + case *engine.CancelVoteForgerData: + if mapTxFee[tx.Tx.ID] >= consensus.CancelVoteForgerFee { + engine.DposVote.ProcessCancelVote(address.EncodeAddress(), data.Forgers, hash, height) + } + } + } + return nil +} + +func (c *Chain) CalculateBalance(block *types.Block, fIsAdd bool) map[bc.Hash]uint64 { + + addressBalances := []engine.AddressBalance{} + mapTxFee := make(map[bc.Hash]uint64) + var ( + address common.Address + err error + ) + + for _, tx := range block.Transactions { + fee := uint64(0) + for _, input := range tx.Inputs { + fee += input.Amount() + value := int64(input.Amount()) + address, err = common.NewAddressWitnessPubKeyHash(input.ControlProgram()[2:], &consensus.ActiveNetParams) + if err != nil { + address, err = common.NewAddressWitnessScriptHash(input.ControlProgram()[2:], &consensus.ActiveNetParams) + if err != nil { + continue + } + } + if fIsAdd { + value = 0 - value + } + addressBalances = append(addressBalances, engine.AddressBalance{address.EncodeAddress(), value}) + } + for _, output := range tx.Outputs { + fee -= output.Amount + value := int64(output.Amount) + address, err = common.NewAddressWitnessPubKeyHash(output.ControlProgram[2:], &consensus.ActiveNetParams) + if err != nil { + address, err = common.NewAddressWitnessScriptHash(output.ControlProgram[2:], &consensus.ActiveNetParams) + if err != nil { + continue + } + } + if fIsAdd { + value = 0 - value + } + addressBalances = append(addressBalances, engine.AddressBalance{address.EncodeAddress(), value}) + } + mapTxFee[tx.Tx.ID] = fee + } + + engine.DposVote.UpdateAddressBalance(addressBalances) + return mapTxFee +} diff --git a/protocol/validation/block.go b/protocol/validation/block.go index 3f8f522c..aa18b552 100644 --- a/protocol/validation/block.go +++ b/protocol/validation/block.go @@ -56,7 +56,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, engine engine.Engine) error { +func ValidateBlockHeader(b *bc.Block, block *types.Block, parent *state.BlockNode, c chain.Chain) error { if b.Version < parent.Version { return errors.WithDetailf(errVersionRegression, "previous block verson %d, current block version %d", parent.Version, b.Version) } @@ -69,7 +69,12 @@ func ValidateBlockHeader(b *bc.Block, block *types.Block, parent *state.BlockNod if err := checkBlockTime(b, parent); err != nil { return err } - if err := engine.VerifySeal(c, &block.BlockHeader); err != nil { + + if err := engine.GDpos.CheckBlockHeader(block.BlockHeader); err != nil { + return err + } + + if err := engine.GDpos.IsValidBlockCheckIrreversibleBlock(block.Height, block.Hash()); err != nil { return err } @@ -77,9 +82,13 @@ func ValidateBlockHeader(b *bc.Block, block *types.Block, parent *state.BlockNod } // ValidateBlock validates a block and the transactions within. -func ValidateBlock(b *bc.Block, parent *state.BlockNode, block *types.Block, c chain.Chain, engine engine.Engine) error { +func ValidateBlock(b *bc.Block, parent *state.BlockNode, block *types.Block, c chain.Chain) error { startTime := time.Now() - if err := ValidateBlockHeader(b, block, parent, c, engine); err != nil { + if err := ValidateBlockHeader(b, block, parent, c); err != nil { + return err + } + + if err := engine.GDpos.CheckBlock(*block, true); err != nil { return err }