OSDN Git Service

last review (#519)
[bytom/vapor.git] / application / mov / mov_core.go
index 48aabe1..a8386c2 100644 (file)
@@ -30,39 +30,34 @@ var (
        errRewardProgramIsWrong         = errors.New("the reward program is not correct")
 )
 
-// MovCore represent the core logic of the match module, which include generate match transactions before packing the block,
+// Core represent the core logic of the match module, which include generate match transactions before packing the block,
 // verify the match transaction in block is correct, and update the order table according to the transaction.
-type MovCore struct {
+type Core struct {
        movStore         database.MovStore
        startBlockHeight uint64
 }
 
-// NewMovCore return a instance of MovCore by path of mov db
-func NewMovCore(dbBackend, dbDir string, startBlockHeight uint64) *MovCore {
+// NewCore return a instance of Core by path of mov db
+func NewCore(dbBackend, dbDir string, startBlockHeight uint64) *Core {
        movDB := dbm.NewDB("mov", dbBackend, dbDir)
-       return &MovCore{movStore: database.NewLevelDBMovStore(movDB), startBlockHeight: startBlockHeight}
+       return &Core{movStore: database.NewLevelDBMovStore(movDB), startBlockHeight: startBlockHeight}
 }
 
-// NewMovCoreWithDB return a instance of MovCore by movStore
-func NewMovCoreWithDB(store *database.LevelDBMovStore, startBlockHeight uint64) *MovCore {
-       return &MovCore{movStore: store, startBlockHeight: startBlockHeight}
+// NewCoreWithDB return a instance of Core by movStore
+func NewCoreWithDB(store *database.LevelDBMovStore, startBlockHeight uint64) *Core {
+       return &Core{movStore: store, startBlockHeight: startBlockHeight}
 }
 
 // ApplyBlock parse pending order and cancel from the the transactions of block
 // and add pending order to the dex db, remove cancel order from dex db.
-func (m *MovCore) ApplyBlock(block *types.Block) error {
+func (m *Core) ApplyBlock(block *types.Block) error {
        if block.Height < m.startBlockHeight {
                return nil
        }
 
        if block.Height == m.startBlockHeight {
                blockHash := block.Hash()
-               if err := m.movStore.InitDBState(block.Height, &blockHash); err != nil {
-                       return err
-               }
-
-               // the next block can send orders
-               return nil
+               return m.movStore.InitDBState(block.Height, &blockHash)
        }
 
        if err := m.validateMatchedTxSequence(block.Transactions); err != nil {
@@ -78,7 +73,7 @@ func (m *MovCore) ApplyBlock(block *types.Block) error {
 }
 
 // BeforeProposalBlock return all transactions than can be matched, and the number of transactions cannot exceed the given capacity.
-func (m *MovCore) BeforeProposalBlock(txs []*types.Tx, blockHeight uint64, gasLeft int64, isTimeout func() bool) ([]*types.Tx, error) {
+func (m *Core) BeforeProposalBlock(txs []*types.Tx, blockHeight uint64, gasLeft int64, isTimeout func() bool) ([]*types.Tx, error) {
        if blockHeight <= m.startBlockHeight {
                return nil, nil
        }
@@ -101,7 +96,7 @@ func (m *MovCore) BeforeProposalBlock(txs []*types.Tx, blockHeight uint64, gasLe
 }
 
 // ChainStatus return the current block height and block hash in dex core
-func (m *MovCore) ChainStatus() (uint64, *bc.Hash, error) {
+func (m *Core) ChainStatus() (uint64, *bc.Hash, error) {
        state, err := m.movStore.GetMovDatabaseState()
        if err != nil {
                return 0, nil, err
@@ -112,7 +107,7 @@ func (m *MovCore) ChainStatus() (uint64, *bc.Hash, error) {
 
 // DetachBlock parse pending order and cancel from the the transactions of block
 // and add cancel order to the dex db, remove pending order from dex db.
-func (m *MovCore) DetachBlock(block *types.Block) error {
+func (m *Core) DetachBlock(block *types.Block) error {
        if block.Height < m.startBlockHeight {
                return nil
        }
@@ -126,7 +121,7 @@ func (m *MovCore) DetachBlock(block *types.Block) error {
 }
 
 // IsDust block the transaction that are not generated by the match engine
-func (m *MovCore) IsDust(tx *types.Tx) bool {
+func (m *Core) IsDust(tx *types.Tx) bool {
        for _, input := range tx.Inputs {
                if segwit.IsP2WMCScript(input.ControlProgram()) && !contract.IsCancelClauseSelector(input) {
                        return true
@@ -136,18 +131,18 @@ func (m *MovCore) IsDust(tx *types.Tx) bool {
 }
 
 // Name return the name of current module
-func (m *MovCore) Name() string {
+func (m *Core) Name() string {
        return "MOV"
 }
 
 // StartHeight return the start block height of current module
-func (m *MovCore) StartHeight() uint64 {
+func (m *Core) StartHeight() uint64 {
        return m.startBlockHeight
 }
 
 // ValidateBlock no need to verify the block header, because the first module has been verified.
 // just need to verify the transactions in the block.
-func (m *MovCore) ValidateBlock(block *types.Block, verifyResults []*bc.TxVerifyResult) error {
+func (m *Core) ValidateBlock(block *types.Block, verifyResults []*bc.TxVerifyResult) error {
        for i, tx := range block.Transactions {
                if err := m.ValidateTx(tx, verifyResults[i], block.Height); err != nil {
                        return err
@@ -157,7 +152,15 @@ func (m *MovCore) ValidateBlock(block *types.Block, verifyResults []*bc.TxVerify
 }
 
 // ValidateTx validate one transaction.
-func (m *MovCore) ValidateTx(tx *types.Tx, verifyResult *bc.TxVerifyResult, blockHeight uint64) error {
+func (m *Core) ValidateTx(tx *types.Tx, verifyResult *bc.TxVerifyResult, blockHeight uint64) error {
+       if blockHeight <= m.startBlockHeight {
+               return nil
+       }
+
+       if verifyResult.StatusFail {
+               return errStatusFailMustFalse
+       }
+
        if common.IsMatchedTx(tx) {
                if err := validateMatchedTx(tx, verifyResult, blockHeight); err != nil {
                        return err
@@ -172,9 +175,6 @@ func (m *MovCore) ValidateTx(tx *types.Tx, verifyResult *bc.TxVerifyResult, bloc
                if !segwit.IsP2WMCScript(output.ControlProgram()) {
                        continue
                }
-               if verifyResult.StatusFail {
-                       return errStatusFailMustFalse
-               }
 
                if err := validateMagneticContractArgs(output.AssetAmount(), output.ControlProgram()); err != nil {
                        return err
@@ -211,18 +211,16 @@ func calcFeeAmount(matchedTx *types.Tx) (map[bc.AssetID]*matchedTxFee, error) {
                        if assetFeeMap[*assetAmount.AssetId].amount <= 0 {
                                delete(assetFeeMap, *assetAmount.AssetId)
                        }
-               } else {
+               } else if assetFeeMap[*assetAmount.AssetId].rewardProgram == nil {
                        assetFeeMap[*assetAmount.AssetId].rewardProgram = output.ControlProgram()
+               } else {
+                       return nil, errors.Wrap(errRewardProgramIsWrong, "double reward program")
                }
        }
        return assetFeeMap, nil
 }
 
 func validateCancelOrderTx(tx *types.Tx, verifyResult *bc.TxVerifyResult) error {
-       if verifyResult.StatusFail {
-               return errStatusFailMustFalse
-       }
-
        for _, input := range tx.Inputs {
                if !segwit.IsP2WMCScript(input.ControlProgram()) {
                        return errInputProgramMustP2WMCScript
@@ -256,10 +254,6 @@ func validateMagneticContractArgs(fromAssetAmount bc.AssetAmount, program []byte
 }
 
 func validateMatchedTx(tx *types.Tx, verifyResult *bc.TxVerifyResult, blockHeight uint64) error {
-       if verifyResult.StatusFail {
-               return errStatusFailMustFalse
-       }
-
        fromAssetIDMap := make(map[string]bool)
        toAssetIDMap := make(map[string]bool)
        for i, input := range tx.Inputs {
@@ -314,7 +308,7 @@ func validateMatchedTxFee(tx *types.Tx, blockHeight uint64) error {
        return feeStrategy.Validate(receivedAmount, feeAmounts)
 }
 
-func (m *MovCore) validateMatchedTxSequence(txs []*types.Tx) error {
+func (m *Core) validateMatchedTxSequence(txs []*types.Tx) error {
        orderBook := match.NewOrderBook(m.movStore, nil, nil)
        for _, tx := range txs {
                if common.IsMatchedTx(tx) {
@@ -404,15 +398,8 @@ func decodeTxsOrders(txs []*types.Tx) ([]*common.Order, []*common.Order, error)
 }
 
 func buildOrderBook(store database.MovStore, txs []*types.Tx) (*match.OrderBook, error) {
-       var nonMatchedTxs []*types.Tx
-       for _, tx := range txs {
-               if !common.IsMatchedTx(tx) {
-                       nonMatchedTxs = append(nonMatchedTxs, tx)
-               }
-       }
-
        var arrivalAddOrders, arrivalDelOrders []*common.Order
-       for _, tx := range nonMatchedTxs {
+       for _, tx := range txs {
                addOrders, err := getAddOrdersFromTx(tx)
                if err != nil {
                        return nil, err
@@ -437,6 +424,10 @@ func getAddOrdersFromTx(tx *types.Tx) ([]*common.Order, error) {
                        continue
                }
 
+               if output.AssetAmount().Amount == 0 {
+                       continue
+               }
+
                order, err := common.NewOrderFromOutput(tx, i)
                if err != nil {
                        return nil, err