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 {
}
// 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
}
}
// 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
// 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
}
}
// 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
}
// 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
}
// 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
if !segwit.IsP2WMCScript(output.ControlProgram()) {
continue
}
- if verifyResult.StatusFail {
- return errStatusFailMustFalse
- }
if err := validateMagneticContractArgs(output.AssetAmount(), output.ControlProgram()); err != nil {
return err
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
}
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 {
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) {
}
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
continue
}
+ if output.AssetAmount().Amount == 0 {
+ continue
+ }
+
order, err := common.NewOrderFromOutput(tx, i)
if err != nil {
return nil, err