Skip to content

Commit 910472f

Browse files
committed
feat(slasher): add stub contract
1 parent 1ef5f51 commit 910472f

14 files changed

Lines changed: 147 additions & 42 deletions

File tree

cli/src/node/config.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use tycho_control::ControlServerConfig;
1010
use tycho_core::node::NodeBaseConfig;
1111
use tycho_crypto::ed25519;
1212
use tycho_rpc::RpcConfig;
13+
use tycho_slasher::SlasherConfig;
1314
use tycho_types::cell::HashBytes;
1415
use tycho_types::models::StdAddr;
1516
use tycho_util::cli::config::ThreadPoolConfig;
@@ -165,6 +166,9 @@ pub struct NodeConfig {
165166

166167
pub validator: ValidatorStdImplConfig,
167168

169+
#[partial]
170+
pub slasher: SlasherConfig,
171+
168172
#[partial]
169173
pub rpc: Option<RpcConfig>,
170174

@@ -191,6 +195,7 @@ impl Default for NodeConfig {
191195
mempool: Default::default(),
192196
internal_queue: Default::default(),
193197
validator: Default::default(),
198+
slasher: Default::default(),
194199
rpc: Some(Default::default()),
195200
control: Default::default(),
196201
metrics: Some(Default::default()),

cli/src/node/mod.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use tycho_core::node::{NodeBase, NodeKeys};
3131
use tycho_core::storage::NodeSyncState;
3232
use tycho_network::InboundRequestMeta;
3333
use tycho_rpc::{NodeBaseInitRpc, RpcConfig};
34+
use tycho_slasher::SlasherConfig;
3435
use tycho_types::models::*;
3536
use tycho_util::futures::JoinTask;
3637
use tycho_wu_tuner::service::WuTunerServiceBuilder;
@@ -54,6 +55,7 @@ pub struct Node {
5455
collator_config: CollatorConfig,
5556
validator_config: ValidatorStdImplConfig,
5657
internal_queue_config: QueueConfig,
58+
slasher_config: SlasherConfig,
5759
mempool_config_override: Option<MempoolGlobalConfig>,
5860

5961
/// Path to the work units tuner config.
@@ -114,6 +116,7 @@ impl Node {
114116
collator_config: node_config.collator,
115117
validator_config: node_config.validator,
116118
internal_queue_config: node_config.internal_queue,
119+
slasher_config: node_config.slasher,
117120
mempool_config_override: global_config.mempool,
118121
wu_tuner_config_path,
119122
})
@@ -202,7 +205,12 @@ impl Node {
202205
message_queue_adapter.clear_uncommitted_state(&top_shards)?;
203206

204207
// NOTE: Stub
205-
let slasher = tycho_slasher::Slasher::new(base.keypair.clone());
208+
let slasher = tycho_slasher::Slasher::new(
209+
base.keypair.clone(),
210+
tycho_slasher::StubSlasherContract,
211+
base.blockchain_rpc_client.clone(),
212+
self.slasher_config,
213+
);
206214

207215
let validator = ValidatorStdImpl::new(
208216
ValidatorNetworkContext {

collator/src/manager/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use tycho_core::storage::ShardStateStorageError;
1515
use tycho_crypto::ed25519::KeyPair;
1616
use tycho_types::models::{
1717
BlockId, BlockIdShort, CollationConfig, GlobalCapabilities, IndexedValidatorDescription,
18-
ProcessedUptoInfo, ShardIdent, ValidatorDescription,
18+
ProcessedUptoInfo, ShardIdent,
1919
};
2020
use tycho_util::futures::AwaitBlocking;
2121
use tycho_util::metrics::HistogramGuard;

collator/src/manager/utils.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use tycho_crypto::ed25519::{KeyPair, PublicKey};
2-
use tycho_types::models::ValidatorDescription;
32
use tycho_util::FastHashMap;
43

54
pub fn find_us_in_collators_set<T>(

collator/tests/collation_tests.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use tycho_core::block_strider::{
1818
PersistentBlockStriderState, PrintSubscriber, StateSubscriber, StateSubscriberContext,
1919
};
2020
use tycho_crypto::ed25519;
21-
use tycho_slasher_traits::NoopValidatorEventsListener;
21+
use tycho_slasher_traits::NoopValidatorEventsRecorder;
2222
use tycho_types::models::BlockId;
2323

2424
mod common;
@@ -120,7 +120,7 @@ async fn test_collation_process_on_stubs() {
120120
validator_network,
121121
node_1_keypair.clone(),
122122
Default::default(),
123-
Arc::new(NoopValidatorEventsListener),
123+
Arc::new(NoopValidatorEventsRecorder),
124124
),
125125
CollatorStdImplFactory {
126126
wu_tuner_event_sender: None,

collator/tests/validator_tests.rs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ use tycho_collator::validator::{
99
};
1010
use tycho_crypto::ed25519;
1111
use tycho_network::{DhtClient, PeerInfo};
12-
use tycho_slasher_traits::NoopValidatorEventsListener;
12+
use tycho_slasher_traits::NoopValidatorEventsRecorder;
1313
use tycho_types::cell::HashBytes;
14-
use tycho_types::models::{BlockId, ShardIdent, ValidatorDescription};
14+
use tycho_types::models::{BlockId, IndexedValidatorDescription, ShardIdent, ValidatorDescription};
1515
use tycho_util::futures::JoinTask;
1616

1717
mod common;
@@ -24,7 +24,7 @@ struct ValidatorNode {
2424
}
2525

2626
impl ValidatorNode {
27-
fn generate(zerostate_id: &BlockId, rng: &mut impl rand::Rng) -> Self {
27+
fn generate(zerostate_id: &BlockId, rng: &mut impl rand::Rng, idx: u16) -> Self {
2828
let secret_key = rng.random::<ed25519::SecretKey>();
2929
let keypair = Arc::new(ed25519::KeyPair::from(&secret_key));
3030

@@ -33,6 +33,7 @@ impl ValidatorNode {
3333
peer_id: *validator_network.network.peer_id(),
3434
public_key: keypair.public_key,
3535
weight: 1,
36+
validator_idx: idx,
3637
};
3738

3839
let network = &validator_network.network;
@@ -46,7 +47,7 @@ impl ValidatorNode {
4647
validator_network,
4748
keypair.clone(),
4849
ValidatorStdImplConfig::default(),
49-
Arc::new(NoopValidatorEventsListener),
50+
Arc::new(NoopValidatorEventsRecorder),
5051
);
5152

5253
Self {
@@ -64,7 +65,7 @@ fn generate_network(
6465
rng: &mut impl rand::Rng,
6566
) -> Vec<ValidatorNode> {
6667
let nodes = (0..node_count)
67-
.map(|_| ValidatorNode::generate(zerostate_id, rng))
68+
.map(|i| ValidatorNode::generate(zerostate_id, rng, i as u16))
6869
.collect::<Vec<_>>();
6970

7071
for i in 0..nodes.len() {
@@ -83,16 +84,19 @@ fn generate_network(
8384
nodes
8485
}
8586

86-
fn make_description(seqno: u32, nodes: &[ValidatorNode]) -> Vec<ValidatorDescription> {
87+
fn make_description(seqno: u32, nodes: &[ValidatorNode]) -> Vec<IndexedValidatorDescription> {
8788
let mut validators = Vec::with_capacity(nodes.len());
8889
let mut prev_total_weight = 0;
89-
for node in nodes {
90-
validators.push(ValidatorDescription {
91-
public_key: HashBytes(*node.descr.public_key.as_bytes()),
92-
weight: 1,
93-
adnl_addr: Some(HashBytes(*node.descr.peer_id.as_bytes())),
94-
mc_seqno_since: seqno,
95-
prev_total_weight,
90+
for (i, node) in nodes.iter().enumerate() {
91+
validators.push(IndexedValidatorDescription {
92+
desc: ValidatorDescription {
93+
public_key: HashBytes(*node.descr.public_key.as_bytes()),
94+
weight: 1,
95+
adnl_addr: Some(HashBytes(*node.descr.peer_id.as_bytes())),
96+
mc_seqno_since: seqno,
97+
prev_total_weight,
98+
},
99+
validator_idx: i as u16,
96100
});
97101
prev_total_weight += node.descr.weight;
98102
}

contracts/src/slasher-stub.tolk

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import "@stdlib/gas-payments"
2+
import "lib/config-params"
3+
4+
const ERROR_INVALID_SIGNATURE = 40
5+
const ERROR_VALIDATOR_NOT_FOUND = 50
6+
const ERROR_REPLAY_PROTECTION = 52
7+
const ERROR_MESSAGE_EXPIRED = 57
8+
9+
const REPLAY_OFFSET_MS = 5000
10+
const FUTURE_OFFSET_SEC = 60
11+
12+
struct Storage {
13+
updatedAtMs: uint64
14+
}
15+
16+
fun Storage.load(): Storage {
17+
return Storage.fromCell(contract.getData());
18+
}
19+
20+
fun Storage.save(self) {
21+
contract.setData(self.toCell());
22+
}
23+
24+
fun onInternalMessage(_in: InMessage) {}
25+
26+
fun onExternalMessage(inMsg: slice) {
27+
val signature = inMsg.loadBits(512);
28+
val signedBody = inMsg;
29+
val createdAtMs = inMsg.loadUint(64);
30+
val expireAtSec = inMsg.loadUint(32);
31+
val validatorIdx = inMsg.loadUint(16);
32+
inMsg.assertEnd();
33+
assert(blockchain.now() <= expireAtSec, ERROR_MESSAGE_EXPIRED);
34+
35+
var data = Storage.load();
36+
assert(createdAtMs > (data.updatedAtMs - REPLAY_OFFSET_MS) &&
37+
createdAtMs <= (blockchain.now() + FUTURE_OFFSET_SEC) * 1000, ERROR_REPLAY_PROTECTION);
38+
39+
var validatorCs = CurrentVset.getValidatorDescription(validatorIdx);
40+
assert(validatorCs != null, ERROR_VALIDATOR_NOT_FOUND);
41+
val validator = ValidatorDescr.readFromSlice(mutate validatorCs);
42+
43+
val toSign = beginCell().storeSlice(signedBody).endCell();
44+
assert(isSignatureValid(toSign.hash(), signature, validator.pubkey), ERROR_INVALID_SIGNATURE);
45+
46+
data.updatedAtMs = max(createdAtMs, data.updatedAtMs);
47+
data.save();
48+
49+
acceptExternalMessage();
50+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { CompilerConfig } from "@ton/blueprint";
2+
3+
export const compile: CompilerConfig = {
4+
lang: "tolk",
5+
entrypoint: "src/slasher-stub.tolk",
6+
withStackComments: true,
7+
withSrcLineComments: true,
8+
experimentalOptions: "",
9+
};

scripts/build-contracts.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ yarn build --all
1919
copy_code Elector
2020
copy_code ElectorPoA
2121
copy_code Config
22+
copy_code SlasherStub

slasher-traits/src/validator.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ impl BlockValidationScope {
156156
pub fn commit(&self) -> bool {
157157
if self.seal() {
158158
// TODO: Use some unsafe magic to make this closer to a NOOP.
159-
let mut signatures = Arc::new_uninit_slice(self.signature_slots.len() as usize);
159+
let mut signatures = Arc::new_uninit_slice(self.signature_slots.len());
160160
for (res, slot) in std::iter::zip(
161161
Arc::get_mut(&mut signatures).unwrap(),
162162
&self.signature_slots,

0 commit comments

Comments
 (0)