Move budget_program out of src/
This commit is contained in:
parent
27d456bf93
commit
9ee858a00c
|
@ -1762,6 +1762,7 @@ dependencies = [
|
||||||
"sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"solana-bpfloader 0.11.0",
|
"solana-bpfloader 0.11.0",
|
||||||
|
"solana-budget-program 0.11.0",
|
||||||
"solana-drone 0.11.0",
|
"solana-drone 0.11.0",
|
||||||
"solana-erc20 0.11.0",
|
"solana-erc20 0.11.0",
|
||||||
"solana-jsonrpc-core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"solana-jsonrpc-core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1806,6 +1807,19 @@ dependencies = [
|
||||||
"solana_rbpf 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"solana_rbpf 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "solana-budget-program"
|
||||||
|
version = "0.11.0"
|
||||||
|
dependencies = [
|
||||||
|
"bincode 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"solana-sdk 0.11.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "solana-drone"
|
name = "solana-drone"
|
||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
|
@ -1949,6 +1963,7 @@ dependencies = [
|
||||||
"bincode 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bincode 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1987,6 +2002,7 @@ name = "solana-vote-program"
|
||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bincode 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bincode 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
|
@ -98,6 +98,7 @@ serde_json = "1.0.10"
|
||||||
sha2 = "0.8.0"
|
sha2 = "0.8.0"
|
||||||
socket2 = "0.3.8"
|
socket2 = "0.3.8"
|
||||||
solana-bpfloader = { path = "programs/native/bpf_loader", version = "0.11.0" }
|
solana-bpfloader = { path = "programs/native/bpf_loader", version = "0.11.0" }
|
||||||
|
solana-budget-program = { path = "programs/native/budget", version = "0.11.0" }
|
||||||
solana-drone = { path = "drone", version = "0.11.0" }
|
solana-drone = { path = "drone", version = "0.11.0" }
|
||||||
solana-erc20 = { path = "programs/native/erc20", version = "0.11.0" }
|
solana-erc20 = { path = "programs/native/erc20", version = "0.11.0" }
|
||||||
solana-jsonrpc-core = "0.3.0"
|
solana-jsonrpc-core = "0.3.0"
|
||||||
|
@ -148,6 +149,7 @@ members = [
|
||||||
"sdk",
|
"sdk",
|
||||||
"programs/bpf/rust/noop",
|
"programs/bpf/rust/noop",
|
||||||
"programs/native/bpf_loader",
|
"programs/native/bpf_loader",
|
||||||
|
"programs/native/budget",
|
||||||
"programs/native/erc20",
|
"programs/native/erc20",
|
||||||
"programs/native/lua_loader",
|
"programs/native/lua_loader",
|
||||||
"programs/native/noop",
|
"programs/native/noop",
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
[package]
|
||||||
|
name = "solana-budget-program"
|
||||||
|
version = "0.11.0"
|
||||||
|
description = "Solana budget program"
|
||||||
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
|
repository = "https://github.com/solana-labs/solana"
|
||||||
|
license = "Apache-2.0"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
bincode = "1.0.0"
|
||||||
|
chrono = { version = "0.4.0", features = ["serde"] }
|
||||||
|
env_logger = "0.6.0"
|
||||||
|
log = "0.4.2"
|
||||||
|
serde = "1.0.27"
|
||||||
|
serde_derive = "1.0.27"
|
||||||
|
solana-sdk = { path = "../../../sdk", version = "0.11.0" }
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "solana_budget_program"
|
||||||
|
crate-type = ["cdylib"]
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
//! budget program
|
//! budget program
|
||||||
use bincode::{self, deserialize, serialize_into, serialized_size};
|
use bincode::{self, deserialize, serialize_into, serialized_size};
|
||||||
use budget_expr::BudgetExpr;
|
|
||||||
use budget_instruction::Instruction;
|
|
||||||
use chrono::prelude::{DateTime, Utc};
|
use chrono::prelude::{DateTime, Utc};
|
||||||
use payment_plan::Witness;
|
use solana_sdk::account::KeyedAccount;
|
||||||
use solana_sdk::account::Account;
|
use solana_sdk::budget_expr::BudgetExpr;
|
||||||
use solana_sdk::native_program::ProgramError;
|
use solana_sdk::budget_instruction::Instruction;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::payment_plan::Witness;
|
||||||
use solana_sdk::transaction::Transaction;
|
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
||||||
|
@ -31,26 +28,11 @@ pub struct BudgetProgram {
|
||||||
pub pending_budget: Option<BudgetExpr>,
|
pub pending_budget: Option<BudgetExpr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
const BUDGET_PROGRAM_ID: [u8; 32] = [
|
|
||||||
129, 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,
|
|
||||||
];
|
|
||||||
|
|
||||||
pub fn id() -> Pubkey {
|
|
||||||
Pubkey::new(&BUDGET_PROGRAM_ID)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn check_id(program_id: &Pubkey) -> bool {
|
|
||||||
program_id.as_ref() == BUDGET_PROGRAM_ID
|
|
||||||
}
|
|
||||||
|
|
||||||
fn apply_debits(
|
fn apply_debits(
|
||||||
tx: &Transaction,
|
keyed_accounts: &mut [KeyedAccount],
|
||||||
instruction_index: usize,
|
|
||||||
accounts: &mut [&mut Account],
|
|
||||||
instruction: &Instruction,
|
instruction: &Instruction,
|
||||||
) -> Result<(), BudgetError> {
|
) -> Result<(), BudgetError> {
|
||||||
if !accounts[0].userdata.is_empty() {
|
if !keyed_accounts[0].account.userdata.is_empty() {
|
||||||
trace!("source is pending");
|
trace!("source is pending");
|
||||||
return Err(BudgetError::SourceIsPendingContract);
|
return Err(BudgetError::SourceIsPendingContract);
|
||||||
}
|
}
|
||||||
|
@ -58,25 +40,26 @@ fn apply_debits(
|
||||||
Instruction::NewBudget(expr) => {
|
Instruction::NewBudget(expr) => {
|
||||||
let expr = expr.clone();
|
let expr = expr.clone();
|
||||||
if let Some(payment) = expr.final_payment() {
|
if let Some(payment) = expr.final_payment() {
|
||||||
accounts[1].tokens += payment.tokens;
|
keyed_accounts[1].account.tokens += payment.tokens;
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
let existing = BudgetProgram::deserialize(&accounts[1].userdata).ok();
|
let existing = BudgetProgram::deserialize(&keyed_accounts[1].account.userdata).ok();
|
||||||
if Some(true) == existing.map(|x| x.initialized) {
|
if Some(true) == existing.map(|x| x.initialized) {
|
||||||
trace!("contract already exists");
|
trace!("contract already exists");
|
||||||
Err(BudgetError::ContractAlreadyExists)
|
Err(BudgetError::ContractAlreadyExists)
|
||||||
} else {
|
} else {
|
||||||
let mut program = BudgetProgram::default();
|
let mut program = BudgetProgram::default();
|
||||||
program.pending_budget = Some(expr);
|
program.pending_budget = Some(expr);
|
||||||
accounts[1].tokens += accounts[0].tokens;
|
keyed_accounts[1].account.tokens += keyed_accounts[0].account.tokens;
|
||||||
accounts[0].tokens = 0;
|
keyed_accounts[0].account.tokens = 0;
|
||||||
program.initialized = true;
|
program.initialized = true;
|
||||||
program.serialize(&mut accounts[1].userdata)
|
program.serialize(&mut keyed_accounts[1].account.userdata)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Instruction::ApplyTimestamp(dt) => {
|
Instruction::ApplyTimestamp(dt) => {
|
||||||
if let Ok(mut program) = BudgetProgram::deserialize(&accounts[1].userdata) {
|
if let Ok(mut program) = BudgetProgram::deserialize(&keyed_accounts[1].account.userdata)
|
||||||
|
{
|
||||||
if !program.is_pending() {
|
if !program.is_pending() {
|
||||||
Err(BudgetError::ContractNotPending)
|
Err(BudgetError::ContractNotPending)
|
||||||
} else if !program.initialized {
|
} else if !program.initialized {
|
||||||
|
@ -84,16 +67,17 @@ fn apply_debits(
|
||||||
Err(BudgetError::UninitializedContract)
|
Err(BudgetError::UninitializedContract)
|
||||||
} else {
|
} else {
|
||||||
trace!("apply timestamp");
|
trace!("apply timestamp");
|
||||||
program.apply_timestamp(tx, instruction_index, accounts, *dt)?;
|
program.apply_timestamp(keyed_accounts, *dt)?;
|
||||||
trace!("apply timestamp committed");
|
trace!("apply timestamp committed");
|
||||||
program.serialize(&mut accounts[1].userdata)
|
program.serialize(&mut keyed_accounts[1].account.userdata)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(BudgetError::UninitializedContract)
|
Err(BudgetError::UninitializedContract)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Instruction::ApplySignature => {
|
Instruction::ApplySignature => {
|
||||||
if let Ok(mut program) = BudgetProgram::deserialize(&accounts[1].userdata) {
|
if let Ok(mut program) = BudgetProgram::deserialize(&keyed_accounts[1].account.userdata)
|
||||||
|
{
|
||||||
if !program.is_pending() {
|
if !program.is_pending() {
|
||||||
Err(BudgetError::ContractNotPending)
|
Err(BudgetError::ContractNotPending)
|
||||||
} else if !program.initialized {
|
} else if !program.initialized {
|
||||||
|
@ -101,9 +85,9 @@ fn apply_debits(
|
||||||
Err(BudgetError::UninitializedContract)
|
Err(BudgetError::UninitializedContract)
|
||||||
} else {
|
} else {
|
||||||
trace!("apply signature");
|
trace!("apply signature");
|
||||||
program.apply_signature(tx, instruction_index, accounts)?;
|
program.apply_signature(keyed_accounts)?;
|
||||||
trace!("apply signature committed");
|
trace!("apply signature committed");
|
||||||
program.serialize(&mut accounts[1].userdata)
|
program.serialize(&mut keyed_accounts[1].account.userdata)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(BudgetError::UninitializedContract)
|
Err(BudgetError::UninitializedContract)
|
||||||
|
@ -113,36 +97,24 @@ fn apply_debits(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Budget DSL contract interface
|
/// Budget DSL contract interface
|
||||||
/// * tx - the transaction
|
|
||||||
/// * accounts[0] - The source of the tokens
|
/// * accounts[0] - The source of the tokens
|
||||||
/// * accounts[1] - The contract context. Once the contract has been completed, the tokens can
|
/// * accounts[1] - The contract context. Once the contract has been completed, the tokens can
|
||||||
/// be spent from this account .
|
/// be spent from this account .
|
||||||
pub fn process_instruction(
|
pub fn process_instruction(
|
||||||
tx: &Transaction,
|
keyed_accounts: &mut [KeyedAccount],
|
||||||
instruction_index: usize,
|
data: &[u8],
|
||||||
accounts: &mut [&mut Account],
|
|
||||||
) -> Result<(), BudgetError> {
|
) -> Result<(), BudgetError> {
|
||||||
if let Ok(instruction) = deserialize(tx.userdata(instruction_index)) {
|
if let Ok(instruction) = deserialize(data) {
|
||||||
trace!("process_instruction: {:?}", instruction);
|
trace!("process_instruction: {:?}", instruction);
|
||||||
apply_debits(tx, instruction_index, accounts, &instruction)
|
apply_debits(keyed_accounts, &instruction)
|
||||||
} else {
|
} else {
|
||||||
info!(
|
info!("Invalid transaction userdata: {:?}", data);
|
||||||
"Invalid transaction userdata: {:?}",
|
|
||||||
tx.userdata(instruction_index)
|
|
||||||
);
|
|
||||||
Err(BudgetError::UserdataDeserializeFailure)
|
Err(BudgetError::UserdataDeserializeFailure)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn process(
|
// TODO: Re-instate budget_program special case in bank.rs?
|
||||||
tx: &Transaction,
|
/*
|
||||||
instruction_index: usize,
|
|
||||||
accounts: &mut [&mut Account],
|
|
||||||
) -> std::result::Result<(), ProgramError> {
|
|
||||||
process_instruction(&tx, instruction_index, accounts).map_err(|_| ProgramError::GenericError)
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO the contract needs to provide a "get_balance" introspection call of the userdata
|
|
||||||
pub fn get_balance(account: &Account) -> u64 {
|
pub fn get_balance(account: &Account) -> u64 {
|
||||||
if let Ok(program) = deserialize(&account.userdata) {
|
if let Ok(program) = deserialize(&account.userdata) {
|
||||||
let program: BudgetProgram = program;
|
let program: BudgetProgram = program;
|
||||||
|
@ -155,6 +127,7 @@ pub fn get_balance(account: &Account) -> u64 {
|
||||||
account.tokens
|
account.tokens
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
impl BudgetProgram {
|
impl BudgetProgram {
|
||||||
fn is_pending(&self) -> bool {
|
fn is_pending(&self) -> bool {
|
||||||
|
@ -162,15 +135,10 @@ impl BudgetProgram {
|
||||||
}
|
}
|
||||||
/// Process a Witness Signature. Any payment plans waiting on this signature
|
/// Process a Witness Signature. Any payment plans waiting on this signature
|
||||||
/// will progress one step.
|
/// will progress one step.
|
||||||
fn apply_signature(
|
fn apply_signature(&mut self, keyed_accounts: &mut [KeyedAccount]) -> Result<(), BudgetError> {
|
||||||
&mut self,
|
|
||||||
tx: &Transaction,
|
|
||||||
instruction_index: usize,
|
|
||||||
accounts: &mut [&mut Account],
|
|
||||||
) -> Result<(), BudgetError> {
|
|
||||||
let mut final_payment = None;
|
let mut final_payment = None;
|
||||||
if let Some(ref mut expr) = self.pending_budget {
|
if let Some(ref mut expr) = self.pending_budget {
|
||||||
let key = match tx.signer_key(instruction_index, 0) {
|
let key = match keyed_accounts[0].signer_key() {
|
||||||
None => return Err(BudgetError::UnsignedKey),
|
None => return Err(BudgetError::UnsignedKey),
|
||||||
Some(key) => key,
|
Some(key) => key,
|
||||||
};
|
};
|
||||||
|
@ -179,13 +147,13 @@ impl BudgetProgram {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(payment) = final_payment {
|
if let Some(payment) = final_payment {
|
||||||
if Some(&payment.to) != tx.key(instruction_index, 2) {
|
if &payment.to != keyed_accounts[2].unsigned_key() {
|
||||||
trace!("destination missing");
|
trace!("destination missing");
|
||||||
return Err(BudgetError::DestinationMissing);
|
return Err(BudgetError::DestinationMissing);
|
||||||
}
|
}
|
||||||
self.pending_budget = None;
|
self.pending_budget = None;
|
||||||
accounts[1].tokens -= payment.tokens;
|
keyed_accounts[1].account.tokens -= payment.tokens;
|
||||||
accounts[2].tokens += payment.tokens;
|
keyed_accounts[2].account.tokens += payment.tokens;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -194,16 +162,14 @@ impl BudgetProgram {
|
||||||
/// will progress one step.
|
/// will progress one step.
|
||||||
fn apply_timestamp(
|
fn apply_timestamp(
|
||||||
&mut self,
|
&mut self,
|
||||||
tx: &Transaction,
|
keyed_accounts: &mut [KeyedAccount],
|
||||||
instruction_index: usize,
|
|
||||||
accounts: &mut [&mut Account],
|
|
||||||
dt: DateTime<Utc>,
|
dt: DateTime<Utc>,
|
||||||
) -> Result<(), BudgetError> {
|
) -> Result<(), BudgetError> {
|
||||||
// Check to see if any timelocked transactions can be completed.
|
// Check to see if any timelocked transactions can be completed.
|
||||||
let mut final_payment = None;
|
let mut final_payment = None;
|
||||||
|
|
||||||
if let Some(ref mut expr) = self.pending_budget {
|
if let Some(ref mut expr) = self.pending_budget {
|
||||||
let key = match tx.signer_key(instruction_index, 0) {
|
let key = match keyed_accounts[0].signer_key() {
|
||||||
None => return Err(BudgetError::UnsignedKey),
|
None => return Err(BudgetError::UnsignedKey),
|
||||||
Some(key) => key,
|
Some(key) => key,
|
||||||
};
|
};
|
||||||
|
@ -212,13 +178,13 @@ impl BudgetProgram {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(payment) = final_payment {
|
if let Some(payment) = final_payment {
|
||||||
if Some(&payment.to) != tx.key(instruction_index, 2) {
|
if &payment.to != keyed_accounts[2].unsigned_key() {
|
||||||
trace!("destination missing");
|
trace!("destination missing");
|
||||||
return Err(BudgetError::DestinationMissing);
|
return Err(BudgetError::DestinationMissing);
|
||||||
}
|
}
|
||||||
self.pending_budget = None;
|
self.pending_budget = None;
|
||||||
accounts[1].tokens -= payment.tokens;
|
keyed_accounts[1].account.tokens -= payment.tokens;
|
||||||
accounts[2].tokens += payment.tokens;
|
keyed_accounts[2].account.tokens += payment.tokens;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -259,22 +225,40 @@ impl BudgetProgram {
|
||||||
deserialize(&input[8..8 + len as usize])
|
deserialize(&input[8..8 + len as usize])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use bincode::serialize;
|
use bincode::serialize;
|
||||||
use budget_transaction::BudgetTransaction;
|
|
||||||
use chrono::prelude::{DateTime, NaiveDate, Utc};
|
|
||||||
use signature::GenKeys;
|
|
||||||
use solana_sdk::account::Account;
|
use solana_sdk::account::Account;
|
||||||
|
use solana_sdk::budget_program::*;
|
||||||
|
use solana_sdk::budget_transaction::BudgetTransaction;
|
||||||
use solana_sdk::hash::Hash;
|
use solana_sdk::hash::Hash;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||||
use solana_sdk::transaction::Transaction;
|
use solana_sdk::transaction::{Instruction, Transaction};
|
||||||
|
|
||||||
fn process_transaction(tx: &Transaction, accounts: &mut [Account]) -> Result<(), BudgetError> {
|
fn process_transaction(
|
||||||
let mut refs: Vec<&mut Account> = accounts.iter_mut().collect();
|
tx: &Transaction,
|
||||||
super::process_instruction(&tx, 0, &mut refs[..])
|
program_accounts: &mut [Account],
|
||||||
|
) -> Result<(), BudgetError> {
|
||||||
|
assert_eq!(tx.instructions.len(), 1);
|
||||||
|
let Instruction {
|
||||||
|
ref accounts,
|
||||||
|
ref userdata,
|
||||||
|
..
|
||||||
|
} = tx.instructions[0];
|
||||||
|
|
||||||
|
let mut keyed_accounts: Vec<_> = accounts
|
||||||
|
.iter()
|
||||||
|
.map(|&index| {
|
||||||
|
let index = index as usize;
|
||||||
|
let key = &tx.account_keys[index];
|
||||||
|
(key, index < tx.signatures.len())
|
||||||
|
}).zip(program_accounts.iter_mut())
|
||||||
|
.map(|((key, is_signer), account)| KeyedAccount::new(key, is_signer, account))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
super::process_instruction(&mut keyed_accounts, &userdata)
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_serializer() {
|
fn test_serializer() {
|
||||||
|
@ -574,77 +558,4 @@ mod test {
|
||||||
|
|
||||||
// Success if there was no panic...
|
// Success if there was no panic...
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Detect binary changes in the serialized contract userdata, which could have a downstream
|
|
||||||
/// affect on SDKs and DApps
|
|
||||||
#[test]
|
|
||||||
fn test_sdk_serialize() {
|
|
||||||
let keypair = &GenKeys::new([0u8; 32]).gen_n_keypairs(1)[0];
|
|
||||||
let to = Pubkey::new(&[
|
|
||||||
1, 1, 1, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 8, 7, 6, 5, 4,
|
|
||||||
1, 1, 1,
|
|
||||||
]);
|
|
||||||
let contract = Pubkey::new(&[
|
|
||||||
2, 2, 2, 4, 5, 6, 7, 8, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 8, 7, 6, 5, 4,
|
|
||||||
2, 2, 2,
|
|
||||||
]);
|
|
||||||
let date =
|
|
||||||
DateTime::<Utc>::from_utc(NaiveDate::from_ymd(2016, 7, 8).and_hms(9, 10, 11), Utc);
|
|
||||||
let date_iso8601 = "2016-07-08T09:10:11Z";
|
|
||||||
|
|
||||||
let tx = Transaction::budget_new(&keypair, to, 192, Hash::default());
|
|
||||||
assert_eq!(
|
|
||||||
tx.userdata(0).to_vec(),
|
|
||||||
vec![2, 0, 0, 0, 192, 0, 0, 0, 0, 0, 0, 0]
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
tx.userdata(1).to_vec(),
|
|
||||||
vec![
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 4, 5, 6, 7, 8, 9, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 8, 7, 6, 5, 4, 1, 1, 1
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
let tx = Transaction::budget_new_on_date(
|
|
||||||
&keypair,
|
|
||||||
to,
|
|
||||||
contract,
|
|
||||||
date,
|
|
||||||
keypair.pubkey(),
|
|
||||||
Some(keypair.pubkey()),
|
|
||||||
192,
|
|
||||||
Hash::default(),
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
tx.userdata(0).to_vec(),
|
|
||||||
vec![
|
|
||||||
0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 50, 48, 49, 54, 45,
|
|
||||||
48, 55, 45, 48, 56, 84, 48, 57, 58, 49, 48, 58, 49, 49, 90, 32, 253, 186, 201, 177,
|
|
||||||
11, 117, 135, 187, 167, 181, 188, 22, 59, 206, 105, 231, 150, 215, 30, 78, 212, 76,
|
|
||||||
16, 252, 180, 72, 134, 137, 247, 161, 68, 192, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 4, 5,
|
|
||||||
6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 8, 7, 6, 5, 4, 1, 1, 1, 1,
|
|
||||||
0, 0, 0, 32, 253, 186, 201, 177, 11, 117, 135, 187, 167, 181, 188, 22, 59, 206,
|
|
||||||
105, 231, 150, 215, 30, 78, 212, 76, 16, 252, 180, 72, 134, 137, 247, 161, 68, 192,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 32, 253, 186, 201, 177, 11, 117, 135, 187, 167, 181, 188, 22,
|
|
||||||
59, 206, 105, 231, 150, 215, 30, 78, 212, 76, 16, 252, 180, 72, 134, 137, 247, 161,
|
|
||||||
68
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
// ApplyTimestamp(date)
|
|
||||||
let tx = Transaction::budget_new_timestamp(
|
|
||||||
&keypair,
|
|
||||||
keypair.pubkey(),
|
|
||||||
to,
|
|
||||||
date,
|
|
||||||
Hash::default(),
|
|
||||||
);
|
|
||||||
let mut expected_userdata = vec![1, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0];
|
|
||||||
expected_userdata.extend(date_iso8601.as_bytes());
|
|
||||||
assert_eq!(tx.userdata(0).to_vec(), expected_userdata);
|
|
||||||
|
|
||||||
// ApplySignature
|
|
||||||
let tx = Transaction::budget_new_signature(&keypair, keypair.pubkey(), to, Hash::default());
|
|
||||||
assert_eq!(tx.userdata(0).to_vec(), vec![2, 0, 0, 0]);
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
extern crate bincode;
|
||||||
|
extern crate chrono;
|
||||||
|
extern crate env_logger;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate log;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate serde_derive;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate solana_sdk;
|
||||||
|
|
||||||
|
mod budget_program;
|
||||||
|
|
||||||
|
use solana_sdk::account::KeyedAccount;
|
||||||
|
use solana_sdk::native_program::ProgramError;
|
||||||
|
use solana_sdk::pubkey::Pubkey;
|
||||||
|
use std::sync::{Once, ONCE_INIT};
|
||||||
|
|
||||||
|
use budget_program::process_instruction;
|
||||||
|
|
||||||
|
solana_entrypoint!(entrypoint);
|
||||||
|
fn entrypoint(
|
||||||
|
_program_id: &Pubkey,
|
||||||
|
keyed_accounts: &mut [KeyedAccount],
|
||||||
|
data: &[u8],
|
||||||
|
_tick_height: u64,
|
||||||
|
) -> Result<(), ProgramError> {
|
||||||
|
static INIT: Once = ONCE_INIT;
|
||||||
|
INIT.call_once(|| {
|
||||||
|
// env_logger can only be initialized once
|
||||||
|
env_logger::init();
|
||||||
|
});
|
||||||
|
|
||||||
|
trace!("process_instruction: {:?}", data);
|
||||||
|
trace!("keyed_accounts: {:?}", keyed_accounts);
|
||||||
|
process_instruction(keyed_accounts, data).map_err(|_| ProgramError::GenericError)
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ license = "Apache-2.0"
|
||||||
bincode = "1.0.0"
|
bincode = "1.0.0"
|
||||||
byteorder = "1.2.1"
|
byteorder = "1.2.1"
|
||||||
bs58 = "0.2.0"
|
bs58 = "0.2.0"
|
||||||
|
chrono = { version = "0.4.0", features = ["serde"] }
|
||||||
generic-array = { version = "0.12.0", default-features = false, features = ["serde"] }
|
generic-array = { version = "0.12.0", default-features = false, features = ["serde"] }
|
||||||
log = "0.4.2"
|
log = "0.4.2"
|
||||||
ring = "0.13.2"
|
ring = "0.13.2"
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
use chrono::prelude::*;
|
use chrono::prelude::*;
|
||||||
use payment_plan::{Payment, Witness};
|
use payment_plan::{Payment, Witness};
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use pubkey::Pubkey;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
/// A data type representing a `Witness` that the payment plan is waiting on.
|
/// A data type representing a `Witness` that the payment plan is waiting on.
|
||||||
|
@ -141,7 +141,7 @@ impl BudgetExpr {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
use signature::{Keypair, KeypairUtil};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_signature_satisfied() {
|
fn test_signature_satisfied() {
|
|
@ -0,0 +1,14 @@
|
||||||
|
use pubkey::Pubkey;
|
||||||
|
|
||||||
|
pub const BUDGET_PROGRAM_ID: [u8; 32] = [
|
||||||
|
129, 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,
|
||||||
|
];
|
||||||
|
|
||||||
|
pub fn id() -> Pubkey {
|
||||||
|
Pubkey::new(&BUDGET_PROGRAM_ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check_id(program_id: &Pubkey) -> bool {
|
||||||
|
program_id.as_ref() == BUDGET_PROGRAM_ID
|
||||||
|
}
|
|
@ -5,14 +5,13 @@ use budget_expr::{BudgetExpr, Condition};
|
||||||
use budget_instruction::Instruction;
|
use budget_instruction::Instruction;
|
||||||
use budget_program;
|
use budget_program;
|
||||||
use chrono::prelude::*;
|
use chrono::prelude::*;
|
||||||
|
use hash::Hash;
|
||||||
use payment_plan::Payment;
|
use payment_plan::Payment;
|
||||||
use solana_sdk::hash::Hash;
|
use pubkey::Pubkey;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use signature::{Keypair, KeypairUtil};
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
use system_instruction::SystemInstruction;
|
||||||
use solana_sdk::system_instruction::SystemInstruction;
|
use system_program;
|
||||||
use solana_sdk::system_program;
|
use transaction::{self, Transaction};
|
||||||
|
|
||||||
use solana_sdk::transaction::{self, Transaction};
|
|
||||||
|
|
||||||
pub trait BudgetTransaction {
|
pub trait BudgetTransaction {
|
||||||
fn budget_new_taxed(
|
fn budget_new_taxed(
|
|
@ -1,10 +1,15 @@
|
||||||
pub mod account;
|
pub mod account;
|
||||||
pub mod bpf_loader;
|
pub mod bpf_loader;
|
||||||
|
pub mod budget_expr;
|
||||||
|
pub mod budget_instruction;
|
||||||
|
pub mod budget_program;
|
||||||
|
pub mod budget_transaction;
|
||||||
pub mod hash;
|
pub mod hash;
|
||||||
pub mod loader_instruction;
|
pub mod loader_instruction;
|
||||||
pub mod native_loader;
|
pub mod native_loader;
|
||||||
pub mod native_program;
|
pub mod native_program;
|
||||||
pub mod packet;
|
pub mod packet;
|
||||||
|
pub mod payment_plan;
|
||||||
pub mod pubkey;
|
pub mod pubkey;
|
||||||
pub mod signature;
|
pub mod signature;
|
||||||
pub mod storage_program;
|
pub mod storage_program;
|
||||||
|
@ -18,6 +23,7 @@ pub mod vote_program;
|
||||||
extern crate bincode;
|
extern crate bincode;
|
||||||
extern crate bs58;
|
extern crate bs58;
|
||||||
extern crate byteorder;
|
extern crate byteorder;
|
||||||
|
extern crate chrono;
|
||||||
extern crate generic_array;
|
extern crate generic_array;
|
||||||
extern crate log;
|
extern crate log;
|
||||||
extern crate ring;
|
extern crate ring;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
//! `Payment`, the payment is executed.
|
//! `Payment`, the payment is executed.
|
||||||
|
|
||||||
use chrono::prelude::*;
|
use chrono::prelude::*;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use pubkey::Pubkey;
|
||||||
|
|
||||||
/// The types of events a payment plan can process.
|
/// The types of events a payment plan can process.
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
26
src/bank.rs
26
src/bank.rs
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
use bincode::deserialize;
|
use bincode::deserialize;
|
||||||
use bincode::serialize;
|
use bincode::serialize;
|
||||||
use budget_program;
|
|
||||||
use counter::Counter;
|
use counter::Counter;
|
||||||
use entry::Entry;
|
use entry::Entry;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
@ -15,7 +14,6 @@ use ledger::Block;
|
||||||
use log::Level;
|
use log::Level;
|
||||||
use mint::Mint;
|
use mint::Mint;
|
||||||
use native_loader;
|
use native_loader;
|
||||||
use payment_plan::Payment;
|
|
||||||
use poh_recorder::PohRecorder;
|
use poh_recorder::PohRecorder;
|
||||||
use poh_service::NUM_TICKS_PER_SECOND;
|
use poh_service::NUM_TICKS_PER_SECOND;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
@ -23,8 +21,10 @@ use rpc::RpcSignatureStatus;
|
||||||
use runtime::{self, RuntimeError};
|
use runtime::{self, RuntimeError};
|
||||||
use solana_sdk::account::Account;
|
use solana_sdk::account::Account;
|
||||||
use solana_sdk::bpf_loader;
|
use solana_sdk::bpf_loader;
|
||||||
|
use solana_sdk::budget_program;
|
||||||
use solana_sdk::hash::{hash, Hash};
|
use solana_sdk::hash::{hash, Hash};
|
||||||
use solana_sdk::native_program::ProgramError;
|
use solana_sdk::native_program::ProgramError;
|
||||||
|
use solana_sdk::payment_plan::Payment;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
use solana_sdk::signature::Keypair;
|
use solana_sdk::signature::Keypair;
|
||||||
use solana_sdk::signature::Signature;
|
use solana_sdk::signature::Signature;
|
||||||
|
@ -448,6 +448,16 @@ impl Bank {
|
||||||
|
|
||||||
accounts.store(&bpf_loader::id(), &bpf_loader_account);
|
accounts.store(&bpf_loader::id(), &bpf_loader_account);
|
||||||
|
|
||||||
|
// Budget program
|
||||||
|
let budget_program_account = Account {
|
||||||
|
tokens: 1,
|
||||||
|
owner: budget_program::id(),
|
||||||
|
userdata: b"solana_budget_program".to_vec(),
|
||||||
|
executable: true,
|
||||||
|
loader: native_loader::id(),
|
||||||
|
};
|
||||||
|
accounts.store(&budget_program::id(), &budget_program_account);
|
||||||
|
|
||||||
// Erc20 token program
|
// Erc20 token program
|
||||||
let erc20_account = Account {
|
let erc20_account = Account {
|
||||||
tokens: 1,
|
tokens: 1,
|
||||||
|
@ -765,10 +775,6 @@ impl Bank {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_executable_accounts(&self, mut program_id: Pubkey) -> Result<Vec<(Pubkey, Account)>> {
|
fn load_executable_accounts(&self, mut program_id: Pubkey) -> Result<Vec<(Pubkey, Account)>> {
|
||||||
if runtime::is_legacy_program(&program_id) {
|
|
||||||
return Ok(vec![]);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut accounts = Vec::new();
|
let mut accounts = Vec::new();
|
||||||
let mut depth = 0;
|
let mut depth = 0;
|
||||||
loop {
|
loop {
|
||||||
|
@ -1228,11 +1234,13 @@ impl Bank {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_balance(account: &Account) -> u64 {
|
pub fn read_balance(account: &Account) -> u64 {
|
||||||
|
// TODO: Re-instate budget_program special case?
|
||||||
|
/*
|
||||||
if budget_program::check_id(&account.owner) {
|
if budget_program::check_id(&account.owner) {
|
||||||
budget_program::get_balance(account)
|
return budget_program::get_balance(account);
|
||||||
} else {
|
|
||||||
account.tokens
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
account.tokens
|
||||||
}
|
}
|
||||||
/// Each program would need to be able to introspect its own state
|
/// Each program would need to be able to introspect its own state
|
||||||
/// this is hard-coded to the Budget language
|
/// this is hard-coded to the Budget language
|
||||||
|
|
|
@ -272,9 +272,9 @@ pub fn reconstruct_entries_from_blobs(blobs: Vec<SharedBlob>) -> Result<(Vec<Ent
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use budget_transaction::BudgetTransaction;
|
|
||||||
use chrono::prelude::*;
|
use chrono::prelude::*;
|
||||||
use entry::Entry;
|
use entry::Entry;
|
||||||
|
use solana_sdk::budget_transaction::BudgetTransaction;
|
||||||
use solana_sdk::hash::hash;
|
use solana_sdk::hash::hash;
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||||
use solana_sdk::transaction::Transaction;
|
use solana_sdk::transaction::Transaction;
|
||||||
|
|
|
@ -3,24 +3,24 @@
|
||||||
//! access read to a persistent file-based ledger.
|
//! access read to a persistent file-based ledger.
|
||||||
|
|
||||||
use bincode::{self, deserialize_from, serialize_into, serialized_size};
|
use bincode::{self, deserialize_from, serialize_into, serialized_size};
|
||||||
use budget_transaction::BudgetTransaction;
|
|
||||||
use chrono::prelude::Utc;
|
use chrono::prelude::Utc;
|
||||||
use entry::Entry;
|
use entry::Entry;
|
||||||
use log::Level::Trace;
|
use log::Level::Trace;
|
||||||
use mint::Mint;
|
use mint::Mint;
|
||||||
use packet::{SharedBlob, BLOB_DATA_SIZE};
|
use packet::{SharedBlob, BLOB_DATA_SIZE};
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
use solana_sdk::budget_transaction::BudgetTransaction;
|
||||||
use solana_sdk::hash::{hash, Hash};
|
use solana_sdk::hash::{hash, Hash};
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||||
use solana_sdk::transaction::Transaction;
|
use solana_sdk::transaction::Transaction;
|
||||||
|
use solana_sdk::vote_program::Vote;
|
||||||
use std::fs::{copy, create_dir_all, remove_dir_all, File, OpenOptions};
|
use std::fs::{copy, create_dir_all, remove_dir_all, File, OpenOptions};
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::io::{self, BufReader, BufWriter, Seek, SeekFrom};
|
use std::io::{self, BufReader, BufWriter, Seek, SeekFrom};
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use solana_sdk::vote_program::Vote;
|
|
||||||
use vote_transaction::VoteTransaction;
|
use vote_transaction::VoteTransaction;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -701,15 +701,14 @@ pub fn make_large_test_entries(num_entries: usize) -> Vec<Entry> {
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use bincode::{deserialize, serialized_size};
|
use bincode::{deserialize, serialized_size};
|
||||||
use budget_transaction::BudgetTransaction;
|
|
||||||
use entry::{next_entry, reconstruct_entries_from_blobs, Entry};
|
use entry::{next_entry, reconstruct_entries_from_blobs, Entry};
|
||||||
use packet::{to_blobs, BLOB_DATA_SIZE, PACKET_DATA_SIZE};
|
use packet::{to_blobs, BLOB_DATA_SIZE, PACKET_DATA_SIZE};
|
||||||
use solana_sdk::hash::hash;
|
use solana_sdk::hash::hash;
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||||
use solana_sdk::transaction::Transaction;
|
use solana_sdk::transaction::Transaction;
|
||||||
|
use solana_sdk::vote_program::Vote;
|
||||||
use std;
|
use std;
|
||||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||||
use solana_sdk::vote_program::Vote;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_verify_slice() {
|
fn test_verify_slice() {
|
||||||
|
|
|
@ -14,9 +14,6 @@ pub mod banking_stage;
|
||||||
pub mod blob_fetch_stage;
|
pub mod blob_fetch_stage;
|
||||||
pub mod bloom;
|
pub mod bloom;
|
||||||
pub mod broadcast_stage;
|
pub mod broadcast_stage;
|
||||||
pub mod budget_expr;
|
|
||||||
pub mod budget_instruction;
|
|
||||||
pub mod budget_transaction;
|
|
||||||
#[cfg(feature = "chacha")]
|
#[cfg(feature = "chacha")]
|
||||||
pub mod chacha;
|
pub mod chacha;
|
||||||
#[cfg(all(feature = "chacha", feature = "cuda"))]
|
#[cfg(all(feature = "chacha", feature = "cuda"))]
|
||||||
|
@ -31,7 +28,6 @@ pub mod crds_traits_impls;
|
||||||
pub mod crds_value;
|
pub mod crds_value;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod contact_info;
|
pub mod contact_info;
|
||||||
pub mod budget_program;
|
|
||||||
pub mod cluster_info;
|
pub mod cluster_info;
|
||||||
pub mod compute_leader_finality_service;
|
pub mod compute_leader_finality_service;
|
||||||
pub mod db_ledger;
|
pub mod db_ledger;
|
||||||
|
@ -51,7 +47,6 @@ pub mod native_loader;
|
||||||
pub mod ncp;
|
pub mod ncp;
|
||||||
pub mod netutil;
|
pub mod netutil;
|
||||||
pub mod packet;
|
pub mod packet;
|
||||||
pub mod payment_plan;
|
|
||||||
pub mod poh;
|
pub mod poh;
|
||||||
pub mod poh_recorder;
|
pub mod poh_recorder;
|
||||||
pub mod poh_service;
|
pub mod poh_service;
|
||||||
|
|
|
@ -246,10 +246,10 @@ impl RpcSolPubSub for RpcSolPubSubImpl {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use budget_program;
|
|
||||||
use budget_transaction::BudgetTransaction;
|
|
||||||
use jsonrpc_core::futures::sync::mpsc;
|
use jsonrpc_core::futures::sync::mpsc;
|
||||||
use mint::Mint;
|
use mint::Mint;
|
||||||
|
use solana_sdk::budget_program;
|
||||||
|
use solana_sdk::budget_transaction::BudgetTransaction;
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||||
use solana_sdk::transaction::Transaction;
|
use solana_sdk::transaction::Transaction;
|
||||||
use std::net::{IpAddr, Ipv4Addr};
|
use std::net::{IpAddr, Ipv4Addr};
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use budget_program;
|
|
||||||
use native_loader;
|
use native_loader;
|
||||||
use solana_sdk::account::{create_keyed_accounts, Account, KeyedAccount};
|
use solana_sdk::account::{create_keyed_accounts, Account, KeyedAccount};
|
||||||
use solana_sdk::native_program::ProgramError;
|
use solana_sdk::native_program::ProgramError;
|
||||||
|
@ -13,10 +12,6 @@ pub enum RuntimeError {
|
||||||
ProgramError(u8, ProgramError),
|
ProgramError(u8, ProgramError),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_legacy_program(program_id: &Pubkey) -> bool {
|
|
||||||
budget_program::check_id(program_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Process an instruction
|
/// Process an instruction
|
||||||
/// This method calls the instruction's program entrypoint method
|
/// This method calls the instruction's program entrypoint method
|
||||||
fn process_instruction(
|
fn process_instruction(
|
||||||
|
@ -28,36 +23,25 @@ fn process_instruction(
|
||||||
) -> Result<(), ProgramError> {
|
) -> Result<(), ProgramError> {
|
||||||
let program_id = tx.program_id(instruction_index);
|
let program_id = tx.program_id(instruction_index);
|
||||||
|
|
||||||
// Call the program method
|
let mut keyed_accounts = create_keyed_accounts(executable_accounts);
|
||||||
// It's up to the program to implement its own rules on moving funds
|
let mut keyed_accounts2: Vec<_> = tx.instructions[instruction_index]
|
||||||
if is_legacy_program(&program_id) {
|
.accounts
|
||||||
if budget_program::check_id(&program_id) {
|
.iter()
|
||||||
budget_program::process(&tx, instruction_index, program_accounts)?;
|
.map(|&index| {
|
||||||
} else {
|
let index = index as usize;
|
||||||
unreachable!();
|
let key = &tx.account_keys[index];
|
||||||
};
|
(key, index < tx.signatures.len())
|
||||||
Ok(())
|
}).zip(program_accounts.iter_mut())
|
||||||
} else {
|
.map(|((key, is_signer), account)| KeyedAccount::new(key, is_signer, account))
|
||||||
let mut keyed_accounts = create_keyed_accounts(executable_accounts);
|
.collect();
|
||||||
let mut keyed_accounts2: Vec<_> = tx.instructions[instruction_index]
|
keyed_accounts.append(&mut keyed_accounts2);
|
||||||
.accounts
|
|
||||||
.iter()
|
|
||||||
.map(|&index| {
|
|
||||||
let index = index as usize;
|
|
||||||
let key = &tx.account_keys[index];
|
|
||||||
(key, index < tx.signatures.len())
|
|
||||||
}).zip(program_accounts.iter_mut())
|
|
||||||
.map(|((key, is_signer), account)| KeyedAccount::new(key, is_signer, account))
|
|
||||||
.collect();
|
|
||||||
keyed_accounts.append(&mut keyed_accounts2);
|
|
||||||
|
|
||||||
native_loader::process_instruction(
|
native_loader::process_instruction(
|
||||||
&program_id,
|
&program_id,
|
||||||
&mut keyed_accounts,
|
&mut keyed_accounts,
|
||||||
&tx.instructions[instruction_index].userdata,
|
&tx.instructions[instruction_index].userdata,
|
||||||
tick_height,
|
tick_height,
|
||||||
)
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn verify_instruction(
|
fn verify_instruction(
|
||||||
|
|
|
@ -323,9 +323,9 @@ pub fn make_packet_from_transaction(tx: Transaction) -> Packet {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use bincode::serialize;
|
use bincode::serialize;
|
||||||
use budget_program;
|
|
||||||
use packet::{Packet, SharedPackets};
|
use packet::{Packet, SharedPackets};
|
||||||
use sigverify;
|
use sigverify;
|
||||||
|
use solana_sdk::budget_program;
|
||||||
use solana_sdk::hash::Hash;
|
use solana_sdk::hash::Hash;
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||||
use solana_sdk::system_instruction::SystemInstruction;
|
use solana_sdk::system_instruction::SystemInstruction;
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
use bincode::serialize;
|
use bincode::serialize;
|
||||||
use bs58;
|
use bs58;
|
||||||
use budget_program;
|
|
||||||
use budget_transaction::BudgetTransaction;
|
|
||||||
use chrono::prelude::*;
|
use chrono::prelude::*;
|
||||||
use clap::ArgMatches;
|
use clap::ArgMatches;
|
||||||
use elf;
|
use elf;
|
||||||
|
@ -14,6 +12,8 @@ use rpc_request::{get_rpc_request_str, RpcClient, RpcRequest};
|
||||||
use serde_json;
|
use serde_json;
|
||||||
use solana_drone::drone::{request_airdrop_transaction, DRONE_PORT};
|
use solana_drone::drone::{request_airdrop_transaction, DRONE_PORT};
|
||||||
use solana_sdk::bpf_loader;
|
use solana_sdk::bpf_loader;
|
||||||
|
use solana_sdk::budget_program;
|
||||||
|
use solana_sdk::budget_transaction::BudgetTransaction;
|
||||||
use solana_sdk::hash::Hash;
|
use solana_sdk::hash::Hash;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil, Signature};
|
use solana_sdk::signature::{Keypair, KeypairUtil, Signature};
|
||||||
|
|
Loading…
Reference in New Issue