"os"
"testing"
- "github.com/vapor/application/mov/common"
- "github.com/vapor/application/mov/database"
- "github.com/vapor/application/mov/mock"
- "github.com/vapor/consensus"
- dbm "github.com/vapor/database/leveldb"
- "github.com/vapor/protocol/bc"
- "github.com/vapor/protocol/bc/types"
- "github.com/vapor/protocol/vm"
- "github.com/vapor/testutil"
+ "github.com/bytom/vapor/application/mov/common"
+ "github.com/bytom/vapor/application/mov/database"
+ "github.com/bytom/vapor/application/mov/mock"
+ "github.com/bytom/vapor/consensus"
+ dbm "github.com/bytom/vapor/database/leveldb"
+ "github.com/bytom/vapor/protocol/bc"
+ "github.com/bytom/vapor/protocol/bc/types"
+ "github.com/bytom/vapor/protocol/vm"
+ "github.com/bytom/vapor/testutil"
)
-/*
- @addTest:BeforeProposalBlock: will gas affect generate tx? will be packed tx affect generate tx?
- @addTest:TestApplyBlock: one block has two different trade pairs & different trade pair won't affect each order(attach & detach)
- @addTest:TestApplyBlock: node packed maker tx and match transaction in random order(attach & detach)
- @addTest:TestValidateBlock: one tx has trade input and cancel input mixed
- @addTest:TestValidateBlock: regular match transaction's seller program is also a P2WMCProgram
-*/
+var initBlockHeader = &types.BlockHeader{Height: 1, PreviousBlockHash: bc.Hash{}}
+
func TestApplyBlock(t *testing.T) {
- initBlockHeader := &types.BlockHeader{Height: 1, PreviousBlockHash: bc.Hash{}}
cases := []struct {
desc string
block *types.Block
wantDBState: &common.MovDatabaseState{Height: 2, Hash: hashPtr(testutil.MustDecodeHash("88dbcde57bb2b53b107d7494f20f1f1a892307a019705980c3510890449c0020"))},
},
{
+ desc: "apply block has two different trade pairs & different trade pair won't affect each order",
+ block: &types.Block{
+ BlockHeader: types.BlockHeader{Height: 2, PreviousBlockHash: initBlockHeader.Hash()},
+ Transactions: []*types.Tx{
+ mock.Btc2EthMakerTxs[0],
+ mock.Eth2BtcMakerTxs[0],
+ mock.Eos2EtcMakerTxs[0],
+ mock.Eth2EosMakerTxs[0],
+ },
+ },
+ blockFunc: applyBlock,
+ wantOrders: []*common.Order{
+ mock.MustNewOrderFromOutput(mock.Btc2EthMakerTxs[0], 0),
+ mock.MustNewOrderFromOutput(mock.Eth2BtcMakerTxs[0], 0),
+ mock.MustNewOrderFromOutput(mock.Eos2EtcMakerTxs[0], 0),
+ mock.MustNewOrderFromOutput(mock.Eth2EosMakerTxs[0], 0),
+ },
+ wantDBState: &common.MovDatabaseState{Height: 2, Hash: hashPtr(testutil.MustDecodeHash("88dbcde57bb2b53b107d7494f20f1f1a892307a019705980c3510890449c0020"))},
+ },
+ {
desc: "apply block has full matched transaction",
block: &types.Block{
BlockHeader: types.BlockHeader{Height: 2, PreviousBlockHash: initBlockHeader.Hash()},
wantDBState: &common.MovDatabaseState{Height: 2, Hash: hashPtr(testutil.MustDecodeHash("88dbcde57bb2b53b107d7494f20f1f1a892307a019705980c3510890449c0020"))},
},
{
+ desc: "apply block which node packed maker tx and match transaction in random orde",
+ block: &types.Block{
+ BlockHeader: types.BlockHeader{Height: 2, PreviousBlockHash: initBlockHeader.Hash()},
+ Transactions: []*types.Tx{
+ mock.Eos2EtcMakerTxs[0],
+ mock.Btc2EthMakerTxs[0],
+ mock.Eth2BtcMakerTxs[1],
+ mock.MatchedTxs[4],
+ mock.Eth2EosMakerTxs[0],
+ mock.Etc2EosMakerTxs[0],
+ mock.MatchedTxs[5],
+ },
+ },
+ blockFunc: applyBlock,
+ initOrders: []*common.Order{},
+ wantOrders: []*common.Order{
+ mock.MustNewOrderFromOutput(mock.MatchedTxs[4], 1),
+ mock.MustNewOrderFromOutput(mock.Eth2EosMakerTxs[0], 0),
+ },
+ wantDBState: &common.MovDatabaseState{Height: 2, Hash: hashPtr(testutil.MustDecodeHash("88dbcde57bb2b53b107d7494f20f1f1a892307a019705980c3510890449c0020"))},
+ },
+ {
+ desc: "apply block has partial matched transaction chain",
+ block: &types.Block{
+ BlockHeader: types.BlockHeader{Height: 2, PreviousBlockHash: initBlockHeader.Hash()},
+ Transactions: []*types.Tx{
+ mock.Btc2EthMakerTxs[0],
+ mock.Eth2BtcMakerTxs[1],
+ mock.MatchedTxs[4],
+ mock.Eth2BtcMakerTxs[0],
+ mock.MatchedTxs[7],
+ },
+ },
+ blockFunc: applyBlock,
+ initOrders: []*common.Order{},
+ wantOrders: []*common.Order{mock.MustNewOrderFromOutput(mock.MatchedTxs[7], 2)},
+ wantDBState: &common.MovDatabaseState{Height: 2, Hash: hashPtr(testutil.MustDecodeHash("88dbcde57bb2b53b107d7494f20f1f1a892307a019705980c3510890449c0020"))},
+ },
+ {
desc: "detach block has pending order transaction",
block: &types.Block{
BlockHeader: *initBlockHeader,
wantDBState: &common.MovDatabaseState{Height: 0, Hash: &bc.Hash{}},
},
{
+ desc: "detach block has two different trade pairs & different trade pair won't affect each order",
+ block: &types.Block{
+ BlockHeader: *initBlockHeader,
+ Transactions: []*types.Tx{
+ mock.Btc2EthMakerTxs[0],
+ mock.Eth2BtcMakerTxs[0],
+ mock.Eos2EtcMakerTxs[0],
+ mock.Eth2EosMakerTxs[0],
+ },
+ },
+ blockFunc: detachBlock,
+ initOrders: []*common.Order{
+ mock.MustNewOrderFromOutput(mock.Btc2EthMakerTxs[0], 0),
+ mock.MustNewOrderFromOutput(mock.Eth2BtcMakerTxs[0], 0),
+ mock.MustNewOrderFromOutput(mock.Eos2EtcMakerTxs[0], 0),
+ mock.MustNewOrderFromOutput(mock.Eth2EosMakerTxs[0], 0),
+ },
+ wantOrders: []*common.Order{},
+ wantDBState: &common.MovDatabaseState{Height: 0, Hash: &bc.Hash{}},
+ },
+ {
desc: "detach block has full matched transaction",
block: &types.Block{
BlockHeader: *initBlockHeader,
wantOrders: []*common.Order{mock.Btc2EthOrders[0], mock.Btc2EthOrders[1], mock.Eth2BtcOrders[2]},
wantDBState: &common.MovDatabaseState{Height: 0, Hash: &bc.Hash{}},
},
+ {
+ desc: "detach block which node packed maker tx and match transaction in random orde",
+ block: &types.Block{
+ BlockHeader: *initBlockHeader,
+ Transactions: []*types.Tx{
+ mock.Eos2EtcMakerTxs[0],
+ mock.Btc2EthMakerTxs[0],
+ mock.MatchedTxs[4],
+ mock.Eth2EosMakerTxs[0],
+ mock.Eth2BtcMakerTxs[1],
+ mock.MatchedTxs[5],
+ mock.Etc2EosMakerTxs[0],
+ },
+ },
+ blockFunc: detachBlock,
+ initOrders: []*common.Order{
+ mock.MustNewOrderFromOutput(mock.MatchedTxs[4], 1),
+ mock.MustNewOrderFromOutput(mock.Eth2EosMakerTxs[0], 0),
+ },
+ wantOrders: []*common.Order{},
+ wantDBState: &common.MovDatabaseState{Height: 0, Hash: &bc.Hash{}},
+ },
}
defer os.RemoveAll("temp")
Transactions: []*types.Tx{
types.NewTx(types.TxData{
Inputs: []*types.TxInput{types.NewSpendInput(nil, *mock.Btc2EthOrders[0].Utxo.SourceID, *mock.Btc2EthOrders[0].FromAssetID, mock.Btc2EthOrders[0].Utxo.Amount, mock.Btc2EthOrders[0].Utxo.SourcePos, []byte{0x51})},
- Outputs: []*types.TxOutput{types.NewIntraChainOutput(*mock.Btc2EthOrders[0].FromAssetID, mock.Btc2EthOrders[0].Utxo.Amount, mock.MustCreateP2WMCProgram(mock.ETH, testutil.MustDecodeHexString("51"), 0, 1))},
+ Outputs: []*types.TxOutput{types.NewIntraChainOutput(*mock.Btc2EthOrders[0].FromAssetID, mock.Btc2EthOrders[0].Utxo.Amount, mock.MustCreateP2WMCProgram(mock.ETH, testutil.MustDecodeHexString("0014f928b723999312df4ed51cb275a2644336c19251"), 0, 1))},
}),
},
},
Transactions: []*types.Tx{
types.NewTx(types.TxData{
Inputs: []*types.TxInput{types.NewSpendInput(nil, *mock.Btc2EthOrders[0].Utxo.SourceID, *mock.Btc2EthOrders[0].FromAssetID, mock.Btc2EthOrders[0].Utxo.Amount, mock.Btc2EthOrders[0].Utxo.SourcePos, []byte{0x51})},
- Outputs: []*types.TxOutput{types.NewIntraChainOutput(*mock.Btc2EthOrders[0].FromAssetID, mock.Btc2EthOrders[0].Utxo.Amount, mock.MustCreateP2WMCProgram(mock.ETH, testutil.MustDecodeHexString("51"), 1, 0))},
+ Outputs: []*types.TxOutput{types.NewIntraChainOutput(*mock.Btc2EthOrders[0].FromAssetID, mock.Btc2EthOrders[0].Utxo.Amount, mock.MustCreateP2WMCProgram(mock.ETH, testutil.MustDecodeHexString("0014f928b723999312df4ed51cb275a2644336c19251"), 1, 0))},
}),
},
},
wantError: errRatioOfTradeLessThanZero,
},
{
- desc: "ratio numerator product input amount is overflow",
+ desc: "want amount is overflow",
block: &types.Block{
Transactions: []*types.Tx{
types.NewTx(types.TxData{
Inputs: []*types.TxInput{types.NewSpendInput(nil, *mock.Btc2EthOrders[0].Utxo.SourceID, *mock.Btc2EthOrders[0].FromAssetID, mock.Btc2EthOrders[0].Utxo.Amount, mock.Btc2EthOrders[0].Utxo.SourcePos, []byte{0x51})},
- Outputs: []*types.TxOutput{types.NewIntraChainOutput(*mock.Btc2EthOrders[0].FromAssetID, mock.Btc2EthOrders[0].Utxo.Amount, mock.MustCreateP2WMCProgram(mock.ETH, testutil.MustDecodeHexString("51"), math.MaxInt64, 10))},
+ Outputs: []*types.TxOutput{types.NewIntraChainOutput(*mock.Btc2EthOrders[0].FromAssetID, mock.Btc2EthOrders[0].Utxo.Amount, mock.MustCreateP2WMCProgram(mock.ETH, testutil.MustDecodeHexString("0014f928b723999312df4ed51cb275a2644336c19251"), math.MaxInt64, 1))},
}),
},
},
verifyResults: []*bc.TxVerifyResult{{StatusFail: false}},
- wantError: errNumeratorOfRatioIsOverflow,
+ wantError: errRequestAmountMath,
},
}
}
}
+func TestBeforeProposalBlock(t *testing.T) {
+ cases := []struct {
+ desc string
+ initOrders []*common.Order
+ gasLeft int64
+ wantMatchedTxs []*types.Tx
+ }{
+ {
+ desc: "has matched tx, but gas left is zero",
+ initOrders: []*common.Order{mock.Btc2EthOrders[0], mock.Eth2BtcOrders[0]},
+ gasLeft: 0,
+ wantMatchedTxs: []*types.Tx{},
+ },
+ {
+ desc: "has one matched tx, and gas is sufficient",
+ initOrders: []*common.Order{mock.Btc2EthOrders[0], mock.Eth2BtcOrders[0]},
+ gasLeft: 2000,
+ wantMatchedTxs: []*types.Tx{mock.MatchedTxs[1]},
+ },
+ {
+ desc: "has two matched tx, but gas is only enough to pack a matched tx",
+ initOrders: []*common.Order{
+ mock.Btc2EthOrders[0],
+ mock.Btc2EthOrders[1],
+ mock.Eth2BtcOrders[2],
+ },
+ gasLeft: 2000,
+ wantMatchedTxs: []*types.Tx{mock.MatchedTxs[2]},
+ },
+ {
+ desc: "has two matched tx, and gas left is sufficient",
+ initOrders: []*common.Order{
+ mock.Btc2EthOrders[0],
+ mock.Btc2EthOrders[1],
+ mock.Eth2BtcOrders[2],
+ },
+ gasLeft: 4000,
+ wantMatchedTxs: []*types.Tx{mock.MatchedTxs[2], mock.MatchedTxs[3]},
+ },
+ {
+ desc: "has multiple trade pairs, and gas left is sufficient",
+ initOrders: []*common.Order{
+ mock.Btc2EthOrders[0],
+ mock.Btc2EthOrders[1],
+ mock.Eth2BtcOrders[2],
+ mock.Eos2EtcOrders[0],
+ mock.Etc2EosOrders[0],
+ },
+ gasLeft: 6000,
+ wantMatchedTxs: []*types.Tx{mock.MatchedTxs[2], mock.MatchedTxs[3], mock.MatchedTxs[5]},
+ },
+ }
+
+ for i, c := range cases {
+ testDB := dbm.NewDB("testdb", "leveldb", "temp")
+ store := database.NewLevelDBMovStore(testDB)
+ if err := store.InitDBState(0, &bc.Hash{}); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := store.ProcessOrders(c.initOrders, nil, initBlockHeader); err != nil {
+ t.Fatal(err)
+ }
+
+ movCore := &MovCore{movStore: store}
+ gotMatchedTxs, err := movCore.BeforeProposalBlock(nil, []byte{0x51}, 2, c.gasLeft, func() bool { return false })
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ gotMatchedTxMap := make(map[string]interface{})
+ for _, matchedTx := range gotMatchedTxs {
+ gotMatchedTxMap[matchedTx.ID.String()] = nil
+ }
+
+ wantMatchedTxMap := make(map[string]interface{})
+ for _, matchedTx := range c.wantMatchedTxs {
+ wantMatchedTxMap[matchedTx.ID.String()] = nil
+ }
+
+ if !testutil.DeepEqual(gotMatchedTxMap, wantMatchedTxMap) {
+ t.Errorf("#%d(%s):want matched tx(%v) is not equals got matched tx(%v)", i, c.desc, c.wantMatchedTxs, gotMatchedTxs)
+ }
+
+ testDB.Close()
+ os.RemoveAll("temp")
+ }
+}
+
type testFun func(movCore *MovCore, block *types.Block) error
func applyBlock(movCore *MovCore, block *types.Block) error {