Skip to content

Commit

Permalink
fix(core): handle skipped testnet eras when configured for auto-upgrade
Browse files Browse the repository at this point in the history
It's possible to configure when particular eras are upgraded, without an upgrade proposal, in
testnet cardano-node configuration, including the specification of multiple eras in the same
epoch. Era summaries therefore need to be filtered to remove eras that are being skipped,
which is evidenced by a later era starting in the same slot.
  • Loading branch information
iadmytro authored and rhyslbw committed Sep 5, 2022
1 parent b5b2512 commit 47fe7c1
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 2 deletions.
11 changes: 9 additions & 2 deletions packages/core/src/util/slotCalc.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { CardanoNetworkMagic, EpochNo, Slot } from '../Cardano';
import { CustomError } from 'ts-custom-error';
import { EraSummary } from '../CardanoNode';
import groupBy from 'lodash/groupBy';
import last from 'lodash/last';
import orderBy from 'lodash/orderBy';

export interface SlotDate {
Expand All @@ -17,7 +19,7 @@ export interface EpochInfo {
export class EraSummaryError extends CustomError {}

/**
* Were valid at 2022-05-28
* Valid at 2022-05-28
*/
export const mainnetEraSummaries: EraSummary[] = [
{ parameters: { epochLength: 21_600, slotLength: 20_000 }, start: { slot: 0, time: new Date(1_506_192_291_000) } },
Expand All @@ -43,7 +45,12 @@ export const eraSummariesConfig: EraSummariesMap = {
};

const createSlotEpochCalcImpl = (eraSummaries: EraSummary[]) => {
const eraSummariesAsc = orderBy(eraSummaries, ({ start }) => start.slot);
// It's possible to configure when particular eras are upgraded, without an upgrade proposal, in
// testnet cardano-node configuration, including the specification of multiple eras in the same
// epoch. Era summaries therefore need to be filtered to remove eras that are being skipped,
// which is evidenced by a later era starting in the same slot.
const eraSummariesWithoutSkippedEras = Object.values(groupBy(eraSummaries, 'start.slot')).map(last) as EraSummary[];
const eraSummariesAsc = orderBy(eraSummariesWithoutSkippedEras, ({ start }) => start.slot);
return (slotNo: Slot) => {
const relevantEraSummariesAsc = orderBy(
eraSummariesAsc.filter(({ start }) => start.slot <= slotNo),
Expand Down
34 changes: 34 additions & 0 deletions packages/core/test/util/slotCalc.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,40 @@ describe('slotCalc utils', () => {
});

describe('slotEpochCalc', () => {
describe('testnet with auto-upgrading eras', () => {
it('correctly computes epoch with multiple summaries starting from genesis', () => {
const eraSummaries: EraSummary[] = [
{
parameters: { epochLength: 100, slotLength: 3 },
start: { slot: 0, time: new Date(1_563_999_616_000) }
},
{ parameters: { epochLength: 200, slotLength: 10 }, start: { slot: 0, time: new Date(1_563_999_616_000) } },
{ parameters: { epochLength: 200, slotLength: 1 }, start: { slot: 0, time: new Date(1_563_999_616_000) } }
];
const slotEpochCalc: SlotEpochCalc = createSlotEpochCalc(eraSummaries);

expect(slotEpochCalc(1031)).toEqual(5);
});
it('correctly computes epoch with summaries indicating an upgrade after genesis, from the same slotNo', () => {
const eraSummaries: EraSummary[] = [
{
parameters: { epochLength: 100, slotLength: 3 },
start: { slot: 0, time: new Date(1_563_999_616_000) }
},
{
parameters: { epochLength: 200, slotLength: 10 },
start: { slot: 301, time: new Date(1_563_999_716_000) }
},
{
parameters: { epochLength: 200, slotLength: 1 },
start: { slot: 301, time: new Date(1_563_999_716_000) }
}
];
const slotEpochCalc: SlotEpochCalc = createSlotEpochCalc(eraSummaries);

expect(slotEpochCalc(1031)).toEqual(6);
});
});
describe('testnet', () => {
const slotEpochCalc: SlotEpochCalc = createSlotEpochCalc(testnetEraSummaries);

Expand Down

0 comments on commit 47fe7c1

Please sign in to comment.