diff --git a/package.json b/package.json index 36dfc618bf7114793e8064d36b649e977f75a1b7..8a0e1a8dae14e9d86d9918ebe3d86ed7c53dfe04 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "squid", "author": "Hugo Trentesaux <hugo@trentesaux.fr>", "license": "AGPL-3.0", - "version": "0.2.8", + "version": "0.2.9", "private": true, "engines": { "node": ">=20" diff --git a/schema.graphql b/schema.graphql index 60e1aa33a8dc0e83c327548ae9007602fbdd8094..821f9ef05b6e08304501ba8991ebd1617c54cdfc 100644 --- a/schema.graphql +++ b/schema.graphql @@ -276,11 +276,14 @@ type ChangeOwnerKey @entity { "Certification" type Cert @entity { + "certification source" issuer: Identity! @index + "certification target" receiver: Identity! @index - "whether the certification is currently active or not" # helper to avoid compare expireOn to current block number + "whether the certification is currently active or not" isActive: Boolean! - "the first block number of the certification creation" # helper field to avoid looking for all CertCreation + "the first block number of the certification creation" + # (helper field to avoid looking for all CertCreation and choose the first) createdOn: Int! "the event corresponding to the first certification creation" createdIn: Event! @@ -288,8 +291,12 @@ type Cert @entity { updatedOn: Int! "the event corresponding to the last certification renewal" updatedIn: Event! - "the current expireOn value" # helper field to avoid looking for all CertRenewal and search for the last one + "the current expireOn value" + # usually this is updatedOn + certDuration *but*: + # - certs can be removed prematurely for unconfirmed or unvalidated identity + # - update can be before genesis, in this case we still need expire block after genesis expireOn: Int! + "list all events of this cert" certHistory: [CertEvent!] @derivedFrom(field: "cert") } diff --git a/src/data_handler.ts b/src/data_handler.ts index 101453bc68cd9f7d927e59dba0caa17ed6ba4947..ae2ddbd1ab87f108a9260b8b4b8eb667e5b9cce6 100644 --- a/src/data_handler.ts +++ b/src/data_handler.ts @@ -114,14 +114,14 @@ export class DataHandler { const remarkRaw = Buffer.from(remarkHex.substring(2), "hex") // convert it back to bytes const [commentType, remarkString] = getCommentType(remarkRaw) const txcomment = new TxComment({ - blockNumber: commentEvt.blockNumber, id: commentEvt.event.id, author: sender, - event: await ctx.store.getOrFail(Event, commentEvt.event!.id), remarkBytes: remarkRaw, remark: remarkString, hash: commentEvt.hash, // raw hex hash (temporary) type: commentType, + event: await ctx.store.getOrFail(Event, commentEvt.event!.id), + blockNumber: commentEvt.blockNumber, }) this.data.comments.push(txcomment) @@ -303,14 +303,14 @@ export class DataHandler { // Process certifications creations for (const c of newData.certCreation) { - const { issuerId, receiverId, createdOn, expireOn, event } = c; + const { issuerId, receiverId, blockNumber, expireOn, event } = c; // first creation of the cert let cert = await ctx.store.findOne(Cert, { relations: { issuer: true, receiver: true }, where: { issuer: { index: issuerId }, receiver: { index: receiverId } }, }); - const createdIn = await ctx.store.getOrFail(Event, event.id); + const eventObj = await ctx.store.getOrFail(Event, event.id); if (cert == null) { const issuer = await this.getIdtyByIndexOrFail(ctx, issuerId); const receiver = await this.getIdtyByIndexOrFail(ctx, receiverId); @@ -319,18 +319,18 @@ export class DataHandler { isActive: true, issuer, receiver, - createdOn, - createdIn, - updatedOn: createdOn, - updatedIn: createdIn, - expireOn, + createdOn: blockNumber, + createdIn: eventObj, + updatedOn: blockNumber, + updatedIn: eventObj, + expireOn }); // the cert has already existed, expired, and is created again // we update it accordingly } else { cert.isActive = true; - cert.updatedOn = createdOn; - cert.updatedIn = createdIn; + cert.updatedOn = blockNumber; + cert.updatedIn = eventObj; cert.expireOn = expireOn; } @@ -340,9 +340,9 @@ export class DataHandler { new CertEvent({ id: event.id, cert, - blockNumber: createdOn, eventType: EventType.Creation, - event: await ctx.store.getOrFail(Event, event.id), + event: eventObj, + blockNumber, }) ); } @@ -356,19 +356,19 @@ export class DataHandler { relations: { issuer: true, receiver: true }, where: { issuer: { index: issuerId }, receiver: { index: receiverId } }, }); - const createdIn = await ctx.store.getOrFail(Event, event.id); + const eventObj = await ctx.store.getOrFail(Event, event.id); // update expiration date cert.expireOn = expireOn; cert.updatedOn = blockNumber; - cert.updatedIn = createdIn; + cert.updatedIn = eventObj; this.data.certification.set([issuerId, receiverId], cert); this.data.certEvent.push( new CertEvent({ id: event.id, cert, - blockNumber, eventType: EventType.Renewal, - event: await ctx.store.getOrFail(Event, event.id), + event: eventObj, + blockNumber, }) ); } @@ -389,23 +389,20 @@ export class DataHandler { const { issuerId, receiverId, blockNumber, event } = c; // should never fail because cert removal can only happen on existing cert // and cert should not be removed at their creation block - const createdIn = await ctx.store.getOrFail(Event, event.id); const cert = await ctx.store.findOneOrFail(Cert, { relations: { issuer: true, receiver: true }, where: { issuer: { index: issuerId }, receiver: { index: receiverId } }, }); // update cert cert.isActive = false; - cert.expireOn = blockNumber; this.data.certification.set([issuerId, receiverId], cert); - this.data.certEvent.push( new CertEvent({ id: event.id, cert, - blockNumber, eventType: EventType.Removal, event: await ctx.store.getOrFail(Event, event.id), + blockNumber, }) ); } @@ -544,15 +541,14 @@ export class DataHandler { // Process universal dividend for (const ud of newData.universalDividend) { const { blockNumber, amount, monetaryMass, membersCount, event, timestamp } = ud; - const createdIn = await ctx.store.getOrFail(Event, event.id); this.data.universalDividend.push(new UniversalDividend({ id: event.id, - blockNumber, timestamp: timestamp, amount: BigInt(amount), monetaryMass, membersCount: Number(membersCount), - event: createdIn, + event: await ctx.store.getOrFail(Event, event.id), + blockNumber, })); } @@ -560,15 +556,14 @@ export class DataHandler { for (const udReeval of newData.udReeval) { const { blockNumber, newUdAmount, monetaryMass, membersCount, event, timestamp } = udReeval; - const createdIn = await ctx.store.getOrFail(Event, event.id); this.data.udReeval.push(new UdReeval({ id: event.id, - blockNumber, timestamp: timestamp, newUdAmount: BigInt(newUdAmount), monetaryMass, membersCount: Number(membersCount), - event: createdIn, + event: await ctx.store.getOrFail(Event, event.id), + blockNumber, })); } } diff --git a/src/genesis/genesis.ts b/src/genesis/genesis.ts index 4bf77bfb2d62bc6476446448cb5b9bb63a1d5a95..426a8ae7221d84edd40870ed686db48fb027e9fe 100644 --- a/src/genesis/genesis.ts +++ b/src/genesis/genesis.ts @@ -20,11 +20,11 @@ export async function saveGenesis(ctx: Ctx, block: Block) { const v1_to_v2 = (n: number) => v1_to_v2_height(n, last_v1_block) // converter const NOTIF_INTERVAL = 100000 // cert validity in number of v2 blocks - // const CERTVALIDITYv2 = 5259600 // 2 years in blocks = 365.25 * 24 * 60 * 60 / 6 + // const CERTVALIDITYv2 = 10519200 // 2 years in blocks = 2 * 365.25 * 24 * 60 * 60 / 6 // cert validity in number of v1 blocks // time interval of v1 blocks measured between block 0 and 729313 // 311.17641533 seconds unix2datetime(1715932132) - unix2datetime(1488987127) / 729313 - const CERTVALIDITYv1 = 101413 // 2 years in blocks = 365.25 * 24 * 60 * 60 / 311.17641533 + const CERTVALIDITYv1 = 202828 // 2 years in blocks = 2 * 365.25 * 24 * 60 * 60 / 311.17641533 // with 5 min block time (300 seconds) validity would be 105192 // negative block number to history blocks @@ -321,9 +321,6 @@ export async function saveGenesis(ctx: Ctx, block: Block) { }); certs.set(certstr, cert) } else { - // update cert - cert.updatedOn = negHeight - cert.updatedIn = fakeBlockEvents.get(negHeight)! switch (c.type) { case EventType.Creation: // TODO decide what should be the value of createdOn @@ -332,15 +329,23 @@ export async function saveGenesis(ctx: Ctx, block: Block) { cert.createdOn = negHeight cert.createdIn = fakeBlockEvents.get(negHeight)! } + // update cert in any case + cert.updatedOn = negHeight + cert.updatedIn = fakeBlockEvents.get(negHeight)! break case EventType.Renewal: // only update expiration block if it is before genesis + // otherwise, it will be known at genesis if (negExpire < 0) { cert.expireOn = negExpire } + // update cert + cert.updatedOn = negHeight + cert.updatedIn = fakeBlockEvents.get(negHeight)! break case EventType.Removal: // do not touch isActive since the genesis value is already known + // cert removal does not touch cert "updatedOn" break } } diff --git a/src/main.ts b/src/main.ts index c72a13386d17b0c48ccdbe1b8346ad66ab0ae6d4..ac45b8b1ba30fafc1b081c80909b167012c0ae41 100644 --- a/src/main.ts +++ b/src/main.ts @@ -273,6 +273,9 @@ function collectDataFromEvents(ctx: Ctx, newData: NewData) { index: evt.member, // after membership added, there is a given time to renew expireOn: evt.expireOn, + // should be equal to: + // block.header.height + + // constants.membership.membershipPeriod.v800.get(event.block), event: event, }); acc.memberCount += 1; @@ -302,6 +305,9 @@ function collectDataFromEvents(ctx: Ctx, newData: NewData) { index: evt.member, // after membership renewed, there is a given time to renew again expireOn: evt.expireOn, + // should be equal to: + // block.header.height + + // constants.membership.membershipPeriod.v800.get(event.block), event: event, }); break; @@ -312,7 +318,7 @@ function collectDataFromEvents(ctx: Ctx, newData: NewData) { newData.certCreation.push({ issuerId: evt.issuer, receiverId: evt.receiver, - createdOn: block.header.height, + blockNumber: block.header.height, expireOn: block.header.height + constants.certification.validityPeriod.v800.get(event.block), diff --git a/src/model/generated/cert.model.ts b/src/model/generated/cert.model.ts index 807f46dd6a3eac6a2a6f12bf832e42b6e15dfa72..805862edf7e148591b5c391a0bbe0597dca26e78 100644 --- a/src/model/generated/cert.model.ts +++ b/src/model/generated/cert.model.ts @@ -15,10 +15,16 @@ export class Cert { @PrimaryColumn_() id!: string + /** + * certification source + */ @Index_() @ManyToOne_(() => Identity, {nullable: true}) issuer!: Identity + /** + * certification target + */ @Index_() @ManyToOne_(() => Identity, {nullable: true}) receiver!: Identity @@ -61,6 +67,9 @@ export class Cert { @IntColumn_({nullable: false}) expireOn!: number + /** + * list all events of this cert + */ @OneToMany_(() => CertEvent, e => e.cert) certHistory!: CertEvent[] } diff --git a/src/types_custom.ts b/src/types_custom.ts index 27bfefa21e41171bdd99c654bfd0abccdc47529e..af079ac5c2e2902a0f84f2c8b35de8030c639695 100644 --- a/src/types_custom.ts +++ b/src/types_custom.ts @@ -259,16 +259,16 @@ interface CommentEvents { interface CertCreationEvent { issuerId: IdtyIndex; receiverId: IdtyIndex; - createdOn: BlockNumber; expireOn: BlockNumber; + blockNumber: BlockNumber; event: Event; } interface CertRenewalEvent { issuerId: IdtyIndex; receiverId: IdtyIndex; - blockNumber: BlockNumber; expireOn: BlockNumber; + blockNumber: BlockNumber; event: Event; }