From 070b154b273748fcc087a012009f70457b4a5d2d Mon Sep 17 00:00:00 2001 From: Mujahid Khan <106528609+mujahidkay@users.noreply.github.com> Date: Fri, 22 Nov 2024 11:38:24 +0500 Subject: [PATCH 1/5] fix(telemetry): event name typo --- packages/telemetry/src/slog-to-otel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/telemetry/src/slog-to-otel.js b/packages/telemetry/src/slog-to-otel.js index bf91db575aa..b539b7da8e4 100644 --- a/packages/telemetry/src/slog-to-otel.js +++ b/packages/telemetry/src/slog-to-otel.js @@ -976,7 +976,7 @@ export const makeSlogToOtelKit = (tracer, overrideAttrs = {}) => { spans.pop('timer-poll'); break; } - case 'cosmic-swinget-inject-kernel-upgrade-events': { + case 'cosmic-swingset-inject-kernel-upgrade-events': { spans.push('kernel-upgrade-events'); spans.pop('kernel-upgrade-events'); break; From 3988aa0f0708e367629aca30fe5d09f760ed3ef1 Mon Sep 17 00:00:00 2001 From: Usman Saleem <57341641+usmanmani1122@users.noreply.github.com> Date: Fri, 6 Dec 2024 18:20:45 +0500 Subject: [PATCH 2/5] fix(telemetry): Empty context persisted when remaining beans are negative after run finish (#10635) --- packages/telemetry/src/context-aware-slog.js | 16 ++++++++++------ .../telemetry/src/otel-context-aware-slog.js | 4 ++-- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/packages/telemetry/src/context-aware-slog.js b/packages/telemetry/src/context-aware-slog.js index 33c2739efc5..dd55f418734 100644 --- a/packages/telemetry/src/context-aware-slog.js +++ b/packages/telemetry/src/context-aware-slog.js @@ -135,9 +135,9 @@ export const makeContextualSlogProcessor = ( /** * @param {Slog} slog - * @returns {{ attributes: T & LogAttributes, body: Partial; timestamp: Slog['time'] }} + * @returns {{ attributes: T & LogAttributes, body: Partial; time: Slog['time'] }} */ - const slogProcessor = ({ monotime, time: timestamp, ...body }) => { + const slogProcessor = ({ monotime, time, ...body }) => { const finalBody = { ...body }; /** @type {{'crank.syscallNum'?: Slog['syscallNum']}} */ @@ -321,13 +321,13 @@ export const makeContextualSlogProcessor = ( const logAttributes = { ...staticContext, - 'process.uptime': monotime, ...initContext, // Optional prelude ...blockContext, // Block is the first level of execution nesting ...triggerContext, // run and trigger info is nested next ...crankContext, // Finally cranks are the last level of nesting ...replayContext, // Replay is a substitute for crank context during vat page in ...eventLogAttributes, + 'process.uptime': monotime, }; /** @@ -356,7 +356,11 @@ export const makeContextualSlogProcessor = ( // eslint-disable-next-line no-restricted-syntax case SLOG_TYPES.COSMIC_SWINGSET.RUN.FINISH: { assert(!!triggerContext); - persistContext(finalBody.remainingBeans ? {} : triggerContext); + persistContext( + finalBody.remainingBeans && finalBody.remainingBeans > 0 + ? {} + : triggerContext, + ); triggerContext = null; break; } @@ -373,9 +377,9 @@ export const makeContextualSlogProcessor = ( } return { - attributes: /** @type {T & LogAttributes} */ (logAttributes), body: finalBody, - timestamp, + attributes: /** @type {T & LogAttributes} */ (logAttributes), + time, }; }; diff --git a/packages/telemetry/src/otel-context-aware-slog.js b/packages/telemetry/src/otel-context-aware-slog.js index 51891460eba..271c13da787 100644 --- a/packages/telemetry/src/otel-context-aware-slog.js +++ b/packages/telemetry/src/otel-context-aware-slog.js @@ -82,9 +82,9 @@ export const makeSlogSender = async options => { * @param {import('./context-aware-slog.js').Slog} slog */ const slogSender = slog => { - const { timestamp, ...logRecord } = contextualSlogProcessor(slog); + const { time, ...logRecord } = contextualSlogProcessor(slog); - const [secondsStr, fractionStr] = String(timestamp).split('.'); + const [secondsStr, fractionStr] = String(time).split('.'); const seconds = parseInt(secondsStr, 10); const nanoSeconds = parseInt( (fractionStr || String(0)).padEnd(9, String(0)).slice(0, 9), From 4e2a4234d131c1a406384f45c4b921d6a4f1144d Mon Sep 17 00:00:00 2001 From: mujahidkay Date: Fri, 6 Dec 2024 08:51:53 +0500 Subject: [PATCH 3/5] chore: add dATOM brand name to DEVNET config --- packages/builders/scripts/inter-protocol/updatePriceFeeds.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builders/scripts/inter-protocol/updatePriceFeeds.js b/packages/builders/scripts/inter-protocol/updatePriceFeeds.js index 6b5f0c2e442..f5e71a6c137 100644 --- a/packages/builders/scripts/inter-protocol/updatePriceFeeds.js +++ b/packages/builders/scripts/inter-protocol/updatePriceFeeds.js @@ -32,7 +32,7 @@ const configurations = { 'agoric1qj07c7vfk3knqdral0sej7fa6eavkdn8vd8etf', // Simply Staking 'agoric10vjkvkmpp9e356xeh6qqlhrny2htyzp8hf88fk', // P2P ], - inBrandNames: ['ATOM', 'stTIA', 'stkATOM'], + inBrandNames: ['ATOM', 'stTIA', 'stkATOM', 'dATOM'], }, EMERYNET: { oracleAddresses: [ From f0bde0bda218fcf8f68a27d896db31a435beaafd Mon Sep 17 00:00:00 2001 From: Chris Hibbert Date: Wed, 4 Dec 2024 15:44:22 -0800 Subject: [PATCH 4/5] don't reschedule auction's price notifier if we already have one (#10615) ## Description It was observed, after applying upgrade 18 to EmeryNet, that a whole slew of promises resolved when a price was provided. The current belief is that `observeQuoteNotifier` will be called every auction round until a price is available, and that creates a new observer with each call that wait until a price is published, and then they all continue waiting for each successive update. This change adds an interlock, so if there's already a notifier waiting, we don't add a new one. ### Security Considerations No security implication. ### Scaling Considerations Processing about 19000 actions waiting on a notifier in EmeryNet took several hours. If we're correct that the notifiers will continue to cycle, we expect to see a similar wait for each price update on that currency. That's unsustainable. The only current theory about dropping all those actions waiting for notifiers is to kill the vat. We can't kill the priceAuthority vats that hold the notifiers, but we might be able to cleanly kill the abandoned auctioneers. ### Documentation Considerations Not needed. ### Testing Considerations Tough to test in unit tests. It's conceivable that we could recreate the situation in `a3p-integration`, though it would be hard to observe the results. ### Upgrade Considerations We probably shouldn't ship upgrade 18 with something to address this problem. --- .../inter-protocol/src/auction/auctionBook.js | 74 ++++++++++++------- 1 file changed, 49 insertions(+), 25 deletions(-) diff --git a/packages/inter-protocol/src/auction/auctionBook.js b/packages/inter-protocol/src/auction/auctionBook.js index 998cafd3eb5..a40c813b21f 100644 --- a/packages/inter-protocol/src/auction/auctionBook.js +++ b/packages/inter-protocol/src/auction/auctionBook.js @@ -118,6 +118,8 @@ export const makeOfferSpecShape = (bidBrand, collateralBrand) => { export const prepareAuctionBook = (baggage, zcf, makeRecorderKit) => { const makeScaledBidBook = prepareScaledBidBook(baggage); const makePriceBook = preparePriceBook(baggage); + // Brands that have or are making active quoteNotifier Observers + const observedBrands = new Set(); const AuctionBookStateShape = harden({ collateralBrand: M.any(), @@ -454,38 +456,59 @@ export const prepareAuctionBook = (baggage, zcf, makeRecorderKit) => { }); return state.bookDataKit.recorder.write(bookData); }, - observeQuoteNotifier() { + // Ensure that there is an observer monitoring the quoteNotifier. We + // assume that all failure modes for quoteNotifier eventually lead to + // fail or finish. + ensureQuoteNotifierObserved() { const { state, facets } = this; const { collateralBrand, bidBrand, priceAuthority } = state; + if (observedBrands.has(collateralBrand)) { + return; + } + observedBrands.add(collateralBrand); trace('observing'); - const quoteNotifier = E(priceAuthority).makeQuoteNotifier( + const quoteNotifierP = E(priceAuthority).makeQuoteNotifier( AmountMath.make(collateralBrand, QUOTE_SCALE), bidBrand, ); - void observeNotifier(quoteNotifier, { - updateState: quote => { - trace( - `BOOK notifier ${priceFrom(quote).numerator.value}/${ - priceFrom(quote).denominator.value - }`, - ); - state.updatingOracleQuote = priceFrom(quote); - }, - fail: reason => { - trace(`Failure from quoteNotifier (${reason}) setting to null`); - // lack of quote will trigger restart - state.updatingOracleQuote = null; - }, - finish: done => { - trace( - `quoteNotifier invoked finish(${done}). setting quote to null`, - ); - // lack of quote will trigger restart + + void E.when( + quoteNotifierP, + quoteNotifier => + observeNotifier(quoteNotifier, { + updateState: quote => { + trace( + `BOOK notifier ${priceFrom(quote).numerator.value}/${ + priceFrom(quote).denominator.value + }`, + ); + state.updatingOracleQuote = priceFrom(quote); + }, + fail: reason => { + trace( + `Failure from quoteNotifier (${reason}) setting to null`, + ); + // lack of quote will trigger restart + state.updatingOracleQuote = null; + observedBrands.delete(collateralBrand); + }, + finish: done => { + trace( + `quoteNotifier invoked finish(${done}). setting quote to null`, + ); + // lack of quote will trigger restart + state.updatingOracleQuote = null; + observedBrands.delete(collateralBrand); + }, + }), + e => { + trace('makeQuoteNotifier failed, resetting', e); state.updatingOracleQuote = null; + observedBrands.delete(collateralBrand); }, - }); + ); void facets.helper.publishBookData(); }, @@ -645,8 +668,9 @@ export const prepareAuctionBook = (baggage, zcf, makeRecorderKit) => { trace(`capturing oracle price `, state.updatingOracleQuote); if (!state.updatingOracleQuote) { - // if the price has feed has died, try restarting it. - facets.helper.observeQuoteNotifier(); + // if the price feed has died (or hasn't been started for this + // incarnation), (re)start it. + facets.helper.ensureQuoteNotifierObserved(); return; } @@ -750,7 +774,7 @@ export const prepareAuctionBook = (baggage, zcf, makeRecorderKit) => { const { collateralBrand, bidBrand, priceAuthority } = state; assertAllDefined({ collateralBrand, bidBrand, priceAuthority }); - facets.helper.observeQuoteNotifier(); + facets.helper.ensureQuoteNotifierObserved(); }, stateShape: AuctionBookStateShape, }, From 4292ab5b750546dd7a86f0a29a713653c3662da1 Mon Sep 17 00:00:00 2001 From: Mujahid Khan <106528609+mujahidkay@users.noreply.github.com> Date: Mon, 9 Dec 2024 11:49:05 +0500 Subject: [PATCH 5/5] chore: new non-primary upgrade name just-in-case --- golang/cosmos/app/upgrade.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/golang/cosmos/app/upgrade.go b/golang/cosmos/app/upgrade.go index 6975663ce0e..7b7c3ffda01 100644 --- a/golang/cosmos/app/upgrade.go +++ b/golang/cosmos/app/upgrade.go @@ -19,6 +19,7 @@ var upgradeNamesOfThisVersion = []string{ "agoric-upgrade-18-emerynet", "agoric-upgrade-18-basic", "agoric-upgrade-18-basic-2", + "agoric-upgrade-18-emerynet-rc3", "agoric-upgrade-18-a3p", } @@ -59,7 +60,8 @@ func isPrimaryUpgradeName(name string) bool { validUpgradeName("agoric-upgrade-18-basic"), validUpgradeName("agoric-upgrade-18-a3p"): return true - case validUpgradeName("agoric-upgrade-18-basic-2"): + case validUpgradeName("agoric-upgrade-18-basic-2"), + validUpgradeName("agoric-upgrade-18-emerynet-rc3"): return false default: panic(fmt.Errorf("unexpected upgrade name %s", validUpgradeName(name)))