diff --git a/solana/anchor-bridge/Cargo.lock b/solana/anchor-bridge/Cargo.lock index 3fc99aaa..d647ce03 100644 --- a/solana/anchor-bridge/Cargo.lock +++ b/solana/anchor-bridge/Cargo.lock @@ -183,6 +183,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634" +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "crypto-mac" version = "0.8.0" @@ -206,6 +212,17 @@ dependencies = [ "zeroize", ] +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "digest" version = "0.8.1" @@ -260,6 +277,15 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da" +[[package]] +name = "fixed-hash" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c" +dependencies = [ + "static_assertions", +] + [[package]] name = "generic-array" version = "0.12.4" @@ -392,6 +418,28 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_enum" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "226b45a5c2ac4dd696ed30fa6b94b057ad909c7b7fc2e0d0808192bced894066" +dependencies = [ + "derivative", + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c0fd9eba1d5db0994a239e09c1be402d35622277e35468ba891aa5e3188ce7e" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "opaque-debug" version = "0.3.0" @@ -404,6 +452,16 @@ version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" +[[package]] +name = "primitive-types" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2415937401cb030a2a0a4d922483f945fa068f52a7dbb22ce0fe5f2b6f6adace" +dependencies = [ + "fixed-hash", + "uint", +] + [[package]] name = "proc-macro-crate" version = "0.1.5" @@ -687,6 +745,26 @@ dependencies = [ "solana-program", ] +[[package]] +name = "spl-token" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbfa8fd791aeb4d7ad5fedb7872478de9f4e8b4fcb02dfd9e7f2f9ae3f3ddd73" +dependencies = [ + "arrayref", + "num-derive", + "num-traits", + "num_enum", + "solana-program", + "thiserror", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "subtle" version = "2.4.0" @@ -733,6 +811,20 @@ dependencies = [ "syn", ] +[[package]] +name = "token-bridge" +version = "0.1.0" +dependencies = [ + "borsh", + "byteorder", + "primitive-types", + "rocksalt", + "sha3", + "solana-program", + "solitaire", + "spl-token", +] + [[package]] name = "toml" version = "0.5.8" @@ -748,6 +840,18 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" +[[package]] +name = "uint" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e11fe9a9348741cf134085ad57c249508345fe16411b3d7fb4ff2da2f1d6382e" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + [[package]] name = "unicode-xid" version = "0.2.2" diff --git a/solana/anchor-bridge/programs/solitaire/src/lib.rs b/solana/anchor-bridge/programs/solitaire/src/lib.rs index fb639610..4fed2967 100644 --- a/solana/anchor-bridge/programs/solitaire/src/lib.rs +++ b/solana/anchor-bridge/programs/solitaire/src/lib.rs @@ -32,11 +32,15 @@ pub use borsh::{BorshDeserialize, BorshSerialize}; use solana_program::{ account_info::next_account_info, instruction::AccountMeta, - program::invoke_signed, program_error::ProgramError, + program_pack::Pack, rent::Rent, }; -use std::slice::Iter; +use std::{ + io::{ErrorKind, Write}, + slice::Iter, + string::FromUtf8Error, +}; /// There are several places in Solitaire that might fail, we want descriptive errors. #[derive(Debug)] @@ -55,25 +59,69 @@ pub enum SolitaireError { /// An IO error was captured, wrap it up and forward it along. IoError(std::io::Error), + + /// An solana program error + ProgramError(ProgramError), + + Custom(u64), +} + +impl From for SolitaireError { + fn from(e: ProgramError) -> Self { + SolitaireError::ProgramError(e) + } +} + +impl From for SolitaireError { + fn from(e: std::io::Error) -> Self { + SolitaireError::IoError(e) + } } impl Into for SolitaireError { fn into(self) -> ProgramError { - //TODO + if let SolitaireError::ProgramError(e) = self { + return e; + } + // TODO ProgramError::Custom(0) } } /// Quality of life Result type for the Solitaire stack. -pub type Result = std::result::Result; +pub type Result = std::result::Result; pub type ErrBox = Box; pub trait Persist { fn persist(self); } -pub trait Seeded { - fn seeds(self) -> Vec>>; +#[repr(transparent)] +pub struct Packed(T); + +impl BorshDeserialize for Packed { + fn deserialize(buf: &mut &[u8]) -> std::io::Result { + Ok(Packed( + T::unpack(buf).map_err(|e| std::io::Error::new(ErrorKind::Other, e))?, + )) + } +} + +impl BorshSerialize for Packed { + fn serialize(&self, writer: &mut W) -> std::io::Result<()> { + let mut data: [u8; 2000] = [0u8; 2000]; + T::pack_into_slice(self, &mut data); + writer.write(&data); + + Ok(()) + } +} + +impl Deref for Packed { + type Target = T; + fn deref(&self) -> &Self::Target { + unsafe { std::mem::transmute(&self.0) } + } } // The following set of recursive types form the basis of this library, each one represents a @@ -383,8 +431,7 @@ impl<'a, 'b: 'a, 'c, T: BorshDeserialize, const IsInitialized: bool, const Lazy: ctx.deps.push(system_program::ID); } - let data = T::try_from_slice(&mut *ctx.info().data.borrow_mut()) - .map_err::(|e| SolitaireError::IoError(e).into())?; + let data = T::try_from_slice(&mut *ctx.info().data.borrow_mut())?; Ok(Data(ctx.info().clone(), data)) } @@ -461,7 +508,7 @@ macro_rules! solitaire { mod instruction { use super::*; use borsh::{BorshDeserialize, BorshSerialize}; - use solitaire::{Persist, FromAccounts}; + use solitaire::{Persist, FromAccounts, Result}; /// Generated: /// This Instruction contains a 1-1 mapping for each enum variant to function call. The @@ -474,8 +521,8 @@ macro_rules! solitaire { /// This entrypoint is generated from the enum above, it deserializes incoming bytes /// and automatically dispatches to the correct method. - pub fn dispatch<'a, 'b: 'a, 'c>(p: &Pubkey, a: &'c [AccountInfo<'b>], d: &[u8]) -> ProgramResult { - match Instruction::try_from_slice(d)? { + pub fn dispatch<'a, 'b: 'a, 'c>(p: &Pubkey, a: &'c [AccountInfo<'b>], d: &[u8]) -> Result<()> { + match BorshDeserialize::try_from_slice(d).map_err(|_| SolitaireError::InstructionDeserializeFailed)? { $( Instruction::$row(ix_data) => { let (mut accounts, _deps): ($row, _) = FromAccounts::from(p, &mut a.iter(), &()).unwrap();