Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add double stake detection #4132

Merged
merged 7 commits into from
Jun 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions massa-execution-worker/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ massa_final_state = { path = "../massa-final-state" }
massa_versioning = { path = "../massa-versioning" }
massa_db_exports = { path = "../massa-db-exports" }
massa_db_worker = { path = "../massa-db-worker", optional = true }
massa_wallet = { path = "../massa-wallet" }

[dev-dependencies]
tokio = { version = "1.23", features = ["sync"] }
Expand Down Expand Up @@ -73,6 +74,7 @@ testing = [
"massa_pos_exports/testing",
"massa_final_state/testing",
"massa-sc-runtime/testing",
"massa_wallet/testing",
"tempfile",
"massa_pos_worker",
"massa_ledger_worker",
Expand Down
14 changes: 14 additions & 0 deletions massa-execution-worker/src/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ use massa_pos_exports::SelectorController;
use massa_sc_runtime::{Interface, Response, VMError};
use massa_storage::Storage;
use massa_versioning::versioning::MipStore;
use massa_wallet::Wallet;
use parking_lot::{Mutex, RwLock};
use std::collections::{BTreeMap, BTreeSet};
use std::sync::Arc;
Expand Down Expand Up @@ -85,6 +86,8 @@ pub(crate) struct ExecutionState {
vesting_manager: Arc<VestingManager>,
// MipStore (Versioning)
mip_store: MipStore,
// wallet used to verify double staking on local addresses
wallet: Arc<RwLock<Wallet>>,
// selector controller to get draws
selector: Box<dyn SelectorController>,
// channels used by the execution worker
Expand All @@ -108,6 +111,7 @@ impl ExecutionState {
mip_store: MipStore,
selector: Box<dyn SelectorController>,
channels: ExecutionChannels,
wallet: Arc<RwLock<Wallet>>,
massa_metrics: MassaMetrics,
) -> ExecutionState {
// Get the slot at the output of which the final state is attached.
Expand Down Expand Up @@ -181,6 +185,7 @@ impl ExecutionState {
mip_store,
selector,
channels,
wallet,
massa_metrics,
}
}
Expand Down Expand Up @@ -555,6 +560,15 @@ impl ExecutionState {
}
}

if self
.wallet
.read()
.get_wallet_address_list()
.contains(&addr_denounced)
{
panic!("You are being slashed at slot {} for double-staking using address {}. The node is stopping to prevent any further loss", block_slot, addr_denounced);
}

Ok(())
}

Expand Down
26 changes: 26 additions & 0 deletions massa-execution-worker/src/tests/scenarios_mandatories.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ mod tests {
use massa_storage::Storage;
use massa_time::MassaTime;
use massa_versioning::versioning::{MipStatsConfig, MipStore};
use massa_wallet::test_exports::create_test_wallet;
use num::rational::Ratio;
use parking_lot::RwLock;
use serial_test::serial;
Expand Down Expand Up @@ -79,6 +80,7 @@ mod tests {
sample_state.read().pos_state.selector.clone(),
mip_store,
channels,
Arc::new(RwLock::new(create_test_wallet(Some(PreHashMap::default())))),
MassaMetrics::new(false, 32),
);
manager.stop();
Expand Down Expand Up @@ -112,6 +114,7 @@ mod tests {
sample_state.read().pos_state.selector.clone(),
mip_store,
channels,
Arc::new(RwLock::new(create_test_wallet(Some(PreHashMap::default())))),
MassaMetrics::new(false, 32),
);
controller.update_blockclique_status(
Expand Down Expand Up @@ -157,6 +160,7 @@ mod tests {
sample_state.read().pos_state.selector.clone(),
mip_store,
channels,
Arc::new(RwLock::new(create_test_wallet(Some(PreHashMap::default())))),
MassaMetrics::new(false, 32),
);
// initialize the execution system with genesis blocks
Expand Down Expand Up @@ -261,6 +265,7 @@ mod tests {
sample_state.read().pos_state.selector.clone(),
mip_store,
channels,
Arc::new(RwLock::new(create_test_wallet(Some(PreHashMap::default())))),
MassaMetrics::new(false, 32),
);
// initialize the execution system with genesis blocks
Expand Down Expand Up @@ -422,6 +427,7 @@ mod tests {
sample_state.read().pos_state.selector.clone(),
mip_store,
channels,
Arc::new(RwLock::new(create_test_wallet(Some(PreHashMap::default())))),
MassaMetrics::new(false, 32),
);
// initialize the execution system with genesis blocks
Expand Down Expand Up @@ -576,6 +582,7 @@ mod tests {
sample_state.read().pos_state.selector.clone(),
mip_store,
channels,
Arc::new(RwLock::new(create_test_wallet(Some(PreHashMap::default())))),
MassaMetrics::new(false, 32),
);
// initialize the execution system with genesis blocks
Expand Down Expand Up @@ -688,6 +695,7 @@ mod tests {
sample_state.read().pos_state.selector.clone(),
mip_store,
channels,
Arc::new(RwLock::new(create_test_wallet(Some(PreHashMap::default())))),
MassaMetrics::new(false, 32),
);
// initialize the execution system with genesis blocks
Expand Down Expand Up @@ -790,6 +798,7 @@ mod tests {
sample_state.read().pos_state.selector.clone(),
mip_store,
channels,
Arc::new(RwLock::new(create_test_wallet(Some(PreHashMap::default())))),
MassaMetrics::new(false, 32),
);
// initialize the execution system with genesis blocks
Expand Down Expand Up @@ -914,6 +923,7 @@ mod tests {
sample_state.read().pos_state.selector.clone(),
mip_store,
channels,
Arc::new(RwLock::new(create_test_wallet(Some(PreHashMap::default())))),
MassaMetrics::new(false, 32),
);
// initialize the execution system with genesis blocks
Expand Down Expand Up @@ -1028,6 +1038,7 @@ mod tests {
sample_state.read().pos_state.selector.clone(),
mip_store,
channels,
Arc::new(RwLock::new(create_test_wallet(Some(PreHashMap::default())))),
MassaMetrics::new(false, 32),
);
// initialize the execution system with genesis blocks
Expand Down Expand Up @@ -1181,6 +1192,7 @@ mod tests {
sample_state.read().pos_state.selector.clone(),
mip_store,
channels,
Arc::new(RwLock::new(create_test_wallet(Some(PreHashMap::default())))),
MassaMetrics::new(false, 32),
);
// initialize the execution system with genesis blocks
Expand Down Expand Up @@ -1280,6 +1292,7 @@ mod tests {
sample_state.read().pos_state.selector.clone(),
mip_store,
channels,
Arc::new(RwLock::new(create_test_wallet(Some(PreHashMap::default())))),
MassaMetrics::new(false, 32),
);
// initialize the execution system with genesis blocks
Expand Down Expand Up @@ -1394,6 +1407,7 @@ mod tests {
sample_state.read().pos_state.selector.clone(),
mip_store,
channels,
Arc::new(RwLock::new(create_test_wallet(Some(PreHashMap::default())))),
MassaMetrics::new(false, 32),
);
// initialize the execution system with genesis blocks
Expand Down Expand Up @@ -1491,6 +1505,7 @@ mod tests {
sample_state.read().pos_state.selector.clone(),
mip_store,
channels,
Arc::new(RwLock::new(create_test_wallet(Some(PreHashMap::default())))),
MassaMetrics::new(false, 32),
);
// initialize the execution system with genesis blocks
Expand Down Expand Up @@ -1590,6 +1605,7 @@ mod tests {
sample_state.read().pos_state.selector.clone(),
mip_store,
channels,
Arc::new(RwLock::new(create_test_wallet(Some(PreHashMap::default())))),
MassaMetrics::new(false, 32),
);
// initialize the execution system with genesis blocks
Expand Down Expand Up @@ -1795,6 +1811,7 @@ mod tests {
sample_state.read().pos_state.selector.clone(),
mip_store,
channels,
Arc::new(RwLock::new(create_test_wallet(Some(PreHashMap::default())))),
MassaMetrics::new(false, 32),
);
// initialize the execution system with genesis blocks
Expand Down Expand Up @@ -1957,6 +1974,7 @@ mod tests {
sample_state.read().pos_state.selector.clone(),
mip_store,
channels,
Arc::new(RwLock::new(create_test_wallet(Some(PreHashMap::default())))),
MassaMetrics::new(false, 32),
);
// initialize the execution system with genesis blocks
Expand Down Expand Up @@ -2126,6 +2144,7 @@ mod tests {
sample_state.read().pos_state.selector.clone(),
mip_store,
channels,
Arc::new(RwLock::new(create_test_wallet(Some(PreHashMap::default())))),
MassaMetrics::new(false, 32),
);
// initialize the execution system with genesis blocks
Expand Down Expand Up @@ -2215,6 +2234,7 @@ mod tests {
sample_state.read().pos_state.selector.clone(),
mip_store,
channels,
Arc::new(RwLock::new(create_test_wallet(Some(PreHashMap::default())))),
MassaMetrics::new(false, 32),
);
// initialize the execution system with genesis blocks
Expand Down Expand Up @@ -2301,6 +2321,7 @@ mod tests {
sample_state.read().pos_state.selector.clone(),
mip_store,
channels,
Arc::new(RwLock::new(create_test_wallet(Some(PreHashMap::default())))),
MassaMetrics::new(false, 32),
);
// initialize the execution system with genesis blocks
Expand Down Expand Up @@ -2387,6 +2408,7 @@ mod tests {
sample_state.read().pos_state.selector.clone(),
mip_store,
channels,
Arc::new(RwLock::new(create_test_wallet(Some(PreHashMap::default())))),
MassaMetrics::new(false, 32),
);
// initialize the execution system with genesis blocks
Expand Down Expand Up @@ -2530,6 +2552,7 @@ mod tests {
sample_state.read().pos_state.selector.clone(),
mip_store,
channels,
Arc::new(RwLock::new(create_test_wallet(Some(PreHashMap::default())))),
MassaMetrics::new(false, 32),
);
// initialize the execution system with genesis blocks
Expand Down Expand Up @@ -2641,6 +2664,7 @@ mod tests {
sample_state.read().pos_state.selector.clone(),
mip_store,
channels,
Arc::new(RwLock::new(create_test_wallet(Some(PreHashMap::default())))),
MassaMetrics::new(false, 32),
);
// initialize the execution system with genesis blocks
Expand Down Expand Up @@ -2788,6 +2812,7 @@ mod tests {
sample_state.read().pos_state.selector.clone(),
mip_store,
channels,
Arc::new(RwLock::new(create_test_wallet(Some(PreHashMap::default())))),
MassaMetrics::new(false, 32),
);
// initialize the execution system with genesis blocks
Expand Down Expand Up @@ -2883,6 +2908,7 @@ mod tests {
sample_state.read().pos_state.selector.clone(),
mip_store,
channels,
Arc::new(RwLock::new(create_test_wallet(Some(PreHashMap::default())))),
MassaMetrics::new(false, 32),
);
// initialize the execution system with genesis blocks
Expand Down
3 changes: 3 additions & 0 deletions massa-execution-worker/src/worker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use massa_pos_exports::SelectorController;
use massa_storage::Storage;
use massa_time::MassaTime;
use massa_versioning::versioning::MipStore;
use massa_wallet::Wallet;
use parking_lot::{Condvar, Mutex, RwLock};
use std::sync::Arc;
use std::thread;
Expand Down Expand Up @@ -249,6 +250,7 @@ pub fn start_execution_worker(
selector: Box<dyn SelectorController>,
mip_store: MipStore,
channels: ExecutionChannels,
wallet: Arc<RwLock<Wallet>>,
massa_metrics: MassaMetrics,
) -> (Box<dyn ExecutionManager>, Box<dyn ExecutionController>) {
// create an execution state
Expand All @@ -258,6 +260,7 @@ pub fn start_execution_worker(
mip_store,
selector.clone(),
channels,
wallet,
massa_metrics,
)));

Expand Down
14 changes: 13 additions & 1 deletion massa-factory-worker/src/block_factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,22 @@ impl BlockFactoryWorker {
// the selected block producer is not managed locally => quit
return;
};
let mut block_storage = self.channels.storage.clone_without_refs();
{
let block_lock = block_storage.read_blocks();
if let Some(block_ids) = block_lock.get_blocks_by_slot(&slot) {
for block_id in block_ids {
if let Some(block) = block_lock.get(block_id) {
if block.content_creator_address == block_producer_addr {
panic!("You already created a block for slot {} with address {}, node is stopping to prevent you from losing all your stake due to double staking protection", slot, block_producer_addr);
}
}
}
}
}
// get best parents and their periods
let parents: Vec<(BlockId, u64)> = self.channels.consensus.get_best_parents(); // Vec<(parent_id, parent_period)>
// generate the local storage object
let mut block_storage = self.channels.storage.clone_without_refs();

// claim block parents in local storage
{
Expand Down
1 change: 1 addition & 0 deletions massa-node/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,7 @@ async fn launch(
selector_controller.clone(),
mip_store.clone(),
execution_channels.clone(),
node_wallet.clone(),
metrics.clone(),
);

Expand Down