OSDN Git Service

edit code while reviw (#253)
authorPaladz <yzhu101@uottawa.ca>
Tue, 9 Jul 2019 02:20:55 +0000 (10:20 +0800)
committerGitHub <noreply@github.com>
Tue, 9 Jul 2019 02:20:55 +0000 (10:20 +0800)
* edit code while reviw

* edit the code format

protocol/state/consensus_result.go
protocol/state/utxo_view.go
protocol/txpool.go
protocol/validation/vmcontext.go

index e136848..16fcded 100644 (file)
@@ -29,30 +29,6 @@ func (c byVote) Less(i, j int) bool {
 }
 func (c byVote) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
 
-// CalcVoteSeq calculate the vote sequence
-// seq 0 is the genesis block
-// seq 1 is the the block height 1, to block height RoundVoteBlockNums
-// seq 2 is the block height RoundVoteBlockNums + 1 to block height 2 * RoundVoteBlockNums
-// consensus node of the current round is the final result of previous round
-func CalcVoteSeq(blockHeight uint64) uint64 {
-       if blockHeight == 0 {
-               return 0
-       }
-       return (blockHeight-1)/consensus.RoundVoteBlockNums + 1
-}
-
-// ConsensusResult represents a snapshot of each round of DPOS voting
-// Seq indicates the sequence of current votes, which start from zero
-// NumOfVote indicates the number of votes each consensus node receives, the key of map represent public key
-// CoinbaseReward indicates the coinbase receiver and reward
-type ConsensusResult struct {
-       Seq            uint64
-       NumOfVote      map[string]uint64
-       CoinbaseReward map[string]uint64
-       BlockHash      bc.Hash
-       BlockHeight    uint64
-}
-
 // CoinbaseReward contains receiver and reward
 type CoinbaseReward struct {
        Amount         uint64
@@ -68,28 +44,47 @@ func (a SortByAmount) Less(i, j int) bool { return a[i].Amount < a[j].Amount }
 
 // CalCoinbaseReward calculate the coinbase reward for block
 func CalCoinbaseReward(block *types.Block) (*CoinbaseReward, error) {
-       var coinbaseReceiver []byte
+       result := &CoinbaseReward{}
        if len(block.Transactions) > 0 && len(block.Transactions[0].Outputs) > 0 {
-               coinbaseReceiver = block.Transactions[0].Outputs[0].ControlProgram()
-       }
-
-       if coinbaseReceiver == nil {
+               result.ControlProgram = block.Transactions[0].Outputs[0].ControlProgram()
+       } else {
                return nil, errors.New("not found coinbase receiver")
        }
 
-       coinbaseAmount := consensus.BlockSubsidy(block.BlockHeader.Height)
+       result.Amount = consensus.BlockSubsidy(block.BlockHeader.Height)
        for _, tx := range block.Transactions {
                txFee, err := arithmetic.CalculateTxFee(tx)
                if err != nil {
                        return nil, errors.Wrap(checked.ErrOverflow, "calculate transaction fee")
                }
-               coinbaseAmount += txFee
+
+               result.Amount += txFee
+       }
+       return result, nil
+}
+
+// CalcVoteSeq calculate the vote sequence
+// seq 0 is the genesis block
+// seq 1 is the the block height 1, to block height RoundVoteBlockNums
+// seq 2 is the block height RoundVoteBlockNums + 1 to block height 2 * RoundVoteBlockNums
+// consensus node of the current round is the final result of previous round
+func CalcVoteSeq(blockHeight uint64) uint64 {
+       if blockHeight == 0 {
+               return 0
        }
+       return (blockHeight-1)/consensus.RoundVoteBlockNums + 1
+}
 
-       return &CoinbaseReward{
-               Amount:         coinbaseAmount,
-               ControlProgram: coinbaseReceiver,
-       }, nil
+// ConsensusResult represents a snapshot of each round of DPOS voting
+// Seq indicates the sequence of current votes, which start from zero
+// NumOfVote indicates the number of votes each consensus node receives, the key of map represent public key
+// CoinbaseReward indicates the coinbase receiver and reward
+type ConsensusResult struct {
+       Seq            uint64
+       NumOfVote      map[string]uint64
+       CoinbaseReward map[string]uint64
+       BlockHash      bc.Hash
+       BlockHeight    uint64
 }
 
 // ApplyBlock calculate the consensus result for new block
@@ -139,6 +134,26 @@ func (c *ConsensusResult) ApplyBlock(block *types.Block) error {
        return nil
 }
 
+// AttachCoinbaseReward attach coinbase reward
+func (c *ConsensusResult) AttachCoinbaseReward(block *types.Block) error {
+       reward, err := CalCoinbaseReward(block)
+       if err != nil {
+               return err
+       }
+
+       if block.Height%consensus.RoundVoteBlockNums == 1 {
+               c.CoinbaseReward = map[string]uint64{}
+       }
+
+       var ok bool
+       program := hex.EncodeToString(reward.ControlProgram)
+       c.CoinbaseReward[program], ok = checked.AddUint64(c.CoinbaseReward[program], reward.Amount)
+       if !ok {
+               return checked.ErrOverflow
+       }
+       return nil
+}
+
 // ConsensusNodes returns all consensus nodes
 func (c *ConsensusResult) ConsensusNodes() (map[string]*ConsensusNode, error) {
        var nodes []*ConsensusNode
@@ -167,14 +182,6 @@ func (c *ConsensusResult) ConsensusNodes() (map[string]*ConsensusNode, error) {
        return federationNodes(), nil
 }
 
-func federationNodes() map[string]*ConsensusNode {
-       consensusResult := map[string]*ConsensusNode{}
-       for i, xpub := range config.CommonConfig.Federation.Xpubs {
-               consensusResult[xpub.String()] = &ConsensusNode{XPub: xpub, VoteNum: 0, Order: uint64(i)}
-       }
-       return consensusResult
-}
-
 // DetachBlock calculate the consensus result for detach block
 func (c *ConsensusResult) DetachBlock(block *types.Block) error {
        if c.BlockHash != block.Hash() {
@@ -223,49 +230,6 @@ func (c *ConsensusResult) DetachBlock(block *types.Block) error {
        return nil
 }
 
-func (c *ConsensusResult) Fork() *ConsensusResult {
-       f := &ConsensusResult{
-               Seq:            c.Seq,
-               NumOfVote:      map[string]uint64{},
-               CoinbaseReward: map[string]uint64{},
-               BlockHash:      c.BlockHash,
-               BlockHeight:    c.BlockHeight,
-       }
-
-       for key, value := range c.NumOfVote {
-               f.NumOfVote[key] = value
-       }
-
-       for key, value := range c.CoinbaseReward {
-               f.CoinbaseReward[key] = value
-       }
-       return f
-}
-
-func (c *ConsensusResult) IsFinalize() bool {
-       return c.BlockHeight%consensus.RoundVoteBlockNums == 0
-}
-
-// AttachCoinbaseReward attach coinbase reward
-func (c *ConsensusResult) AttachCoinbaseReward(block *types.Block) error {
-       reward, err := CalCoinbaseReward(block)
-       if err != nil {
-               return err
-       }
-
-       if block.Height%consensus.RoundVoteBlockNums == 1 {
-               c.CoinbaseReward = map[string]uint64{}
-       }
-
-       var ok bool
-       program := hex.EncodeToString(reward.ControlProgram)
-       c.CoinbaseReward[program], ok = checked.AddUint64(c.CoinbaseReward[program], reward.Amount)
-       if !ok {
-               return checked.ErrOverflow
-       }
-       return nil
-}
-
 // DetachCoinbaseReward detach coinbase reward
 func (c *ConsensusResult) DetachCoinbaseReward(block *types.Block) error {
        if block.Height%consensus.RoundVoteBlockNums == 0 {
@@ -295,6 +259,31 @@ func (c *ConsensusResult) DetachCoinbaseReward(block *types.Block) error {
        return nil
 }
 
+// Fork copy the ConsensusResult struct
+func (c *ConsensusResult) Fork() *ConsensusResult {
+       f := &ConsensusResult{
+               Seq:            c.Seq,
+               NumOfVote:      map[string]uint64{},
+               CoinbaseReward: map[string]uint64{},
+               BlockHash:      c.BlockHash,
+               BlockHeight:    c.BlockHeight,
+       }
+
+       for key, value := range c.NumOfVote {
+               f.NumOfVote[key] = value
+       }
+
+       for key, value := range c.CoinbaseReward {
+               f.CoinbaseReward[key] = value
+       }
+       return f
+}
+
+// IsFinalize check if the result is end of consensus round
+func (c *ConsensusResult) IsFinalize() bool {
+       return c.BlockHeight%consensus.RoundVoteBlockNums == 0
+}
+
 // GetCoinbaseRewards convert into CoinbaseReward array and sort it by amount
 func (c *ConsensusResult) GetCoinbaseRewards(blockHeight uint64) ([]CoinbaseReward, error) {
        rewards := []CoinbaseReward{}
@@ -303,17 +292,24 @@ func (c *ConsensusResult) GetCoinbaseRewards(blockHeight uint64) ([]CoinbaseRewa
        }
 
        for p, amount := range c.CoinbaseReward {
-               coinbaseAmount := amount
                program, err := hex.DecodeString(p)
                if err != nil {
                        return nil, err
                }
 
                rewards = append(rewards, CoinbaseReward{
-                       Amount:         coinbaseAmount,
+                       Amount:         amount,
                        ControlProgram: program,
                })
        }
        sort.Sort(SortByAmount(rewards))
        return rewards, nil
 }
+
+func federationNodes() map[string]*ConsensusNode {
+       consensusResult := map[string]*ConsensusNode{}
+       for i, xpub := range config.CommonConfig.Federation.Xpubs {
+               consensusResult[xpub.String()] = &ConsensusNode{XPub: xpub, VoteNum: 0, Order: uint64(i)}
+       }
+       return consensusResult
+}
index 90c71b1..4e0d56c 100644 (file)
@@ -20,80 +20,93 @@ func NewUtxoViewpoint() *UtxoViewpoint {
 }
 
 func (view *UtxoViewpoint) ApplyTransaction(block *bc.Block, tx *bc.Tx, statusFail bool) error {
-       for _, prevout := range tx.MainchainOutputIDs {
-               entry, ok := view.Entries[prevout]
-               if !ok {
-                       return errors.New("fail to find mainchain output entry")
-               }
+       if err := view.applyCrossChainUtxo(block, tx); err != nil {
+               return err
+       }
 
-               if entry.Type != storage.CrosschainUTXOType {
-                       return errors.New("look up mainchainOutputID but find utxo not from mainchain")
+       if err := view.applySpendUtxo(block, tx, statusFail); err != nil {
+               return err
+       }
+
+       return view.applyOutputUtxo(block, tx, statusFail)
+}
+
+func (view *UtxoViewpoint) ApplyBlock(block *bc.Block, txStatus *bc.TransactionStatus) error {
+       for i, tx := range block.Transactions {
+               statusFail, err := txStatus.GetStatus(i)
+               if err != nil {
+                       return err
                }
 
-               if entry.Spent {
-                       return errors.New("mainchain output has been spent")
+               if err := view.ApplyTransaction(block, tx, statusFail); err != nil {
+                       return err
                }
+       }
+       return nil
+}
 
-               entry.BlockHeight = block.Height
-               entry.SpendOutput()
+func (view *UtxoViewpoint) CanSpend(hash *bc.Hash) bool {
+       entry := view.Entries[*hash]
+       return entry != nil && !entry.Spent
+}
+
+func (view *UtxoViewpoint) DetachTransaction(tx *bc.Tx, statusFail bool) error {
+       if err := view.detachCrossChainUtxo(tx); err != nil {
+               return err
        }
 
-       for _, prevout := range tx.SpentOutputIDs {
-               assetID := bc.AssetID{}
-               entryOutput, err := tx.Entry(prevout)
+       if err := view.detachSpendUtxo(tx, statusFail); err != nil {
+               return err
+       }
+
+       return view.detachOutputUtxo(tx, statusFail)
+}
+
+func (view *UtxoViewpoint) DetachBlock(block *bc.Block, txStatus *bc.TransactionStatus) error {
+       for i := len(block.Transactions) - 1; i >= 0; i-- {
+               statusFail, err := txStatus.GetStatus(i)
                if err != nil {
                        return err
                }
 
-               switch output := entryOutput.(type) {
-               case *bc.IntraChainOutput:
-                       assetID = *output.Source.Value.AssetId
-               case *bc.VoteOutput:
-                       assetID = *output.Source.Value.AssetId
-               default:
-                       return errors.Wrapf(bc.ErrEntryType, "entry %x has unexpected type %T", prevout.Bytes(), entryOutput)
+               if err := view.DetachTransaction(block.Transactions[i], statusFail); err != nil {
+                       return err
                }
+       }
+       return nil
+}
 
-               if statusFail && assetID != *consensus.BTMAssetID {
-                       continue
-               }
+func (view *UtxoViewpoint) HasUtxo(hash *bc.Hash) bool {
+       _, ok := view.Entries[*hash]
+       return ok
+}
 
+func (view *UtxoViewpoint) applyCrossChainUtxo(block *bc.Block, tx *bc.Tx) error {
+       for _, prevout := range tx.MainchainOutputIDs {
                entry, ok := view.Entries[prevout]
                if !ok {
-                       return errors.New("fail to find utxo entry")
+                       return errors.New("fail to find mainchain output entry")
                }
 
                if entry.Spent {
-                       return errors.New("utxo has been spent")
-               }
-
-               switch entry.Type {
-               case storage.CrosschainUTXOType:
-                       return errors.New("look up spentOutputID but find utxo from mainchain")
-
-               case storage.CoinbaseUTXOType:
-                       if (entry.BlockHeight + consensus.CoinbasePendingBlockNumber) > block.Height {
-                               return errors.New("coinbase utxo is not ready for use")
-                       }
-
-               case storage.VoteUTXOType:
-                       if (entry.BlockHeight + consensus.VotePendingBlockNumber) > block.Height {
-                               return errors.New("Coin is  within the voting lock time")
-                       }
+                       return errors.New("mainchain output has been spent")
                }
 
+               entry.BlockHeight = block.Height
                entry.SpendOutput()
        }
+       return nil
+}
 
+func (view *UtxoViewpoint) applyOutputUtxo(block *bc.Block, tx *bc.Tx, statusFail bool) error {
        for _, id := range tx.TxHeader.ResultIds {
-               assetID := bc.AssetID{}
                entryOutput, err := tx.Entry(*id)
                if err != nil {
-                       continue
+                       return err
                }
 
+               var assetID bc.AssetID
                utxoType := storage.NormalUTXOType
-
                switch output := entryOutput.(type) {
                case *bc.IntraChainOutput:
                        if output.Source.Value.Amount == uint64(0) {
@@ -120,57 +133,19 @@ func (view *UtxoViewpoint) ApplyTransaction(block *bc.Block, tx *bc.Tx, statusFa
        return nil
 }
 
-func (view *UtxoViewpoint) ApplyBlock(block *bc.Block, txStatus *bc.TransactionStatus) error {
-       for i, tx := range block.Transactions {
-               statusFail, err := txStatus.GetStatus(i)
-               if err != nil {
-                       return err
-               }
-               if err := view.ApplyTransaction(block, tx, statusFail); err != nil {
-                       return err
-               }
-       }
-       return nil
-}
-
-func (view *UtxoViewpoint) CanSpend(hash *bc.Hash) bool {
-       entry := view.Entries[*hash]
-       return entry != nil && !entry.Spent
-}
-
-func (view *UtxoViewpoint) DetachTransaction(tx *bc.Tx, statusFail bool) error {
-       for _, prevout := range tx.MainchainOutputIDs {
-               // don't simply delete(view.Entries, prevout), because we need to delete from db in saveUtxoView()
-               entry, ok := view.Entries[prevout]
-               if ok && (entry.Type != storage.CrosschainUTXOType) {
-                       return errors.New("look up mainchainOutputID but find utxo not from mainchain")
-               }
-
-               if ok && !entry.Spent {
-                       return errors.New("try to revert an unspent utxo")
-               }
-
-               if !ok {
-                       view.Entries[prevout] = storage.NewUtxoEntry(storage.CrosschainUTXOType, 0, false)
-                       continue
-               }
-               entry.UnspendOutput()
-       }
-
+func (view *UtxoViewpoint) applySpendUtxo(block *bc.Block, tx *bc.Tx, statusFail bool) error {
        for _, prevout := range tx.SpentOutputIDs {
-               assetID := bc.AssetID{}
                entryOutput, err := tx.Entry(prevout)
                if err != nil {
                        return err
                }
 
-               utxoType := storage.NormalUTXOType
+               var assetID bc.AssetID
                switch output := entryOutput.(type) {
                case *bc.IntraChainOutput:
                        assetID = *output.Source.Value.AssetId
                case *bc.VoteOutput:
                        assetID = *output.Source.Value.AssetId
-                       utxoType = storage.VoteUTXOType
                default:
                        return errors.Wrapf(bc.ErrEntryType, "entry %x has unexpected type %T", prevout.Bytes(), entryOutput)
                }
@@ -180,28 +155,55 @@ func (view *UtxoViewpoint) DetachTransaction(tx *bc.Tx, statusFail bool) error {
                }
 
                entry, ok := view.Entries[prevout]
-               if ok && (entry.Type == storage.CrosschainUTXOType) {
-                       return errors.New("look up SpentOutputIDs but find mainchain utxo")
+               if !ok {
+                       return errors.New("fail to find utxo entry")
                }
 
-               if ok && !entry.Spent {
-                       return errors.New("try to revert an unspent utxo")
+               if entry.Spent {
+                       return errors.New("utxo has been spent")
                }
 
+               switch entry.Type {
+               case storage.CoinbaseUTXOType:
+                       if (entry.BlockHeight + consensus.CoinbasePendingBlockNumber) > block.Height {
+                               return errors.New("coinbase utxo is not ready for use")
+                       }
+
+               case storage.VoteUTXOType:
+                       if (entry.BlockHeight + consensus.VotePendingBlockNumber) > block.Height {
+                               return errors.New("Coin is  within the voting lock time")
+                       }
+               }
+
+               entry.SpendOutput()
+       }
+       return nil
+}
+
+func (view *UtxoViewpoint) detachCrossChainUtxo(tx *bc.Tx) error {
+       for _, prevout := range tx.MainchainOutputIDs {
+               entry, ok := view.Entries[prevout]
                if !ok {
-                       view.Entries[prevout] = storage.NewUtxoEntry(utxoType, 0, false)
-                       continue
+                       return errors.New("fail to find mainchain output entry")
                }
+
+               if !entry.Spent {
+                       return errors.New("mainchain output is unspent")
+               }
+
                entry.UnspendOutput()
        }
+       return nil
+}
 
+func (view *UtxoViewpoint) detachOutputUtxo(tx *bc.Tx, statusFail bool) error {
        for _, id := range tx.TxHeader.ResultIds {
-               assetID := bc.AssetID{}
                entryOutput, err := tx.Entry(*id)
                if err != nil {
-                       continue
+                       return err
                }
 
+               var assetID bc.AssetID
                utxoType := storage.NormalUTXOType
                switch output := entryOutput.(type) {
                case *bc.IntraChainOutput:
@@ -226,20 +228,39 @@ func (view *UtxoViewpoint) DetachTransaction(tx *bc.Tx, statusFail bool) error {
        return nil
 }
 
-func (view *UtxoViewpoint) DetachBlock(block *bc.Block, txStatus *bc.TransactionStatus) error {
-       for i := len(block.Transactions) - 1; i >= 0; i-- {
-               statusFail, err := txStatus.GetStatus(i)
+func (view *UtxoViewpoint) detachSpendUtxo(tx *bc.Tx, statusFail bool) error {
+       for _, prevout := range tx.SpentOutputIDs {
+               entryOutput, err := tx.Entry(prevout)
                if err != nil {
                        return err
                }
-               if err := view.DetachTransaction(block.Transactions[i], statusFail); err != nil {
-                       return err
+
+               var assetID bc.AssetID
+               utxoType := storage.NormalUTXOType
+               switch output := entryOutput.(type) {
+               case *bc.IntraChainOutput:
+                       assetID = *output.Source.Value.AssetId
+               case *bc.VoteOutput:
+                       assetID = *output.Source.Value.AssetId
+                       utxoType = storage.VoteUTXOType
+               default:
+                       return errors.Wrapf(bc.ErrEntryType, "entry %x has unexpected type %T", prevout.Bytes(), entryOutput)
+               }
+
+               if statusFail && assetID != *consensus.BTMAssetID {
+                       continue
+               }
+
+               entry, ok := view.Entries[prevout]
+               if ok && !entry.Spent {
+                       return errors.New("try to revert an unspent utxo")
                }
+
+               if !ok {
+                       view.Entries[prevout] = storage.NewUtxoEntry(utxoType, 0, false)
+                       continue
+               }
+               entry.UnspendOutput()
        }
        return nil
 }
-
-func (view *UtxoViewpoint) HasUtxo(hash *bc.Hash) bool {
-       _, ok := view.Entries[*hash]
-       return ok
-}
index 32d3f6d..912091c 100644 (file)
@@ -208,8 +208,7 @@ func isTransactionNoBtmInput(tx *types.Tx) bool {
 
 func isTransactionZeroOutput(tx *types.Tx) bool {
        for _, output := range tx.TxData.Outputs {
-               value := output.AssetAmount()
-               if value.Amount == uint64(0) {
+               if value := output.AssetAmount(); value.Amount == uint64(0) {
                        return true
                }
        }
@@ -282,11 +281,12 @@ func (tp *TxPool) addTransaction(txD *TxDesc) error {
        txD.Added = time.Now()
        tp.pool[tx.ID] = txD
        for _, id := range tx.ResultIds {
-               var assetID bc.AssetID
                outputEntry, err := tx.Entry(*id)
                if err != nil {
                        return err
                }
+
+               var assetID bc.AssetID
                switch output := outputEntry.(type) {
                case *bc.IntraChainOutput:
                        assetID = *output.Source.Value.AssetId
index df67693..7ac617c 100644 (file)
@@ -51,7 +51,6 @@ func NewTxVMContext(vs *validationState, entry bc.Entry, prog *bc.Program, args
                destPos = &e.WitnessDestination.Position
                s := e.SpentOutputId.Bytes()
                spentOutputID = &s
-
        }
 
        var txSigHash *[]byte