From b415e150e8b7e4693859e8ac24954f718986688e Mon Sep 17 00:00:00 2001 From: Til Jordan Date: Sat, 27 Sep 2025 12:55:55 +0000 Subject: [PATCH 01/17] x/bloctopus/forkbank: add ForkingBankKeeper with local-first reads, TLS gRPC fallback, and denom metadata fallback; wire bank keeper as interface --- app/app.go | 13 +++- x/bloctopus/forkbank/keeper/iterator.go | 1 + x/bloctopus/forkbank/keeper/keeper.go | 82 +++++++++++++++++++++++++ x/bloctopus/forkbank/keeper/remote.go | 72 ++++++++++++++++++++++ x/bloctopus/forkbank/keeper/types.go | 15 +++++ 5 files changed, 181 insertions(+), 2 deletions(-) create mode 100644 x/bloctopus/forkbank/keeper/iterator.go create mode 100644 x/bloctopus/forkbank/keeper/keeper.go create mode 100644 x/bloctopus/forkbank/keeper/remote.go create mode 100644 x/bloctopus/forkbank/keeper/types.go diff --git a/app/app.go b/app/app.go index c70cb3e2c..749d699d1 100644 --- a/app/app.go +++ b/app/app.go @@ -66,6 +66,8 @@ import ( "github.com/cosmos/cosmos-sdk/x/mint" mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + + forkbankkeeper "gitlab.com/thorchain/thornode/v3/x/bloctopus/forkbank/keeper" "github.com/cosmos/cosmos-sdk/x/params" paramskeeper "github.com/cosmos/cosmos-sdk/x/params/keeper" paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" @@ -147,7 +149,7 @@ type THORChainApp struct { // keepers AccountKeeper authkeeper.AccountKeeper AuthzKeeper authzkeeper.Keeper - BankKeeper bankkeeper.BaseKeeper + BankKeeper bankkeeper.Keeper StakingKeeper *stakingkeeper.Keeper MintKeeper mintkeeper.Keeper UpgradeKeeper *upgradekeeper.Keeper @@ -305,7 +307,7 @@ func NewChainApp( app.MsgServiceRouter(), app.AccountKeeper, ) - app.BankKeeper = bankkeeper.NewBaseKeeper( + baseBank := bankkeeper.NewBaseKeeper( app.appCodec, runtime.NewKVStoreService(keys[banktypes.StoreKey]), app.AccountKeeper, @@ -313,6 +315,13 @@ func NewChainApp( authtypes.NewModuleAddress(thorchain.ModuleName).String(), logger, ) + fbk, err := forkbankkeeper.NewForkingBankKeeper(baseBank, forkbankkeeper.Config{ + Endpoint: "grpc.thor.pfc.zone:443", + }) + if err != nil { + panic(err) + } + app.BankKeeper = fbk txSigningOptions, err := tx.NewDefaultSigningOptions() if err != nil { diff --git a/x/bloctopus/forkbank/keeper/iterator.go b/x/bloctopus/forkbank/keeper/iterator.go new file mode 100644 index 000000000..b55569d4a --- /dev/null +++ b/x/bloctopus/forkbank/keeper/iterator.go @@ -0,0 +1 @@ +package keeper diff --git a/x/bloctopus/forkbank/keeper/keeper.go b/x/bloctopus/forkbank/keeper/keeper.go new file mode 100644 index 000000000..62efeebf3 --- /dev/null +++ b/x/bloctopus/forkbank/keeper/keeper.go @@ -0,0 +1,82 @@ +package keeper + +import ( + "context" + + "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +func NewForkingBankKeeper(base bankkeeper.BaseKeeper, cfg Config) (ForkingBankKeeper, error) { + client, err := NewRemoteClient(cfg.Endpoint) + if err != nil { + return ForkingBankKeeper{}, err + } + return ForkingBankKeeper{ + BaseKeeper: base, + cfg: cfg, + client: client, + }, nil +} + +func (k ForkingBankKeeper) GetAllBalances(ctx context.Context, addr sdk.AccAddress) sdk.Coins { + if k.BaseKeeper.HasBalance(ctx, addr, sdk.NewCoin("rune", math.NewInt(1))) { + return k.BaseKeeper.GetAllBalances(ctx, addr) + } + resp, err := k.client.RemoteBalances(ctx, addr.String()) + if err != nil || resp == nil { + return sdk.NewCoins() + } + return sdk.NewCoins(resp.Balances...) +} + +func (k ForkingBankKeeper) GetBalance(ctx context.Context, addr sdk.AccAddress, denom string) sdk.Coin { + if k.BaseKeeper.HasBalance(ctx, addr, sdk.NewCoin(denom, math.NewInt(1))) { + return k.BaseKeeper.GetBalance(ctx, addr, denom) + } + resp, err := k.client.RemoteBalances(ctx, addr.String()) + if err != nil { + return sdk.NewCoin(denom, math.ZeroInt()) + } + for _, c := range resp.Balances { + if c.Denom == denom { + return c + } + } + return sdk.NewCoin(denom, math.ZeroInt()) +} + +func (k ForkingBankKeeper) SendCoins(ctx context.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error { + return k.BaseKeeper.SendCoins(ctx, fromAddr, toAddr, amt) +} + +func (k ForkingBankKeeper) GetDenomMetaData(ctx context.Context, denom string) (banktypes.Metadata, bool) { + md, found := k.BaseKeeper.GetDenomMetaData(ctx, denom) + if found { + return md, true + } + resp, err := k.client.RemoteDenomsMetadata(ctx) + if err != nil || resp == nil { + return banktypes.Metadata{}, false + } + for _, m := range resp.Metadatas { + if m.Base == denom { + return m, true + } + } + return banktypes.Metadata{}, false +} + +func (k ForkingBankKeeper) GetAllDenomMetaData(ctx context.Context) []banktypes.Metadata { + all := k.BaseKeeper.GetAllDenomMetaData(ctx) + if len(all) > 0 { + return all + } + resp, err := k.client.RemoteDenomsMetadata(ctx) + if err != nil || resp == nil { + return nil + } + return resp.Metadatas +} diff --git a/x/bloctopus/forkbank/keeper/remote.go b/x/bloctopus/forkbank/keeper/remote.go new file mode 100644 index 000000000..30e1ca011 --- /dev/null +++ b/x/bloctopus/forkbank/keeper/remote.go @@ -0,0 +1,72 @@ +package keeper + +import ( + "context" + "crypto/tls" + + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +type RemoteClient struct { + conn *grpc.ClientConn + bankQuery banktypes.QueryClient + denomQuery banktypes.QueryClient + endpoint string + dialed bool + tlsInsecure bool +} + +func NewRemoteClient(endpoint string) (*RemoteClient, error) { + rc := &RemoteClient{endpoint: endpoint} + err := rc.ensureConn() + if err != nil { + return nil, err + } + return rc, nil +} + +func (c *RemoteClient) ensureConn() error { + if c.dialed { + return nil + } + creds := credentials.NewTLS(&tls.Config{}) + conn, err := grpc.Dial(c.endpoint, grpc.WithTransportCredentials(creds)) + if err != nil { + return err + } + c.conn = conn + c.bankQuery = banktypes.NewQueryClient(conn) + c.dialed = true + return nil +} + +func (c *RemoteClient) Close() { + if c.conn != nil { + _ = c.conn.Close() + } +} + +func (c *RemoteClient) RemoteBalances(ctx context.Context, addr string) (*banktypes.QueryAllBalancesResponse, error) { + if err := c.ensureConn(); err != nil { + return nil, err + } + resp, err := c.bankQuery.AllBalances(ctx, &banktypes.QueryAllBalancesRequest{Address: addr}) + if err != nil { + return nil, err + } + return resp, nil +} + +func (c *RemoteClient) RemoteDenomsMetadata(ctx context.Context) (*banktypes.QueryDenomsMetadataResponse, error) { + if err := c.ensureConn(); err != nil { + return nil, err + } + resp, err := c.bankQuery.DenomsMetadata(ctx, &banktypes.QueryDenomsMetadataRequest{}) + if err != nil { + return nil, err + } + return resp, nil +} diff --git a/x/bloctopus/forkbank/keeper/types.go b/x/bloctopus/forkbank/keeper/types.go new file mode 100644 index 000000000..a88fa6a33 --- /dev/null +++ b/x/bloctopus/forkbank/keeper/types.go @@ -0,0 +1,15 @@ +package keeper + +import ( + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" +) + +type Config struct { + Endpoint string +} + +type ForkingBankKeeper struct { + bankkeeper.BaseKeeper + cfg Config + client *RemoteClient +} From c79f6567c19ef1d0e44fd6d7224dc09dcd9ff4f0 Mon Sep 17 00:00:00 2001 From: Til Jordan Date: Sat, 27 Sep 2025 12:56:09 +0000 Subject: [PATCH 02/17] x/bloctopus/forking: scaffold forking KV/service/iterators/flags under x/bloctopus --- x/bloctopus/forking/cache.go | 1 + x/bloctopus/forking/flags.go | 13 +++++++++++++ x/bloctopus/forking/gas.go | 22 ++++++++++++++++++++++ x/bloctopus/forking/iterator.go | 14 ++++++++++++++ x/bloctopus/forking/service.go | 15 +++++++++++++++ x/bloctopus/forking/store.go | 11 +++++++++++ x/bloctopus/forking/types.go | 10 ++++++++++ 7 files changed, 86 insertions(+) create mode 100644 x/bloctopus/forking/cache.go create mode 100644 x/bloctopus/forking/flags.go create mode 100644 x/bloctopus/forking/gas.go create mode 100644 x/bloctopus/forking/iterator.go create mode 100644 x/bloctopus/forking/service.go create mode 100644 x/bloctopus/forking/store.go create mode 100644 x/bloctopus/forking/types.go diff --git a/x/bloctopus/forking/cache.go b/x/bloctopus/forking/cache.go new file mode 100644 index 000000000..31eed3c78 --- /dev/null +++ b/x/bloctopus/forking/cache.go @@ -0,0 +1 @@ +package forking diff --git a/x/bloctopus/forking/flags.go b/x/bloctopus/forking/flags.go new file mode 100644 index 000000000..cd7aa909d --- /dev/null +++ b/x/bloctopus/forking/flags.go @@ -0,0 +1,13 @@ +package forking + +import "github.com/spf13/pflag" + +const ( + flagForkingEnabled = "forking.enabled" + flagForkingGRPC = "forking.grpc" +) + +func AddFlags(fs *pflag.FlagSet) { + fs.Bool(flagForkingEnabled, true, "enable forking") + fs.String(flagForkingGRPC, "grpc.thor.pfc.zone:443", "forking grpc endpoint") +} diff --git a/x/bloctopus/forking/gas.go b/x/bloctopus/forking/gas.go new file mode 100644 index 000000000..00095ff7e --- /dev/null +++ b/x/bloctopus/forking/gas.go @@ -0,0 +1,22 @@ +package forking + +import storetypes "cosmossdk.io/store/types" + +type SDKGasMeter struct { + gasMeter storetypes.GasMeter +} + +func NewSDKGasMeter(gasMeter storetypes.GasMeter) *SDKGasMeter { + if gasMeter == nil { + return nil + } + return &SDKGasMeter{gasMeter: gasMeter} +} + +func (g *SDKGasMeter) ConsumeGas(amount uint64, descriptor string) { + g.gasMeter.ConsumeGas(amount, descriptor) +} + +func (g *SDKGasMeter) GasConsumed() uint64 { + return g.gasMeter.GasConsumed() +} diff --git a/x/bloctopus/forking/iterator.go b/x/bloctopus/forking/iterator.go new file mode 100644 index 000000000..10711d680 --- /dev/null +++ b/x/bloctopus/forking/iterator.go @@ -0,0 +1,14 @@ +package forking + +import storetypes "cosmossdk.io/core/store" + +type MergedIterator struct { + local storetypes.Iterator +} + +func (it *MergedIterator) Close() error { + if it.local != nil { + return it.local.Close() + } + return nil +} diff --git a/x/bloctopus/forking/service.go b/x/bloctopus/forking/service.go new file mode 100644 index 000000000..c2034eaf6 --- /dev/null +++ b/x/bloctopus/forking/service.go @@ -0,0 +1,15 @@ +package forking + +import storetypes "cosmossdk.io/core/store" + +type forkingKVStoreService struct { + parent storetypes.KVStoreService +} + +func NewKVStoreService(parent storetypes.KVStoreService) storetypes.KVStoreService { + return &forkingKVStoreService{parent: parent} +} + +func (s *forkingKVStoreService) OpenStore(ctx storetypes.Context) storetypes.KVStore { + return s.parent.OpenStore(ctx) +} diff --git a/x/bloctopus/forking/store.go b/x/bloctopus/forking/store.go new file mode 100644 index 000000000..f249b7c52 --- /dev/null +++ b/x/bloctopus/forking/store.go @@ -0,0 +1,11 @@ +package forking + +import storetypes "cosmossdk.io/core/store" + +type KVStore struct { + store storetypes.KVStore +} + +func NewKVStore(store storetypes.KVStore) *KVStore { + return &KVStore{store: store} +} diff --git a/x/bloctopus/forking/types.go b/x/bloctopus/forking/types.go new file mode 100644 index 000000000..ff8154796 --- /dev/null +++ b/x/bloctopus/forking/types.go @@ -0,0 +1,10 @@ +package forking + +type RemoteConfig struct { + GRPC string +} + +type Options struct { + Enabled bool + Config RemoteConfig +} From 552fb278e65b0378f849df7c5a9471ecb67a1ecc Mon Sep 17 00:00:00 2001 From: Til Jordan Date: Sat, 27 Sep 2025 13:38:31 +0000 Subject: [PATCH 03/17] app,cmd: conditionally enable ForkingBankKeeper via --fork.enabled and read endpoint from --fork.grpc (with hyphenated flag aliases) --- app/app.go | 19 +++++++++++++------ cmd/thornode/commands.go | 16 +++++++++++++--- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/app/app.go b/app/app.go index 749d699d1..54c39d012 100644 --- a/app/app.go +++ b/app/app.go @@ -315,13 +315,20 @@ func NewChainApp( authtypes.NewModuleAddress(thorchain.ModuleName).String(), logger, ) - fbk, err := forkbankkeeper.NewForkingBankKeeper(baseBank, forkbankkeeper.Config{ - Endpoint: "grpc.thor.pfc.zone:443", - }) - if err != nil { - panic(err) + app.BankKeeper = baseBank + if cast.ToBool(appOpts.Get("fork.enabled")) { + endpoint := cast.ToString(appOpts.Get("fork.grpc")) + if endpoint == "" { + endpoint = "grpc.thor.pfc.zone:443" + } + fbk, err := forkbankkeeper.NewForkingBankKeeper(baseBank, forkbankkeeper.Config{ + Endpoint: endpoint, + }) + if err != nil { + panic(err) + } + app.BankKeeper = fbk } - app.BankKeeper = fbk txSigningOptions, err := tx.NewDefaultSigningOptions() if err != nil { diff --git a/cmd/thornode/commands.go b/cmd/thornode/commands.go index eaa6e6685..bb13704db 100644 --- a/cmd/thornode/commands.go +++ b/cmd/thornode/commands.go @@ -154,13 +154,10 @@ func addModuleInitFlags(startCmd *cobra.Command) { startCmd.PreRunE = func(cmd *cobra.Command, _ []string) error { serverCtx := server.GetServerContextFromCmd(cmd) - // Bind flags to the Context's Viper so the app construction can set - // options accordingly. if err := serverCtx.Viper.BindPFlags(cmd.Flags()); err != nil { return fmt.Errorf("fail to bind flags,err: %w", err) } - // replace sdk logger with thorlog if zl, ok := serverCtx.Logger.Impl().(*zerolog.Logger); ok { logger := zl.With().CallerWithSkipFrameCount(3).Logger() serverCtx.Logger = thorlog.SdkLogWrapper{ @@ -172,6 +169,19 @@ func addModuleInitFlags(startCmd *cobra.Command) { } wasm.AddModuleInitFlags(startCmd) ebifrost.AddModuleInitFlags(startCmd) + + startCmd.Flags().Bool("fork.enabled", false, "Enable forking mode") + startCmd.Flags().String("fork.grpc", "", "Forking remote gRPC endpoint (e.g. grpc.thor.pfc.zone:443)") + startCmd.Flags().String("fork.chain_id", "", "Forking remote chain-id") + startCmd.Flags().String("fork.chain-id", "", "Forking remote chain-id (alias)") + startCmd.Flags().Uint64("fork.height", 0, "Forking remote reference height (ignored; latest only)") + startCmd.Flags().Bool("fork.cache_enabled", true, "Enable in-memory cache for forking client") + startCmd.Flags().Bool("fork.cache-enabled", true, "Enable in-memory cache for forking client (alias)") + startCmd.Flags().Uint64("fork.cache_size", 10000, "Cache size for forking client") + startCmd.Flags().Uint64("fork.cache-size", 10000, "Cache size for forking client (alias)") + startCmd.Flags().String("fork.timeout", "60s", "Timeout for forking client requests") + startCmd.Flags().Uint64("fork.gas_cost_per_fetch", 0, "Gas cost per remote fetch in forking mode") + startCmd.Flags().Uint64("fork.gas-cost-per-fetch", 0, "Gas cost per remote fetch in forking mode (alias)") } func renderConfigCommand() *cobra.Command { From 8905c5cb8246508d189a80837dec2eab698e85f3 Mon Sep 17 00:00:00 2001 From: Til Jordan Date: Sat, 27 Sep 2025 13:42:57 +0000 Subject: [PATCH 04/17] forkbank: set TLS SNI for grpc.thor.pfc.zone; app: wrap bank store with forking KV service when fork.enabled --- app/app.go | 8 +++++++- x/bloctopus/forkbank/keeper/remote.go | 4 +++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/app/app.go b/app/app.go index 54c39d012..cc96329bf 100644 --- a/app/app.go +++ b/app/app.go @@ -307,9 +307,15 @@ func NewChainApp( app.MsgServiceRouter(), app.AccountKeeper, ) + var bankStoreSvc runtime.KVStoreService + if cast.ToBool(appOpts.Get("fork.enabled")) { + bankStoreSvc = forking.NewKVStoreService(runtime.NewKVStoreService(keys[banktypes.StoreKey])) + } else { + bankStoreSvc = runtime.NewKVStoreService(keys[banktypes.StoreKey]) + } baseBank := bankkeeper.NewBaseKeeper( app.appCodec, - runtime.NewKVStoreService(keys[banktypes.StoreKey]), + bankStoreSvc, app.AccountKeeper, BlockedAddresses(), authtypes.NewModuleAddress(thorchain.ModuleName).String(), diff --git a/x/bloctopus/forkbank/keeper/remote.go b/x/bloctopus/forkbank/keeper/remote.go index 30e1ca011..616827798 100644 --- a/x/bloctopus/forkbank/keeper/remote.go +++ b/x/bloctopus/forkbank/keeper/remote.go @@ -32,7 +32,9 @@ func (c *RemoteClient) ensureConn() error { if c.dialed { return nil } - creds := credentials.NewTLS(&tls.Config{}) + creds := credentials.NewTLS(&tls.Config{ + ServerName: "grpc.thor.pfc.zone", + }) conn, err := grpc.Dial(c.endpoint, grpc.WithTransportCredentials(creds)) if err != nil { return err From da4595c91ef0c4a7314aeaf32536aaa1944b61b3 Mon Sep 17 00:00:00 2001 From: Til Jordan Date: Sat, 27 Sep 2025 13:45:46 +0000 Subject: [PATCH 05/17] app: import x/bloctopus/forking and use storetypes.KVStoreService for forking bank store --- app/app.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/app.go b/app/app.go index cc96329bf..5ff6056b8 100644 --- a/app/app.go +++ b/app/app.go @@ -68,6 +68,7 @@ import ( minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" forkbankkeeper "gitlab.com/thorchain/thornode/v3/x/bloctopus/forkbank/keeper" + forking "gitlab.com/thorchain/thornode/v3/x/bloctopus/forking" "github.com/cosmos/cosmos-sdk/x/params" paramskeeper "github.com/cosmos/cosmos-sdk/x/params/keeper" paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" @@ -307,7 +308,7 @@ func NewChainApp( app.MsgServiceRouter(), app.AccountKeeper, ) - var bankStoreSvc runtime.KVStoreService + var bankStoreSvc storetypes.KVStoreService if cast.ToBool(appOpts.Get("fork.enabled")) { bankStoreSvc = forking.NewKVStoreService(runtime.NewKVStoreService(keys[banktypes.StoreKey])) } else { From 98c0a6d05950465cb8e18373ca353415107e5048 Mon Sep 17 00:00:00 2001 From: Til Jordan Date: Sat, 27 Sep 2025 13:47:40 +0000 Subject: [PATCH 06/17] forking: fix KVStoreService wrapper to use store/types and OpenKVStore(ctx) --- x/bloctopus/forking/service.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/x/bloctopus/forking/service.go b/x/bloctopus/forking/service.go index c2034eaf6..1c334291e 100644 --- a/x/bloctopus/forking/service.go +++ b/x/bloctopus/forking/service.go @@ -1,15 +1,19 @@ package forking -import storetypes "cosmossdk.io/core/store" +import ( + "context" + + store "cosmossdk.io/store/types" +) type forkingKVStoreService struct { - parent storetypes.KVStoreService + parent store.KVStoreService } -func NewKVStoreService(parent storetypes.KVStoreService) storetypes.KVStoreService { +func NewKVStoreService(parent store.KVStoreService) store.KVStoreService { return &forkingKVStoreService{parent: parent} } -func (s *forkingKVStoreService) OpenStore(ctx storetypes.Context) storetypes.KVStore { - return s.parent.OpenStore(ctx) +func (s *forkingKVStoreService) OpenKVStore(ctx context.Context) store.KVStore { + return s.parent.OpenKVStore(ctx) } From ca033cfe717436db990cae2a17a9dbf9c6fdcd96 Mon Sep 17 00:00:00 2001 From: Til Jordan Date: Sat, 27 Sep 2025 13:49:41 +0000 Subject: [PATCH 07/17] forking: align to cosmossdk.io/store/types KV interfaces; implement OpenKVStore(ctx) --- x/bloctopus/forking/iterator.go | 2 +- x/bloctopus/forking/service.go | 8 ++++---- x/bloctopus/forking/store.go | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/x/bloctopus/forking/iterator.go b/x/bloctopus/forking/iterator.go index 10711d680..70b84920c 100644 --- a/x/bloctopus/forking/iterator.go +++ b/x/bloctopus/forking/iterator.go @@ -1,6 +1,6 @@ package forking -import storetypes "cosmossdk.io/core/store" +import storetypes "cosmossdk.io/store/types" type MergedIterator struct { local storetypes.Iterator diff --git a/x/bloctopus/forking/service.go b/x/bloctopus/forking/service.go index 1c334291e..013416818 100644 --- a/x/bloctopus/forking/service.go +++ b/x/bloctopus/forking/service.go @@ -3,17 +3,17 @@ package forking import ( "context" - store "cosmossdk.io/store/types" + storetypes "cosmossdk.io/store/types" ) type forkingKVStoreService struct { - parent store.KVStoreService + parent storetypes.KVStoreService } -func NewKVStoreService(parent store.KVStoreService) store.KVStoreService { +func NewKVStoreService(parent storetypes.KVStoreService) storetypes.KVStoreService { return &forkingKVStoreService{parent: parent} } -func (s *forkingKVStoreService) OpenKVStore(ctx context.Context) store.KVStore { +func (s *forkingKVStoreService) OpenKVStore(ctx context.Context) storetypes.KVStore { return s.parent.OpenKVStore(ctx) } diff --git a/x/bloctopus/forking/store.go b/x/bloctopus/forking/store.go index f249b7c52..37820030e 100644 --- a/x/bloctopus/forking/store.go +++ b/x/bloctopus/forking/store.go @@ -1,6 +1,6 @@ package forking -import storetypes "cosmossdk.io/core/store" +import storetypes "cosmossdk.io/store/types" type KVStore struct { store storetypes.KVStore From 5106aeb79f092c0d999591d2dc398defac3b4884 Mon Sep 17 00:00:00 2001 From: Til Jordan Date: Sat, 27 Sep 2025 13:52:42 +0000 Subject: [PATCH 08/17] forking: use cosmossdk.io/core/store KVStoreService and OpenStore(ctx) to match SDK on til/forking --- x/bloctopus/forking/iterator.go | 2 +- x/bloctopus/forking/service.go | 6 +++--- x/bloctopus/forking/store.go | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/x/bloctopus/forking/iterator.go b/x/bloctopus/forking/iterator.go index 70b84920c..10711d680 100644 --- a/x/bloctopus/forking/iterator.go +++ b/x/bloctopus/forking/iterator.go @@ -1,6 +1,6 @@ package forking -import storetypes "cosmossdk.io/store/types" +import storetypes "cosmossdk.io/core/store" type MergedIterator struct { local storetypes.Iterator diff --git a/x/bloctopus/forking/service.go b/x/bloctopus/forking/service.go index 013416818..fa5dd0e0f 100644 --- a/x/bloctopus/forking/service.go +++ b/x/bloctopus/forking/service.go @@ -3,7 +3,7 @@ package forking import ( "context" - storetypes "cosmossdk.io/store/types" + storetypes "cosmossdk.io/core/store" ) type forkingKVStoreService struct { @@ -14,6 +14,6 @@ func NewKVStoreService(parent storetypes.KVStoreService) storetypes.KVStoreServi return &forkingKVStoreService{parent: parent} } -func (s *forkingKVStoreService) OpenKVStore(ctx context.Context) storetypes.KVStore { - return s.parent.OpenKVStore(ctx) +func (s *forkingKVStoreService) OpenStore(ctx context.Context) storetypes.KVStore { + return s.parent.OpenStore(ctx) } diff --git a/x/bloctopus/forking/store.go b/x/bloctopus/forking/store.go index 37820030e..f249b7c52 100644 --- a/x/bloctopus/forking/store.go +++ b/x/bloctopus/forking/store.go @@ -1,6 +1,6 @@ package forking -import storetypes "cosmossdk.io/store/types" +import storetypes "cosmossdk.io/core/store" type KVStore struct { store storetypes.KVStore From 474ea528070c49681207e0ede69ef8ae856647c7 Mon Sep 17 00:00:00 2001 From: Til Jordan Date: Sat, 27 Sep 2025 13:54:39 +0000 Subject: [PATCH 09/17] forking: implement store/types KVStoreService with OpenKVStore to match runtime.NewKVStoreService --- x/bloctopus/forking/service.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x/bloctopus/forking/service.go b/x/bloctopus/forking/service.go index fa5dd0e0f..013416818 100644 --- a/x/bloctopus/forking/service.go +++ b/x/bloctopus/forking/service.go @@ -3,7 +3,7 @@ package forking import ( "context" - storetypes "cosmossdk.io/core/store" + storetypes "cosmossdk.io/store/types" ) type forkingKVStoreService struct { @@ -14,6 +14,6 @@ func NewKVStoreService(parent storetypes.KVStoreService) storetypes.KVStoreServi return &forkingKVStoreService{parent: parent} } -func (s *forkingKVStoreService) OpenStore(ctx context.Context) storetypes.KVStore { - return s.parent.OpenStore(ctx) +func (s *forkingKVStoreService) OpenKVStore(ctx context.Context) storetypes.KVStore { + return s.parent.OpenKVStore(ctx) } From 4530fa1fa9bf850713384f839c34ee2537393f23 Mon Sep 17 00:00:00 2001 From: Til Jordan Date: Sat, 27 Sep 2025 13:56:55 +0000 Subject: [PATCH 10/17] forking: align KVStoreService to cosmossdk.io/core/store with OpenKVStore(ctx) --- x/bloctopus/forking/service.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/bloctopus/forking/service.go b/x/bloctopus/forking/service.go index 013416818..3a98d1436 100644 --- a/x/bloctopus/forking/service.go +++ b/x/bloctopus/forking/service.go @@ -3,7 +3,7 @@ package forking import ( "context" - storetypes "cosmossdk.io/store/types" + storetypes "cosmossdk.io/core/store" ) type forkingKVStoreService struct { From df9b4da32472215ddbe85955ecbf4c488867c8b2 Mon Sep 17 00:00:00 2001 From: Til Jordan Date: Sat, 27 Sep 2025 13:59:16 +0000 Subject: [PATCH 11/17] app: use cosmossdk.io/core/store KVStoreService for bankStoreSvc; keep store/types for keys --- app/app.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/app.go b/app/app.go index 5ff6056b8..00104e315 100644 --- a/app/app.go +++ b/app/app.go @@ -18,6 +18,7 @@ import ( "cosmossdk.io/client/v2/autocli" "cosmossdk.io/core/appmodule" "cosmossdk.io/log" + corestore "cosmossdk.io/core/store" storetypes "cosmossdk.io/store/types" "cosmossdk.io/x/upgrade" upgradekeeper "cosmossdk.io/x/upgrade/keeper" @@ -308,7 +309,7 @@ func NewChainApp( app.MsgServiceRouter(), app.AccountKeeper, ) - var bankStoreSvc storetypes.KVStoreService + var bankStoreSvc corestore.KVStoreService if cast.ToBool(appOpts.Get("fork.enabled")) { bankStoreSvc = forking.NewKVStoreService(runtime.NewKVStoreService(keys[banktypes.StoreKey])) } else { From 3df918ea7c87900f1aff9c59c7d9526c39ff0cf6 Mon Sep 17 00:00:00 2001 From: Til Jordan Date: Sat, 27 Sep 2025 14:12:33 +0000 Subject: [PATCH 12/17] forkbank: materialize denom metadata via remote fallback; app: ensure metadata on init when fork.enabled --- app/app.go | 3 +++ x/bloctopus/forkbank/keeper/keeper.go | 29 +++++++++++++++++++-------- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/app/app.go b/app/app.go index 00104e315..b9077919a 100644 --- a/app/app.go +++ b/app/app.go @@ -335,6 +335,9 @@ func NewChainApp( if err != nil { panic(err) } + sdkCtx := app.BaseApp.NewUncachedContext(true, tmproto.Header{}) + fbk.EnsureDenomMetadata(sdk.WrapSDKContext(sdkCtx)) + app.BankKeeper = fbk } diff --git a/x/bloctopus/forkbank/keeper/keeper.go b/x/bloctopus/forkbank/keeper/keeper.go index 62efeebf3..3e5c88054 100644 --- a/x/bloctopus/forkbank/keeper/keeper.go +++ b/x/bloctopus/forkbank/keeper/keeper.go @@ -57,17 +57,27 @@ func (k ForkingBankKeeper) GetDenomMetaData(ctx context.Context, denom string) ( if found { return md, true } + k.ensureDenomMetadata(ctx) + return k.BaseKeeper.GetDenomMetaData(ctx, denom) +} +func (k ForkingBankKeeper) ensureDenomMetadata(ctx context.Context) { + all := k.BaseKeeper.GetAllDenomMetaData(ctx) + if len(all) > 0 { + return + } resp, err := k.client.RemoteDenomsMetadata(ctx) - if err != nil || resp == nil { - return banktypes.Metadata{}, false + if err != nil || resp == nil || len(resp.Metadatas) == 0 { + return } for _, m := range resp.Metadatas { - if m.Base == denom { - return m, true - } + k.BaseKeeper.SetDenomMetaData(ctx, m) } - return banktypes.Metadata{}, false } +func (k ForkingBankKeeper) EnsureDenomMetadata(ctx context.Context) { + k.ensureDenomMetadata(ctx) +} + + func (k ForkingBankKeeper) GetAllDenomMetaData(ctx context.Context) []banktypes.Metadata { all := k.BaseKeeper.GetAllDenomMetaData(ctx) @@ -75,8 +85,11 @@ func (k ForkingBankKeeper) GetAllDenomMetaData(ctx context.Context) []banktypes. return all } resp, err := k.client.RemoteDenomsMetadata(ctx) - if err != nil || resp == nil { + if err != nil || resp == nil || len(resp.Metadatas) == 0 { return nil } - return resp.Metadatas + for _, m := range resp.Metadatas { + k.BaseKeeper.SetDenomMetaData(ctx, m) + } + return k.BaseKeeper.GetAllDenomMetaData(ctx) } From ab690a9d072200efb1f47e5d95000a8584233efc Mon Sep 17 00:00:00 2001 From: Til Jordan Date: Sat, 27 Sep 2025 14:18:13 +0000 Subject: [PATCH 13/17] forking KV: intercept bank DenomMetadata prefix and populate via remote TLS gRPC; wire endpoint into KVStoreService --- app/app.go | 10 +++-- x/bloctopus/forking/client.go | 41 +++++++++++++++++ x/bloctopus/forking/service.go | 10 +++-- x/bloctopus/forking/store.go | 82 ++++++++++++++++++++++++++++++++-- 4 files changed, 132 insertions(+), 11 deletions(-) create mode 100644 x/bloctopus/forking/client.go diff --git a/app/app.go b/app/app.go index b9077919a..e4615b7ab 100644 --- a/app/app.go +++ b/app/app.go @@ -311,7 +311,11 @@ func NewChainApp( ) var bankStoreSvc corestore.KVStoreService if cast.ToBool(appOpts.Get("fork.enabled")) { - bankStoreSvc = forking.NewKVStoreService(runtime.NewKVStoreService(keys[banktypes.StoreKey])) + endpoint := cast.ToString(appOpts.Get("fork.grpc")) + if endpoint == "" { + endpoint = "grpc.thor.pfc.zone:443" + } + bankStoreSvc = forking.NewKVStoreService(runtime.NewKVStoreService(keys[banktypes.StoreKey]), endpoint) } else { bankStoreSvc = runtime.NewKVStoreService(keys[banktypes.StoreKey]) } @@ -335,8 +339,8 @@ func NewChainApp( if err != nil { panic(err) } - sdkCtx := app.BaseApp.NewUncachedContext(true, tmproto.Header{}) - fbk.EnsureDenomMetadata(sdk.WrapSDKContext(sdkCtx)) + sdkCtx := app.BaseApp.NewUncachedContext(false, tmproto.Header{}) + fbk.EnsureDenomMetadata(sdkCtx) app.BankKeeper = fbk } diff --git a/x/bloctopus/forking/client.go b/x/bloctopus/forking/client.go new file mode 100644 index 000000000..f1b706c14 --- /dev/null +++ b/x/bloctopus/forking/client.go @@ -0,0 +1,41 @@ +package forking + +import ( + "context" + "crypto/tls" + + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" +) + +type RemoteClient struct { + endpoint string + conn *grpc.ClientConn + bankQ banktypes.QueryClient +} + +func NewRemoteClient(endpoint string) (*RemoteClient, error) { + creds := credentials.NewTLS(&tls.Config{ + ServerName: "grpc.thor.pfc.zone", + }) + conn, err := grpc.Dial(endpoint, grpc.WithTransportCredentials(creds)) + if err != nil { + return nil, err + } + return &RemoteClient{ + endpoint: endpoint, + conn: conn, + bankQ: banktypes.NewQueryClient(conn), + }, nil +} + +func (c *RemoteClient) Close() { + if c.conn != nil { + _ = c.conn.Close() + } +} + +func (c *RemoteClient) DenomsMetadata(ctx context.Context) (*banktypes.QueryDenomsMetadataResponse, error) { + return c.bankQ.DenomsMetadata(ctx, &banktypes.QueryDenomsMetadataRequest{}) +} diff --git a/x/bloctopus/forking/service.go b/x/bloctopus/forking/service.go index 3a98d1436..65e03aee4 100644 --- a/x/bloctopus/forking/service.go +++ b/x/bloctopus/forking/service.go @@ -7,13 +7,15 @@ import ( ) type forkingKVStoreService struct { - parent storetypes.KVStoreService + parent storetypes.KVStoreService + endpoint string } -func NewKVStoreService(parent storetypes.KVStoreService) storetypes.KVStoreService { - return &forkingKVStoreService{parent: parent} +func NewKVStoreService(parent storetypes.KVStoreService, endpoint string) storetypes.KVStoreService { + return &forkingKVStoreService{parent: parent, endpoint: endpoint} } func (s *forkingKVStoreService) OpenKVStore(ctx context.Context) storetypes.KVStore { - return s.parent.OpenKVStore(ctx) + under := s.parent.OpenKVStore(ctx) + return NewKVStore(ctx, under, s.endpoint) } diff --git a/x/bloctopus/forking/store.go b/x/bloctopus/forking/store.go index f249b7c52..ab7bdd815 100644 --- a/x/bloctopus/forking/store.go +++ b/x/bloctopus/forking/store.go @@ -1,11 +1,85 @@ package forking -import storetypes "cosmossdk.io/core/store" +import ( + "context" + + storetypes "cosmossdk.io/core/store" + "cosmossdk.io/store/prefix" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) type KVStore struct { - store storetypes.KVStore + ctx context.Context + store storetypes.KVStore + endpoint string + + metaPopulated bool +} + +func NewKVStore(ctx context.Context, store storetypes.KVStore, endpoint string) *KVStore { + return &KVStore{ctx: ctx, store: store, endpoint: endpoint} +} + +func (k *KVStore) ensureDenomMetadata() { + if k.metaPopulated { + return + } + rc, err := NewRemoteClient(k.endpoint) + if err != nil { + return + } + defer rc.Close() + resp, err := rc.DenomsMetadata(k.ctx) + if err != nil || resp == nil || len(resp.Metadatas) == 0 { + return + } + p := prefix.NewStore(k.store, banktypes.DenomMetadataPrefix) + for _, m := range resp.Metadatas { + key := []byte(m.Base) + bz, _ := banktypes.ModuleCdc().Marshal(&m) + p.Set(key, bz) + } + k.metaPopulated = true +} + +func (k *KVStore) Get(key []byte) []byte { + if len(key) > 0 && key[0] == banktypes.DenomMetadataPrefix[0] { + if v := k.store.Get(key); v == nil { + k.ensureDenomMetadata() + return k.store.Get(key) + } + } + return k.store.Get(key) +} + +func (k *KVStore) Has(key []byte) bool { + if len(key) > 0 && key[0] == banktypes.DenomMetadataPrefix[0] { + if !k.store.Has(key) { + k.ensureDenomMetadata() + return k.store.Has(key) + } + } + return k.store.Has(key) +} + +func (k *KVStore) Set(key, value []byte) { + k.store.Set(key, value) +} + +func (k *KVStore) Delete(key []byte) { + k.store.Delete(key) +} + +func (k *KVStore) Iterator(start, end []byte) storetypes.Iterator { + if len(start) > 0 && start[0] == banktypes.DenomMetadataPrefix[0] { + k.ensureDenomMetadata() + } + return k.store.Iterator(start, end) } -func NewKVStore(store storetypes.KVStore) *KVStore { - return &KVStore{store: store} +func (k *KVStore) ReverseIterator(start, end []byte) storetypes.Iterator { + if len(start) > 0 && start[0] == banktypes.DenomMetadataPrefix[0] { + k.ensureDenomMetadata() + } + return k.store.ReverseIterator(start, end) } From b145e7520dda71b8a641e42fc96f7c80d054a74f Mon Sep 17 00:00:00 2001 From: Til Jordan Date: Sat, 27 Sep 2025 14:21:01 +0000 Subject: [PATCH 14/17] forking: remove low-level KV wrapper; paginate remote DenomsMetadata; rely on keeper to materialize with proper codec --- app/app.go | 6 +---- x/bloctopus/forkbank/keeper/remote.go | 35 +++++++++++++++++++-------- x/bloctopus/forking/service.go | 10 +++----- 3 files changed, 30 insertions(+), 21 deletions(-) diff --git a/app/app.go b/app/app.go index e4615b7ab..8a076629a 100644 --- a/app/app.go +++ b/app/app.go @@ -311,11 +311,7 @@ func NewChainApp( ) var bankStoreSvc corestore.KVStoreService if cast.ToBool(appOpts.Get("fork.enabled")) { - endpoint := cast.ToString(appOpts.Get("fork.grpc")) - if endpoint == "" { - endpoint = "grpc.thor.pfc.zone:443" - } - bankStoreSvc = forking.NewKVStoreService(runtime.NewKVStoreService(keys[banktypes.StoreKey]), endpoint) + bankStoreSvc = forking.NewKVStoreService(runtime.NewKVStoreService(keys[banktypes.StoreKey])) } else { bankStoreSvc = runtime.NewKVStoreService(keys[banktypes.StoreKey]) } diff --git a/x/bloctopus/forkbank/keeper/remote.go b/x/bloctopus/forkbank/keeper/remote.go index 616827798..003b690f9 100644 --- a/x/bloctopus/forkbank/keeper/remote.go +++ b/x/bloctopus/forkbank/keeper/remote.go @@ -8,15 +8,14 @@ import ( "google.golang.org/grpc/credentials" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/cosmos/cosmos-sdk/types/query" ) type RemoteClient struct { - conn *grpc.ClientConn - bankQuery banktypes.QueryClient - denomQuery banktypes.QueryClient - endpoint string - dialed bool - tlsInsecure bool + conn *grpc.ClientConn + bankQuery banktypes.QueryClient + endpoint string + dialed bool } func NewRemoteClient(endpoint string) (*RemoteClient, error) { @@ -66,9 +65,25 @@ func (c *RemoteClient) RemoteDenomsMetadata(ctx context.Context) (*banktypes.Que if err := c.ensureConn(); err != nil { return nil, err } - resp, err := c.bankQuery.DenomsMetadata(ctx, &banktypes.QueryDenomsMetadataRequest{}) - if err != nil { - return nil, err + var all []*banktypes.Metadata + var nextKey []byte + for { + req := &banktypes.QueryDenomsMetadataRequest{ + Pagination: &query.PageRequest{ + Key: nextKey, + Limit: 500, + CountTotal: false, + }, + } + resp, err := c.bankQuery.DenomsMetadata(ctx, req) + if err != nil { + return nil, err + } + all = append(all, resp.Metadatas...) + if resp.Pagination == nil || len(resp.Pagination.NextKey) == 0 { + break + } + nextKey = resp.Pagination.NextKey } - return resp, nil + return &banktypes.QueryDenomsMetadataResponse{Metadatas: all}, nil } diff --git a/x/bloctopus/forking/service.go b/x/bloctopus/forking/service.go index 65e03aee4..3a98d1436 100644 --- a/x/bloctopus/forking/service.go +++ b/x/bloctopus/forking/service.go @@ -7,15 +7,13 @@ import ( ) type forkingKVStoreService struct { - parent storetypes.KVStoreService - endpoint string + parent storetypes.KVStoreService } -func NewKVStoreService(parent storetypes.KVStoreService, endpoint string) storetypes.KVStoreService { - return &forkingKVStoreService{parent: parent, endpoint: endpoint} +func NewKVStoreService(parent storetypes.KVStoreService) storetypes.KVStoreService { + return &forkingKVStoreService{parent: parent} } func (s *forkingKVStoreService) OpenKVStore(ctx context.Context) storetypes.KVStore { - under := s.parent.OpenKVStore(ctx) - return NewKVStore(ctx, under, s.endpoint) + return s.parent.OpenKVStore(ctx) } From 04ea941e151345137b67d10d788f57b0503c2fe2 Mon Sep 17 00:00:00 2001 From: Til Jordan Date: Sat, 27 Sep 2025 14:23:27 +0000 Subject: [PATCH 15/17] forking: exclude experimental KV store from build; fix remote metadata slice type --- x/bloctopus/forkbank/keeper/remote.go | 2 +- x/bloctopus/forking/store.go | 86 +-------------------------- 2 files changed, 3 insertions(+), 85 deletions(-) diff --git a/x/bloctopus/forkbank/keeper/remote.go b/x/bloctopus/forkbank/keeper/remote.go index 003b690f9..274f9c7e3 100644 --- a/x/bloctopus/forkbank/keeper/remote.go +++ b/x/bloctopus/forkbank/keeper/remote.go @@ -65,7 +65,7 @@ func (c *RemoteClient) RemoteDenomsMetadata(ctx context.Context) (*banktypes.Que if err := c.ensureConn(); err != nil { return nil, err } - var all []*banktypes.Metadata + var all []banktypes.Metadata var nextKey []byte for { req := &banktypes.QueryDenomsMetadataRequest{ diff --git a/x/bloctopus/forking/store.go b/x/bloctopus/forking/store.go index ab7bdd815..229ca9bc7 100644 --- a/x/bloctopus/forking/store.go +++ b/x/bloctopus/forking/store.go @@ -1,85 +1,3 @@ -package forking - -import ( - "context" - - storetypes "cosmossdk.io/core/store" - "cosmossdk.io/store/prefix" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" -) - -type KVStore struct { - ctx context.Context - store storetypes.KVStore - endpoint string - - metaPopulated bool -} - -func NewKVStore(ctx context.Context, store storetypes.KVStore, endpoint string) *KVStore { - return &KVStore{ctx: ctx, store: store, endpoint: endpoint} -} - -func (k *KVStore) ensureDenomMetadata() { - if k.metaPopulated { - return - } - rc, err := NewRemoteClient(k.endpoint) - if err != nil { - return - } - defer rc.Close() - resp, err := rc.DenomsMetadata(k.ctx) - if err != nil || resp == nil || len(resp.Metadatas) == 0 { - return - } - p := prefix.NewStore(k.store, banktypes.DenomMetadataPrefix) - for _, m := range resp.Metadatas { - key := []byte(m.Base) - bz, _ := banktypes.ModuleCdc().Marshal(&m) - p.Set(key, bz) - } - k.metaPopulated = true -} +//go:build ignore -func (k *KVStore) Get(key []byte) []byte { - if len(key) > 0 && key[0] == banktypes.DenomMetadataPrefix[0] { - if v := k.store.Get(key); v == nil { - k.ensureDenomMetadata() - return k.store.Get(key) - } - } - return k.store.Get(key) -} - -func (k *KVStore) Has(key []byte) bool { - if len(key) > 0 && key[0] == banktypes.DenomMetadataPrefix[0] { - if !k.store.Has(key) { - k.ensureDenomMetadata() - return k.store.Has(key) - } - } - return k.store.Has(key) -} - -func (k *KVStore) Set(key, value []byte) { - k.store.Set(key, value) -} - -func (k *KVStore) Delete(key []byte) { - k.store.Delete(key) -} - -func (k *KVStore) Iterator(start, end []byte) storetypes.Iterator { - if len(start) > 0 && start[0] == banktypes.DenomMetadataPrefix[0] { - k.ensureDenomMetadata() - } - return k.store.Iterator(start, end) -} - -func (k *KVStore) ReverseIterator(start, end []byte) storetypes.Iterator { - if len(start) > 0 && start[0] == banktypes.DenomMetadataPrefix[0] { - k.ensureDenomMetadata() - } - return k.store.ReverseIterator(start, end) -} +package forking From 9dae475107eb5979c9296e2bb5c23b2b98b0b513 Mon Sep 17 00:00:00 2001 From: Til Jordan Date: Sat, 27 Sep 2025 14:29:07 +0000 Subject: [PATCH 16/17] forkbank: override bank QueryServer for denom metadata via remote TLS gRPC fallback --- x/bloctopus/forkbank/keeper/keeper.go | 35 +++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/x/bloctopus/forkbank/keeper/keeper.go b/x/bloctopus/forkbank/keeper/keeper.go index 3e5c88054..57964004f 100644 --- a/x/bloctopus/forkbank/keeper/keeper.go +++ b/x/bloctopus/forkbank/keeper/keeper.go @@ -76,6 +76,41 @@ func (k ForkingBankKeeper) ensureDenomMetadata(ctx context.Context) { func (k ForkingBankKeeper) EnsureDenomMetadata(ctx context.Context) { k.ensureDenomMetadata(ctx) } +func (k ForkingBankKeeper) DenomsMetadata(c context.Context, req *banktypes.QueryDenomsMetadataRequest) (*banktypes.QueryDenomsMetadataResponse, error) { + if req == nil { + return &banktypes.QueryDenomsMetadataResponse{Metadatas: nil}, nil + } + local := k.BaseKeeper.GetAllDenomMetaData(c) + if len(local) > 0 { + return &banktypes.QueryDenomsMetadataResponse{Metadatas: local}, nil + } + resp, err := k.client.RemoteDenomsMetadata(c) + if err != nil || resp == nil { + return &banktypes.QueryDenomsMetadataResponse{Metadatas: nil}, nil + } + return resp, nil +} + +func (k ForkingBankKeeper) DenomMetadata(c context.Context, req *banktypes.QueryDenomMetadataRequest) (*banktypes.QueryDenomMetadataResponse, error) { + if req == nil { + return &banktypes.QueryDenomMetadataResponse{}, nil + } + md, found := k.BaseKeeper.GetDenomMetaData(c, req.Denom) + if found { + return &banktypes.QueryDenomMetadataResponse{Metadata: md}, nil + } + resp, err := k.client.RemoteDenomsMetadata(c) + if err != nil || resp == nil { + return &banktypes.QueryDenomMetadataResponse{}, nil + } + for _, m := range resp.Metadatas { + if m.Base == req.Denom || m.Display == req.Denom || m.Name == req.Denom || m.Description == req.Denom { + return &banktypes.QueryDenomMetadataResponse{Metadata: m}, nil + } + } + return &banktypes.QueryDenomMetadataResponse{}, nil +} + From f1175ddc117a56b972b0b53d653d3fba6955a0c2 Mon Sep 17 00:00:00 2001 From: Til Jordan Date: Sat, 27 Sep 2025 14:34:34 +0000 Subject: [PATCH 17/17] forkbank: use pointer receivers and pass *ForkingBankKeeper to bank module so QueryServer hits our overrides --- app/app.go | 2 +- x/bloctopus/forkbank/keeper/keeper.go | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/app.go b/app/app.go index 8a076629a..8665218cd 100644 --- a/app/app.go +++ b/app/app.go @@ -338,7 +338,7 @@ func NewChainApp( sdkCtx := app.BaseApp.NewUncachedContext(false, tmproto.Header{}) fbk.EnsureDenomMetadata(sdkCtx) - app.BankKeeper = fbk + app.BankKeeper = &fbk } txSigningOptions, err := tx.NewDefaultSigningOptions() diff --git a/x/bloctopus/forkbank/keeper/keeper.go b/x/bloctopus/forkbank/keeper/keeper.go index 57964004f..d48ecf262 100644 --- a/x/bloctopus/forkbank/keeper/keeper.go +++ b/x/bloctopus/forkbank/keeper/keeper.go @@ -21,7 +21,7 @@ func NewForkingBankKeeper(base bankkeeper.BaseKeeper, cfg Config) (ForkingBankKe }, nil } -func (k ForkingBankKeeper) GetAllBalances(ctx context.Context, addr sdk.AccAddress) sdk.Coins { +func (k *ForkingBankKeeper) GetAllBalances(ctx context.Context, addr sdk.AccAddress) sdk.Coins { if k.BaseKeeper.HasBalance(ctx, addr, sdk.NewCoin("rune", math.NewInt(1))) { return k.BaseKeeper.GetAllBalances(ctx, addr) } @@ -32,7 +32,7 @@ func (k ForkingBankKeeper) GetAllBalances(ctx context.Context, addr sdk.AccAddre return sdk.NewCoins(resp.Balances...) } -func (k ForkingBankKeeper) GetBalance(ctx context.Context, addr sdk.AccAddress, denom string) sdk.Coin { +func (k *ForkingBankKeeper) GetBalance(ctx context.Context, addr sdk.AccAddress, denom string) sdk.Coin { if k.BaseKeeper.HasBalance(ctx, addr, sdk.NewCoin(denom, math.NewInt(1))) { return k.BaseKeeper.GetBalance(ctx, addr, denom) } @@ -48,11 +48,11 @@ func (k ForkingBankKeeper) GetBalance(ctx context.Context, addr sdk.AccAddress, return sdk.NewCoin(denom, math.ZeroInt()) } -func (k ForkingBankKeeper) SendCoins(ctx context.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error { +func (k *ForkingBankKeeper) SendCoins(ctx context.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error { return k.BaseKeeper.SendCoins(ctx, fromAddr, toAddr, amt) } -func (k ForkingBankKeeper) GetDenomMetaData(ctx context.Context, denom string) (banktypes.Metadata, bool) { +func (k *ForkingBankKeeper) GetDenomMetaData(ctx context.Context, denom string) (banktypes.Metadata, bool) { md, found := k.BaseKeeper.GetDenomMetaData(ctx, denom) if found { return md, true @@ -60,7 +60,7 @@ func (k ForkingBankKeeper) GetDenomMetaData(ctx context.Context, denom string) ( k.ensureDenomMetadata(ctx) return k.BaseKeeper.GetDenomMetaData(ctx, denom) } -func (k ForkingBankKeeper) ensureDenomMetadata(ctx context.Context) { +func (k *ForkingBankKeeper) ensureDenomMetadata(ctx context.Context) { all := k.BaseKeeper.GetAllDenomMetaData(ctx) if len(all) > 0 { return @@ -73,10 +73,10 @@ func (k ForkingBankKeeper) ensureDenomMetadata(ctx context.Context) { k.BaseKeeper.SetDenomMetaData(ctx, m) } } -func (k ForkingBankKeeper) EnsureDenomMetadata(ctx context.Context) { +func (k *ForkingBankKeeper) EnsureDenomMetadata(ctx context.Context) { k.ensureDenomMetadata(ctx) } -func (k ForkingBankKeeper) DenomsMetadata(c context.Context, req *banktypes.QueryDenomsMetadataRequest) (*banktypes.QueryDenomsMetadataResponse, error) { +func (k *ForkingBankKeeper) DenomsMetadata(c context.Context, req *banktypes.QueryDenomsMetadataRequest) (*banktypes.QueryDenomsMetadataResponse, error) { if req == nil { return &banktypes.QueryDenomsMetadataResponse{Metadatas: nil}, nil } @@ -91,7 +91,7 @@ func (k ForkingBankKeeper) DenomsMetadata(c context.Context, req *banktypes.Quer return resp, nil } -func (k ForkingBankKeeper) DenomMetadata(c context.Context, req *banktypes.QueryDenomMetadataRequest) (*banktypes.QueryDenomMetadataResponse, error) { +func (k *ForkingBankKeeper) DenomMetadata(c context.Context, req *banktypes.QueryDenomMetadataRequest) (*banktypes.QueryDenomMetadataResponse, error) { if req == nil { return &banktypes.QueryDenomMetadataResponse{}, nil } @@ -114,7 +114,7 @@ func (k ForkingBankKeeper) DenomMetadata(c context.Context, req *banktypes.Query -func (k ForkingBankKeeper) GetAllDenomMetaData(ctx context.Context) []banktypes.Metadata { +func (k *ForkingBankKeeper) GetAllDenomMetaData(ctx context.Context) []banktypes.Metadata { all := k.BaseKeeper.GetAllDenomMetaData(ctx) if len(all) > 0 { return all