From b4119c454ae5413e27dbf5f15ba0add3d66828e9 Mon Sep 17 00:00:00 2001 From: Rob Walker Date: Wed, 23 Oct 2019 22:01:22 -0700 Subject: [PATCH] credit_only credits forwarding (#6509) * credit_only_credits_forwarding * whack transfer_now() * fixup * bench should retry the airdrop TX * fixup * try to make bench-exchange a bit more robust, informative --- bench-exchange/src/bench.rs | 16 +- bench-tps/src/bench.rs | 23 +- client/src/rpc_client.rs | 8 +- core/benches/poh_verify.rs | 2 +- core/src/banking_stage.rs | 34 +- core/src/blockstream_service.rs | 2 +- core/src/broadcast_stage/broadcast_utils.rs | 2 +- core/src/chacha.rs | 2 +- core/src/packet.rs | 2 +- core/src/replay_stage.rs | 4 +- core/src/rpc_pubsub.rs | 4 +- core/src/test_tx.rs | 2 +- core/tests/bank_forks.rs | 11 +- drone/src/drone.rs | 10 +- drone/src/drone_mock.rs | 2 +- drone/tests/local-drone.rs | 2 +- ledger/src/blocktree_processor.rs | 82 ++-- ledger/src/entry.rs | 6 +- ledger/src/snapshot_utils.rs | 2 +- local_cluster/src/local_cluster.rs | 2 +- programs/bpf/tests/programs.rs | 2 - .../tests/storage_processor.rs | 2 +- runtime/src/accounts.rs | 369 +++++++++------ runtime/src/accounts_db.rs | 443 +++++++++--------- runtime/src/accounts_index.rs | 112 ++--- runtime/src/bank.rs | 63 +-- sdk-c/src/lib.rs | 6 +- sdk/src/epoch_schedule.rs | 4 +- sdk/src/system_instruction.rs | 13 - sdk/src/system_transaction.rs | 13 - 30 files changed, 615 insertions(+), 630 deletions(-) diff --git a/bench-exchange/src/bench.rs b/bench-exchange/src/bench.rs index d226a4f99f..00ce6b7e76 100644 --- a/bench-exchange/src/bench.rs +++ b/bench-exchange/src/bench.rs @@ -633,7 +633,7 @@ fn trader( } } -fn verify_transfer(sync_client: &T, tx: &Transaction) -> bool +fn verify_transaction(sync_client: &T, tx: &Transaction) -> bool where T: SyncClient + ?Sized, { @@ -657,9 +657,11 @@ fn verify_funding_transfer( tx: &Transaction, amount: u64, ) -> bool { - for a in &tx.message().account_keys[1..] { - if client.get_balance(a).unwrap_or(0) >= amount { - return true; + if verify_transaction(client, tx) { + for a in &tx.message().account_keys[1..] { + if client.get_balance(a).unwrap_or(0) >= amount { + return true; + } } } @@ -830,11 +832,11 @@ pub fn create_token_accounts(client: &dyn Client, signers: &[Arc], acco let mut waits = 0; while !to_create_txs.is_empty() { sleep(Duration::from_millis(200)); - to_create_txs.retain(|(_, tx)| !verify_transfer(client, &tx)); + to_create_txs.retain(|(_, tx)| !verify_transaction(client, &tx)); if to_create_txs.is_empty() { break; } - debug!( + info!( " {} transactions outstanding, waits {:?}", to_create_txs.len(), waits @@ -847,7 +849,7 @@ pub fn create_token_accounts(client: &dyn Client, signers: &[Arc], acco if !to_create_txs.is_empty() { retries += 1; - debug!(" Retry {:?}", retries); + info!(" Retry {:?} {} txes left", retries, to_create_txs.len()); if retries >= 20 { error!( "create_token_accounts: Too many retries ({}), give up", diff --git a/bench-tps/src/bench.rs b/bench-tps/src/bench.rs index 686b221e17..785743308b 100644 --- a/bench-tps/src/bench.rs +++ b/bench-tps/src/bench.rs @@ -306,7 +306,7 @@ fn generate_system_txs( .par_iter() .map(|(from, to)| { ( - system_transaction::transfer_now(from, &to.pubkey(), 1, *blockhash), + system_transaction::transfer(from, &to.pubkey(), 1, *blockhash), timestamp(), ) }) @@ -634,15 +634,22 @@ pub fn airdrop_lamports( let (blockhash, _fee_calculator) = get_recent_blockhash(client); match request_airdrop_transaction(&drone_addr, &id.pubkey(), airdrop_amount, blockhash) { Ok(transaction) => { - let signature = client.async_send_transaction(transaction).unwrap(); - client - .poll_for_signature_confirmation(&signature, 1) - .unwrap_or_else(|_| { + let mut tries = 0; + loop { + tries += 1; + let signature = client.async_send_transaction(transaction.clone()).unwrap(); + let result = client.poll_for_signature_confirmation(&signature, 1); + + if result.is_ok() { + break; + } + if tries >= 5 { panic!( - "Error requesting airdrop: to addr: {:?} amount: {}", - drone_addr, airdrop_amount + "Error requesting airdrop: to addr: {:?} amount: {} {:?}", + drone_addr, airdrop_amount, result ) - }) + } + } } Err(err) => { panic!( diff --git a/client/src/rpc_client.rs b/client/src/rpc_client.rs index dc1cb02e0e..d8e9b0340f 100644 --- a/client/src/rpc_client.rs +++ b/client/src/rpc_client.rs @@ -871,7 +871,7 @@ mod tests { let key = Keypair::new(); let to = Pubkey::new_rand(); let blockhash = Hash::default(); - let tx = system_transaction::transfer_now(&key, &to, 50, blockhash); + let tx = system_transaction::transfer(&key, &to, 50, blockhash); let signature = rpc_client.send_transaction(&tx); assert_eq!(signature.unwrap(), SIGNATURE.to_string()); @@ -920,7 +920,7 @@ mod tests { let key = Keypair::new(); let to = Pubkey::new_rand(); let blockhash = Hash::default(); - let mut tx = system_transaction::transfer_now(&key, &to, 50, blockhash); + let mut tx = system_transaction::transfer(&key, &to, 50, blockhash); let result = rpc_client.send_and_confirm_transaction(&mut tx, &[&key]); result.unwrap(); @@ -943,8 +943,8 @@ mod tests { let blockhash: Hash = "HUu3LwEzGRsUkuJS121jzkPJW39Kq62pXCTmTa1F9jDL" .parse() .unwrap(); - let prev_tx = system_transaction::transfer_now(&key, &to, 50, blockhash); - let mut tx = system_transaction::transfer_now(&key, &to, 50, blockhash); + let prev_tx = system_transaction::transfer(&key, &to, 50, blockhash); + let mut tx = system_transaction::transfer(&key, &to, 50, blockhash); rpc_client.resign_transaction(&mut tx, &[&key]).unwrap(); diff --git a/core/benches/poh_verify.rs b/core/benches/poh_verify.rs index c5e8792189..688fd3254f 100644 --- a/core/benches/poh_verify.rs +++ b/core/benches/poh_verify.rs @@ -37,7 +37,7 @@ fn bench_poh_verify_transaction_entries(bencher: &mut Bencher) { let mut ticks: Vec = Vec::with_capacity(NUM_ENTRIES); for _ in 0..NUM_ENTRIES { - let tx = system_transaction::transfer_now(&keypair1, &pubkey1, 42, cur_hash); + let tx = system_transaction::transfer(&keypair1, &pubkey1, 42, cur_hash); ticks.push(next_entry_mut(&mut cur_hash, NUM_HASHES, vec![tx])); } diff --git a/core/src/banking_stage.rs b/core/src/banking_stage.rs index 9d79ef375b..897df1aac4 100644 --- a/core/src/banking_stage.rs +++ b/core/src/banking_stage.rs @@ -1096,21 +1096,21 @@ mod tests { // fund another account so we can send 2 good transactions in a single batch. let keypair = Keypair::new(); let fund_tx = - system_transaction::transfer_now(&mint_keypair, &keypair.pubkey(), 2, start_hash); + system_transaction::transfer(&mint_keypair, &keypair.pubkey(), 2, start_hash); bank.process_transaction(&fund_tx).unwrap(); // good tx let to = Pubkey::new_rand(); - let tx = system_transaction::transfer_now(&mint_keypair, &to, 1, start_hash); + let tx = system_transaction::transfer(&mint_keypair, &to, 1, start_hash); // good tx, but no verify let to2 = Pubkey::new_rand(); - let tx_no_ver = system_transaction::transfer_now(&keypair, &to2, 2, start_hash); + let tx_no_ver = system_transaction::transfer(&keypair, &to2, 2, start_hash); // bad tx, AccountNotFound let keypair = Keypair::new(); let to3 = Pubkey::new_rand(); - let tx_anf = system_transaction::transfer_now(&keypair, &to3, 1, start_hash); + let tx_anf = system_transaction::transfer(&keypair, &to3, 1, start_hash); // send 'em over let packets = to_packets(&[tx_no_ver, tx_anf, tx]); @@ -1186,12 +1186,8 @@ mod tests { // Process a batch that includes a transaction that receives two lamports. let alice = Keypair::new(); - let tx = system_transaction::transfer_now( - &mint_keypair, - &alice.pubkey(), - 2, - genesis_block.hash(), - ); + let tx = + system_transaction::transfer(&mint_keypair, &alice.pubkey(), 2, genesis_block.hash()); let packets = to_packets(&[tx]); let packets = packets @@ -1200,13 +1196,9 @@ mod tests { .collect(); verified_sender.send(packets).unwrap(); - // Process a second batch that spends one of those lamports. - let tx = system_transaction::transfer_now( - &alice, - &mint_keypair.pubkey(), - 1, - genesis_block.hash(), - ); + // Process a second batch that uses the same from account, so conflicts with above TX + let tx = + system_transaction::transfer(&mint_keypair, &alice.pubkey(), 1, genesis_block.hash()); let packets = to_packets(&[tx]); let packets = packets .into_iter() @@ -1241,7 +1233,7 @@ mod tests { ); // wait for banking_stage to eat the packets - while bank.get_balance(&alice.pubkey()) != 1 { + while bank.get_balance(&alice.pubkey()) < 2 { sleep(Duration::from_millis(100)); } exit.store(true, Ordering::Relaxed); @@ -1265,10 +1257,10 @@ mod tests { .for_each(|x| assert_eq!(*x, Ok(()))); } - // Assert the user holds one lamport, not two. If the stage only outputs one + // Assert the user holds two lamports, not three. If the stage only outputs one // entry, then the second transaction will be rejected, because it drives // the account balance below zero before the credit is added. - assert_eq!(bank.get_balance(&alice.pubkey()), 1); + assert_eq!(bank.get_balance(&alice.pubkey()), 2); } Blocktree::destroy(&ledger_path).unwrap(); } @@ -1607,7 +1599,7 @@ mod tests { let bank = Arc::new(Bank::new(&genesis_block)); let pubkey = Pubkey::new_rand(); - let transactions = vec![system_transaction::transfer_now( + let transactions = vec![system_transaction::transfer( &mint_keypair, &pubkey, 1, diff --git a/core/src/blockstream_service.rs b/core/src/blockstream_service.rs index b37eb63517..69530faaf5 100644 --- a/core/src/blockstream_service.rs +++ b/core/src/blockstream_service.rs @@ -138,7 +138,7 @@ mod test { let keypair = Keypair::new(); let mut blockhash = entries[3].hash; - let tx = system_transaction::transfer_now(&keypair, &keypair.pubkey(), 1, Hash::default()); + let tx = system_transaction::transfer(&keypair, &keypair.pubkey(), 1, Hash::default()); let entry = Entry::new(&mut blockhash, 1, vec![tx]); blockhash = entry.hash; entries.push(entry); diff --git a/core/src/broadcast_stage/broadcast_utils.rs b/core/src/broadcast_stage/broadcast_utils.rs index fd7c24f0d1..50c9603320 100644 --- a/core/src/broadcast_stage/broadcast_utils.rs +++ b/core/src/broadcast_stage/broadcast_utils.rs @@ -87,7 +87,7 @@ mod tests { .. } = create_genesis_block(2); let bank0 = Arc::new(Bank::new(&genesis_block)); - let tx = system_transaction::transfer_now( + let tx = system_transaction::transfer( &mint_keypair, &Pubkey::new_rand(), 1, diff --git a/core/src/chacha.rs b/core/src/chacha.rs index ca6bfebfd2..a94ee79f0e 100644 --- a/core/src/chacha.rs +++ b/core/src/chacha.rs @@ -101,7 +101,7 @@ mod tests { Entry::new_mut( &mut id, &mut num_hashes, - vec![system_transaction::transfer_now( + vec![system_transaction::transfer( &keypair, &keypair.pubkey(), 1, diff --git a/core/src/packet.rs b/core/src/packet.rs index 653b6fb533..84802d8343 100644 --- a/core/src/packet.rs +++ b/core/src/packet.rs @@ -602,7 +602,7 @@ mod tests { fn test_to_packets() { let keypair = Keypair::new(); let hash = Hash::new(&[1; 32]); - let tx = system_transaction::transfer_now(&keypair, &keypair.pubkey(), 1, hash); + let tx = system_transaction::transfer(&keypair, &keypair.pubkey(), 1, hash); let rv = to_packets(&vec![tx.clone(); 1]); assert_eq!(rv.len(), 1); assert_eq!(rv[0].packets.len(), 1); diff --git a/core/src/replay_stage.rs b/core/src/replay_stage.rs index a9fdd35e30..01180d3961 100644 --- a/core/src/replay_stage.rs +++ b/core/src/replay_stage.rs @@ -956,7 +956,7 @@ mod test { blockhash, 1, vec![ - system_transaction::transfer_now(&keypair1, &keypair2.pubkey(), 2, *blockhash), // should be fine, + system_transaction::transfer(&keypair1, &keypair2.pubkey(), 2, *blockhash), // should be fine, system_transaction::transfer( &missing_keypair, &missing_keypair2.pubkey(), @@ -983,7 +983,7 @@ mod test { // Use wrong blockhash so that the entry causes an entry verification failure &bad_hash, 1, - vec![system_transaction::transfer_now( + vec![system_transaction::transfer( &genesis_keypair, &keypair2.pubkey(), 2, diff --git a/core/src/rpc_pubsub.rs b/core/src/rpc_pubsub.rs index 1e154e1364..4ec5eab1f4 100644 --- a/core/src/rpc_pubsub.rs +++ b/core/src/rpc_pubsub.rs @@ -391,7 +391,7 @@ mod tests { None, ); - let tx = system_transaction::transfer_now(&alice, &contract_funds.pubkey(), 51, blockhash); + let tx = system_transaction::transfer(&alice, &contract_funds.pubkey(), 51, blockhash); process_transaction_and_notify(&bank_forks, &tx, &rpc.subscriptions).unwrap(); let ixs = budget_instruction::when_signed( @@ -435,7 +435,7 @@ mod tests { assert_eq!(serde_json::to_string(&expected).unwrap(), response); } - let tx = system_transaction::transfer_now(&alice, &witness.pubkey(), 1, blockhash); + let tx = system_transaction::transfer(&alice, &witness.pubkey(), 1, blockhash); process_transaction_and_notify(&bank_forks, &tx, &rpc.subscriptions).unwrap(); sleep(Duration::from_millis(200)); let ix = budget_instruction::apply_signature( diff --git a/core/src/test_tx.rs b/core/src/test_tx.rs index 62821c1850..b8cff31036 100644 --- a/core/src/test_tx.rs +++ b/core/src/test_tx.rs @@ -10,7 +10,7 @@ pub fn test_tx() -> Transaction { let keypair1 = Keypair::new(); let pubkey1 = keypair1.pubkey(); let zero = Hash::default(); - system_transaction::transfer_now(&keypair1, &pubkey1, 42, zero) + system_transaction::transfer(&keypair1, &pubkey1, 42, zero) } pub fn test_multisig_tx() -> Transaction { diff --git a/core/tests/bank_forks.rs b/core/tests/bank_forks.rs index ccc27535c1..a2e0e42254 100644 --- a/core/tests/bank_forks.rs +++ b/core/tests/bank_forks.rs @@ -156,12 +156,8 @@ mod tests { 4, |bank, mint_keypair| { let key1 = Keypair::new().pubkey(); - let tx = system_transaction::transfer_now( - &mint_keypair, - &key1, - 1, - bank.last_blockhash(), - ); + let tx = + system_transaction::transfer(&mint_keypair, &key1, 1, bank.last_blockhash()); assert_eq!(bank.process_transaction(&tx), Ok(())); bank.freeze(); }, @@ -224,8 +220,7 @@ mod tests { ); let slot = bank.slot(); let key1 = Keypair::new().pubkey(); - let tx = - system_transaction::transfer_now(&mint_keypair, &key1, 1, genesis_block.hash()); + let tx = system_transaction::transfer(&mint_keypair, &key1, 1, genesis_block.hash()); assert_eq!(bank.process_transaction(&tx), Ok(())); bank.freeze(); bank_forks.insert(bank); diff --git a/drone/src/drone.rs b/drone/src/drone.rs index a1b2619feb..55cf40f3af 100644 --- a/drone/src/drone.rs +++ b/drone/src/drone.rs @@ -121,11 +121,8 @@ impl Drone { ); info!("Requesting airdrop of {} to {:?}", lamports, to); - let create_instruction = system_instruction::transfer_now( - &self.mint_keypair.pubkey(), - &to, - lamports, - ); + let create_instruction = + system_instruction::transfer(&self.mint_keypair.pubkey(), &to, lamports); let message = Message::new(vec![create_instruction]); Ok(Transaction::new(&[&self.mint_keypair], message, blockhash)) } else { @@ -411,8 +408,7 @@ mod tests { bytes.put(&req[..]); let keypair = Keypair::new(); - let expected_instruction = - system_instruction::transfer_now(&keypair.pubkey(), &to, lamports); + let expected_instruction = system_instruction::transfer(&keypair.pubkey(), &to, lamports); let message = Message::new(vec![expected_instruction]); let expected_tx = Transaction::new(&[&keypair], message, blockhash); let expected_bytes = serialize(&expected_tx).unwrap(); diff --git a/drone/src/drone_mock.rs b/drone/src/drone_mock.rs index e054b18b26..c5ee6d88de 100644 --- a/drone/src/drone_mock.rs +++ b/drone/src/drone_mock.rs @@ -18,7 +18,7 @@ pub fn request_airdrop_transaction( let key = Keypair::new(); let to = Pubkey::new_rand(); let blockhash = Hash::default(); - let tx = system_transaction::transfer_now(&key, &to, lamports, blockhash); + let tx = system_transaction::transfer(&key, &to, lamports, blockhash); Ok(tx) } } diff --git a/drone/tests/local-drone.rs b/drone/tests/local-drone.rs index fc704ec17b..0c2d663ac3 100644 --- a/drone/tests/local-drone.rs +++ b/drone/tests/local-drone.rs @@ -13,7 +13,7 @@ fn test_local_drone() { let to = Pubkey::new_rand(); let lamports = 50; let blockhash = Hash::new(&to.as_ref()); - let create_instruction = system_instruction::transfer_now(&keypair.pubkey(), &to, lamports); + let create_instruction = system_instruction::transfer(&keypair.pubkey(), &to, lamports); let message = Message::new(vec![create_instruction]); let expected_tx = Transaction::new(&[&keypair], message, blockhash); diff --git a/ledger/src/blocktree_processor.rs b/ledger/src/blocktree_processor.rs index 6b97ac50dd..ee27966672 100644 --- a/ledger/src/blocktree_processor.rs +++ b/ledger/src/blocktree_processor.rs @@ -842,7 +842,7 @@ pub mod tests { let bank = Arc::new(Bank::new(&genesis_block)); let keypair = Keypair::new(); let slot_entries = create_ticks(genesis_block.ticks_per_slot, genesis_block.hash()); - let tx = system_transaction::transfer_now( + let tx = system_transaction::transfer( &mint_keypair, &keypair.pubkey(), 1, @@ -879,8 +879,7 @@ pub mod tests { for _ in 0..deducted_from_mint { // Transfer one token from the mint to a random account let keypair = Keypair::new(); - let tx = - system_transaction::transfer_now(&mint_keypair, &keypair.pubkey(), 1, blockhash); + let tx = system_transaction::transfer(&mint_keypair, &keypair.pubkey(), 1, blockhash); let entry = Entry::new(&last_entry_hash, 1, vec![tx]); last_entry_hash = entry.hash; entries.push(entry); @@ -888,7 +887,8 @@ pub mod tests { // Add a second Transaction that will produce a // InstructionError<0, ResultWithNegativeLamports> error when processed let keypair2 = Keypair::new(); - let tx = system_transaction::transfer_now(&keypair, &keypair2.pubkey(), 42, blockhash); + let tx = + system_transaction::transfer(&mint_keypair, &keypair2.pubkey(), 101, blockhash); let entry = Entry::new(&last_entry_hash, 1, vec![tx]); last_entry_hash = entry.hash; entries.push(entry); @@ -997,12 +997,10 @@ pub mod tests { let blockhash = genesis_block.hash(); let keypairs = [Keypair::new(), Keypair::new(), Keypair::new()]; - let tx = - system_transaction::transfer_now(&mint_keypair, &keypairs[0].pubkey(), 1, blockhash); + let tx = system_transaction::transfer(&mint_keypair, &keypairs[0].pubkey(), 1, blockhash); let entry_1 = next_entry(&last_entry_hash, 1, vec![tx]); - let tx = - system_transaction::transfer_now(&mint_keypair, &keypairs[1].pubkey(), 1, blockhash); + let tx = system_transaction::transfer(&mint_keypair, &keypairs[1].pubkey(), 1, blockhash); let entry_2 = next_entry(&entry_1.hash, 1, vec![tx]); let mut entries = vec![entry_1, entry_2]; @@ -1067,14 +1065,14 @@ pub mod tests { let blockhash = bank.last_blockhash(); // ensure bank can process 2 entries that have a common account and no tick is registered - let tx = system_transaction::transfer_now( + let tx = system_transaction::transfer( &mint_keypair, &keypair1.pubkey(), 2, bank.last_blockhash(), ); let entry_1 = next_entry(&blockhash, 1, vec![tx]); - let tx = system_transaction::transfer_now( + let tx = system_transaction::transfer( &mint_keypair, &keypair2.pubkey(), 2, @@ -1107,7 +1105,7 @@ pub mod tests { let entry_1_to_mint = next_entry( &bank.last_blockhash(), 1, - vec![system_transaction::transfer_now( + vec![system_transaction::transfer( &keypair1, &mint_keypair.pubkey(), 1, @@ -1119,13 +1117,13 @@ pub mod tests { &entry_1_to_mint.hash, 1, vec![ - system_transaction::transfer_now( + system_transaction::transfer( &keypair2, &keypair3.pubkey(), 2, bank.last_blockhash(), ), // should be fine - system_transaction::transfer_now( + system_transaction::transfer( &keypair1, &mint_keypair.pubkey(), 2, @@ -1167,7 +1165,7 @@ pub mod tests { &bank.last_blockhash(), 1, vec![ - system_transaction::transfer_now( + system_transaction::transfer( &keypair1, &mint_keypair.pubkey(), 1, @@ -1186,13 +1184,13 @@ pub mod tests { &entry_1_to_mint.hash, 1, vec![ - system_transaction::transfer_now( + system_transaction::transfer( &keypair2, &keypair3.pubkey(), 2, bank.last_blockhash(), ), // should be fine - system_transaction::transfer_now( + system_transaction::transfer( &keypair1, &mint_keypair.pubkey(), 2, @@ -1265,7 +1263,7 @@ pub mod tests { &entry_1_to_mint.hash, 1, vec![ - system_transaction::transfer_now( + system_transaction::transfer( &keypair2, &keypair3.pubkey(), 2, @@ -1338,14 +1336,14 @@ pub mod tests { let keypair4 = Keypair::new(); //load accounts - let tx = system_transaction::transfer_now( + let tx = system_transaction::transfer( &mint_keypair, &keypair1.pubkey(), 1, bank.last_blockhash(), ); assert_eq!(bank.process_transaction(&tx), Ok(())); - let tx = system_transaction::transfer_now( + let tx = system_transaction::transfer( &mint_keypair, &keypair2.pubkey(), 1, @@ -1355,19 +1353,11 @@ pub mod tests { // ensure bank can process 2 entries that do not have a common account and no tick is registered let blockhash = bank.last_blockhash(); - let tx = system_transaction::transfer_now( - &keypair1, - &keypair3.pubkey(), - 1, - bank.last_blockhash(), - ); + let tx = + system_transaction::transfer(&keypair1, &keypair3.pubkey(), 1, bank.last_blockhash()); let entry_1 = next_entry(&blockhash, 1, vec![tx]); - let tx = system_transaction::transfer_now( - &keypair2, - &keypair4.pubkey(), - 1, - bank.last_blockhash(), - ); + let tx = + system_transaction::transfer(&keypair2, &keypair4.pubkey(), 1, bank.last_blockhash()); let entry_2 = next_entry(&entry_1.hash, 1, vec![tx]); assert_eq!(process_entries(&bank, &[entry_1, entry_2], true), Ok(())); assert_eq!(bank.get_balance(&keypair3.pubkey()), 1); @@ -1448,7 +1438,7 @@ pub mod tests { for _ in 0..num_accounts { let keypair = Keypair::new(); - let create_account_tx = system_transaction::transfer_now( + let create_account_tx = system_transaction::transfer( &mint_keypair, &keypair.pubkey(), 0, @@ -1516,14 +1506,14 @@ pub mod tests { let keypair4 = Keypair::new(); //load accounts - let tx = system_transaction::transfer_now( + let tx = system_transaction::transfer( &mint_keypair, &keypair1.pubkey(), 1, bank.last_blockhash(), ); assert_eq!(bank.process_transaction(&tx), Ok(())); - let tx = system_transaction::transfer_now( + let tx = system_transaction::transfer( &mint_keypair, &keypair2.pubkey(), 1, @@ -1537,15 +1527,11 @@ pub mod tests { } // ensure bank can process 2 entries that do not have a common account and tick is registered - let tx = system_transaction::transfer_now(&keypair2, &keypair3.pubkey(), 1, blockhash); + let tx = system_transaction::transfer(&keypair2, &keypair3.pubkey(), 1, blockhash); let entry_1 = next_entry(&blockhash, 1, vec![tx]); let tick = next_entry(&entry_1.hash, 1, vec![]); - let tx = system_transaction::transfer_now( - &keypair1, - &keypair4.pubkey(), - 1, - bank.last_blockhash(), - ); + let tx = + system_transaction::transfer(&keypair1, &keypair4.pubkey(), 1, bank.last_blockhash()); let entry_2 = next_entry(&tick.hash, 1, vec![tx]); assert_eq!( process_entries( @@ -1559,12 +1545,8 @@ pub mod tests { assert_eq!(bank.get_balance(&keypair4.pubkey()), 1); // ensure that an error is returned for an empty account (keypair2) - let tx = system_transaction::transfer_now( - &keypair2, - &keypair3.pubkey(), - 1, - bank.last_blockhash(), - ); + let tx = + system_transaction::transfer(&keypair2, &keypair3.pubkey(), 1, bank.last_blockhash()); let entry_3 = next_entry(&entry_2.hash, 1, vec![tx]); assert_eq!( process_entries(&bank, &[entry_3], true), @@ -1598,7 +1580,7 @@ pub mod tests { ); // Make sure other errors don't update the signature cache - let tx = system_transaction::transfer_now(&mint_keypair, &pubkey, 1000, Hash::default()); + let tx = system_transaction::transfer(&mint_keypair, &pubkey, 1000, Hash::default()); let signature = tx.signatures[0]; // Should fail with blockhash not found @@ -1624,13 +1606,13 @@ pub mod tests { let bank = Arc::new(Bank::new(&genesis_block)); let keypair1 = Keypair::new(); let keypair2 = Keypair::new(); - let success_tx = system_transaction::transfer_now( + let success_tx = system_transaction::transfer( &mint_keypair, &keypair1.pubkey(), 1, bank.last_blockhash(), ); - let fail_tx = system_transaction::transfer_now( + let fail_tx = system_transaction::transfer( &mint_keypair, &keypair2.pubkey(), 2, diff --git a/ledger/src/entry.rs b/ledger/src/entry.rs index 135b6a6aaa..7960167233 100644 --- a/ledger/src/entry.rs +++ b/ledger/src/entry.rs @@ -412,8 +412,8 @@ mod tests { // First, verify entries let keypair = Keypair::new(); - let tx0 = system_transaction::transfer_now(&keypair, &keypair.pubkey(), 0, zero); - let tx1 = system_transaction::transfer_now(&keypair, &keypair.pubkey(), 1, zero); + let tx0 = system_transaction::transfer(&keypair, &keypair.pubkey(), 0, zero); + let tx1 = system_transaction::transfer(&keypair, &keypair.pubkey(), 1, zero); let mut e0 = Entry::new(&zero, 0, vec![tx0.clone(), tx1.clone()]); assert!(e0.verify(&zero)); @@ -463,7 +463,7 @@ mod tests { fn test_next_entry_panic() { let zero = Hash::default(); let keypair = Keypair::new(); - let tx = system_transaction::transfer_now(&keypair, &keypair.pubkey(), 0, zero); + let tx = system_transaction::transfer(&keypair, &keypair.pubkey(), 0, zero); next_entry(&zero, 0, vec![tx]); } diff --git a/ledger/src/snapshot_utils.rs b/ledger/src/snapshot_utils.rs index 921b1481d4..88dcfe99fd 100644 --- a/ledger/src/snapshot_utils.rs +++ b/ledger/src/snapshot_utils.rs @@ -87,7 +87,7 @@ pub fn package_snapshot, Q: AsRef>( .rc .get_storage_entries() .into_iter() - .filter(|x| x.fork_id() <= bank.slot()) + .filter(|x| x.slot_id() <= bank.slot()) .collect(); // Create a snapshot package diff --git a/local_cluster/src/local_cluster.rs b/local_cluster/src/local_cluster.rs index 0d6c2274e7..0785d36702 100644 --- a/local_cluster/src/local_cluster.rs +++ b/local_cluster/src/local_cluster.rs @@ -426,7 +426,7 @@ impl LocalCluster { trace!("getting leader blockhash"); let (blockhash, _fee_calculator) = client.get_recent_blockhash().unwrap(); let mut tx = - system_transaction::transfer_now(&source_keypair, dest_pubkey, lamports, blockhash); + system_transaction::transfer(&source_keypair, dest_pubkey, lamports, blockhash); info!( "executing transfer of {} from {} to {}", lamports, diff --git a/programs/bpf/tests/programs.rs b/programs/bpf/tests/programs.rs index 6f3f927081..6303fb4e6d 100644 --- a/programs/bpf/tests/programs.rs +++ b/programs/bpf/tests/programs.rs @@ -117,10 +117,8 @@ mod bpf { } = create_genesis_block(50); let bank = Arc::new(Bank::new(&genesis_block)); // Create bank with specific slot, used by solana_bpf_rust_sysvar test - dbg!(bank.epoch()); let bank = Bank::new_from_parent(&bank, &Pubkey::default(), DEFAULT_SLOTS_PER_EPOCH + 1); - dbg!(bank.epoch()); let bank_client = BankClient::new(bank); // Call user program diff --git a/programs/storage_program/tests/storage_processor.rs b/programs/storage_program/tests/storage_processor.rs index 738b0bfb82..de523a5d14 100644 --- a/programs/storage_program/tests/storage_processor.rs +++ b/programs/storage_program/tests/storage_processor.rs @@ -469,7 +469,7 @@ fn init_storage_accounts( archiver_accounts_to_create: &[&Pubkey], lamports: u64, ) { - let mut ixs: Vec<_> = vec![system_instruction::transfer_now(&mint.pubkey(), owner, 1)]; + let mut ixs: Vec<_> = vec![system_instruction::transfer(&mint.pubkey(), owner, 1)]; ixs.append( &mut validator_accounts_to_create .into_iter() diff --git a/runtime/src/accounts.rs b/runtime/src/accounts.rs index 01c0495e99..e5602f9bc8 100644 --- a/runtime/src/accounts.rs +++ b/runtime/src/accounts.rs @@ -1,5 +1,5 @@ use crate::accounts_db::{AccountInfo, AccountStorage, AccountsDB, AppendVecId, ErrorCounters}; -use crate::accounts_index::{AccountsIndex, Fork}; +use crate::accounts_index::AccountsIndex; use crate::append_vec::StoredAccount; use crate::blockhash_queue::BlockhashQueue; use crate::message_processor::has_duplicates; @@ -9,6 +9,7 @@ use rayon::slice::ParallelSliceMut; use solana_metrics::inc_new_counter_error; use solana_sdk::account::Account; use solana_sdk::bank_hash::BankHash; +use solana_sdk::clock::Slot; use solana_sdk::message::Message; use solana_sdk::native_loader; use solana_sdk::pubkey::Pubkey; @@ -19,7 +20,7 @@ use std::collections::{HashMap, HashSet}; use std::io::{BufReader, Error as IOError, Read}; use std::path::Path; use std::sync::atomic::{AtomicU64, Ordering}; -use std::sync::{Arc, Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard}; +use std::sync::{Arc, Mutex, RwLock}; use crate::transaction_utils::OrderedIterator; @@ -32,6 +33,9 @@ struct CreditOnlyLock { /// This structure handles synchronization for db #[derive(Default, Debug)] pub struct Accounts { + /// my slot + pub slot: Slot, + /// Single global AccountsDB pub accounts_db: Arc, @@ -41,7 +45,7 @@ pub struct Accounts { /// Set of credit-only accounts which are currently in the pipeline, caching account balance /// and number of locks. On commit_credits(), we do a take() on the option so that the hashmap /// is no longer available to be written to. - credit_only_account_locks: Arc>>>, + credit_only_locks: Arc>>>, } // for the load instructions @@ -62,18 +66,20 @@ impl Accounts { let accounts_db = Arc::new(AccountsDB::new(paths)); Accounts { + slot: 0, accounts_db, account_locks: Mutex::new(HashSet::new()), - credit_only_account_locks: Arc::new(RwLock::new(Some(HashMap::new()))), + credit_only_locks: Arc::new(RwLock::new(Some(HashMap::new()))), } } - pub fn new_from_parent(parent: &Accounts, slot: Fork, parent_slot: Fork) -> Self { + pub fn new_from_parent(parent: &Accounts, slot: Slot, parent_slot: Slot) -> Self { let accounts_db = parent.accounts_db.clone(); accounts_db.set_hash(slot, parent_slot); Accounts { + slot, accounts_db, account_locks: Mutex::new(HashSet::new()), - credit_only_account_locks: Arc::new(RwLock::new(Some(HashMap::new()))), + credit_only_locks: Arc::new(RwLock::new(Some(HashMap::new()))), } } @@ -88,14 +94,15 @@ impl Accounts { } fn load_tx_accounts( + &self, storage: &AccountStorage, - ancestors: &HashMap, + ancestors: &HashMap, accounts_index: &AccountsIndex, tx: &Transaction, fee: u64, error_counters: &mut ErrorCounters, rent_collector: &RentCollector, - ) -> Result<(TransactionAccounts, TransactionCredits, TransactionRents)> { + ) -> Result<(TransactionAccounts, TransactionRents)> { // Copy all the accounts let message = tx.message(); if tx.signatures.is_empty() && fee != 0 { @@ -110,19 +117,17 @@ impl Accounts { // There is no way to predict what program will execute without an error // If a fee can pay for execution then the program will be scheduled let mut accounts: TransactionAccounts = vec![]; - let mut credits: TransactionCredits = vec![]; let mut rents: TransactionRents = vec![]; for key in message .account_keys .iter() - .filter(|key| !message.program_ids().contains(&key)) + .filter(|key| !message.program_ids().contains(key)) { let (account, rent) = AccountsDB::load(storage, ancestors, accounts_index, key) .and_then(|(account, _)| rent_collector.update(account)) .unwrap_or_default(); accounts.push(account); - credits.push(0); rents.push(rent); } @@ -137,14 +142,14 @@ impl Accounts { Err(TransactionError::InsufficientFundsForFee) } else { accounts[0].lamports -= fee; - Ok((accounts, credits, rents)) + Ok((accounts, rents)) } } } fn load_executable_accounts( storage: &AccountStorage, - ancestors: &HashMap, + ancestors: &HashMap, accounts_index: &AccountsIndex, program_id: &Pubkey, error_counters: &mut ErrorCounters, @@ -189,7 +194,7 @@ impl Accounts { /// For each program_id in the transaction, load its loaders. fn load_loaders( storage: &AccountStorage, - ancestors: &HashMap, + ancestors: &HashMap, accounts_index: &AccountsIndex, tx: &Transaction, error_counters: &mut ErrorCounters, @@ -217,7 +222,7 @@ impl Accounts { pub fn load_accounts( &self, - ancestors: &HashMap, + ancestors: &HashMap, txs: &[Transaction], txs_iteration_order: Option<&[usize]>, lock_results: Vec>, @@ -238,7 +243,7 @@ impl Accounts { .ok_or(TransactionError::BlockhashNotFound)?; let fee = fee_calculator.calculate_fee(tx.message()); - let (accounts, credits, rents) = Self::load_tx_accounts( + let (accounts, rents) = self.load_tx_accounts( &storage, ancestors, &accounts_index, @@ -254,6 +259,7 @@ impl Accounts { tx, error_counters, )?; + let credits = vec![0; accounts.len()]; Ok((accounts, loaders, credits, rents)) } (_, Err(e)) => Err(e), @@ -264,24 +270,33 @@ impl Accounts { /// Slow because lock is held for 1 operation instead of many pub fn load_slow( &self, - ancestors: &HashMap, + ancestors: &HashMap, pubkey: &Pubkey, - ) -> Option<(Account, Fork)> { - self.accounts_db + ) -> Option<(Account, Slot)> { + let (mut account, slot) = self + .accounts_db .load_slow(ancestors, pubkey) - .filter(|(acc, _)| acc.lamports != 0) + .unwrap_or((Account::default(), self.slot)); + + account.lamports += self.credit_only_pending_credits(pubkey); + + if account.lamports > 0 { + Some((account, slot)) + } else { + None + } } - /// scans underlying accounts_db for this delta (fork) with a map function + /// scans underlying accounts_db for this delta (slot) with a map function /// from StoredAccount to B - /// returns only the latest/current version of B for this fork - fn scan_fork(&self, fork: Fork, func: F) -> Vec + /// returns only the latest/current version of B for this slot + fn scan_slot(&self, slot: Slot, func: F) -> Vec where F: Fn(&StoredAccount) -> Option + Send + Sync, B: Send + Default, { let accumulator: Vec> = self.accounts_db.scan_account_storage( - fork, + slot, |stored_account: &StoredAccount, _id: AppendVecId, accum: &mut Vec<(Pubkey, u64, B)>| { @@ -306,8 +321,8 @@ impl Accounts { .collect() } - pub fn load_by_program_fork(&self, fork: Fork, program_id: &Pubkey) -> Vec<(Pubkey, Account)> { - self.scan_fork(fork, |stored_account| { + pub fn load_by_program_slot(&self, slot: Slot, program_id: &Pubkey) -> Vec<(Pubkey, Account)> { + self.scan_slot(slot, |stored_account| { if stored_account.account_meta.owner == *program_id { Some((stored_account.meta.pubkey, stored_account.clone_account())) } else { @@ -316,13 +331,13 @@ impl Accounts { }) } - pub fn verify_hash_internal_state(&self, fork: Fork, ancestors: &HashMap) -> bool { - self.accounts_db.verify_hash_internal_state(fork, ancestors) + pub fn verify_hash_internal_state(&self, slot: Slot, ancestors: &HashMap) -> bool { + self.accounts_db.verify_hash_internal_state(slot, ancestors) } pub fn load_by_program( &self, - ancestors: &HashMap, + ancestors: &HashMap, program_id: &Pubkey, ) -> Vec<(Pubkey, Account)> { self.accounts_db.scan_accounts( @@ -330,7 +345,7 @@ impl Accounts { |collector: &mut Vec<(Pubkey, Account)>, option| { if let Some(data) = option .filter(|(_, account, _)| account.owner == *program_id && account.lamports != 0) - .map(|(pubkey, account, _fork)| (*pubkey, account)) + .map(|(pubkey, account, _slot)| (*pubkey, account)) { collector.push(data) } @@ -339,51 +354,88 @@ impl Accounts { } /// Slow because lock is held for 1 operation instead of many - pub fn store_slow(&self, fork: Fork, pubkey: &Pubkey, account: &Account) { - self.accounts_db.store(fork, &[(pubkey, account)]); + pub fn store_slow(&self, slot: Slot, pubkey: &Pubkey, account: &Account) { + self.accounts_db.store(slot, &[(pubkey, account)]); } - fn get_read_access_credit_only<'a>( - credit_only_locks: &'a RwLockReadGuard>>, - ) -> Result<&'a HashMap> { - credit_only_locks - .as_ref() - .ok_or(TransactionError::AccountInUse) - } - - fn get_write_access_credit_only<'a>( - credit_only_locks: &'a mut RwLockWriteGuard>>, - ) -> Result<&'a mut HashMap> { - credit_only_locks - .as_mut() - .ok_or(TransactionError::AccountInUse) - } - - fn take_credit_only( - credit_only_locks: &Arc>>>, - ) -> Result> { - let mut w_credit_only_locks = credit_only_locks.write().unwrap(); + fn take_credit_only(&self) -> Result> { + let mut w_credit_only_locks = self.credit_only_locks.write().unwrap(); w_credit_only_locks .take() .ok_or(TransactionError::AccountInUse) } + fn is_locked_credit_only(&self, key: &Pubkey) -> bool { + self.credit_only_locks + .read() + .unwrap() + .as_ref() + .map_or(false, |locks| { + locks + .get(key) + .map_or(false, |lock| *lock.lock_count.lock().unwrap() > 0) + }) + } + + fn credit_only_pending_credits(&self, key: &Pubkey) -> u64 { + self.credit_only_locks + .read() + .unwrap() + .as_ref() + .map_or(0, |locks| { + locks + .get(key) + .map_or(0, |lock| lock.credits.load(Ordering::Relaxed)) + }) + } + + fn unlock_credit_only(&self, key: &Pubkey) { + self.credit_only_locks + .read() + .unwrap() + .as_ref() + .map(|locks| { + locks + .get(key) + .map(|lock| *lock.lock_count.lock().unwrap() -= 1) + }); + } + + fn lock_credit_only(&self, key: &Pubkey) -> bool { + self.credit_only_locks + .read() + .unwrap() + .as_ref() + .map_or(false, |locks| { + locks.get(key).map_or(false, |lock| { + *lock.lock_count.lock().unwrap() += 1; + true + }) + }) + } + + fn insert_credit_only(&self, key: &Pubkey, lock: CreditOnlyLock) -> bool { + self.credit_only_locks + .write() + .unwrap() + .as_mut() + .map_or(false, |locks| { + assert!(locks.get(key).is_none()); + locks.insert(*key, lock); + true + }) + } + fn lock_account( + &self, locks: &mut HashSet, - credit_only_locks: &Arc>>>, message: &Message, error_counters: &mut ErrorCounters, ) -> Result<()> { let (credit_debit_keys, credit_only_keys) = message.get_account_keys_by_lock_type(); for k in credit_debit_keys.iter() { - let r_credit_only_locks = credit_only_locks.read().unwrap(); - let r_credit_only_locks = Self::get_read_access_credit_only(&r_credit_only_locks)?; - if locks.contains(k) - || r_credit_only_locks - .get(&k) - .map_or(false, |lock| *lock.lock_count.lock().unwrap() > 0) - { + if locks.contains(k) || self.is_locked_credit_only(k) { error_counters.account_in_use += 1; debug!("CD Account in use: {:?}", k); return Err(TransactionError::AccountInUse); @@ -400,23 +452,15 @@ impl Accounts { for k in credit_debit_keys { locks.insert(*k); } - let mut credit_only_writes: Vec<&Pubkey> = vec![]; - for k in credit_only_keys { - let r_credit_only_locks = credit_only_locks.read().unwrap(); - let r_credit_only_locks = Self::get_read_access_credit_only(&r_credit_only_locks)?; - if let Some(credit_only_lock) = r_credit_only_locks.get(&k) { - *credit_only_lock.lock_count.lock().unwrap() += 1; - } else { - credit_only_writes.push(k); - } - } + + let credit_only_writes: Vec<&&Pubkey> = credit_only_keys + .iter() + .filter(|k| !self.lock_credit_only(k)) + .collect(); for k in credit_only_writes.iter() { - let mut w_credit_only_locks = credit_only_locks.write().unwrap(); - let w_credit_only_locks = Self::get_write_access_credit_only(&mut w_credit_only_locks)?; - assert!(w_credit_only_locks.get(&k).is_none()); - w_credit_only_locks.insert( - **k, + self.insert_credit_only( + *k, CreditOnlyLock { credits: AtomicU64::new(0), lock_count: Mutex::new(1), @@ -427,12 +471,7 @@ impl Accounts { Ok(()) } - fn unlock_account( - tx: &Transaction, - result: &Result<()>, - locks: &mut HashSet, - credit_only_locks: &Arc>>>, - ) { + fn unlock_account(&self, tx: &Transaction, result: &Result<()>, locks: &mut HashSet) { let (credit_debit_keys, credit_only_keys) = &tx.message().get_account_keys_by_lock_type(); match result { Err(TransactionError::AccountInUse) => (), @@ -441,23 +480,17 @@ impl Accounts { locks.remove(k); } for k in credit_only_keys { - let r_credit_only_locks = credit_only_locks.read().unwrap(); - let locks = Self::get_read_access_credit_only(&r_credit_only_locks); - if let Ok(locks) = locks { - if let Some(lock) = locks.get(&k) { - *lock.lock_count.lock().unwrap() -= 1; - } - } + self.unlock_credit_only(k); } } } } - pub fn hash_internal_state(&self, fork_id: Fork) -> Option { - let fork_hashes = self.accounts_db.fork_hashes.read().unwrap(); - let fork_hash = fork_hashes.get(&fork_id)?; - if fork_hash.0 { - Some(fork_hash.1) + pub fn hash_internal_state(&self, slot_id: Slot) -> Option { + let slot_hashes = self.accounts_db.slot_hashes.read().unwrap(); + let slot_hash = slot_hashes.get(&slot_id)?; + if slot_hash.0 { + Some(slot_hash.1) } else { None } @@ -475,9 +508,8 @@ impl Accounts { let rv = OrderedIterator::new(txs, txs_iteration_order) .map(|tx| { let message = &tx.message(); - Self::lock_account( + self.lock_account( &mut self.account_locks.lock().unwrap(), - &self.credit_only_account_locks, &message, &mut error_counters, ) @@ -502,24 +534,21 @@ impl Accounts { results: &[Result<()>], ) { let mut account_locks = self.account_locks.lock().unwrap(); - let credit_only_locks = self.credit_only_account_locks.clone(); debug!("bank unlock accounts"); OrderedIterator::new(txs, txs_iteration_order) .zip(results.iter()) - .for_each(|(tx, result)| { - Self::unlock_account(tx, result, &mut account_locks, &credit_only_locks) - }); + .for_each(|(tx, result)| self.unlock_account(tx, result, &mut account_locks)); } - pub fn has_accounts(&self, fork: Fork) -> bool { - self.accounts_db.has_accounts(fork) + pub fn has_accounts(&self, slot: Slot) -> bool { + self.accounts_db.has_accounts(slot) } /// Store the accounts into the DB pub fn store_accounts( &self, - fork: Fork, + slot: Slot, txs: &[Transaction], txs_iteration_order: Option<&[usize]>, res: &[Result<()>], @@ -527,22 +556,22 @@ impl Accounts { ) { let accounts_to_store = self.collect_accounts_to_store(txs, txs_iteration_order, res, loaded); - self.accounts_db.store(fork, &accounts_to_store); + self.accounts_db.store(slot, &accounts_to_store); } - /// Purge a fork if it is not a root - /// Root forks cannot be purged - pub fn purge_fork(&self, fork: Fork) { - self.accounts_db.purge_fork(fork); + /// Purge a slot if it is not a root + /// Root slots cannot be purged + pub fn purge_slot(&self, slot: Slot) { + self.accounts_db.purge_slot(slot); } - /// Add a fork to root. Root forks cannot be purged - pub fn add_root(&self, fork: Fork) { - self.accounts_db.add_root(fork) + /// Add a slot to root. Root slots cannot be purged + pub fn add_root(&self, slot: Slot) { + self.accounts_db.add_root(slot) } /// Commit remaining credit-only changes, regardless of reference count /// - /// We do a take() on `self.credit_only_account_locks` so that the hashmap is no longer + /// We do a take() on `self.credit_only_locks` so that the hashmap is no longer /// available to be written to. This prevents any transactions from reinserting into the hashmap. /// Then there are then only 2 cases for interleaving with commit_credits and lock_accounts. /// Either: @@ -550,32 +579,34 @@ impl Accounts { // so will fail the lock // 2) Any transaction that grabs a lock and then commit_credits clears the HashMap will find // the HashMap is None on unlock_accounts, and will perform a no-op. - pub fn commit_credits(&self, ancestors: &HashMap, fork: Fork) { + pub fn commit_credits(&self, ancestors: &HashMap, slot: Slot) { // Clear the credit only hashmap so that no further transactions can modify it - let credit_only_account_locks = Self::take_credit_only(&self.credit_only_account_locks) + let credit_only_locks = self + .take_credit_only() .expect("Credit only locks didn't exist in commit_credits"); - self.store_credit_only_credits(credit_only_account_locks, ancestors, fork); + self.store_credit_only_credits(credit_only_locks, ancestors, slot); } /// Used only for tests to store credit-only accounts after every transaction - pub fn commit_credits_unsafe(&self, ancestors: &HashMap, fork: Fork) { + pub fn commit_credits_unsafe(&self, ancestors: &HashMap, slot: Slot) { // Clear the credit only hashmap so that no further transactions can modify it - let mut w_credit_only_account_locks = self.credit_only_account_locks.write().unwrap(); - let w_credit_only_account_locks = - Self::get_write_access_credit_only(&mut w_credit_only_account_locks) - .expect("Credit only locks didn't exist in commit_credits"); - self.store_credit_only_credits(w_credit_only_account_locks.drain(), ancestors, fork); + let mut credit_only_locks = self.credit_only_locks.write().unwrap(); + let credit_only_locks = credit_only_locks + .as_mut() + .expect("Credit only locks didn't exist in commit_credits"); + + self.store_credit_only_credits(credit_only_locks.drain(), ancestors, slot); } fn store_credit_only_credits( &self, - credit_only_account_locks: I, - ancestors: &HashMap, - fork: Fork, + credit_only_locks: I, + ancestors: &HashMap, + slot: Slot, ) where I: IntoIterator, { - for (pubkey, lock) in credit_only_account_locks { + for (pubkey, lock) in credit_only_locks { let lock_count = *lock.lock_count.lock().unwrap(); if lock_count != 0 { warn!( @@ -585,12 +616,12 @@ impl Accounts { } let credit = lock.credits.load(Ordering::Relaxed); if credit > 0 { - let mut account = self + let (mut account, _slot) = self + .accounts_db .load_slow(ancestors, &pubkey) - .map(|(account, _)| account) .unwrap_or_default(); account.lamports += credit; - self.store_slow(fork, &pubkey, &account); + self.store_slow(slot, &pubkey, &account); } } } @@ -626,7 +657,7 @@ impl Accounts { } if *credit > 0 { // Increment credit-only account balance Atomic - self.credit_only_account_locks + self.credit_only_locks .read() .unwrap() .as_ref() @@ -642,11 +673,11 @@ impl Accounts { } } -pub fn create_test_accounts(accounts: &Accounts, pubkeys: &mut Vec, num: usize, fork: u64) { +pub fn create_test_accounts(accounts: &Accounts, pubkeys: &mut Vec, num: usize, slot: u64) { for t in 0..num { let pubkey = Pubkey::new_rand(); let account = Account::new((t + 1) as u64, 0, &Account::default().owner); - accounts.store_slow(fork, &pubkey, &account); + accounts.store_slow(slot, &pubkey, &account); pubkeys.push(pubkey); } } @@ -1124,7 +1155,7 @@ mod tests { } #[test] - fn test_load_by_program_fork() { + fn test_load_by_program_slot() { let accounts = Accounts::new(None); // Load accounts owned by various programs into AccountsDB @@ -1138,11 +1169,11 @@ mod tests { let account2 = Account::new(1, 0, &Pubkey::new(&[3; 32])); accounts.store_slow(0, &pubkey2, &account2); - let loaded = accounts.load_by_program_fork(0, &Pubkey::new(&[2; 32])); + let loaded = accounts.load_by_program_slot(0, &Pubkey::new(&[2; 32])); assert_eq!(loaded.len(), 2); - let loaded = accounts.load_by_program_fork(0, &Pubkey::new(&[3; 32])); + let loaded = accounts.load_by_program_slot(0, &Pubkey::new(&[3; 32])); assert_eq!(loaded, vec![(pubkey2, account2)]); - let loaded = accounts.load_by_program_fork(0, &Pubkey::new(&[4; 32])); + let loaded = accounts.load_by_program_slot(0, &Pubkey::new(&[4; 32])); assert_eq!(loaded, vec![]); } @@ -1258,7 +1289,7 @@ mod tests { assert!(results0[0].is_ok()); assert_eq!( *accounts - .credit_only_account_locks + .credit_only_locks .read() .unwrap() .as_ref() @@ -1298,7 +1329,7 @@ mod tests { assert!(results1[1].is_err()); // Credit-only account (keypair1) cannot also be locked as credit-debit assert_eq!( *accounts - .credit_only_account_locks + .credit_only_locks .read() .unwrap() .as_ref() @@ -1329,9 +1360,9 @@ mod tests { assert!(results2[0].is_ok()); // Now keypair1 account can be locked as credit-debit // Check that credit-only credits are still cached in accounts struct - let credit_only_account_locks = accounts.credit_only_account_locks.read().unwrap(); - let credit_only_account_locks = credit_only_account_locks.as_ref().unwrap(); - let keypair1_lock = credit_only_account_locks.get(&keypair1.pubkey()); + let credit_only_locks = accounts.credit_only_locks.read().unwrap(); + let credit_only_locks = credit_only_locks.as_ref().unwrap(); + let keypair1_lock = credit_only_locks.get(&keypair1.pubkey()); assert!(keypair1_lock.is_some()); assert_eq!(*keypair1_lock.unwrap().lock_count.lock().unwrap(), 0); } @@ -1427,23 +1458,23 @@ mod tests { accounts.store_slow(0, &pubkey1, &account1); { - let mut credit_only_account_locks = accounts.credit_only_account_locks.write().unwrap(); - let credit_only_account_locks = credit_only_account_locks.as_mut().unwrap(); - credit_only_account_locks.insert( + let mut credit_only_locks = accounts.credit_only_locks.write().unwrap(); + let credit_only_locks = credit_only_locks.as_mut().unwrap(); + credit_only_locks.insert( pubkey0, CreditOnlyLock { credits: AtomicU64::new(0), lock_count: Mutex::new(1), }, ); - credit_only_account_locks.insert( + credit_only_locks.insert( pubkey1, CreditOnlyLock { credits: AtomicU64::new(5), lock_count: Mutex::new(1), }, ); - credit_only_account_locks.insert( + credit_only_locks.insert( pubkey2, CreditOnlyLock { credits: AtomicU64::new(10), @@ -1453,7 +1484,7 @@ mod tests { } let ancestors = vec![(0, 0)].into_iter().collect(); - accounts.commit_credits_unsafe(&ancestors, 0); + accounts.commit_credits(&ancestors, 0); // No change when CreditOnlyLock credits are 0 assert_eq!( @@ -1471,15 +1502,49 @@ mod tests { 10 ); // Account locks should be cleared + assert!(accounts.credit_only_locks.read().unwrap().is_none()); + } + + #[test] + fn test_credit_only_pending_credits() { + let pubkey = Pubkey::new_rand(); + let account = Account::new(1, 0, &Pubkey::default()); + + let accounts = Accounts::new(None); + accounts.store_slow(0, &pubkey, &account); + + accounts.insert_credit_only( + &pubkey, + CreditOnlyLock { + credits: AtomicU64::new(10), + lock_count: Mutex::new(1), + }, + ); + + let ancestors = vec![(0, 0)].into_iter().collect(); + assert_eq!( + accounts.load_slow(&ancestors, &pubkey).unwrap().0.lamports, + 11 + ); assert_eq!( accounts - .credit_only_account_locks - .read() + .accounts_db + .load_slow(&ancestors, &pubkey) .unwrap() - .as_ref() + .0 + .lamports, + 1 + ); + + accounts.commit_credits(&ancestors, 0); + assert_eq!( + accounts + .accounts_db + .load_slow(&ancestors, &pubkey) .unwrap() - .len(), - 0 + .0 + .lamports, + 11 ); } @@ -1544,7 +1609,7 @@ mod tests { let accounts = Accounts::new(None); { - let mut credit_only_locks = accounts.credit_only_account_locks.write().unwrap(); + let mut credit_only_locks = accounts.credit_only_locks.write().unwrap(); let credit_only_locks = credit_only_locks.as_mut().unwrap(); credit_only_locks.insert( pubkey, @@ -1567,7 +1632,7 @@ mod tests { .is_some()); // Ensure credit_only_lock reflects credits from both accounts: 2 + 3 = 5 - let credit_only_locks = accounts.credit_only_account_locks.read().unwrap(); + let credit_only_locks = accounts.credit_only_locks.read().unwrap(); let credit_only_locks = credit_only_locks.as_ref().unwrap(); assert_eq!( credit_only_locks diff --git a/runtime/src/accounts_db.rs b/runtime/src/accounts_db.rs index 3d6f06395e..f34c475810 100644 --- a/runtime/src/accounts_db.rs +++ b/runtime/src/accounts_db.rs @@ -12,13 +12,13 @@ //! The only required in memory data structure with a write lock is the index, //! which should be fast to update. //! -//! AppendVec's only store accounts for single forks. To bootstrap the +//! AppendVec's only store accounts for single slots. To bootstrap the //! index from a persistent store of AppendVec's, the entries include //! a "write_version". A single global atomic `AccountsDB::write_version` //! tracks the number of commits to the entire data store. So the latest -//! commit for each fork entry would be indexed. +//! commit for each slot entry would be indexed. -use crate::accounts_index::{AccountsIndex, Fork}; +use crate::accounts_index::AccountsIndex; use crate::append_vec::{AppendVec, StoredAccount, StoredMeta}; use bincode::{deserialize_from, serialize_into}; use byteorder::{ByteOrder, LittleEndian}; @@ -34,6 +34,7 @@ use solana_measure::measure::Measure; use solana_rayon_threadlimit::get_thread_count; use solana_sdk::account::Account; use solana_sdk::bank_hash::BankHash; +use solana_sdk::clock::Slot; use solana_sdk::hash::{Hash, Hasher}; use solana_sdk::pubkey::Pubkey; use solana_sdk::sysvar; @@ -81,8 +82,8 @@ pub struct AccountInfo { /// An offset into the AccountsDB::storage vector pub type AppendVecId = usize; -// Each fork has a set of storage entries. -type ForkStores = HashMap>; +// Each slot has a set of storage entries. +type SlotStores = HashMap>; struct AccountStorageVisitor; @@ -99,12 +100,12 @@ impl<'de> Visitor<'de> for AccountStorageVisitor { M: MapAccess<'de>, { let mut map = HashMap::new(); - while let Some((fork_id, storage_entries)) = access.next_entry()? { + while let Some((slot_id, storage_entries)) = access.next_entry()? { let storage_entries: Vec = storage_entries; - let storage_fork_map = map.entry(fork_id).or_insert_with(HashMap::new); + let storage_slot_map = map.entry(slot_id).or_insert_with(HashMap::new); for mut storage in storage_entries { - storage.fork_id = fork_id; - storage_fork_map.insert(storage.id, Arc::new(storage)); + storage.slot_id = slot_id; + storage_slot_map.insert(storage.id, Arc::new(storage)); } } @@ -131,19 +132,19 @@ impl<'a> Serialize for AccountStorageSerialize<'a> { S: Serializer, { let mut len: usize = 0; - for fork_id in self.account_storage.0.keys() { - if *fork_id <= self.slot { + for slot_id in self.account_storage.0.keys() { + if *slot_id <= self.slot { len += 1; } } let mut map = serializer.serialize_map(Some(len))?; let mut count = 0; let mut serialize_account_storage_timer = Measure::start("serialize_account_storage_ms"); - for (fork_id, fork_storage) in &self.account_storage.0 { - if *fork_id <= self.slot { - let storage_entries: Vec<_> = fork_storage.values().collect(); - map.serialize_entry(&fork_id, &storage_entries)?; - count += fork_storage.len(); + for (slot_id, slot_storage) in &self.account_storage.0 { + if *slot_id <= self.slot { + let storage_entries: Vec<_> = slot_storage.values().collect(); + map.serialize_entry(&slot_id, &storage_entries)?; + count += slot_storage.len(); } } serialize_account_storage_timer.stop(); @@ -157,7 +158,7 @@ impl<'a> Serialize for AccountStorageSerialize<'a> { } #[derive(Clone, Default, Debug)] -pub struct AccountStorage(pub HashMap); +pub struct AccountStorage(pub HashMap); impl<'de> Deserialize<'de> for AccountStorage { fn deserialize(deserializer: D) -> Result where @@ -180,7 +181,7 @@ pub struct AccountStorageEntry { id: AppendVecId, #[serde(skip)] - fork_id: Fork, + slot_id: Slot, /// storage holding the accounts accounts: AppendVec, @@ -194,14 +195,14 @@ pub struct AccountStorageEntry { } impl AccountStorageEntry { - pub fn new(path: &Path, fork_id: Fork, id: usize, file_size: u64) -> Self { - let tail = AppendVec::new_relative_path(fork_id, id); + pub fn new(path: &Path, slot_id: Slot, id: usize, file_size: u64) -> Self { + let tail = AppendVec::new_relative_path(slot_id, id); let path = Path::new(path).join(&tail); let accounts = AppendVec::new(&path, true, file_size as usize); AccountStorageEntry { id, - fork_id, + slot_id, accounts, count_and_status: RwLock::new((0, AccountStorageStatus::Available)), } @@ -236,8 +237,8 @@ impl AccountStorageEntry { self.count_and_status.read().unwrap().0 } - pub fn fork_id(&self) -> Fork { - self.fork_id + pub fn slot_id(&self) -> Slot { + self.slot_id } pub fn append_vec_id(&self) -> AppendVecId { @@ -288,7 +289,7 @@ impl AccountStorageEntry { if count > 0 { *count_and_status = (count - 1, status); } else { - warn!("count value 0 for fork {}", self.fork_id); + warn!("count value 0 for slot {}", self.slot_id); } count_and_status.0 } @@ -343,10 +344,10 @@ impl<'a> Serialize for AccountsDBSerialize<'a> { let account_storage_serialize = AccountStorageSerialize::new(&*storage, self.slot); serialize_into(&mut wr, &account_storage_serialize).map_err(Error::custom)?; serialize_into(&mut wr, &version).map_err(Error::custom)?; - let fork_hashes = self.accounts_db.fork_hashes.read().unwrap(); + let slot_hashes = self.accounts_db.slot_hashes.read().unwrap(); serialize_into( &mut wr, - &(self.slot, &*fork_hashes.get(&self.slot).unwrap()), + &(self.slot, &*slot_hashes.get(&self.slot).unwrap()), ) .map_err(Error::custom)?; let len = wr.position() as usize; @@ -357,7 +358,7 @@ impl<'a> Serialize for AccountsDBSerialize<'a> { // This structure handles the load/store of the accounts #[derive(Debug)] pub struct AccountsDB { - /// Keeps tracks of index into AppendVec on a per fork basis + /// Keeps tracks of index into AppendVec on a per slot basis pub accounts_index: RwLock>, /// Account storage @@ -385,8 +386,8 @@ pub struct AccountsDB { /// the accounts min_num_stores: usize, - /// fork to BankHash and a status flag to indicate if the hash has been initialized or not - pub fork_hashes: RwLock>, + /// slot to BankHash and a status flag to indicate if the hash has been initialized or not + pub slot_hashes: RwLock>, } impl Default for AccountsDB { @@ -406,7 +407,7 @@ impl Default for AccountsDB { .build() .unwrap(), min_num_stores: num_threads, - fork_hashes: RwLock::new(HashMap::default()), + slot_hashes: RwLock::new(HashMap::default()), } } } @@ -467,12 +468,12 @@ impl AccountsDB { // Remap the deserialized AppendVec paths to point to correct local paths let local_account_paths = get_paths_vec(&local_account_paths); - let new_storage_map: Result, IOError> = storage + let new_storage_map: Result, IOError> = storage .0 .into_iter() - .map(|(fork_id, mut fork_storage)| { - let mut new_fork_storage = HashMap::new(); - for (id, storage_entry) in fork_storage.drain() { + .map(|(slot_id, mut slot_storage)| { + let mut new_slot_storage = HashMap::new(); + for (id, storage_entry) in slot_storage.drain() { let path_index = thread_rng().gen_range(0, local_account_paths.len()); let local_dir = &local_account_paths[path_index]; @@ -481,7 +482,7 @@ impl AccountsDB { // Move the corresponding AppendVec from the snapshot into the directory pointed // at by `local_dir` let append_vec_relative_path = - AppendVec::new_relative_path(fork_id, storage_entry.id); + AppendVec::new_relative_path(slot_id, storage_entry.id); let append_vec_abs_path = append_vecs_path.as_ref().join(&append_vec_relative_path); let mut copy_options = CopyOptions::new(); @@ -500,9 +501,9 @@ impl AccountsDB { u_storage_entry .set_file(local_path) .map_err(|e| AccountsDB::get_io_error(&e.to_string()))?; - new_fork_storage.insert(id, Arc::new(u_storage_entry)); + new_slot_storage.insert(id, Arc::new(u_storage_entry)); } - Ok((fork_id, new_fork_storage)) + Ok((slot_id, new_slot_storage)) }) .collect(); @@ -511,12 +512,12 @@ impl AccountsDB { let version: u64 = deserialize_from(&mut stream) .map_err(|_| AccountsDB::get_io_error("write version deserialize error"))?; - let fork_hash: (Fork, (bool, BankHash)) = deserialize_from(&mut stream) - .map_err(|_| AccountsDB::get_io_error("fork hashes deserialize error"))?; - self.fork_hashes + let slot_hash: (Slot, (bool, BankHash)) = deserialize_from(&mut stream) + .map_err(|_| AccountsDB::get_io_error("slot hashes deserialize error"))?; + self.slot_hashes .write() .unwrap() - .insert(fork_hash.0, fork_hash.1); + .insert(slot_hash.0, slot_hash.1); // Process deserialized data, set necessary fields in self *self.paths.write().unwrap() = local_account_paths; @@ -539,18 +540,18 @@ impl AccountsDB { Ok(()) } - fn new_storage_entry(&self, fork_id: Fork, path: &Path, size: u64) -> AccountStorageEntry { + fn new_storage_entry(&self, slot_id: Slot, path: &Path, size: u64) -> AccountStorageEntry { AccountStorageEntry::new( path, - fork_id, + slot_id, self.next_id.fetch_add(1, Ordering::Relaxed), size, ) } - pub fn has_accounts(&self, fork: Fork) -> bool { - if let Some(storage_forks) = self.storage.read().unwrap().0.get(&fork) { - for x in storage_forks.values() { + pub fn has_accounts(&self, slot: Slot) -> bool { + if let Some(storage_slots) = self.storage.read().unwrap().0.get(&slot) { + for x in storage_slots.values() { if x.count() > 0 { return true; } @@ -562,8 +563,8 @@ impl AccountsDB { pub fn purge_zero_lamport_accounts(&self, ancestors: &HashMap) { let accounts_index = self.accounts_index.read().unwrap(); let mut purges = Vec::new(); - accounts_index.scan_accounts(ancestors, |pubkey, (account_info, fork)| { - if account_info.lamports == 0 && accounts_index.is_root(fork) { + accounts_index.scan_accounts(ancestors, |pubkey, (account_info, slot)| { + if account_info.lamports == 0 && accounts_index.is_root(slot) { purges.push(*pubkey); } }); @@ -575,24 +576,24 @@ impl AccountsDB { } let last_root = accounts_index.last_root; drop(accounts_index); - let mut dead_forks = self.remove_dead_accounts(reclaims); - self.cleanup_dead_forks(&mut dead_forks, last_root); + let mut dead_slots = self.remove_dead_accounts(reclaims); + self.cleanup_dead_slots(&mut dead_slots, last_root); } - pub fn scan_accounts(&self, ancestors: &HashMap, scan_func: F) -> A + pub fn scan_accounts(&self, ancestors: &HashMap, scan_func: F) -> A where - F: Fn(&mut A, Option<(&Pubkey, Account, Fork)>) -> (), + F: Fn(&mut A, Option<(&Pubkey, Account, Slot)>) -> (), A: Default, { let mut collector = A::default(); let accounts_index = self.accounts_index.read().unwrap(); let storage = self.storage.read().unwrap(); - accounts_index.scan_accounts(ancestors, |pubkey, (account_info, fork)| { + accounts_index.scan_accounts(ancestors, |pubkey, (account_info, slot)| { scan_func( &mut collector, storage .0 - .get(&fork) + .get(&slot) .and_then(|storage_map| storage_map.get(&account_info.id)) .and_then(|store| { Some( @@ -603,15 +604,15 @@ impl AccountsDB { .clone_account(), ) }) - .map(|account| (pubkey, account, fork)), + .map(|account| (pubkey, account, slot)), ) }); collector } - /// Scan a specific fork through all the account storage in parallel with sequential read + /// Scan a specific slot through all the account storage in parallel with sequential read // PERF: Sequentially read each storage entry in parallel - pub fn scan_account_storage(&self, fork_id: Fork, scan_func: F) -> Vec + pub fn scan_account_storage(&self, slot_id: Slot, scan_func: F) -> Vec where F: Fn(&StoredAccount, AppendVecId, &mut B) -> () + Send + Sync, B: Send + Default, @@ -621,7 +622,7 @@ impl AccountsDB { .read() .unwrap() .0 - .get(&fork_id) + .get(&slot_id) .unwrap_or(&HashMap::new()) .values() .cloned() @@ -641,29 +642,29 @@ impl AccountsDB { }) } - pub fn set_hash(&self, slot: Fork, parent_slot: Fork) { - let mut fork_hashes = self.fork_hashes.write().unwrap(); - let hash = *fork_hashes + pub fn set_hash(&self, slot: Slot, parent_slot: Slot) { + let mut slot_hashes = self.slot_hashes.write().unwrap(); + let hash = *slot_hashes .get(&parent_slot) .expect("accounts_db::set_hash::no parent slot"); - fork_hashes.insert(slot, (false, hash.1)); + slot_hashes.insert(slot, (false, hash.1)); } pub fn load( storage: &AccountStorage, - ancestors: &HashMap, + ancestors: &HashMap, accounts_index: &AccountsIndex, pubkey: &Pubkey, - ) -> Option<(Account, Fork)> { + ) -> Option<(Account, Slot)> { let (lock, index) = accounts_index.get(pubkey, ancestors)?; - let fork = lock[index].0; + let slot = lock[index].0; //TODO: thread this as a ref - if let Some(fork_storage) = storage.0.get(&fork) { + if let Some(slot_storage) = storage.0.get(&slot) { let info = &lock[index].1; - fork_storage + slot_storage .get(&info.id) .and_then(|store| Some(store.accounts.get_account(info.offset)?.0.clone_account())) - .map(|account| (account, fork)) + .map(|account| (account, slot)) } else { None } @@ -671,46 +672,46 @@ impl AccountsDB { pub fn load_slow( &self, - ancestors: &HashMap, + ancestors: &HashMap, pubkey: &Pubkey, - ) -> Option<(Account, Fork)> { + ) -> Option<(Account, Slot)> { let accounts_index = self.accounts_index.read().unwrap(); let storage = self.storage.read().unwrap(); Self::load(&storage, ancestors, &accounts_index, pubkey) } - fn find_storage_candidate(&self, fork_id: Fork) -> Arc { + fn find_storage_candidate(&self, slot_id: Slot) -> Arc { let mut create_extra = false; let stores = self.storage.read().unwrap(); - if let Some(fork_stores) = stores.0.get(&fork_id) { - if !fork_stores.is_empty() { - if fork_stores.len() <= self.min_num_stores { + if let Some(slot_stores) = stores.0.get(&slot_id) { + if !slot_stores.is_empty() { + if slot_stores.len() <= self.min_num_stores { let mut total_accounts = 0; - for store in fork_stores.values() { + for store in slot_stores.values() { total_accounts += store.count_and_status.read().unwrap().0; } // Create more stores so that when scanning the storage all CPUs have work - if (total_accounts / 16) >= fork_stores.len() { + if (total_accounts / 16) >= slot_stores.len() { create_extra = true; } } // pick an available store at random by iterating from a random point - let to_skip = thread_rng().gen_range(0, fork_stores.len()); + let to_skip = thread_rng().gen_range(0, slot_stores.len()); - for (i, store) in fork_stores.values().cycle().skip(to_skip).enumerate() { + for (i, store) in slot_stores.values().cycle().skip(to_skip).enumerate() { if store.try_available() { let ret = store.clone(); drop(stores); if create_extra { - self.create_and_insert_store(fork_id, self.file_size); + self.create_and_insert_store(slot_id, self.file_size); } return ret; } // looked at every store, bail... - if i == fork_stores.len() { + if i == slot_stores.len() { break; } } @@ -719,53 +720,53 @@ impl AccountsDB { drop(stores); - let store = self.create_and_insert_store(fork_id, self.file_size); + let store = self.create_and_insert_store(slot_id, self.file_size); store.try_available(); store } - fn create_and_insert_store(&self, fork_id: Fork, size: u64) -> Arc { + fn create_and_insert_store(&self, slot_id: Slot, size: u64) -> Arc { let mut stores = self.storage.write().unwrap(); - let fork_storage = stores.0.entry(fork_id).or_insert_with(HashMap::new); + let slot_storage = stores.0.entry(slot_id).or_insert_with(HashMap::new); - self.create_store(fork_id, fork_storage, size) + self.create_store(slot_id, slot_storage, size) } fn create_store( &self, - fork_id: Fork, - fork_storage: &mut ForkStores, + slot_id: Slot, + slot_storage: &mut SlotStores, size: u64, ) -> Arc { let paths = self.paths.read().unwrap(); let path_index = thread_rng().gen_range(0, paths.len()); - let store = Arc::new(self.new_storage_entry(fork_id, &Path::new(&paths[path_index]), size)); - fork_storage.insert(store.id, store.clone()); + let store = Arc::new(self.new_storage_entry(slot_id, &Path::new(&paths[path_index]), size)); + slot_storage.insert(store.id, store.clone()); store } - pub fn purge_fork(&self, fork: Fork) { + pub fn purge_slot(&self, slot: Slot) { //add_root should be called first - let is_root = self.accounts_index.read().unwrap().is_root(fork); + let is_root = self.accounts_index.read().unwrap().is_root(slot); if !is_root { - self.storage.write().unwrap().0.remove(&fork); + self.storage.write().unwrap().0.remove(&slot); } } - pub fn hash_stored_account(fork: Fork, account: &StoredAccount) -> Hash { + pub fn hash_stored_account(slot: Slot, account: &StoredAccount) -> Hash { Self::hash_account_data( - fork, + slot, account.account_meta.lamports, account.data, &account.meta.pubkey, ) } - pub fn hash_account(fork: Fork, account: &Account, pubkey: &Pubkey) -> Hash { - Self::hash_account_data(fork, account.lamports, &account.data, pubkey) + pub fn hash_account(slot: Slot, account: &Account, pubkey: &Pubkey) -> Hash { + Self::hash_account_data(slot, account.lamports, &account.data, pubkey) } - pub fn hash_account_data(fork: Fork, lamports: u64, data: &[u8], pubkey: &Pubkey) -> Hash { + pub fn hash_account_data(slot: Slot, lamports: u64, data: &[u8], pubkey: &Pubkey) -> Hash { if lamports == 0 { return Hash::default(); } @@ -776,7 +777,7 @@ impl AccountsDB { LittleEndian::write_u64(&mut buf[..], lamports); hasher.hash(&buf); - LittleEndian::write_u64(&mut buf[..], fork); + LittleEndian::write_u64(&mut buf[..], slot); hasher.hash(&buf); hasher.hash(&data); @@ -788,7 +789,7 @@ impl AccountsDB { fn store_accounts( &self, - fork_id: Fork, + slot_id: Slot, accounts: &[(&Pubkey, &Account)], hashes: &[Hash], ) -> Vec { @@ -812,7 +813,7 @@ impl AccountsDB { .collect(); let mut infos: Vec = vec![]; while infos.len() < with_meta.len() { - let storage = self.find_storage_candidate(fork_id); + let storage = self.find_storage_candidate(slot_id); let rvs = storage .accounts .append_accounts(&with_meta[infos.len()..], &hashes); @@ -822,7 +823,7 @@ impl AccountsDB { // See if an account overflows the default append vec size. let data_len = (with_meta[infos.len()].1.data.len() + 4096) as u64; if data_len > self.file_size { - self.create_and_insert_store(fork_id, data_len * 2); + self.create_and_insert_store(slot_id, data_len * 2); } continue; } @@ -840,14 +841,14 @@ impl AccountsDB { infos } - pub fn verify_hash_internal_state(&self, fork: Fork, ancestors: &HashMap) -> bool { + pub fn verify_hash_internal_state(&self, slot: Slot, ancestors: &HashMap) -> bool { let mut hash_state = BankHash::default(); let hashes: Vec<_> = self.scan_accounts( ancestors, - |collector: &mut Vec, option: Option<(&Pubkey, Account, Fork)>| { - if let Some((pubkey, account, fork)) = option { + |collector: &mut Vec, option: Option<(&Pubkey, Account, Slot)>| { + if let Some((pubkey, account, slot)) = option { if !sysvar::check_id(&account.owner) { - let hash = BankHash::from_hash(&Self::hash_account(fork, &account, pubkey)); + let hash = BankHash::from_hash(&Self::hash_account(slot, &account, pubkey)); debug!("xoring..{} key: {}", hash, pubkey); collector.push(hash); } @@ -857,36 +858,36 @@ impl AccountsDB { for hash in hashes { hash_state.xor(hash); } - let fork_hashes = self.fork_hashes.read().unwrap(); - if let Some((_, state)) = fork_hashes.get(&fork) { + let slot_hashes = self.slot_hashes.read().unwrap(); + if let Some((_, state)) = slot_hashes.get(&slot) { hash_state == *state } else { false } } - pub fn xor_in_hash_state(&self, fork_id: Fork, hash: BankHash) { - let mut fork_hashes = self.fork_hashes.write().unwrap(); - let fork_hash_state = fork_hashes - .entry(fork_id) + pub fn xor_in_hash_state(&self, slot_id: Slot, hash: BankHash) { + let mut slot_hashes = self.slot_hashes.write().unwrap(); + let slot_hash_state = slot_hashes + .entry(slot_id) .or_insert((false, BankHash::default())); - fork_hash_state.1.xor(hash); - fork_hash_state.0 = true; + slot_hash_state.1.xor(hash); + slot_hash_state.0 = true; } fn update_index( &self, - fork_id: Fork, + slot_id: Slot, infos: Vec, accounts: &[(&Pubkey, &Account)], - ) -> (Vec<(Fork, AccountInfo)>, u64) { - let mut reclaims: Vec<(Fork, AccountInfo)> = Vec::with_capacity(infos.len() * 2); + ) -> (Vec<(Slot, AccountInfo)>, u64) { + let mut reclaims: Vec<(Slot, AccountInfo)> = Vec::with_capacity(infos.len() * 2); let mut inserts = vec![]; let index = self.accounts_index.read().unwrap(); let mut update_index_work = Measure::start("update_index_work"); for (info, pubkey_account) in infos.into_iter().zip(accounts.iter()) { let pubkey = pubkey_account.0; - if let Some(info) = index.update(fork_id, pubkey, info, &mut reclaims) { + if let Some(info) = index.update(slot_id, pubkey, info, &mut reclaims) { inserts.push((pubkey, info)); } } @@ -895,34 +896,34 @@ impl AccountsDB { if !inserts.is_empty() { let mut index = self.accounts_index.write().unwrap(); for (pubkey, info) in inserts { - index.insert(fork_id, pubkey, info, &mut reclaims); + index.insert(slot_id, pubkey, info, &mut reclaims); } } update_index_work.stop(); (reclaims, last_root) } - fn remove_dead_accounts(&self, reclaims: Vec<(Fork, AccountInfo)>) -> HashSet { + fn remove_dead_accounts(&self, reclaims: Vec<(Slot, AccountInfo)>) -> HashSet { let storage = self.storage.read().unwrap(); - let mut dead_forks = HashSet::new(); - for (fork_id, account_info) in reclaims { - if let Some(fork_storage) = storage.0.get(&fork_id) { - if let Some(store) = fork_storage.get(&account_info.id) { + let mut dead_slots = HashSet::new(); + for (slot_id, account_info) in reclaims { + if let Some(slot_storage) = storage.0.get(&slot_id) { + if let Some(store) = slot_storage.get(&account_info.id) { assert_eq!( - fork_id, store.fork_id, - "AccountDB::accounts_index corrupted. Storage should only point to one fork" + slot_id, store.slot_id, + "AccountDB::accounts_index corrupted. Storage should only point to one slot" ); let count = store.remove_account(); if count == 0 { - dead_forks.insert(fork_id); + dead_slots.insert(slot_id); } } } } - dead_forks.retain(|fork| { - if let Some(fork_storage) = storage.0.get(&fork) { - for x in fork_storage.values() { + dead_slots.retain(|slot| { + if let Some(slot_storage) = storage.0.get(&slot) { + for x in slot_storage.values() { if x.count() != 0 { return false; } @@ -931,36 +932,36 @@ impl AccountsDB { true }); - dead_forks + dead_slots } - fn cleanup_dead_forks(&self, dead_forks: &mut HashSet, last_root: u64) { - // a fork is not totally dead until it is older than the root - dead_forks.retain(|fork| *fork < last_root); - if !dead_forks.is_empty() { + fn cleanup_dead_slots(&self, dead_slots: &mut HashSet, last_root: u64) { + // a slot is not totally dead until it is older than the root + dead_slots.retain(|slot| *slot < last_root); + if !dead_slots.is_empty() { { let mut index = self.accounts_index.write().unwrap(); - for fork in dead_forks.iter() { - index.cleanup_dead_fork(*fork); + for slot in dead_slots.iter() { + index.cleanup_dead_slot(*slot); } } { - let mut fork_hashes = self.fork_hashes.write().unwrap(); - for fork in dead_forks.iter() { - fork_hashes.remove(fork); + let mut slot_hashes = self.slot_hashes.write().unwrap(); + for slot in dead_slots.iter() { + slot_hashes.remove(slot); } } } } - fn hash_accounts(&self, fork_id: Fork, accounts: &[(&Pubkey, &Account)]) -> Vec { + fn hash_accounts(&self, slot_id: Slot, accounts: &[(&Pubkey, &Account)]) -> Vec { let mut hashes = vec![]; let mut hash_state = BankHash::default(); let mut had_account = false; for (pubkey, account) in accounts { if !sysvar::check_id(&account.owner) { let hash = BankHash::from_hash(&account.hash); - let new_hash = Self::hash_account(fork_id, account, pubkey); + let new_hash = Self::hash_account(slot_id, account, pubkey); let new_bank_hash = BankHash::from_hash(&new_hash); debug!( "hash_accounts: key: {} xor {} current: {}", @@ -980,43 +981,43 @@ impl AccountsDB { } if had_account { - self.xor_in_hash_state(fork_id, hash_state); + self.xor_in_hash_state(slot_id, hash_state); } hashes } /// Store the account update. - pub fn store(&self, fork_id: Fork, accounts: &[(&Pubkey, &Account)]) { - let hashes = self.hash_accounts(fork_id, accounts); + pub fn store(&self, slot_id: Slot, accounts: &[(&Pubkey, &Account)]) { + let hashes = self.hash_accounts(slot_id, accounts); let mut store_accounts = Measure::start("store::store_accounts"); - let infos = self.store_accounts(fork_id, accounts, &hashes); + let infos = self.store_accounts(slot_id, accounts, &hashes); store_accounts.stop(); let mut update_index = Measure::start("store::update_index"); - let (reclaims, last_root) = self.update_index(fork_id, infos, accounts); + let (reclaims, last_root) = self.update_index(slot_id, infos, accounts); update_index.stop(); trace!("reclaim: {}", reclaims.len()); let mut remove_dead_accounts = Measure::start("store::remove_dead"); - let mut dead_forks = self.remove_dead_accounts(reclaims); + let mut dead_slots = self.remove_dead_accounts(reclaims); remove_dead_accounts.stop(); - trace!("dead_forks: {}", dead_forks.len()); + trace!("dead_slots: {}", dead_slots.len()); - let mut cleanup_dead_forks = Measure::start("store::cleanup_dead_forks"); - self.cleanup_dead_forks(&mut dead_forks, last_root); - cleanup_dead_forks.stop(); - trace!("purge_forks: {}", dead_forks.len()); + let mut cleanup_dead_slots = Measure::start("store::cleanup_dead_slots"); + self.cleanup_dead_slots(&mut dead_slots, last_root); + cleanup_dead_slots.stop(); + trace!("purge_slots: {}", dead_slots.len()); - let mut purge_forks = Measure::start("store::purge_forks"); - for fork in dead_forks { - self.purge_fork(fork); + let mut purge_slots = Measure::start("store::purge_slots"); + for slot in dead_slots { + self.purge_slot(slot); } - purge_forks.stop(); + purge_slots.stop(); } - pub fn add_root(&self, fork: Fork) { - self.accounts_index.write().unwrap().add_root(fork) + pub fn add_root(&self, slot: Slot) { + self.accounts_index.write().unwrap().add_root(slot) } pub fn get_storage_entries(&self) -> Vec> { @@ -1024,7 +1025,7 @@ impl AccountsDB { r_storage .0 .values() - .flat_map(|fork_store| fork_store.values().cloned()) + .flat_map(|slot_store| slot_store.values().cloned()) .collect() } @@ -1049,13 +1050,13 @@ impl AccountsDB { fn generate_index(&self) { let storage = self.storage.read().unwrap(); - let mut forks: Vec = storage.0.keys().cloned().collect(); - forks.sort(); + let mut slots: Vec = storage.0.keys().cloned().collect(); + slots.sort(); let mut accounts_index = self.accounts_index.write().unwrap(); - for fork_id in forks.iter() { + for slot_id in slots.iter() { let mut accumulator: Vec> = self .scan_account_storage( - *fork_id, + *slot_id, |stored_account: &StoredAccount, id: AppendVecId, accum: &mut HashMap| { @@ -1076,10 +1077,10 @@ impl AccountsDB { AccountsDB::merge(&mut account_maps, &maps); } if !account_maps.is_empty() { - accounts_index.roots.insert(*fork_id); + accounts_index.roots.insert(*slot_id); let mut _reclaims: Vec<(u64, AccountInfo)> = vec![]; for (pubkey, (_, account_info)) in account_maps.iter() { - accounts_index.insert(*fork_id, pubkey, account_info.clone(), &mut _reclaims); + accounts_index.insert(*slot_id, pubkey, account_info.clone(), &mut _reclaims); } } } @@ -1157,7 +1158,7 @@ pub mod tests { } #[test] - fn test_accountsdb_root_one_fork() { + fn test_accountsdb_root_one_slot() { solana_logger::setup(); let db = AccountsDB::new(None); @@ -1172,8 +1173,8 @@ pub mod tests { // root0 -> key.lamports==1 // / \ // / \ - // key.lamports==0 <- fork1 \ - // fork2 -> key.lamports==1 + // key.lamports==0 <- slot1 \ + // slot2 -> key.lamports==1 // (via root0) // store value 0 in one child @@ -1186,7 +1187,7 @@ pub mod tests { let ancestors = vec![(0, 0), (1, 1)].into_iter().collect(); assert_eq!(&db.load_slow(&ancestors, &key).unwrap().0, &account1); - // we should see 1 token in fork 2 + // we should see 1 token in slot 2 let ancestors = vec![(0, 0), (2, 2)].into_iter().collect(); assert_eq!(&db.load_slow(&ancestors, &key).unwrap().0, &account0); @@ -1244,22 +1245,22 @@ pub mod tests { db.store(1, &[(&pubkeys[0], &account)]); { let stores = db.storage.read().unwrap(); - let fork_0_stores = &stores.0.get(&0).unwrap(); - let fork_1_stores = &stores.0.get(&1).unwrap(); - assert_eq!(fork_0_stores.len(), 1); - assert_eq!(fork_1_stores.len(), 1); - assert_eq!(fork_0_stores[&0].count(), 2); - assert_eq!(fork_1_stores[&1].count(), 2); + let slot_0_stores = &stores.0.get(&0).unwrap(); + let slot_1_stores = &stores.0.get(&1).unwrap(); + assert_eq!(slot_0_stores.len(), 1); + assert_eq!(slot_1_stores.len(), 1); + assert_eq!(slot_0_stores[&0].count(), 2); + assert_eq!(slot_1_stores[&1].count(), 2); } db.add_root(1); { let stores = db.storage.read().unwrap(); - let fork_0_stores = &stores.0.get(&0).unwrap(); - let fork_1_stores = &stores.0.get(&1).unwrap(); - assert_eq!(fork_0_stores.len(), 1); - assert_eq!(fork_1_stores.len(), 1); - assert_eq!(fork_0_stores[&0].count(), 2); - assert_eq!(fork_1_stores[&1].count(), 2); + let slot_0_stores = &stores.0.get(&0).unwrap(); + let slot_1_stores = &stores.0.get(&1).unwrap(); + assert_eq!(slot_0_stores.len(), 1); + assert_eq!(slot_1_stores.len(), 1); + assert_eq!(slot_0_stores[&0].count(), 2); + assert_eq!(slot_1_stores[&1].count(), 2); } } @@ -1287,38 +1288,38 @@ pub mod tests { fn create_account( accounts: &AccountsDB, pubkeys: &mut Vec, - fork: Fork, + slot: Slot, num: usize, space: usize, num_vote: usize, ) { - let ancestors = vec![(fork, 0)].into_iter().collect(); + let ancestors = vec![(slot, 0)].into_iter().collect(); for t in 0..num { let pubkey = Pubkey::new_rand(); let account = Account::new((t + 1) as u64, space, &Account::default().owner); pubkeys.push(pubkey.clone()); assert!(accounts.load_slow(&ancestors, &pubkey).is_none()); - accounts.store(fork, &[(&pubkey, &account)]); + accounts.store(slot, &[(&pubkey, &account)]); } for t in 0..num_vote { let pubkey = Pubkey::new_rand(); let account = Account::new((num + t + 1) as u64, space, &solana_vote_api::id()); pubkeys.push(pubkey.clone()); - let ancestors = vec![(fork, 0)].into_iter().collect(); + let ancestors = vec![(slot, 0)].into_iter().collect(); assert!(accounts.load_slow(&ancestors, &pubkey).is_none()); - accounts.store(fork, &[(&pubkey, &account)]); + accounts.store(slot, &[(&pubkey, &account)]); } } - fn update_accounts(accounts: &AccountsDB, pubkeys: &Vec, fork: Fork, range: usize) { + fn update_accounts(accounts: &AccountsDB, pubkeys: &Vec, slot: Slot, range: usize) { for _ in 1..1000 { let idx = thread_rng().gen_range(0, range); - let ancestors = vec![(fork, 0)].into_iter().collect(); + let ancestors = vec![(slot, 0)].into_iter().collect(); if let Some((mut account, _)) = accounts.load_slow(&ancestors, &pubkeys[idx]) { account.lamports = account.lamports + 1; - accounts.store(fork, &[(&pubkeys[idx], &account)]); + accounts.store(slot, &[(&pubkeys[idx], &account)]); if account.lamports == 0 { - let ancestors = vec![(fork, 0)].into_iter().collect(); + let ancestors = vec![(slot, 0)].into_iter().collect(); assert!(accounts.load_slow(&ancestors, &pubkeys[idx]).is_none()); } else { let mut default_account = Account::default(); @@ -1329,12 +1330,12 @@ pub mod tests { } } - fn check_storage(accounts: &AccountsDB, fork: Fork, count: usize) -> bool { + fn check_storage(accounts: &AccountsDB, slot: Slot, count: usize) -> bool { let storage = accounts.storage.read().unwrap(); - assert_eq!(storage.0[&fork].len(), 1); - let fork_storage = storage.0.get(&fork).unwrap(); + assert_eq!(storage.0[&slot].len(), 1); + let slot_storage = storage.0.get(&slot).unwrap(); let mut total_count: usize = 0; - for store in fork_storage.values() { + for store in slot_storage.values() { assert_eq!(store.status(), AccountStorageStatus::Available); total_count += store.count(); } @@ -1345,17 +1346,17 @@ pub mod tests { fn check_accounts( accounts: &AccountsDB, pubkeys: &Vec, - fork: Fork, + slot: Slot, num: usize, count: usize, ) { - let ancestors = vec![(fork, 0)].into_iter().collect(); + let ancestors = vec![(slot, 0)].into_iter().collect(); for _ in 0..num { let idx = thread_rng().gen_range(0, num); let account = accounts.load_slow(&ancestors, &pubkeys[idx]); let account1 = Some(( Account::new((idx + count) as u64, 0, &Account::default().owner), - fork, + slot, )); assert_eq!(account, account1); } @@ -1364,13 +1365,13 @@ pub mod tests { fn modify_accounts( accounts: &AccountsDB, pubkeys: &Vec, - fork: Fork, + slot: Slot, num: usize, count: usize, ) { for idx in 0..num { let account = Account::new((idx + count) as u64, 0, &Account::default().owner); - accounts.store(fork, &[(&pubkeys[idx], &account)]); + accounts.store(slot, &[(&pubkeys[idx], &account)]); } } @@ -1434,7 +1435,7 @@ pub mod tests { .values() .flat_map(|x| x.values()) { - *append_vec_histogram.entry(storage.fork_id).or_insert(0) += 1; + *append_vec_histogram.entry(storage.slot_id).or_insert(0) += 1; } for count in append_vec_histogram.values() { assert!(*count >= 2); @@ -1507,31 +1508,31 @@ pub mod tests { } #[test] - fn test_purge_fork_not_root() { + fn test_purge_slot_not_root() { let accounts = AccountsDB::new(None); let mut pubkeys: Vec = vec![]; create_account(&accounts, &mut pubkeys, 0, 1, 0, 0); let ancestors = vec![(0, 0)].into_iter().collect(); assert!(accounts.load_slow(&ancestors, &pubkeys[0]).is_some()); - accounts.purge_fork(0); + accounts.purge_slot(0); assert!(accounts.load_slow(&ancestors, &pubkeys[0]).is_none()); } #[test] - fn test_purge_fork_after_root() { + fn test_purge_slot_after_root() { let accounts = AccountsDB::new(None); let mut pubkeys: Vec = vec![]; create_account(&accounts, &mut pubkeys, 0, 1, 0, 0); let ancestors = vec![(0, 0)].into_iter().collect(); accounts.add_root(0); - accounts.purge_fork(0); + accounts.purge_slot(0); assert!(accounts.load_slow(&ancestors, &pubkeys[0]).is_some()); } #[test] - fn test_lazy_gc_fork() { + fn test_lazy_gc_slot() { //This test is pedantic - //A fork is purged when a non root bank is cleaned up. If a fork is behind root but it is + //A slot is purged when a non root bank is cleaned up. If a slot is behind root but it is //not root, it means we are retaining dead banks. let accounts = AccountsDB::new(None); let pubkey = Pubkey::new_rand(); @@ -1544,17 +1545,17 @@ pub mod tests { let (list, idx) = index.get(&pubkey, &ancestors).unwrap(); list[idx].1.id }; - //fork 0 is behind root, but it is not root, therefore it is purged + //slot 0 is behind root, but it is not root, therefore it is purged accounts.add_root(1); assert!(accounts.accounts_index.read().unwrap().is_purged(0)); - //fork is still there, since gc is lazy + //slot is still there, since gc is lazy assert!(accounts.storage.read().unwrap().0[&0].get(&id).is_some()); //store causes cleanup accounts.store(1, &[(&pubkey, &account)]); - //fork is gone + //slot is gone assert!(accounts.storage.read().unwrap().0.get(&0).is_none()); //new value is there @@ -1575,13 +1576,13 @@ pub mod tests { accounts.add_root(0); let mut pubkeys1: Vec = vec![]; - let latest_fork = 1; - create_account(&accounts, &mut pubkeys1, latest_fork, 10, 0, 0); + let latest_slot = 1; + create_account(&accounts, &mut pubkeys1, latest_slot, 10, 0, 0); let mut writer = Cursor::new(vec![]); serialize_into( &mut writer, - &AccountsDBSerialize::new(&accounts, latest_fork), + &AccountsDBSerialize::new(&accounts, latest_slot), ) .unwrap(); assert!(check_storage(&accounts, 0, 100)); @@ -1611,12 +1612,12 @@ pub mod tests { accounts.next_id.load(Ordering::Relaxed) ); - // Get the hash for the latest fork, which should be the only hash in the - // fork_hashes map on the deserializied AccountsDb - assert_eq!(daccounts.fork_hashes.read().unwrap().len(), 1); + // Get the hash for the latest slot, which should be the only hash in the + // slot_hashes map on the deserializied AccountsDb + assert_eq!(daccounts.slot_hashes.read().unwrap().len(), 1); assert_eq!( - daccounts.fork_hashes.read().unwrap().get(&latest_fork), - accounts.fork_hashes.read().unwrap().get(&latest_fork) + daccounts.slot_hashes.read().unwrap().get(&latest_slot), + accounts.slot_hashes.read().unwrap().get(&latest_slot) ); check_accounts(&daccounts, &pubkeys, 0, 100, 2); check_accounts(&daccounts, &pubkeys1, 1, 10, 1); @@ -1627,7 +1628,7 @@ pub mod tests { #[test] #[ignore] fn test_store_account_stress() { - let fork_id = 42; + let slot_id = 42; let num_threads = 2; let min_file_bytes = std::mem::size_of::() @@ -1635,7 +1636,7 @@ pub mod tests { let db = Arc::new(AccountsDB::new_sized(None, min_file_bytes as u64)); - db.add_root(fork_id); + db.add_root(slot_id); let thread_hdls: Vec<_> = (0..num_threads) .into_iter() .map(|_| { @@ -1649,11 +1650,11 @@ pub mod tests { loop { let account_bal = thread_rng().gen_range(1, 99); account.lamports = account_bal; - db.store(fork_id, &[(&pubkey, &account)]); - let (account, fork) = db.load_slow(&HashMap::new(), &pubkey).expect( + db.store(slot_id, &[(&pubkey, &account)]); + let (account, slot) = db.load_slow(&HashMap::new(), &pubkey).expect( &format!("Could not fetch stored account {}, iter {}", pubkey, i), ); - assert_eq!(fork, fork_id); + assert_eq!(slot, slot_id); assert_eq!(account.lamports, account_bal); i += 1; } diff --git a/runtime/src/accounts_index.rs b/runtime/src/accounts_index.rs index 9d6a31cabe..0939f3581b 100644 --- a/runtime/src/accounts_index.rs +++ b/runtime/src/accounts_index.rs @@ -2,53 +2,53 @@ use solana_sdk::pubkey::Pubkey; use std::collections::{HashMap, HashSet}; use std::sync::{RwLock, RwLockReadGuard}; -pub type Fork = u64; -type ForkList = Vec<(Fork, T)>; +pub type Slot = u64; +type SlotList = Vec<(Slot, T)>; #[derive(Debug, Default)] pub struct AccountsIndex { - pub account_maps: HashMap>>, + pub account_maps: HashMap>>, - pub roots: HashSet, + pub roots: HashSet, //This value that needs to be stored to recover the index from AppendVec - pub last_root: Fork, + pub last_root: Slot, } impl AccountsIndex { /// call func with every pubkey and index visible from a given set of ancestors - pub fn scan_accounts(&self, ancestors: &HashMap, mut func: F) + pub fn scan_accounts(&self, ancestors: &HashMap, mut func: F) where - F: FnMut(&Pubkey, (&T, Fork)) -> (), + F: FnMut(&Pubkey, (&T, Slot)) -> (), { for (pubkey, list) in self.account_maps.iter() { let list_r = list.read().unwrap(); - if let Some(index) = self.latest_fork(ancestors, &list_r) { + if let Some(index) = self.latest_slot(ancestors, &list_r) { func(pubkey, (&list_r[index].1, list_r[index].0)); } } } - pub fn purge(&mut self, pubkey: &Pubkey) -> Vec<(Fork, T)> { + pub fn purge(&mut self, pubkey: &Pubkey) -> Vec<(Slot, T)> { let mut list = self.account_maps.get(&pubkey).unwrap().write().unwrap(); let reclaims = list .iter() - .filter(|(fork, _)| self.is_root(*fork)) + .filter(|(slot, _)| self.is_root(*slot)) .cloned() .collect(); - list.retain(|(fork, _)| !self.is_root(*fork)); + list.retain(|(slot, _)| !self.is_root(*slot)); reclaims } - // find the latest fork and T in a list for a given ancestor + // find the latest slot and T in a list for a given ancestor // returns index into 'list' if found, None if not. - fn latest_fork(&self, ancestors: &HashMap, list: &[(Fork, T)]) -> Option { + fn latest_slot(&self, ancestors: &HashMap, list: &[(Slot, T)]) -> Option { let mut max = 0; let mut rv = None; - for (i, (fork, _t)) in list.iter().rev().enumerate() { - if *fork >= max && (ancestors.get(fork).is_some() || self.is_root(*fork)) { + for (i, (slot, _t)) in list.iter().rev().enumerate() { + if *slot >= max && (ancestors.get(slot).is_some() || self.is_root(*slot)) { rv = Some((list.len() - 1) - i); - max = *fork; + max = *slot; } } rv @@ -59,11 +59,11 @@ impl AccountsIndex { pub fn get( &self, pubkey: &Pubkey, - ancestors: &HashMap, - ) -> Option<(RwLockReadGuard>, usize)> { + ancestors: &HashMap, + ) -> Option<(RwLockReadGuard>, usize)> { self.account_maps.get(pubkey).and_then(|list| { let lock = list.read().unwrap(); - if let Some(found_index) = self.latest_fork(ancestors, &lock) { + if let Some(found_index) = self.latest_slot(ancestors, &lock) { Some((lock, found_index)) } else { None @@ -71,9 +71,9 @@ impl AccountsIndex { }) } - pub fn get_max_root(roots: &HashSet, fork_vec: &[(Fork, T)]) -> Fork { + pub fn get_max_root(roots: &HashSet, slot_vec: &[(Slot, T)]) -> Slot { let mut max_root = 0; - for (f, _) in fork_vec.iter() { + for (f, _) in slot_vec.iter() { if *f > max_root && roots.contains(f) { max_root = *f; } @@ -83,16 +83,16 @@ impl AccountsIndex { pub fn insert( &mut self, - fork: Fork, + slot: Slot, pubkey: &Pubkey, account_info: T, - reclaims: &mut Vec<(Fork, T)>, + reclaims: &mut Vec<(Slot, T)>, ) { - let _fork_vec = self + let _slot_vec = self .account_maps .entry(*pubkey) .or_insert_with(|| RwLock::new(Vec::with_capacity(32))); - self.update(fork, pubkey, account_info, reclaims); + self.update(slot, pubkey, account_info, reclaims); } // Try to update an item in account_maps. If the account is not @@ -101,30 +101,30 @@ impl AccountsIndex { // It returns None if the item is already present and thus successfully updated. pub fn update( &self, - fork: Fork, + slot: Slot, pubkey: &Pubkey, account_info: T, - reclaims: &mut Vec<(Fork, T)>, + reclaims: &mut Vec<(Slot, T)>, ) -> Option { let roots = &self.roots; if let Some(lock) = self.account_maps.get(pubkey) { - let mut fork_vec = lock.write().unwrap(); + let mut slot_vec = lock.write().unwrap(); // filter out old entries - reclaims.extend(fork_vec.iter().filter(|(f, _)| *f == fork).cloned()); - fork_vec.retain(|(f, _)| *f != fork); + reclaims.extend(slot_vec.iter().filter(|(f, _)| *f == slot).cloned()); + slot_vec.retain(|(f, _)| *f != slot); // add the new entry - fork_vec.push((fork, account_info)); + slot_vec.push((slot, account_info)); - let max_root = Self::get_max_root(roots, &fork_vec); + let max_root = Self::get_max_root(roots, &slot_vec); reclaims.extend( - fork_vec + slot_vec .iter() - .filter(|(fork, _)| Self::can_purge(max_root, *fork)) + .filter(|(slot, _)| Self::can_purge(max_root, *slot)) .cloned(), ); - fork_vec.retain(|(fork, _)| !Self::can_purge(max_root, *fork)); + slot_vec.retain(|(slot, _)| !Self::can_purge(max_root, *slot)); None } else { @@ -132,38 +132,38 @@ impl AccountsIndex { } } - pub fn add_index(&mut self, fork: Fork, pubkey: &Pubkey, account_info: T) { + pub fn add_index(&mut self, slot: Slot, pubkey: &Pubkey, account_info: T) { let entry = self .account_maps .entry(*pubkey) .or_insert_with(|| RwLock::new(vec![])); - entry.write().unwrap().push((fork, account_info)); + entry.write().unwrap().push((slot, account_info)); } - pub fn is_purged(&self, fork: Fork) -> bool { - fork < self.last_root + pub fn is_purged(&self, slot: Slot) -> bool { + slot < self.last_root } - pub fn can_purge(max_root: Fork, fork: Fork) -> bool { - fork < max_root + pub fn can_purge(max_root: Slot, slot: Slot) -> bool { + slot < max_root } - pub fn is_root(&self, fork: Fork) -> bool { - self.roots.contains(&fork) + pub fn is_root(&self, slot: Slot) -> bool { + self.roots.contains(&slot) } - pub fn add_root(&mut self, fork: Fork) { + pub fn add_root(&mut self, slot: Slot) { assert!( - (self.last_root == 0 && fork == 0) || (fork >= self.last_root), + (self.last_root == 0 && slot == 0) || (slot >= self.last_root), "new roots must be increasing" ); - self.last_root = fork; - self.roots.insert(fork); + self.last_root = slot; + self.roots.insert(slot); } - /// Remove the fork when the storage for the fork is freed - /// Accounts no longer reference this fork. - pub fn cleanup_dead_fork(&mut self, fork: Fork) { - self.roots.remove(&fork); + /// Remove the slot when the storage for the slot is freed + /// Accounts no longer reference this slot. + pub fn cleanup_dead_slot(&mut self, slot: Slot) { + self.roots.remove(&slot); } } @@ -290,18 +290,18 @@ mod tests { let mut index = AccountsIndex::::default(); index.add_root(0); index.add_root(1); - index.cleanup_dead_fork(0); + index.cleanup_dead_slot(0); assert!(index.is_root(1)); assert!(!index.is_root(0)); } #[test] fn test_cleanup_last() { - //this behavior might be undefined, clean up should only occur on older forks + //this behavior might be undefined, clean up should only occur on older slots let mut index = AccountsIndex::::default(); index.add_root(0); index.add_root(1); - index.cleanup_dead_fork(1); + index.cleanup_dead_slot(1); assert!(!index.is_root(1)); assert!(index.is_root(0)); } @@ -326,7 +326,7 @@ mod tests { } #[test] - fn test_update_new_fork() { + fn test_update_new_slot() { solana_logger::setup(); let key = Keypair::new(); let mut index = AccountsIndex::::default(); @@ -344,7 +344,7 @@ mod tests { } #[test] - fn test_update_gc_purged_fork() { + fn test_update_gc_purged_slot() { let key = Keypair::new(); let mut index = AccountsIndex::::default(); let mut gc = Vec::new(); diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 1e50891362..6ffce2de1f 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -5,7 +5,6 @@ use crate::{ accounts::{Accounts, TransactionLoadResult}, accounts_db::{AccountStorageEntry, AccountsDBSerialize, AppendVecId, ErrorCounters}, - accounts_index::Fork, blockhash_queue::BlockhashQueue, message_processor::{MessageProcessor, ProcessInstruction}, rent_collector::RentCollector, @@ -1318,7 +1317,7 @@ impl Bank { self.rc .accounts .load_slow(&self.ancestors, pubkey) - .map(|(account, _)| account) + .map(|(acc, _slot)| acc) } pub fn get_program_accounts(&self, program_id: &Pubkey) -> Vec<(Pubkey, Account)> { @@ -1333,10 +1332,10 @@ impl Bank { ) -> Vec<(Pubkey, Account)> { self.rc .accounts - .load_by_program_fork(self.slot(), program_id) + .load_by_program_slot(self.slot(), program_id) } - pub fn get_account_modified_since_parent(&self, pubkey: &Pubkey) -> Option<(Account, Fork)> { + pub fn get_account_modified_since_parent(&self, pubkey: &Pubkey) -> Option<(Account, Slot)> { let just_self: HashMap = vec![(self.slot(), 0)].into_iter().collect(); self.rc.accounts.load_slow(&just_self, pubkey) } @@ -1617,8 +1616,8 @@ impl Bank { impl Drop for Bank { fn drop(&mut self) { - // For root forks this is a noop - self.rc.accounts.purge_fork(self.slot()); + // For root slots this is a noop + self.rc.accounts.purge_slot(self.slot()); } } @@ -1796,7 +1795,7 @@ mod tests { for _ in 0..10 { let blockhash = bank.last_blockhash(); let pubkey = Pubkey::new_rand(); - let tx = system_transaction::transfer_now(&mint_keypair, &pubkey, 0, blockhash); + let tx = system_transaction::transfer(&mint_keypair, &pubkey, 0, blockhash); bank.process_transaction(&tx).unwrap(); bank.squash(); bank = Arc::new(new_from_parent(&bank)); @@ -1809,13 +1808,13 @@ mod tests { let bank0 = Arc::new(new_from_parent(&bank)); let blockhash = bank.last_blockhash(); let keypair = Keypair::new(); - let tx = system_transaction::transfer_now(&mint_keypair, &keypair.pubkey(), 10, blockhash); + let tx = system_transaction::transfer(&mint_keypair, &keypair.pubkey(), 10, blockhash); bank0.process_transaction(&tx).unwrap(); let bank1 = Arc::new(new_from_parent(&bank0)); let pubkey = Pubkey::new_rand(); let blockhash = bank.last_blockhash(); - let tx = system_transaction::transfer_now(&keypair, &pubkey, 10, blockhash); + let tx = system_transaction::transfer(&keypair, &pubkey, 10, blockhash); bank1.process_transaction(&tx).unwrap(); assert_eq!(bank0.get_account(&keypair.pubkey()).unwrap().lamports, 10); @@ -1941,12 +1940,8 @@ mod tests { let dest = Keypair::new(); // source with 0 program context - let tx = system_transaction::transfer_now( - &mint_keypair, - &dest.pubkey(), - 2, - genesis_block.hash(), - ); + let tx = + system_transaction::transfer(&mint_keypair, &dest.pubkey(), 2, genesis_block.hash()); let signature = tx.signatures[0]; assert!(!bank.has_signature(&signature)); @@ -2230,18 +2225,10 @@ mod tests { let (genesis_block, mint_keypair) = create_genesis_block(2); let bank = Bank::new(&genesis_block); let keypair = Keypair::new(); - let tx0 = system_transaction::transfer_now( - &mint_keypair, - &keypair.pubkey(), - 2, - genesis_block.hash(), - ); - let tx1 = system_transaction::transfer_now( - &keypair, - &mint_keypair.pubkey(), - 1, - genesis_block.hash(), - ); + let tx0 = + system_transaction::transfer(&mint_keypair, &keypair.pubkey(), 2, genesis_block.hash()); + let tx1 = + system_transaction::transfer(&keypair, &mint_keypair.pubkey(), 1, genesis_block.hash()); let txs = vec![tx0, tx1]; let results = bank.process_transactions(&txs); assert!(results[1].is_err()); @@ -2272,9 +2259,6 @@ mod tests { system_transaction::transfer(&payer1, &recipient.pubkey(), 1, genesis_block.hash()); let txs = vec![tx0, tx1, tx2]; let results = bank.process_transactions(&txs); - bank.rc - .accounts - .commit_credits_unsafe(&bank.ancestors, bank.slot()); // If multiple transactions attempt to deposit into the same account, they should succeed, // since System Transfer `To` accounts are given credit-only handling @@ -2293,9 +2277,6 @@ mod tests { system_transaction::transfer(&recipient, &payer0.pubkey(), 1, genesis_block.hash()); let txs = vec![tx0, tx1]; let results = bank.process_transactions(&txs); - bank.rc - .accounts - .commit_credits_unsafe(&bank.ancestors, bank.slot()); // However, an account may not be locked as credit-only and credit-debit at the same time. assert_eq!(results[0], Ok(())); assert_eq!(results[1], Err(TransactionError::AccountInUse)); @@ -2308,12 +2289,8 @@ mod tests { let alice = Keypair::new(); let bob = Keypair::new(); - let tx1 = system_transaction::transfer_now( - &mint_keypair, - &alice.pubkey(), - 1, - genesis_block.hash(), - ); + let tx1 = + system_transaction::transfer(&mint_keypair, &alice.pubkey(), 1, genesis_block.hash()); let pay_alice = vec![tx1]; let lock_result = bank.prepare_batch(&pay_alice, None); @@ -3112,12 +3089,8 @@ mod tests { let keypair1 = Keypair::new(); let keypair2 = Keypair::new(); - let fail_tx = system_transaction::transfer_now( - &keypair1, - &keypair2.pubkey(), - 1, - bank.last_blockhash(), - ); + let fail_tx = + system_transaction::transfer(&keypair1, &keypair2.pubkey(), 1, bank.last_blockhash()); // Should fail with TransactionError::AccountNotFound, which means // the account which this tx operated on will not be committed. Thus diff --git a/sdk-c/src/lib.rs b/sdk-c/src/lib.rs index 2a70ac0706..a0a29b6531 100644 --- a/sdk-c/src/lib.rs +++ b/sdk-c/src/lib.rs @@ -501,7 +501,7 @@ mod tests { let key = KeypairNative::new(); let to = Pubkey::new_rand(); let blockhash = Hash::default(); - let tx = system_transaction::transfer_now(&key, &to, 50, blockhash); + let tx = system_transaction::transfer(&key, &to, 50, blockhash); let serialized = serialize(&tx).unwrap(); let tx = Box::new(Transaction::from_native(tx)); let tx = Box::into_raw(tx); @@ -520,7 +520,7 @@ mod tests { let key = KeypairNative::new(); let to = Pubkey::new_rand(); let blockhash = Hash::default(); - let tx = system_transaction::transfer_now(&key, &to, 50, blockhash); + let tx = system_transaction::transfer(&key, &to, 50, blockhash); let serialized = serialize(&tx).unwrap(); let deserialized; unsafe { @@ -559,7 +559,7 @@ mod tests { let key_native = KeypairNative::new(); let to = Pubkey::new_rand(); let blockhash = Hash::default(); - let mut tx_native = system_transaction::transfer_now(&key_native, &to, 50, blockhash); + let mut tx_native = system_transaction::transfer(&key_native, &to, 50, blockhash); let tx = Box::into_raw(Box::new(Transaction::from_native(tx_native.clone()))); let key = Keypair::from_native(&key_native); let tx2; diff --git a/sdk/src/epoch_schedule.rs b/sdk/src/epoch_schedule.rs index d989f69741..cafafb3dd5 100644 --- a/sdk/src/epoch_schedule.rs +++ b/sdk/src/epoch_schedule.rs @@ -24,10 +24,10 @@ pub struct EpochSchedule { /// whether epochs start short and grow pub warmup: bool, - /// basically: log2(slots_per_epoch) - log2(MINIMUM_SLOT_LEN) + /// basically: log2(slots_per_epoch) - log2(MINIMUM_SLOTS_PER_EPOCH) pub first_normal_epoch: Epoch, - /// basically: 2.pow(first_normal_epoch) - MINIMUM_SLOT_LEN + /// basically: MINIMUM_SLOTS_PER_EPOCH * (2.pow(first_normal_epoch) - 1) pub first_normal_slot: Slot, } diff --git a/sdk/src/system_instruction.rs b/sdk/src/system_instruction.rs index 6ff2943e15..a2d9f5b851 100644 --- a/sdk/src/system_instruction.rs +++ b/sdk/src/system_instruction.rs @@ -69,19 +69,6 @@ pub fn create_account( ) } -/// transfer with to as credit-debit -pub fn transfer_now(from_pubkey: &Pubkey, to_pubkey: &Pubkey, lamports: u64) -> Instruction { - let account_metas = vec![ - AccountMeta::new(*from_pubkey, true), - AccountMeta::new(*to_pubkey, false), - ]; - Instruction::new( - system_program::id(), - &SystemInstruction::Transfer { lamports }, - account_metas, - ) -} - pub fn assign(from_pubkey: &Pubkey, program_id: &Pubkey) -> Instruction { let account_metas = vec![AccountMeta::new(*from_pubkey, true)]; Instruction::new( diff --git a/sdk/src/system_transaction.rs b/sdk/src/system_transaction.rs index 2a52c3d8c8..7544b8de08 100644 --- a/sdk/src/system_transaction.rs +++ b/sdk/src/system_transaction.rs @@ -24,19 +24,6 @@ pub fn create_account( Transaction::new_signed_instructions(&[from_keypair], instructions, recent_blockhash) } -/// Create and sign new system_instruction::Transfer transaction, but don't use a CO "to" -pub fn transfer_now( - from_keypair: &Keypair, - to: &Pubkey, - lamports: u64, - recent_blockhash: Hash, -) -> Transaction { - let from_pubkey = from_keypair.pubkey(); - let transfer_instruction = system_instruction::transfer_now(&from_pubkey, to, lamports); - let instructions = vec![transfer_instruction]; - Transaction::new_signed_instructions(&[from_keypair], instructions, recent_blockhash) -} - /// Create and sign new system_instruction::Assign transaction pub fn assign(from_keypair: &Keypair, recent_blockhash: Hash, program_id: &Pubkey) -> Transaction { let from_pubkey = from_keypair.pubkey();