Skip to content

Commit d57ada5

Browse files
committed
refactor(x/bme): add max retries
Signed-off-by: Artur Troian <troian@users.noreply.github.com>
1 parent fac91f2 commit d57ada5

File tree

10 files changed

+270
-97
lines changed

10 files changed

+270
-97
lines changed

.goreleaser.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,3 +215,11 @@ release:
215215
prerelease: auto
216216
mode: replace
217217
draft: false
218+
219+
changelog:
220+
use: github
221+
sort: asc
222+
filters:
223+
exclude:
224+
- "^docs:"
225+
- "^test:"

_run/node/price-feeder.sh

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
set -euo pipefail
1111

1212
# Configuration
13-
AKASH_CHAIN_ID="${AKASH_CHAIN_ID:=testnet-8}"
14-
AKASH_NODE="${AKASH_NODE:=https://testnetrpc.akashnet.net:443}"
13+
AKASH_CHAIN_ID="${AKASH_CHAIN_ID:=local}"
14+
#AKASH_NODE="${AKASH_NODE:=https://testnetrpc.akashnet.net:443}"
1515
AKASH_KEYRING_BACKEND="${AKASH_KEYRING_BACKEND:=test}"
16-
AKASH_FROM="${AKASH_FROM:=price-feeder}"
16+
AKASH_FROM="${AKASH_FROM:=hermes}"
1717
UPDATE_INTERVAL=10 # seconds between updates
1818

1919
# Pyth configuration
@@ -77,7 +77,7 @@ check_balance() {
7777
local balance
7878

7979
address=$(akash keys show "$AKASH_FROM" -a )
80-
balance=$(akash query bank balances "$address" -o json 2>/dev/null | jq -r '.balances[] | select(.denom=="uakt") | .amount // "0"')
80+
balance=$(akash query bank balances "$address" -o json 2>/dev/null | jq -r '.balances[] | select(.denom=="akt") | .amount // "0"')
8181

8282
if [ -z "$balance" ] || [ "$balance" -lt 100000 ]; then
8383
log "WARN" "Low balance: ${balance:-0}uakt (recommend >100000uakt for gas)"
@@ -143,6 +143,7 @@ submit_price_to_oracle() {
143143
--gas-adjustment 1.5 \
144144
--gas-prices 0.025uakt \
145145
--yes \
146+
--from="${AKASH_FROM}" \
146147
-o json 2>&1)
147148

148149
local exit_code=$?

_run/node/prop.json

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,17 @@
55
"authority": "akash10d07y265gmmuvt4z0w9aw880jnsr700jhe7z0f",
66
"params": {
77
"sources": [
8-
"akash1xcfl5u6g2yprvpr4q8j2pp5h6l5ys3nuf529qa"
8+
"akash1kwngmq9s7mfs6x7aes5t0jcm5yvmd7367jm3ke"
99
],
1010
"min_price_sources": 1,
11-
"max_price_staleness_period": "30",
12-
"twap_window": "50",
13-
"max_price_deviation_bps": "150",
11+
"max_price_staleness_period": "60s",
12+
"twap_window": "30s",
13+
"max_price_deviation_bps": "1000",
14+
"feed_contracts_params": [],
1415
"price_retention": "86400s",
1516
"prune_epoch": "hour",
16-
"max_prune_per_epoch": "1000"
17+
"max_prune_per_epoch": "1000",
18+
"max_future_time_drift": "10s"
1719
}
1820
}
1921
],

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module pkg.akt.dev/node/v2
22

3-
go 1.25.5
3+
go 1.25.9
44

55
require (
66
cosmossdk.io/api v0.9.2
@@ -48,7 +48,7 @@ require (
4848
google.golang.org/grpc v1.76.0
4949
gopkg.in/yaml.v3 v3.0.1
5050
gotest.tools/v3 v3.5.2
51-
pkg.akt.dev/go v0.2.6
51+
pkg.akt.dev/go v0.2.9
5252
pkg.akt.dev/go/cli v0.2.2
5353
pkg.akt.dev/go/sdl v0.2.0
5454
)

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3293,8 +3293,8 @@ nhooyr.io/websocket v1.8.17 h1:KEVeLJkUywCKVsnLIDlD/5gtayKp8VoCkksHCGGfT9Y=
32933293
nhooyr.io/websocket v1.8.17/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c=
32943294
pgregory.net/rapid v0.5.5 h1:jkgx1TjbQPD/feRoK+S/mXw9e1uj6WilpHrXJowi6oA=
32953295
pgregory.net/rapid v0.5.5/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04=
3296-
pkg.akt.dev/go v0.2.6 h1:QpZqFNTKu4xNwZcgit6SVJsKNhWkd0IH0Y0Lzgpco9c=
3297-
pkg.akt.dev/go v0.2.6/go.mod h1:x9Cku9yibLk4aGLTE/Yy7eEkkda0uOSRWmYwQeFw23o=
3296+
pkg.akt.dev/go v0.2.9 h1:2oU971PeW/f9UY2pBL4tmFTrsk4CvSroGlTQ38uKQjY=
3297+
pkg.akt.dev/go v0.2.9/go.mod h1:x9Cku9yibLk4aGLTE/Yy7eEkkda0uOSRWmYwQeFw23o=
32983298
pkg.akt.dev/go/cli v0.2.2 h1:PWDAAeHkVtcZ9qE76yh4IhJ2J/42ekhwSyrGWLPGi/g=
32993299
pkg.akt.dev/go/cli v0.2.2/go.mod h1:MHm9lU8hb+xQ8BX3b9c9S1pMyZKUob5tVjHXQ4T1uwU=
33003300
pkg.akt.dev/go/sdl v0.2.0 h1:hY74GjN4itV92REf8HqGt1rQDtXsruzE/iIzd/FpUB8=

make/releasing.mk

Lines changed: 27 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -60,79 +60,53 @@ install: wasmvm-libs
6060
image-minikube:
6161
eval $$(minikube docker-env) && docker-image
6262

63-
.PHONY: test-bins
64-
test-bins: wasmvm-libs build-contracts
63+
GORELEASER_ARGS := --clean
64+
65+
ifeq (,$(findstring release,$(BUILDOPTS)))
66+
GORELEASER_ARGS += --skip=publish,validate --snapshot
67+
endif
68+
69+
ifneq (,$(findstring verbose,$(BUILDOPTS)))
70+
GORELEASER_ARGS += --verbose
71+
endif
72+
73+
.PHONY: goreleaser
74+
goreleaser: wasmvm-libs build-contracts
6575
docker run \
6676
--rm \
6777
-e MOD="$(GOMOD)" \
6878
-e STABLE=$(IS_STABLE) \
6979
-e BUILD_TAGS="$(GORELEASER_TAGS)" \
7080
-e BUILD_LDFLAGS="$(GORELEASER_LDFLAGS)" \
81+
-e GITHUB_TOKEN="$(GITHUB_TOKEN)" \
82+
-e GORELEASER_CURRENT_TAG="$(RELEASE_TAG)" \
7183
-e DOCKER_IMAGE=$(RELEASE_DOCKER_IMAGE) \
72-
-e GOPATH=/go \
7384
-e GOTOOLCHAIN="$(GOTOOLCHAIN)" \
7485
-e GOWORK="$(GORELEASER_GOWORK)" \
86+
-e GOPATH=/go \
7587
-v /var/run/docker.sock:/var/run/docker.sock \
7688
-v $(GOPATH):/go \
7789
-v $(AKASH_ROOT):/go/src/$(GORELEASER_MOD_MOUNT) \
7890
-w /go/src/$(GORELEASER_MOD_MOUNT) \
7991
$(GORELEASER_IMAGE) \
80-
-f .goreleaser-test-bins.yaml \
81-
--verbose=$(GORELEASER_VERBOSE) \
82-
--clean \
83-
--skip=publish,validate \
84-
--snapshot
92+
-f "$(GORELEASER_CONFIG)" \
93+
release \
94+
$(GORELEASER_ARGS)
95+
96+
.PHONY: test-bins
97+
test-bins: GORELEASER_CONFIG=.goreleaser-test-bins.yaml
98+
test-bins: goreleaser
8599

86100
.PHONY: docker-image
87-
docker-image: wasmvm-libs build-contracts
88-
docker run \
89-
--rm \
90-
-e MOD="$(GOMOD)" \
91-
-e STABLE=$(IS_STABLE) \
92-
-e BUILD_TAGS="$(GORELEASER_TAGS)" \
93-
-e BUILD_LDFLAGS="$(GORELEASER_LDFLAGS)" \
94-
-e DOCKER_IMAGE=$(RELEASE_DOCKER_IMAGE) \
95-
-e GOPATH=/go \
96-
-e GOTOOLCHAIN="$(GOTOOLCHAIN)" \
97-
-e GOWORK="$(GORELEASER_GOWORK)" \
98-
-v /var/run/docker.sock:/var/run/docker.sock \
99-
-v $(GOPATH):/go \
100-
-v $(AKASH_ROOT):/go/src/$(GORELEASER_MOD_MOUNT) \
101-
-w /go/src/$(GORELEASER_MOD_MOUNT) \
102-
$(GORELEASER_IMAGE) \
103-
-f .goreleaser-docker.yaml \
104-
--verbose=$(GORELEASER_VERBOSE) \
105-
--clean \
106-
--skip=publish,validate \
107-
--snapshot
101+
docker-image: GORELEASER_CONFIG=.goreleaser-docker.yaml
102+
docker-image: goreleaser
108103

109104
.PHONY: gen-changelog
110105
gen-changelog: $(GIT_CHGLOG)
111106
@echo "generating changelog to .cache/changelog"
112107
./script/genchangelog.sh "$(RELEASE_TAG)" .cache/changelog.md
113108

114109
.PHONY: release
115-
release: wasmvm-libs build-contracts gen-changelog
116-
docker run \
117-
--rm \
118-
-e MOD="$(GOMOD)" \
119-
-e STABLE=$(IS_STABLE) \
120-
-e BUILD_TAGS="$(GORELEASER_TAGS)" \
121-
-e BUILD_LDFLAGS="$(GORELEASER_LDFLAGS)" \
122-
-e GITHUB_TOKEN="$(GITHUB_TOKEN)" \
123-
-e GORELEASER_CURRENT_TAG="$(RELEASE_TAG)" \
124-
-e DOCKER_IMAGE=$(RELEASE_DOCKER_IMAGE) \
125-
-e GOTOOLCHAIN="$(GOTOOLCHAIN)" \
126-
-e GOWORK="$(GORELEASER_GOWORK)" \
127-
-e GOPATH=/go \
128-
-v /var/run/docker.sock:/var/run/docker.sock \
129-
-v $(GOPATH):/go \
130-
-v $(AKASH_ROOT):/go/src/$(GORELEASER_MOD_MOUNT) \
131-
-w /go/src/$(GORELEASER_MOD_MOUNT) \
132-
$(GORELEASER_IMAGE) \
133-
-f "$(GORELEASER_CONFIG)" \
134-
release \
135-
$(GORELEASER_SKIP) \
136-
--verbose=$(GORELEASER_VERBOSE) \
137-
--clean \
138-
--release-notes=/go/src/$(GORELEASER_MOD_MOUNT)/.cache/changelog.md
110+
release: GORELEASER_CONFIG=.goreleaser.yaml
111+
release: GORELEASER_ARGS:=$(GORELEASER_ARGS) --release-notes=.cache/changelog.md
112+
release: gen-changelog goreleaser

upgrades/software/v2.1.0/upgrade.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,19 @@ func (up *upgrade) UpgradeHandler() upgradetypes.UpgradeHandler {
107107
}
108108
}
109109

110+
bparams, err := up.Keepers.Akash.Bme.GetParams(sctx)
111+
if err != nil {
112+
return toVM, fmt.Errorf("failed to get bme params: %w", err)
113+
}
114+
115+
if bparams.MaxPendingAttempts == 0 {
116+
bparams.MaxPendingAttempts = 3
117+
err = up.Keepers.Akash.Bme.SetParams(sctx, bparams)
118+
if err != nil {
119+
return toVM, fmt.Errorf("failed to set bme params: %w", err)
120+
}
121+
}
122+
110123
return toVM, err
111124
}
112125
}

x/bme/keeper/abci.go

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
sdk "github.com/cosmos/cosmos-sdk/types"
1212

1313
types "pkg.akt.dev/go/node/bme/v1"
14-
otypes "pkg.akt.dev/go/node/oracle/v2"
1514
"pkg.akt.dev/go/sdkutil"
1615
)
1716

@@ -57,18 +56,50 @@ func (k *keeper) EndBlocker(ctx context.Context) error {
5756
return false, err
5857
}
5958

60-
// Use CacheContext so that a partial failure (e.g. MintCoins succeeds
59+
// Use CacheContext so that a partial failure (e.g., MintCoins succeeds
6160
// but SendCoinsFromModuleToAccount fails) does not leave a corrupted
6261
// state. Only commit on success; on error the pending record stays
6362
// unmodified and will be retried next block.
6463
cacheCtx, writeCache := sctx.CacheContext()
6564
err = k.executeBurnMint(cacheCtx, params, id, ownerAddr, dstAddr, value.CoinsToBurn, value.DenomToMint)
6665
if err == nil {
6766
writeCache()
67+
processed++
68+
return processed >= int64(params.MaxEndblockerRecords), nil
69+
}
70+
71+
// Error path: classify and handle
72+
if isFatalBurnMintError(err) {
73+
// Fatal error: cancel immediately with specific reason
74+
cancelCtx, writeCancel := sctx.CacheContext()
75+
reason := errorToCancelReason(err)
76+
if cancelErr := k.cancelBurnMint(cancelCtx, id, ownerAddr, dstAddr, value.CoinsToBurn, value.DenomToMint, reason); cancelErr != nil {
77+
sctx.Logger().Error("failed to cancel burn/mint record", "id", id, "reason", reason, "err", cancelErr)
78+
return false, cancelErr
79+
}
80+
writeCancel()
81+
} else {
82+
// Retriable error: increment attempts
83+
value.Attempts++
84+
if value.Attempts >= params.MaxPendingAttempts {
85+
// Max attempts exceeded: cancel
86+
cancelCtx, writeCancel := sctx.CacheContext()
87+
if cancelErr := k.cancelBurnMint(cancelCtx, id, ownerAddr, dstAddr, value.CoinsToBurn, value.DenomToMint, types.BMCancelReasonMaxAttempts); cancelErr != nil {
88+
sctx.Logger().Error("failed to cancel burn/mint record after max attempts", "id", id, "attempts", value.Attempts, "err", cancelErr)
89+
return false, cancelErr
90+
}
91+
writeCancel()
92+
} else {
93+
// Still has attempts: update pending record in-place
94+
if updErr := k.ledgerPending.Set(sctx, id, value); updErr != nil {
95+
sctx.Logger().Error("failed to update pending record attempts", "id", id, "err", updErr)
96+
return false, updErr
97+
}
98+
}
6899
}
69100

70101
processed++
71-
return processed >= int64(params.MaxEndblockerRecords), err
102+
return processed >= int64(params.MaxEndblockerRecords), nil
72103
}
73104

74105
iteratePending := func(p []byte, postCondition func() error) error {
@@ -94,10 +125,7 @@ func (k *keeper) EndBlocker(ctx context.Context) error {
94125

95126
stop, err = executeMint(id, val)
96127
if err != nil {
97-
sctx.Logger().Error("processing ledger pending records ", "id", id, "err", err)
98-
if errors.Is(err, otypes.ErrPriceStalled) {
99-
return err
100-
}
128+
sctx.Logger().Error("processing ledger pending records", "id", id, "err", err)
101129
}
102130
}
103131

0 commit comments

Comments
 (0)