Skip to content

Forwarder #1179

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 34 commits into
base: develop
Choose a base branch
from
Open

Forwarder #1179

wants to merge 34 commits into from

Conversation

augustbleeds
Copy link
Contributor

@augustbleeds augustbleeds commented Apr 10, 2025

Description

Design of forwarder based off of #614

EDIT: please see the committed README.md docs for more info

instructions:

  • initialize: creates a new forwarder state, and precomputes the bump for the forwarder authority pda which signs the CPI to the receiver
  • transfer/accept_ownership: self-explanatory
  • init/update/close_oracles_config: oracle configs (which are called oracle sets in EVM) are stored as separate data accounts since a new config version / config_id with the same DON would create a new oracle config so the size is unbounded (as opposed to finding a soft-limit on the new dons that are created)
  • report: processes the report which is of format data = bump | len_signatures (N) | signatures (N*65) | raw_report (M) | report_context (96). A report will create a new execution_state pda data account if doesn't exist via create_account instruction. It executes a CPI to a receiver program where the forwarder authority pda is the signer.

Requires Dependencies

Resolves Dependencies


use super::*;

pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Curious about what steps we need to perform for deployment. Is it

  1. Deploy the program.
  2. Initialize (can we do it as part of the deployment transaction?)
  3. Init oracles config
  4. Transfer ownership to MCMS
  5. Accept ownership on MCMS

#[account]
#[derive(Default)]
#[derive(InitSpace)]
pub struct ExecutionState {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I wonder how we can verify if the report was forwarded on the WriteTarget 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.

can you elaborate on the scenario? we can add an event to the report function which you can listen to or you can query the execution status account associated with the transmission

pub struct OraclesConfig {
config_id: u64,
f: u8,
signer_addresses: Vec<EthAddress>, // maybe think about doing ECDSA over ed25519?
Copy link
Collaborator

Choose a reason for hiding this comment

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

Personally I'd use a constant size array plus a length int and make the type zero_copy

Copy link
Contributor Author

Choose a reason for hiding this comment

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

let data = &data[2..];
let _signatures = &data[..65*len];
let data = &data[65*len..];
let _report_context = &data[data.len()-96..];
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think it would make more sense to have the report context before the report

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I kept it this way because the existing solana keyring assumes the report context comes after https://github.com/smartcontractkit/chainlink/blob/develop/core/services/keystore/keys/ocr2key/solana_keyring.go#L38 . But open to changing it as well.

We should be using ocr2 signatures, not ocr3 right?

prev_signer = curr_signer;
}

oracles_config.config_id = ((don_id as u64) << 32) | (config_version as u64);
Copy link
Collaborator

Choose a reason for hiding this comment

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

This should use get_config_id

Copy link
Collaborator

Choose a reason for hiding this comment

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

agreed

}

fn get_config_id(don_id: u32, config_version: u32) -> u64 {
((don_id as u64) << 32) | (config_version as u64)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Config id could technically just be a struct with two u32 fields, it would have the same underlying size

* Adding events to forwader contract

* README update for nix test

* Revision 1

* rust lint

* removed unnecc

* nits
@cl-sonarqube-production
Copy link

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.

6 participants