-
Notifications
You must be signed in to change notification settings - Fork 43
/
chainkit_client.go
155 lines (124 loc) · 4 KB
/
chainkit_client.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package lndclient
import (
"bytes"
"context"
"sync"
"time"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire"
"github.com/lightningnetwork/lnd/lnrpc/chainrpc"
"google.golang.org/grpc"
)
// ChainKitClient exposes chain functionality.
type ChainKitClient interface {
// GetBlock returns a block given the corresponding block hash.
GetBlock(ctx context.Context, hash chainhash.Hash) (*wire.MsgBlock,
error)
// GetBlockHeader returns a block header given the corresponding block
// hash.
GetBlockHeader(ctx context.Context,
hash chainhash.Hash) (*wire.BlockHeader, error)
// GetBestBlock returns the latest block hash and current height of the
// valid most-work chain.
GetBestBlock(ctx context.Context) (chainhash.Hash, int32, error)
// GetBlockHash returns the hash of the block in the best blockchain
// at the given height.
GetBlockHash(ctx context.Context, blockHeight int64) (chainhash.Hash,
error)
}
type chainKitClient struct {
client chainrpc.ChainKitClient
chainMac serializedMacaroon
timeout time.Duration
wg sync.WaitGroup
}
func newChainKitClient(conn grpc.ClientConnInterface,
chainMac serializedMacaroon, timeout time.Duration) *chainKitClient {
return &chainKitClient{
client: chainrpc.NewChainKitClient(conn),
chainMac: chainMac,
timeout: timeout,
}
}
func (s *chainKitClient) WaitForFinished() {
s.wg.Wait()
}
// GetBlock returns a block given the corresponding block hash.
func (s *chainKitClient) GetBlock(ctxParent context.Context,
hash chainhash.Hash) (*wire.MsgBlock, error) {
ctx, cancel := context.WithTimeout(ctxParent, s.timeout)
defer cancel()
macaroonAuth := s.chainMac.WithMacaroonAuth(ctx)
req := &chainrpc.GetBlockRequest{
BlockHash: hash[:],
}
resp, err := s.client.GetBlock(macaroonAuth, req)
if err != nil {
return nil, err
}
// Convert raw block bytes into wire.MsgBlock.
msgBlock := &wire.MsgBlock{}
blockReader := bytes.NewReader(resp.RawBlock)
err = msgBlock.Deserialize(blockReader)
if err != nil {
return nil, err
}
return msgBlock, nil
}
// GetBlockHeader returns a block header given the corresponding block hash.
func (s *chainKitClient) GetBlockHeader(ctxParent context.Context,
hash chainhash.Hash) (*wire.BlockHeader, error) {
ctx, cancel := context.WithTimeout(ctxParent, s.timeout)
defer cancel()
macaroonAuth := s.chainMac.WithMacaroonAuth(ctx)
req := &chainrpc.GetBlockHeaderRequest{
BlockHash: hash[:],
}
resp, err := s.client.GetBlockHeader(macaroonAuth, req)
if err != nil {
return nil, err
}
// Convert raw block header bytes into wire.BlockHeader.
blockHeader := &wire.BlockHeader{}
blockReader := bytes.NewReader(resp.RawBlockHeader)
err = blockHeader.Deserialize(blockReader)
if err != nil {
return nil, err
}
return blockHeader, nil
}
// GetBestBlock returns the block hash and current height from the valid
// most-work chain.
func (s *chainKitClient) GetBestBlock(ctxParent context.Context) (chainhash.Hash,
int32, error) {
ctx, cancel := context.WithTimeout(ctxParent, s.timeout)
defer cancel()
macaroonAuth := s.chainMac.WithMacaroonAuth(ctx)
resp, err := s.client.GetBestBlock(
macaroonAuth, &chainrpc.GetBestBlockRequest{},
)
if err != nil {
return chainhash.Hash{}, 0, err
}
// Cast gRPC block hash bytes as chain hash type.
var blockHash chainhash.Hash
copy(blockHash[:], resp.BlockHash)
return blockHash, resp.BlockHeight, nil
}
// GetBlockHash returns the hash of the block in the best blockchain at the
// given height.
func (s *chainKitClient) GetBlockHash(ctxParent context.Context,
blockHeight int64) (chainhash.Hash, error) {
ctx, cancel := context.WithTimeout(ctxParent, s.timeout)
defer cancel()
macaroonAuth := s.chainMac.WithMacaroonAuth(ctx)
req := &chainrpc.GetBlockHashRequest{BlockHeight: blockHeight}
resp, err := s.client.GetBlockHash(macaroonAuth, req)
if err != nil {
return chainhash.Hash{}, err
}
// Cast gRPC block hash bytes as chain hash type.
var blockHash chainhash.Hash
copy(blockHash[:], resp.BlockHash)
return blockHash, nil
}