Add storage mining pool (#4364)
* Add storage mining pool * Set gossip port * Add create-storage-mining-pool-account wallet command * Add claim-storage-reward wallet command * Create storage account upfront * Add storage program to genesis * Use STORAGE_ACCOUNT_SPACE * Fix tests * Add wallet commands to create validator/replicator storage accounts * Add create_validator_storage_account() * Storage stage no longer implicitly creates a storage account
This commit is contained in:
@ -142,12 +142,19 @@ pub fn kill_entry_and_spend_and_verify_rest(
|
||||
assert!(cluster_nodes.len() >= nodes);
|
||||
let client = create_client(entry_point_info.client_facing_addr(), FULLNODE_PORT_RANGE);
|
||||
let first_two_epoch_slots = MINIMUM_SLOT_LENGTH * 3;
|
||||
|
||||
for ingress_node in &cluster_nodes {
|
||||
client
|
||||
.poll_get_balance(&ingress_node.id)
|
||||
.unwrap_or_else(|err| panic!("Node {} has no balance: {}", ingress_node.id, err));
|
||||
}
|
||||
|
||||
info!("sleeping for 2 leader fortnights");
|
||||
sleep(Duration::from_millis(
|
||||
slot_millis * first_two_epoch_slots as u64,
|
||||
));
|
||||
info!("done sleeping for first 2 warmup epochs");
|
||||
info!("killing entry point");
|
||||
info!("killing entry point: {}", entry_point_info.id);
|
||||
assert!(client.fullnode_exit().unwrap());
|
||||
info!("sleeping for some time");
|
||||
sleep(Duration::from_millis(
|
||||
@ -160,10 +167,10 @@ pub fn kill_entry_and_spend_and_verify_rest(
|
||||
}
|
||||
|
||||
let client = create_client(ingress_node.client_facing_addr(), FULLNODE_PORT_RANGE);
|
||||
let bal = client
|
||||
let balance = client
|
||||
.poll_get_balance(&funding_keypair.pubkey())
|
||||
.expect("balance in source");
|
||||
assert!(bal > 0);
|
||||
assert_ne!(balance, 0);
|
||||
|
||||
let mut result = Ok(());
|
||||
let mut retries = 0;
|
||||
|
@ -387,6 +387,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn validator_exit() {
|
||||
solana_logger::setup();
|
||||
let leader_keypair = Keypair::new();
|
||||
let leader_node = Node::new_localhost_with_pubkey(&leader_keypair.pubkey());
|
||||
|
||||
|
@ -11,6 +11,7 @@ use solana_client::thin_client::create_client;
|
||||
use solana_client::thin_client::ThinClient;
|
||||
use solana_sdk::client::SyncClient;
|
||||
use solana_sdk::genesis_block::GenesisBlock;
|
||||
use solana_sdk::message::Message;
|
||||
use solana_sdk::poh_config::PohConfig;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||
@ -19,6 +20,7 @@ use solana_sdk::timing::DEFAULT_SLOTS_PER_EPOCH;
|
||||
use solana_sdk::timing::DEFAULT_TICKS_PER_SLOT;
|
||||
use solana_sdk::transaction::Transaction;
|
||||
use solana_stake_api::stake_instruction;
|
||||
use solana_storage_api::storage_instruction;
|
||||
use solana_vote_api::vote_instruction;
|
||||
use solana_vote_api::vote_state::VoteState;
|
||||
use std::collections::HashMap;
|
||||
@ -120,6 +122,7 @@ impl LocalCluster {
|
||||
mut genesis_block,
|
||||
mint_keypair,
|
||||
voting_keypair,
|
||||
storage_keypair,
|
||||
} = create_genesis_block_with_leader(
|
||||
config.cluster_lamports,
|
||||
&leader_pubkey,
|
||||
@ -135,7 +138,7 @@ impl LocalCluster {
|
||||
let (genesis_ledger_path, _blockhash) = create_new_tmp_ledger!(&genesis_block);
|
||||
let leader_ledger_path = tmp_copy_blocktree!(&genesis_ledger_path);
|
||||
let leader_contact_info = leader_node.info.clone();
|
||||
let leader_storage_keypair = Arc::new(Keypair::new());
|
||||
let leader_storage_keypair = Arc::new(storage_keypair);
|
||||
let leader_voting_keypair = Arc::new(voting_keypair);
|
||||
let leader_server = Fullnode::new(
|
||||
leader_node,
|
||||
@ -238,12 +241,12 @@ impl LocalCluster {
|
||||
// setup as a listener
|
||||
info!("listener {} ", validator_pubkey,);
|
||||
} else {
|
||||
// Send each validator some lamports to vote
|
||||
// Give the validator some lamports to setup vote and storage accounts
|
||||
let validator_balance = Self::transfer_with_client(
|
||||
&client,
|
||||
&self.funding_keypair,
|
||||
&validator_pubkey,
|
||||
stake * 2 + 1,
|
||||
stake * 2 + 2,
|
||||
);
|
||||
info!(
|
||||
"validator {} balance {}",
|
||||
@ -257,6 +260,9 @@ impl LocalCluster {
|
||||
stake,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
Self::setup_storage_account(&client, &storage_keypair, &validator_keypair, false)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
let voting_keypair = Arc::new(voting_keypair);
|
||||
@ -298,21 +304,24 @@ impl LocalCluster {
|
||||
|
||||
fn add_replicator(&mut self) {
|
||||
let replicator_keypair = Arc::new(Keypair::new());
|
||||
let replicator_id = replicator_keypair.pubkey();
|
||||
let replicator_pubkey = replicator_keypair.pubkey();
|
||||
let storage_keypair = Arc::new(Keypair::new());
|
||||
let storage_id = storage_keypair.pubkey();
|
||||
let storage_pubkey = storage_keypair.pubkey();
|
||||
let client = create_client(
|
||||
self.entry_point_info.client_facing_addr(),
|
||||
FULLNODE_PORT_RANGE,
|
||||
);
|
||||
|
||||
// Give the replicator some lamports to setup its storage accounts
|
||||
Self::transfer_with_client(
|
||||
&client,
|
||||
&self.funding_keypair,
|
||||
&replicator_keypair.pubkey(),
|
||||
1,
|
||||
42,
|
||||
);
|
||||
let replicator_node = Node::new_localhost_replicator(&replicator_id);
|
||||
let replicator_node = Node::new_localhost_replicator(&replicator_pubkey);
|
||||
|
||||
Self::setup_storage_account(&client, &storage_keypair, &replicator_keypair, true).unwrap();
|
||||
|
||||
let (replicator_ledger_path, _blockhash) = create_new_tmp_ledger!(&self.genesis_block);
|
||||
let replicator = Replicator::new(
|
||||
@ -322,12 +331,12 @@ impl LocalCluster {
|
||||
replicator_keypair,
|
||||
storage_keypair,
|
||||
)
|
||||
.unwrap();
|
||||
.unwrap_or_else(|err| panic!("Replicator::new() failed: {:?}", err));
|
||||
|
||||
self.replicators.push(replicator);
|
||||
self.replicator_infos.insert(
|
||||
replicator_id,
|
||||
ReplicatorInfo::new(storage_id, replicator_ledger_path),
|
||||
replicator_pubkey,
|
||||
ReplicatorInfo::new(storage_pubkey, replicator_ledger_path),
|
||||
);
|
||||
}
|
||||
|
||||
@ -464,6 +473,36 @@ impl LocalCluster {
|
||||
"expected successful vote account registration",
|
||||
))
|
||||
}
|
||||
|
||||
fn setup_storage_account(
|
||||
client: &ThinClient,
|
||||
storage_keypair: &Keypair,
|
||||
from_keypair: &Arc<Keypair>,
|
||||
replicator: bool,
|
||||
) -> Result<()> {
|
||||
let message = Message::new_with_payer(
|
||||
if replicator {
|
||||
storage_instruction::create_replicator_storage_account(
|
||||
&from_keypair.pubkey(),
|
||||
&storage_keypair.pubkey(),
|
||||
1,
|
||||
)
|
||||
} else {
|
||||
storage_instruction::create_validator_storage_account(
|
||||
&from_keypair.pubkey(),
|
||||
&storage_keypair.pubkey(),
|
||||
1,
|
||||
)
|
||||
},
|
||||
Some(&from_keypair.pubkey()),
|
||||
);
|
||||
let signer_keys = vec![from_keypair.as_ref()];
|
||||
let blockhash = client.get_recent_blockhash().unwrap().0;
|
||||
let mut transaction = Transaction::new(&signer_keys, message, blockhash);
|
||||
client
|
||||
.retry_transfer(&from_keypair, &mut transaction, 5)
|
||||
.map(|_signature| ())
|
||||
}
|
||||
}
|
||||
|
||||
impl Cluster for LocalCluster {
|
||||
@ -529,7 +568,7 @@ mod test {
|
||||
let num_replicators = 1;
|
||||
let config = ClusterConfig {
|
||||
fullnode_config,
|
||||
num_replicators: 1,
|
||||
num_replicators,
|
||||
node_stakes: vec![3; NUM_NODES],
|
||||
cluster_lamports: 100,
|
||||
ticks_per_slot: 8,
|
||||
|
@ -290,8 +290,8 @@ impl Replicator {
|
||||
.expect("ledger encrypt not successful");
|
||||
loop {
|
||||
self.create_sampling_offsets();
|
||||
if self.sample_file_to_create_mining_hash().is_err() {
|
||||
info!("Error sampling file, exiting...");
|
||||
if let Err(err) = self.sample_file_to_create_mining_hash() {
|
||||
warn!("Error sampling file, exiting: {:?}", err);
|
||||
break;
|
||||
}
|
||||
self.submit_mining_proof();
|
||||
@ -365,7 +365,10 @@ impl Replicator {
|
||||
self.num_chacha_blocks = num_encrypted_bytes / CHACHA_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
info!("Done encrypting the ledger");
|
||||
info!(
|
||||
"Done encrypting the ledger: {:?}",
|
||||
self.ledger_data_file_encrypted
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -406,29 +409,30 @@ impl Replicator {
|
||||
if client.poll_get_balance(&keypair.pubkey())? == 0 {
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"No account has been setup",
|
||||
"keypair account has no balance",
|
||||
))?
|
||||
}
|
||||
|
||||
// check if the account exists
|
||||
let bal = client.poll_get_balance(&storage_keypair.pubkey());
|
||||
if bal.is_err() || bal.unwrap() == 0 {
|
||||
// check if the storage account exists
|
||||
let balance = client.poll_get_balance(&storage_keypair.pubkey());
|
||||
if balance.is_err() || balance.unwrap() == 0 {
|
||||
let (blockhash, _fee_calculator) = client.get_recent_blockhash().expect("blockhash");
|
||||
|
||||
let ix = vec![storage_instruction::create_account(
|
||||
let ix = storage_instruction::create_replicator_storage_account(
|
||||
&keypair.pubkey(),
|
||||
&storage_keypair.pubkey(),
|
||||
1,
|
||||
)];
|
||||
);
|
||||
let tx = Transaction::new_signed_instructions(&[keypair], ix, blockhash);
|
||||
let signature = client.async_send_transaction(tx)?;
|
||||
client
|
||||
.poll_for_signature(&signature)
|
||||
.map_err(|err| match err {
|
||||
TransportError::IoError(e) => e,
|
||||
TransportError::TransactionError(_) => {
|
||||
io::Error::new(ErrorKind::Other, "signature not found")
|
||||
}
|
||||
TransportError::TransactionError(_) => io::Error::new(
|
||||
ErrorKind::Other,
|
||||
"setup_mining_account: signature not found",
|
||||
),
|
||||
})?;
|
||||
}
|
||||
Ok(())
|
||||
@ -504,10 +508,11 @@ impl Replicator {
|
||||
.expect("rpc request")
|
||||
.as_u64()
|
||||
.unwrap();
|
||||
info!("max slot: {}", storage_slot);
|
||||
info!("storage slot: {}", storage_slot);
|
||||
if get_segment_from_slot(storage_slot) != 0 {
|
||||
return Ok((storage_blockhash, storage_slot));
|
||||
}
|
||||
info!("waiting for segment...");
|
||||
sleep(Duration::from_secs(5));
|
||||
}
|
||||
Err(Error::new(
|
||||
|
@ -192,6 +192,15 @@ impl StorageStage {
|
||||
.name("solana-storage-create-accounts".to_string())
|
||||
.spawn(move || {
|
||||
let transactions_socket = UdpSocket::bind("0.0.0.0:0").unwrap();
|
||||
|
||||
{
|
||||
let working_bank = bank_forks.read().unwrap().working_bank();
|
||||
let storage_account = working_bank.get_account(&storage_keypair.pubkey());
|
||||
if storage_account.is_none() {
|
||||
warn!("Storage account not found: {}", storage_keypair.pubkey());
|
||||
}
|
||||
}
|
||||
|
||||
loop {
|
||||
match instruction_receiver.recv_timeout(Duration::from_secs(1)) {
|
||||
Ok(instruction) => {
|
||||
@ -238,22 +247,29 @@ impl StorageStage {
|
||||
) -> io::Result<()> {
|
||||
let working_bank = bank_forks.read().unwrap().working_bank();
|
||||
let blockhash = working_bank.confirmed_last_blockhash();
|
||||
let mut instructions = vec![];
|
||||
let signer_keys = vec![keypair.as_ref(), storage_keypair.as_ref()];
|
||||
let keypair_balance = working_bank.get_balance(&keypair.pubkey());
|
||||
|
||||
if keypair_balance == 0 {
|
||||
warn!("keypair account balance empty: {}", keypair.pubkey(),);
|
||||
} else {
|
||||
debug!(
|
||||
"keypair account balance: {}: {}",
|
||||
keypair.pubkey(),
|
||||
keypair_balance
|
||||
);
|
||||
}
|
||||
if working_bank
|
||||
.get_account(&storage_keypair.pubkey())
|
||||
.is_none()
|
||||
{
|
||||
let create_instruction = storage_instruction::create_account(
|
||||
&keypair.pubkey(),
|
||||
&storage_keypair.pubkey(),
|
||||
1,
|
||||
warn!(
|
||||
"storage account does not exist: {}",
|
||||
storage_keypair.pubkey()
|
||||
);
|
||||
instructions.push(create_instruction);
|
||||
info!("storage account requested");
|
||||
}
|
||||
instructions.push(instruction);
|
||||
let message = Message::new_with_payer(instructions, Some(&signer_keys[0].pubkey()));
|
||||
|
||||
let signer_keys = vec![keypair.as_ref(), storage_keypair.as_ref()];
|
||||
let message = Message::new_with_payer(vec![instruction], Some(&signer_keys[0].pubkey()));
|
||||
let transaction = Transaction::new(&signer_keys, message, blockhash);
|
||||
|
||||
transactions_socket.send_to(
|
||||
|
Reference in New Issue
Block a user