Add Confidential Transfer Extension boilerplate

This commit is contained in:
Michael Vines 2022-01-07 11:50:53 -08:00
parent 0a98473f0a
commit 5fe1eb6a9d
8 changed files with 266 additions and 4 deletions

124
Cargo.lock generated
View File

@ -27,6 +27,42 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "aead"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877"
dependencies = [
"generic-array",
]
[[package]]
name = "aes"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8"
dependencies = [
"cfg-if",
"cipher",
"cpufeatures",
"opaque-debug",
]
[[package]]
name = "aes-gcm-siv"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589c637f0e68c877bbd59a4599bbe849cac8e5f3e4b5a3ebae8f528cd218dcdc"
dependencies = [
"aead",
"aes",
"cipher",
"ctr",
"polyval",
"subtle",
"zeroize",
]
[[package]] [[package]]
name = "ahash" name = "ahash"
version = "0.4.7" version = "0.4.7"
@ -425,6 +461,15 @@ dependencies = [
"chrono", "chrono",
] ]
[[package]]
name = "cipher"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7"
dependencies = [
"generic-array",
]
[[package]] [[package]]
name = "clap" name = "clap"
version = "2.34.0" version = "2.34.0"
@ -607,6 +652,15 @@ dependencies = [
"subtle", "subtle",
] ]
[[package]]
name = "ctr"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea"
dependencies = [
"cipher",
]
[[package]] [[package]]
name = "curve25519-dalek" name = "curve25519-dalek"
version = "3.2.0" version = "3.2.0"
@ -616,6 +670,7 @@ dependencies = [
"byteorder", "byteorder",
"digest", "digest",
"rand_core 0.5.1", "rand_core 0.5.1",
"serde",
"subtle", "subtle",
"zeroize", "zeroize",
] ]
@ -1570,6 +1625,18 @@ dependencies = [
"autocfg", "autocfg",
] ]
[[package]]
name = "merlin"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e261cf0f8b3c42ded9f7d2bb59dea03aa52bc8a1cbc7482f9fc3fd1229d3b42"
dependencies = [
"byteorder",
"keccak",
"rand_core 0.5.1",
"zeroize",
]
[[package]] [[package]]
name = "metaplex-token-metadata" name = "metaplex-token-metadata"
version = "0.0.1" version = "0.0.1"
@ -1913,6 +1980,18 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
[[package]]
name = "polyval"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1"
dependencies = [
"cfg-if",
"cpufeatures",
"opaque-debug",
"universal-hash",
]
[[package]] [[package]]
name = "ppv-lite86" name = "ppv-lite86"
version = "0.2.15" version = "0.2.15"
@ -3310,6 +3389,36 @@ dependencies = [
"thiserror", "thiserror",
] ]
[[package]]
name = "solana-zk-token-sdk"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2243307ab81fedd2f7e3b4b2b541ab0314cc4a26aebbf7ed6ddb839808cb244"
dependencies = [
"aes-gcm-siv",
"arrayref",
"base64 0.13.0",
"bincode",
"bytemuck",
"byteorder",
"cipher",
"curve25519-dalek",
"getrandom 0.1.16",
"lazy_static",
"merlin",
"num-derive",
"num-traits",
"rand 0.7.3",
"serde",
"serde_json",
"sha3",
"solana-program",
"solana-sdk",
"subtle",
"thiserror",
"zeroize",
]
[[package]] [[package]]
name = "solana_rbpf" name = "solana_rbpf"
version = "0.2.19" version = "0.2.19"
@ -3706,6 +3815,7 @@ dependencies = [
"solana-program", "solana-program",
"solana-program-test", "solana-program-test",
"solana-sdk", "solana-sdk",
"solana-zk-token-sdk",
"thiserror", "thiserror",
] ]
@ -4309,6 +4419,16 @@ version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f14ee04d9415b52b3aeab06258a3f07093182b88ba0f9b8d203f211a7a7d41c7" checksum = "f14ee04d9415b52b3aeab06258a3f07093182b88ba0f9b8d203f211a7a7d41c7"
[[package]]
name = "universal-hash"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05"
dependencies = [
"generic-array",
"subtle",
]
[[package]] [[package]]
name = "unreachable" name = "unreachable"
version = "1.0.0" version = "1.0.0"
@ -4567,9 +4687,9 @@ dependencies = [
[[package]] [[package]]
name = "zeroize" name = "zeroize"
version = "1.4.3" version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d68d9dcec5f9b43a30d38c49f91dfedfaac384cb8f085faca366c26207dd1619" checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd"
dependencies = [ dependencies = [
"zeroize_derive", "zeroize_derive",
] ]

View File

@ -19,6 +19,7 @@ num-derive = "0.3"
num-traits = "0.2" num-traits = "0.2"
num_enum = "0.5.4" num_enum = "0.5.4"
solana-program = "1.9.2" solana-program = "1.9.2"
solana-zk-token-sdk = "0.1.0"
thiserror = "1.0" thiserror = "1.0"
[dev-dependencies] [dev-dependencies]

View File

@ -0,0 +1,56 @@
use {
crate::{id, instruction::TokenInstruction, pod::*},
bytemuck::Pod,
num_derive::{FromPrimitive, ToPrimitive},
num_traits::{FromPrimitive, ToPrimitive},
solana_program::{
instruction::{AccountMeta, Instruction},
program_error::ProgramError,
},
};
/// Confidential Transfer extension instructions
#[derive(Clone, Copy, Debug, FromPrimitive, ToPrimitive)]
#[repr(u8)]
pub enum ConfidentialTransferInstruction {
/// TODO: inline `zk_token_program::instructions::ZkTokenInstruction` here
Todo,
}
pub(crate) fn decode_instruction_type(
input: &[u8],
) -> Result<ConfidentialTransferInstruction, ProgramError> {
if input.is_empty() {
Err(ProgramError::InvalidInstructionData)
} else {
FromPrimitive::from_u8(input[0]).ok_or(ProgramError::InvalidInstructionData)
}
}
pub(crate) fn decode_instruction_data<T: Pod>(input: &[u8]) -> Result<&T, ProgramError> {
if input.is_empty() {
Err(ProgramError::InvalidInstructionData)
} else {
pod_from_bytes(&input[1..])
}
}
fn encode_instruction<T: Pod>(
accounts: Vec<AccountMeta>,
instruction_type: ConfidentialTransferInstruction,
instruction_data: &T,
) -> Instruction {
let mut data = TokenInstruction::ConfidentialTransferExtension.pack();
data.push(ToPrimitive::to_u8(&instruction_type).unwrap());
data.extend_from_slice(bytemuck::bytes_of(instruction_data));
Instruction {
program_id: id(),
accounts,
data,
}
}
/// Create a `Todo` instruction
pub fn todo() -> Instruction {
encode_instruction(vec![], ConfidentialTransferInstruction::Todo, &())
}

View File

@ -0,0 +1,34 @@
use {
crate::extension::{AccountType, Extension, ExtensionType},
bytemuck::{Pod, Zeroable},
};
/// Confidential Transfer Extension instructions
pub mod instruction;
/// Confidential Transfer Extension processor
pub mod processor;
/// Transfer auditor configuration
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)]
pub struct MintConfidentialTransferAuditor {
// TODO: inline `zk_token_program::state::Auditor` here
}
impl Extension for MintConfidentialTransferAuditor {
const TYPE: ExtensionType = ExtensionType::MintConfidentialTransferAuditor;
const ACCOUNT_TYPE: AccountType = AccountType::Mint;
}
/// Confidential account state
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)]
pub struct AccountConfidentialState {
// TODO: inline `zk_token_program::state::ZkAccount` here
}
impl Extension for AccountConfidentialState {
const TYPE: ExtensionType = ExtensionType::AccountConfidentialState;
const ACCOUNT_TYPE: AccountType = AccountType::Account;
}

View File

@ -0,0 +1,19 @@
use {
super::instruction::*,
solana_program::{account_info::AccountInfo, entrypoint::ProgramResult, msg, pubkey::Pubkey},
};
/// TODO: inline `zk_token_program::processor.rs` here
pub fn process_instruction(
_program_id: &Pubkey,
_accounts: &[AccountInfo],
input: &[u8],
) -> ProgramResult {
match decode_instruction_type(input)? {
ConfidentialTransferInstruction::Todo => {
let todo_data = decode_instruction_data::<()>(input)?;
msg!("Todo: {:?}", todo_data);
Ok(())
}
}
}

View File

@ -3,6 +3,7 @@
use { use {
crate::{ crate::{
extension::{ extension::{
confidential_transfer::{AccountConfidentialState, MintConfidentialTransferAuditor},
mint_close_authority::MintCloseAuthority, mint_close_authority::MintCloseAuthority,
transfer_fee::{AccountTransferFee, MintTransferFee}, transfer_fee::{AccountTransferFee, MintTransferFee},
}, },
@ -21,8 +22,12 @@ use {
}, },
}; };
mod mint_close_authority; /// Confidential Transfer extension
mod transfer_fee; pub mod confidential_transfer;
/// Mint Close Authority extension
pub mod mint_close_authority;
/// Transfer Fee extension
pub mod transfer_fee;
/// Length in TLV structure /// Length in TLV structure
#[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] #[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)]
@ -332,6 +337,10 @@ pub enum ExtensionType {
AccountTransferFee, AccountTransferFee,
/// Includes an optional mint close authority /// Includes an optional mint close authority
MintCloseAuthority, MintCloseAuthority,
/// Auditor configuration for confidential transfers
MintConfidentialTransferAuditor,
/// Confidential Account state
AccountConfidentialState,
/// Padding extension used to make an account exactly Multisig::LEN, used for testing /// Padding extension used to make an account exactly Multisig::LEN, used for testing
#[cfg(test)] #[cfg(test)]
AccountPaddingTest = u16::MAX - 1, AccountPaddingTest = u16::MAX - 1,
@ -361,6 +370,12 @@ impl ExtensionType {
ExtensionType::MintTransferFee => pod_get_packed_len::<MintTransferFee>(), ExtensionType::MintTransferFee => pod_get_packed_len::<MintTransferFee>(),
ExtensionType::AccountTransferFee => pod_get_packed_len::<AccountTransferFee>(), ExtensionType::AccountTransferFee => pod_get_packed_len::<AccountTransferFee>(),
ExtensionType::MintCloseAuthority => pod_get_packed_len::<MintCloseAuthority>(), ExtensionType::MintCloseAuthority => pod_get_packed_len::<MintCloseAuthority>(),
ExtensionType::MintConfidentialTransferAuditor => {
pod_get_packed_len::<MintConfidentialTransferAuditor>()
}
ExtensionType::AccountConfidentialState => {
pod_get_packed_len::<AccountConfidentialState>()
}
#[cfg(test)] #[cfg(test)]
ExtensionType::AccountPaddingTest => pod_get_packed_len::<AccountPaddingTest>(), ExtensionType::AccountPaddingTest => pod_get_packed_len::<AccountPaddingTest>(),
#[cfg(test)] #[cfg(test)]

View File

@ -569,6 +569,12 @@ pub enum TokenInstruction {
/// Maximum fee assessed on transfers /// Maximum fee assessed on transfers
maximum_fee: u64, maximum_fee: u64,
}, },
/// The common instruction prefix for Confidential Transfer extension instructions.
///
/// See `extension::confidential_transfer::instruction::ConfidentialTransferInstruction` for
/// further details about the extended instructions that share this instruction prefix
ConfidentialTransferExtension,
} }
impl TokenInstruction { impl TokenInstruction {
/// Unpacks a byte buffer into a [TokenInstruction](enum.TokenInstruction.html). /// Unpacks a byte buffer into a [TokenInstruction](enum.TokenInstruction.html).
@ -755,6 +761,7 @@ impl TokenInstruction {
maximum_fee, maximum_fee,
} }
} }
29 => Self::ConfidentialTransferExtension,
_ => return Err(TokenError::InvalidInstruction.into()), _ => return Err(TokenError::InvalidInstruction.into()),
}) })
} }
@ -900,6 +907,9 @@ impl TokenInstruction {
buf.extend_from_slice(&transfer_fee_basis_points.to_le_bytes()); buf.extend_from_slice(&transfer_fee_basis_points.to_le_bytes());
buf.extend_from_slice(&maximum_fee.to_le_bytes()); buf.extend_from_slice(&maximum_fee.to_le_bytes());
} }
&Self::ConfidentialTransferExtension => {
buf.push(29);
}
}; };
buf buf
} }

View File

@ -851,6 +851,13 @@ impl Processor {
TokenInstruction::SetTransferFee { .. } => { TokenInstruction::SetTransferFee { .. } => {
unimplemented!(); unimplemented!();
} }
TokenInstruction::ConfidentialTransferExtension => {
crate::extension::confidential_transfer::processor::process_instruction(
program_id,
accounts,
&input[1..],
)
}
} }
} }