Remove Instruction wrapper structs and name functions after enum fields
This commit is contained in:
@ -6,7 +6,7 @@ use chrono::prelude::{DateTime, Utc};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use solana_sdk::instruction::{AccountMeta, Instruction};
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::system_instruction::SystemInstruction;
|
||||
use solana_sdk::system_instruction;
|
||||
|
||||
/// A smart contract.
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
||||
@ -30,93 +30,90 @@ pub enum BudgetInstruction {
|
||||
ApplySignature,
|
||||
}
|
||||
|
||||
impl BudgetInstruction {
|
||||
fn new_initialize_account(contract: &Pubkey, expr: BudgetExpr) -> Instruction {
|
||||
let mut keys = vec![];
|
||||
if let BudgetExpr::Pay(payment) = &expr {
|
||||
keys.push(AccountMeta::new(payment.to, false));
|
||||
}
|
||||
keys.push(AccountMeta::new(*contract, false));
|
||||
Instruction::new(id(), &BudgetInstruction::InitializeAccount(expr), keys)
|
||||
fn initialize_account(contract: &Pubkey, expr: BudgetExpr) -> Instruction {
|
||||
let mut keys = vec![];
|
||||
if let BudgetExpr::Pay(payment) = &expr {
|
||||
keys.push(AccountMeta::new(payment.to, false));
|
||||
}
|
||||
keys.push(AccountMeta::new(*contract, false));
|
||||
Instruction::new(id(), &BudgetInstruction::InitializeAccount(expr), keys)
|
||||
}
|
||||
|
||||
pub fn new_account(
|
||||
from: &Pubkey,
|
||||
contract: &Pubkey,
|
||||
lamports: u64,
|
||||
expr: BudgetExpr,
|
||||
) -> Vec<Instruction> {
|
||||
if !expr.verify(lamports) {
|
||||
panic!("invalid budget expression");
|
||||
}
|
||||
let space = serialized_size(&BudgetState::new(expr.clone())).unwrap();
|
||||
vec![
|
||||
SystemInstruction::new_account(&from, contract, lamports, space, &id()),
|
||||
BudgetInstruction::new_initialize_account(contract, expr),
|
||||
]
|
||||
pub fn create_account(
|
||||
from: &Pubkey,
|
||||
contract: &Pubkey,
|
||||
lamports: u64,
|
||||
expr: BudgetExpr,
|
||||
) -> Vec<Instruction> {
|
||||
if !expr.verify(lamports) {
|
||||
panic!("invalid budget expression");
|
||||
}
|
||||
let space = serialized_size(&BudgetState::new(expr.clone())).unwrap();
|
||||
vec![
|
||||
system_instruction::create_account(&from, contract, lamports, space, &id()),
|
||||
initialize_account(contract, expr),
|
||||
]
|
||||
}
|
||||
|
||||
/// Create a new payment script.
|
||||
pub fn new_payment(from: &Pubkey, to: &Pubkey, lamports: u64) -> Vec<Instruction> {
|
||||
let contract = Pubkey::new_rand();
|
||||
let expr = BudgetExpr::new_payment(lamports, to);
|
||||
Self::new_account(from, &contract, lamports, expr)
|
||||
}
|
||||
/// Create a new payment script.
|
||||
pub fn payment(from: &Pubkey, to: &Pubkey, lamports: u64) -> Vec<Instruction> {
|
||||
let contract = Pubkey::new_rand();
|
||||
let expr = BudgetExpr::new_payment(lamports, to);
|
||||
create_account(from, &contract, lamports, expr)
|
||||
}
|
||||
|
||||
/// Create a future payment script.
|
||||
pub fn new_on_date(
|
||||
from: &Pubkey,
|
||||
to: &Pubkey,
|
||||
contract: &Pubkey,
|
||||
dt: DateTime<Utc>,
|
||||
dt_pubkey: &Pubkey,
|
||||
cancelable: Option<Pubkey>,
|
||||
lamports: u64,
|
||||
) -> Vec<Instruction> {
|
||||
let expr =
|
||||
BudgetExpr::new_cancelable_future_payment(dt, dt_pubkey, lamports, to, cancelable);
|
||||
Self::new_account(from, contract, lamports, expr)
|
||||
}
|
||||
/// Create a future payment script.
|
||||
pub fn on_date(
|
||||
from: &Pubkey,
|
||||
to: &Pubkey,
|
||||
contract: &Pubkey,
|
||||
dt: DateTime<Utc>,
|
||||
dt_pubkey: &Pubkey,
|
||||
cancelable: Option<Pubkey>,
|
||||
lamports: u64,
|
||||
) -> Vec<Instruction> {
|
||||
let expr = BudgetExpr::new_cancelable_future_payment(dt, dt_pubkey, lamports, to, cancelable);
|
||||
create_account(from, contract, lamports, expr)
|
||||
}
|
||||
|
||||
/// Create a multisig payment script.
|
||||
pub fn new_when_signed(
|
||||
from: &Pubkey,
|
||||
to: &Pubkey,
|
||||
contract: &Pubkey,
|
||||
witness: &Pubkey,
|
||||
cancelable: Option<Pubkey>,
|
||||
lamports: u64,
|
||||
) -> Vec<Instruction> {
|
||||
let expr = BudgetExpr::new_cancelable_authorized_payment(witness, lamports, to, cancelable);
|
||||
Self::new_account(from, contract, lamports, expr)
|
||||
}
|
||||
/// Create a multisig payment script.
|
||||
pub fn when_signed(
|
||||
from: &Pubkey,
|
||||
to: &Pubkey,
|
||||
contract: &Pubkey,
|
||||
witness: &Pubkey,
|
||||
cancelable: Option<Pubkey>,
|
||||
lamports: u64,
|
||||
) -> Vec<Instruction> {
|
||||
let expr = BudgetExpr::new_cancelable_authorized_payment(witness, lamports, to, cancelable);
|
||||
create_account(from, contract, lamports, expr)
|
||||
}
|
||||
|
||||
pub fn new_apply_timestamp(
|
||||
from: &Pubkey,
|
||||
contract: &Pubkey,
|
||||
to: &Pubkey,
|
||||
dt: DateTime<Utc>,
|
||||
) -> Instruction {
|
||||
let mut account_metas = vec![
|
||||
AccountMeta::new(*from, true),
|
||||
AccountMeta::new(*contract, false),
|
||||
];
|
||||
if from != to {
|
||||
account_metas.push(AccountMeta::new(*to, false));
|
||||
}
|
||||
Instruction::new(id(), &BudgetInstruction::ApplyTimestamp(dt), account_metas)
|
||||
pub fn apply_timestamp(
|
||||
from: &Pubkey,
|
||||
contract: &Pubkey,
|
||||
to: &Pubkey,
|
||||
dt: DateTime<Utc>,
|
||||
) -> Instruction {
|
||||
let mut account_metas = vec![
|
||||
AccountMeta::new(*from, true),
|
||||
AccountMeta::new(*contract, false),
|
||||
];
|
||||
if from != to {
|
||||
account_metas.push(AccountMeta::new(*to, false));
|
||||
}
|
||||
Instruction::new(id(), &BudgetInstruction::ApplyTimestamp(dt), account_metas)
|
||||
}
|
||||
|
||||
pub fn new_apply_signature(from: &Pubkey, contract: &Pubkey, to: &Pubkey) -> Instruction {
|
||||
let mut account_metas = vec![
|
||||
AccountMeta::new(*from, true),
|
||||
AccountMeta::new(*contract, false),
|
||||
];
|
||||
if from != to {
|
||||
account_metas.push(AccountMeta::new(*to, false));
|
||||
}
|
||||
Instruction::new(id(), &BudgetInstruction::ApplySignature, account_metas)
|
||||
pub fn apply_signature(from: &Pubkey, contract: &Pubkey, to: &Pubkey) -> Instruction {
|
||||
let mut account_metas = vec![
|
||||
AccountMeta::new(*from, true),
|
||||
AccountMeta::new(*contract, false),
|
||||
];
|
||||
if from != to {
|
||||
account_metas.push(AccountMeta::new(*to, false));
|
||||
}
|
||||
Instruction::new(id(), &BudgetInstruction::ApplySignature, account_metas)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -128,7 +125,7 @@ mod tests {
|
||||
fn test_budget_instruction_verify() {
|
||||
let alice_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
BudgetInstruction::new_payment(&alice_pubkey, &bob_pubkey, 1); // No panic! indicates success.
|
||||
payment(&alice_pubkey, &bob_pubkey, 1); // No panic! indicates success.
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -138,7 +135,7 @@ mod tests {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let budget_pubkey = Pubkey::new_rand();
|
||||
let expr = BudgetExpr::new_payment(2, &bob_pubkey);
|
||||
BudgetInstruction::new_account(&alice_pubkey, &budget_pubkey, 1, expr);
|
||||
create_account(&alice_pubkey, &budget_pubkey, 1, expr);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -148,6 +145,6 @@ mod tests {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let budget_pubkey = Pubkey::new_rand();
|
||||
let expr = BudgetExpr::new_payment(1, &bob_pubkey);
|
||||
BudgetInstruction::new_account(&alice_pubkey, &budget_pubkey, 2, expr);
|
||||
create_account(&alice_pubkey, &budget_pubkey, 2, expr);
|
||||
}
|
||||
}
|
||||
|
@ -143,7 +143,7 @@ pub fn process_instruction(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::budget_instruction::BudgetInstruction;
|
||||
use crate::budget_instruction;
|
||||
use crate::id;
|
||||
use solana_runtime::bank::Bank;
|
||||
use solana_runtime::bank_client::BankClient;
|
||||
@ -166,7 +166,7 @@ mod tests {
|
||||
let bank_client = BankClient::new(&bank);
|
||||
let alice_pubkey = alice_keypair.pubkey();
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let instructions = BudgetInstruction::new_payment(&alice_pubkey, &bob_pubkey, 100);
|
||||
let instructions = budget_instruction::payment(&alice_pubkey, &bob_pubkey, 100);
|
||||
let message = Message::new(instructions);
|
||||
bank_client
|
||||
.process_message(&[&alice_keypair], message)
|
||||
@ -184,7 +184,7 @@ mod tests {
|
||||
let budget_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let witness = Pubkey::new_rand();
|
||||
let instructions = BudgetInstruction::new_when_signed(
|
||||
let instructions = budget_instruction::when_signed(
|
||||
&alice_pubkey,
|
||||
&bob_pubkey,
|
||||
&budget_pubkey,
|
||||
@ -204,7 +204,7 @@ mod tests {
|
||||
.transfer(1, &alice_keypair, &mallory_pubkey)
|
||||
.unwrap();
|
||||
let instruction =
|
||||
BudgetInstruction::new_apply_signature(&mallory_pubkey, &budget_pubkey, &bob_pubkey);
|
||||
budget_instruction::apply_signature(&mallory_pubkey, &budget_pubkey, &bob_pubkey);
|
||||
let mut message = Message::new(vec![instruction]);
|
||||
|
||||
// Attack! Part 2: Point the instruction to the expected, but unsigned, key.
|
||||
@ -231,7 +231,7 @@ mod tests {
|
||||
let budget_pubkey = Pubkey::new_rand();
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let dt = Utc::now();
|
||||
let instructions = BudgetInstruction::new_on_date(
|
||||
let instructions = budget_instruction::on_date(
|
||||
&alice_pubkey,
|
||||
&bob_pubkey,
|
||||
&budget_pubkey,
|
||||
@ -251,12 +251,8 @@ mod tests {
|
||||
bank_client
|
||||
.transfer(1, &alice_keypair, &mallory_pubkey)
|
||||
.unwrap();
|
||||
let instruction = BudgetInstruction::new_apply_timestamp(
|
||||
&mallory_pubkey,
|
||||
&budget_pubkey,
|
||||
&bob_pubkey,
|
||||
dt,
|
||||
);
|
||||
let instruction =
|
||||
budget_instruction::apply_timestamp(&mallory_pubkey, &budget_pubkey, &bob_pubkey, dt);
|
||||
let mut message = Message::new(vec![instruction]);
|
||||
|
||||
// Attack! Part 2: Point the instruction to the expected, but unsigned, key.
|
||||
@ -282,7 +278,7 @@ mod tests {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let mallory_pubkey = Pubkey::new_rand();
|
||||
let dt = Utc::now();
|
||||
let instructions = BudgetInstruction::new_on_date(
|
||||
let instructions = budget_instruction::on_date(
|
||||
&alice_pubkey,
|
||||
&bob_pubkey,
|
||||
&budget_pubkey,
|
||||
@ -303,12 +299,8 @@ mod tests {
|
||||
assert!(budget_state.is_pending());
|
||||
|
||||
// Attack! Try to payout to mallory_pubkey
|
||||
let instruction = BudgetInstruction::new_apply_timestamp(
|
||||
&alice_pubkey,
|
||||
&budget_pubkey,
|
||||
&mallory_pubkey,
|
||||
dt,
|
||||
);
|
||||
let instruction =
|
||||
budget_instruction::apply_timestamp(&alice_pubkey, &budget_pubkey, &mallory_pubkey, dt);
|
||||
assert_eq!(
|
||||
bank_client
|
||||
.process_instruction(&alice_keypair, instruction)
|
||||
@ -329,7 +321,7 @@ mod tests {
|
||||
// Now, acknowledge the time in the condition occurred and
|
||||
// that pubkey's funds are now available.
|
||||
let instruction =
|
||||
BudgetInstruction::new_apply_timestamp(&alice_pubkey, &budget_pubkey, &bob_pubkey, dt);
|
||||
budget_instruction::apply_timestamp(&alice_pubkey, &budget_pubkey, &bob_pubkey, dt);
|
||||
bank_client
|
||||
.process_instruction(&alice_keypair, instruction)
|
||||
.unwrap();
|
||||
@ -348,7 +340,7 @@ mod tests {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let dt = Utc::now();
|
||||
|
||||
let instructions = BudgetInstruction::new_on_date(
|
||||
let instructions = budget_instruction::on_date(
|
||||
&alice_pubkey,
|
||||
&bob_pubkey,
|
||||
&budget_pubkey,
|
||||
@ -377,7 +369,7 @@ mod tests {
|
||||
assert_eq!(bank.get_balance(&alice_pubkey), 1);
|
||||
|
||||
let instruction =
|
||||
BudgetInstruction::new_apply_signature(&mallory_pubkey, &budget_pubkey, &bob_pubkey);
|
||||
budget_instruction::apply_signature(&mallory_pubkey, &budget_pubkey, &bob_pubkey);
|
||||
bank_client
|
||||
.process_instruction(&mallory_keypair, instruction)
|
||||
.unwrap();
|
||||
@ -388,7 +380,7 @@ mod tests {
|
||||
|
||||
// Now, cancel the transaction. mint gets her funds back
|
||||
let instruction =
|
||||
BudgetInstruction::new_apply_signature(&alice_pubkey, &budget_pubkey, &alice_pubkey);
|
||||
budget_instruction::apply_signature(&alice_pubkey, &budget_pubkey, &alice_pubkey);
|
||||
bank_client
|
||||
.process_instruction(&alice_keypair, instruction)
|
||||
.unwrap();
|
||||
|
@ -2,36 +2,32 @@ use crate::id;
|
||||
use crate::ConfigState;
|
||||
use solana_sdk::instruction::{AccountMeta, Instruction};
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::system_instruction::SystemInstruction;
|
||||
use solana_sdk::system_instruction;
|
||||
|
||||
pub struct ConfigInstruction {}
|
||||
|
||||
impl ConfigInstruction {
|
||||
/// Create a new, empty configuration account
|
||||
pub fn new_account<T: ConfigState>(
|
||||
from_account_pubkey: &Pubkey,
|
||||
config_account_pubkey: &Pubkey,
|
||||
lamports: u64,
|
||||
) -> Instruction {
|
||||
SystemInstruction::new_account(
|
||||
from_account_pubkey,
|
||||
config_account_pubkey,
|
||||
lamports,
|
||||
T::max_space(),
|
||||
&id(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Store new data in a configuration account
|
||||
pub fn new_store<T: ConfigState>(
|
||||
from_account_pubkey: &Pubkey,
|
||||
config_account_pubkey: &Pubkey,
|
||||
data: &T,
|
||||
) -> Instruction {
|
||||
let account_metas = vec![
|
||||
AccountMeta::new(*from_account_pubkey, true),
|
||||
AccountMeta::new(*config_account_pubkey, true),
|
||||
];
|
||||
Instruction::new(id(), data, account_metas)
|
||||
}
|
||||
/// Create a new, empty configuration account
|
||||
pub fn create_account<T: ConfigState>(
|
||||
from_account_pubkey: &Pubkey,
|
||||
config_account_pubkey: &Pubkey,
|
||||
lamports: u64,
|
||||
) -> Instruction {
|
||||
system_instruction::create_account(
|
||||
from_account_pubkey,
|
||||
config_account_pubkey,
|
||||
lamports,
|
||||
T::max_space(),
|
||||
&id(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Store new data in a configuration account
|
||||
pub fn store<T: ConfigState>(
|
||||
from_account_pubkey: &Pubkey,
|
||||
config_account_pubkey: &Pubkey,
|
||||
data: &T,
|
||||
) -> Instruction {
|
||||
let account_metas = vec![
|
||||
AccountMeta::new(*from_account_pubkey, true),
|
||||
AccountMeta::new(*config_account_pubkey, true),
|
||||
];
|
||||
Instruction::new(id(), data, account_metas)
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ pub fn process_instruction(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{id, ConfigInstruction, ConfigState};
|
||||
use crate::{config_instruction, id, ConfigState};
|
||||
use bincode::{deserialize, serialized_size};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use solana_runtime::bank::Bank;
|
||||
@ -36,7 +36,7 @@ mod tests {
|
||||
use solana_sdk::genesis_block::GenesisBlock;
|
||||
use solana_sdk::message::Message;
|
||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::system_instruction::SystemInstruction;
|
||||
use solana_sdk::system_instruction;
|
||||
|
||||
#[derive(Serialize, Deserialize, Default, Debug, PartialEq)]
|
||||
struct MyConfig {
|
||||
@ -78,7 +78,7 @@ mod tests {
|
||||
bank_client
|
||||
.process_instruction(
|
||||
&mint_keypair,
|
||||
ConfigInstruction::new_account::<MyConfig>(
|
||||
config_instruction::create_account::<MyConfig>(
|
||||
&mint_keypair.pubkey(),
|
||||
&config_pubkey,
|
||||
1,
|
||||
@ -111,7 +111,7 @@ mod tests {
|
||||
|
||||
let my_config = MyConfig::new(42);
|
||||
let instruction =
|
||||
ConfigInstruction::new_store(&from_keypair.pubkey(), &config_pubkey, &my_config);
|
||||
config_instruction::store(&from_keypair.pubkey(), &config_pubkey, &my_config);
|
||||
let message = Message::new(vec![instruction]);
|
||||
bank_client
|
||||
.process_message(&[&from_keypair, &config_keypair], message)
|
||||
@ -133,11 +133,8 @@ mod tests {
|
||||
let my_config = MyConfig::new(42);
|
||||
|
||||
// Replace instruction data with a vector that's too large
|
||||
let mut instruction = ConfigInstruction::new_store(
|
||||
&from_keypair.pubkey(),
|
||||
&config_keypair.pubkey(),
|
||||
&my_config,
|
||||
);
|
||||
let mut instruction =
|
||||
config_instruction::store(&from_keypair.pubkey(), &config_keypair.pubkey(), &my_config);
|
||||
instruction.data = vec![0; 123];
|
||||
|
||||
let message = Message::new(vec![instruction]);
|
||||
@ -155,14 +152,10 @@ mod tests {
|
||||
bank.transfer(42, &mint_keypair, &system_pubkey).unwrap();
|
||||
let (bank_client, from_keypair, config_keypair) = create_config_client(&bank, mint_keypair);
|
||||
|
||||
let move_instruction =
|
||||
SystemInstruction::new_transfer(&system_pubkey, &Pubkey::default(), 42);
|
||||
let move_instruction = system_instruction::transfer(&system_pubkey, &Pubkey::default(), 42);
|
||||
let my_config = MyConfig::new(42);
|
||||
let mut store_instruction = ConfigInstruction::new_store(
|
||||
&from_keypair.pubkey(),
|
||||
&config_keypair.pubkey(),
|
||||
&my_config,
|
||||
);
|
||||
let mut store_instruction =
|
||||
config_instruction::store(&from_keypair.pubkey(), &config_keypair.pubkey(), &my_config);
|
||||
store_instruction.accounts[0].is_signer = false;
|
||||
store_instruction.accounts[1].is_signer = false;
|
||||
|
||||
|
@ -1,11 +1,9 @@
|
||||
use serde::Serialize;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
|
||||
mod config_instruction;
|
||||
pub mod config_instruction;
|
||||
pub mod config_processor;
|
||||
|
||||
pub use config_instruction::ConfigInstruction;
|
||||
|
||||
const CONFIG_PROGRAM_ID: [u8; 32] = [
|
||||
133, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0,
|
||||
|
@ -59,89 +59,88 @@ pub enum ExchangeInstruction {
|
||||
/// key 6 - Token account in which to deposit the brokers profit from the swap.
|
||||
SwapRequest,
|
||||
}
|
||||
impl ExchangeInstruction {
|
||||
pub fn new_account_request(owner: &Pubkey, new: &Pubkey) -> Instruction {
|
||||
let account_metas = vec![
|
||||
AccountMeta::new(*owner, true),
|
||||
AccountMeta::new(*new, false),
|
||||
];
|
||||
Instruction::new(id(), &ExchangeInstruction::AccountRequest, account_metas)
|
||||
}
|
||||
|
||||
pub fn new_transfer_request(
|
||||
owner: &Pubkey,
|
||||
to: &Pubkey,
|
||||
from: &Pubkey,
|
||||
token: Token,
|
||||
tokens: u64,
|
||||
) -> Instruction {
|
||||
let account_metas = vec![
|
||||
AccountMeta::new(*owner, true),
|
||||
AccountMeta::new(*to, false),
|
||||
AccountMeta::new(*from, false),
|
||||
];
|
||||
Instruction::new(
|
||||
id(),
|
||||
&ExchangeInstruction::TransferRequest(token, tokens),
|
||||
account_metas,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_trade_request(
|
||||
owner: &Pubkey,
|
||||
trade: &Pubkey,
|
||||
direction: Direction,
|
||||
pair: TokenPair,
|
||||
tokens: u64,
|
||||
price: u64,
|
||||
src_account: &Pubkey,
|
||||
dst_account: &Pubkey,
|
||||
) -> Instruction {
|
||||
let account_metas = vec![
|
||||
AccountMeta::new(*owner, true),
|
||||
AccountMeta::new(*trade, false),
|
||||
AccountMeta::new(*src_account, false),
|
||||
];
|
||||
Instruction::new(
|
||||
id(),
|
||||
&ExchangeInstruction::TradeRequest(TradeRequestInfo {
|
||||
direction,
|
||||
pair,
|
||||
tokens,
|
||||
price,
|
||||
dst_account: *dst_account,
|
||||
}),
|
||||
account_metas,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_trade_cancellation(owner: &Pubkey, trade: &Pubkey, account: &Pubkey) -> Instruction {
|
||||
let account_metas = vec![
|
||||
AccountMeta::new(*owner, true),
|
||||
AccountMeta::new(*trade, false),
|
||||
AccountMeta::new(*account, false),
|
||||
];
|
||||
Instruction::new(id(), &ExchangeInstruction::TradeCancellation, account_metas)
|
||||
}
|
||||
|
||||
pub fn new_swap_request(
|
||||
owner: &Pubkey,
|
||||
swap: &Pubkey,
|
||||
to_trade: &Pubkey,
|
||||
from_trade: &Pubkey,
|
||||
to_trade_account: &Pubkey,
|
||||
from_trade_account: &Pubkey,
|
||||
profit_account: &Pubkey,
|
||||
) -> Instruction {
|
||||
let account_metas = vec![
|
||||
AccountMeta::new(*owner, true),
|
||||
AccountMeta::new(*swap, false),
|
||||
AccountMeta::new(*to_trade, false),
|
||||
AccountMeta::new(*from_trade, false),
|
||||
AccountMeta::new(*to_trade_account, false),
|
||||
AccountMeta::new(*from_trade_account, false),
|
||||
AccountMeta::new(*profit_account, false),
|
||||
];
|
||||
Instruction::new(id(), &ExchangeInstruction::SwapRequest, account_metas)
|
||||
}
|
||||
pub fn account_request(owner: &Pubkey, new: &Pubkey) -> Instruction {
|
||||
let account_metas = vec![
|
||||
AccountMeta::new(*owner, true),
|
||||
AccountMeta::new(*new, false),
|
||||
];
|
||||
Instruction::new(id(), &ExchangeInstruction::AccountRequest, account_metas)
|
||||
}
|
||||
|
||||
pub fn transfer_request(
|
||||
owner: &Pubkey,
|
||||
to: &Pubkey,
|
||||
from: &Pubkey,
|
||||
token: Token,
|
||||
tokens: u64,
|
||||
) -> Instruction {
|
||||
let account_metas = vec![
|
||||
AccountMeta::new(*owner, true),
|
||||
AccountMeta::new(*to, false),
|
||||
AccountMeta::new(*from, false),
|
||||
];
|
||||
Instruction::new(
|
||||
id(),
|
||||
&ExchangeInstruction::TransferRequest(token, tokens),
|
||||
account_metas,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn trade_request(
|
||||
owner: &Pubkey,
|
||||
trade: &Pubkey,
|
||||
direction: Direction,
|
||||
pair: TokenPair,
|
||||
tokens: u64,
|
||||
price: u64,
|
||||
src_account: &Pubkey,
|
||||
dst_account: &Pubkey,
|
||||
) -> Instruction {
|
||||
let account_metas = vec![
|
||||
AccountMeta::new(*owner, true),
|
||||
AccountMeta::new(*trade, false),
|
||||
AccountMeta::new(*src_account, false),
|
||||
];
|
||||
Instruction::new(
|
||||
id(),
|
||||
&ExchangeInstruction::TradeRequest(TradeRequestInfo {
|
||||
direction,
|
||||
pair,
|
||||
tokens,
|
||||
price,
|
||||
dst_account: *dst_account,
|
||||
}),
|
||||
account_metas,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn trade_cancellation(owner: &Pubkey, trade: &Pubkey, account: &Pubkey) -> Instruction {
|
||||
let account_metas = vec![
|
||||
AccountMeta::new(*owner, true),
|
||||
AccountMeta::new(*trade, false),
|
||||
AccountMeta::new(*account, false),
|
||||
];
|
||||
Instruction::new(id(), &ExchangeInstruction::TradeCancellation, account_metas)
|
||||
}
|
||||
|
||||
pub fn swap_request(
|
||||
owner: &Pubkey,
|
||||
swap: &Pubkey,
|
||||
to_trade: &Pubkey,
|
||||
from_trade: &Pubkey,
|
||||
to_trade_account: &Pubkey,
|
||||
from_trade_account: &Pubkey,
|
||||
profit_account: &Pubkey,
|
||||
) -> Instruction {
|
||||
let account_metas = vec![
|
||||
AccountMeta::new(*owner, true),
|
||||
AccountMeta::new(*swap, false),
|
||||
AccountMeta::new(*to_trade, false),
|
||||
AccountMeta::new(*from_trade, false),
|
||||
AccountMeta::new(*to_trade_account, false),
|
||||
AccountMeta::new(*from_trade_account, false),
|
||||
AccountMeta::new(*profit_account, false),
|
||||
];
|
||||
Instruction::new(id(), &ExchangeInstruction::SwapRequest, account_metas)
|
||||
}
|
||||
|
@ -412,11 +412,12 @@ pub fn process_instruction(
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::exchange_instruction;
|
||||
use solana_runtime::bank::Bank;
|
||||
use solana_runtime::bank_client::BankClient;
|
||||
use solana_sdk::genesis_block::GenesisBlock;
|
||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::system_instruction::SystemInstruction;
|
||||
use solana_sdk::system_instruction;
|
||||
use std::mem;
|
||||
|
||||
fn try_calc(
|
||||
@ -527,7 +528,7 @@ mod test {
|
||||
|
||||
fn create_account(client: &BankClient, owner: &Keypair) -> Pubkey {
|
||||
let new = Pubkey::new_rand();
|
||||
let instruction = SystemInstruction::new_account(
|
||||
let instruction = system_instruction::create_account(
|
||||
&owner.pubkey(),
|
||||
&new,
|
||||
1,
|
||||
@ -542,7 +543,7 @@ mod test {
|
||||
|
||||
fn create_token_account(client: &BankClient, owner: &Keypair) -> Pubkey {
|
||||
let new = Pubkey::new_rand();
|
||||
let instruction = SystemInstruction::new_account(
|
||||
let instruction = system_instruction::create_account(
|
||||
&owner.pubkey(),
|
||||
&new,
|
||||
1,
|
||||
@ -552,7 +553,7 @@ mod test {
|
||||
client
|
||||
.process_instruction(owner, instruction)
|
||||
.expect(&format!("{}:{}", line!(), file!()));
|
||||
let instruction = ExchangeInstruction::new_account_request(&owner.pubkey(), &new);
|
||||
let instruction = exchange_instruction::account_request(&owner.pubkey(), &new);
|
||||
client
|
||||
.process_instruction(owner, instruction)
|
||||
.expect(&format!("{}:{}", line!(), file!()));
|
||||
@ -561,7 +562,7 @@ mod test {
|
||||
|
||||
fn transfer(client: &BankClient, owner: &Keypair, to: &Pubkey, token: Token, tokens: u64) {
|
||||
let instruction =
|
||||
ExchangeInstruction::new_transfer_request(&owner.pubkey(), to, &id(), token, tokens);
|
||||
exchange_instruction::transfer_request(&owner.pubkey(), to, &id(), token, tokens);
|
||||
client
|
||||
.process_instruction(owner, instruction)
|
||||
.expect(&format!("{}:{}", line!(), file!()));
|
||||
@ -582,7 +583,7 @@ mod test {
|
||||
let dst = create_token_account(&client, &owner);
|
||||
transfer(&client, &owner, &src, from_token, src_tokens);
|
||||
|
||||
let instruction = ExchangeInstruction::new_trade_request(
|
||||
let instruction = exchange_instruction::trade_request(
|
||||
&owner.pubkey(),
|
||||
&trade,
|
||||
direction,
|
||||
@ -633,7 +634,7 @@ mod test {
|
||||
let (client, owner) = create_client(&bank, mint_keypair);
|
||||
|
||||
let new = create_token_account(&client, &owner);
|
||||
let instruction = ExchangeInstruction::new_account_request(&owner.pubkey(), &new);
|
||||
let instruction = exchange_instruction::account_request(&owner.pubkey(), &new);
|
||||
client
|
||||
.process_instruction(&owner, instruction)
|
||||
.expect_err(&format!("{}:{}", line!(), file!()));
|
||||
@ -648,7 +649,7 @@ mod test {
|
||||
let new = create_token_account(&client, &owner);
|
||||
|
||||
let instruction =
|
||||
ExchangeInstruction::new_transfer_request(&owner.pubkey(), &new, &id(), Token::A, 42);
|
||||
exchange_instruction::transfer_request(&owner.pubkey(), &new, &id(), Token::A, 42);
|
||||
client
|
||||
.process_instruction(&owner, instruction)
|
||||
.expect(&format!("{}:{}", line!(), file!()));
|
||||
@ -743,7 +744,7 @@ mod test {
|
||||
3000,
|
||||
);
|
||||
|
||||
let instruction = ExchangeInstruction::new_swap_request(
|
||||
let instruction = exchange_instruction::swap_request(
|
||||
&owner.pubkey(),
|
||||
&swap,
|
||||
&to_trade,
|
||||
|
@ -1,120 +1,103 @@
|
||||
use crate::exchange_instruction::*;
|
||||
use crate::exchange_instruction;
|
||||
use crate::exchange_state::*;
|
||||
use crate::id;
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::system_instruction::SystemInstruction;
|
||||
use solana_sdk::system_instruction;
|
||||
use solana_sdk::transaction::Transaction;
|
||||
use std::mem;
|
||||
|
||||
pub struct ExchangeTransaction {}
|
||||
|
||||
impl ExchangeTransaction {
|
||||
pub fn new_account_request(
|
||||
owner: &Keypair,
|
||||
new: &Pubkey,
|
||||
recent_blockhash: Hash,
|
||||
_fee: u64,
|
||||
) -> Transaction {
|
||||
let owner_id = &owner.pubkey();
|
||||
let space = mem::size_of::<ExchangeState>() as u64;
|
||||
let create_ix = SystemInstruction::new_account(owner_id, new, 1, space, &id());
|
||||
let request_ix = ExchangeInstruction::new_account_request(owner_id, new);
|
||||
Transaction::new_signed_instructions(
|
||||
&[owner],
|
||||
vec![create_ix, request_ix],
|
||||
recent_blockhash,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_transfer_request(
|
||||
owner: &Keypair,
|
||||
to: &Pubkey,
|
||||
from: &Pubkey,
|
||||
token: Token,
|
||||
tokens: u64,
|
||||
recent_blockhash: Hash,
|
||||
_fee: u64,
|
||||
) -> Transaction {
|
||||
let owner_id = &owner.pubkey();
|
||||
let request_ix =
|
||||
ExchangeInstruction::new_transfer_request(owner_id, to, from, token, tokens);
|
||||
Transaction::new_signed_instructions(&[owner], vec![request_ix], recent_blockhash)
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new_trade_request(
|
||||
owner: &Keypair,
|
||||
trade: &Pubkey,
|
||||
direction: Direction,
|
||||
pair: TokenPair,
|
||||
tokens: u64,
|
||||
price: u64,
|
||||
src_account: &Pubkey,
|
||||
dst_account: &Pubkey,
|
||||
recent_blockhash: Hash,
|
||||
_fee: u64,
|
||||
) -> Transaction {
|
||||
let owner_id = &owner.pubkey();
|
||||
let space = mem::size_of::<ExchangeState>() as u64;
|
||||
let create_ix = SystemInstruction::new_account(owner_id, trade, 1, space, &id());
|
||||
let request_ix = ExchangeInstruction::new_trade_request(
|
||||
owner_id,
|
||||
trade,
|
||||
direction,
|
||||
pair,
|
||||
tokens,
|
||||
price,
|
||||
src_account,
|
||||
dst_account,
|
||||
);
|
||||
Transaction::new_signed_instructions(
|
||||
&[owner],
|
||||
vec![create_ix, request_ix],
|
||||
recent_blockhash,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_trade_cancellation(
|
||||
owner: &Keypair,
|
||||
trade: &Pubkey,
|
||||
account: &Pubkey,
|
||||
recent_blockhash: Hash,
|
||||
_fee: u64,
|
||||
) -> Transaction {
|
||||
let owner_id = &owner.pubkey();
|
||||
let request_ix = ExchangeInstruction::new_trade_cancellation(owner_id, trade, account);
|
||||
Transaction::new_signed_instructions(&[owner], vec![request_ix], recent_blockhash)
|
||||
}
|
||||
|
||||
pub fn new_swap_request(
|
||||
owner: &Keypair,
|
||||
swap: &Pubkey,
|
||||
to_trade: &Pubkey,
|
||||
from_trade: &Pubkey,
|
||||
to_trade_account: &Pubkey,
|
||||
from_trade_account: &Pubkey,
|
||||
profit_account: &Pubkey,
|
||||
recent_blockhash: Hash,
|
||||
_fee: u64,
|
||||
) -> Transaction {
|
||||
let owner_id = &owner.pubkey();
|
||||
let space = mem::size_of::<ExchangeState>() as u64;
|
||||
let create_ix = SystemInstruction::new_account(owner_id, swap, 1, space, &id());
|
||||
let request_ix = ExchangeInstruction::new_swap_request(
|
||||
owner_id,
|
||||
swap,
|
||||
to_trade,
|
||||
from_trade,
|
||||
to_trade_account,
|
||||
from_trade_account,
|
||||
profit_account,
|
||||
);
|
||||
Transaction::new_signed_instructions(
|
||||
&[owner],
|
||||
vec![create_ix, request_ix],
|
||||
recent_blockhash,
|
||||
)
|
||||
}
|
||||
pub fn account_request(
|
||||
owner: &Keypair,
|
||||
new: &Pubkey,
|
||||
recent_blockhash: Hash,
|
||||
_fee: u64,
|
||||
) -> Transaction {
|
||||
let owner_id = &owner.pubkey();
|
||||
let space = mem::size_of::<ExchangeState>() as u64;
|
||||
let create_ix = system_instruction::create_account(owner_id, new, 1, space, &id());
|
||||
let request_ix = exchange_instruction::account_request(owner_id, new);
|
||||
Transaction::new_signed_instructions(&[owner], vec![create_ix, request_ix], recent_blockhash)
|
||||
}
|
||||
|
||||
pub fn transfer_request(
|
||||
owner: &Keypair,
|
||||
to: &Pubkey,
|
||||
from: &Pubkey,
|
||||
token: Token,
|
||||
tokens: u64,
|
||||
recent_blockhash: Hash,
|
||||
_fee: u64,
|
||||
) -> Transaction {
|
||||
let owner_id = &owner.pubkey();
|
||||
let request_ix = exchange_instruction::transfer_request(owner_id, to, from, token, tokens);
|
||||
Transaction::new_signed_instructions(&[owner], vec![request_ix], recent_blockhash)
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn trade_request(
|
||||
owner: &Keypair,
|
||||
trade: &Pubkey,
|
||||
direction: Direction,
|
||||
pair: TokenPair,
|
||||
tokens: u64,
|
||||
price: u64,
|
||||
src_account: &Pubkey,
|
||||
dst_account: &Pubkey,
|
||||
recent_blockhash: Hash,
|
||||
_fee: u64,
|
||||
) -> Transaction {
|
||||
let owner_id = &owner.pubkey();
|
||||
let space = mem::size_of::<ExchangeState>() as u64;
|
||||
let create_ix = system_instruction::create_account(owner_id, trade, 1, space, &id());
|
||||
let request_ix = exchange_instruction::trade_request(
|
||||
owner_id,
|
||||
trade,
|
||||
direction,
|
||||
pair,
|
||||
tokens,
|
||||
price,
|
||||
src_account,
|
||||
dst_account,
|
||||
);
|
||||
Transaction::new_signed_instructions(&[owner], vec![create_ix, request_ix], recent_blockhash)
|
||||
}
|
||||
|
||||
pub fn trade_cancellation(
|
||||
owner: &Keypair,
|
||||
trade: &Pubkey,
|
||||
account: &Pubkey,
|
||||
recent_blockhash: Hash,
|
||||
_fee: u64,
|
||||
) -> Transaction {
|
||||
let owner_id = &owner.pubkey();
|
||||
let request_ix = exchange_instruction::trade_cancellation(owner_id, trade, account);
|
||||
Transaction::new_signed_instructions(&[owner], vec![request_ix], recent_blockhash)
|
||||
}
|
||||
|
||||
pub fn swap_request(
|
||||
owner: &Keypair,
|
||||
swap: &Pubkey,
|
||||
to_trade: &Pubkey,
|
||||
from_trade: &Pubkey,
|
||||
to_trade_account: &Pubkey,
|
||||
from_trade_account: &Pubkey,
|
||||
profit_account: &Pubkey,
|
||||
recent_blockhash: Hash,
|
||||
_fee: u64,
|
||||
) -> Transaction {
|
||||
let owner_id = &owner.pubkey();
|
||||
let space = mem::size_of::<ExchangeState>() as u64;
|
||||
let create_ix = system_instruction::create_account(owner_id, swap, 1, space, &id());
|
||||
let request_ix = exchange_instruction::swap_request(
|
||||
owner_id,
|
||||
swap,
|
||||
to_trade,
|
||||
from_trade,
|
||||
to_trade_account,
|
||||
from_trade_account,
|
||||
profit_account,
|
||||
);
|
||||
Transaction::new_signed_instructions(&[owner], vec![create_ix, request_ix], recent_blockhash)
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ use serde_derive::{Deserialize, Serialize};
|
||||
use solana_sdk::account::KeyedAccount;
|
||||
use solana_sdk::instruction::{AccountMeta, Instruction, InstructionError};
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::system_instruction::SystemInstruction;
|
||||
use solana_sdk::system_instruction;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
||||
pub enum StakeInstruction {
|
||||
@ -22,44 +22,38 @@ pub enum StakeInstruction {
|
||||
RedeemVoteCredits,
|
||||
}
|
||||
|
||||
impl StakeInstruction {
|
||||
pub fn new_account(from_id: &Pubkey, staker_id: &Pubkey, lamports: u64) -> Vec<Instruction> {
|
||||
vec![SystemInstruction::new_account(
|
||||
from_id,
|
||||
staker_id,
|
||||
lamports,
|
||||
std::mem::size_of::<StakeState>() as u64,
|
||||
&id(),
|
||||
)]
|
||||
}
|
||||
pub fn create_account(from_id: &Pubkey, staker_id: &Pubkey, lamports: u64) -> Vec<Instruction> {
|
||||
vec![system_instruction::create_account(
|
||||
from_id,
|
||||
staker_id,
|
||||
lamports,
|
||||
std::mem::size_of::<StakeState>() as u64,
|
||||
&id(),
|
||||
)]
|
||||
}
|
||||
|
||||
pub fn new_redeem_vote_credits(
|
||||
from_id: &Pubkey,
|
||||
mining_pool_id: &Pubkey,
|
||||
stake_id: &Pubkey,
|
||||
vote_id: &Pubkey,
|
||||
) -> Instruction {
|
||||
let account_metas = vec![
|
||||
AccountMeta::new(*from_id, true),
|
||||
AccountMeta::new(*mining_pool_id, false),
|
||||
AccountMeta::new(*stake_id, false),
|
||||
AccountMeta::new(*vote_id, false),
|
||||
];
|
||||
Instruction::new(id(), &StakeInstruction::RedeemVoteCredits, account_metas)
|
||||
}
|
||||
pub fn redeem_vote_credits(
|
||||
from_id: &Pubkey,
|
||||
mining_pool_id: &Pubkey,
|
||||
stake_id: &Pubkey,
|
||||
vote_id: &Pubkey,
|
||||
) -> Instruction {
|
||||
let account_metas = vec![
|
||||
AccountMeta::new(*from_id, true),
|
||||
AccountMeta::new(*mining_pool_id, false),
|
||||
AccountMeta::new(*stake_id, false),
|
||||
AccountMeta::new(*vote_id, false),
|
||||
];
|
||||
Instruction::new(id(), &StakeInstruction::RedeemVoteCredits, account_metas)
|
||||
}
|
||||
|
||||
pub fn new_delegate_stake(
|
||||
from_id: &Pubkey,
|
||||
stake_id: &Pubkey,
|
||||
vote_id: &Pubkey,
|
||||
) -> Instruction {
|
||||
let account_metas = vec![
|
||||
AccountMeta::new(*from_id, true),
|
||||
AccountMeta::new(*stake_id, true),
|
||||
AccountMeta::new(*vote_id, false),
|
||||
];
|
||||
Instruction::new(id(), &StakeInstruction::DelegateStake, account_metas)
|
||||
}
|
||||
pub fn delegate_stake(from_id: &Pubkey, stake_id: &Pubkey, vote_id: &Pubkey) -> Instruction {
|
||||
let account_metas = vec![
|
||||
AccountMeta::new(*from_id, true),
|
||||
AccountMeta::new(*stake_id, true),
|
||||
AccountMeta::new(*vote_id, false),
|
||||
];
|
||||
Instruction::new(id(), &StakeInstruction::DelegateStake, account_metas)
|
||||
}
|
||||
|
||||
pub fn process_instruction(
|
||||
|
@ -26,51 +26,49 @@ pub enum StorageInstruction {
|
||||
},
|
||||
}
|
||||
|
||||
impl StorageInstruction {
|
||||
pub fn new_mining_proof(
|
||||
from_pubkey: &Pubkey,
|
||||
sha_state: Hash,
|
||||
entry_height: u64,
|
||||
signature: Signature,
|
||||
) -> Instruction {
|
||||
let storage_instruction = StorageInstruction::SubmitMiningProof {
|
||||
sha_state,
|
||||
entry_height,
|
||||
signature,
|
||||
};
|
||||
let account_metas = vec![AccountMeta::new(*from_pubkey, true)];
|
||||
Instruction::new(id(), &storage_instruction, account_metas)
|
||||
}
|
||||
|
||||
pub fn new_advertise_recent_blockhash(
|
||||
from_pubkey: &Pubkey,
|
||||
storage_hash: Hash,
|
||||
entry_height: u64,
|
||||
) -> Instruction {
|
||||
let storage_instruction = StorageInstruction::AdvertiseStorageRecentBlockhash {
|
||||
hash: storage_hash,
|
||||
entry_height,
|
||||
};
|
||||
let account_metas = vec![AccountMeta::new(*from_pubkey, true)];
|
||||
Instruction::new(id(), &storage_instruction, account_metas)
|
||||
}
|
||||
|
||||
pub fn new_proof_validation(
|
||||
from_pubkey: &Pubkey,
|
||||
entry_height: u64,
|
||||
proof_mask: Vec<ProofStatus>,
|
||||
) -> Instruction {
|
||||
let storage_instruction = StorageInstruction::ProofValidation {
|
||||
entry_height,
|
||||
proof_mask,
|
||||
};
|
||||
let account_metas = vec![AccountMeta::new(*from_pubkey, true)];
|
||||
Instruction::new(id(), &storage_instruction, account_metas)
|
||||
}
|
||||
|
||||
pub fn new_reward_claim(from_pubkey: &Pubkey, entry_height: u64) -> Instruction {
|
||||
let storage_instruction = StorageInstruction::ClaimStorageReward { entry_height };
|
||||
let account_metas = vec![AccountMeta::new(*from_pubkey, true)];
|
||||
Instruction::new(id(), &storage_instruction, account_metas)
|
||||
}
|
||||
pub fn mining_proof(
|
||||
from_pubkey: &Pubkey,
|
||||
sha_state: Hash,
|
||||
entry_height: u64,
|
||||
signature: Signature,
|
||||
) -> Instruction {
|
||||
let storage_instruction = StorageInstruction::SubmitMiningProof {
|
||||
sha_state,
|
||||
entry_height,
|
||||
signature,
|
||||
};
|
||||
let account_metas = vec![AccountMeta::new(*from_pubkey, true)];
|
||||
Instruction::new(id(), &storage_instruction, account_metas)
|
||||
}
|
||||
|
||||
pub fn advertise_recent_blockhash(
|
||||
from_pubkey: &Pubkey,
|
||||
storage_hash: Hash,
|
||||
entry_height: u64,
|
||||
) -> Instruction {
|
||||
let storage_instruction = StorageInstruction::AdvertiseStorageRecentBlockhash {
|
||||
hash: storage_hash,
|
||||
entry_height,
|
||||
};
|
||||
let account_metas = vec![AccountMeta::new(*from_pubkey, true)];
|
||||
Instruction::new(id(), &storage_instruction, account_metas)
|
||||
}
|
||||
|
||||
pub fn proof_validation(
|
||||
from_pubkey: &Pubkey,
|
||||
entry_height: u64,
|
||||
proof_mask: Vec<ProofStatus>,
|
||||
) -> Instruction {
|
||||
let storage_instruction = StorageInstruction::ProofValidation {
|
||||
entry_height,
|
||||
proof_mask,
|
||||
};
|
||||
let account_metas = vec![AccountMeta::new(*from_pubkey, true)];
|
||||
Instruction::new(id(), &storage_instruction, account_metas)
|
||||
}
|
||||
|
||||
pub fn reward_claim(from_pubkey: &Pubkey, entry_height: u64) -> Instruction {
|
||||
let storage_instruction = StorageInstruction::ClaimStorageReward { entry_height };
|
||||
let account_metas = vec![AccountMeta::new(*from_pubkey, true)];
|
||||
Instruction::new(id(), &storage_instruction, account_metas)
|
||||
}
|
||||
|
@ -171,6 +171,7 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::id;
|
||||
use crate::storage_contract::ProofStatus;
|
||||
use crate::storage_instruction;
|
||||
use crate::ENTRIES_PER_SEGMENT;
|
||||
use bincode::deserialize;
|
||||
use solana_runtime::bank::Bank;
|
||||
@ -181,7 +182,7 @@ mod tests {
|
||||
use solana_sdk::instruction::Instruction;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::signature::{Keypair, KeypairUtil, Signature};
|
||||
use solana_sdk::system_instruction::SystemInstruction;
|
||||
use solana_sdk::system_instruction;
|
||||
|
||||
fn test_instruction(
|
||||
ix: &Instruction,
|
||||
@ -216,7 +217,7 @@ mod tests {
|
||||
let mut user_account = Account::default();
|
||||
keyed_accounts.push(KeyedAccount::new(&pubkey, true, &mut user_account));
|
||||
|
||||
let ix = StorageInstruction::new_advertise_recent_blockhash(
|
||||
let ix = storage_instruction::advertise_recent_blockhash(
|
||||
&pubkey,
|
||||
Hash::default(),
|
||||
ENTRIES_PER_SEGMENT,
|
||||
@ -234,7 +235,7 @@ mod tests {
|
||||
let mut accounts = [Account::default()];
|
||||
|
||||
let ix =
|
||||
StorageInstruction::new_mining_proof(&pubkey, Hash::default(), 0, Signature::default());
|
||||
storage_instruction::mining_proof(&pubkey, Hash::default(), 0, Signature::default());
|
||||
assert!(test_instruction(&ix, &mut accounts).is_err());
|
||||
|
||||
let mut accounts = [Account::default(), Account::default(), Account::default()];
|
||||
@ -250,7 +251,7 @@ mod tests {
|
||||
accounts[1].data.resize(16 * 1024, 0);
|
||||
|
||||
let ix =
|
||||
StorageInstruction::new_mining_proof(&pubkey, Hash::default(), 0, Signature::default());
|
||||
storage_instruction::mining_proof(&pubkey, Hash::default(), 0, Signature::default());
|
||||
|
||||
// Haven't seen a transaction to roll over the epoch, so this should fail
|
||||
assert!(test_instruction(&ix, &mut accounts).is_err());
|
||||
@ -263,7 +264,7 @@ mod tests {
|
||||
let mut accounts = [Account::default(), Account::default()];
|
||||
accounts[0].data.resize(16 * 1024, 0);
|
||||
|
||||
let ix = StorageInstruction::new_advertise_recent_blockhash(
|
||||
let ix = storage_instruction::advertise_recent_blockhash(
|
||||
&pubkey,
|
||||
Hash::default(),
|
||||
ENTRIES_PER_SEGMENT,
|
||||
@ -272,7 +273,7 @@ mod tests {
|
||||
test_instruction(&ix, &mut accounts).unwrap();
|
||||
|
||||
let ix =
|
||||
StorageInstruction::new_mining_proof(&pubkey, Hash::default(), 0, Signature::default());
|
||||
storage_instruction::mining_proof(&pubkey, Hash::default(), 0, Signature::default());
|
||||
|
||||
test_instruction(&ix, &mut accounts).unwrap();
|
||||
}
|
||||
@ -286,7 +287,7 @@ mod tests {
|
||||
|
||||
let entry_height = 0;
|
||||
|
||||
let ix = StorageInstruction::new_advertise_recent_blockhash(
|
||||
let ix = storage_instruction::advertise_recent_blockhash(
|
||||
&pubkey,
|
||||
Hash::default(),
|
||||
ENTRIES_PER_SEGMENT,
|
||||
@ -294,7 +295,7 @@ mod tests {
|
||||
|
||||
test_instruction(&ix, &mut accounts).unwrap();
|
||||
|
||||
let ix = StorageInstruction::new_mining_proof(
|
||||
let ix = storage_instruction::mining_proof(
|
||||
&pubkey,
|
||||
Hash::default(),
|
||||
entry_height,
|
||||
@ -302,28 +303,25 @@ mod tests {
|
||||
);
|
||||
test_instruction(&ix, &mut accounts).unwrap();
|
||||
|
||||
let ix = StorageInstruction::new_advertise_recent_blockhash(
|
||||
let ix = storage_instruction::advertise_recent_blockhash(
|
||||
&pubkey,
|
||||
Hash::default(),
|
||||
ENTRIES_PER_SEGMENT * 2,
|
||||
);
|
||||
test_instruction(&ix, &mut accounts).unwrap();
|
||||
|
||||
let ix = StorageInstruction::new_proof_validation(
|
||||
&pubkey,
|
||||
entry_height,
|
||||
vec![ProofStatus::Valid],
|
||||
);
|
||||
let ix =
|
||||
storage_instruction::proof_validation(&pubkey, entry_height, vec![ProofStatus::Valid]);
|
||||
test_instruction(&ix, &mut accounts).unwrap();
|
||||
|
||||
let ix = StorageInstruction::new_advertise_recent_blockhash(
|
||||
let ix = storage_instruction::advertise_recent_blockhash(
|
||||
&pubkey,
|
||||
Hash::default(),
|
||||
ENTRIES_PER_SEGMENT * 3,
|
||||
);
|
||||
test_instruction(&ix, &mut accounts).unwrap();
|
||||
|
||||
let ix = StorageInstruction::new_reward_claim(&pubkey, entry_height);
|
||||
let ix = storage_instruction::reward_claim(&pubkey, entry_height);
|
||||
test_instruction(&ix, &mut accounts).unwrap();
|
||||
|
||||
assert!(accounts[0].lamports == TOTAL_VALIDATOR_REWARDS);
|
||||
@ -386,11 +384,11 @@ mod tests {
|
||||
.transfer(10, &alice_keypair, &jack_pubkey)
|
||||
.unwrap();
|
||||
|
||||
let ix = SystemInstruction::new_account(&alice_pubkey, &bob_pubkey, 1, 4 * 1024, &id());
|
||||
let ix = system_instruction::create_account(&alice_pubkey, &bob_pubkey, 1, 4 * 1024, &id());
|
||||
|
||||
bank_client.process_instruction(&alice_keypair, ix).unwrap();
|
||||
|
||||
let ix = StorageInstruction::new_advertise_recent_blockhash(
|
||||
let ix = storage_instruction::advertise_recent_blockhash(
|
||||
&bob_pubkey,
|
||||
storage_blockhash,
|
||||
ENTRIES_PER_SEGMENT,
|
||||
@ -399,7 +397,7 @@ mod tests {
|
||||
bank_client.process_instruction(&bob_keypair, ix).unwrap();
|
||||
|
||||
let entry_height = 0;
|
||||
let ix = StorageInstruction::new_mining_proof(
|
||||
let ix = storage_instruction::mining_proof(
|
||||
&bob_pubkey,
|
||||
Hash::default(),
|
||||
entry_height,
|
||||
|
@ -3,7 +3,7 @@ use crate::vote_state::VoteState;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use solana_sdk::instruction::{AccountMeta, Instruction};
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::system_instruction::SystemInstruction;
|
||||
use solana_sdk::system_instruction;
|
||||
|
||||
#[derive(Serialize, Default, Deserialize, Debug, PartialEq, Eq, Clone)]
|
||||
pub struct Vote {
|
||||
@ -37,44 +37,42 @@ pub enum VoteInstruction {
|
||||
ClearCredits,
|
||||
}
|
||||
|
||||
impl VoteInstruction {
|
||||
fn new_initialize_account(vote_id: &Pubkey) -> Instruction {
|
||||
let account_metas = vec![AccountMeta::new(*vote_id, false)];
|
||||
Instruction::new(id(), &VoteInstruction::InitializeAccount, account_metas)
|
||||
}
|
||||
|
||||
pub fn new_account(from_id: &Pubkey, staker_id: &Pubkey, lamports: u64) -> Vec<Instruction> {
|
||||
let space = VoteState::max_size() as u64;
|
||||
let create_ix = SystemInstruction::new_account(&from_id, staker_id, lamports, space, &id());
|
||||
let init_ix = VoteInstruction::new_initialize_account(staker_id);
|
||||
vec![create_ix, init_ix]
|
||||
}
|
||||
|
||||
pub fn new_clear_credits(vote_id: &Pubkey) -> Instruction {
|
||||
let account_metas = vec![AccountMeta::new(*vote_id, true)];
|
||||
Instruction::new(id(), &VoteInstruction::ClearCredits, account_metas)
|
||||
}
|
||||
|
||||
pub fn new_delegate_stake(vote_id: &Pubkey, delegate_id: &Pubkey) -> Instruction {
|
||||
let account_metas = vec![AccountMeta::new(*vote_id, true)];
|
||||
Instruction::new(
|
||||
id(),
|
||||
&VoteInstruction::DelegateStake(*delegate_id),
|
||||
account_metas,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_authorize_voter(vote_id: &Pubkey, authorized_voter_id: &Pubkey) -> Instruction {
|
||||
let account_metas = vec![AccountMeta::new(*vote_id, true)];
|
||||
Instruction::new(
|
||||
id(),
|
||||
&VoteInstruction::AuthorizeVoter(*authorized_voter_id),
|
||||
account_metas,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_vote(vote_id: &Pubkey, vote: Vote) -> Instruction {
|
||||
let account_metas = vec![AccountMeta::new(*vote_id, true)];
|
||||
Instruction::new(id(), &VoteInstruction::Vote(vote), account_metas)
|
||||
}
|
||||
fn initialize_account(vote_id: &Pubkey) -> Instruction {
|
||||
let account_metas = vec![AccountMeta::new(*vote_id, false)];
|
||||
Instruction::new(id(), &VoteInstruction::InitializeAccount, account_metas)
|
||||
}
|
||||
|
||||
pub fn create_account(from_id: &Pubkey, staker_id: &Pubkey, lamports: u64) -> Vec<Instruction> {
|
||||
let space = VoteState::max_size() as u64;
|
||||
let create_ix = system_instruction::create_account(&from_id, staker_id, lamports, space, &id());
|
||||
let init_ix = initialize_account(staker_id);
|
||||
vec![create_ix, init_ix]
|
||||
}
|
||||
|
||||
pub fn clear_credits(vote_id: &Pubkey) -> Instruction {
|
||||
let account_metas = vec![AccountMeta::new(*vote_id, true)];
|
||||
Instruction::new(id(), &VoteInstruction::ClearCredits, account_metas)
|
||||
}
|
||||
|
||||
pub fn delegate_stake(vote_id: &Pubkey, delegate_id: &Pubkey) -> Instruction {
|
||||
let account_metas = vec![AccountMeta::new(*vote_id, true)];
|
||||
Instruction::new(
|
||||
id(),
|
||||
&VoteInstruction::DelegateStake(*delegate_id),
|
||||
account_metas,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn authorize_voter(vote_id: &Pubkey, authorized_voter_id: &Pubkey) -> Instruction {
|
||||
let account_metas = vec![AccountMeta::new(*vote_id, true)];
|
||||
Instruction::new(
|
||||
id(),
|
||||
&VoteInstruction::AuthorizeVoter(*authorized_voter_id),
|
||||
account_metas,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn vote(vote_id: &Pubkey, vote: Vote) -> Instruction {
|
||||
let account_metas = vec![AccountMeta::new(*vote_id, true)];
|
||||
Instruction::new(id(), &VoteInstruction::Vote(vote), account_metas)
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ pub fn process_instruction(
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::id;
|
||||
use crate::vote_instruction::{Vote, VoteInstruction};
|
||||
use crate::vote_instruction::{self, Vote};
|
||||
use crate::vote_state::VoteState;
|
||||
use solana_runtime::bank::{Bank, Result};
|
||||
use solana_runtime::bank_client::BankClient;
|
||||
@ -54,7 +54,7 @@ mod tests {
|
||||
use solana_sdk::message::Message;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::system_instruction::SystemInstruction;
|
||||
use solana_sdk::system_instruction;
|
||||
use solana_sdk::transaction::TransactionError;
|
||||
|
||||
fn create_bank(lamports: u64) -> (Bank, Keypair) {
|
||||
@ -70,7 +70,7 @@ mod tests {
|
||||
vote_id: &Pubkey,
|
||||
lamports: u64,
|
||||
) -> Result<()> {
|
||||
let ixs = VoteInstruction::new_account(&from_keypair.pubkey(), vote_id, lamports);
|
||||
let ixs = vote_instruction::create_account(&from_keypair.pubkey(), vote_id, lamports);
|
||||
let message = Message::new(ixs);
|
||||
bank_client.process_message(&[from_keypair], message)
|
||||
}
|
||||
@ -83,8 +83,8 @@ mod tests {
|
||||
lamports: u64,
|
||||
) -> Result<()> {
|
||||
let vote_id = vote_keypair.pubkey();
|
||||
let mut ixs = VoteInstruction::new_account(&from_keypair.pubkey(), &vote_id, lamports);
|
||||
let delegate_ix = VoteInstruction::new_delegate_stake(&vote_id, delegate_id);
|
||||
let mut ixs = vote_instruction::create_account(&from_keypair.pubkey(), &vote_id, lamports);
|
||||
let delegate_ix = vote_instruction::delegate_stake(&vote_id, delegate_id);
|
||||
ixs.push(delegate_ix);
|
||||
let message = Message::new(ixs);
|
||||
bank_client.process_message(&[&from_keypair, vote_keypair], message)
|
||||
@ -95,7 +95,7 @@ mod tests {
|
||||
vote_keypair: &Keypair,
|
||||
tick_height: u64,
|
||||
) -> Result<()> {
|
||||
let vote_ix = VoteInstruction::new_vote(&vote_keypair.pubkey(), Vote::new(tick_height));
|
||||
let vote_ix = vote_instruction::vote(&vote_keypair.pubkey(), Vote::new(tick_height));
|
||||
bank_client.process_instruction(&vote_keypair, vote_ix)
|
||||
}
|
||||
|
||||
@ -142,13 +142,13 @@ mod tests {
|
||||
create_vote_account(&bank_client, &mallory_keypair, &vote_id, 100).unwrap();
|
||||
|
||||
let mallory_id = mallory_keypair.pubkey();
|
||||
let mut vote_ix = VoteInstruction::new_vote(&vote_id, Vote::new(0));
|
||||
let mut vote_ix = vote_instruction::vote(&vote_id, Vote::new(0));
|
||||
vote_ix.accounts[0].is_signer = false; // <--- attack!! No signer required.
|
||||
|
||||
// Sneak in an instruction so that the transaction is signed but
|
||||
// the 0th account in the second instruction is not! The program
|
||||
// needs to check that it's signed.
|
||||
let move_ix = SystemInstruction::new_transfer(&mallory_id, &vote_id, 1);
|
||||
let move_ix = system_instruction::transfer(&mallory_id, &vote_id, 1);
|
||||
let message = Message::new(vec![move_ix, vote_ix]);
|
||||
let result = bank_client.process_message(&[&mallory_keypair], message);
|
||||
|
||||
|
Reference in New Issue
Block a user