diff --git a/core/src/banking_stage.rs b/core/src/banking_stage.rs index 3005c98eb9..18566982ea 100644 --- a/core/src/banking_stage.rs +++ b/core/src/banking_stage.rs @@ -16,9 +16,9 @@ use crate::service::Service; use crate::sigverify_stage::VerifiedPackets; use bincode::deserialize; use solana_metrics::counter::Counter; -use solana_runtime::bank::{self, Bank, TransactionError}; +use solana_runtime::bank::{self, Bank}; use solana_sdk::timing::{self, duration_as_us, MAX_RECENT_BLOCKHASHES}; -use solana_sdk::transaction::Transaction; +use solana_sdk::transaction::{Transaction, TransactionError}; use std::net::UdpSocket; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::mpsc::{Receiver, RecvTimeoutError}; @@ -445,10 +445,10 @@ mod tests { use crate::entry::EntrySlice; use crate::packet::to_packets; use crate::poh_recorder::WorkingBank; - use solana_runtime::runtime::InstructionError; use solana_sdk::genesis_block::GenesisBlock; use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::system_transaction::SystemTransaction; + use solana_sdk::transaction::InstructionError; use std::sync::mpsc::channel; use std::thread::sleep; diff --git a/core/src/blocktree_processor.rs b/core/src/blocktree_processor.rs index 73009d4a51..2867ccaf82 100644 --- a/core/src/blocktree_processor.rs +++ b/core/src/blocktree_processor.rs @@ -229,11 +229,11 @@ mod tests { use crate::blocktree::create_new_tmp_ledger; use crate::blocktree::tests::entries_to_blobs; use crate::entry::{create_ticks, next_entry, Entry}; - use solana_runtime::bank::TransactionError; use solana_sdk::genesis_block::GenesisBlock; use solana_sdk::hash::Hash; use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::system_transaction::SystemTransaction; + use solana_sdk::transaction::TransactionError; fn fill_blocktree_slot_with_ticks( blocktree: &Blocktree, diff --git a/core/src/result.rs b/core/src/result.rs index f007f87f45..fba0bcefed 100644 --- a/core/src/result.rs +++ b/core/src/result.rs @@ -8,7 +8,7 @@ use crate::packet; use crate::poh_recorder; use bincode; use serde_json; -use solana_runtime::bank; +use solana_sdk::transaction; use std; use std::any::Any; @@ -22,7 +22,7 @@ pub enum Error { RecvTimeoutError(std::sync::mpsc::RecvTimeoutError), TryRecvError(std::sync::mpsc::TryRecvError), Serialize(std::boxed::Box), - TransactionError(bank::TransactionError), + TransactionError(transaction::TransactionError), ClusterInfoError(cluster_info::ClusterInfoError), BlobError(packet::BlobError), #[cfg(feature = "erasure")] @@ -57,8 +57,8 @@ impl std::convert::From for Error { Error::RecvTimeoutError(e) } } -impl std::convert::From for Error { - fn from(e: bank::TransactionError) -> Error { +impl std::convert::From for Error { + fn from(e: transaction::TransactionError) -> Error { Error::TransactionError(e) } } diff --git a/core/src/rpc.rs b/core/src/rpc.rs index 0769194ba0..2469ec43bf 100644 --- a/core/src/rpc.rs +++ b/core/src/rpc.rs @@ -9,11 +9,11 @@ use bs58; use jsonrpc_core::{Error, ErrorCode, Metadata, Result}; use jsonrpc_derive::rpc; use solana_drone::drone::request_airdrop_transaction; -use solana_runtime::bank::{self, Bank, TransactionError}; +use solana_runtime::bank::{self, Bank}; use solana_sdk::account::Account; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::Signature; -use solana_sdk::transaction::Transaction; +use solana_sdk::transaction::{Transaction, TransactionError}; use std::mem; use std::net::{SocketAddr, UdpSocket}; use std::sync::atomic::{AtomicBool, Ordering}; diff --git a/core/src/rpc_subscriptions.rs b/core/src/rpc_subscriptions.rs index c287121ef6..c77dbcbb33 100644 --- a/core/src/rpc_subscriptions.rs +++ b/core/src/rpc_subscriptions.rs @@ -6,10 +6,11 @@ use core::hash::Hash; use jsonrpc_core::futures::Future; use jsonrpc_pubsub::typed::Sink; use jsonrpc_pubsub::SubscriptionId; -use solana_runtime::bank::{self, Bank, TransactionError}; +use solana_runtime::bank::{self, Bank}; use solana_sdk::account::Account; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::Signature; +use solana_sdk::transaction::TransactionError; use std::collections::HashMap; use std::sync::RwLock; diff --git a/programs/failure/tests/failure.rs b/programs/failure/tests/failure.rs index 27998b477e..3343434bae 100644 --- a/programs/failure/tests/failure.rs +++ b/programs/failure/tests/failure.rs @@ -1,11 +1,9 @@ use solana_runtime::bank::Bank; -use solana_runtime::bank::TransactionError; use solana_runtime::loader_utils::load_program; -use solana_runtime::runtime::InstructionError; use solana_sdk::genesis_block::GenesisBlock; use solana_sdk::native_loader; use solana_sdk::native_program::ProgramError; -use solana_sdk::transaction::Transaction; +use solana_sdk::transaction::{InstructionError, Transaction, TransactionError}; #[test] fn test_program_native_failure() { diff --git a/programs/vote/tests/vote.rs b/programs/vote/tests/vote.rs index 05eb63847b..249e17d673 100644 --- a/programs/vote/tests/vote.rs +++ b/programs/vote/tests/vote.rs @@ -1,12 +1,11 @@ -use solana_runtime::bank::TransactionError; use solana_runtime::bank::{Bank, Result}; -use solana_runtime::runtime::InstructionError; use solana_sdk::genesis_block::GenesisBlock; use solana_sdk::hash::hash; use solana_sdk::native_program::ProgramError; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::system_instruction::SystemInstruction; +use solana_sdk::transaction::{InstructionError, TransactionError}; use solana_sdk::transaction_builder::{BuilderInstruction, TransactionBuilder}; use solana_vote_api::vote_instruction::{Vote, VoteInstruction}; use solana_vote_api::vote_state::VoteState; diff --git a/runtime/src/accounts.rs b/runtime/src/accounts.rs index 79eaf74517..13034075f5 100644 --- a/runtime/src/accounts.rs +++ b/runtime/src/accounts.rs @@ -1,5 +1,5 @@ use crate::append_vec::AppendVec; -use crate::bank::{Result, TransactionError}; +use crate::bank::Result; use crate::runtime::has_duplicates; use bincode::serialize; use hashbrown::{HashMap, HashSet}; @@ -11,7 +11,7 @@ use solana_sdk::hash::{hash, Hash}; use solana_sdk::native_loader; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, KeypairUtil}; -use solana_sdk::transaction::Transaction; +use solana_sdk::transaction::{Transaction, TransactionError}; use solana_vote_api; use std::collections::BTreeMap; use std::env; diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 3c49e51c6e..2f7c9b4de3 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -5,7 +5,7 @@ use crate::accounts::{Accounts, ErrorCounters, InstructionAccounts, InstructionLoaders}; use crate::hash_queue::HashQueue; -use crate::runtime::{self, InstructionError}; +use crate::runtime; use crate::status_cache::StatusCache; use bincode::serialize; use hashbrown::HashMap; @@ -19,7 +19,7 @@ use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, Signature}; use solana_sdk::system_transaction::SystemTransaction; use solana_sdk::timing::{duration_as_us, MAX_RECENT_BLOCKHASHES, NUM_TICKS_PER_SECOND}; -use solana_sdk::transaction::Transaction; +use solana_sdk::transaction::{Transaction, TransactionError}; use solana_vote_api::vote_instruction::Vote; use solana_vote_api::vote_state::{Lockout, VoteState}; use std::result; @@ -104,41 +104,6 @@ impl EpochSchedule { } } -/// Reasons a transaction might be rejected. -#[derive(Debug, PartialEq, Eq, Clone)] -pub enum TransactionError { - /// This Pubkey is being processed in another transaction - AccountInUse, - - /// Pubkey appears twice in the same transaction, typically in a pay-to-self - /// transaction. - AccountLoadedTwice, - - /// Attempt to debit from `Pubkey`, but no found no record of a prior credit. - AccountNotFound, - - /// The from `Pubkey` does not have sufficient balance to pay the fee to schedule the transaction - InsufficientFundsForFee, - - /// The bank has seen `Signature` before. This can occur under normal operation - /// when a UDP packet is duplicated, as a user error from a client not updating - /// its `recent_blockhash`, or as a double-spend attack. - DuplicateSignature, - - /// The bank has not seen the given `recent_blockhash` or the transaction is too old and - /// the `recent_blockhash` has been discarded. - BlockhashNotFound, - - /// The program returned an error - InstructionError(u8, InstructionError), - - /// Loader call chain too deep - CallChainTooDeep, - - /// Transaction has a fee but has no signature present - MissingSignatureForFee, -} - pub type Result = result::Result; type BankStatusCache = StatusCache; @@ -882,7 +847,7 @@ mod tests { use solana_sdk::system_instruction::SystemInstruction; use solana_sdk::system_program; use solana_sdk::system_transaction::SystemTransaction; - use solana_sdk::transaction::Instruction; + use solana_sdk::transaction::{Instruction, InstructionError}; #[test] fn test_bank_new() { diff --git a/runtime/src/runtime.rs b/runtime/src/runtime.rs index 4a89eed7aa..ac26728af1 100644 --- a/runtime/src/runtime.rs +++ b/runtime/src/runtime.rs @@ -1,38 +1,9 @@ -use crate::bank::TransactionError; use crate::native_loader; -use crate::system_program::SystemError; use solana_sdk::account::{create_keyed_accounts, Account, KeyedAccount}; use solana_sdk::native_program::ProgramError; use solana_sdk::pubkey::Pubkey; use solana_sdk::system_program; -use solana_sdk::transaction::Transaction; - -/// Reasons the runtime might have rejected an instruction. -#[derive(Debug, PartialEq, Eq, Clone)] -pub enum InstructionError { - /// Executing the instruction produced an error. - ProgramError(ProgramError), - - /// Program's instruction lamport balance does not equal the balance after the instruction - UnbalancedInstruction, - - /// Program modified an account's program id - ModifiedProgramId, - - /// Program spent the lamports of an account that doesn't belong to it - ExternalAccountLamportSpend, - - /// Program modified the userdata of an account that doesn't belong to it - ExternalAccountUserdataModified, -} - -impl InstructionError { - pub fn new_result_with_negative_lamports() -> Self { - let serialized_error = - bincode::serialize(&SystemError::ResultWithNegativeLamports).unwrap(); - InstructionError::ProgramError(ProgramError::CustomError(serialized_error)) - } -} +use solana_sdk::transaction::{InstructionError, Transaction, TransactionError}; /// Process an instruction /// This method calls the instruction's program entrypoint method diff --git a/runtime/src/status_cache.rs b/runtime/src/status_cache.rs index 2cd1cd5d71..e188e9ad6f 100644 --- a/runtime/src/status_cache.rs +++ b/runtime/src/status_cache.rs @@ -167,8 +167,8 @@ impl StatusCache { #[cfg(test)] mod tests { use super::*; - use crate::bank::TransactionError; use solana_sdk::hash::hash; + use solana_sdk::transaction::TransactionError; type BankStatusCache = StatusCache; diff --git a/runtime/src/system_program.rs b/runtime/src/system_program.rs index 9049e999a3..9432a8ff08 100644 --- a/runtime/src/system_program.rs +++ b/runtime/src/system_program.rs @@ -1,22 +1,14 @@ use bincode::serialize; use log::*; -use serde_derive::Serialize; use solana_sdk::account::KeyedAccount; use solana_sdk::native_program::ProgramError; use solana_sdk::pubkey::Pubkey; -use solana_sdk::system_instruction::SystemInstruction; +use solana_sdk::system_instruction::{SystemError, SystemInstruction}; use solana_sdk::system_program; const FROM_ACCOUNT_INDEX: usize = 0; const TO_ACCOUNT_INDEX: usize = 1; -#[derive(Serialize, Debug, Clone, PartialEq)] -pub enum SystemError { - AccountAlreadyInUse, - ResultWithNegativeLamports, - SourceNotSystemAccount, -} - fn create_system_account( keyed_accounts: &mut [KeyedAccount], lamports: u64, diff --git a/runtime/tests/system.rs b/runtime/tests/system.rs index 1ee7941b22..daca3fdfb4 100644 --- a/runtime/tests/system.rs +++ b/runtime/tests/system.rs @@ -1,10 +1,10 @@ -use solana_runtime::bank::{Bank, TransactionError}; -use solana_runtime::runtime::InstructionError; +use solana_runtime::bank::Bank; use solana_sdk::genesis_block::GenesisBlock; use solana_sdk::native_program::ProgramError; use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::system_instruction::SystemInstruction; use solana_sdk::system_program; +use solana_sdk::transaction::{InstructionError, TransactionError}; use solana_sdk::transaction_builder::{BuilderInstruction, TransactionBuilder}; struct SystemBank<'a> { diff --git a/sdk/src/system_instruction.rs b/sdk/src/system_instruction.rs index 47aa686578..a11b3d1cc2 100644 --- a/sdk/src/system_instruction.rs +++ b/sdk/src/system_instruction.rs @@ -2,6 +2,13 @@ use crate::pubkey::Pubkey; use crate::system_program; use crate::transaction_builder::BuilderInstruction; +#[derive(Serialize, Debug, Clone, PartialEq)] +pub enum SystemError { + AccountAlreadyInUse, + ResultWithNegativeLamports, + SourceNotSystemAccount, +} + #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub enum SystemInstruction { /// Create a new account diff --git a/sdk/src/transaction.rs b/sdk/src/transaction.rs index 7391b773c5..41b7abe1f1 100644 --- a/sdk/src/transaction.rs +++ b/sdk/src/transaction.rs @@ -1,6 +1,7 @@ //! The `transaction` module provides functionality for creating log transactions. use crate::hash::{Hash, Hasher}; +use crate::native_program::ProgramError; use crate::packet::PACKET_DATA_SIZE; use crate::pubkey::Pubkey; use crate::shortvec::{ @@ -8,6 +9,7 @@ use crate::shortvec::{ serialize_vec_with, }; use crate::signature::{Keypair, KeypairUtil, Signature}; +use crate::system_instruction::SystemError; use bincode::{serialize, Error}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use serde::{Deserialize, Serialize, Serializer}; @@ -15,6 +17,33 @@ use std::fmt; use std::io::{Cursor, Read, Write}; use std::mem::size_of; +/// Reasons the runtime might have rejected an instruction. +#[derive(Debug, PartialEq, Eq, Clone)] +pub enum InstructionError { + /// Executing the instruction produced an error. + ProgramError(ProgramError), + + /// Program's instruction lamport balance does not equal the balance after the instruction + UnbalancedInstruction, + + /// Program modified an account's program id + ModifiedProgramId, + + /// Program spent the lamports of an account that doesn't belong to it + ExternalAccountLamportSpend, + + /// Program modified the userdata of an account that doesn't belong to it + ExternalAccountUserdataModified, +} + +impl InstructionError { + pub fn new_result_with_negative_lamports() -> Self { + let serialized_error = + bincode::serialize(&SystemError::ResultWithNegativeLamports).unwrap(); + InstructionError::ProgramError(ProgramError::CustomError(serialized_error)) + } +} + /// An instruction to execute a program #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] pub struct Instruction { @@ -76,6 +105,41 @@ impl Instruction { } } +/// Reasons a transaction might be rejected. +#[derive(Debug, PartialEq, Eq, Clone)] +pub enum TransactionError { + /// This Pubkey is being processed in another transaction + AccountInUse, + + /// Pubkey appears twice in the same transaction, typically in a pay-to-self + /// transaction. + AccountLoadedTwice, + + /// Attempt to debit from `Pubkey`, but no found no record of a prior credit. + AccountNotFound, + + /// The from `Pubkey` does not have sufficient balance to pay the fee to schedule the transaction + InsufficientFundsForFee, + + /// The bank has seen `Signature` before. This can occur under normal operation + /// when a UDP packet is duplicated, as a user error from a client not updating + /// its `recent_blockhash`, or as a double-spend attack. + DuplicateSignature, + + /// The bank has not seen the given `recent_blockhash` or the transaction is too old and + /// the `recent_blockhash` has been discarded. + BlockhashNotFound, + + /// The program returned an error + InstructionError(u8, InstructionError), + + /// Loader call chain too deep + CallChainTooDeep, + + /// Transaction has a fee but has no signature present + MissingSignatureForFee, +} + /// An atomic transaction #[derive(Debug, PartialEq, Eq, Clone)] pub struct Transaction {