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  }