Fund all the keys with move many transactions (#1436)
* Fund all the keys with move many transactions * logs
This commit is contained in:
committed by
GitHub
parent
0a39722719
commit
d8d8f0bfc8
@ -25,6 +25,7 @@ use solana::timing::{duration_as_ms, duration_as_s};
|
|||||||
use solana::transaction::Transaction;
|
use solana::transaction::Transaction;
|
||||||
use solana::wallet::request_airdrop;
|
use solana::wallet::request_airdrop;
|
||||||
use solana::window::default_window;
|
use solana::window::default_window;
|
||||||
|
use std::cmp;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
@ -174,21 +175,22 @@ fn send_barrier_transaction(barrier_client: &mut ThinClient, last_id: &mut Hash,
|
|||||||
|
|
||||||
fn generate_txs(
|
fn generate_txs(
|
||||||
shared_txs: &Arc<RwLock<VecDeque<Vec<Transaction>>>>,
|
shared_txs: &Arc<RwLock<VecDeque<Vec<Transaction>>>>,
|
||||||
id: &Keypair,
|
source: &[Keypair],
|
||||||
keypairs: &[Keypair],
|
dest: &[Keypair],
|
||||||
last_id: &Hash,
|
last_id: &Hash,
|
||||||
threads: usize,
|
threads: usize,
|
||||||
reclaim: bool,
|
reclaim: bool,
|
||||||
) {
|
) {
|
||||||
let tx_count = keypairs.len();
|
let tx_count = source.len();
|
||||||
println!("Signing transactions... {} (reclaim={})", tx_count, reclaim);
|
println!("Signing transactions... {} (reclaim={})", tx_count, reclaim);
|
||||||
let signing_start = Instant::now();
|
let signing_start = Instant::now();
|
||||||
|
|
||||||
let transactions: Vec<_> = keypairs
|
let pairs: Vec<_> = source.iter().zip(dest.iter()).collect();
|
||||||
|
let transactions: Vec<_> = pairs
|
||||||
.par_iter()
|
.par_iter()
|
||||||
.map(|keypair| {
|
.map(|(id, keypair)| {
|
||||||
if !reclaim {
|
if !reclaim {
|
||||||
Transaction::system_new(&id, keypair.pubkey(), 1, *last_id)
|
Transaction::system_new(id, keypair.pubkey(), 1, *last_id)
|
||||||
} else {
|
} else {
|
||||||
Transaction::system_new(keypair, id.pubkey(), 1, *last_id)
|
Transaction::system_new(keypair, id.pubkey(), 1, *last_id)
|
||||||
}
|
}
|
||||||
@ -272,6 +274,61 @@ fn do_tx_transfers(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn split_tokens(tokens: i64, per_unit: i64, max_units: usize) -> (usize, i64) {
|
||||||
|
let total_blocks = tokens / per_unit;
|
||||||
|
let max_keys_to_fund = cmp::min(total_blocks - 1, max_units as i64);
|
||||||
|
let blocks_per_unit = total_blocks / (max_keys_to_fund + 1);
|
||||||
|
(max_keys_to_fund as usize, blocks_per_unit * per_unit)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fund_keys(client: &mut ThinClient, source: &Keypair, dests: &[Keypair], tokens: i64) {
|
||||||
|
let max_per_move = 5;
|
||||||
|
let total = tokens * (dests.len() as i64 + 1);
|
||||||
|
let mut funded: Vec<(&Keypair, i64)> = vec![(source, total)];
|
||||||
|
let mut notfunded: Vec<&Keypair> = dests.iter().collect();
|
||||||
|
println!("funding keys {}", dests.len());
|
||||||
|
while !notfunded.is_empty() {
|
||||||
|
let last_id = client.get_last_id();
|
||||||
|
let mut new_funded: Vec<(&Keypair, i64)> = vec![];
|
||||||
|
let mut to_fund = vec![];
|
||||||
|
println!("creating from... {}", funded.len());
|
||||||
|
for f in &mut funded {
|
||||||
|
let max_units = cmp::min(notfunded.len(), max_per_move);
|
||||||
|
let (num, per_unit) = split_tokens(f.1, tokens, max_units);
|
||||||
|
let start = notfunded.len() - num;
|
||||||
|
let moves: Vec<_> = notfunded[start..]
|
||||||
|
.iter()
|
||||||
|
.map(|k| (k.pubkey(), per_unit))
|
||||||
|
.collect();
|
||||||
|
notfunded[start..]
|
||||||
|
.iter()
|
||||||
|
.for_each(|k| new_funded.push((k, per_unit)));
|
||||||
|
notfunded.truncate(start);
|
||||||
|
if !moves.is_empty() {
|
||||||
|
to_fund.push((f.0, moves));
|
||||||
|
}
|
||||||
|
f.1 -= per_unit * (num as i64);
|
||||||
|
assert!(f.1 >= per_unit);
|
||||||
|
}
|
||||||
|
println!("generating... {}", to_fund.len());
|
||||||
|
let to_fund_txs: Vec<_> = to_fund
|
||||||
|
.par_iter()
|
||||||
|
.map(|(k, m)| Transaction::system_move_many(k, &m, last_id, 0))
|
||||||
|
.collect();
|
||||||
|
println!("transfering... {}", to_fund.len());
|
||||||
|
to_fund_txs.iter().for_each(|tx| {
|
||||||
|
let _ = client.transfer_signed(&tx).expect("transfer");
|
||||||
|
});
|
||||||
|
println!(
|
||||||
|
"funded {} total: {} left: {}",
|
||||||
|
new_funded.len(),
|
||||||
|
funded.len() + new_funded.len(),
|
||||||
|
notfunded.len()
|
||||||
|
);
|
||||||
|
funded.append(&mut new_funded);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn airdrop_tokens(client: &mut ThinClient, leader: &NodeInfo, id: &Keypair, tx_count: i64) {
|
fn airdrop_tokens(client: &mut ThinClient, leader: &NodeInfo, id: &Keypair, tx_count: i64) {
|
||||||
let mut drone_addr = leader.contact_info.tpu;
|
let mut drone_addr = leader.contact_info.tpu;
|
||||||
drone_addr.set_port(DRONE_PORT);
|
drone_addr.set_port(DRONE_PORT);
|
||||||
@ -542,8 +599,8 @@ fn main() {
|
|||||||
seed.copy_from_slice(&id.public_key_bytes()[..32]);
|
seed.copy_from_slice(&id.public_key_bytes()[..32]);
|
||||||
let mut rnd = GenKeys::new(seed);
|
let mut rnd = GenKeys::new(seed);
|
||||||
|
|
||||||
println!("Creating {} keypairs...", tx_count / 2);
|
println!("Creating {} keypairs...", tx_count * 2);
|
||||||
let keypairs = rnd.gen_n_keypairs(tx_count / 2);
|
let keypairs = rnd.gen_n_keypairs(tx_count * 2);
|
||||||
let barrier_id = rnd.gen_n_keypairs(1).pop().unwrap();
|
let barrier_id = rnd.gen_n_keypairs(1).pop().unwrap();
|
||||||
|
|
||||||
println!("Get tokens...");
|
println!("Get tokens...");
|
||||||
@ -554,12 +611,9 @@ fn main() {
|
|||||||
let keypair0_balance = client.poll_get_balance(&keypairs[0].pubkey()).unwrap_or(0);
|
let keypair0_balance = client.poll_get_balance(&keypairs[0].pubkey()).unwrap_or(0);
|
||||||
|
|
||||||
if num_tokens_per_account > keypair0_balance {
|
if num_tokens_per_account > keypair0_balance {
|
||||||
airdrop_tokens(
|
let extra = (num_tokens_per_account - keypair0_balance) * (keypairs.len() as i64);
|
||||||
&mut client,
|
airdrop_tokens(&mut client, &leader, &id, extra);
|
||||||
&leader,
|
fund_keys(&mut client, &id, &keypairs, num_tokens_per_account);
|
||||||
&id,
|
|
||||||
(num_tokens_per_account - keypair0_balance) * tx_count,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
airdrop_tokens(&mut barrier_client, &leader, &barrier_id, 1);
|
airdrop_tokens(&mut barrier_client, &leader, &barrier_id, 1);
|
||||||
|
|
||||||
@ -624,10 +678,11 @@ fn main() {
|
|||||||
// ping-pong between source and destination accounts for each loop iteration
|
// ping-pong between source and destination accounts for each loop iteration
|
||||||
// this seems to be faster than trying to determine the balance of individual
|
// this seems to be faster than trying to determine the balance of individual
|
||||||
// accounts
|
// accounts
|
||||||
|
let len = tx_count as usize;
|
||||||
generate_txs(
|
generate_txs(
|
||||||
&shared_txs,
|
&shared_txs,
|
||||||
&id,
|
&keypairs[..len],
|
||||||
&keypairs,
|
&keypairs[len..],
|
||||||
&last_id,
|
&last_id,
|
||||||
threads,
|
threads,
|
||||||
reclaim_tokens_back_to_source_account,
|
reclaim_tokens_back_to_source_account,
|
||||||
@ -733,6 +788,15 @@ fn converge(
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
#[test]
|
||||||
|
fn test_split_tokens() {
|
||||||
|
assert_eq!(split_tokens(3, 2, 5), (0, 2));
|
||||||
|
assert_eq!(split_tokens(4, 2, 5), (1, 2));
|
||||||
|
assert_eq!(split_tokens(5, 2, 5), (1, 2));
|
||||||
|
assert_eq!(split_tokens(6, 2, 5), (2, 2));
|
||||||
|
assert_eq!(split_tokens(20, 2, 5), (5, 2));
|
||||||
|
assert_eq!(split_tokens(30, 2, 5), (5, 4));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_switch_directions() {
|
fn test_switch_directions() {
|
||||||
|
@ -5,7 +5,7 @@ use hash::Hash;
|
|||||||
use signature::{Keypair, KeypairUtil};
|
use signature::{Keypair, KeypairUtil};
|
||||||
use solana_program_interface::pubkey::Pubkey;
|
use solana_program_interface::pubkey::Pubkey;
|
||||||
use system_program::SystemProgram;
|
use system_program::SystemProgram;
|
||||||
use transaction::Transaction;
|
use transaction::{Instruction, Transaction};
|
||||||
|
|
||||||
pub trait SystemTransaction {
|
pub trait SystemTransaction {
|
||||||
fn system_create(
|
fn system_create(
|
||||||
@ -37,6 +37,12 @@ pub trait SystemTransaction {
|
|||||||
program_id: Pubkey,
|
program_id: Pubkey,
|
||||||
name: String,
|
name: String,
|
||||||
) -> Self;
|
) -> Self;
|
||||||
|
fn system_move_many(
|
||||||
|
from_keypair: &Keypair,
|
||||||
|
moves: &[(Pubkey, i64)],
|
||||||
|
last_id: Hash,
|
||||||
|
fee: i64,
|
||||||
|
) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SystemTransaction for Transaction {
|
impl SystemTransaction for Transaction {
|
||||||
@ -120,6 +126,29 @@ impl SystemTransaction for Transaction {
|
|||||||
fee,
|
fee,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
fn system_move_many(from: &Keypair, moves: &[(Pubkey, i64)], last_id: Hash, fee: i64) -> Self {
|
||||||
|
let instructions: Vec<_> = moves
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, (_, amount))| {
|
||||||
|
let spend = SystemProgram::Move { tokens: *amount };
|
||||||
|
Instruction {
|
||||||
|
program_ids_index: 0,
|
||||||
|
userdata: serialize(&spend).unwrap(),
|
||||||
|
accounts: vec![0, i as u8],
|
||||||
|
}
|
||||||
|
}).collect();
|
||||||
|
let to_keys: Vec<_> = moves.iter().map(|(to_key, _)| *to_key).collect();
|
||||||
|
|
||||||
|
Transaction::new_with_instructions(
|
||||||
|
from,
|
||||||
|
&to_keys,
|
||||||
|
last_id,
|
||||||
|
fee,
|
||||||
|
vec![SystemProgram::id()],
|
||||||
|
instructions,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn test_tx() -> Transaction {
|
pub fn test_tx() -> Transaction {
|
||||||
|
Reference in New Issue
Block a user