-
Notifications
You must be signed in to change notification settings - Fork 2
/
cosmos.go
216 lines (182 loc) · 5.84 KB
/
cosmos.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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
package types
import (
"crypto/sha256"
"fmt"
"time"
cometbftcrypto "github.com/cometbft/cometbft/crypto"
cometbftcoretypes "github.com/cometbft/cometbft/rpc/core/types"
cometbfttypes "github.com/cometbft/cometbft/types"
"github.com/cosmos/cosmos-sdk/codec"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/bech32"
sdktx "github.com/cosmos/cosmos-sdk/types/tx"
"github.com/pkg/errors"
"golang.org/x/crypto/ripemd160" // nolint: staticcheck
)
var (
ErrNoEventFound = errors.New("no event found")
ErrNoAttributeFound = errors.New("no event with attribute")
)
type (
PubKey interface {
Bytes() []byte
}
ValidatorPreCommit struct {
Timestamp time.Time
ValidatorAddress string
BlockIDFlag uint64
VotingPower int64
}
Block struct {
Timestamp time.Time
Hash string
ProposerAddress string
ValidatorPreCommits []ValidatorPreCommit
Evidence cometbfttypes.EvidenceData
TxNum int
TotalGas uint64
Height int64
}
// Txs - slice of transactions
Txs []*Tx
// Tx represents an already existing blockchain transaction
Tx struct {
*sdktx.Tx
*sdk.TxResponse
Signer string
}
Validators []*Validator
Validator struct {
ConsAddr string
ConsPubkey string
}
)
func NewBlock(height int64, hash, proposerAddress string, txNum int, totalGas uint64, timestamp time.Time,
evidence cometbfttypes.EvidenceData) *Block {
return &Block{
Height: height,
Hash: hash,
TxNum: txNum,
ProposerAddress: proposerAddress,
Timestamp: timestamp,
Evidence: evidence,
TotalGas: totalGas,
}
}
// NewBlockFromTmBlock builds a new Block instance from a given ResultBlock object
func NewBlockFromTmBlock(blk *cometbftcoretypes.ResultBlock, totalGas uint64) *Block {
res := NewBlock(
blk.Block.Height,
blk.Block.Hash().String(),
sdk.ConsAddress(blk.Block.ProposerAddress).String(),
len(blk.Block.Txs),
totalGas,
blk.Block.Time,
blk.Block.Evidence,
)
if blk.Block.LastCommit != nil {
res.ValidatorPreCommits = NewValidatorPreCommitsFromTmSignatures(blk.Block.LastCommit.Signatures)
}
return res
}
func NewValidatorPreCommitsFromTmSignatures(sigs []cometbfttypes.CommitSig) []ValidatorPreCommit {
res := make([]ValidatorPreCommit, 0, len(sigs))
for _, sig := range sigs {
if len(sig.Signature) == 0 {
continue
}
res = append(res, ValidatorPreCommit{
ValidatorAddress: sdk.ConsAddress(sig.ValidatorAddress).String(),
BlockIDFlag: uint64(sig.BlockIDFlag),
Timestamp: sig.Timestamp,
})
}
return res
}
func NewTxsFromTmTxs(txs []*sdktx.GetTxResponse, cdc codec.Codec) Txs {
res := make(Txs, len(txs))
for i, tx := range txs {
var signer string
if tx.Tx.AuthInfo != nil {
if len(tx.Tx.AuthInfo.SignerInfos) > 0 && tx.Tx.AuthInfo.SignerInfos[0].PublicKey != nil {
var pk cryptotypes.PubKey
if err := cdc.UnpackAny(tx.Tx.AuthInfo.SignerInfos[0].PublicKey, &pk); err == nil {
signer, _ = ConvertAddressToBech32String(pk.Address())
}
}
}
res[i] = &Tx{
Tx: tx.Tx,
TxResponse: tx.TxResponse,
Signer: signer,
}
}
return res
}
func NewValidatorsFromTmValidator(tmVals *cometbftcoretypes.ResultValidators) Validators {
res := make(Validators, 0, len(tmVals.Validators))
for _, val := range tmVals.Validators {
consAddr := sdk.ConsAddress(val.Address).String()
if consPubKey, err := ConvertValidatorPubKeyToBech32String(val.PubKey); err == nil {
// we need only valid validators
res = append(res, NewValidator(consAddr, consPubKey))
}
}
return res
}
// NewValidator allows to build a new Validator instance
func NewValidator(consAddr string, consPubKey string) *Validator {
return &Validator{
ConsAddr: consAddr,
ConsPubkey: consPubKey,
}
}
func ConvertAddressToBech32String(address cryptotypes.Address) (string, error) {
bech32Prefix := sdk.GetConfig().GetBech32AccountAddrPrefix()
return bech32.ConvertAndEncode(bech32Prefix, address)
}
// ConvertValidatorPubKeyToBech32String converts the given pubKey to Bech32 string
func ConvertValidatorPubKeyToBech32String(pubKey cometbftcrypto.PubKey) (string, error) {
bech32Prefix := sdk.GetConfig().GetBech32ConsensusPubPrefix()
return bech32.ConvertAndEncode(bech32Prefix, pubKey.Bytes())
}
func BytesToAddress(key []byte) cryptotypes.Address {
sha := sha256.Sum256(key)
hasherRIPEMD160 := ripemd160.New()
hasherRIPEMD160.Write(sha[:])
return hasherRIPEMD160.Sum(nil)
}
// TotalGas calculates and returns total used gas of all transactions
func (txs Txs) TotalGas() (totalGas uint64) {
for _, tx := range txs {
totalGas += uint64(tx.GasUsed)
}
return totalGas
}
// FindEventByType searches inside the given tx events for the message having the specified index, in order
// to find the event having the given type, and returns it.
// If no such event is found, returns an error instead.
func (tx Tx) FindEventByType(index int, eventType string) (sdk.StringEvent, error) {
for _, ev := range tx.Logs[index].Events {
if ev.Type == eventType {
return ev, nil
}
}
return sdk.StringEvent{}, fmt.Errorf("%w: %s inside tx with hash %s", ErrNoEventFound,
eventType, tx.TxHash)
}
// FindAttributeByKey searches inside the specified event of the given tx to find the attribute having the given key.
// If the specified event does not contain a such attribute, returns an error instead.
func (tx Tx) FindAttributeByKey(event sdk.StringEvent, attrKey string) (string, error) {
for _, attr := range event.Attributes {
if attr.Key == attrKey {
return attr.Value, nil
}
}
return "", fmt.Errorf("%w: %s found inside tx with hash %s", ErrNoAttributeFound, attrKey, tx.TxHash)
}
// Successful tells whether this tx is successful or not
func (tx Tx) Successful() bool {
return tx.TxResponse.Code == 0
}