aboutsummaryrefslogtreecommitdiffstats
path: root/dex
diff options
context:
space:
mode:
authorbojie <bojie@dexon.org>2018-12-03 16:30:53 +0800
committerWei-Ning Huang <w@dexon.org>2019-04-09 21:32:54 +0800
commitc4ee0ef189bc00661c7ca8c1d3e94e929aa5eee1 (patch)
tree3e6105d45ca1bc71c9117864eb91b59998d03d58 /dex
parentd3c9496ee0256154477d0c74397a28c93a26af6f (diff)
downloaddexon-c4ee0ef189bc00661c7ca8c1d3e94e929aa5eee1.tar
dexon-c4ee0ef189bc00661c7ca8c1d3e94e929aa5eee1.tar.gz
dexon-c4ee0ef189bc00661c7ca8c1d3e94e929aa5eee1.tar.bz2
dexon-c4ee0ef189bc00661c7ca8c1d3e94e929aa5eee1.tar.lz
dexon-c4ee0ef189bc00661c7ca8c1d3e94e929aa5eee1.tar.xz
dexon-c4ee0ef189bc00661c7ca8c1d3e94e929aa5eee1.tar.zst
dexon-c4ee0ef189bc00661c7ca8c1d3e94e929aa5eee1.zip
app: add app test case and benchmark (#66)
Diffstat (limited to 'dex')
-rw-r--r--dex/app.go51
-rw-r--r--dex/app_test.go689
-rw-r--r--dex/backend.go2
3 files changed, 723 insertions, 19 deletions
diff --git a/dex/app.go b/dex/app.go
index 02e0a484f..cf36ad816 100644
--- a/dex/app.go
+++ b/dex/app.go
@@ -29,7 +29,6 @@ import (
"github.com/dexon-foundation/dexon/common"
"github.com/dexon-foundation/dexon/core"
"github.com/dexon-foundation/dexon/core/types"
- "github.com/dexon-foundation/dexon/core/vm"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/log"
"github.com/dexon-foundation/dexon/rlp"
@@ -46,20 +45,13 @@ type DexconApp struct {
gov *DexconGovernance
chainDB ethdb.Database
config *Config
- vmConfig vm.Config
chainLocksInitMu sync.Mutex
chainLocks map[uint32]*sync.RWMutex
- notifyMu sync.Mutex
- notifyChan sync.Map
chainLatestRoot sync.Map
}
-type notify struct {
- results []chan uint64
-}
-
type witnessData struct {
Root common.Hash
TxHash common.Hash
@@ -67,14 +59,13 @@ type witnessData struct {
}
func NewDexconApp(txPool *core.TxPool, blockchain *core.BlockChain, gov *DexconGovernance,
- chainDB ethdb.Database, config *Config, vmConfig vm.Config) *DexconApp {
+ chainDB ethdb.Database, config *Config) *DexconApp {
return &DexconApp{
txPool: txPool,
blockchain: blockchain,
gov: gov,
chainDB: chainDB,
config: config,
- vmConfig: vmConfig,
chainLocks: make(map[uint32]*sync.RWMutex),
}
}
@@ -275,17 +266,39 @@ func (d *DexconApp) VerifyBlock(block *coreTypes.Block) coreTypes.BlockVerifySta
}
// Wait until the witnessed root is seen on our local chain.
- for i := 0; i < verifyBlockMaxRetries && err != nil; i++ {
+ for i := 0; i < verifyBlockMaxRetries; i++ {
+ if d.blockchain.GetPendingHeight() < block.Witness.Height {
+ log.Debug("Pending height < witness height")
+ time.Sleep(500 * time.Millisecond)
+ continue
+ }
+
+ b := d.blockchain.GetPendingBlockByNumber(block.Witness.Height)
+ if b == nil {
+ b = d.blockchain.GetBlockByNumber(block.Witness.Height)
+ if b == nil {
+ log.Error("Can not get block by height %v", block.Witness.Height)
+ return coreTypes.VerifyInvalidBlock
+ }
+ }
+
+ if b.Root() != witnessData.Root {
+ log.Error("Witness root not correct expect %v but %v", b.Root(), witnessData.Root)
+ return coreTypes.VerifyInvalidBlock
+ }
+
+ if b.ReceiptHash() != witnessData.ReceiptHash {
+ log.Error("Witness receipt hash not correct expect %v but %v", b.ReceiptHash(), witnessData.ReceiptHash)
+ return coreTypes.VerifyInvalidBlock
+ }
+
_, err = d.blockchain.StateAt(witnessData.Root)
if err != nil {
- log.Debug("Witness root not found, retry in 500ms", "error", err)
- time.Sleep(500 * time.Millisecond)
+ log.Error("Get state by root %v error: %v", witnessData.Root, err)
+ return coreTypes.VerifyInvalidBlock
}
- }
- if err != nil {
- log.Error("Expected witness root not in stateDB", "err", err)
- return coreTypes.VerifyRetryLater
+ break
}
d.chainRLock(block.Position.ChainID)
@@ -457,5 +470,7 @@ func (d *DexconApp) BlockConfirmed(block coreTypes.Block) {
d.chainLock(block.Position.ChainID)
defer d.chainUnlock(block.Position.ChainID)
- d.blockchain.AddConfirmedBlock(&block)
+ if err := d.blockchain.AddConfirmedBlock(&block); err != nil {
+ panic(err)
+ }
}
diff --git a/dex/app_test.go b/dex/app_test.go
new file mode 100644
index 000000000..cbd29d0dc
--- /dev/null
+++ b/dex/app_test.go
@@ -0,0 +1,689 @@
+package dex
+
+import (
+ "crypto/ecdsa"
+ "fmt"
+ "math/big"
+ "testing"
+ "time"
+
+ coreCommon "github.com/dexon-foundation/dexon-consensus/common"
+ coreTypes "github.com/dexon-foundation/dexon-consensus/core/types"
+
+ "github.com/dexon-foundation/dexon/common"
+ "github.com/dexon-foundation/dexon/consensus/dexcon"
+ "github.com/dexon-foundation/dexon/core"
+ "github.com/dexon-foundation/dexon/core/types"
+ "github.com/dexon-foundation/dexon/core/vm"
+ "github.com/dexon-foundation/dexon/crypto"
+ "github.com/dexon-foundation/dexon/ethdb"
+ "github.com/dexon-foundation/dexon/params"
+ "github.com/dexon-foundation/dexon/rlp"
+)
+
+func TestPreparePayload(t *testing.T) {
+ key, err := crypto.GenerateKey()
+ if err != nil {
+ t.Errorf("hex to ecdsa error: %v", err)
+ }
+
+ dex, err := newTestDexonWithGenesis(key)
+ if err != nil {
+ t.Errorf("new test dexon error: %v", err)
+ }
+
+ signer := types.NewEIP155Signer(dex.chainConfig.ChainID)
+
+ var expectTx types.Transactions
+ for i := 0; i < 5; i++ {
+ tx, err := addTx(dex, i, signer, key)
+ if err != nil {
+ t.Errorf("add tx error: %v", err)
+ }
+ expectTx = append(expectTx, tx)
+ }
+
+ // This transaction will not be included.
+ _, err = addTx(dex, 100, signer, key)
+ if err != nil {
+ t.Errorf("add tx error: %v", err)
+ }
+
+ chainID := new(big.Int).Mod(crypto.PubkeyToAddress(key.PublicKey).Big(),
+ big.NewInt(int64(dex.chainConfig.Dexcon.NumChains)))
+ var chainNum uint32
+ for chainNum = 0; chainNum < dex.chainConfig.Dexcon.NumChains; chainNum++ {
+
+ payload, err := dex.app.PreparePayload(coreTypes.Position{ChainID: chainNum})
+ if err != nil {
+ t.Errorf("prepare payload error: %v", err)
+ }
+
+ var transactions types.Transactions
+ err = rlp.DecodeBytes(payload, &transactions)
+ if err != nil {
+ t.Errorf("rlp decode error: %v", err)
+ }
+
+ // Only one chain id allow prepare transactions.
+ if chainID.Uint64() == uint64(chainNum) && len(transactions) != 5 {
+ t.Errorf("incorrect transaction num expect %v but %v", 5, len(transactions))
+ } else if chainID.Uint64() != uint64(chainNum) && len(transactions) != 0 {
+ t.Errorf("expect empty slice but %v", len(transactions))
+ }
+
+ for i, tx := range transactions {
+ if expectTx[i].Gas() != tx.Gas() {
+ t.Errorf("unexpected gas expect %v but %v", expectTx[i].Gas(), tx.Gas())
+ }
+
+ if expectTx[i].Hash() != tx.Hash() {
+ t.Errorf("unexpected hash expect %v but %v", expectTx[i].Hash(), tx.Hash())
+ }
+
+ if expectTx[i].Nonce() != tx.Nonce() {
+ t.Errorf("unexpected nonce expect %v but %v", expectTx[i].Nonce(), tx.Nonce())
+ }
+
+ if expectTx[i].GasPrice().Uint64() != tx.GasPrice().Uint64() {
+ t.Errorf("unexpected gas price expect %v but %v",
+ expectTx[i].GasPrice().Uint64(), tx.GasPrice().Uint64())
+ }
+ }
+ }
+}
+
+func TestPrepareWitness(t *testing.T) {
+ key, err := crypto.GenerateKey()
+ if err != nil {
+ t.Errorf("hex to ecdsa error: %v", err)
+ }
+
+ dex, err := newTestDexonWithGenesis(key)
+ if err != nil {
+ t.Errorf("new test dexon error: %v", err)
+ }
+
+ currentBlock := dex.blockchain.CurrentBlock()
+
+ witness, err := dex.app.PrepareWitness(0)
+ if err != nil {
+ t.Errorf("prepare witness error: %v", err)
+ }
+
+ if witness.Height != currentBlock.NumberU64() {
+ t.Errorf("unexpeted witness height %v", witness.Height)
+ }
+
+ var witnessData witnessData
+ err = rlp.DecodeBytes(witness.Data, &witnessData)
+ if err != nil {
+ t.Errorf("rlp decode error: %v", err)
+ }
+
+ if witnessData.TxHash != currentBlock.TxHash() {
+ t.Errorf("expect tx hash %v but %v", currentBlock.TxHash(), witnessData.TxHash)
+ }
+
+ if witnessData.Root != currentBlock.Root() {
+ t.Errorf("expect root %v but %v", currentBlock.Root(), witnessData.Root)
+ }
+
+ if witnessData.ReceiptHash != currentBlock.ReceiptHash() {
+ t.Errorf("expect receipt hash %v but %v", currentBlock.ReceiptHash(), witnessData.ReceiptHash)
+ }
+
+ if _, err := dex.app.PrepareWitness(999); err == nil {
+ t.Errorf("it must be get error from prepare")
+ } else {
+ t.Logf("Nice error: %v", err)
+ }
+}
+
+func TestVerifyBlock(t *testing.T) {
+ key, err := crypto.GenerateKey()
+ if err != nil {
+ t.Errorf("hex to ecdsa error: %v", err)
+ }
+
+ dex, err := newTestDexonWithGenesis(key)
+ if err != nil {
+ t.Errorf("new test dexon error: %v", err)
+ }
+
+ // Prepare first confirmed block.
+ prepareConfirmedBlocks(dex, []*ecdsa.PrivateKey{key}, 0)
+
+ chainID := new(big.Int).Mod(crypto.PubkeyToAddress(key.PublicKey).Big(),
+ big.NewInt(int64(dex.chainConfig.Dexcon.NumChains)))
+
+ // Prepare normal block.
+ block := coreTypes.NewBlock()
+ block.Hash = coreCommon.NewRandomHash()
+ block.Position.ChainID = uint32(chainID.Uint64())
+ block.Position.Height = 1
+ block.Payload, block.Witness, err = prepareDataWithoutTxPool(dex, key, 0, 100)
+ if err != nil {
+ t.Errorf("prepare data error: %v", err)
+ }
+
+ // Expect ok.
+ status := dex.app.VerifyBlock(block)
+ if status != coreTypes.VerifyOK {
+ t.Errorf("verify fail: %v", status)
+ }
+
+ // Prepare invalid nonce tx.
+ block = coreTypes.NewBlock()
+ block.Hash = coreCommon.NewRandomHash()
+ block.Position.ChainID = uint32(chainID.Uint64())
+ block.Position.Height = 1
+ block.Payload, block.Witness, err = prepareDataWithoutTxPool(dex, key, 1, 100)
+ if err != nil {
+ t.Errorf("prepare data error: %v", err)
+ }
+
+ // Expect invalid block.
+ status = dex.app.VerifyBlock(block)
+ if status != coreTypes.VerifyInvalidBlock {
+ t.Errorf("verify fail: %v", status)
+ }
+
+ // Prepare invalid block height.
+ block = coreTypes.NewBlock()
+ block.Hash = coreCommon.NewRandomHash()
+ block.Position.ChainID = uint32(chainID.Uint64())
+ block.Position.Height = 2
+ block.Payload, block.Witness, err = prepareDataWithoutTxPool(dex, key, 0, 100)
+ if err != nil {
+ t.Errorf("prepare data error: %v", err)
+ }
+
+ // Expect retry later.
+ status = dex.app.VerifyBlock(block)
+ if status != coreTypes.VerifyRetryLater {
+ t.Errorf("verify fail expect retry later but get %v", status)
+ }
+
+ // Prepare reach block limit.
+ block = coreTypes.NewBlock()
+ block.Hash = coreCommon.NewRandomHash()
+ block.Position.ChainID = uint32(chainID.Uint64())
+ block.Position.Height = 1
+ block.Payload, block.Witness, err = prepareDataWithoutTxPool(dex, key, 0, 10000)
+ if err != nil {
+ t.Errorf("prepare data error: %v", err)
+ }
+
+ // Expect invalid block.
+ status = dex.app.VerifyBlock(block)
+ if status != coreTypes.VerifyInvalidBlock {
+ t.Errorf("verify fail expect invalid block but get %v", status)
+ }
+
+ // Prepare insufficient funds.
+ block = coreTypes.NewBlock()
+ block.Hash = coreCommon.NewRandomHash()
+ block.Position.ChainID = uint32(chainID.Uint64())
+ block.Position.Height = 1
+ _, block.Witness, err = prepareDataWithoutTxPool(dex, key, 0, 0)
+ if err != nil {
+ t.Errorf("prepare data error: %v", err)
+ }
+
+ signer := types.NewEIP155Signer(dex.chainConfig.ChainID)
+ tx := types.NewTransaction(
+ 0,
+ common.BytesToAddress([]byte{9}),
+ big.NewInt(50000000000000001),
+ params.TxGas,
+ big.NewInt(1),
+ nil)
+ tx, err = types.SignTx(tx, signer, key)
+ if err != nil {
+ return
+ }
+
+ block.Payload, err = rlp.EncodeToBytes(types.Transactions{tx})
+ if err != nil {
+ return
+ }
+
+ // expect invalid block
+ status = dex.app.VerifyBlock(block)
+ if status != coreTypes.VerifyInvalidBlock {
+ t.Errorf("verify fail expect invalid block but get %v", status)
+ }
+
+ // Prepare invalid intrinsic gas.
+ block = coreTypes.NewBlock()
+ block.Hash = coreCommon.NewRandomHash()
+ block.Position.ChainID = uint32(chainID.Uint64())
+ block.Position.Height = 1
+ _, block.Witness, err = prepareDataWithoutTxPool(dex, key, 0, 0)
+ if err != nil {
+ t.Errorf("prepare data error: %v", err)
+ }
+
+ signer = types.NewEIP155Signer(dex.chainConfig.ChainID)
+ tx = types.NewTransaction(
+ 0,
+ common.BytesToAddress([]byte{9}),
+ big.NewInt(1),
+ params.TxGas,
+ big.NewInt(1),
+ make([]byte, 1))
+ tx, err = types.SignTx(tx, signer, key)
+ if err != nil {
+ return
+ }
+
+ block.Payload, err = rlp.EncodeToBytes(types.Transactions{tx})
+ if err != nil {
+ return
+ }
+
+ // Expect invalid block.
+ status = dex.app.VerifyBlock(block)
+ if status != coreTypes.VerifyInvalidBlock {
+ t.Errorf("verify fail expect invalid block but get %v", status)
+ }
+
+ // Prepare invalid transactions with nonce.
+ block = coreTypes.NewBlock()
+ block.Hash = coreCommon.NewRandomHash()
+ block.Position.ChainID = uint32(chainID.Uint64())
+ block.Position.Height = 1
+ _, block.Witness, err = prepareDataWithoutTxPool(dex, key, 0, 0)
+ if err != nil {
+ t.Errorf("prepare data error: %v", err)
+ }
+
+ signer = types.NewEIP155Signer(dex.chainConfig.ChainID)
+ tx1 := types.NewTransaction(
+ 0,
+ common.BytesToAddress([]byte{9}),
+ big.NewInt(1),
+ params.TxGas,
+ big.NewInt(1),
+ make([]byte, 1))
+ tx1, err = types.SignTx(tx, signer, key)
+ if err != nil {
+ return
+ }
+
+ // Invalid nonce.
+ tx2 := types.NewTransaction(
+ 2,
+ common.BytesToAddress([]byte{9}),
+ big.NewInt(1),
+ params.TxGas,
+ big.NewInt(1),
+ make([]byte, 1))
+ tx2, err = types.SignTx(tx, signer, key)
+ if err != nil {
+ return
+ }
+
+ block.Payload, err = rlp.EncodeToBytes(types.Transactions{tx1, tx2})
+ if err != nil {
+ return
+ }
+
+ // Expect invalid block.
+ status = dex.app.VerifyBlock(block)
+ if status != coreTypes.VerifyInvalidBlock {
+ t.Errorf("verify fail expect invalid block but get %v", status)
+ }
+}
+
+func TestBlockConfirmed(t *testing.T) {
+ key, err := crypto.GenerateKey()
+ if err != nil {
+ t.Errorf("hex to ecdsa error: %v", err)
+ }
+
+ dex, err := newTestDexonWithGenesis(key)
+ if err != nil {
+ t.Errorf("new test dexon error: %v", err)
+ }
+
+ chainID := new(big.Int).Mod(crypto.PubkeyToAddress(key.PublicKey).Big(),
+ big.NewInt(int64(dex.chainConfig.Dexcon.NumChains)))
+
+ var (
+ expectCost big.Int
+ expectNonce uint64
+ expectCounter uint64
+ )
+ for i := 0; i < 10; i++ {
+ var startNonce int
+ if expectNonce != 0 {
+ startNonce = int(expectNonce) + 1
+ }
+ payload, witness, cost, nonce, err := prepareData(dex, key, startNonce, 50)
+ if err != nil {
+ t.Errorf("prepare data error: %v", err)
+ }
+ expectCost.Add(&expectCost, &cost)
+ expectNonce = nonce
+
+ block := coreTypes.NewBlock()
+ block.Hash = coreCommon.NewRandomHash()
+ block.Witness = witness
+ block.Payload = payload
+ block.Position.ChainID = uint32(chainID.Uint64())
+
+ dex.app.BlockConfirmed(*block)
+ expectCounter++
+ }
+
+ info := dex.app.blockchain.GetAddressInfo(uint32(chainID.Uint64()),
+ crypto.PubkeyToAddress(key.PublicKey))
+
+ if info.Counter != expectCounter {
+ t.Errorf("expect address counter is %v but %v", expectCounter, info.Counter)
+ }
+
+ if info.Cost.Cmp(&expectCost) != 0 {
+ t.Errorf("expect address cost is %v but %v", expectCost.Uint64(), info.Cost.Uint64())
+ }
+
+ if info.Nonce != expectNonce {
+ t.Errorf("expect address nonce is %v but %v", expectNonce, info.Nonce)
+ }
+}
+
+func TestBlockDelivered(t *testing.T) {
+ key, err := crypto.GenerateKey()
+ if err != nil {
+ t.Errorf("hex to ecdsa error: %v", err)
+ }
+
+ dex, err := newTestDexonWithGenesis(key)
+ if err != nil {
+ t.Errorf("new test dexon error: %v", err)
+ }
+
+ address := crypto.PubkeyToAddress(key.PublicKey)
+ firstBlocksInfo, err := prepareConfirmedBlocks(dex, []*ecdsa.PrivateKey{key}, 50)
+ if err != nil {
+ t.Errorf("preapare confirmed block error: %v", err)
+ }
+
+ dex.app.BlockDelivered(firstBlocksInfo[0].Block.Hash, firstBlocksInfo[0].Block.Position,
+ coreTypes.FinalizationResult{
+ Timestamp: time.Now(),
+ Height: 1,
+ })
+
+ pendingBlock, pendingState := dex.blockchain.GetPending()
+
+ r, ok := dex.app.chainLatestRoot.Load(firstBlocksInfo[0].Block.Position.ChainID)
+ if !ok {
+ t.Errorf("lastest root cache not exist")
+ }
+
+ if *r.(*common.Hash) != pendingBlock.Root() {
+ t.Errorf("incorrect pending root")
+ }
+
+ currentBlock := dex.blockchain.CurrentBlock()
+ if currentBlock.NumberU64() != 0 {
+ t.Errorf("unexpected current block number %v", currentBlock.NumberU64())
+ }
+
+ pendingNonce := pendingState.GetNonce(address)
+ if pendingNonce != firstBlocksInfo[0].Nonce+1 {
+ t.Errorf("unexpected pending state nonce %v", pendingNonce)
+ }
+
+ balance := pendingState.GetBalance(address)
+ if new(big.Int).Add(balance, &firstBlocksInfo[0].Cost).Cmp(big.NewInt(50000000000000000)) != 0 {
+ t.Errorf("unexpected pending state balance %v", balance)
+ }
+
+ // prepare second block to witness first block
+ secondBlocksInfo, err := prepareConfirmedBlocks(dex, []*ecdsa.PrivateKey{key}, 25)
+ if err != nil {
+ t.Errorf("preapare confirmed block error: %v", err)
+ }
+
+ dex.app.BlockDelivered(secondBlocksInfo[0].Block.Hash, secondBlocksInfo[0].Block.Position,
+ coreTypes.FinalizationResult{
+ Timestamp: time.Now(),
+ Height: 2,
+ })
+
+ // second block witness first block, so current block number should be 1
+ currentBlock = dex.blockchain.CurrentBlock()
+ if currentBlock.NumberU64() != 1 {
+ t.Errorf("unexpected current block number %v", currentBlock.NumberU64())
+ }
+
+ currentState, err := dex.blockchain.State()
+ if err != nil {
+ t.Errorf("current state error: %v", err)
+ }
+
+ currentNonce := currentState.GetNonce(address)
+ if currentNonce != firstBlocksInfo[0].Nonce+1 {
+ t.Errorf("unexpected current state nonce %v", currentNonce)
+ }
+
+ balance = currentState.GetBalance(address)
+ if new(big.Int).Add(balance, &firstBlocksInfo[0].Cost).Cmp(big.NewInt(50000000000000000)) != 0 {
+ t.Errorf("unexpected current state balance %v", balance)
+ }
+}
+
+func BenchmarkBlockDeliveredFlow(b *testing.B) {
+ key, err := crypto.GenerateKey()
+ if err != nil {
+ b.Errorf("hex to ecdsa error: %v", err)
+ return
+ }
+
+ dex, err := newTestDexonWithGenesis(key)
+ if err != nil {
+ b.Errorf("new test dexon error: %v", err)
+ }
+
+ b.ResetTimer()
+ for i := 1; i <= b.N; i++ {
+ blocksInfo, err := prepareConfirmedBlocks(dex, []*ecdsa.PrivateKey{key}, 100)
+ if err != nil {
+ b.Errorf("preapare confirmed block error: %v", err)
+ return
+ }
+
+ dex.app.BlockDelivered(blocksInfo[0].Block.Hash, blocksInfo[0].Block.Position,
+ coreTypes.FinalizationResult{
+ Timestamp: time.Now(),
+ Height: uint64(i),
+ })
+ }
+}
+
+func newTestDexonWithGenesis(allocKey *ecdsa.PrivateKey) (*Dexon, error) {
+ db := ethdb.NewMemDatabase()
+
+ testBankAddress := crypto.PubkeyToAddress(allocKey.PublicKey)
+ genesis := core.DefaultTestnetGenesisBlock()
+ genesis.Alloc = core.GenesisAlloc{
+ testBankAddress: {
+ Balance: big.NewInt(100000000000000000),
+ Staked: big.NewInt(50000000000000000),
+ },
+ }
+ chainConfig, _, err := core.SetupGenesisBlock(db, genesis)
+ if err != nil {
+ return nil, err
+ }
+
+ key, err := crypto.GenerateKey()
+ if err != nil {
+ return nil, err
+ }
+
+ config := Config{PrivateKey: key}
+ vmConfig := vm.Config{IsBlockProposer: true}
+
+ engine := dexcon.New()
+
+ dex := &Dexon{
+ chainDb: db,
+ chainConfig: chainConfig,
+ networkID: config.NetworkId,
+ engine: engine,
+ }
+
+ dex.blockchain, err = core.NewBlockChain(db, nil, chainConfig, engine, vmConfig, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ txPoolConfig := core.DefaultTxPoolConfig
+ dex.txPool = core.NewTxPool(txPoolConfig, chainConfig, dex.blockchain, true)
+
+ dex.APIBackend = &DexAPIBackend{dex, nil}
+ dex.governance = NewDexconGovernance(dex.APIBackend, dex.chainConfig, config.PrivateKey)
+ engine.SetConfigFetcher(dex.governance)
+ dex.app = NewDexconApp(dex.txPool, dex.blockchain, dex.governance, db, &config)
+
+ return dex, nil
+}
+
+// Add tx into tx pool.
+func addTx(dex *Dexon, nonce int, signer types.Signer, key *ecdsa.PrivateKey) (
+ *types.Transaction, error) {
+ tx := types.NewTransaction(
+ uint64(nonce),
+ common.BytesToAddress([]byte{9}),
+ big.NewInt(int64(nonce*1)),
+ params.TxGas,
+ big.NewInt(1),
+ nil)
+ tx, err := types.SignTx(tx, signer, key)
+ if err != nil {
+ return nil, err
+ }
+
+ if err := dex.txPool.AddRemote(tx); err != nil {
+ return nil, err
+ }
+
+ return tx, nil
+}
+
+// Prepare data with given transaction number and start nonce.
+func prepareData(dex *Dexon, key *ecdsa.PrivateKey, startNonce, txNum int) (
+ payload []byte, witness coreTypes.Witness, cost big.Int, nonce uint64, err error) {
+ signer := types.NewEIP155Signer(dex.chainConfig.ChainID)
+ chainID := new(big.Int).Mod(crypto.PubkeyToAddress(key.PublicKey).Big(),
+ big.NewInt(int64(dex.chainConfig.Dexcon.NumChains)))
+
+ for n := startNonce; n < startNonce+txNum; n++ {
+ var tx *types.Transaction
+ tx, err = addTx(dex, n, signer, key)
+ if err != nil {
+ return
+ }
+
+ cost.Add(&cost, tx.Cost())
+ nonce = uint64(n)
+ }
+
+ payload, err = dex.app.PreparePayload(coreTypes.Position{ChainID: uint32(chainID.Uint64())})
+ if err != nil {
+ return
+ }
+
+ witness, err = dex.app.PrepareWitness(0)
+ if err != nil {
+ return
+ }
+
+ return
+}
+
+func prepareDataWithoutTxPool(dex *Dexon, key *ecdsa.PrivateKey, startNonce, txNum int) (
+ payload []byte, witness coreTypes.Witness, err error) {
+ signer := types.NewEIP155Signer(dex.chainConfig.ChainID)
+
+ var transactions types.Transactions
+ for n := startNonce; n < startNonce+txNum; n++ {
+ tx := types.NewTransaction(
+ uint64(n),
+ common.BytesToAddress([]byte{9}),
+ big.NewInt(int64(n*1)),
+ params.TxGas,
+ big.NewInt(1),
+ nil)
+ tx, err = types.SignTx(tx, signer, key)
+ if err != nil {
+ return
+ }
+ transactions = append(transactions, tx)
+ }
+
+ payload, err = rlp.EncodeToBytes(&transactions)
+ if err != nil {
+ return
+ }
+
+ witness, err = dex.app.PrepareWitness(0)
+ if err != nil {
+ return
+ }
+
+ return
+}
+
+func prepareConfirmedBlocks(dex *Dexon, keys []*ecdsa.PrivateKey, txNum int) (blocksInfo []struct {
+ Block *coreTypes.Block
+ Cost big.Int
+ Nonce uint64
+}, err error) {
+ for _, key := range keys {
+ address := crypto.PubkeyToAddress(key.PublicKey)
+ chainID := new(big.Int).Mod(address.Big(),
+ big.NewInt(int64(dex.chainConfig.Dexcon.NumChains)))
+
+ // Prepare one block for pending.
+ var (
+ payload []byte
+ witness coreTypes.Witness
+ cost big.Int
+ nonce uint64
+ )
+ startNonce := dex.txPool.State().GetNonce(address)
+ payload, witness, cost, nonce, err = prepareData(dex, key, int(startNonce), txNum)
+ if err != nil {
+ err = fmt.Errorf("prepare data error: %v", err)
+ return
+ }
+
+ block := coreTypes.NewBlock()
+ block.Hash = coreCommon.NewRandomHash()
+ block.Witness = witness
+ block.Payload = payload
+ block.Position.ChainID = uint32(chainID.Uint64())
+
+ status := dex.app.VerifyBlock(block)
+ if status != coreTypes.VerifyOK {
+ err = fmt.Errorf("verify fail: %v", status)
+ return
+ }
+
+ dex.app.BlockConfirmed(*block)
+
+ blocksInfo = append(blocksInfo, struct {
+ Block *coreTypes.Block
+ Cost big.Int
+ Nonce uint64
+ }{Block: block, Cost: cost, Nonce: nonce})
+ }
+
+ return
+}
diff --git a/dex/backend.go b/dex/backend.go
index 550b1051a..eb9d8f765 100644
--- a/dex/backend.go
+++ b/dex/backend.go
@@ -150,7 +150,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Dexon, error) {
// Dexcon related objects.
dex.governance = NewDexconGovernance(dex.APIBackend, dex.chainConfig, config.PrivateKey)
- dex.app = NewDexconApp(dex.txPool, dex.blockchain, dex.governance, chainDb, config, vmConfig)
+ dex.app = NewDexconApp(dex.txPool, dex.blockchain, dex.governance, chainDb, config)
// Set config fetcher so engine can fetch current system configuration from state.
engine.SetConfigFetcher(dex.governance)