Skip to content

Commit

Permalink
feat(solana): starts debridge_reporter
Browse files Browse the repository at this point in the history
  • Loading branch information
allemanfredi committed Nov 29, 2024
1 parent c222917 commit 34593ca
Show file tree
Hide file tree
Showing 10 changed files with 417 additions and 0 deletions.
2 changes: 2 additions & 0 deletions packages/solana/Anchor.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ resolution = true
skip-lint = false

[programs.localnet]
debridge-reporter = "2TvQ6gqQGAifdV2cQ1f8zHGYV2t6wPUNTKzpcALt8rX7"
hashi = "EyqiZf8Yt2CgVU5yPsj5e4EiGXeKrLhefWBn7CSqKPMC"
help = "EJy8wh5fqP5LYqs1mNbH2S6jxKGkP64PkXRmZgQxk9CE"
reporter = "4wFzP8uwPvvW2kZGxxkL45SP2Wn3oRbfe1LdHheUFZ9k"
solana = "4VFxPo4BF53PkVFBFjCQBFUn8bCxZZm6Dc2VgrJ5HXS8"

[registry]
Expand Down
147 changes: 147 additions & 0 deletions packages/solana/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions packages/solana/programs/debridge-reporter/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[package]
name = "debridge-reporter"
version = "0.1.0"
description = "Debridge reporter"
edition = "2021"

[lib]
crate-type = ["cdylib", "lib"]
name = "debridge_reporter"

[features]
default = []
cpi = ["no-entrypoint"]
no-entrypoint = []
no-idl = []
no-log-ix-name = []
idl-build = ["anchor-lang/idl-build"]

[dependencies]
anchor-lang = "0.30.1"
debridge-solana-sdk = { git = "ssh://git@github.com/debridge-finance/debridge-solana-sdk.git", version = "1.0.2" }
2 changes: 2 additions & 0 deletions packages/solana/programs/debridge-reporter/Xargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[target.bpfel-unknown-unknown.dependencies.std]
features = []
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use anchor_lang::prelude::*;
use anchor_lang::solana_program::sysvar;

#[derive(Accounts)]
pub struct DispatchSlot<'info> {
/// CHECK: We are reading from SlotHashes sysvar the latest slot hash
#[account(address = sysvar::slot_hashes::ID)]
pub slot_hashes: AccountInfo<'info>,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod dispatch_slot;

pub use dispatch_slot::*;
13 changes: 13 additions & 0 deletions packages/solana/programs/debridge-reporter/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use anchor_lang::prelude::*;

#[error_code]
pub enum ErrorCode {
#[msg("Invalid latest hash hash.")]
InvalidLatestHashLength,
#[msg("Invalid slot hashes sysvar.")]
InvalidSlotHashesSysVar,
#[msg("Slot hashes not available.")]
SlotHashesNotAvailable,
#[msg("Slot not found")]
SlotNotFound,
}
48 changes: 48 additions & 0 deletions packages/solana/programs/debridge-reporter/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use anchor_lang::prelude::*;
use borsh::{BorshDeserialize, BorshSerialize};
use debridge_solana_sdk::sending;

declare_id!("2TvQ6gqQGAifdV2cQ1f8zHGYV2t6wPUNTKzpcALt8rX7");

pub mod contexts;
pub mod error;
pub mod utils;

pub use contexts::*;
pub use utils::{get_slot, u64_to_u8_32};

#[derive(BorshSerialize)]
pub struct Message {
pub ids: Vec<[u8; 32]>,
pub hashes: Vec<[u8; 32]>,
}

#[program]
pub mod debridge_reporter {
use super::*;

pub fn dispatch_slot(
ctx: Context<DispatchSlot>,
target_chain_id: [u8; 32],
receiver: Vec<u8>,
slot_number: u64,
) -> Result<()> {
let (number, hash) = get_slot(&ctx.accounts.slot_hashes, slot_number)?;

let ids: Vec<[u8; 32]> = vec![u64_to_u8_32(number)];
let hashes: Vec<[u8; 32]> = vec![hash];
let message = Message { ids, hashes };

sending::invoke_send_message(
message.try_to_vec()?,
target_chain_id,
receiver,
0, // execution_fee = 0 means auto claim
vec![0u8; 32], // fallback address
ctx.remaining_accounts,
)
.map_err(ProgramError::from)?;

Ok(())
}
}
46 changes: 46 additions & 0 deletions packages/solana/programs/debridge-reporter/src/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use anchor_lang::prelude::*;
use anchor_lang::solana_program::sysvar;

use crate::error::ErrorCode;

pub fn get_slot(slot_hashes: &AccountInfo, slot_number: u64) -> Result<(u64, [u8; 32])> {
if *slot_hashes.key != sysvar::slot_hashes::ID {
return Err(error!(ErrorCode::InvalidSlotHashesSysVar));
}

let data = slot_hashes.try_borrow_data()?;
let num_slot_hashes = u64::from_le_bytes(data[0..8].try_into().unwrap());
let mut pos = 8;

if num_slot_hashes == 0 {
return Err(error!(ErrorCode::SlotHashesNotAvailable));
}

for _i in 0..num_slot_hashes {
let current_slot_number = u64::from_le_bytes(data[pos..pos + 8].try_into().unwrap());
pos += 8;

let current_slot_hash: [u8; 32] = match &data[pos..pos + 32].try_into() {
Ok(hash) => *hash,
Err(_) => return Err(error!(ErrorCode::InvalidLatestHashLength)),
};

if current_slot_number == slot_number {
return Ok((current_slot_number, current_slot_hash));
}

pos += 32;
}

Err(error!(ErrorCode::SlotNotFound))
}

pub fn u64_to_u8_32(number: u64) -> [u8; 32] {
let mut bytes = [0u8; 32];
let number_bytes = number.to_be_bytes(); // Convert u64 to a big-endian 8-byte array

// Copy the 8 bytes of the u64 into the last 8 bytes of the 32-byte array
bytes[24..].copy_from_slice(&number_bytes);

bytes
}
Loading

0 comments on commit 34593ca

Please sign in to comment.