Skip to content

CIP 0104: Traffic Weighted App Rewards: Serve App Activity Records and Traffic Summarys from /v0/events#4154

Open
adetokunbo wants to merge 22 commits intohyperledger-labs:dfordivam/adetokunbo/cip-0104-composite-ingestionfrom
obsidiansystems:adetokunbo/cip-0104-serve-other-info-in-events-api
Open

CIP 0104: Traffic Weighted App Rewards: Serve App Activity Records and Traffic Summarys from /v0/events#4154
adetokunbo wants to merge 22 commits intohyperledger-labs:dfordivam/adetokunbo/cip-0104-composite-ingestionfrom
obsidiansystems:adetokunbo/cip-0104-serve-other-info-in-events-api

Conversation

@adetokunbo
Copy link
Contributor

Follows-up from #4037

N.B. #4037 is not yet merged, so this contains all it's commits. It will be submitted before this one is, in the meantime please review the latest commits on this PR

Pull Request Checklist

Cluster Testing

  • If a cluster test is required, comment /cluster_test on this PR to request it, and ping someone with access to the DA-internal system to approve it.
  • If a hard-migration test is required (from the latest release), comment /hdm_test on this PR to request it, and ping someone with access to the DA-internal system to approve it.

PR Guidelines

  • Include any change that might be observable by our partners or affect their deployment in the release notes.
  • Specify fixed issues with Fixes #n, and mention issues worked on using #n
  • Include a screenshot for frontend-related PRs - see README or use your favorite screenshot tool

Merge Guidelines

  • Make the git commit message look sensible when squash-merging on GitHub (most likely: just copy your PR description).

Tim Emiola and others added 10 commits February 26, 2026 03:24
Signed-off-by: Tim Emiola <adetokunbo@emio.la>
Signed-off-by: Tim Emiola <adetokunbo@emio.la>
Signed-off-by: Tim Emiola <adetokunbo@emio.la>
Signed-off-by: Tim Emiola <adetokunbo@emio.la>
Co-authored-by: Divam <681060+dfordivam@users.noreply.github.com>
Signed-off-by: Timothy Emiola <adetokunbo@users.noreply.github.com>
Co-authored-by: Divam <681060+dfordivam@users.noreply.github.com>
Signed-off-by: Timothy Emiola <adetokunbo@users.noreply.github.com>
Co-authored-by: Divam <681060+dfordivam@users.noreply.github.com>
Signed-off-by: Timothy Emiola <adetokunbo@users.noreply.github.com>
Signed-off-by: Tim Emiola <adetokunbo@emio.la>
Signed-off-by: Tim Emiola <adetokunbo@emio.la>
Co-authored-by: Divam <681060+dfordivam@users.noreply.github.com>
Signed-off-by: Timothy Emiola <adetokunbo@users.noreply.github.com>
@dfordivam dfordivam changed the base branch from dfordivam/feat-cip-104-activity-records to dfordivam/adetokunbo/cip-0104-composite-ingestion February 26, 2026 06:14
@dfordivam dfordivam self-requested a review February 26, 2026 06:18
Copy link
Contributor

@dfordivam dfordivam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we possibly also need to add two "enable" flags in request, and disable serving these by default with events

description: |
Computed app activity record derived from verdicts and traffic summaries.
Each record represents the traffic-weighted activity of featured app providers at a given record_time,
and is derived from a computation involving the verdict and traffic summary data.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could mention CIP-0104 here

Copy link
Contributor Author

@adetokunbo adetokunbo Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possible, but at the moment it does not look like a CIP number is mentioned in any other open API descriptions, so this would be the first

- total_traffic_cost
- envelope_traffic_costs
properties:
sequencing_time:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if we really need to include this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neither am I. @meiersi-da should we replicate fields like sequencing time, and in the activity record record time that can be obtained from the verdict ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think sequencing_time is special. It serves as the primary key for the events themselves. The right place might be to serve it on the EventHistoryItem itself.

That said: I'm not sure. It really depends on the access patterns that we want to make easily possible. Let's have a quick chat in our sync meeting.

.map(toUpdateV2)
val verdictEncoded = verdictWithViewsO.map { case (v, views) =>
ScanHttpEncodings.encodeVerdict(v, views)
items <- Future.traverse(events) { case (verdictWithViewsO, updateO) =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about doing a batch read of activity records?
Given that the activity records are also being provided by the ScanEventStore, modifying the getEvents may be better?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Signed-off-by: Tim Emiola <adetokunbo@emio.la>
@adetokunbo
Copy link
Contributor Author

we possibly also need to add two "enable" flags in request, and disable serving these by default with events

These have been added.

Signed-off-by: Tim Emiola <adetokunbo@emio.la>
If an event pertains to a contract reassignment, there will be no verdict data.
If an event pertains to a wholly private transaction, there will only be verdict data.
If an event pertains to a transaction that is partially private, it may also bear verdict information for the private portions.
When both fields are present, the transaction and verdict have the same `update_id` and `record_time`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update this comment as well wrt traffic summaries and activity records.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Copy link
Contributor

@meiersi-da meiersi-da left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Did a quick review of the API parts only as prep for our meeting.

items:
type: integer
format: int32
EventHistoryAppActivityRecord:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
EventHistoryAppActivityRecord:
EventHistoryAppActivityRecords:

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

properties:
record_time:
description: |
The record_time (= sequencing_time) of the verdict/traffic summary.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, OK. This hints very much at pushing the sequencing_time of the confirmation request to the top-level.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, as discussed in the meeting

format: int64
entries:
description: |
App activity entries, one per featured app provider.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
App activity entries, one per featured app provider.
App activity entries, one per app provider.

we'll want this API to also work when we start to support unfeatured app providers: https://github.com/canton-foundation/cips/blob/main/cip-0104/cip-0104.md#rewards-for-unfeatured-apps

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, and in 2 other locations in the change.

Comment on lines +3913 to +3915
Computed app activity record derived from verdicts and traffic summaries.
Each record represents the traffic-weighted activity of featured app providers at a given record_time,
and is derived from a computation involving the verdict and traffic summary data.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Computed app activity record derived from verdicts and traffic summaries.
Each record represents the traffic-weighted activity of featured app providers at a given record_time,
and is derived from a computation involving the verdict and traffic summary data.
App activity record compted from verdicts and traffic summaries
as per [CIP-104](https://github.com/canton-foundation/cips/blob/main/cip-0104/cip-0104.md).

Minimize specificity to make the API hold up when we evolve rewards further. Referring to CIP-104 seems fine though, as we can just replace it with a reference to the new CIP that changes it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

adetokunbo and others added 3 commits February 26, 2026 16:36
Co-authored-by: Simon Meier <simon@digitalasset.com>
Signed-off-by: Timothy Emiola <adetokunbo@users.noreply.github.com>
Signed-off-by: Tim Emiola <adetokunbo@emio.la>
Signed-off-by: Tim Emiola <adetokunbo@emio.la>
Tim Emiola added 3 commits February 26, 2026 07:50
Signed-off-by: Tim Emiola <adetokunbo@emio.la>
Signed-off-by: Tim Emiola <adetokunbo@emio.la>
Signed-off-by: Tim Emiola <adetokunbo@emio.la>
@adetokunbo
Copy link
Contributor Author

@meiersi-da PTAL, the outstanding comments should all be addressed, and I also removed duplicate fields as discussed earlier

Copy link
Contributor

@meiersi-da meiersi-da left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Looks good. Looking forward to seeing this code pass an integration test.

If an event pertains to a wholly private transaction, there will only be verdict data.
If an event pertains to a transaction that is partially private, it may also bear verdict information for the private portions.
When both fields are present, the transaction and verdict have the same `update_id` and `record_time`.
A traffic summary is present when sequencer traffic cost data is available for the verdict's confirmation request.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
A traffic summary is present when sequencer traffic cost data is available for the verdict's confirmation request.
**Experimental**: for networks where the SVs enable activity record
computation, a traffic summary and app activity record are present when
a verdict is present.
This support is experimental while the preview phase of CIP-104
is running.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know we internally have a finer grained configuration. I'd not communicate this as the intention is to enable both of them at all times, but we might disable one of them in case of problems. No need for users to care about the exceptional circumstance.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Comment on lines +3730 to +3731
An app activity record is present when the verdict is successful and involves app providers.
When present, both the traffic summary and app activity record correspond to the verdict's record_time.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
An app activity record is present when the verdict is successful and involves app providers.
When present, both the traffic summary and app activity record correspond to the verdict's record_time.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

**EXPERIMENTAL**: This property is experimental and subject to change. Data may be incomplete or missing.
$ref: "#/components/schemas/EventHistoryTrafficSummary"
nullable: true
app_activity_record:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
app_activity_record:
app_activity_records:

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

properties:
round_number:
description: |
The round number assigned to the activity record.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The round number assigned to the activity record.
The round number assigned to the activity records.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

as per [CIP-104](https://github.com/canton-foundation/cips/blob/main/cip-0104/cip-0104.md).
required:
- round_number
- entries
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- entries
- records

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here and in related names

reason for using record is whitepaper, page 12 scoping an activity record to a single app

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

type: array
items:
$ref: "#/components/schemas/AppActivityEntry"
AppActivityEntry:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
AppActivityEntry:
AppActivityRecord:

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

AppActivityEntry:
type: object
description: |
A single app provider's activity weight.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
A single app provider's activity weight.
Activity record for an app.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

)(implicit tc: TraceContext): Future[Map[CantonTimestamp, AppActivityRecordT]] = {
if (recordTimes.isEmpty) Future.successful(Map.empty)
else {
val inClause = sqlCommaSeparated(recordTimes.map(rt => sql"$rt"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rautenrieth-da : what is our guidance of using in-clauses with many parameters, vs using ANY(array)? AFAIR, the latter has lower query parsing overhead, and better planner cache hits...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. I updated this to ANY(array) via the inClause function. Details in f61dbcd

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Using the inClause() helper is definitely the right thing to do here.

Tim Emiola added 4 commits February 26, 2026 12:02
Signed-off-by: Tim Emiola <adetokunbo@emio.la>
Signed-off-by: Tim Emiola <adetokunbo@emio.la>
Signed-off-by: Tim Emiola <adetokunbo@emio.la>
- needed to add an implicit for setting arrays of timestamps to AcsJdbcTypes

Signed-off-by: Tim Emiola <adetokunbo@emio.la>
@adetokunbo adetokunbo force-pushed the adetokunbo/cip-0104-serve-other-info-in-events-api branch from f61dbcd to d0879d7 Compare March 2, 2026 04:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants