-
Notifications
You must be signed in to change notification settings - Fork 271
/
read.go
138 lines (129 loc) · 4.04 KB
/
read.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
package testnode
import (
"context"
"fmt"
"github.com/celestiaorg/celestia-app/v2/app"
"github.com/celestiaorg/celestia-app/v2/app/encoding"
"github.com/celestiaorg/go-square/blob"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/tendermint/tendermint/rpc/client/http"
"github.com/tendermint/tendermint/types"
)
func ReadRecentBlocks(ctx context.Context, rpcAddress string, blocks int64) ([]*types.Block, error) {
client, err := http.New(rpcAddress, "/websocket")
if err != nil {
return nil, err
}
status, err := client.Status(ctx)
if err != nil {
return nil, err
}
if status.SyncInfo.LatestBlockHeight < blocks {
return nil, fmt.Errorf("latest block height %d is less than requested blocks %d", status.SyncInfo.LatestBlockHeight, blocks)
}
return ReadBlockHeights(ctx, rpcAddress, status.SyncInfo.LatestBlockHeight-blocks+1, status.SyncInfo.LatestBlockHeight)
}
func ReadBlockchain(ctx context.Context, rpcAddress string) ([]*types.Block, error) {
client, err := http.New(rpcAddress, "/websocket")
if err != nil {
return nil, err
}
status, err := client.Status(ctx)
if err != nil {
return nil, err
}
return ReadBlockHeights(ctx, rpcAddress, 1, status.SyncInfo.LatestBlockHeight)
}
func ReadBlockHeights(ctx context.Context, rpcAddress string, fromHeight, toHeight int64) ([]*types.Block, error) {
client, err := http.New(rpcAddress, "/websocket")
if err != nil {
return nil, err
}
blocks := make([]*types.Block, toHeight-fromHeight+1)
for i := fromHeight; i <= toHeight; i++ {
resp, err := client.Block(ctx, &i)
if err != nil {
return nil, err
}
blocks[i-fromHeight] = resp.Block
}
return blocks, nil
}
func DecodeBlockData(data types.Data) ([]sdk.Tx, error) {
encCfg := encoding.MakeConfig(app.ModuleEncodingRegisters...)
decoder := encCfg.TxConfig.TxDecoder()
txs := make([]sdk.Tx, 0)
for _, txBytes := range data.Txs {
blobTx, isBlobTx := blob.UnmarshalBlobTx(txBytes)
if isBlobTx {
txBytes = blobTx.Tx
}
tx, err := decoder(txBytes)
if err != nil {
return nil, fmt.Errorf("decoding tx: %s: %w", string(txBytes), err)
}
txs = append(txs, tx)
}
return txs, nil
}
func CalculateMeanGasFromRecentBlocks(ctx context.Context, rpcAddress, msgType string, blocks int64) (float64, int64, error) {
client, err := http.New(rpcAddress, "/websocket")
if err != nil {
return 0.0, 0, err
}
status, err := client.Status(ctx)
if err != nil {
return 0.0, 0, err
}
if status.SyncInfo.LatestBlockHeight <= blocks {
return 0.0, 0, fmt.Errorf("latest block height %d is less than %d", status.SyncInfo.LatestBlockHeight, blocks)
}
return CalculateMeanGas(ctx, rpcAddress, msgType, status.SyncInfo.LatestBlockHeight-blocks+1, status.SyncInfo.LatestBlockHeight)
}
func CalculateMeanGas(ctx context.Context, rpcAddress, msgType string, fromHeight int64, toHeight int64) (float64, int64, error) {
var (
encCfg = encoding.MakeConfig(app.ModuleEncodingRegisters...)
decoder = encCfg.TxConfig.TxDecoder()
totalGas int64
count int64
average = func() float64 {
if count == 0 {
return 0
}
return float64(totalGas) / float64(count)
}
)
client, err := http.New(rpcAddress, "/websocket")
if err != nil {
return 0.0, 0, err
}
for height := fromHeight; height <= toHeight; height++ {
resp, err := client.Block(ctx, &height)
if err != nil {
return average(), count, err
}
indices := make([]int, 0, len(resp.Block.Data.Txs))
for i, rawTx := range resp.Block.Data.Txs {
tx, err := decoder(rawTx)
if err != nil {
return average(), count, fmt.Errorf("decoding tx (height: %d): %w", height, err)
}
msgs := tx.GetMsgs()
// multi message transactions are not included
if len(msgs) == 1 && sdk.MsgTypeURL(msgs[0]) == msgType {
indices = append(indices, i)
}
}
if len(indices) > 0 {
results, err := client.BlockResults(ctx, &height)
if err != nil {
return average(), count, fmt.Errorf("getting block results (height %d): %w", height, err)
}
for _, i := range indices {
totalGas += results.TxsResults[i].GasUsed
count++
}
}
}
return average(), count, nil
}