return m.InitChainStatus(&blockHash)
}
- if err := m.validateMatchedTxSequence(block.Transactions); err != nil {
+ if err := m.validateMatchedTxSequence(movTxs(block)); err != nil {
return err
}
- addOrders, deleteOrders, err := decodeTxsOrders(block.Transactions)
+ addOrders, deleteOrders, err := decodeTxsOrders(movTxs(block))
if err != nil {
return err
}
return m.movStore.ProcessOrders(addOrders, deleteOrders, &block.BlockHeader)
}
+// Tx contains raw transaction and the sequence of tx in block
+type Tx struct {
+ rawTx *types.Tx
+ blockHeight uint64
+ txIndex uint64
+}
+
+// NewTx create a new Tx instance
+func NewTx(tx *types.Tx, blockHeight, txIndex uint64) *Tx {
+ return &Tx{rawTx: tx, blockHeight: blockHeight, txIndex: txIndex}
+}
+
// BeforeProposalBlock return all transactions than can be matched, and the number of transactions cannot exceed the given capacity.
-func (m *Core) BeforeProposalBlock(txs []*types.Tx, blockHeight uint64, gasLeft int64, isTimeout func() bool) ([]*types.Tx, error) {
- if blockHeight <= m.startBlockHeight {
+func (m *Core) BeforeProposalBlock(block *types.Block, gasLeft int64, isTimeout func() bool) ([]*types.Tx, error) {
+ if block.Height <= m.startBlockHeight {
return nil, nil
}
- orderBook, err := buildOrderBook(m.movStore, txs)
+ orderBook, err := buildOrderBook(m.movStore, movTxs(block))
if err != nil {
return nil, err
}
- program, _ := getRewardProgram(blockHeight)
+ program, _ := getRewardProgram(block.Height)
rewardProgram, err := hex.DecodeString(program)
if err != nil {
return nil, errNotConfiguredRewardProgram
}
- matchEngine := match.NewEngine(orderBook, match.NewDefaultFeeStrategy(), rewardProgram)
+ matchEngine := match.NewEngine(orderBook, rewardProgram)
tradePairIterator := database.NewTradePairIterator(m.movStore)
matchCollector := newMatchTxCollector(matchEngine, tradePairIterator, gasLeft, isTimeout)
return matchCollector.result()
return nil
}
- deleteOrders, addOrders, err := decodeTxsOrders(block.Transactions)
+ deleteOrders, addOrders, err := decodeTxsOrders(movTxs(block))
if err != nil {
return err
}
toAssetIDMap[order.ToAssetID.String()] = true
}
- if len(fromAssetIDMap) != len(tx.Inputs) || len(toAssetIDMap) != len(tx.Inputs) {
+ if inputSize := len(tx.Inputs); len(fromAssetIDMap) != inputSize || len(toAssetIDMap) != inputSize {
return errAssetIDMustUniqueInMatchedTx
}
}
}
- orders, err := getDeleteOrdersFromTx(tx)
+ orders, err := parseDeleteOrdersFromTx(tx)
if err != nil {
return err
}
- receivedAmount, _ := match.CalcReceivedAmount(orders)
+ receivedAmount, priceDiffs := match.CalcReceivedAmount(orders)
feeAmounts := make(map[bc.AssetID]uint64)
for assetID, fee := range matchedTxFees {
feeAmounts[assetID] = fee.amount
}
feeStrategy := match.NewDefaultFeeStrategy()
- return feeStrategy.Validate(receivedAmount, feeAmounts)
+ return feeStrategy.Validate(receivedAmount, priceDiffs, feeAmounts, blockHeight)
}
-func (m *Core) validateMatchedTxSequence(txs []*types.Tx) error {
+func (m *Core) validateMatchedTxSequence(txs []*Tx) error {
orderBook := match.NewOrderBook(m.movStore, nil, nil)
for _, tx := range txs {
- if common.IsMatchedTx(tx) {
- tradePairs, err := getTradePairsFromMatchedTx(tx)
+ if common.IsMatchedTx(tx.rawTx) {
+ tradePairs, err := parseTradePairsFromMatchedTx(tx.rawTx)
if err != nil {
return err
}
orders := orderBook.PeekOrders(tradePairs)
- if err := validateSpendOrders(tx, orders); err != nil {
+ if err := validateSpendOrders(tx.rawTx, orders); err != nil {
return err
}
orderBook.PopOrders(tradePairs)
- } else if common.IsCancelOrderTx(tx) {
- orders, err := getDeleteOrdersFromTx(tx)
+ } else if common.IsCancelOrderTx(tx.rawTx) {
+ orders, err := parseDeleteOrdersFromTx(tx.rawTx)
if err != nil {
return err
}
}
}
- addOrders, err := getAddOrdersFromTx(tx)
+ addOrders, err := parseAddOrdersFromTx(tx)
if err != nil {
return err
}
return nil
}
-func decodeTxsOrders(txs []*types.Tx) ([]*common.Order, []*common.Order, error) {
+func decodeTxsOrders(txs []*Tx) ([]*common.Order, []*common.Order, error) {
deleteOrderMap := make(map[string]*common.Order)
addOrderMap := make(map[string]*common.Order)
for _, tx := range txs {
- addOrders, err := getAddOrdersFromTx(tx)
+ addOrders, err := parseAddOrdersFromTx(tx)
if err != nil {
return nil, nil, err
}
addOrderMap[order.Key()] = order
}
- deleteOrders, err := getDeleteOrdersFromTx(tx)
+ deleteOrders, err := parseDeleteOrdersFromTx(tx.rawTx)
if err != nil {
return nil, nil, err
}
return addOrders, deleteOrders, nil
}
-func buildOrderBook(store database.MovStore, txs []*types.Tx) (*match.OrderBook, error) {
+func buildOrderBook(store database.MovStore, txs []*Tx) (*match.OrderBook, error) {
var arrivalAddOrders, arrivalDelOrders []*common.Order
for _, tx := range txs {
- addOrders, err := getAddOrdersFromTx(tx)
+ addOrders, err := parseAddOrdersFromTx(tx)
if err != nil {
return nil, err
}
- delOrders, err := getDeleteOrdersFromTx(tx)
+ delOrders, err := parseDeleteOrdersFromTx(tx.rawTx)
if err != nil {
return nil, err
}
return match.NewOrderBook(store, arrivalAddOrders, arrivalDelOrders), nil
}
-func getAddOrdersFromTx(tx *types.Tx) ([]*common.Order, error) {
+func parseAddOrdersFromTx(tx *Tx) ([]*common.Order, error) {
var orders []*common.Order
- for i, output := range tx.Outputs {
+ for i, output := range tx.rawTx.Outputs {
if output.OutputType() != types.IntraChainOutputType || !segwit.IsP2WMCScript(output.ControlProgram()) {
continue
}
continue
}
- order, err := common.NewOrderFromOutput(tx, i)
+ order, err := common.NewOrderFromOutput(tx.rawTx, i, tx.blockHeight, tx.txIndex)
if err != nil {
return nil, err
}
return orders, nil
}
-func getDeleteOrdersFromTx(tx *types.Tx) ([]*common.Order, error) {
+func parseDeleteOrdersFromTx(tx *types.Tx) ([]*common.Order, error) {
var orders []*common.Order
for i, input := range tx.Inputs {
if input.InputType() != types.SpendInputType || !segwit.IsP2WMCScript(input.ControlProgram()) {
return orders, nil
}
-func getTradePairsFromMatchedTx(tx *types.Tx) ([]*common.TradePair, error) {
+func parseTradePairsFromMatchedTx(tx *types.Tx) ([]*common.TradePair, error) {
var tradePairs []*common.TradePair
for _, tx := range tx.Inputs {
contractArgs, err := segwit.DecodeP2WMCProgram(tx.ControlProgram())
return addOrders, deleteOrders
}
+func movTxs(block *types.Block) []*Tx {
+ var movTxs []*Tx
+ for i, tx := range block.Transactions {
+ movTxs = append(movTxs, NewTx(tx, block.Height, uint64(i)))
+ }
+ return movTxs
+}
+
// getRewardProgram return the reward program by specified block height
// if no reward program configured, then will return empty string
// if reward program of 0-100 height is configured, but the specified height is 200, then will return 0-100's reward program