Skip to content

TrustChain On-Chain Integrity Protocol#12

Open
Freedomwithin wants to merge 1 commit into
fairscale-integrationfrom
feature/on-chain-notary-13705485681884725483
Open

TrustChain On-Chain Integrity Protocol#12
Freedomwithin wants to merge 1 commit into
fairscale-integrationfrom
feature/on-chain-notary-13705485681884725483

Conversation

@Freedomwithin

@Freedomwithin Freedomwithin commented Feb 14, 2026

Copy link
Copy Markdown
Owner

Transition TrustChain to an On-Chain Integrity Protocol.

Changes:

  1. Anchor Program: Initialized in on-chain/trustchain-notary. Defines UserIntegrity account (gini_score, hhi_score, status) and update_integrity instruction. Enforces access control using a hardcoded Notary Public Key.
  2. Backend Service: Added backend/services/notary_sync.ts to simulate fetching verified scores and signing transactions. Implements Ed25519 signature verification to ensure authenticity.
  3. Security:
    • Loads Notary Secret from NOTARY_SECRET environment variable (added .env.example).
    • On-chain program verifies the signer matches the authorized Notary.
    • Added padding to on-chain account structure for future upgrades.
  4. Dependencies: Added @coral-xyz/anchor and tweetnacl to backend.

PR created automatically by Jules for task 13705485681884725483 started by @Freedomwithin

Summary by Sourcery

Introduce an on-chain TrustChain notary program and a backend notary sync service to record and authorize user integrity scores on Solana.

New Features:

  • Add a Solana Anchor program that maintains per-user integrity accounts with scores and status, updatable only by an authorized notary.
  • Add a backend notary sync script that fetches verified integrity scores and constructs signed transactions to update on-chain PDAs.

Enhancements:

  • Enforce notary-based access control on-chain using a hardcoded notary public key and dedicated error type for unauthorized signers.
  • Implement explicit Ed25519 signature verification in the backend to ensure that only the notary keypair authorizes integrity updates.

Build:

  • Add Anchor and TweetNaCl dependencies to the backend and define a package script to run the notary sync job.
  • Introduce a new on-chain workspace and program configuration for the trustchain-notary Anchor project.

Chores:

  • Add a backend .env example to document the NOTARY_SECRET configuration for the notary keypair.

- Initialize Anchor project in `on-chain/trustchain-notary`
- Implement `UserIntegrity` account and `update_integrity` instruction with Notary access control
- Create `backend/services/notary_sync.ts` for signing and verifying updates
- Add `sync:notary` script and dependencies to backend
- Secure secret management via environment variables

Co-authored-by: Freedomwithin <166790647+Freedomwithin@users.noreply.github.com>
@google-labs-jules

Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@vercel

vercel Bot commented Feb 14, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
trust-chain-backend Ready Ready Preview, Comment Feb 14, 2026 8:56am
trust-chain-frontend Ready Ready Preview, Comment Feb 14, 2026 8:56am

@sourcery-ai

sourcery-ai Bot commented Feb 14, 2026

Copy link
Copy Markdown

Reviewer's Guide

Implements a new on-chain TrustChain notary program using Anchor, plus a backend notary sync service that derives the PDA, encodes the integrity update instruction, signs and verifies transactions with an env-configured notary key, and wires the necessary dependencies and configuration.

Sequence diagram for backend notary sync updating on-chain integrity

sequenceDiagram
    actor Operator
    participant NotarySyncService
    participant IntegrityEngine
    participant SolanaRPC
    participant TrustchainNotaryProgram
    participant UserIntegrityAccount

    Operator->>NotarySyncService: run sync:notary
    NotarySyncService->>NotarySyncService: load NOTARY_SECRET
    NotarySyncService->>IntegrityEngine: fetchVerifiedScore(wallet)
    IntegrityEngine-->>NotarySyncService: IntegrityScore(gini,hhi,status)

    NotarySyncService->>NotarySyncService: derive PDA with seeds [b("integrity"), wallet]
    NotarySyncService->>NotarySyncService: build update_integrity instruction data
    NotarySyncService->>SolanaRPC: getLatestBlockhash()
    SolanaRPC-->>NotarySyncService: blockhash
    NotarySyncService->>NotarySyncService: construct Transaction
    NotarySyncService->>NotarySyncService: sign with NOTARY_KEYPAIR

    NotarySyncService->>NotarySyncService: transaction.verifySignatures()
    NotarySyncService->>NotarySyncService: nacl.sign.detached.verify(message, signature, notary_pubkey)

    NotarySyncService->>SolanaRPC: sendTransaction(transaction)  
    SolanaRPC->>TrustchainNotaryProgram: invoke update_integrity
    TrustchainNotaryProgram->>TrustchainNotaryProgram: check notary signer == NOTARY_PUBKEY
    TrustchainNotaryProgram->>UserIntegrityAccount: init_if_needed and update fields
    TrustchainNotaryProgram-->>SolanaRPC: success
    SolanaRPC-->>NotarySyncService: transaction confirmation
Loading

Updated class diagram for TrustChain notary program and notary sync service

classDiagram
    class trustchain_notary_program {
        <<program>>
        +update_integrity(ctx: UpdateIntegrity, gini_score: u16, hhi_score: u16, status: u8) Result
    }

    class UpdateIntegrity {
        +user_integrity: UserIntegrity
        +user: UncheckedAccount
        +notary: Signer
        +system_program: System
    }

    class UserIntegrity {
        +gini_score: u16
        +hhi_score: u16
        +status: u8
        +last_updated: i64
    }

    class TrustChainError {
        <<enum>>
        +UnauthorizedNotary
    }

    class IntegrityScore {
        +gini: number
        +hhi: number
        +status: string
    }

    class NotarySyncService {
        +MOCK_WALLET: PublicKey
        +NOTARY_KEYPAIR: Keypair
        +PROGRAM_ID: PublicKey
        +fetchVerifiedScore(wallet: PublicKey) Promise~IntegrityScore~
        +updateOnChainPDA(wallet: PublicKey, score: IntegrityScore) Promise~void~
        +main() Promise~void~
    }

    class EnvConfig {
        +NOTARY_SECRET: string
        +loadNotarySecret() Uint8Array
    }

    class SolanaConnection {
        +getLatestBlockhash() Promise
        +sendTransaction(transaction: Transaction) Promise
    }

    class TransactionBuilder {
        +derivePDA(wallet: PublicKey, programId: PublicKey) PublicKey
        +buildUpdateIntegrityData(gini: number, hhi: number, status: string) Buffer
        +buildInstruction(pda: PublicKey, wallet: PublicKey, notaryPubkey: PublicKey, programId: PublicKey, data: Buffer) TransactionInstruction
        +signAndVerify(transaction: Transaction, notaryKeypair: Keypair) boolean
    }

    trustchain_notary_program --> UpdateIntegrity
    UpdateIntegrity --> UserIntegrity
    trustchain_notary_program --> TrustChainError

    NotarySyncService --> IntegrityScore
    NotarySyncService --> SolanaConnection
    NotarySyncService --> TransactionBuilder
    NotarySyncService --> EnvConfig

    TransactionBuilder --> UserIntegrity
    EnvConfig --> NotarySyncService
Loading

File-Level Changes

Change Details Files
Introduce an Anchor-based TrustChain notary Solana program that stores per-user integrity scores and restricts updates to a hardcoded notary signer.
  • Declare the trustchain-notary program ID and a constant authorized notary public key.
  • Implement update_integrity instruction that writes gini, hhi, status, and last_updated to a UserIntegrity account.
  • Define UpdateIntegrity accounts context with a PDA-backed user_integrity account, unchecked user address, notary signer, and system program, including padded space for future upgrades.
  • Add UserIntegrity account struct and a custom UnauthorizedNotary error code.
on-chain/trustchain-notary/programs/trustchain-notary/src/lib.rs
Set up the on-chain workspace configuration for the new Anchor program.
  • Create program Cargo.toml defining crate metadata, features, and anchor-lang dependency.
  • Add root Cargo.toml workspace that includes the trustchain-notary program and sets release profile optimizations.
  • Define Anchor.toml with program ID mapping, provider config, and test script placeholder.
on-chain/trustchain-notary/programs/trustchain-notary/Cargo.toml
on-chain/trustchain-notary/Cargo.toml
on-chain/trustchain-notary/Anchor.toml
Add a backend notary_sync service that fetches integrity scores, constructs and signs an update_integrity transaction, and verifies the notary signature using Ed25519.
  • Load NOTARY_SECRET from the environment, supporting both JSON array and hex-encoded secret key formats, and derive the notary Keypair.
  • Mock retrieval of a verified integrity score and a user wallet, then derive the PDA for the user_integrity account with the same seeds as the on-chain program.
  • Compute the Anchor instruction discriminator for global:update_integrity, encode gini/hhi as scaled u16 and status as u8, and build the TransactionInstruction with correct accounts and program ID.
  • Construct and sign a transaction with the notary key, attempt to fetch a recent blockhash (with a mock fallback), and verify signatures via both web3.js and tweetnacl before logging success or failing on invalid signatures.
  • Wrap the flow in a main() function that runs the sync and exits with errors on failure.
backend/services/notary_sync.ts
Wire backend tooling and configuration needed for notary sync and Anchor usage.
  • Add sync:notary npm script to run the notary_sync TypeScript service via tsx.
  • Introduce @coral-xyz/anchor and tweetnacl as backend dependencies to support Anchor-style encoding and Ed25519 verification.
  • Create an empty .env.example to document environment-based configuration such as NOTARY_SECRET.
backend/package.json
backend/.env.example

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've found 3 issues, and left some high level feedback:

  • Loading and validating NOTARY_SECRET at module top-level will throw as soon as the file is imported; consider moving this parsing/validation into main() (or a dedicated init function) so that other code can import notary_sync.ts without crashing when the env var is missing or misconfigured.
  • When parsing NOTARY_SECRET into notarySecret, it would be safer to assert the expected length (e.g., 64-byte Ed25519 secret key) and error with a clear message if it doesn't match, to avoid subtle misconfigurations being accepted.
  • The Connection in updateOnChainPDA is hardcoded to https://api.devnet.solana.com; consider sourcing the RPC endpoint and commitment level from configuration (e.g., env vars) so this script can be reused across clusters/environments without code changes.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Loading and validating `NOTARY_SECRET` at module top-level will throw as soon as the file is imported; consider moving this parsing/validation into `main()` (or a dedicated init function) so that other code can import `notary_sync.ts` without crashing when the env var is missing or misconfigured.
- When parsing `NOTARY_SECRET` into `notarySecret`, it would be safer to assert the expected length (e.g., 64-byte Ed25519 secret key) and error with a clear message if it doesn't match, to avoid subtle misconfigurations being accepted.
- The `Connection` in `updateOnChainPDA` is hardcoded to `https://api.devnet.solana.com`; consider sourcing the RPC endpoint and commitment level from configuration (e.g., env vars) so this script can be reused across clusters/environments without code changes.

## Individual Comments

### Comment 1
<location> `backend/services/notary_sync.ts:67` </location>
<code_context>
+
+async function updateOnChainPDA(wallet: PublicKey, score: IntegrityScore) {
+  // Connect to devnet (or localnet)
+  const connection = new Connection("https://api.devnet.solana.com", "confirmed");
+
+  // PDA derivation: seeds = [b"integrity", user.key().as_ref()]
</code_context>

<issue_to_address>
**suggestion:** Hardcoding the devnet RPC URL reduces flexibility across environments.

This ties the function to a single devnet endpoint and commitment. Consider reading the RPC URL (and optionally commitment) from an environment variable with a reasonable default so the same code can be used across devnet, localnet, mainnet, or other providers without code changes.

Suggested implementation:

```typescript
async function updateOnChainPDA(wallet: PublicKey, score: IntegrityScore) {
  // Connect to Solana RPC (configurable via env; defaults to devnet)
  const rpcUrl =
    process.env.SOLANA_RPC_URL ?? "https://api.devnet.solana.com";
  const commitment =
    (process.env.SOLANA_COMMITMENT as Commitment | undefined) ?? "confirmed";
  const connection = new Connection(rpcUrl, commitment);

```

1. Ensure `Commitment` is imported from `@solana/web3.js` at the top of `backend/services/notary_sync.ts`, e.g.:
   `import { Connection, PublicKey, Commitment } from "@solana/web3.js";`
2. Optionally document the new environment variables (`SOLANA_RPC_URL`, `SOLANA_COMMITMENT`) in your configuration / README so deployments know how to target devnet, localnet, or mainnet without code changes.
</issue_to_address>

### Comment 2
<location> `backend/services/notary_sync.ts:121-123` </location>
<code_context>
+  try {
+      const { blockhash } = await connection.getLatestBlockhash();
+      transaction.recentBlockhash = blockhash;
+  } catch (err) {
+      console.warn("Could not fetch blockhash (network issue?), using mock blockhash for simulation.");
+      transaction.recentBlockhash = Keypair.generate().publicKey.toBase58(); // Mock blockhash
+  }
+
</code_context>

<issue_to_address>
**issue (bug_risk):** Using a random public key as a mock blockhash can be misleading and produces an invalid on-chain transaction.

In the catch branch, we fall back to a random public key as the blockhash but still proceed and log a successful transaction. That transaction will never be valid on-chain and can mask underlying network failures. Consider either failing fast and surfacing the `getLatestBlockhash` error, or explicitly gating this behavior behind a dedicated simulation/offline mode so it can’t be mistaken for a sendable transaction.
</issue_to_address>

### Comment 3
<location> `on-chain/trustchain-notary/programs/trustchain-notary/src/lib.rs:6` </location>
<code_context>
+declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
+
+// Hardcoded Notary Public Key
+pub const NOTARY_PUBKEY: Pubkey = pubkey!("Eg39fu7jw4ynYg3N3mzqusb1qLEZBH2ov62T564BFdYF");
+
+#[program]
</code_context>

<issue_to_address>
**suggestion (bug_risk):** Hardcoded NOTARY_PUBKEY risks drifting from the backend's NOTARY_SECRET configuration.

Because the program hardcodes `NOTARY_PUBKEY` while the backend derives its keypair from `NOTARY_SECRET`, any divergence (e.g. key rotation or env mismatch) will cause opaque `UnauthorizedNotary` failures on-chain. Consider either (a) documenting/automating how these values stay in sync, or (b) adding an on-chain config or deployment-time assertion that verifies the backend’s notary public key matches this constant.

Suggested implementation:

```rust
#[doc = "Hardcoded Notary public key.\n\n\
This MUST stay in sync with the backend's NOTARY_SECRET-derived public key.\n\
Deployment and CI pipelines should call the `assert_notary_pubkey` instruction\n\
with the backend-derived notary public key to fail fast if there is any\n\
mismatch, rather than surfacing opaque `UnauthorizedNotary` errors at runtime."]
pub const NOTARY_PUBKEY: Pubkey = pubkey!("Eg39fu7jw4ynYg3N3mzqusb1qLEZBH2ov62T564BFdYF");

```

```rust
#[program]
pub mod trustchain_notary {
    use super::*;

    /// Deployment-time assertion to ensure the backend's NOTARY_SECRET-derived
    /// public key matches the on-chain NOTARY_PUBKEY constant.
    ///
    /// Intended usage:
    /// - Backend derives its notary keypair from NOTARY_SECRET.
    /// - Deployment / CI script calls this instruction once, passing the
    ///   derived public key as `expected_notary`.
    /// - If the keys differ, this transaction fails fast with
    ///   `UnauthorizedNotary`, preventing a misconfigured deployment.
    pub fn assert_notary_pubkey(
        _ctx: Context<AssertNotaryPubkey>,
        expected_notary: Pubkey,
    ) -> Result<()> {
        require_keys_eq!(expected_notary, NOTARY_PUBKEY, TrustChainError::UnauthorizedNotary);
        Ok(())
    }

    pub fn update_integrity(ctx: Context<UpdateIntegrity>, gini_score: u16, hhi_score: u16, status: u8) -> Result<()> {

```

To fully wire this up, add the corresponding accounts struct somewhere in the file (e.g. near your other `#[derive(Accounts)]` definitions):

```rust
#[derive(Accounts)]
pub struct AssertNotaryPubkey {}
```

This empty accounts struct keeps the instruction simple (no runtime dependencies) while allowing off-chain deployment or CI tooling to submit a transaction that verifies the backend’s NOTARY_SECRET-derived public key matches `NOTARY_PUBKEY`.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.


async function updateOnChainPDA(wallet: PublicKey, score: IntegrityScore) {
// Connect to devnet (or localnet)
const connection = new Connection("https://api.devnet.solana.com", "confirmed");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion: Hardcoding the devnet RPC URL reduces flexibility across environments.

This ties the function to a single devnet endpoint and commitment. Consider reading the RPC URL (and optionally commitment) from an environment variable with a reasonable default so the same code can be used across devnet, localnet, mainnet, or other providers without code changes.

Suggested implementation:

async function updateOnChainPDA(wallet: PublicKey, score: IntegrityScore) {
  // Connect to Solana RPC (configurable via env; defaults to devnet)
  const rpcUrl =
    process.env.SOLANA_RPC_URL ?? "https://api.devnet.solana.com";
  const commitment =
    (process.env.SOLANA_COMMITMENT as Commitment | undefined) ?? "confirmed";
  const connection = new Connection(rpcUrl, commitment);
  1. Ensure Commitment is imported from @solana/web3.js at the top of backend/services/notary_sync.ts, e.g.:
    import { Connection, PublicKey, Commitment } from "@solana/web3.js";
  2. Optionally document the new environment variables (SOLANA_RPC_URL, SOLANA_COMMITMENT) in your configuration / README so deployments know how to target devnet, localnet, or mainnet without code changes.

Comment on lines +121 to +123
} catch (err) {
console.warn("Could not fetch blockhash (network issue?), using mock blockhash for simulation.");
transaction.recentBlockhash = Keypair.generate().publicKey.toBase58(); // Mock blockhash

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

issue (bug_risk): Using a random public key as a mock blockhash can be misleading and produces an invalid on-chain transaction.

In the catch branch, we fall back to a random public key as the blockhash but still proceed and log a successful transaction. That transaction will never be valid on-chain and can mask underlying network failures. Consider either failing fast and surfacing the getLatestBlockhash error, or explicitly gating this behavior behind a dedicated simulation/offline mode so it can’t be mistaken for a sendable transaction.

declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");

// Hardcoded Notary Public Key
pub const NOTARY_PUBKEY: Pubkey = pubkey!("Eg39fu7jw4ynYg3N3mzqusb1qLEZBH2ov62T564BFdYF");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion (bug_risk): Hardcoded NOTARY_PUBKEY risks drifting from the backend's NOTARY_SECRET configuration.

Because the program hardcodes NOTARY_PUBKEY while the backend derives its keypair from NOTARY_SECRET, any divergence (e.g. key rotation or env mismatch) will cause opaque UnauthorizedNotary failures on-chain. Consider either (a) documenting/automating how these values stay in sync, or (b) adding an on-chain config or deployment-time assertion that verifies the backend’s notary public key matches this constant.

Suggested implementation:

#[doc = "Hardcoded Notary public key.\n\n\
This MUST stay in sync with the backend's NOTARY_SECRET-derived public key.\n\
Deployment and CI pipelines should call the `assert_notary_pubkey` instruction\n\
with the backend-derived notary public key to fail fast if there is any\n\
mismatch, rather than surfacing opaque `UnauthorizedNotary` errors at runtime."]
pub const NOTARY_PUBKEY: Pubkey = pubkey!("Eg39fu7jw4ynYg3N3mzqusb1qLEZBH2ov62T564BFdYF");
#[program]
pub mod trustchain_notary {
    use super::*;

    /// Deployment-time assertion to ensure the backend's NOTARY_SECRET-derived
    /// public key matches the on-chain NOTARY_PUBKEY constant.
    ///
    /// Intended usage:
    /// - Backend derives its notary keypair from NOTARY_SECRET.
    /// - Deployment / CI script calls this instruction once, passing the
    ///   derived public key as `expected_notary`.
    /// - If the keys differ, this transaction fails fast with
    ///   `UnauthorizedNotary`, preventing a misconfigured deployment.
    pub fn assert_notary_pubkey(
        _ctx: Context<AssertNotaryPubkey>,
        expected_notary: Pubkey,
    ) -> Result<()> {
        require_keys_eq!(expected_notary, NOTARY_PUBKEY, TrustChainError::UnauthorizedNotary);
        Ok(())
    }

    pub fn update_integrity(ctx: Context<UpdateIntegrity>, gini_score: u16, hhi_score: u16, status: u8) -> Result<()> {

To fully wire this up, add the corresponding accounts struct somewhere in the file (e.g. near your other #[derive(Accounts)] definitions):

#[derive(Accounts)]
pub struct AssertNotaryPubkey {}

This empty accounts struct keeps the instruction simple (no runtime dependencies) while allowing off-chain deployment or CI tooling to submit a transaction that verifies the backend’s NOTARY_SECRET-derived public key matches NOTARY_PUBKEY.

@Freedomwithin

Copy link
Copy Markdown
Owner Author

Jules Protocol: Authority Rotation & Config

  1. GlobalConfig PDA: Create a new account GlobalConfig to store the admin and notary pubkeys.
  2. Initialize Instruction: Add an initialize_config instruction that sets the initial admin/notary.
  3. Rotation Instruction: Add a set_notary instruction that allows ONLY the admin to update the notary address.
  4. Update Logic: Refactor the update_integrity instruction to check the signer against the notary address stored in GlobalConfig instead of the hardcoded key.

@Freedomwithin

Copy link
Copy Markdown
Owner Author

Jules Protocol: Fix Notary Sync Account Mapping

Objective

Update backend/services/notary_sync.ts to correctly derive and pass the GlobalConfig PDA required by the refactored Anchor program.

Execution Steps

  1. Derive GlobalConfig PDA:

    const [configPDA] = anchor.web3.PublicKey.findProgramAddressSync(
      [Buffer.from("config")], 
      program.programId
    );
2. Update Instruction Call:
    Refactor the updateIntegrity call to include the missing account:
``` TypeScript

    await program.methods
      .updateIntegrity(giniScaled, hhiScaled, status)
      .accounts({
        user: userPublicKey,
        userIntegrity: userIntegrityPDA,
        notary: notaryKeypair.publicKey,
        globalConfig: configPDA, // <-- Add this
        systemProgram: anchor.web3.SystemProgram.programId,
      })
      .signers([notaryKeypair])
      .rpc();
  1. Retry: Run the sync:notary script again to verify the signature and on-chain update.

🚀 Technical Precision: Fixed-Point Math Reminder

Since we are using u16 for the scores, ensure the backend/services/notary_sync.ts is doing the scaling before sending:

  • Gini Score: Math.floor(gini * 10000)
  • HHI Score: Math.floor(hhi * 10000)
    This ensures your 0.5234 becomes 5234 on-chain, matching the Rust logic we established.

@Freedomwithin

Copy link
Copy Markdown
Owner Author

@jules I think you're hung up on the account mapping.

Please stop the current task and apply these fixes:

  1. Ensure update_integrity in backend/services/notary_sync.ts derives the GlobalConfig PDA using Buffer.from("config").
  2. You must run the initialize_config instruction before attempting to sync scores, otherwise the transaction will fail because the Config account doesn't exist.
  3. Apply the x * 10000 scaling to Gini/HHI scores in the TypeScript service to match the Rust u16 logic.

Once fixed, push the update to this branch.

@Freedomwithin

Copy link
Copy Markdown
Owner Author

Jules Protocol: Atomic Bootstrap (Task 1)

Objective

Initialize the GlobalConfig account on-chain. This is the blocker for all other tasks.

Execution Steps

  1. Dependency Sync: Run npm install in the /backend folder.
  2. PDA Mapping: Confirm the seed in lib.rs and notary_sync.ts is exactly Buffer.from("config").
  3. Initialization: Create and execute a standalone script backend/services/init_config.ts that only calls initialize_config.
  4. Verification: Confirm the GlobalConfig account is initialized by logging the transaction signature.

Note

Do not attempt to sync user scores yet. Only finish the Config initialization.

@Freedomwithin

Copy link
Copy Markdown
Owner Author

@jules I see you're working on the summary. Don't worry about a long explanation.

Please just:

  1. Briefly state if the initialize_config transaction was successful.
  2. Provide the Transaction Signature/Hash.
  3. Confirm that the GlobalConfig logic is now active for the update_integrity instruction.

Keep it minimal so we can move to the next phase.

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.

1 participant