Commit 1d956b38 authored by kingwang's avatar kingwang Committed by 33cn

update chain33 03-20

parent 5dac10d3
......@@ -41,7 +41,7 @@ type DB struct {
// NewCoinsAccount 新建账户
func NewCoinsAccount() *DB {
prefix := "mavl-coins-bty-"
prefix := "mavl-coins-" + types.GetCoinSymbol() + "-"
return newAccountDB(prefix)
}
......
......@@ -47,7 +47,7 @@ func GetLocalDBKeyList() [][]byte {
return [][]byte{
blockLastHeight, bodyPerfix, LastSequence, headerPerfix, heightToHeaderPerfix,
hashPerfix, tdPerfix, heightToHashKeyPerfix, seqToHashKey, HashToSeqPerfix,
seqCBPrefix, seqCBLastNumPrefix,
seqCBPrefix, seqCBLastNumPrefix, tempBlockKey, lastTempBlockKey,
}
}
......@@ -156,11 +156,12 @@ func NewBlockStore(db dbm.DB, client queue.Client) *BlockStore {
//如果没有,那么进行下面的步骤
//1. 先把hash 都给改成 TX:hash
//2. 把所有的 Tx:hash 都加一个 8字节的index
//3. 10000个区块 处理一次,并且打印进度
//3. 2000个交易处理一次,并且打印进度
//4. 全部处理完成了,添加quickIndex 的标记
func (bs *BlockStore) initQuickIndex(height int64) {
batch := bs.db.NewBatch(true)
var count int
var maxsize = 100 * 1024 * 1024
var count = 0
for i := int64(0); i <= height; i++ {
blockdetail, err := bs.LoadBlockByHeight(i)
if err != nil {
......@@ -172,17 +173,17 @@ func (bs *BlockStore) initQuickIndex(height int64) {
if err != nil {
panic(err)
}
count++
count += len(txresult)
batch.Set(types.CalcTxKey(hash), txresult)
batch.Set(types.CalcTxShortKey(hash), []byte("1"))
}
if count > 100000 {
if count > maxsize {
storeLog.Info("initQuickIndex", "height", i)
err := batch.Write()
if err != nil {
panic(err)
}
batch = bs.db.NewBatch(true)
batch.Reset()
count = 0
}
}
......@@ -192,6 +193,7 @@ func (bs *BlockStore) initQuickIndex(height int64) {
panic(err)
}
storeLog.Info("initQuickIndex", "height", height)
batch.Reset()
}
bs.saveQuickIndexFlag()
}
......
......@@ -42,13 +42,6 @@ var (
synlog = chainlog.New("submodule", "syn")
)
//ForkInfo blockchain模块fork处理结构体
type ForkInfo struct {
ForkStartHeight int64
ForkEndHeight int64
ForkPid string
}
//PeerInfo blockchain模块需要保存的peerinfo
type PeerInfo struct {
Name string
......@@ -128,6 +121,9 @@ func (chain *BlockChain) SynRoutine() {
//2分钟尝试检测一次最优链,确保本节点在最优链
checkBestChainTicker := time.NewTicker(120 * time.Second)
//节点启动后首先尝试开启快速下载模式
chain.tickerwg.Add(1)
go chain.FastDownLoadBlocks()
for {
select {
case <-chain.quit:
......@@ -135,9 +131,9 @@ func (chain *BlockChain) SynRoutine() {
return
case <-blockSynTicker.C:
//synlog.Info("blockSynTicker")
//SynBlocksFromPeers在task任务中也会go线程调用
//WaitGroup不太好处理,暂时不加入WaitGroup中
go chain.SynBlocksFromPeers()
if !GetDownloadSyncStatus() {
go chain.SynBlocksFromPeers()
}
case <-fetchPeerListTicker.C:
//synlog.Info("blockUpdateTicker")
......@@ -207,15 +203,19 @@ func (chain *BlockChain) FetchBlock(start int64, end int64, pid []string, syncOr
var cb func()
if syncOrfork {
//还有区块需要请求,挂接钩子回调函数
if requestblock.End < chain.forkInfo.ForkEndHeight {
if requestblock.End < chain.downLoadInfo.EndHeight {
cb = func() {
chain.ReqForkBlocks()
chain.ReqDownLoadBlocks()
}
chain.UpdateForkStartHeight(requestblock.End + 1)
} else { // 所有fork block已请求结束,恢复forkinfo为默认值
chain.DefaultForkInfo()
chain.UpdateDownLoadStartHeight(requestblock.End + 1)
//快速下载时需要及时更新bestpeer,防止下载侧链的block
if GetDownloadSyncStatus() {
chain.UpdateDownLoadPids()
}
} else { // 所有DownLoad block已请求结束,恢复DownLoadInfo为默认值
chain.DefaultDownLoadInfo()
}
err = chain.forktask.Start(requestblock.Start, requestblock.End, cb)
err = chain.downLoadTask.Start(requestblock.Start, requestblock.End, cb)
if err != nil {
return err
}
......@@ -225,13 +225,13 @@ func (chain *BlockChain) FetchBlock(start int64, end int64, pid []string, syncOr
chain.SynBlocksFromPeers()
}
}
err = chain.task.Start(requestblock.Start, requestblock.End, cb)
err = chain.syncTask.Start(requestblock.Start, requestblock.End, cb)
if err != nil {
return err
}
}
synlog.Debug("FetchBlock", "Start", requestblock.Start, "End", requestblock.End)
synlog.Info("FetchBlock", "Start", requestblock.Start, "End", requestblock.End)
msg := chain.client.NewMessage("p2p", types.EventFetchBlocks, &requestblock)
Err := chain.client.Send(msg, true)
if Err != nil {
......@@ -426,6 +426,20 @@ func (chain *BlockChain) GetPeers() PeerInfoList {
return peers
}
//GetPeersMap 获取peers的map列表方便查找
func (chain *BlockChain) GetPeersMap() map[string]bool {
peerMaxBlklock.Lock()
defer peerMaxBlklock.Unlock()
peersmap := make(map[string]bool)
if chain.peerList != nil {
for _, peer := range chain.peerList {
peersmap[peer.Name] = true
}
}
return peersmap
}
//IsFaultPeer 判断指定pid是否在故障faultPeerList中
func (chain *BlockChain) IsFaultPeer(pid string) bool {
faultpeerlock.Lock()
......@@ -562,11 +576,10 @@ func (chain *BlockChain) SynBlocksFromPeers() {
} else {
atomic.CompareAndSwapInt32(&chain.isbatchsync, 0, 1)
}
//synlog.Info("SynBlocksFromPeers", "isbatchsync", chain.isbatchsync)
//如果任务正常,那么不重复启动任务
if chain.task.InProgress() {
synlog.Info("chain task InProgress")
if chain.syncTask.InProgress() {
synlog.Info("chain syncTask InProgress")
return
}
//获取peers的最新高度.处理没有收到广播block的情况
......@@ -759,78 +772,15 @@ func (chain *BlockChain) ProcBlockHeaders(headers *types.Headers, pid string) er
peermaxheight := peerinfo.Height
//启动一个线程在后台获取分叉的blcok
if chain.forktask.InProgress() {
synlog.Info("ProcBlockHeaders forktask.InProgress")
if chain.downLoadTask.InProgress() {
synlog.Info("ProcBlockHeaders downLoadTask.InProgress")
return nil
}
go chain.ProcBlockChainFork(ForkHeight, peermaxheight, pid)
return nil
}
//ProcBlockChainFork 处理从peer获取的headers消息
func (chain *BlockChain) ProcBlockChainFork(forkStartHeight int64, forkEndHeight int64, pid string) {
forkinfo := chain.GetForkInfo()
//可能存在上次fork 处理过程中下载区块超时,forktask任务退出,但forkinfo没有恢复成默认值
if forkinfo.ForkStartHeight != -1 || forkinfo.ForkEndHeight != -1 {
synlog.Error("ProcBlockChainFork Fork processing", "pid", forkinfo.ForkPid, "ForkStartHeight", forkinfo.ForkStartHeight, "ForkEndHeight", forkinfo.ForkEndHeight)
}
chain.DefaultForkInfo()
chain.InitForkInfo(forkStartHeight, forkEndHeight, pid)
chain.ReqForkBlocks()
}
//InitForkInfo 开始新的fork处理
func (chain *BlockChain) InitForkInfo(forkStartHeight int64, forkEndHeight int64, pid string) {
chain.forklock.Lock()
defer chain.forklock.Unlock()
chain.forkInfo.ForkStartHeight = forkStartHeight
chain.forkInfo.ForkEndHeight = forkEndHeight
chain.forkInfo.ForkPid = pid
synlog.Debug("InitForkInfo Fork process begin", "ForkStartHeight", forkStartHeight, "ForkEndHeight", forkEndHeight, "pid", pid)
}
//DefaultForkInfo 将forkinfo恢复成默认值
func (chain *BlockChain) DefaultForkInfo() {
chain.forklock.Lock()
defer chain.forklock.Unlock()
chain.forkInfo.ForkStartHeight = -1
chain.forkInfo.ForkEndHeight = -1
chain.forkInfo.ForkPid = ""
synlog.Debug("DefaultForkInfo")
}
//GetForkInfo 获取forkinfo
func (chain *BlockChain) GetForkInfo() *ForkInfo {
chain.forklock.Lock()
defer chain.forklock.Unlock()
return chain.forkInfo
}
//UpdateForkStartHeight 更新fork 请求的起始block高度
func (chain *BlockChain) UpdateForkStartHeight(forkStartHeight int64) {
chain.forklock.Lock()
defer chain.forklock.Unlock()
chain.forkInfo.ForkStartHeight = forkStartHeight
synlog.Debug("UpdateForkStartHeight", "ForkStartHeight", chain.forkInfo.ForkStartHeight, "ForkEndHeight", chain.forkInfo.ForkEndHeight, "pid", chain.forkInfo.ForkPid)
}
//ReqForkBlocks 请求fork处理的blocks
func (chain *BlockChain) ReqForkBlocks() {
forkinfo := chain.GetForkInfo()
if forkinfo.ForkStartHeight != -1 && forkinfo.ForkEndHeight != -1 && forkinfo.ForkPid != "" {
synlog.Info("ReqForkBlocks", "ForkStartHeight", forkinfo.ForkStartHeight, "ForkEndHeight", forkinfo.ForkEndHeight, "pid", forkinfo.ForkPid)
err := chain.FetchBlock(forkinfo.ForkStartHeight, forkinfo.ForkEndHeight, []string{forkinfo.ForkPid}, true)
if err != nil {
synlog.Error("ReqForkBlocks FetchBlock ", "err", err)
}
//在快速下载block阶段不处理fork的处理
if !GetDownloadSyncStatus() {
go chain.ProcDownLoadBlocks(ForkHeight, peermaxheight, []string{pid})
}
return nil
}
//ProcAddBlockHeadersMsg 处理从peer获取的headers消息
......@@ -1019,7 +969,13 @@ func (chain *BlockChain) GetBestChainPids() []string {
bestpeerlock.Lock()
defer bestpeerlock.Unlock()
peersmap := chain.GetPeersMap()
for key, value := range chain.bestChainPeerList {
if !peersmap[value.Peer.Name] {
delete(chain.bestChainPeerList, value.Peer.Name)
synlog.Debug("GetBestChainPids:delete", "peer", value.Peer.Name)
continue
}
if value.IsBestChain {
ok := chain.IsFaultPeer(value.Peer.Name)
if !ok {
......@@ -1027,7 +983,7 @@ func (chain *BlockChain) GetBestChainPids() []string {
}
}
}
synlog.Debug("GetBestChainPids ", "pids", PeerPids)
synlog.Debug("GetBestChainPids", "pids", PeerPids)
return PeerPids
}
......
......@@ -47,9 +47,9 @@ type BlockChain struct {
blockStore *BlockStore
pushseq *pushseq
//cache 缓存block方便快速查询
cfg *types.BlockChain
task *Task
forktask *Task
cfg *types.BlockChain
syncTask *Task
downLoadTask *Task
query *Query
......@@ -98,9 +98,9 @@ type BlockChain struct {
//记录futureblocks
futureBlocks *lru.Cache // future blocks are broadcast later processing
//fork block req
forkInfo *ForkInfo
forklock sync.Mutex
//downLoad block info
downLoadInfo *DownLoadInfo
downLoadlock sync.Mutex
}
//New new
......@@ -119,8 +119,8 @@ func New(cfg *types.BlockChain) *BlockChain {
recvwg: &sync.WaitGroup{},
tickerwg: &sync.WaitGroup{},
task: newTask(300 * time.Second), //考虑到区块交易多时执行耗时,需要延长task任务的超时时间
forktask: newTask(300 * time.Second),
syncTask: newTask(300 * time.Second), //考虑到区块交易多时执行耗时,需要延长task任务的超时时间
downLoadTask: newTask(300 * time.Second),
quit: make(chan struct{}),
synblock: make(chan struct{}, 1),
......@@ -133,7 +133,7 @@ func New(cfg *types.BlockChain) *BlockChain {
faultPeerList: make(map[string]*FaultPeerInfo),
bestChainPeerList: make(map[string]*BestPeerInfo),
futureBlocks: futureBlocks,
forkInfo: &ForkInfo{},
downLoadInfo: &DownLoadInfo{},
}
return blockchain
......@@ -257,8 +257,8 @@ func (chain *BlockChain) InitBlockChain() {
// 定时处理futureblock
go chain.UpdateRoutine()
}
//初始化默认forkinfo
chain.DefaultForkInfo()
//初始化默认DownLoadInfo
chain.DefaultDownLoadInfo()
}
func (chain *BlockChain) getStateHash() []byte {
......
......@@ -121,6 +121,12 @@ func TestBlockChain(t *testing.T) {
testDelBlock(t, blockchain, curBlock)
testIsRecordFaultErr(t)
testGetsynBlkHeight(t, blockchain)
testProcDelChainBlockMsg(t, mock33, blockchain)
testFaultPeer(t, blockchain)
testCheckBlock(t, blockchain)
testWriteBlockToDbTemp(t, blockchain)
testReadBlockToExec(t, blockchain)
}
func testProcAddBlockMsg(t *testing.T, mock33 *testnode.Chain33Mock, blockchain *blockchain.BlockChain) {
......@@ -923,11 +929,11 @@ func testProcBlockChainFork(t *testing.T, blockchain *blockchain.BlockChain) {
chainlog.Info("testProcBlockChainFork begin --------------------")
curheight := blockchain.GetBlockHeight()
blockchain.ProcBlockChainFork(curheight-1, curheight+256, "self")
blockchain.ProcDownLoadBlocks(curheight-1, curheight+256, []string{"self"})
chainlog.Info("testProcBlockChainFork end --------------------")
}
func testAddBlockSeqCB(t *testing.T, blockchain *blockchain.BlockChain) {
func testAddBlockSeqCB(t *testing.T, chain *blockchain.BlockChain) {
chainlog.Info("testAddBlockSeqCB begin ---------------------")
cb := &types.BlockSeqCB{
......@@ -935,11 +941,11 @@ func testAddBlockSeqCB(t *testing.T, blockchain *blockchain.BlockChain) {
URL: "http://192.168.1.107:15760",
Encode: "json",
}
err := blockchain.ProcAddBlockSeqCB(cb)
blockchain.MaxSeqCB = 1
err := chain.ProcAddBlockSeqCB(cb)
require.NoError(t, err)
cbs, err := blockchain.ProcListBlockSeqCB()
cbs, err := chain.ProcListBlockSeqCB()
require.NoError(t, err)
exist := false
for _, temcb := range cbs.Items {
......@@ -950,10 +956,22 @@ func testAddBlockSeqCB(t *testing.T, blockchain *blockchain.BlockChain) {
if !exist {
t.Error("testAddBlockSeqCB listSeqCB fail", "cb", cb, "cbs", cbs)
}
num := blockchain.ProcGetSeqCBLastNum(cb.Name)
num := chain.ProcGetSeqCBLastNum(cb.Name)
if num != -1 {
t.Error("testAddBlockSeqCB getSeqCBLastNum", "num", num, "name", cb.Name)
}
cb2 := &types.BlockSeqCB{
Name: "test1",
URL: "http://192.168.1.107:15760",
Encode: "json",
}
err = chain.ProcAddBlockSeqCB(cb2)
if err != types.ErrTooManySeqCB {
t.Error("testAddBlockSeqCB", "cb", cb2, "err", err)
}
chainlog.Info("testAddBlockSeqCB end -------------------------")
}
func testIsRecordFaultErr(t *testing.T) {
......@@ -962,5 +980,132 @@ func testIsRecordFaultErr(t *testing.T) {
if isok {
t.Error("testIsRecordFaultErr IsRecordFaultErr", "isok", isok)
}
chainlog.Info("testIsRecordFaultErr begin ---------------------")
chainlog.Info("testIsRecordFaultErr end ---------------------")
}
func testProcDelChainBlockMsg(t *testing.T, mock33 *testnode.Chain33Mock, blockchain *blockchain.BlockChain) {
chainlog.Info("testProcDelChainBlockMsg begin --------------------")
curheight := blockchain.GetBlockHeight()
block, err := blockchain.GetBlock(curheight)
require.NoError(t, err)
var parablockDetail types.ParaChainBlockDetail
parablockDetail.Blockdetail = block
parablockDetail.Sequence = curheight
msgGen := mock33.GetClient().NewMessage("blockchain", types.EventDelParaChainBlockDetail, &parablockDetail)
mock33.GetClient().Send(msgGen, true)
mock33.GetClient().Wait(msgGen)
chainlog.Info("testProcDelChainBlockMsg end --------------------")
}
func testGetsynBlkHeight(t *testing.T, chain *blockchain.BlockChain) {
chainlog.Info("testGetsynBlkHeight begin --------------------")
curheight := chain.GetBlockHeight()
chain.UpdatesynBlkHeight(curheight)
height := chain.GetsynBlkHeight()
if height != curheight {
chainlog.Error("testGetsynBlkHeight", "curheight", curheight, "height", height)
}
//get peerinfo
peerinfo := chain.GetPeerInfo("self")
if peerinfo != nil {
chainlog.Error("testGetsynBlkHeight:GetPeerInfo", "peerinfo", peerinfo)
}
maxpeer := chain.GetMaxPeerInfo()
if maxpeer != nil {
chainlog.Error("testGetsynBlkHeight:GetMaxPeerInfo", "maxpeer", maxpeer)
}
chainlog.Info("testGetsynBlkHeight end --------------------")
}
func testFaultPeer(t *testing.T, chain *blockchain.BlockChain) {
chainlog.Info("testFaultPeer begin ---------------------")
curheight := chain.GetBlockHeight()
block, err := chain.GetBlock(curheight)
require.NoError(t, err)
isok := chain.IsFaultPeer("self")
if isok {
t.Error("testFaultPeer:IsFaultPeer")
}
//记录故障peer信息
chain.RecordFaultPeer("self", curheight+1, block.Block.Hash(), types.ErrSign)
var faultnode blockchain.FaultPeerInfo
var peerinfo blockchain.PeerInfo
peerinfo.Name = "self"
faultnode.Peer = &peerinfo
faultnode.FaultHeight = curheight + 1
faultnode.FaultHash = block.Block.Hash()
faultnode.ErrInfo = types.ErrSign
faultnode.ReqFlag = false
chain.AddFaultPeer(&faultnode)
peer := chain.GetFaultPeer("self")
if peer == nil {
t.Error("testFaultPeer:GetFaultPeer is nil")
}
chain.UpdateFaultPeer("self", true)
chain.RemoveFaultPeer("self")
chainlog.Info("testFaultPeer end ---------------------")
}
func testCheckBlock(t *testing.T, chain *blockchain.BlockChain) {
curheight := chain.GetBlockHeight()
//chain.CheckHeightNoIncrease()
chain.FetchBlockHeaders(0, curheight, "self")
header, err := chain.ProcGetLastHeaderMsg()
var blockheader types.Header
if header != nil && err == nil {
blockheader.Version = header.Version
blockheader.ParentHash = header.ParentHash
blockheader.TxHash = header.TxHash
blockheader.StateHash = header.StateHash
blockheader.Height = header.Height
blockheader.BlockTime = header.BlockTime
blockheader.TxCount = header.TxCount
blockheader.Hash = header.Hash
blockheader.Difficulty = header.Difficulty
blockheader.Signature = header.Signature
}
var blockheaders types.Headers
blockheaders.Items = append(blockheaders.Items, &blockheader)
chain.ProcAddBlockHeadersMsg(&blockheaders, "self")
chain.ProcBlockHeaders(&blockheaders, "self")
}
func testReadBlockToExec(t *testing.T, chain *blockchain.BlockChain) {
chainlog.Info("testReadBlockToExec begin ---------------------")
curheight := chain.GetBlockHeight()
chain.ReadBlockToExec(curheight+1, false)
chainlog.Info("testReadBlockToExec end ---------------------")
}
func testWriteBlockToDbTemp(t *testing.T, chain *blockchain.BlockChain) {
chainlog.Info("WriteBlockToDbTemp begin ---------------------")
curheight := chain.GetBlockHeight()
block, err := chain.GetBlock(curheight)
if err != nil {
t.Error("testWriteBlockToDbTemp", "err", err)
}
var rawblock types.Block
rawblock.Version = block.Block.Version
rawblock.ParentHash = block.Block.ParentHash
rawblock.TxHash = block.Block.TxHash
rawblock.StateHash = block.Block.StateHash
rawblock.BlockTime = block.Block.BlockTime
rawblock.Difficulty = block.Block.Difficulty
rawblock.MainHash = block.Block.MainHash
rawblock.MainHeight = block.Block.MainHeight
rawblock.Height = block.Block.Height + 1
err = chain.WriteBlockToDbTemp(&rawblock)
if err != nil {
t.Error("testWriteBlockToDbTemp", "err", err)
}
chainlog.Info("WriteBlockToDbTemp end ---------------------")
}
This diff is collapsed.
......@@ -157,19 +157,30 @@ func (chain *BlockChain) getBlocks(msg *queue.Message) {
}
func (chain *BlockChain) addBlock(msg *queue.Message) {
//var block *types.Block
var reply types.Reply
reply.IsOk = true
blockpid := msg.Data.(*types.BlockPid)
_, err := chain.ProcAddBlockMsg(false, &types.BlockDetail{Block: blockpid.Block}, blockpid.Pid)
if err != nil {
chainlog.Error("ProcAddBlockMsg", "height", blockpid.Block.Height, "err", err.Error())
reply.IsOk = false
reply.Msg = []byte(err.Error())
//chainlog.Error("addBlock", "height", blockpid.Block.Height, "pid", blockpid.Pid)
if GetDownloadSyncStatus() {
//downLoadTask 运行时设置对应的blockdone
if chain.downLoadTask.InProgress() {
chain.downLoadTask.Done(blockpid.Block.GetHeight())
}
err := chain.WriteBlockToDbTemp(blockpid.Block)
if err != nil {
chainlog.Error("WriteBlockToDbTemp", "height", blockpid.Block.Height, "err", err.Error())
reply.IsOk = false
reply.Msg = []byte(err.Error())
}
} else {
//chain.notifySync()
_, err := chain.ProcAddBlockMsg(false, &types.BlockDetail{Block: blockpid.Block}, blockpid.Pid)
if err != nil {
chainlog.Error("ProcAddBlockMsg", "height", blockpid.Block.Height, "err", err.Error())
reply.IsOk = false
reply.Msg = []byte(err.Error())
}
chainlog.Debug("EventAddBlock", "height", blockpid.Block.Height, "pid", blockpid.Pid, "success", "ok")
}
chainlog.Debug("EventAddBlock", "height", blockpid.Block.Height, "pid", blockpid.Pid, "success", "ok")
msg.Reply(chain.client.NewMessage("p2p", types.EventReply, &reply))
}
......
......@@ -389,7 +389,7 @@ func (b *BlockChain) connectBlock(node *blockNode, blockdetail *types.BlockDetai
chainlog.Debug("connectBlock SendAddBlockEvent", "err", err)
}
// 通知此block已经处理完,主要处理孤儿节点时需要设置
b.task.Done(blockdetail.Block.GetHeight())
b.syncTask.Done(blockdetail.Block.GetHeight())
//广播此block到全网络
if node.broadcast {
......
......@@ -240,14 +240,14 @@ func (chain *BlockChain) ProcAddBlockMsg(broadcast bool, blockdetail *types.Bloc
blockdetail = b
}
//非孤儿block或者已经存在的block
if chain.task.InProgress() {
if chain.syncTask.InProgress() {
if (!isorphan && err == nil) || (err == types.ErrBlockExist) {
chain.task.Done(blockdetail.Block.GetHeight())
chain.syncTask.Done(blockdetail.Block.GetHeight())
}
}
//forktask 运行时设置对应的blockdone
if chain.forktask.InProgress() {
chain.forktask.Done(blockdetail.Block.GetHeight())
//downLoadTask 运行时设置对应的blockdone
if chain.downLoadTask.InProgress() {
chain.downLoadTask.Done(blockdetail.Block.GetHeight())
}
//此处只更新广播block的高度
if broadcast {
......
......@@ -300,11 +300,23 @@ function transfer() {
done
${CLI} account balance -a 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -e coins
balance=$(${CLI} account balance -a 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -e coins | jq -r ".balance")
if [ "${balance}" != "10.0000" ]; then
echo "wrong balance=$balance, should not be 10.0000"
exit 1
fi
local times=100
while true; do
balance=$(${CLI} account balance -a 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -e coins | jq -r ".balance")
echo "account balance is ${balance}, expect 10.0000 "
if [ "${balance}" != "10.0000" ]; then
block_wait 2
times=$((times - 1))
if [ $times -le 0 ]; then
echo "account balance transfer failed"
exit 1
fi
else
echo "account balance transfer success"
break
fi
done
}
......
Title="chain33"
TestNet=true
CoinSymbol="bty"
[log]
# 日志级别,支持debug(dbug)/info/warn/error(eror)/crit
......@@ -197,4 +198,4 @@ superManager=[
[health]
listenAddr="localhost:8805"
checkInterval=1
unSyncMaxTimes=2
\ No newline at end of file
unSyncMaxTimes=2
Title="chain33"
TestNet=true
FixTime=false
CoinSymbol="bty"
[log]
# 日志级别,支持debug(dbug)/info/warn/error(eror)/crit
......@@ -239,6 +240,7 @@ minerwhitelist=["*"]
isFree=false
#执行器执行所需最小费用,低于Mempool和Wallet设置的MinFee,在minExecFee = 0 的情况下,isFree = true才会生效
minExecFee=100000
maxExecFee=1000000000
#是否开启stat插件
enableStat=false
#是否开启MVCC插件
......
syntax = "proto3";
package calculator;
// calculator 合约交易行为总类型
message CalculatorAction {
oneof value {
Add add = 1;
Subtract sub = 2;
Multiply mul = 3;
Divide div = 4;
}
int32 ty = 5;
}
message Add {
int32 summand = 1; //被加数
int32 addend = 2; //加数
}
message AddLog {
int32 sum = 1; //和
}
message Subtract {
int32 minuend = 1; //被减数
int32 subtrahend = 2; //减数
}
message SubLog {
int32 remainder = 1; //差
}
message Multiply {
int32 faciend = 1; //被乘数
int32 multiplier = 2; //乘数
}
message MultiplyLog {
int32 product = 1; //积
}
message Divide {
int32 dividend = 1; //被除数
int32 divisor = 2; //除数
}
message DivideLog {
int32 quotient = 1; //商
int32 remain = 2; //余数
}
message ReqQueryCalcCount {
string action = 1;
}
message ReplyQueryCalcCount {
int32 count = 1;
}
service calculator {
rpc QueryCalcCount(ReqQueryCalcCount) returns (ReplyQueryCalcCount) {}
}
This diff is collapsed.
......@@ -5,7 +5,7 @@
### 编译
```
//本地存在chain33代码,该步骤可省略
$ git clone https://github.com/33cn/chain33.git $GOPATH/src/github.com/33cn/chain33
$ go get github.com/33cn/chain33
//编译chain33 tools
$ go build -i -o $GOPATH/bin/chain33-tool github.com/33cn/chain33/cmd/tools
```
......@@ -36,8 +36,6 @@ $ chain33-tool gendapp -n demo -p ./demo.proto
// 指定输出包路径
$ chain33-tool gendapp -n demo -p ./demo.proto -o github.com/33cn/chain33/plugin/dapp/
//生成proto
cd proto && chmod +x ./create_protobuf.sh && make
```
### proto规范
* 定义合约交易行为结构,采用**oneof value**形式,且名称必须为**NameAction**格式,
......@@ -51,6 +49,11 @@ message DemoAction {
int32 ty = 3;
}
```
* package name设为合约名,适配后续生成目录结构
```
package demo;
```
* 定义service,直接以合约名作为名称
```
service demo {
......@@ -61,7 +64,7 @@ service demo {
### 代码
#####目录结构,以demo合约为例
##### 目录结构,以demo合约为例
```
demo
├── cmd //包含官方ci集成相关脚本
......@@ -84,10 +87,18 @@ demo
│   ├── rpc.go
│   └── types.go
└── types //类型模块
└── demo.go
└── demo
└── demo.go
```
##### 生成pb.go文件
```
//进入到上述proto目录执行相关脚本,将会在types目录下生成对应pb.go文件
$ cd proto && chmod +x ./create_protobuf.sh && make
```
##### 后续开发
在生成代码基础上,需要实现交易创建,执行,及所需rpc服务,初次开发可以参考官方的echo合约
> github.com/33cn/plugin/plugin/dapp/echo
在生成代码基础上,需要实现交易创建,执行,及所需rpc服务<br/>
初次开发可以参考官方简单计算器合约
[开发步骤](https://github.com/33cn/chain33/blob/master/cmd/tools/doc/gencalculator.md)
......@@ -14,7 +14,8 @@ type ICodeFile interface {
GetCodeType() string
GetDirName() string
GetFiles() map[string]string //key:filename, val:file content
GetReplaceTags() []string
GetDirReplaceTags() []string
GetFileReplaceTags() []string
}
//RegisterCodeFile regeister code file
......@@ -47,8 +48,14 @@ func (CodeFile) GetFiles() map[string]string {
return nil
}
//GetReplaceTags get replace tags
func (CodeFile) GetReplaceTags() []string {
//GetDirReplaceTags get directory replace tags
func (CodeFile) GetDirReplaceTags() []string {
return nil
}
//GetFileReplaceTags get file replace tags
func (CodeFile) GetFileReplaceTags() []string {
return nil
}
......@@ -30,7 +30,7 @@ func (c commandsCodeFile) GetFiles() map[string]string {
}
}
func (c commandsCodeFile) GetReplaceTags() []string {
func (c commandsCodeFile) GetFileReplaceTags() []string {
return []string{types.TagExecName}
}
......@@ -39,7 +39,9 @@ var (
commandsFileContent = `/*Package commands implement dapp client commands*/
package commands
import "github.com/spf13/cobra"
import (
"github.com/spf13/cobra"
)
/*
* 实现合约对应客户端
......
......@@ -26,7 +26,7 @@ func (execCode) GetFiles() map[string]string {
}
}
func (execCode) GetReplaceTags() []string {
func (execCode) GetFileReplaceTags() []string {
return []string{types.TagExecName, types.TagImportPath, types.TagClassName, types.TagExecFileContent}
}
......@@ -42,7 +42,7 @@ func (execLocalCode) GetFiles() map[string]string {
}
}
func (execLocalCode) GetReplaceTags() []string {
func (execLocalCode) GetFileReplaceTags() []string {
return []string{types.TagExecName, types.TagImportPath, types.TagExecLocalFileContent}
}
......@@ -58,7 +58,7 @@ func (execDelLocalCode) GetFiles() map[string]string {
}
}
func (execDelLocalCode) GetReplaceTags() []string {
func (execDelLocalCode) GetFileReplaceTags() []string {
return []string{types.TagExecName, types.TagImportPath, types.TagExecDelLocalFileContent}
}
......@@ -68,7 +68,7 @@ var (
execContent = `package executor
import (
ptypes "${IMPORTPATH}/${EXECNAME}/types"
ptypes "${IMPORTPATH}/${EXECNAME}/types/${EXECNAME}"
"github.com/33cn/chain33/types"
)
......@@ -83,7 +83,7 @@ ${EXECFILECONTENT}`
execLocalContent = `package executor
import (
ptypes "${IMPORTPATH}/${EXECNAME}/types"
ptypes "${IMPORTPATH}/${EXECNAME}/types/${EXECNAME}"
"github.com/33cn/chain33/types"
)
......@@ -98,7 +98,7 @@ ${EXECLOCALFILECONTENT}`
execDelContent = `package executor
import (
ptypes "${IMPORTPATH}/${EXECNAME}/types"
ptypes "${IMPORTPATH}/${EXECNAME}/types/${EXECNAME}"
"github.com/33cn/chain33/types"
)
......
......@@ -31,7 +31,7 @@ func (c executorCodeFile) GetFiles() map[string]string {
}
}
func (c executorCodeFile) GetReplaceTags() []string {
func (c executorCodeFile) GetFileReplaceTags() []string {
return []string{types.TagExecName, types.TagImportPath, types.TagClassName}
}
......@@ -42,7 +42,7 @@ var (
import (
log "github.com/33cn/chain33/common/log/log15"
ptypes "${IMPORTPATH}/${EXECNAME}/types"
ptypes "${IMPORTPATH}/${EXECNAME}/types/${EXECNAME}"
drivers "github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/types"
)
......@@ -55,7 +55,7 @@ import (
var (
//日志
elog = log.New("module", "execs.${EXECNAME}")
elog = log.New("module", "${EXECNAME}.executor")
)
var driverName = ptypes.${CLASSNAME}X
......
......@@ -25,7 +25,7 @@ func (c pluginCodeFile) GetFiles() map[string]string {
}
}
func (c pluginCodeFile) GetReplaceTags() []string {
func (c pluginCodeFile) GetFileReplaceTags() []string {
return []string{types.TagExecName, types.TagImportPath, types.TagClassName}
}
......@@ -37,7 +37,7 @@ package ${EXECNAME}
import (
"${IMPORTPATH}/${EXECNAME}/commands"
"${IMPORTPATH}/${EXECNAME}/types"
ptypes "${IMPORTPATH}/${EXECNAME}/types/${EXECNAME}"
"${IMPORTPATH}/${EXECNAME}/executor"
"${IMPORTPATH}/${EXECNAME}/rpc"
"github.com/33cn/chain33/pluginmgr"
......@@ -49,7 +49,7 @@ import (
func init() {
pluginmgr.Register(&pluginmgr.PluginBase{
Name: types.${CLASSNAME}X,
Name: ptypes.${CLASSNAME}X,
ExecName: executor.GetName(),
Exec: executor.Init,
Cmd: commands.Cmd,
......
......@@ -32,6 +32,10 @@ func (protoBase) GetFiles() map[string]string {
}
}
func (protoBase) GetFileReplaceTags() []string {
return []string{types.TagExecName}
}
type protoFile struct {
protoBase
}
......@@ -42,15 +46,15 @@ func (protoFile) GetFiles() map[string]string {
}
}
func (protoFile) GetReplaceTags() []string {
func (protoFile) GetFileReplaceTags() []string {
return []string{types.TagProtoFileContent, types.TagProtoFileAppend, types.TagExecName}
}
var (
protoShellName = "create_protobuf.sh"
protoShellContent = `#!/bin/sh
# proto生成命令,将pb.go文件生成到types目录下
protoc --go_out=plugins=grpc:../types ./*.proto
# proto生成命令,将pb.go文件生成到types/${EXECNAME}目录下
protoc --go_out=plugins=grpc:../types/${EXECNAME} ./*.proto
`
makeName = "Makefile"
......
......@@ -31,7 +31,7 @@ func (c rpcCodeFile) GetFiles() map[string]string {
}
}
func (c rpcCodeFile) GetReplaceTags() []string {
func (c rpcCodeFile) GetFileReplaceTags() []string {
return []string{types.TagExecName, types.TagImportPath, types.TagClassName}
}
......@@ -53,7 +53,7 @@ var (
typesContent = `package rpc
import (
ptypes "${IMPORTPATH}/${EXECNAME}/types"
ptypes "${IMPORTPATH}/${EXECNAME}/types/${EXECNAME}"
rpctypes "github.com/33cn/chain33/rpc/types"
)
......
......@@ -5,6 +5,8 @@
package types
import (
"os"
"github.com/33cn/chain33/cmd/tools/gencode/base"
"github.com/33cn/chain33/cmd/tools/types"
)
......@@ -20,7 +22,7 @@ type typesCode struct {
func (c typesCode) GetDirName() string {
return "types"
return "types" + string(os.PathSeparator) + "${EXECNAME}"
}
func (c typesCode) GetFiles() map[string]string {
......@@ -30,7 +32,11 @@ func (c typesCode) GetFiles() map[string]string {
}
}
func (c typesCode) GetReplaceTags() []string {
func (c typesCode) GetDirReplaceTags() []string {
return []string{types.TagExecName}
}
func (c typesCode) GetFileReplaceTags() []string {
return []string{types.TagExecName, types.TagClassName,
types.TagActionIDText, types.TagTyLogActionType,
......@@ -39,11 +45,11 @@ func (c typesCode) GetReplaceTags() []string {
var (
typesName = "${EXECNAME}.go"
typesContent = `package types
typesContent = `package ${EXECNAME}
import (
"encoding/json"
log "github.com/33cn/chain33/common/log/log15"
"github.com/33cn/chain33/types"
)
......@@ -54,7 +60,7 @@ import (
*/
// action类型id
// action类型id和name,这些常量可以自定义修改
${ACTIONIDTEXT}
// log类型id值
......@@ -63,15 +69,18 @@ ${TYLOGACTIONTYPE}
var (
//${CLASSNAME}X 执行器名称定义
${CLASSNAME}X = "${EXECNAME}"
//定义action的name和id
//定义actionMap
actionMap = ${TYPEMAPTEXT}
//定义log的id和具体log类型及名称,填入具体自定义log类型
logMap = ${LOGMAPTEXT}
tlog = log.New("module", "${EXECNAME}.types")
)
func init() {
types.AllowUserExec = append(types.AllowUserExec, []byte(${CLASSNAME}X))
types.RegistorExecutor(${CLASSNAME}X, newType())
//注册合约启用高度
types.RegisterDappFork(${CLASSNAME}X, "Enable", 0)
}
type ${EXECNAME}Type struct {
......@@ -102,7 +111,6 @@ func (t *${EXECNAME}Type) GetLogMap() map[int64]*types.LogInfo {
// CreateTx 重载基类接口,实现本合约交易创建,供框架调用
func (t *${EXECNAME}Type) CreateTx(action string, message json.RawMessage) (*types.Transaction, error) {
var tx *types.Transaction
// pseudo code
//if action == someAction
//return new tx
return tx, types.ErrNotSupport
......
......@@ -101,10 +101,18 @@ func (c *GenDappCodeTask) genDappCode() error {
for _, code := range codeTypes {
dirPath := filepath.Join(c.DappDir, code.GetDirName())
_ = os.Mkdir(dirPath, os.ModePerm)
dirName := code.GetDirName()
for _, tag := range code.GetDirReplaceTags() {
dirName = strings.Replace(dirName, tag, c.replacePairs[tag], -1)
}
dirPath := filepath.Join(c.DappDir, dirName)
err := os.MkdirAll(dirPath, os.ModePerm)
if err != nil {
mlog.Error("MakeCodeDir", "Err", err.Error(), "DirPath", dirPath)
return err
}
files := code.GetFiles()
tags := code.GetReplaceTags()
tags := code.GetFileReplaceTags()
for name, content := range files {
......@@ -113,7 +121,7 @@ func (c *GenDappCodeTask) genDappCode() error {
content = strings.Replace(content, tag, c.replacePairs[tag], -1)
}
_, err := util.WriteStringToFile(filepath.Join(dirPath, name), content)
_, err = util.WriteStringToFile(filepath.Join(dirPath, name), content)
if err != nil {
mlog.Error("GenNewCodeFile", "Err", err.Error(), "CodeFile", filepath.Join(dirPath, name))
......
......@@ -60,8 +60,9 @@ func readDappActionFromProto(protoContent, actionName string) ([]*actionInfoItem
func formatExecContent(infos []*actionInfoItem, dappName string) string {
fnFmtStr := `func (c *%s) Exec_%s(payload *ptypes.%s, tx *types.Transaction, index int) (*types.Receipt, error) {
var receipt *types.Receipt
//implement code
return &types.Receipt{}, nil
return receipt, nil
}
`
......@@ -76,8 +77,9 @@ func formatExecContent(infos []*actionInfoItem, dappName string) string {
func formatExecLocalContent(infos []*actionInfoItem, dappName string) string {
fnFmtStr := `func (c *%s) ExecLocal_%s(payload *ptypes.%s, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
var dbSet *types.LocalDBSet
//implement code
return &types.LocalDBSet{}, nil
return dbSet, nil
}
`
......@@ -92,8 +94,9 @@ func formatExecLocalContent(infos []*actionInfoItem, dappName string) string {
func formatExecDelLocalContent(infos []*actionInfoItem, dappName string) string {
fnFmtStr := `func (c *%s) ExecDelLocal_%s(payload *ptypes.%s, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
var dbSet *types.LocalDBSet
//implement code
return &types.LocalDBSet{}, nil
return dbSet, nil
}
`
......@@ -107,9 +110,9 @@ func formatExecDelLocalContent(infos []*actionInfoItem, dappName string) string
// 组成规则是 TyLog+ActionName + ActionMemberName
func buildActionLogTypeText(infos []*actionInfoItem, className string) (text string) {
items := fmt.Sprintf("TyLog%sUnknown = iota\n", className)
items := fmt.Sprintf("TyUnknownLog = iota + 100\n")
for _, info := range infos {
items += fmt.Sprintf("TyLog%s%s\n", className, info.memberName)
items += fmt.Sprintf("Ty%sLog\n", info.memberName)
}
text = fmt.Sprintf("const (\n%s)\n", items)
return
......@@ -117,10 +120,16 @@ func buildActionLogTypeText(infos []*actionInfoItem, className string) (text str
// 组成规则是 ActionName + ActionMemberName
func buildActionIDText(infos []*actionInfoItem, className string) (text string) {
var items string
for index, info := range infos {
items += fmt.Sprintf("%sAction%s = %d\n", className, info.memberName, index)
items := fmt.Sprintf("TyUnknowAction = iota + 100\n")
for _, info := range infos {
items += fmt.Sprintf("Ty%sAction\n", info.memberName)
}
items += "\n"
for _, info := range infos {
items += fmt.Sprintf("Name%sAction = \"%s\"\n", info.memberName, info.memberName)
}
text = fmt.Sprintf("const (\n%s)\n", items)
return
}
......@@ -129,7 +138,7 @@ func buildActionIDText(infos []*actionInfoItem, className string) (text string)
func buildTypeMapText(infos []*actionInfoItem, className string) (text string) {
var items string
for _, info := range infos {
items += fmt.Sprintf("\"%s\": %sAction%s,\n", info.memberName, className, info.memberName)
items += fmt.Sprintf("Name%sAction: Ty%sAction,\n", info.memberName, info.memberName)
}
text = fmt.Sprintf("map[string]int32{\n%s}", items)
return
......@@ -137,6 +146,6 @@ func buildTypeMapText(infos []*actionInfoItem, className string) (text string) {
// 返回 map[string]*types.LogInfo
func buildLogMapText() (text string) {
text = fmt.Sprintf("map[int64]*types.LogInfo{\n\t//pseudo code\n\t//LogID: {Ty: refelct.TypeOf(LogStruct), Name: LogName},\n}")
text = fmt.Sprintf("map[int64]*types.LogInfo{\n\t//LogID: {Ty: reflect.TypeOf(LogStruct), Name: LogName},\n}")
return
}
......@@ -203,7 +203,7 @@ func (e *executor) Exec(tx *types.Transaction, index int) (*types.Receipt, error
if err := drivers.CheckAddress(tx.GetRealToAddr(), e.height); err != nil {
return nil, err
}
if e.localDB != nil {
if e.localDB != nil && types.IsFork(e.height, "ForkLocalDBAccess") {
e.localDB.(*LocalDB).DisableWrite()
if exec.ExecutorOrder() != drivers.ExecLocalSameTime {
e.localDB.(*LocalDB).DisableRead()
......
......@@ -10,7 +10,6 @@ import (
"strings"
"sync"
"github.com/33cn/chain33/account"
"github.com/33cn/chain33/client/api"
dbm "github.com/33cn/chain33/common/db"
clog "github.com/33cn/chain33/common/log"
......@@ -26,7 +25,7 @@ import (
)
var elog = log.New("module", "execs")
var coinsAccount = account.NewCoinsAccount()
var coinsAccount *dbm.DB
// SetLogLevel set log level
func SetLogLevel(level string) {
......
......@@ -1184,3 +1184,12 @@ func fmtAccount(balances []*types.Account) []*rpctypes.Account {
}
return accounts
}
// GetCoinSymbol get coin symbol
func (c *Chain33) GetCoinSymbol(in types.ReqNil, result *interface{}) error {
symbol := types.GetCoinSymbol()
resp := types.ReplyString{Data: symbol}
log.Warn("GetCoinSymbol", "Symbol", symbol)
*result = &resp
return nil
}
......@@ -140,7 +140,7 @@ func (c *CoinsType) GetAssets(tx *types.Transaction) ([]*types.Asset, error) {
return nil, err
}
if assetlist[0].Symbol == "" {
assetlist[0].Symbol = types.BTY
assetlist[0].Symbol = types.GetCoinSymbol()
}
return assetlist, nil
}
......@@ -22,6 +22,7 @@ type Config struct {
Pprof *Pprof `protobuf:"bytes,14,opt,name=pprof" json:"pprof,omitempty"`
Fork *ForkList `protobuf:"bytes,15,opt,name=fork" json:"fork,omitempty"`
Health *HealthCheck `protobuf:"bytes,16,opt,name=health" json:"health,omitempty"`
CoinSymbol string `protobuf:"bytes,16,opt,name=coinSymbol" json:"coinSymbol,omitempty"`
}
// ForkList fork列表配置
......
......@@ -28,6 +28,7 @@ var (
titles = map[string]bool{}
chainConfig = make(map[string]interface{})
mver = make(map[string]*mversion)
coinSymbol = "bty"
)
// coin conversation
......@@ -247,6 +248,7 @@ func Init(t string, cfg *Config) {
}
titles[t] = true
title = t
if cfg != nil {
if isLocal() {
setTestNet(true)
......@@ -264,6 +266,12 @@ func Init(t string, cfg *Config) {
if cfg.Exec.MaxExecFee > 0 {
setChainConfig("MaxFee", cfg.Exec.MaxExecFee)
}
if cfg.CoinSymbol != "" {
if strings.Contains(cfg.CoinSymbol, "-") {
panic("config CoinSymbol must without '-'")
}
coinSymbol = cfg.CoinSymbol
}
}
//local 只用于单元测试
if isLocal() {
......@@ -301,6 +309,14 @@ func GetTitle() string {
return s
}
// GetCoinSymbol 获取 coin symbol
func GetCoinSymbol() string {
mu.Lock()
s := coinSymbol
mu.Unlock()
return s
}
func isLocal() bool {
return title == "local"
}
......
......@@ -100,6 +100,7 @@ driver="leveldb"
[mempool]
poolCacheSize=102400
minTxFee=100000
maxTxFee=1000000000
[consensus]
name="ticket"
......@@ -186,6 +187,7 @@ signType="secp256k1"
[exec]
isFree=false
minExecFee=100000
maxExecFee=1000000000
[exec.sub.token]
#配置一个空值,防止配置文件被覆盖
......@@ -219,6 +221,7 @@ ForkTxHeight= -1
ForkTxGroupPara= -1
ForkChainParamV2= -1
ForkBlockCheck=1725000
ForkLocalDBAccess=1
[fork.sub.coins]
Enable=0
......
......@@ -210,8 +210,9 @@ func SetTestNetFork() {
systemFork.SetFork("chain33", "ForkTxGroupPara", 806578)
systemFork.SetFork("chain33", "ForkCheckBlockTime", 1200000)
systemFork.SetFork("chain33", "ForkMultiSignAddress", 1298600)
systemFork.SetFork("chain33", "ForkStateDBSet", MaxHeight)
systemFork.SetFork("chain33", "ForkStateDBSet", 1572391)
systemFork.SetFork("chain33", "ForkBlockCheck", 1560000)
systemFork.SetFork("chain33", "ForkLocalDBAccess", 1572391)
}
func setLocalFork() {
......
......@@ -173,6 +173,7 @@ ForkTxGroupPara= -1
ForkCheckBlockTime=1200000
ForkMultiSignAddress=1298600
ForkBlockCheck=1725000
ForkLocalDBAccess=1
[fork.sub.coins]
Enable=0
......
......@@ -189,6 +189,7 @@ ForkTxGroupPara= -1
ForkCheckBlockTime=1200000
ForkMultiSignAddress=1298600
ForkBlockCheck=1
ForkLocalDBAccess=0
[fork.sub.coins]
Enable=0
......
......@@ -105,7 +105,7 @@ func (s *HealthCheckServer) getHealth(sync bool) (bool, error) {
return false, err
}
log.Info("healthCheck tick", "peers", len(peerList.Peers), "isCaughtUp", reply.IsOk,
log.Debug("healthCheck tick", "peers", len(peerList.Peers), "isCaughtUp", reply.IsOk,
"health", len(peerList.Peers) > 1 && reply.IsOk, "listen", sync)
return len(peerList.Peers) > 1 && reply.IsOk, nil
......
......@@ -20,8 +20,8 @@ func TestStart(t *testing.T) {
health := NewHealthCheckServer(q.Client())
api := new(mocks.QueueProtocolAPI)
reply := &types.Reply{IsOk: true}
api.On("IsSync").Return(reply, nil)
api.On("IsSync").Return(&types.Reply{IsOk: true}, nil).Times(2)
api.On("IsSync").Return(&types.Reply{IsOk: false}, nil)
peer1 := &types.Peer{Addr: "addr1"}
peer2 := &types.Peer{Addr: "addr2"}
peers := &types.PeerList{Peers: []*types.Peer{peer1, peer2}}
......@@ -31,12 +31,11 @@ func TestStart(t *testing.T) {
cfg, _ := types.InitCfg("../cmd/chain33/chain33.test.toml")
health.Start(cfg.Health)
time.Sleep(time.Second * 3)
api.On("IsSync").Return(&types.Reply{IsOk: false}, nil)
health.Start(cfg.Health)
time.Sleep(time.Second * 3)
time.Sleep(time.Second * 6)
health.Close()
time.Sleep(time.Second * 1)
}
func TestGetHealth(t *testing.T) {
......
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