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))) 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: [ 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, }, 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), 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;