Commit 334d1b01 authored by mdj33's avatar mdj33 Committed by 33cn

empty interval

parent 31d287af
......@@ -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]
......
......@@ -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
}
}
......
......@@ -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, int64(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, int64(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, int64(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, int64(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, int64(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)
}
......@@ -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 seperate", "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 {
......
......@@ -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)
......@@ -378,8 +387,8 @@ 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
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))
......
......@@ -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}"
......
......@@ -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 {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment