Skip to content

Commit 7f4939a

Browse files
committed
adding some gateway functions
1 parent c062491 commit 7f4939a

File tree

3 files changed

+173
-12
lines changed

3 files changed

+173
-12
lines changed

Diff for: gmp/solana/contract/src/errors.rs

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
use anchor_lang::prelude::*;
2+
3+
#[error_code]
4+
pub enum GatewayError {
5+
#[msg("The gateway is not initialized.")]
6+
NotInitialized,
7+
#[msg("The gateway is already initialized")]
8+
AlreadyInitialized,
9+
#[msg("Unauthorized: The provided authority is not the gateway admin.")]
10+
Unauthorized,
11+
#[msg("Too much shards to register")]
12+
ShardsLengthExceedLimit,
13+
}

Diff for: gmp/solana/contract/src/lib.rs

+67-12
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,79 @@
11
use anchor_lang::prelude::*;
22

3+
mod errors;
4+
mod state;
5+
6+
use errors::*;
7+
use state::*;
8+
39
declare_id!("11111111111111111111111111111111");
410

511
#[program]
6-
mod hello_anchor {
12+
mod gateway {
713
use super::*;
14+
// Admin executable
15+
pub fn initialize(ctx: Context<Initialize>, admin: Pubkey) -> Result<()> {
16+
let state = &mut ctx.accounts.gateway_state;
17+
if !state.is_initialized {
18+
state.admin = admin;
19+
state.is_initialized = true;
20+
}
21+
Ok(())
22+
}
823

9-
pub fn initialize(_ctx: Context<Initialize>) -> Result<()> {
24+
// Admin executable
25+
pub fn set_admin(ctx: Context<SetAdmin>, new_admin: Pubkey) -> Result<()> {
26+
let state = &mut ctx.accounts.gateway_state;
27+
require_keys_eq!(ctx.accounts.signer.key(), state.admin, GatewayError::Unauthorized);
28+
require!(state.is_initialized, GatewayError::AlreadyInitialized);
29+
state.admin = new_admin;
1030
Ok(())
1131
}
12-
}
1332

14-
#[derive(Accounts)]
15-
pub struct Initialize<'info> {
16-
#[account(mut)]
17-
pub signer: Signer<'info>,
18-
pub system_program: Program<'info, System>,
19-
}
33+
// only executed by admin
34+
pub fn set_shards(ctx: Context<SetShards>, shards: Vec<Shard>) -> Result<()> {
35+
require!(shards.len() < MAX_SHARDS_LEN, GatewayError::ShardsLengthExceedLimit);
36+
let state = &mut ctx.accounts.gateway_state;
37+
require_keys_eq!(ctx.accounts.signer.key(), state.admin, GatewayError::Unauthorized);
38+
state.shards.clear();
39+
for shard in shards.into_iter() {
40+
let seed_x = shard.x_coord;
41+
let seed_y = [shard.y_parity];
42+
43+
let (nonce_pda, _bump) =
44+
Pubkey::find_program_address(&[b"shard_nonce", &seed_x, &seed_y], ctx.program_id);
45+
46+
let mut shard_nonce = 0u64;
47+
let mut found = false;
48+
for acc in ctx.remaining_accounts.iter() {
49+
if acc.key() == nonce_pda {
50+
let shard_nonce_acc =
51+
ShardNonce::try_deserialize(&mut acc.data.borrow().as_ref())?;
52+
shard_nonce = shard_nonce_acc.nonce;
53+
found = true;
54+
break;
55+
}
56+
}
57+
if !found {
58+
shard_nonce = 0;
59+
}
60+
state.shards.push(ShardAcc {
61+
shard: shard.clone(),
62+
nonce: shard_nonce,
63+
});
64+
}
2065

21-
#[account]
22-
pub struct NewAccount {
23-
data: u64,
66+
Ok(())
67+
}
68+
69+
// excuted by user
70+
pub fn submit_message(ctx: Context<Initialize>, msg: GmpMessage) -> Result<()> {
71+
msg!("gmp executed: {:?}", msg);
72+
Ok(())
73+
}
74+
75+
// excuted by chronicles
76+
pub fn execute_batch(ctx: Context<Initialize>) -> Result<()> {
77+
Ok(())
78+
}
2479
}

Diff for: gmp/solana/contract/src/state.rs

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
use anchor_lang::prelude::*;
2+
use borsh::{BorshDeserialize, BorshSerialize};
3+
4+
type GmpID = [u8; 32];
5+
type NetworkId = u16;
6+
type Address = [u8; 32];
7+
8+
pub const MAX_SHARDS_LEN: usize = 50;
9+
10+
#[derive(Accounts)]
11+
pub struct Initialize<'info> {
12+
#[account(
13+
init,
14+
payer = signer,
15+
// first 8 bytes is type discriminator: <https://www.anchor-lang.com/docs/basics/program-structure#account-discriminator>
16+
space = 8 + 32 + 1,
17+
// look into the security issues of seeds
18+
seeds = [b"gateway_state"],
19+
bump
20+
)]
21+
pub gateway_state: Account<'info, GatewayState>,
22+
#[account(mut)]
23+
pub signer: Signer<'info>,
24+
25+
pub system_program: Program<'info, System>,
26+
}
27+
28+
#[derive(Accounts)]
29+
pub struct SetAdmin<'info> {
30+
#[account(mut)]
31+
pub gateway_state: Account<'info, GatewayState>,
32+
#[account(mut)]
33+
pub signer: Signer<'info>,
34+
}
35+
36+
#[derive(Accounts)]
37+
pub struct SetShards<'info> {
38+
#[account(mut)]
39+
pub gateway_state: Account<'info, GatewayState>,
40+
#[account(mut)]
41+
pub signer: Signer<'info>,
42+
}
43+
44+
#[account]
45+
#[derive(Default)]
46+
pub struct GatewayState {
47+
pub admin: Pubkey,
48+
pub is_initialized: bool,
49+
pub shards: Vec<ShardAcc>,
50+
}
51+
52+
#[account]
53+
pub struct GmpInfo {
54+
pub msg: [u8; 32],
55+
pub y_parity: u8,
56+
pub nonce: u64,
57+
}
58+
59+
#[account]
60+
pub struct ShardAcc {
61+
pub shard: Shard,
62+
pub nonce: u64,
63+
}
64+
65+
#[account]
66+
pub struct ShardNonce {
67+
pub nonce: u64,
68+
}
69+
70+
#[derive(Clone, BorshSerialize, BorshDeserialize)]
71+
pub struct Shard {
72+
pub x_coord: [u8; 32],
73+
pub y_parity: u8,
74+
}
75+
76+
#[derive(Clone, Copy, BorshSerialize, BorshDeserialize, PartialEq)]
77+
pub enum GmpStatus {
78+
Pending,
79+
Executed,
80+
Failed,
81+
}
82+
83+
#[derive(Clone, Debug, BorshSerialize, BorshDeserialize)]
84+
pub struct GmpMessage {
85+
pub src_network: NetworkId,
86+
pub dest_network: NetworkId,
87+
pub src: Address,
88+
pub dest: Address,
89+
pub nonce: u64,
90+
pub gas_limit: u128,
91+
pub gas_cost: u128,
92+
pub bytes: Vec<u8>,
93+
}

0 commit comments

Comments
 (0)