Repository: 33cn/plugin (go)

Issue:
平行链空块间隔参数配置优化
之前空块间隔的配置在批量读写toml配置文件时候支持比较复杂，改为简单的单kv 类型

Pull request description:
平行链空块间隔优化
fixes #812

Patch:
diff --git a/chain33.para.toml b/chain33.para.toml
index 567962cd1..ba1718fd5 100644
--- a/chain33.para.toml
+++ b/chain33.para.toml
@@ -103,11 +103,8 @@ mainBlockHashForkHeight=209186
 mainForkParacrossCommitTx=2270000
 #主链开启循环检查共识交易done的fork高度,需要和主链保持严格一致,不可修改,4320000是bityuan主链对应高度， ycc或其他按实际修改
 mainLoopCheckCommitTxDoneForkHeight=4320000
-#主链每隔几个没有相关平行链交易的区块，平行链上打包空区块，缺省从平行链blockHeight=0开始，依次增长，空块间隔不能为0
-[[consensus.sub.para.emptyBlockInterval]]
-blockHeight=0
-interval=50
-
+#无平行链交易的主链区块间隔，平行链产生一个空块，从高度0开始，配置[blockHeight:interval],比如["0:50","1000:100"]
+emptyBlockInterval=["0:50"]
 
 
 [store]
diff --git a/go.mod b/go.mod
index 3a055d5de..40f259f91 100644
--- a/go.mod
+++ b/go.mod
@@ -3,7 +3,7 @@ module github.com/33cn/plugin
 go 1.12
 
 require (
-	github.com/33cn/chain33 v0.0.0-20200314025239-68ef1b429d3b
+	github.com/33cn/chain33 v0.0.0-20200322081059-10e7a26d6dc3
 	github.com/BurntSushi/toml v0.3.1
 	github.com/NebulousLabs/Sia v1.3.7
 	github.com/beorn7/perks v1.0.1 // indirect
diff --git a/go.sum b/go.sum
index b43727276..973df142a 100644
--- a/go.sum
+++ b/go.sum
@@ -1,6 +1,6 @@
 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-github.com/33cn/chain33 v0.0.0-20200314025239-68ef1b429d3b h1:p0z3gfCHhwPIv8n89mLNUS2JJxpeQeiMO3ETQNOIkt8=
-github.com/33cn/chain33 v0.0.0-20200314025239-68ef1b429d3b/go.mod h1:lQwHpQNknnHEQla33z42+YuBkjwjcNooMMwRqmhsG/c=
+github.com/33cn/chain33 v0.0.0-20200322081059-10e7a26d6dc3 h1:mfjZi5jQxSQTMZXxgAmtVCaAJ5YQp2fmxOVFIl7vt7Y=
+github.com/33cn/chain33 v0.0.0-20200322081059-10e7a26d6dc3/go.mod h1:lQwHpQNknnHEQla33z42+YuBkjwjcNooMMwRqmhsG/c=
 github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7 h1:PqzgE6kAMi81xWQA2QIVxjWkFHptGgC547vchpUbtFo=
 github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
 github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9 h1:HD8gA2tkByhMAwYaFAX9w2l7vxvBQ5NMoxDrkhqhtn4=
diff --git a/plugin/consensus/para/para.go b/plugin/consensus/para/para.go
index 519aac9f7..220e123a9 100644
--- a/plugin/consensus/para/para.go
+++ b/plugin/consensus/para/para.go
@@ -9,6 +9,8 @@ import (
 	"fmt"
 	"sync"
 
+	"sort"
+
 	log "github.com/33cn/chain33/common/log/log15"
 
 	"sync/atomic"
@@ -62,36 +64,32 @@ type client struct {
 	minerPrivateKey crypto.PrivKey
 	wg              sync.WaitGroup
 	subCfg          *subConfig
+	dldCfg          *downloadClient
 	isClosed        int32
 	quitCreate      chan struct{}
 }
 
-type emptyBlockInterval struct {
-	BlockHeight int64 `json:"blockHeight,omitempty"`
-	Interval    int64 `json:"interval,omitempty"`
-}
-
 type subConfig struct {
-	WriteBlockSeconds       int64                 `json:"writeBlockSeconds,omitempty"`
-	ParaRemoteGrpcClient    string                `json:"paraRemoteGrpcClient,omitempty"`
-	StartHeight             int64                 `json:"startHeight,omitempty"`
-	GenesisStartHeightSame  bool                  `json:"genesisStartHeightSame,omitempty"`
-	EmptyBlockInterval      []*emptyBlockInterval `json:"emptyBlockInterval,omitempty"`
-	AuthAccount             string                `json:"authAccount,omitempty"`
-	WaitBlocks4CommitMsg    int32                 `json:"waitBlocks4CommitMsg,omitempty"`
-	GenesisAmount           int64                 `json:"genesisAmount,omitempty"`
-	MainBlockHashForkHeight int64                 `json:"mainBlockHashForkHeight,omitempty"`
-	WaitConsensStopTimes    uint32                `json:"waitConsensStopTimes,omitempty"`
-	MaxCacheCount           int64                 `json:"maxCacheCount,omitempty"`
-	MaxSyncErrCount         int32                 `json:"maxSyncErrCount,omitempty"`
-	BatchFetchBlockCount    int64                 `json:"batchFetchBlockCount,omitempty"`
-	ParaConsensStartHeight  int64                 `json:"paraConsensStartHeight,omitempty"`
-	MultiDownloadOpen       bool                  `json:"multiDownloadOpen,omitempty"`
-	MultiDownInvNumPerJob   int64                 `json:"multiDownInvNumPerJob,omitempty"`
-	MultiDownJobBuffNum     uint32                `json:"multiDownJobBuffNum,omitempty"`
-	MultiDownServerRspTime  uint32                `json:"multiDownServerRspTime,omitempty"`
-	RmCommitParamMainHeight int64                 `json:"rmCommitParamMainHeight,omitempty"`
-	JumpDownloadClose       bool                  `json:"jumpDownloadClose,omitempty"`
+	WriteBlockSeconds       int64    `json:"writeBlockSeconds,omitempty"`
+	ParaRemoteGrpcClient    string   `json:"paraRemoteGrpcClient,omitempty"`
+	StartHeight             int64    `json:"startHeight,omitempty"`
+	GenesisStartHeightSame  bool     `json:"genesisStartHeightSame,omitempty"`
+	EmptyBlockInterval      []string `json:"emptyBlockInterval,omitempty"`
+	AuthAccount             string   `json:"authAccount,omitempty"`
+	WaitBlocks4CommitMsg    int32    `json:"waitBlocks4CommitMsg,omitempty"`
+	GenesisAmount           int64    `json:"genesisAmount,omitempty"`
+	MainBlockHashForkHeight int64    `json:"mainBlockHashForkHeight,omitempty"`
+	WaitConsensStopTimes    uint32   `json:"waitConsensStopTimes,omitempty"`
+	MaxCacheCount           int64    `json:"maxCacheCount,omitempty"`
+	MaxSyncErrCount         int32    `json:"maxSyncErrCount,omitempty"`
+	BatchFetchBlockCount    int64    `json:"batchFetchBlockCount,omitempty"`
+	ParaConsensStartHeight  int64    `json:"paraConsensStartHeight,omitempty"`
+	MultiDownloadOpen       bool     `json:"multiDownloadOpen,omitempty"`
+	MultiDownInvNumPerJob   int64    `json:"multiDownInvNumPerJob,omitempty"`
+	MultiDownJobBuffNum     uint32   `json:"multiDownJobBuffNum,omitempty"`
+	MultiDownServerRspTime  uint32   `json:"multiDownServerRspTime,omitempty"`
+	RmCommitParamMainHeight int64    `json:"rmCommitParamMainHeight,omitempty"`
+	JumpDownloadClose       bool     `json:"jumpDownloadClose,omitempty"`
 }
 
 // New function to init paracross env
@@ -108,11 +106,12 @@ func New(cfg *types.Consensus, sub []byte) queue.Module {
 	if subcfg.WriteBlockSeconds <= 0 {
 		subcfg.WriteBlockSeconds = poolMainBlockSec
 	}
-	if len(subcfg.EmptyBlockInterval) == 0 {
-		interval := &emptyBlockInterval{Interval: defaultEmptyBlockInterval}
-		subcfg.EmptyBlockInterval = append(subcfg.EmptyBlockInterval, interval)
+
+	emptyInterval, err := parseEmptyBlockInterval(subcfg.EmptyBlockInterval)
+	if err != nil {
+		panic("para EmptyBlockInterval config not correct")
 	}
-	err := checkEmptyBlockInterval(subcfg.EmptyBlockInterval)
+	err = checkEmptyBlockInterval(emptyInterval)
 	if err != nil {
 		panic("para EmptyBlockInterval config not correct")
 	}
@@ -144,6 +143,9 @@ func New(cfg *types.Consensus, sub []byte) queue.Module {
 		quitCreate:      make(chan struct{}),
 	}
 
+	para.dldCfg = &downloadClient{}
+	para.dldCfg.emptyInterval = append(para.dldCfg.emptyInterval, emptyInterval...)
+
 	para.commitMsgClient = &commitMsgClient{
 		paraClient:           para,
 		authAccount:          subcfg.AuthAccount,
@@ -206,18 +208,45 @@ func New(cfg *types.Consensus, sub []byte) queue.Module {
 	return para
 }
 
+//["0:50","100:20","500:30"]
+func parseEmptyBlockInterval(cfg []string) ([]*emptyBlockInterval, error) {
+	var emptyInter []*emptyBlockInterval
+	if len(cfg) == 0 {
+		interval := &emptyBlockInterval{startHeight: 0, interval: defaultEmptyBlockInterval}
+		emptyInter = append(emptyInter, interval)
+		return emptyInter, nil
+	}
+
+	list := make(map[int64]int64)
+	var seq []int64
+	for _, e := range cfg {
+		ret, err := divideStr2Int64s(e, ":")
+		if err != nil {
+			plog.Error("parse empty block inter config", "str", e)
+			return nil, err
+		}
+		seq = append(seq, ret[0])
+		list[ret[0]] = ret[1]
+	}
+	sort.Slice(seq, func(i, j int) bool { return seq[i] < seq[j] })
+	for _, h := range seq {
+		emptyInter = append(emptyInter, &emptyBlockInterval{startHeight: h, interval: list[h]})
+	}
+	return emptyInter, nil
+}
+
 func checkEmptyBlockInterval(in []*emptyBlockInterval) error {
 	for i := 0; i < len(in); i++ {
-		if i == 0 && in[i].BlockHeight != 0 {
-			plog.Error("EmptyBlockInterval,first blockHeight should be 0", "height", in[i].BlockHeight)
+		if i == 0 && in[i].startHeight != 0 {
+			plog.Error("EmptyBlockInterval,first blockHeight should be 0", "height", in[i].startHeight)
 			return types.ErrInvalidParam
 		}
-		if i > 0 && in[i].BlockHeight <= in[i-1].BlockHeight {
-			plog.Error("EmptyBlockInterval,blockHeight should be sequence", "preHeight", in[i-1].BlockHeight, "laterHeight", in[i].BlockHeight)
+		if i > 0 && in[i].startHeight <= in[i-1].startHeight {
+			plog.Error("EmptyBlockInterval,blockHeight should be sequence", "preHeight", in[i-1].startHeight, "laterHeight", in[i].startHeight)
 			return types.ErrInvalidParam
 		}
-		if in[i].Interval <= 0 {
-			plog.Error("EmptyBlockInterval,interval should > 0", "height", in[i].BlockHeight)
+		if in[i].interval <= 0 {
+			plog.Error("EmptyBlockInterval,interval should > 0", "height", in[i].startHeight)
 			return types.ErrInvalidParam
 		}
 	}
diff --git a/plugin/consensus/para/paracommitmsg.go b/plugin/consensus/para/paracommitmsg.go
index 6cfcb9b61..50b8755a7 100644
--- a/plugin/consensus/para/paracommitmsg.go
+++ b/plugin/consensus/para/paracommitmsg.go
@@ -907,24 +907,35 @@ func (client *commitMsgClient) fetchPriKey() error {
 }
 
 func parseSelfConsEnableStr(selfEnables []string) ([]*paraSelfConsEnable, error) {
-	var err error
 	var list []*paraSelfConsEnable
-	for _, v := range selfEnables {
-		hs := strings.Split(v, "-")
-		enable := &paraSelfConsEnable{}
-		enable.startHeight, err = strconv.ParseInt(hs[0], 0, 64)
+	for _, e := range selfEnables {
+		ret, err := divideStr2Int64s(e, "-")
 		if err != nil {
-			plog.Error("para setSelfConsEnable", "v0", hs[0], "err", err)
 			return nil, err
 		}
-		enable.endHeight, err = strconv.ParseInt(hs[1], 0, 64)
+		list = append(list, &paraSelfConsEnable{ret[0], ret[1]})
+	}
+	return list, nil
+}
+
+//only for "0:50" or "0-50" with one sep
+func divideStr2Int64s(s, sep string) ([]int64, error) {
+	var r []int64
+	a := strings.Split(s, sep)
+	if len(a) != 2 {
+		plog.Error("error format for config to separate", "s", s)
+		return nil, types.ErrInvalidParam
+	}
+
+	for _, v := range a {
+		val, err := strconv.ParseInt(v, 0, 64)
 		if err != nil {
-			plog.Error("para setSelfConsEnable", "v1", hs[1], "err", err)
+			plog.Error("error format for config to parse to int", "s", s)
 			return nil, err
 		}
-		list = append(list, enable)
+		r = append(r, val)
 	}
-	return list, nil
+	return r, nil
 }
 
 func (client *commitMsgClient) setSelfConsEnable() error {
diff --git a/plugin/consensus/para/paracreate.go b/plugin/consensus/para/paracreate.go
index 2da3936a6..81372a4b3 100644
--- a/plugin/consensus/para/paracreate.go
+++ b/plugin/consensus/para/paracreate.go
@@ -21,6 +21,15 @@ import (
 	pt "github.com/33cn/plugin/plugin/dapp/paracross/types"
 )
 
+type emptyBlockInterval struct {
+	startHeight int64
+	interval    int64
+}
+
+type downloadClient struct {
+	emptyInterval []*emptyBlockInterval
+}
+
 func (client *client) createLocalGenesisBlock(genesis *types.Block) error {
 	return client.alignLocalBlock2ChainBlock(genesis)
 }
@@ -236,7 +245,7 @@ func (client *client) getBatchSeqCount(currSeq int64) (int64, error) {
 	}
 
 	if lastSeq > currSeq {
-		if lastSeq-currSeq > client.subCfg.EmptyBlockInterval[0].Interval {
+		if lastSeq-currSeq > client.dldCfg.emptyInterval[0].interval {
 			atomic.StoreInt32(&client.caughtUp, 0)
 		} else {
 			atomic.StoreInt32(&client.caughtUp, 1)
@@ -377,9 +386,9 @@ func (client *client) processHashNotMatchError(currSeq int64, lastSeqMainHash []
 }
 
 func (client *client) getEmptyInterval(lastBlock *pt.ParaLocalDbBlock) int64 {
-	for i := len(client.subCfg.EmptyBlockInterval) - 1; i >= 0; i-- {
-		if lastBlock.Height >= client.subCfg.EmptyBlockInterval[i].BlockHeight {
-			return client.subCfg.EmptyBlockInterval[i].Interval
+	for i := len(client.dldCfg.emptyInterval) - 1; i >= 0; i-- {
+		if lastBlock.Height >= client.dldCfg.emptyInterval[i].startHeight {
+			return client.dldCfg.emptyInterval[i].interval
 		}
 	}
 	panic(fmt.Sprintf("emptyBlockInterval not set for height=%d", lastBlock.Height))
diff --git a/plugin/dapp/paracross/commands/paracross.go b/plugin/dapp/paracross/commands/paracross.go
index 73c9ee62b..134ac8312 100644
--- a/plugin/dapp/paracross/commands/paracross.go
+++ b/plugin/dapp/paracross/commands/paracross.go
@@ -299,8 +299,16 @@ func createCrossAssetTransfer(cmd *cobra.Command, args []string) {
 	}
 
 	rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
-	ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.CreateTransaction", params, nil)
-	ctx.RunWithoutMarshal()
+	var res string
+	ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.CreateTransaction", params, &res)
+	_, err := ctx.RunResult()
+	if err != nil {
+		fmt.Println(err)
+		return
+	}
+	//remove 0x
+	fmt.Println(res[2:])
+
 }
 
 func superNodeCmd() *cobra.Command {


Test patch:
diff --git a/plugin/consensus/para/para_test.go b/plugin/consensus/para/para_test.go
index 64d7fa7e3..55e7f2279 100644
--- a/plugin/consensus/para/para_test.go
+++ b/plugin/consensus/para/para_test.go
@@ -225,62 +225,116 @@ func TestGetLastBlockInfo(t *testing.T) {
 }
 
 func TestGetEmptyInterval(t *testing.T) {
-	int1 := &emptyBlockInterval{BlockHeight: 0, Interval: 1}
-	int2 := &emptyBlockInterval{BlockHeight: 10, Interval: 10}
-	int3 := &emptyBlockInterval{BlockHeight: 15, Interval: 15}
+	int1 := &emptyBlockInterval{startHeight: 0, interval: 1}
+	int2 := &emptyBlockInterval{startHeight: 10, interval: 10}
+	int3 := &emptyBlockInterval{startHeight: 15, interval: 15}
 
 	ints := []*emptyBlockInterval{int1, int2, int3}
 	para := new(client)
-	para.subCfg = &subConfig{EmptyBlockInterval: ints}
+	para.dldCfg = &downloadClient{}
+	para.dldCfg.emptyInterval = append(para.dldCfg.emptyInterval, ints...)
 
 	lastBlock := &pt.ParaLocalDbBlock{Height: 1}
 	ret := para.getEmptyInterval(lastBlock)
-	assert.Equal(t, int1.Interval, ret)
+	assert.Equal(t, int1.interval, ret)
 
 	lastBlock = &pt.ParaLocalDbBlock{Height: 10}
 	ret = para.getEmptyInterval(lastBlock)
-	assert.Equal(t, int2.Interval, ret)
+	assert.Equal(t, int2.interval, ret)
 
 	lastBlock = &pt.ParaLocalDbBlock{Height: 11}
 	ret = para.getEmptyInterval(lastBlock)
-	assert.Equal(t, int2.Interval, ret)
+	assert.Equal(t, int2.interval, ret)
 
 	lastBlock = &pt.ParaLocalDbBlock{Height: 16}
 	ret = para.getEmptyInterval(lastBlock)
-	assert.Equal(t, int3.Interval, ret)
+	assert.Equal(t, int3.interval, ret)
 
 }
 
 func TestCheckEmptyInterval(t *testing.T) {
-	int1 := &emptyBlockInterval{BlockHeight: 0, Interval: 1}
-	int2 := &emptyBlockInterval{BlockHeight: 10, Interval: 10}
-	int3 := &emptyBlockInterval{BlockHeight: 15, Interval: 15}
+	int1 := &emptyBlockInterval{startHeight: 0, interval: 1}
+	int2 := &emptyBlockInterval{startHeight: 10, interval: 10}
+	int3 := &emptyBlockInterval{startHeight: 15, interval: 15}
 
-	int1.BlockHeight = 5
+	int1.startHeight = 5
 	ints := []*emptyBlockInterval{int1, int2, int3}
 	err := checkEmptyBlockInterval(ints)
 	assert.Equal(t, types.ErrInvalidParam, err)
-	int1.BlockHeight = 0
+	int1.startHeight = 0
 
-	int3.BlockHeight = 5
+	int3.startHeight = 5
 	ints = []*emptyBlockInterval{int1, int2, int3}
 	err = checkEmptyBlockInterval(ints)
 	assert.Equal(t, types.ErrInvalidParam, err)
 
-	int3.BlockHeight = 10
+	int3.startHeight = 10
 	ints = []*emptyBlockInterval{int1, int2, int3}
 	err = checkEmptyBlockInterval(ints)
 	assert.Equal(t, types.ErrInvalidParam, err)
-	int3.BlockHeight = 15
+	int3.startHeight = 15
 
-	int2.Interval = 0
+	int2.interval = 0
 	ints = []*emptyBlockInterval{int1, int2, int3}
 	err = checkEmptyBlockInterval(ints)
 	assert.Equal(t, types.ErrInvalidParam, err)
 
-	int2.Interval = 2
+	int2.interval = 2
 	ints = []*emptyBlockInterval{int1, int2, int3}
 	err = checkEmptyBlockInterval(ints)
 	assert.Equal(t, nil, err)
 
 }
+
+func TestParseEmptyBlockInterval(t *testing.T) {
+	cfg := []string{}
+	ret, err := parseEmptyBlockInterval(cfg)
+	assert.Nil(t, err)
+	assert.Equal(t, int64(0), ret[0].startHeight)
+	assert.Equal(t, defaultEmptyBlockInterval, ret[0].interval)
+
+	cfg = []string{"0:50"}
+	ret, err = parseEmptyBlockInterval(cfg)
+	assert.Nil(t, err)
+	assert.Equal(t, int64(0), ret[0].startHeight)
+	assert.Equal(t, defaultEmptyBlockInterval, ret[0].interval)
+
+	cfg = []string{"0:50", "100:20"}
+	ret, err = parseEmptyBlockInterval(cfg)
+	assert.Nil(t, err)
+	assert.Equal(t, int64(0), ret[0].startHeight)
+	assert.Equal(t, defaultEmptyBlockInterval, ret[0].interval)
+	assert.Equal(t, int64(100), ret[1].startHeight)
+	assert.Equal(t, int64(20), ret[1].interval)
+
+	cfg = []string{"10:50"}
+	ret, err = parseEmptyBlockInterval(cfg)
+	assert.Nil(t, err)
+	assert.Equal(t, int64(10), ret[0].startHeight)
+	assert.Equal(t, defaultEmptyBlockInterval, ret[0].interval)
+
+	cfg = []string{"10:50", "20-30"}
+	ret, err = parseEmptyBlockInterval(cfg)
+	assert.NotNil(t, err)
+
+	cfg = []string{"10:50", "20:"}
+	ret, err = parseEmptyBlockInterval(cfg)
+	assert.NotNil(t, err)
+
+	cfg = []string{"10:50", ":20"}
+	ret, err = parseEmptyBlockInterval(cfg)
+	assert.NotNil(t, err)
+
+	//mess sequence
+	cfg = []string{"100:30", "0:50", "30:20", "200:10"}
+	ret, err = parseEmptyBlockInterval(cfg)
+	assert.Nil(t, err)
+	assert.Equal(t, int64(0), ret[0].startHeight)
+	assert.Equal(t, defaultEmptyBlockInterval, ret[0].interval)
+	assert.Equal(t, int64(30), ret[1].startHeight)
+	assert.Equal(t, int64(20), ret[1].interval)
+	assert.Equal(t, int64(100), ret[2].startHeight)
+	assert.Equal(t, int64(30), ret[2].interval)
+	assert.Equal(t, int64(200), ret[3].startHeight)
+	assert.Equal(t, int64(10), ret[3].interval)
+}
diff --git a/plugin/dapp/paracross/cmd/build/chain33.para.test.toml b/plugin/dapp/paracross/cmd/build/chain33.para.test.toml
index d6e94e858..9800147c8 100644
--- a/plugin/dapp/paracross/cmd/build/chain33.para.test.toml
+++ b/plugin/dapp/paracross/cmd/build/chain33.para.test.toml
@@ -103,9 +103,8 @@ waitBlocks4CommitMsg=2
 genesisAmount=100000000
 selfConsensEnablePreContract=["0-1000"]
 #主链每隔几个没有相关交易的区块，平行链上打包空区块
-[[consensus.sub.para.emptyBlockInterval]]
-blockHeight=0
-interval=4
+emptyBlockInterval=["0:4"]
+
 
 
 [store]
diff --git a/plugin/dapp/paracross/cmd/build/testcase.sh b/plugin/dapp/paracross/cmd/build/testcase.sh
index 204e3982c..0e035c3a6 100644
--- a/plugin/dapp/paracross/cmd/build/testcase.sh
+++ b/plugin/dapp/paracross/cmd/build/testcase.sh
@@ -42,7 +42,7 @@ function para_set_toml() {
     sed -i $xsedfix 's/^Title.*/Title="user.p.'''"$paraname"'''."/g' "${1}"
     sed -i $xsedfix 's/^# TestNet=.*/TestNet=true/g' "${1}"
     sed -i $xsedfix 's/^startHeight=.*/startHeight=1/g' "${1}"
-    sed -i $xsedfix 's/^interval=.*/interval=4/g' "${1}"
+    sed -i $xsedfix 's/^emptyBlockInterval=.*/emptyBlockInterval=["0:4"]/g' "${1}"
 
     sed -i $xsedfix 's/^mainForkParacrossCommitTx=.*/mainForkParacrossCommitTx=10/g' "${1}"
     sed -i $xsedfix 's/^mainLoopCheckCommitTxDoneForkHeight=.*/mainLoopCheckCommitTxDoneForkHeight='''$MainLoopCheckForkHeight'''/g' "${1}"
diff --git a/plugin/dapp/paracross/testnode/cfg.go b/plugin/dapp/paracross/testnode/cfg.go
index 1371adb5b..f9bfba1f4 100644
--- a/plugin/dapp/paracross/testnode/cfg.go
+++ b/plugin/dapp/paracross/testnode/cfg.go
@@ -118,9 +118,7 @@ mainBlockHashForkHeight=1
 mainForkParacrossCommitTx=1
 mainLoopCheckCommitTxDoneForkHeight=11
 selfConsensEnablePreContract=["0-1000"]
-[[consensus.sub.para.emptyBlockInterval]]
-blockHeight=0
-interval=2
+emptyBlockInterval=["0:2"]
 
 
 [store]