Add CPI proxy

Change-Id: Iba395084fe0cf5ebd4e1cd7bb3515c6c1f7e8756
This commit is contained in:
Hendrik Hofstadt 2021-07-29 14:32:59 +02:00
parent 2a6f7eaa0e
commit dd5388a748
12 changed files with 226 additions and 11 deletions

View File

@ -44,6 +44,9 @@ spec:
- --bpf-program
- B6RHG3mfcckmrYN1UhmJzyS1XX3fZKbkeUcpJe9Sy3FE
- /opt/solana/deps/token_bridge.so
- --bpf-program
- CP1co2QMMoDPbsmV7PGcUTLFwyhgCgTXt25gLQ5LewE1
- /opt/solana/deps/cpi_poster.so
- --log
ports:
- containerPort: 8001

View File

@ -19,10 +19,13 @@ COPY solitaire solitaire
RUN --mount=type=cache,target=/usr/local,from=rust,source=/usr/local \
--mount=type=cache,target=/root/.cache \
--mount=type=cache,target=bridge/target \
--mount=type=cache,target=modules/token_bridge/target \
--mount=type=cache,target=target \
--mount=type=cache,target=bin,from=rust,source=bin \
cargo build-bpf --manifest-path "bridge/program/Cargo.toml" && \
cargo build-bpf --manifest-path "bridge/cpi_poster/Cargo.toml" && \
cargo build-bpf --manifest-path "modules/token_bridge/program/Cargo.toml" && \
mkdir -p /opt/solana/deps && \
cp bridge/target/deploy/bridge.so /opt/solana/deps/bridge.so && \
cp modules/token_bridge/target/deploy/token_bridge.so /opt/solana/deps/token_bridge.so
cp bridge/target/deploy/cpi_poster.so /opt/solana/deps/cpi_poster.so && \
cp modules/token_bridge/target/deploy/token_bridge.so /opt/solana/deps/token_bridge.so

View File

@ -503,6 +503,7 @@ dependencies = [
"borsh",
"bridge",
"clap",
"cpi-poster",
"hex",
"rand 0.7.3",
"shellexpand",
@ -578,6 +579,26 @@ version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b"
[[package]]
name = "cpi-poster"
version = "0.1.0"
dependencies = [
"borsh",
"bridge",
"byteorder",
"hex",
"hex-literal",
"libsecp256k1",
"primitive-types 0.9.1",
"rand 0.7.3",
"sha3",
"solana-client",
"solana-program",
"solana-sdk",
"solitaire",
"solitaire-client",
]
[[package]]
name = "cpufeatures"
version = "0.1.5"

View File

@ -1,5 +1,5 @@
[workspace]
members = ["agent", "program", "client", "program_stub"]
members = ["agent", "program", "client", "program_stub", "cpi_poster"]
[patch.crates-io]
memmap2 = { path = "memmap2-rs" }

View File

@ -8,6 +8,7 @@ edition = "2018"
anyhow = "1.0.40"
borsh = "0.8.1"
bridge = { path = "../program", features = ["client"] }
cpi-poster = { path = "../cpi_poster", features = ["no-entrypoint"] }
clap = "2.33.0"
rand = "0.7.3"
shellexpand = "2.1.0"

View File

@ -114,6 +114,7 @@ fn command_post_message(
nonce: u32,
payload: Vec<u8>,
commitment: bridge::types::ConsistencyLevel,
proxy: Option<Pubkey>,
) -> CommmandResult {
println!("Posting a message to the wormhole");
@ -134,15 +135,33 @@ fn command_post_message(
);
let emitter = Keypair::new();
let (_, ix) = bridge::instructions::post_message(
*bridge,
config.owner.pubkey(),
emitter.pubkey(),
nonce,
payload,
commitment,
)
.unwrap();
let ix = match proxy {
Some(p) => {
cpi_poster::instructions::post_message(
p,
*bridge,
config.owner.pubkey(),
emitter.pubkey(),
nonce,
payload,
commitment,
)
.unwrap()
.1
}
None => {
bridge::instructions::post_message(
*bridge,
config.owner.pubkey(),
emitter.pubkey(),
nonce,
payload,
commitment,
)
.unwrap()
.1
}
};
let mut transaction =
Transaction::new_with_payer(&[transfer_ix, ix], Some(&config.fee_payer.pubkey()));
@ -299,6 +318,14 @@ fn main() {
.index(4)
.required(true)
.help("Payload of the message"),
)
.arg(
Arg::with_name("proxy")
.long("proxy")
.validator(is_pubkey_or_keypair)
.value_name("PROXY")
.takes_value(true)
.help("CPI Proxy to use"),
),
)
.get_matches();
@ -362,6 +389,7 @@ fn main() {
let data = hex::decode(data_str).unwrap();
let nonce: u32 = value_of(arg_matches, "nonce").unwrap();
let consistency_level: String = value_of(arg_matches, "consistency_level").unwrap();
let proxy = pubkey_of(arg_matches, "proxy");
command_post_message(
&config,
@ -376,6 +404,7 @@ fn main() {
exit(1);
}
},
proxy,
)
}

View File

@ -0,0 +1,34 @@
[package]
name = "cpi-poster"
version = "0.1.0"
description = "Wormhole bridge core contract"
edition = "2018"
[lib]
crate-type = ["cdylib", "lib"]
name = "cpi_poster"
[features]
client = ["solitaire/client", "solitaire-client", "no-entrypoint"]
cpi = ["no-entrypoint"]
default = []
no-entrypoint = ["solitaire/no-entrypoint"]
trace = ["solitaire/trace"]
[dependencies]
borsh = "0.8.1"
byteorder = "1.4.3"
primitive-types = { version = "0.9.0", default-features = false }
sha3 = "0.9.1"
solana-program = "=1.7.0"
solitaire-client = { path = "../../solitaire/client", optional = true }
solitaire = { path = "../../solitaire/program" }
bridge = { path = "../program", features = ["no-entrypoint"] }
[dev-dependencies]
hex = "*"
rand = "0.7.3"
hex-literal = "0.3.1"
libsecp256k1 = { version = "0.3.5", features = [] }
solana-client = "1.7.0"
solana-sdk = "=1.7.0"

View File

@ -0,0 +1,2 @@
[target.bpfel-unknown-unknown.dependencies.std]
features = []

View File

@ -0,0 +1,3 @@
pub mod post_message;
pub use post_message::*;

View File

@ -0,0 +1,65 @@
use bridge::types::ConsistencyLevel;
use solana_program::program::invoke;
use solitaire::{
trace,
*,
};
#[derive(FromAccounts)]
pub struct PostMessage<'b> {
/// Bridge config needed for fee calculation.
pub bridge: Mut<Info<'b>>,
/// Account to store the posted message
pub message: Mut<Info<'b>>,
/// Emitter of the VAA
pub emitter: Info<'b>,
/// Tracker for the emitter sequence
pub sequence: Mut<Info<'b>>,
/// Payer for account creation
pub payer: Mut<Info<'b>>,
/// Account to collect tx fee
pub fee_collector: Mut<Info<'b>>,
pub clock: Info<'b>,
pub bridge_program: Info<'b>,
}
impl<'b> InstructionContext<'b> for PostMessage<'b> {
}
#[derive(BorshDeserialize, BorshSerialize)]
pub struct PostMessageData {
/// Unique nonce for this message
pub nonce: u32,
/// Message payload
pub payload: Vec<u8>,
/// Commitment Level required for an attestation to be produced
pub consistency_level: ConsistencyLevel,
}
pub fn post_message(
ctx: &ExecutionContext,
accs: &mut PostMessage,
data: PostMessageData,
) -> Result<()> {
let (_, ix) = bridge::instructions::post_message(
*accs.bridge_program.key,
*accs.payer.key,
*accs.emitter.key,
data.nonce,
data.payload,
data.consistency_level,
)
.unwrap();
invoke(&ix, ctx.accounts)?;
Ok(())
}

View File

@ -0,0 +1,34 @@
use bridge::types::ConsistencyLevel;
use solana_program::{
instruction::{
AccountMeta,
Instruction,
},
pubkey::Pubkey,
};
pub fn post_message(
program_id: Pubkey,
bridge_id: Pubkey,
payer: Pubkey,
emitter: Pubkey,
nonce: u32,
payload: Vec<u8>,
commitment: ConsistencyLevel,
) -> solitaire::Result<(Pubkey, Instruction)> {
let (k, ix) =
bridge::instructions::post_message(bridge_id, payer, emitter, nonce, payload, commitment)?;
let mut accounts = ix.accounts;
accounts.insert(7, AccountMeta::new_readonly(bridge_id, false));
let mut data = ix.data;
data[0] = 0;
Ok((
k,
Instruction {
program_id,
accounts,
data,
},
))
}

View File

@ -0,0 +1,20 @@
#![feature(const_generics)]
#![allow(non_upper_case_globals)]
#![allow(incomplete_features)]
pub mod api;
use solitaire::*;
#[cfg(feature = "no-entrypoint")]
pub mod instructions;
pub use api::{
post_message,
PostMessage,
PostMessageData,
};
solitaire! {
PostMessage(PostMessageData) => post_message,
}