Support deserialization on Pack types

Change-Id: I1eeee002b4a396f94661a938fb0dad1bf958719f
This commit is contained in:
Hendrik Hofstadt 2021-06-02 12:39:47 +02:00
parent 02ecdb691a
commit e2195c9b17
2 changed files with 162 additions and 11 deletions

View File

@ -183,6 +183,12 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634" checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634"
[[package]]
name = "crunchy"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]] [[package]]
name = "crypto-mac" name = "crypto-mac"
version = "0.8.0" version = "0.8.0"
@ -206,6 +212,17 @@ dependencies = [
"zeroize", "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]] [[package]]
name = "digest" name = "digest"
version = "0.8.1" version = "0.8.1"
@ -260,6 +277,15 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da" 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]] [[package]]
name = "generic-array" name = "generic-array"
version = "0.12.4" version = "0.12.4"
@ -392,6 +418,28 @@ dependencies = [
"autocfg", "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]] [[package]]
name = "opaque-debug" name = "opaque-debug"
version = "0.3.0" version = "0.3.0"
@ -404,6 +452,16 @@ version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" 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]] [[package]]
name = "proc-macro-crate" name = "proc-macro-crate"
version = "0.1.5" version = "0.1.5"
@ -687,6 +745,26 @@ dependencies = [
"solana-program", "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]] [[package]]
name = "subtle" name = "subtle"
version = "2.4.0" version = "2.4.0"
@ -733,6 +811,20 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "token-bridge"
version = "0.1.0"
dependencies = [
"borsh",
"byteorder",
"primitive-types",
"rocksalt",
"sha3",
"solana-program",
"solitaire",
"spl-token",
]
[[package]] [[package]]
name = "toml" name = "toml"
version = "0.5.8" version = "0.5.8"
@ -748,6 +840,18 @@ version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" 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]] [[package]]
name = "unicode-xid" name = "unicode-xid"
version = "0.2.2" version = "0.2.2"

View File

@ -32,11 +32,15 @@ pub use borsh::{BorshDeserialize, BorshSerialize};
use solana_program::{ use solana_program::{
account_info::next_account_info, account_info::next_account_info,
instruction::AccountMeta, instruction::AccountMeta,
program::invoke_signed,
program_error::ProgramError, program_error::ProgramError,
program_pack::Pack,
rent::Rent, 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. /// There are several places in Solitaire that might fail, we want descriptive errors.
#[derive(Debug)] #[derive(Debug)]
@ -55,25 +59,69 @@ pub enum SolitaireError {
/// An IO error was captured, wrap it up and forward it along. /// An IO error was captured, wrap it up and forward it along.
IoError(std::io::Error), IoError(std::io::Error),
/// An solana program error
ProgramError(ProgramError),
Custom(u64),
}
impl From<ProgramError> for SolitaireError {
fn from(e: ProgramError) -> Self {
SolitaireError::ProgramError(e)
}
}
impl From<std::io::Error> for SolitaireError {
fn from(e: std::io::Error) -> Self {
SolitaireError::IoError(e)
}
} }
impl Into<ProgramError> for SolitaireError { impl Into<ProgramError> for SolitaireError {
fn into(self) -> ProgramError { fn into(self) -> ProgramError {
//TODO if let SolitaireError::ProgramError(e) = self {
return e;
}
// TODO
ProgramError::Custom(0) ProgramError::Custom(0)
} }
} }
/// Quality of life Result type for the Solitaire stack. /// Quality of life Result type for the Solitaire stack.
pub type Result<T> = std::result::Result<T, ProgramError>; pub type Result<T> = std::result::Result<T, SolitaireError>;
pub type ErrBox = Box<dyn std::error::Error>; pub type ErrBox = Box<dyn std::error::Error>;
pub trait Persist { pub trait Persist {
fn persist(self); fn persist(self);
} }
pub trait Seeded { #[repr(transparent)]
fn seeds(self) -> Vec<Vec<Vec<u8>>>; pub struct Packed<T: Pack + solana_program::program_pack::IsInitialized>(T);
impl<T: Pack + solana_program::program_pack::IsInitialized> BorshDeserialize for Packed<T> {
fn deserialize(buf: &mut &[u8]) -> std::io::Result<Self> {
Ok(Packed(
T::unpack(buf).map_err(|e| std::io::Error::new(ErrorKind::Other, e))?,
))
}
}
impl<T: Pack + solana_program::program_pack::IsInitialized> BorshSerialize for Packed<T> {
fn serialize<W: Write>(&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<T: Pack + solana_program::program_pack::IsInitialized> Deref for Packed<T> {
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 // 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); ctx.deps.push(system_program::ID);
} }
let data = T::try_from_slice(&mut *ctx.info().data.borrow_mut()) let data = T::try_from_slice(&mut *ctx.info().data.borrow_mut())?;
.map_err::<ProgramError, _>(|e| SolitaireError::IoError(e).into())?;
Ok(Data(ctx.info().clone(), data)) Ok(Data(ctx.info().clone(), data))
} }
@ -461,7 +508,7 @@ macro_rules! solitaire {
mod instruction { mod instruction {
use super::*; use super::*;
use borsh::{BorshDeserialize, BorshSerialize}; use borsh::{BorshDeserialize, BorshSerialize};
use solitaire::{Persist, FromAccounts}; use solitaire::{Persist, FromAccounts, Result};
/// Generated: /// Generated:
/// This Instruction contains a 1-1 mapping for each enum variant to function call. The /// 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 /// This entrypoint is generated from the enum above, it deserializes incoming bytes
/// and automatically dispatches to the correct method. /// and automatically dispatches to the correct method.
pub fn dispatch<'a, 'b: 'a, 'c>(p: &Pubkey, a: &'c [AccountInfo<'b>], d: &[u8]) -> ProgramResult { pub fn dispatch<'a, 'b: 'a, 'c>(p: &Pubkey, a: &'c [AccountInfo<'b>], d: &[u8]) -> Result<()> {
match Instruction::try_from_slice(d)? { match BorshDeserialize::try_from_slice(d).map_err(|_| SolitaireError::InstructionDeserializeFailed)? {
$( $(
Instruction::$row(ix_data) => { Instruction::$row(ix_data) => {
let (mut accounts, _deps): ($row, _) = FromAccounts::from(p, &mut a.iter(), &()).unwrap(); let (mut accounts, _deps): ($row, _) = FromAccounts::from(p, &mut a.iter(), &()).unwrap();