Skip to content

Commit e2bd982

Browse files
committed
feat: add chain_id to signer config
1 parent 21a196a commit e2bd982

File tree

9 files changed

+97
-19
lines changed

9 files changed

+97
-19
lines changed

stacks-signer/src/client/stackerdb.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ mod tests {
255255
Some(100_000),
256256
None,
257257
Some(9000),
258+
None,
258259
);
259260
let config = GlobalConfig::load_from_str(&signer_config[0]).unwrap();
260261
let signer_config = generate_signer_config(&config, 5);

stacks-signer/src/client/stacks_client.rs

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ use serde::Deserialize;
4545
use serde_json::json;
4646
use slog::{slog_debug, slog_warn};
4747
use stacks_common::codec::StacksMessageCodec;
48-
use stacks_common::consts::{CHAIN_ID_MAINNET, CHAIN_ID_TESTNET};
48+
use stacks_common::consts::CHAIN_ID_MAINNET;
4949
use stacks_common::types::chainstate::{
5050
ConsensusHash, StacksAddress, StacksPrivateKey, StacksPublicKey,
5151
};
@@ -99,7 +99,7 @@ impl From<&GlobalConfig> for StacksClient {
9999
stacks_address: config.stacks_address,
100100
http_origin: format!("http://{}", config.node_host),
101101
tx_version: config.network.to_transaction_version(),
102-
chain_id: config.network.to_chain_id(),
102+
chain_id: config.to_chain_id(),
103103
stacks_node_client: reqwest::blocking::Client::new(),
104104
mainnet: config.network.is_mainnet(),
105105
auth_password: config.auth_password.clone(),
@@ -114,18 +114,14 @@ impl StacksClient {
114114
node_host: String,
115115
auth_password: String,
116116
mainnet: bool,
117+
chain_id: u32,
117118
) -> Self {
118119
let pubkey = StacksPublicKey::from_private(&stacks_private_key);
119120
let tx_version = if mainnet {
120121
TransactionVersion::Mainnet
121122
} else {
122123
TransactionVersion::Testnet
123124
};
124-
let chain_id = if mainnet {
125-
CHAIN_ID_MAINNET
126-
} else {
127-
CHAIN_ID_TESTNET
128-
};
129125
let stacks_address = StacksAddress::p2pkh(mainnet, &pubkey);
130126
Self {
131127
stacks_private_key,
@@ -145,7 +141,13 @@ impl StacksClient {
145141
node_host: String,
146142
auth_password: String,
147143
) -> Result<Self, ClientError> {
148-
let mut stacks_client = Self::new(stacks_private_key, node_host, auth_password, true);
144+
let mut stacks_client = Self::new(
145+
stacks_private_key,
146+
node_host,
147+
auth_password,
148+
true,
149+
CHAIN_ID_MAINNET,
150+
);
149151
let pubkey = StacksPublicKey::from_private(&stacks_private_key);
150152
let info = stacks_client.get_peer_info()?;
151153
if info.network_id == CHAIN_ID_MAINNET {
@@ -154,7 +156,7 @@ impl StacksClient {
154156
stacks_client.tx_version = TransactionVersion::Mainnet;
155157
} else {
156158
stacks_client.mainnet = false;
157-
stacks_client.chain_id = CHAIN_ID_TESTNET;
159+
stacks_client.chain_id = info.network_id;
158160
stacks_client.tx_version = TransactionVersion::Testnet;
159161
}
160162
stacks_client.stacks_address = StacksAddress::p2pkh(stacks_client.mainnet, &pubkey);
@@ -1219,4 +1221,12 @@ mod tests {
12191221
write_response(mock.server, response.as_bytes());
12201222
assert_eq!(h.join().unwrap().unwrap(), reward_cycle as u128);
12211223
}
1224+
1225+
#[test]
1226+
fn get_chain_id_from_config() {
1227+
let mock = MockServerClient::from_config(
1228+
GlobalConfig::load_from_file("./src/tests/conf/signer-custom-chain-id.toml").unwrap(),
1229+
);
1230+
assert_eq!(mock.client.chain_id, 0x80000100);
1231+
}
12221232
}

stacks-signer/src/config.rs

Lines changed: 63 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,6 @@ impl std::fmt::Display for Network {
7676
}
7777

7878
impl Network {
79-
/// Converts a Network enum variant to a corresponding chain id
80-
pub const fn to_chain_id(&self) -> u32 {
81-
match self {
82-
Self::Mainnet => CHAIN_ID_MAINNET,
83-
Self::Testnet | Self::Mocknet => CHAIN_ID_TESTNET,
84-
}
85-
}
86-
8779
/// Convert a Network enum variant to a corresponding address version
8880
pub const fn to_address_version(&self) -> u8 {
8981
match self {
@@ -163,6 +155,8 @@ pub struct GlobalConfig {
163155
pub first_proposal_burn_block_timing: Duration,
164156
/// How much time to wait for a miner to propose a block following a sortition
165157
pub block_proposal_timeout: Duration,
158+
/// An optional custom Chain ID
159+
chain_id: Option<u32>,
166160
}
167161

168162
/// Internal struct for loading up the config file
@@ -190,6 +184,8 @@ struct RawConfigFile {
190184
pub first_proposal_burn_block_timing_secs: Option<u64>,
191185
/// How much time to wait for a miner to propose a block following a sortition in milliseconds
192186
pub block_proposal_timeout_ms: Option<u64>,
187+
/// An optional custom Chain ID
188+
pub chain_id: Option<u32>,
193189
}
194190

195191
impl RawConfigFile {
@@ -278,6 +274,7 @@ impl TryFrom<RawConfigFile> for GlobalConfig {
278274
metrics_endpoint,
279275
first_proposal_burn_block_timing,
280276
block_proposal_timeout,
277+
chain_id: raw_data.chain_id,
281278
})
282279
}
283280
}
@@ -308,13 +305,15 @@ impl GlobalConfig {
308305
Some(endpoint) => endpoint.to_string(),
309306
None => "None".to_string(),
310307
};
308+
let chain_id = format!("{:x}", self.to_chain_id());
311309
format!(
312310
r#"
313311
Stacks node host: {node_host}
314312
Signer endpoint: {endpoint}
315313
Stacks address: {stacks_address}
316314
Public key: {public_key}
317315
Network: {network}
316+
Chain ID: 0x{chain_id}
318317
Database path: {db_path}
319318
Metrics endpoint: {metrics_endpoint}
320319
"#,
@@ -329,6 +328,14 @@ Metrics endpoint: {metrics_endpoint}
329328
metrics_endpoint = metrics_endpoint,
330329
)
331330
}
331+
332+
/// Get the chain ID for the network
333+
pub fn to_chain_id(&self) -> u32 {
334+
self.chain_id.unwrap_or_else(|| match self.network {
335+
Network::Mainnet => CHAIN_ID_MAINNET,
336+
Network::Testnet | Network::Mocknet => CHAIN_ID_TESTNET,
337+
})
338+
}
332339
}
333340

334341
impl Display for GlobalConfig {
@@ -356,6 +363,7 @@ pub fn build_signer_config_tomls(
356363
max_tx_fee_ustx: Option<u64>,
357364
tx_fee_ustx: Option<u64>,
358365
mut metrics_port_start: Option<usize>,
366+
chain_id: Option<u32>,
359367
) -> Vec<String> {
360368
let mut signer_config_tomls = vec![];
361369

@@ -421,6 +429,15 @@ metrics_endpoint = "{metrics_endpoint}"
421429
metrics_port_start = Some(metrics_port + 1);
422430
}
423431

432+
if let Some(chain_id) = chain_id {
433+
signer_config_toml = format!(
434+
r#"
435+
{signer_config_toml}
436+
chain_id = {chain_id}
437+
"#
438+
)
439+
}
440+
424441
signer_config_tomls.push(signer_config_toml);
425442
}
426443

@@ -453,13 +470,16 @@ mod tests {
453470
None,
454471
None,
455472
Some(4000),
473+
None,
456474
);
457475

458476
let config =
459477
RawConfigFile::load_from_str(&config_tomls[0]).expect("Failed to parse config file");
460478

461479
assert_eq!(config.auth_password, "melon");
462480
assert_eq!(config.metrics_endpoint, Some("localhost:4000".to_string()));
481+
let global_config = GlobalConfig::try_from(config).unwrap();
482+
assert_eq!(global_config.to_chain_id(), CHAIN_ID_TESTNET);
463483
}
464484

465485
#[test]
@@ -473,8 +493,10 @@ Signer endpoint: 127.0.0.1:30000
473493
Stacks address: ST3FPN8KBZ3YPBP0ZJGAAHTVFMQDTJCR5QPS7VTNJ
474494
Public key: 03bc489f27da3701d9f9e577c88de5567cf4023111b7577042d55cde4d823a3505
475495
Network: testnet
496+
Chain ID: 0x80000000
476497
Database path: :memory:
477498
Metrics endpoint: 0.0.0.0:9090
499+
Chain ID: 2147483648
478500
"#;
479501

480502
let expected_str_v6 = r#"
@@ -483,6 +505,7 @@ Signer endpoint: [::1]:30000
483505
Stacks address: ST3FPN8KBZ3YPBP0ZJGAAHTVFMQDTJCR5QPS7VTNJ
484506
Public key: 03bc489f27da3701d9f9e577c88de5567cf4023111b7577042d55cde4d823a3505
485507
Network: testnet
508+
Chain ID: 0x80000000
486509
Database path: :memory:
487510
Metrics endpoint: 0.0.0.0:9090
488511
"#;
@@ -531,5 +554,37 @@ db_path = ":memory:"
531554
);
532555
let config = GlobalConfig::load_from_str(&config_toml).unwrap();
533556
assert_eq!(config.stacks_address.to_string(), expected_addr);
557+
assert_eq!(config.to_chain_id(), CHAIN_ID_MAINNET);
558+
}
559+
560+
#[test]
561+
fn test_custom_chain_id() {
562+
let pk = StacksPrivateKey::from_hex(
563+
"eb05c83546fdd2c79f10f5ad5434a90dd28f7e3acb7c092157aa1bc3656b012c01",
564+
)
565+
.unwrap();
566+
567+
let node_host = "localhost";
568+
let network = Network::Testnet;
569+
let password = "melon";
570+
let config_tomls = build_signer_config_tomls(
571+
&[pk],
572+
node_host,
573+
None,
574+
&network,
575+
password,
576+
rand::random(),
577+
3000,
578+
None,
579+
None,
580+
Some(4000),
581+
Some(0x80000100),
582+
);
583+
584+
let config =
585+
RawConfigFile::load_from_str(&config_tomls[0]).expect("Failed to parse config file");
586+
assert_eq!(config.chain_id, Some(0x80000100));
587+
let global_config = GlobalConfig::try_from(config).unwrap();
588+
assert_eq!(global_config.to_chain_id(), 0x80000100);
534589
}
535590
}

stacks-signer/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ fn handle_generate_stacking_signature(
121121
&private_key, //
122122
args.reward_cycle.into(),
123123
args.method.topic(),
124-
config.network.to_chain_id(),
124+
config.to_chain_id(),
125125
args.period.into(),
126126
args.max_amount,
127127
args.auth_id,

stacks-signer/src/tests/chainstate.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use clarity::util::vrf::VRFProof;
3232
use libsigner::BlockProposal;
3333
use slog::slog_info;
3434
use stacks_common::bitvec::BitVec;
35+
use stacks_common::consts::CHAIN_ID_TESTNET;
3536
use stacks_common::info;
3637
use stacks_common::types::chainstate::{
3738
ConsensusHash, StacksBlockId, StacksPrivateKey, StacksPublicKey, TrieHash,
@@ -96,6 +97,7 @@ fn setup_test_environment(
9697
SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 10000).to_string(),
9798
"FOO".into(),
9899
false,
100+
CHAIN_ID_TESTNET,
99101
);
100102

101103
let signer_db_dir = "/tmp/stacks-node-tests/signer-units/";
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
stacks_private_key = "126e916e77359ccf521e168feea1fcb9626c59dc375cae00c7464303381c7dff01"
2+
node_host = "127.0.0.1:20444"
3+
endpoint = "localhost:30001"
4+
network = "testnet"
5+
auth_password = "12345"
6+
db_path = ":memory:"
7+
chain_id = 0x80000100

testnet/stacks-node/src/tests/nakamoto_integrations.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ use stacks::util_lib::signed_structured_data::pox4::{
7878
use stacks_common::address::AddressHashMode;
7979
use stacks_common::bitvec::BitVec;
8080
use stacks_common::codec::StacksMessageCodec;
81-
use stacks_common::consts::STACKS_EPOCH_MAX;
81+
use stacks_common::consts::{CHAIN_ID_TESTNET, STACKS_EPOCH_MAX};
8282
use stacks_common::types::chainstate::{
8383
BlockHeaderHash, BurnchainHeaderHash, StacksAddress, StacksPrivateKey, StacksPublicKey,
8484
TrieHash,
@@ -6400,6 +6400,7 @@ fn signer_chainstate() {
64006400
.clone()
64016401
.unwrap_or("".into()),
64026402
false,
6403+
CHAIN_ID_TESTNET,
64036404
);
64046405

64056406
wait_for_first_naka_block_commit(60, &commits_submitted);

testnet/stacks-node/src/tests/signer/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ impl<S: Signer<T> + Send + 'static, T: SignerEventTrait + 'static> SignerTest<Sp
173173
Some(100_000),
174174
None,
175175
Some(9000),
176+
None,
176177
)
177178
.into_iter()
178179
.map(|toml| {

testnet/stacks-node/src/tests/signer/v0.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2990,6 +2990,7 @@ fn signer_set_rollover() {
29902990
Some(100_000),
29912991
None,
29922992
Some(9000 + num_signers),
2993+
None,
29932994
);
29942995

29952996
let new_spawned_signers: Vec<_> = (0..new_num_signers)

0 commit comments

Comments
 (0)