Add Confidential Transfer Extension boilerplate
This commit is contained in:
parent
0a98473f0a
commit
5fe1eb6a9d
|
@ -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",
|
||||||
]
|
]
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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, &())
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)]
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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..],
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue