github.com/turingchain2020/turingchain@v1.1.21/cmd/miner_accounts/accounts/block.go (about) 1 // Copyright Turing Corp. 2018 All Rights Reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package accounts 实现了挖矿监控账户相关的功能 6 package accounts 7 8 import ( 9 "fmt" 10 "os" 11 "time" 12 13 "github.com/turingchain2020/turingchain/rpc/jsonclient" 14 rpctypes "github.com/turingchain2020/turingchain/rpc/types" 15 "github.com/turingchain2020/turingchain/types" 16 ) 17 18 // ts/height -> blockHeader 19 type turingchain struct { 20 lastHeader *rpctypes.Header 21 // height -> ts -> header 22 Headers map[int64]*rpctypes.Header 23 Height2Ts map[int64]int64 24 // new only cache ticket for miner 25 accountCache map[int64]*types.Accounts 26 Host string 27 } 28 29 func (b turingchain) findBlock(ts int64) (int64, *rpctypes.Header) { 30 log.Info("show", "utc", ts, "lastBlockTime", b.lastHeader.BlockTime) 31 if ts > b.lastHeader.BlockTime { 32 ts = b.lastHeader.BlockTime 33 return ts, b.lastHeader 34 } 35 // 到底怎么样才能快速根据时间找到block 36 // 1. 一般情况下, 几秒内会有块, 所以直接根据 ts , 进行前后搜索 37 for delta := int64(1); delta < int64(100); delta++ { 38 39 if _, ok := b.Headers[ts-delta]; ok { 40 log.Info("show", "utc", ts, "find", b.Headers[ts-delta]) 41 return ts - delta, b.Headers[ts-delta] 42 } 43 } 44 45 return 0, nil 46 } 47 48 func (b turingchain) getBalance(addrs []string, exec string, height int64) (*rpctypes.Header, []*rpctypes.Account, error) { 49 rpcCli, err := jsonclient.NewJSONClient(b.Host) 50 if err != nil { 51 fmt.Fprintln(os.Stderr, err) 52 return nil, nil, err 53 } 54 hs, err := getHeaders(rpcCli, height, height) 55 if err != nil { 56 fmt.Fprintln(os.Stderr, err) 57 return nil, nil, err 58 } 59 60 acc, err := getBalanceAt(rpcCli, addrs, exec, hs.Items[0].StateHash) 61 return hs.Items[0], acc, err 62 } 63 64 func (b turingchain) addBlock(h *rpctypes.Header) error { 65 b.Headers[h.BlockTime] = h 66 b.Height2Ts[h.Height] = h.BlockTime 67 if h.Height > b.lastHeader.Height { 68 cache.lastHeader = h 69 } 70 71 return nil 72 } 73 74 var cache = turingchain{ 75 lastHeader: &rpctypes.Header{Height: 0}, 76 Headers: map[int64]*rpctypes.Header{}, 77 Height2Ts: map[int64]int64{}, 78 accountCache: map[int64]*types.Accounts{}, 79 } 80 81 func getLastHeader(cli *jsonclient.JSONClient) (*rpctypes.Header, error) { 82 method := "Turingchain.GetLastHeader" 83 var res rpctypes.Header 84 err := cli.Call(method, nil, &res) 85 return &res, err 86 } 87 88 func getHeaders(cli *jsonclient.JSONClient, start, end int64) (*rpctypes.Headers, error) { 89 method := "Turingchain.GetHeaders" 90 params := &types.ReqBlocks{Start: start, End: end, IsDetail: false} 91 var res rpctypes.Headers 92 err := cli.Call(method, params, &res) 93 return &res, err 94 } 95 96 func getBalanceAt(cli *jsonclient.JSONClient, addrs []string, exec, stateHash string) ([]*rpctypes.Account, error) { 97 method := "Turingchain.GetBalance" 98 params := &types.ReqBalance{Addresses: addrs, Execer: exec, StateHash: stateHash} 99 var res []*rpctypes.Account 100 err := cli.Call(method, params, &res) 101 return res, err 102 } 103 104 func syncHeaders(host string) { 105 rpcCli, err := jsonclient.NewJSONClient(host) 106 if err != nil { 107 fmt.Fprintln(os.Stderr, err) 108 return 109 } 110 last, err := getLastHeader(rpcCli) 111 if err != nil { 112 fmt.Fprintln(os.Stderr, err) 113 return 114 } 115 curHeight := cache.lastHeader.Height 116 lastHeight := last.Height 117 118 // 节省监控的内存, 15000的区块头大约10M 119 if lastHeight-15000 > curHeight { //} && false { 120 curHeight = lastHeight - 15000 121 } 122 123 for curHeight < lastHeight { 124 hs, err := getHeaders(rpcCli, curHeight, curHeight+100) 125 if err != nil { 126 fmt.Fprintln(os.Stderr, err) 127 return 128 } 129 for _, h := range hs.Items { 130 if h.Height > cache.lastHeader.Height { 131 curHeight = h.Height 132 } 133 cache.addBlock(h) 134 } 135 fmt.Fprintln(os.Stderr, err, cache.lastHeader.Height) 136 } 137 138 fmt.Fprintln(os.Stderr, err, cache.lastHeader.Height) 139 } 140 141 //SyncBlock 同步区块 142 func SyncBlock(host string) { 143 cache.Host = host 144 syncHeaders(host) 145 146 timeout := time.NewTicker(time.Minute) 147 for { 148 <-timeout.C 149 syncHeaders(host) 150 } 151 }