Commit 5e8dbeec authored by sanghg's avatar sanghg Committed by vipwzw

#51

调整保存Ticket列表的容器结构,由slice修改为map,修复了随机访问时可能出现的崩溃问题,提高了搜索效率。
parent 08854e25
...@@ -39,8 +39,8 @@ func init() { ...@@ -39,8 +39,8 @@ func init() {
// Client export ticket client struct // Client export ticket client struct
type Client struct { type Client struct {
*drivers.BaseClient *drivers.BaseClient
//ticket list for miner //ticket map for miner
tlist *ty.ReplyTicketList ticketsMap map[string]*ty.Ticket
privmap map[string]crypto.PrivKey privmap map[string]crypto.PrivKey
ticketmu sync.Mutex ticketmu sync.Mutex
done chan struct{} done chan struct{}
...@@ -68,7 +68,13 @@ func New(cfg *types.Consensus, sub []byte) queue.Module { ...@@ -68,7 +68,13 @@ func New(cfg *types.Consensus, sub []byte) queue.Module {
if subcfg.GenesisBlockTime > 0 { if subcfg.GenesisBlockTime > 0 {
cfg.GenesisBlockTime = subcfg.GenesisBlockTime cfg.GenesisBlockTime = subcfg.GenesisBlockTime
} }
t := &Client{c, &ty.ReplyTicketList{}, nil, sync.Mutex{}, make(chan struct{}), &subcfg} t := &Client{
BaseClient: c,
ticketsMap: make(map[string]*ty.Ticket),
privmap: nil,
ticketmu: sync.Mutex{},
done: make(chan struct{}),
subcfg: &subcfg}
c.SetChild(t) c.SetChild(t)
go t.flushTicketBackend() go t.flushTicketBackend()
return t return t
...@@ -188,16 +194,17 @@ func (client *Client) getTickets() ([]*ty.Ticket, []crypto.PrivKey, error) { ...@@ -188,16 +194,17 @@ func (client *Client) getTickets() ([]*ty.Ticket, []crypto.PrivKey, error) {
func (client *Client) getTicketCount() int64 { func (client *Client) getTicketCount() int64 {
client.ticketmu.Lock() client.ticketmu.Lock()
defer client.ticketmu.Unlock() defer client.ticketmu.Unlock()
if client.tlist == nil { return int64(len(client.ticketsMap))
return 0
}
return int64(len(client.tlist.Tickets))
} }
func (client *Client) setTicket(tlist *ty.ReplyTicketList, privmap map[string]crypto.PrivKey) { func (client *Client) setTicket(tlist *ty.ReplyTicketList, privmap map[string]crypto.PrivKey) {
client.ticketmu.Lock() client.ticketmu.Lock()
defer client.ticketmu.Unlock() defer client.ticketmu.Unlock()
client.tlist = tlist client.ticketsMap = make(map[string]*ty.Ticket)
for _, ticket := range tlist.Tickets {
client.ticketsMap[ticket.GetTicketId()] = ticket
}
//client.tlist = tlist
client.privmap = privmap client.privmap = privmap
tlog.Debug("setTicket", "n", len(tlist.GetTickets())) tlog.Debug("setTicket", "n", len(tlist.GetTickets()))
} }
...@@ -464,27 +471,32 @@ func printBInt(data *big.Int) string { ...@@ -464,27 +471,32 @@ func printBInt(data *big.Int) string {
return strings.Repeat("0", 64-len(txt)) + txt return strings.Repeat("0", 64-len(txt)) + txt
} }
func (client *Client) searchTargetTicket(parent, block *types.Block) (*ty.Ticket, crypto.PrivKey, *big.Int, []byte, int, error) { func (client *Client) searchTargetTicket(parent, block *types.Block) (*ty.Ticket, crypto.PrivKey, *big.Int, []byte, string, error) {
bits := parent.Difficulty bits := parent.Difficulty
diff, modify, err := client.getNextTarget(parent, bits) diff, modify, err := client.getNextTarget(parent, bits)
if err != nil { if err != nil {
return nil, nil, nil, nil, 0, err return nil, nil, nil, nil, "", err
} }
client.ticketmu.Lock() client.ticketmu.Lock()
defer client.ticketmu.Unlock() defer client.ticketmu.Unlock()
for i := 0; i < len(client.tlist.Tickets); i++ { for ticketID, ticket := range client.ticketsMap {
ticket := client.tlist.Tickets[i]
if ticket == nil { if ticket == nil {
tlog.Warn("Client searchTargetTicket ticket is nil", "ticketID", ticketID)
continue continue
} }
//已经到成熟 //已经到成熟
if !ticket.IsGenesis && block.BlockTime-ticket.CreateTime <= types.GetP(block.Height).TicketFrozenTime { if !ticket.GetIsGenesis() && (block.BlockTime-ticket.GetCreateTime() <= types.GetP(block.Height).TicketFrozenTime) {
continue continue
} }
//find priv key // 查找私钥
priv := client.privmap[ticket.MinerAddress] priv, ok := client.privmap[ticket.MinerAddress]
privHash, err := genPrivHash(priv, ticket.TicketId) if !ok {
tlog.Error("Client searchTargetTicket can't find private key", "MinerAddress", ticket.MinerAddress)
continue
}
privHash, err := genPrivHash(priv, ticketID)
if err != nil { if err != nil {
tlog.Error("Client searchTargetTicket genPrivHash ", "error", err)
continue continue
} }
currentdiff := client.getCurrentTarget(block.BlockTime, ticket.TicketId, modify, privHash) currentdiff := client.getCurrentTarget(block.BlockTime, ticket.TicketId, modify, privHash)
...@@ -493,36 +505,26 @@ func (client *Client) searchTargetTicket(parent, block *types.Block) (*ty.Ticket ...@@ -493,36 +505,26 @@ func (client *Client) searchTargetTicket(parent, block *types.Block) (*ty.Ticket
} }
tlog.Info("currentdiff", "hex", printBInt(currentdiff)) tlog.Info("currentdiff", "hex", printBInt(currentdiff))
tlog.Info("FindBlock", "height------->", block.Height, "ntx", len(block.Txs)) tlog.Info("FindBlock", "height------->", block.Height, "ntx", len(block.Txs))
return ticket, priv, diff, modify, i, nil return ticket, priv, diff, modify, ticketID, nil
} }
return nil, nil, nil, nil, 0, nil return nil, nil, nil, nil, "", nil
} }
func (client *Client) delTicket(ticket *ty.Ticket, index int) { func (client *Client) delTicket(ticketID string) {
client.ticketmu.Lock() client.ticketmu.Lock()
defer client.ticketmu.Unlock() defer client.ticketmu.Unlock()
//1. 结构体没有被重新调整过 if client.ticketsMap == nil || len(ticketID) == 0 {
oldticket := client.tlist.Tickets[index]
if oldticket.TicketId == ticket.TicketId {
client.tlist.Tickets[index] = nil
}
//2. 全表search
for i := 0; i < len(client.tlist.Tickets); i++ {
oldticket = client.tlist.Tickets[i]
if oldticket == nil {
continue
}
if oldticket.TicketId == ticket.TicketId {
client.tlist.Tickets[i] = nil
return return
} }
if _, ok := client.ticketsMap[ticketID]; ok {
delete(client.ticketsMap, ticketID)
} }
} }
// Miner ticket miner function // Miner ticket miner function
func (client *Client) Miner(parent, block *types.Block) bool { func (client *Client) Miner(parent, block *types.Block) bool {
//add miner address //add miner address
ticket, priv, diff, modify, index, err := client.searchTargetTicket(parent, block) ticket, priv, diff, modify, ticketID, err := client.searchTargetTicket(parent, block)
if err != nil { if err != nil {
tlog.Error("Miner", "err", err) tlog.Error("Miner", "err", err)
newblock, err := client.RequestLastBlock() newblock, err := client.RequestLastBlock()
...@@ -543,7 +545,7 @@ func (client *Client) Miner(parent, block *types.Block) bool { ...@@ -543,7 +545,7 @@ func (client *Client) Miner(parent, block *types.Block) bool {
if err != nil { if err != nil {
return false return false
} }
client.delTicket(ticket, index) client.delTicket(ticketID)
return true return true
} }
......
...@@ -7,6 +7,8 @@ package ticket ...@@ -7,6 +7,8 @@ package ticket
import ( import (
"testing" "testing"
"github.com/33cn/plugin/plugin/dapp/ticket/types"
_ "github.com/33cn/chain33/system" _ "github.com/33cn/chain33/system"
"github.com/33cn/chain33/util/testnode" "github.com/33cn/chain33/util/testnode"
_ "github.com/33cn/plugin/plugin/dapp/init" _ "github.com/33cn/plugin/plugin/dapp/init"
...@@ -23,3 +25,20 @@ func TestTicket(t *testing.T) { ...@@ -23,3 +25,20 @@ func TestTicket(t *testing.T) {
err := mock33.WaitHeight(100) err := mock33.WaitHeight(100)
assert.Nil(t, err) assert.Nil(t, err)
} }
func TestTicketMap(t *testing.T) {
c := Client{}
ticketList := &types.ReplyTicketList{}
ticketList.Tickets = []*types.Ticket{
{TicketId: "1111"},
{TicketId: "2222"},
{TicketId: "3333"},
{TicketId: "4444"},
}
assert.Equal(t, c.getTicketCount(), int64(0))
c.setTicket(ticketList, nil)
assert.Equal(t, c.getTicketCount(), int64(4))
c.delTicket("3333")
assert.Equal(t, c.getTicketCount(), int64(3))
}
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