Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add evm-tx submodules and minor improvement for plain tx #57

Merged
merged 3 commits into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions go.work.sum
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,7 @@ github.com/cosmos/ibc-apps/modules/async-icq/v8 v8.0.1-0.20240124225747-f055ce5b
github.com/cosmos/ibc-apps/modules/async-icq/v8 v8.0.1-0.20240124225747-f055ce5b405c/go.mod h1:D3Q380FpWRFtmUQWLosPxachi6w24Og2t5u/Tww5wtY=
github.com/cosmos/ibc-go/v8 v8.1.0/go.mod h1:o1ipS95xpdjqNcB8Drq0eI3Sn4FRLigjll42ec1ECuU=
github.com/cosmos/interchain-security/v5 v5.0.0-alpha1/go.mod h1:c4oYjNwdfPKAhxzkwzTkkWROXKeUNPvc4VJHyNWrRU8=
github.com/cosmos/interchain-security/v5 v5.0.0-rc0 h1:Sh5CDqLDS32q2WsO9k5j3NyBzmW+mm66c+kgRniCthA=
github.com/cosmos/interchain-security/v5 v5.0.0-rc0/go.mod h1:h/RkwOppo5AJj+1pkQyfjqU1MPdpohD/S6oEeAXpGZY=
github.com/cosmos/relayer/v2 v2.5.2/go.mod h1:h4Ng2QsVpxExIq5S+WvLr8slDb9MSBh82gQS4DeMwDo=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
Expand Down Expand Up @@ -857,6 +858,7 @@ github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99
github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg=
github.com/googleapis/enterprise-certificate-proxy v0.2.4/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k=
github.com/googleapis/gax-go v0.0.0-20161107002406-da06d194a00e h1:CYRpN206UTHUinz3VJoLaBdy1gEGeJNsqT0mvswDcMw=
github.com/googleapis/gax-go v0.0.0-20161107002406-da06d194a00e/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
Expand Down Expand Up @@ -1174,6 +1176,7 @@ github.com/nishanths/exhaustive v0.12.0/go.mod h1:mEZ95wPIZW+x8kC4TgC+9YCUgiST7e
github.com/nishanths/predeclared v0.0.0-20190419143655-18a43bb90ffc/go.mod h1:62PewwiQTlm/7Rj+cxVYqZvDIUc+JjZq6GHAC1fsObQ=
github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c=
github.com/noble-assets/forwarding v0.0.0-20240416085758-ed8e9efaf69a/go.mod h1:nMEL3w1pf7+2LAQ3jqX+XaK0GWcdnwXjwlBnX7QO9ho=
github.com/noble-assets/forwarding/v2 v2.0.0-20240514101621-172acc02aac6 h1:YQ6I+9F24PD9U/Q83/t/DCPwye8IeHXOrQWorPx2aSE=
github.com/noble-assets/forwarding/v2 v2.0.0-20240514101621-172acc02aac6/go.mod h1:fkfElMT7VJZXXqywx+OE6qsEXddT/fwKX5XNdIl747U=
github.com/nunnatsa/ginkgolinter v0.9.0/go.mod h1:FHaMLURXP7qImeH6bvxWJUpyH+2tuqe5j4rW1gxJRmI=
github.com/nunnatsa/ginkgolinter v0.14.1/go.mod h1:nY0pafUSst7v7F637e7fymaMlQqI9c0Wka2fGsDkzWg=
Expand Down Expand Up @@ -1341,6 +1344,7 @@ github.com/sivchari/nosnakecase v1.7.0/go.mod h1:CwDzrzPea40/GB6uynrNLiorAlgFRvR
github.com/sivchari/tenv v1.7.1/go.mod h1:64yStXKSOxDfX47NlhVwND4dHwfZDdbp2Lyl018Icvg=
github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
github.com/skip-mev/block-sdk/v2 v2.1.1/go.mod h1:AOjFICNrPpq/Cq1f97CcC7ljWhxCzmfmyz4/Ir8/xFM=
github.com/skip-mev/block-sdk/v2 v2.1.2 h1:fNKbrb+PVVzuU0JiSuWgBV4Afj5zZ1VeHQJp88wSl1g=
github.com/skip-mev/block-sdk/v2 v2.1.2/go.mod h1:kIq7SMva0/eHKTCiG/oI5XGxD4HNVK0t71TrUZqHcvA=
github.com/skip-mev/chaintestutil v0.0.0-20231221145345-f208ee3b1383/go.mod h1:FvYgT9wJSLvtBkwWp4mHo+A5/r9OkvHXJJh9u8RhGWk=
github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa/go.mod h1:oJyF+mSPHbB5mVY2iO9KV3pTt/QbIkGaO8gQ2WrDbP4=
Expand Down
200 changes: 200 additions & 0 deletions submodules/evm-tx/collect.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
package tx

import (
"context"
"encoding/json"
"fmt"
"time"

"cosmossdk.io/collections"
cosmoserr "cosmossdk.io/errors"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/tx"

abci "github.com/cometbft/cometbft/abci/types"
"github.com/cometbft/cometbft/crypto/tmhash"
coretypes "github.com/cometbft/cometbft/rpc/core/types"

evmtypes "github.com/initia-labs/minievm/x/evm/types"

"github.com/initia-labs/kvindexer/submodules/tx/types"
)

func (sm EvmTxSubmodule) finalizeBlock(ctx context.Context, req abci.RequestFinalizeBlock, res abci.ResponseFinalizeBlock) error {
sm.Logger(ctx).Debug("finalizeBlock", "submodule", types.SubmoduleName, "txs", len(req.Txs), "height", req.Height)

if err := sm.processTxs(ctx, req, res); err != nil {
return err
}

return nil
}

func (sm EvmTxSubmodule) processTxs(ctx context.Context, req abci.RequestFinalizeBlock, res abci.ResponseFinalizeBlock) error {
// key: address, value: txs slice
accTxMap := map[string][]string{}

txHashes := []string{}
for idx, txBytes := range req.Txs {
tx, err := parseTx(sm.cdc, txBytes)
if err != nil {
sm.Logger(ctx).Info("failed to parse tx", "error", err, "index", idx)
continue
}

any, err := codectypes.NewAnyWithValue(tx)
if err != nil {
sm.Logger(ctx).Info("failed to unpack any", "error", err, "index", idx)
continue
}

txHash := tmhash.Sum(txBytes)
txHashStr := fmt.Sprintf("%x", txHash)
resultTx := coretypes.ResultTx{
Hash: txHash,
Height: req.Height,
TxResult: *res.TxResults[idx],
// No Index, Tx and Proof here. sdk.NewResponseTxResult() don't use them
}

txr := sdk.NewResponseResultTx(&resultTx, any, req.Time.UTC().Format(time.RFC3339))

if err := sm.txMap.Set(ctx, txHashStr, *txr); err != nil {
sm.Logger(ctx).Info("failed to store tx", "error", err, "index", idx)
continue
}

// get addresses from the tx
addrs, err := grepAddressesFromTx(txr)
if err != nil {
sm.Logger(ctx).Info("failed to grep addresses from tx", "error", err, "index", idx)
continue
}

for _, addr := range addrs {
accTxMap[addr] = uniqueAppend(accTxMap[addr], txHashStr)
}
txHashes = append(txHashes, txHashStr)
}

// store tx/account pair into txAccMap
for addr, txHashes := range accTxMap {
err := sm.storeAccTxs(ctx, addr, txHashes)
if err != nil {
sm.Logger(ctx).Info("failed to store tx/account pair", "error", err, "address", addr)
}
}
return sm.storeIndices(ctx, req.Height, txHashes)
}

func uniqueAppend(slice []string, elem string) []string {
for _, e := range slice {
if e == elem {
return slice
}
}
return append(slice, elem)
}

func parseTx(cdc codec.Codec, txBytes []byte) (*tx.Tx, error) {
tx := tx.Tx{}
err := cdc.Unmarshal(txBytes, &tx)
if err != nil {
return nil, err
}
return &tx, nil
}

func grepAddressesFromTx(txr *sdk.TxResponse) ([]string, error) {
grepped := []string{}
for _, event := range txr.Events {
for _, attr := range event.Attributes {
var addrs []string

if event.Type == evmtypes.EventTypeEVM && attr.Key == evmtypes.AttributeKeyLog {
contractAddr, err := extractAddressesFromEVMLog(attr.Value)
if err != nil {
continue
}
addrs = append(addrs, contractAddr)
} else {
addrs = findAllBech32Address(attr.Value)
addrs = append(addrs, findAllHexAddress(attr.Value)...)
}

for _, addr := range addrs {
accAddr, err := accAddressFromString(addr)
if err != nil {
continue
}
grepped = append(grepped, accAddr.String())
}
}
}

return grepped, nil
}

func extractAddressesFromEVMLog(attrVal string) (string, error) {
log := evmtypes.Log{}
if err := json.Unmarshal([]byte(attrVal), &log); err != nil {
return "", err
}
return convertContractAddressToBech32(log.Address)
}

func (sm EvmTxSubmodule) storeAccTxs(ctx context.Context, addr string, txHashes []string) error {
if len(txHashes) == 0 {
return nil
}
acc, err := sdk.AccAddressFromBech32(addr)
if err != nil {
sm.Logger(ctx).Info("failed to convert address", "error", err, "address", addr)
return err
}

seq, err := sm.accountSequenceMap.Get(ctx, acc)
if err != nil && !cosmoserr.IsOf(err, collections.ErrNotFound) {
return err
}

for i, txHash := range txHashes {
err = sm.txhashesByAccountMap.Set(ctx, collections.Join(acc, seq+uint64(i)), txHash)
if err != nil {
sm.Logger(ctx).Info("failed to store tx/account pair", "error", err, "address", addr, "txhash", txHash)
continue
}

}
delta := seq + uint64(len(txHashes)+1)
if err = sm.accountSequenceMap.Set(ctx, acc, delta); err != nil {
sm.Logger(ctx).Info("failed to store account sequence", "error", err, "address", addr, "delta", delta)
return err
}

return err
}

func (sm EvmTxSubmodule) storeIndices(ctx context.Context, height int64, txHashes []string) error {
for i, txHash := range txHashes {
err := sm.txhashesByHeightMap.Set(ctx, collections.Join(height, uint64(i)), txHash)
if err != nil {
sm.Logger(ctx).Info("failed to store tx/height pair", "error", err, "height", height, "txhash", txHash)
continue
}

seq, err := sm.sequence.Next(ctx)
if err != nil {
return err
}

err = sm.txhashesBySequenceMap.Set(ctx, seq, txHash)
if err != nil {
return err
}
}

return nil
}
Loading
Loading