Skip to content

Commit

Permalink
Merge pull request #101 from Neptune-Crypto/alphanet-v6
Browse files Browse the repository at this point in the history
Revisit Block Structure
  • Loading branch information
aszepieniec authored Feb 2, 2024
2 parents b6b3b31 + 78b9793 commit 2fa96ae
Show file tree
Hide file tree
Showing 49 changed files with 2,518 additions and 1,463 deletions.
156 changes: 83 additions & 73 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions benchmarks/tasm_neptune_transaction_compute_indices.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
[
{
"name": "tasm_neptune_transaction_compute_indices",
"clock_cycle_count": 5367,
"clock_cycle_count": 5375,
"hash_table_height": 607,
"u32_table_height": 4378,
"case": "CommonCase"
},
{
"name": "tasm_neptune_transaction_compute_indices",
"clock_cycle_count": 5367,
"clock_cycle_count": 5375,
"hash_table_height": 607,
"u32_table_height": 4514,
"case": "WorstCase"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
[
{
"name": "tasm_neptune_transaction_removal_records_integrity",
"clock_cycle_count": 29578,
"hash_table_height": 5615,
"u32_table_height": 13250,
"clock_cycle_count": 29649,
"hash_table_height": 5633,
"u32_table_height": 13245,
"case": "CommonCase"
}
]
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
[
{
"name": "tasm_neptune_transaction_transaction_kernel_mast_hash",
"clock_cycle_count": 7822,
"hash_table_height": 3631,
"u32_table_height": 74,
"clock_cycle_count": 7758,
"hash_table_height": 3607,
"u32_table_height": 73,
"case": "CommonCase"
},
{
"name": "tasm_neptune_transaction_transaction_kernel_mast_hash",
"clock_cycle_count": 8484,
"hash_table_height": 3967,
"clock_cycle_count": 8490,
"hash_table_height": 3973,
"u32_table_height": 74,
"case": "WorstCase"
}
Expand Down
325 changes: 171 additions & 154 deletions profiles/tasm_neptune_transaction_removal_records_integrity.profile

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion src/bin/dashboard_src/overview_screen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,9 @@ impl OverviewData {
is_mining: Some(false),
syncing: false,
block_header: Some(
neptune_core::models::blockchain::block::Block::genesis_block().header,
neptune_core::models::blockchain::block::Block::genesis_block()
.kernel
.header,
),
block_interval: Some(558u64),

Expand Down
36 changes: 23 additions & 13 deletions src/main_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,26 +307,28 @@ impl MainLoopHandler {
// and we assume it is the longest chain even though we could have received
// a block from a peer thread before this event is triggered.
let new_block = new_block_info.block;
info!("Miner found new block: {}", new_block.header.height);
info!("Miner found new block: {}", new_block.kernel.header.height);

// Store block in database
// This block spans global state write lock for updating.
let mut global_state_mut = self.global_state_lock.lock_guard_mut().await;

let (tip_hash, tip_proof_of_work_family) = (
global_state_mut.chain.light_state().hash,
global_state_mut.chain.light_state().hash(),
global_state_mut
.chain
.light_state()
.kernel
.header
.proof_of_work_family,
);

// If we received a new block from a peer and updated the global state before this message from the miner was handled,
// we abort and do not store the newly found block. The newly found block has to be the direct descendant of what this
// node considered the most canonical block.
let block_is_new = tip_proof_of_work_family < new_block.header.proof_of_work_family
&& new_block.header.prev_block_digest == tip_hash;
let block_is_new = tip_proof_of_work_family
< new_block.kernel.header.proof_of_work_family
&& new_block.kernel.header.prev_block_digest == tip_hash;
if !block_is_new {
warn!("Got new block from miner thread that was not child of tip. Discarding.");
return Ok(());
Expand Down Expand Up @@ -380,11 +382,12 @@ impl MainLoopHandler {
let tip_proof_of_work_family = global_state_mut
.chain
.light_state()
.kernel
.header
.proof_of_work_family;

let block_is_new =
tip_proof_of_work_family < last_block.header.proof_of_work_family;
tip_proof_of_work_family < last_block.kernel.header.proof_of_work_family;
if !block_is_new {
warn!("Blocks were not new. Not storing blocks.");

Expand All @@ -397,7 +400,7 @@ impl MainLoopHandler {
// Get out of sync mode if needed
if global_state_mut.net.syncing {
let stay_in_sync_mode = stay_in_sync_mode(
&last_block.header,
&last_block.kernel.header,
&main_loop_state.sync_state,
global_state_mut.cli.max_number_of_blocks_before_syncing,
);
Expand All @@ -410,10 +413,12 @@ impl MainLoopHandler {
for new_block in blocks {
debug!(
"Storing block {} in database. Height: {}, Mined: {}",
new_block.hash.emojihash(),
new_block.header.height,
crate::utc_timestamp_to_localtime(new_block.header.timestamp.value())
.to_string()
new_block.hash().emojihash(),
new_block.kernel.header.height,
crate::utc_timestamp_to_localtime(
new_block.kernel.header.timestamp.value()
)
.to_string()
);

global_state_mut.store_block(new_block).await?;
Expand Down Expand Up @@ -716,9 +721,14 @@ impl MainLoopHandler {

// Check when latest batch of blocks was requested
let (current_block_hash, current_block_height, current_block_proof_of_work_family) = (
global_state.chain.light_state().hash,
global_state.chain.light_state().header.height,
global_state.chain.light_state().header.proof_of_work_family,
global_state.chain.light_state().hash(),
global_state.chain.light_state().kernel.header.height,
global_state
.chain
.light_state()
.kernel
.header
.proof_of_work_family,
);

let (peer_to_sanction, try_new_request): (Option<SocketAddr>, bool) = main_loop_state
Expand Down
64 changes: 33 additions & 31 deletions src/mine_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::models::blockchain::transaction::utxo::*;
use crate::models::blockchain::transaction::validity::TransactionValidationLogic;
use crate::models::blockchain::transaction::*;
use crate::models::channel::*;
use crate::models::consensus::mast_hash::MastHash;
use crate::models::shared::SIZE_20MB_IN_BYTES;
use crate::models::state::wallet::utxo_notification_pool::{ExpectedUtxo, UtxoNotifier};
use crate::models::state::wallet::WalletSecret;
Expand All @@ -27,6 +28,8 @@ use rand::SeedableRng;
use std::ops::Deref;
use std::time::Duration;
use std::time::{SystemTime, UNIX_EPOCH};
use tasm_lib::twenty_first::util_types::mmr::mmr_accumulator::MmrAccumulator;
use tasm_lib::twenty_first::util_types::mmr::mmr_trait::Mmr;
use tokio::select;
use tokio::sync::{mpsc, watch};
use tokio::task::JoinHandle;
Expand All @@ -48,7 +51,7 @@ fn make_block_template(
let additions = transaction.kernel.outputs.clone();
let removals = transaction.kernel.inputs.clone();
let mut next_mutator_set_accumulator: MutatorSetAccumulator<Hash> =
previous_block.body.next_mutator_set_accumulator.clone();
previous_block.kernel.body.mutator_set_accumulator.clone();

// Apply the mutator set update to the mutator set accumulator
// This function mutates the MS accumulator that is given as argument to
Expand All @@ -58,41 +61,40 @@ fn make_block_template(
.apply(&mut next_mutator_set_accumulator)
.expect("Mutator set mutation must work");

let mut block_mmra = previous_block.kernel.body.block_mmr_accumulator.clone();
block_mmra.append(previous_block.hash());
let block_body: BlockBody = BlockBody {
transaction,
next_mutator_set_accumulator: next_mutator_set_accumulator.clone(),
previous_mutator_set_accumulator: previous_block.body.next_mutator_set_accumulator.clone(),
stark_proof: vec![],
mutator_set_accumulator: next_mutator_set_accumulator.clone(),
lock_free_mmr_accumulator: MmrAccumulator::<Hash>::new(vec![]),
block_mmr_accumulator: block_mmra,
uncle_blocks: vec![],
};

let zero = BFieldElement::zero();
let new_pow_line: U32s<5> =
previous_block.header.proof_of_work_family + previous_block.header.difficulty;
let mutator_set_commitment: Digest = next_mutator_set_accumulator.hash();
let next_block_height = previous_block.header.height.next();
previous_block.kernel.header.proof_of_work_family + previous_block.kernel.header.difficulty;
let next_block_height = previous_block.kernel.header.height.next();
let mut block_timestamp = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("Got bad time timestamp in mining process")
.as_millis() as u64;
if block_timestamp < previous_block.header.timestamp.value() {
if block_timestamp < previous_block.kernel.header.timestamp.value() {
warn!("Received block is timestamped in the future; mining on future-timestamped block.");
block_timestamp = previous_block.header.timestamp.value() + 1;
block_timestamp = previous_block.kernel.header.timestamp.value() + 1;
}
let difficulty: U32s<5> = Block::difficulty_control(previous_block, block_timestamp);

let block_header = BlockHeader {
version: zero,
height: next_block_height,
mutator_set_hash: mutator_set_commitment,
prev_block_digest: Hash::hash(&previous_block.header),
prev_block_digest: previous_block.kernel.mast_hash(),
timestamp: BFieldElement::new(block_timestamp),
nonce: [zero, zero, zero],
max_block_size: MOCK_MAX_BLOCK_SIZE,
proof_of_work_line: new_pow_line,
proof_of_work_family: new_pow_line,
difficulty,
block_body_merkle_root: Hash::hash(&block_body),
uncles: vec![],
};

(block_header, block_body)
Expand Down Expand Up @@ -153,13 +155,13 @@ async fn mine_block(
);

let new_block_info = NewBlockFound {
block: Box::new(Block::new(block_header, block_body)),
block: Box::new(Block::new(block_header, block_body, None)),
coinbase_utxo_info: Box::new(coinbase_utxo_info),
};

info!(
"PoW digest of new block: {}. Threshold was: {threshold}",
new_block_info.block.hash
new_block_info.block.hash()
);

sender
Expand Down Expand Up @@ -206,29 +208,29 @@ fn make_coinbase_transaction(
let kernel = TransactionKernel {
inputs: vec![],
outputs: vec![coinbase_addition_record],
pubscript_hashes_and_inputs: vec![],
public_announcements: vec![],
fee: Amount::zero(),
timestamp,
coinbase: Some(coinbase_amount),
mutator_set_hash: mutator_set_accumulator.hash(),
};

let primitive_witness = PrimitiveWitness {
let primitive_witness = TransactionPrimitiveWitness {
input_utxos: vec![],
type_scripts: vec![TypeScript::native_coin()],
input_lock_scripts: vec![],
lock_script_witnesses: vec![],
input_membership_proofs: vec![],
output_utxos: vec![coinbase_utxo.clone()],
pubscripts: vec![],
public_announcements: vec![],
mutator_set_accumulator,
};
let validity_logic =
TransactionValidationLogic::new_from_primitive_witness(&primitive_witness, &kernel);
(
Transaction {
kernel,
witness: Witness::ValidityLogic((validity_logic, primitive_witness)),
witness: TransactionWitness::ValidationLogic(validity_logic),
},
sender_randomness,
)
Expand Down Expand Up @@ -258,7 +260,7 @@ fn create_block_transaction(
.wallet_secret
.nth_generation_spending_key(0);
let receiving_address = coinbase_recipient_spending_key.to_address();
let next_block_height: BlockHeight = latest_block.header.height.next();
let next_block_height: BlockHeight = latest_block.kernel.header.height.next();

let lock_script = receiving_address.lock_script();
let coinbase_amount = Block::get_mining_reward(next_block_height) + transaction_fees;
Expand All @@ -269,14 +271,15 @@ fn create_block_transaction(
receiving_address.privacy_digest,
&global_state.wallet_state.wallet_secret,
next_block_height,
latest_block.body.next_mutator_set_accumulator.clone(),
latest_block.kernel.body.mutator_set_accumulator.clone(),
);

debug!(
"Creating block transaction with mutator set hash: {}",
latest_block
.kernel
.body
.next_mutator_set_accumulator
.mutator_set_accumulator
.hash()
.emojihash()
);
Expand Down Expand Up @@ -337,7 +340,7 @@ pub async fn mine(
worker_thread_tx,
global_state_lock.clone(),
coinbase_utxo_info,
latest_block.header.difficulty,
latest_block.kernel.header.difficulty,
);
global_state_lock.set_mining(true).await;
Some(
Expand Down Expand Up @@ -371,7 +374,7 @@ pub async fn mine(
mt.abort();
}
latest_block = *block;
info!("Miner thread received {} block height {}", global_state_lock.lock(|s| s.cli.network).await, latest_block.header.height);
info!("Miner thread received {} block height {}", global_state_lock.lock(|s| s.cli.network).await, latest_block.kernel.header.height);
}
MainToMiner::Empty => (),
MainToMiner::ReadyToMineNextBlock => {
Expand Down Expand Up @@ -402,7 +405,7 @@ pub async fn mine(
}
};

debug!("Worker thread reports new block of height {}", new_block_info.block.header.height);
debug!("Worker thread reports new block of height {}", new_block_info.block.kernel.header.height);

// Sanity check, remove for more efficient mining.
// The below PoW check could fail due to race conditions. So we don't panic,
Expand All @@ -415,7 +418,7 @@ pub async fn mine(
// if it is not.
assert!(new_block_info.block.is_valid(&latest_block), "Own mined block must be valid. Failed validity check after successful PoW check.");

info!("Found new {} block with block height {}. Hash: {}", global_state_lock.lock(|s| s.cli.network).await, new_block_info.block.header.height, new_block_info.block.hash.emojihash());
info!("Found new {} block with block height {}. Hash: {}", global_state_lock.lock(|s| s.cli.network).await, new_block_info.block.kernel.header.height, new_block_info.block.hash().emojihash());

latest_block = *new_block_info.block.to_owned();
to_main.send(MinerToMain::NewBlockFound(new_block_info)).await?;
Expand Down Expand Up @@ -484,6 +487,7 @@ mod mine_loop_tests {
let block_template_empty_mempool = Block::new(
block_header_template_empty_mempool,
block_body_empty_mempool,
None,
);
assert!(
block_template_empty_mempool.is_valid(&genesis_block),
Expand All @@ -494,8 +498,7 @@ mod mine_loop_tests {
let four_neptune_coins = Amount::from(4).to_native_coins();
let receiver_privacy_digest = Digest::default();
let sender_randomness = Digest::default();
let pubscript: PubScript = PubScript::default();
let pubscript_input: Vec<BFieldElement> = vec![];
let public_announcement = PublicAnnouncement::default();
let tx_output = Utxo {
coins: four_neptune_coins,
lock_script_hash: LockScript::anyone_can_spend().hash(),
Expand All @@ -507,8 +510,7 @@ mod mine_loop_tests {
utxo: tx_output,
sender_randomness,
receiver_privacy_digest,
pubscript,
pubscript_input,
public_announcement,
}),
],
1.into(),
Expand All @@ -533,7 +535,7 @@ mod mine_loop_tests {
// Build and verify block template
let (block_header_template, block_body) =
make_block_template(&genesis_block, transaction_non_empty_mempool);
let block_template_non_empty_mempool = Block::new(block_header_template, block_body);
let block_template_non_empty_mempool = Block::new(block_header_template, block_body, None);
assert!(
block_template_non_empty_mempool.is_valid(&genesis_block),
"Block template created by miner with non-empty mempool must be valid"
Expand Down
Loading

0 comments on commit 2fa96ae

Please sign in to comment.