2019-03-14 20:42:01 -06:00
|
|
|
use crate::bank::Bank;
|
2019-04-19 07:29:07 -06:00
|
|
|
use solana_sdk::client::{AsyncClient, Client, SyncClient};
|
2019-04-11 00:25:14 -07:00
|
|
|
use solana_sdk::hash::Hash;
|
2019-03-23 21:12:27 -06:00
|
|
|
use solana_sdk::instruction::Instruction;
|
2019-03-27 05:36:01 -06:00
|
|
|
use solana_sdk::message::Message;
|
2019-03-16 14:30:10 -06:00
|
|
|
use solana_sdk::pubkey::Pubkey;
|
2019-04-03 16:36:10 -06:00
|
|
|
use solana_sdk::signature::Signature;
|
2019-03-16 14:30:10 -06:00
|
|
|
use solana_sdk::signature::{Keypair, KeypairUtil};
|
2019-04-03 09:45:57 -06:00
|
|
|
use solana_sdk::system_instruction;
|
2019-04-05 10:42:54 -06:00
|
|
|
use solana_sdk::transaction::{self, Transaction};
|
2019-04-03 21:40:29 -06:00
|
|
|
use solana_sdk::transport::Result;
|
2019-04-05 10:26:48 -06:00
|
|
|
use std::io;
|
2019-04-19 07:29:07 -06:00
|
|
|
use std::sync::mpsc::{channel, Receiver, Sender};
|
|
|
|
use std::sync::Arc;
|
2019-04-19 13:18:20 -07:00
|
|
|
use std::sync::Mutex;
|
2019-04-19 07:29:07 -06:00
|
|
|
use std::thread::Builder;
|
2019-03-14 20:42:01 -06:00
|
|
|
|
2019-04-11 11:29:59 -07:00
|
|
|
pub struct BankClient {
|
2019-04-19 07:29:07 -06:00
|
|
|
bank: Arc<Bank>,
|
2019-04-19 13:18:20 -07:00
|
|
|
transaction_sender: Mutex<Sender<Transaction>>,
|
2019-03-14 20:42:01 -06:00
|
|
|
}
|
|
|
|
|
2019-04-19 07:29:07 -06:00
|
|
|
impl Client for BankClient {}
|
|
|
|
|
2019-04-11 11:29:59 -07:00
|
|
|
impl AsyncClient for BankClient {
|
2019-04-05 10:26:48 -06:00
|
|
|
fn async_send_transaction(&self, transaction: Transaction) -> io::Result<Signature> {
|
2019-04-19 07:29:07 -06:00
|
|
|
let signature = transaction.signatures.get(0).cloned().unwrap_or_default();
|
2019-04-19 13:18:20 -07:00
|
|
|
let transaction_sender = self.transaction_sender.lock().unwrap();
|
|
|
|
transaction_sender.send(transaction).unwrap();
|
2019-04-19 07:29:07 -06:00
|
|
|
Ok(signature)
|
2019-04-05 10:26:48 -06:00
|
|
|
}
|
|
|
|
|
2019-04-11 00:25:14 -07:00
|
|
|
fn async_send_message(
|
|
|
|
&self,
|
|
|
|
keypairs: &[&Keypair],
|
|
|
|
message: Message,
|
|
|
|
recent_blockhash: Hash,
|
|
|
|
) -> io::Result<Signature> {
|
|
|
|
let transaction = Transaction::new(&keypairs, message, recent_blockhash);
|
2019-04-05 10:26:48 -06:00
|
|
|
self.async_send_transaction(transaction)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn async_send_instruction(
|
|
|
|
&self,
|
|
|
|
keypair: &Keypair,
|
|
|
|
instruction: Instruction,
|
2019-04-11 00:25:14 -07:00
|
|
|
recent_blockhash: Hash,
|
2019-04-05 10:26:48 -06:00
|
|
|
) -> io::Result<Signature> {
|
|
|
|
let message = Message::new(vec![instruction]);
|
2019-04-11 00:25:14 -07:00
|
|
|
self.async_send_message(&[keypair], message, recent_blockhash)
|
2019-04-05 10:26:48 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Transfer `lamports` from `keypair` to `pubkey`
|
|
|
|
fn async_transfer(
|
|
|
|
&self,
|
|
|
|
lamports: u64,
|
|
|
|
keypair: &Keypair,
|
|
|
|
pubkey: &Pubkey,
|
2019-04-11 00:25:14 -07:00
|
|
|
recent_blockhash: Hash,
|
2019-04-05 10:26:48 -06:00
|
|
|
) -> io::Result<Signature> {
|
|
|
|
let transfer_instruction =
|
|
|
|
system_instruction::transfer(&keypair.pubkey(), pubkey, lamports);
|
2019-04-11 00:25:14 -07:00
|
|
|
self.async_send_instruction(keypair, transfer_instruction, recent_blockhash)
|
2019-04-05 10:26:48 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-11 11:29:59 -07:00
|
|
|
impl SyncClient for BankClient {
|
2019-04-03 21:40:29 -06:00
|
|
|
fn send_message(&self, keypairs: &[&Keypair], message: Message) -> Result<Signature> {
|
2019-03-27 05:36:01 -06:00
|
|
|
let blockhash = self.bank.last_blockhash();
|
|
|
|
let transaction = Transaction::new(&keypairs, message, blockhash);
|
2019-04-03 16:36:10 -06:00
|
|
|
self.bank.process_transaction(&transaction)?;
|
|
|
|
Ok(transaction.signatures.get(0).cloned().unwrap_or_default())
|
2019-03-16 14:30:10 -06:00
|
|
|
}
|
|
|
|
|
2019-03-17 09:55:42 -06:00
|
|
|
/// Create and process a transaction from a single instruction.
|
2019-04-03 21:40:29 -06:00
|
|
|
fn send_instruction(&self, keypair: &Keypair, instruction: Instruction) -> Result<Signature> {
|
2019-03-27 05:50:50 -06:00
|
|
|
let message = Message::new(vec![instruction]);
|
2019-04-03 15:11:08 -06:00
|
|
|
self.send_message(&[keypair], message)
|
2019-03-16 14:30:10 -06:00
|
|
|
}
|
|
|
|
|
2019-03-27 07:34:01 -06:00
|
|
|
/// Transfer `lamports` from `keypair` to `pubkey`
|
2019-04-03 21:40:29 -06:00
|
|
|
fn transfer(&self, lamports: u64, keypair: &Keypair, pubkey: &Pubkey) -> Result<Signature> {
|
2019-04-05 10:26:48 -06:00
|
|
|
let transfer_instruction =
|
|
|
|
system_instruction::transfer(&keypair.pubkey(), pubkey, lamports);
|
|
|
|
self.send_instruction(keypair, transfer_instruction)
|
2019-04-03 15:11:08 -06:00
|
|
|
}
|
2019-04-03 16:36:10 -06:00
|
|
|
|
2019-04-03 21:40:29 -06:00
|
|
|
fn get_account_data(&self, pubkey: &Pubkey) -> Result<Option<Vec<u8>>> {
|
|
|
|
Ok(self.bank.get_account(pubkey).map(|account| account.data))
|
2019-04-03 16:36:10 -06:00
|
|
|
}
|
|
|
|
|
2019-04-03 21:40:29 -06:00
|
|
|
fn get_balance(&self, pubkey: &Pubkey) -> Result<u64> {
|
|
|
|
Ok(self.bank.get_balance(pubkey))
|
2019-04-03 16:36:10 -06:00
|
|
|
}
|
2019-04-05 10:42:54 -06:00
|
|
|
|
|
|
|
fn get_signature_status(
|
|
|
|
&self,
|
|
|
|
signature: &Signature,
|
|
|
|
) -> Result<Option<transaction::Result<()>>> {
|
|
|
|
Ok(self.bank.get_signature_status(signature))
|
|
|
|
}
|
2019-04-11 00:25:14 -07:00
|
|
|
|
|
|
|
fn get_recent_blockhash(&self) -> Result<Hash> {
|
|
|
|
let last_blockhash = self.bank.last_blockhash();
|
|
|
|
Ok(last_blockhash)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_transaction_count(&self) -> Result<u64> {
|
|
|
|
Ok(self.bank.transaction_count())
|
|
|
|
}
|
2019-04-03 15:11:08 -06:00
|
|
|
}
|
|
|
|
|
2019-04-11 11:29:59 -07:00
|
|
|
impl BankClient {
|
2019-04-19 07:29:07 -06:00
|
|
|
fn run(bank: &Bank, transaction_receiver: Receiver<Transaction>) {
|
|
|
|
while let Ok(tx) = transaction_receiver.recv() {
|
|
|
|
let mut transactions = vec![tx];
|
|
|
|
while let Ok(tx) = transaction_receiver.try_recv() {
|
|
|
|
transactions.push(tx);
|
|
|
|
}
|
|
|
|
let _ = bank.process_transactions(&transactions);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-11 11:29:59 -07:00
|
|
|
pub fn new(bank: Bank) -> Self {
|
2019-04-19 07:29:07 -06:00
|
|
|
let bank = Arc::new(bank);
|
|
|
|
let (transaction_sender, transaction_receiver) = channel();
|
2019-04-19 13:18:20 -07:00
|
|
|
let transaction_sender = Mutex::new(transaction_sender);
|
2019-04-19 07:29:07 -06:00
|
|
|
let thread_bank = bank.clone();
|
|
|
|
let bank = bank.clone();
|
|
|
|
Builder::new()
|
|
|
|
.name("solana-bank-client".to_string())
|
|
|
|
.spawn(move || Self::run(&thread_bank, transaction_receiver))
|
|
|
|
.unwrap();
|
|
|
|
Self {
|
|
|
|
bank,
|
|
|
|
transaction_sender,
|
|
|
|
}
|
2019-03-14 20:42:01 -06:00
|
|
|
}
|
|
|
|
}
|
2019-03-18 15:35:47 -06:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
use solana_sdk::genesis_block::GenesisBlock;
|
2019-03-23 21:12:27 -06:00
|
|
|
use solana_sdk::instruction::AccountMeta;
|
2019-03-18 15:35:47 -06:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_bank_client_new_with_keypairs() {
|
|
|
|
let (genesis_block, john_doe_keypair) = GenesisBlock::new(10_000);
|
2019-03-27 07:34:01 -06:00
|
|
|
let john_pubkey = john_doe_keypair.pubkey();
|
2019-03-18 15:35:47 -06:00
|
|
|
let jane_doe_keypair = Keypair::new();
|
2019-03-27 07:34:01 -06:00
|
|
|
let jane_pubkey = jane_doe_keypair.pubkey();
|
|
|
|
let doe_keypairs = vec![&john_doe_keypair, &jane_doe_keypair];
|
2019-03-18 15:35:47 -06:00
|
|
|
let bank = Bank::new(&genesis_block);
|
2019-04-11 11:29:59 -07:00
|
|
|
let bank_client = BankClient::new(bank);
|
2019-03-18 15:35:47 -06:00
|
|
|
|
2019-04-02 21:52:07 -06:00
|
|
|
// Create 2-2 Multisig Transfer instruction.
|
2019-03-30 21:37:33 -06:00
|
|
|
let bob_pubkey = Pubkey::new_rand();
|
2019-04-03 09:45:57 -06:00
|
|
|
let mut move_instruction = system_instruction::transfer(&john_pubkey, &bob_pubkey, 42);
|
2019-03-19 13:03:20 -06:00
|
|
|
move_instruction
|
|
|
|
.accounts
|
2019-03-19 15:25:48 -06:00
|
|
|
.push(AccountMeta::new(jane_pubkey, true));
|
2019-03-18 15:35:47 -06:00
|
|
|
|
2019-03-27 07:34:01 -06:00
|
|
|
let message = Message::new(vec![move_instruction]);
|
2019-04-03 15:11:08 -06:00
|
|
|
bank_client.send_message(&doe_keypairs, message).unwrap();
|
2019-04-03 21:40:29 -06:00
|
|
|
assert_eq!(bank_client.get_balance(&bob_pubkey).unwrap(), 42);
|
2019-03-18 15:35:47 -06:00
|
|
|
}
|
|
|
|
}
|