Skip to content

Commit d9c4387

Browse files
Start mining when mining_author is set. (#1706)
* Start mining when `mining_author` is set. And use another configuration `stop_mining` to allow seting mining_author without mining blocks for testing purposes. * Allow "0x" prefix in configurations that take hex strings. * Fix unit test. * Use disable_stratum and start_mining to config minings. * Allow 0x prefix in node id. * Fix unit test. * Update CHANGELOG. * Fix tests. * Remove false check. * Fix. * Use `mining_type`. * Fix comments.
1 parent 7de1721 commit d9c4387

File tree

12 files changed

+128
-68
lines changed

12 files changed

+128
-68
lines changed

blockgen/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ impl BlockGenerator {
174174

175175
/// Send new PoW problem to workers
176176
pub fn send_problem(bg: Arc<BlockGenerator>, problem: ProofOfWorkProblem) {
177-
if bg.pow_config.use_stratum {
177+
if bg.pow_config.use_stratum() {
178178
let stratum = bg.stratum.read();
179179
stratum.as_ref().unwrap().notify(problem);
180180
} else {
@@ -697,7 +697,7 @@ impl BlockGenerator {
697697
time::Duration::from_millis(BLOCKGEN_LOOP_SLEEP_IN_MILISECS);
698698

699699
let receiver: mpsc::Receiver<ProofOfWorkSolution> =
700-
if bg.pow_config.use_stratum {
700+
if bg.pow_config.use_stratum() {
701701
BlockGenerator::start_new_stratum_worker(bg.clone())
702702
} else {
703703
BlockGenerator::start_new_worker(1, bg.clone())
@@ -793,7 +793,7 @@ impl BlockGenerator {
793793
// disconnected people may lose the previous message
794794
if let Some(problem) = current_problem {
795795
if let Ok(elapsed) = last_notify.elapsed() {
796-
if bg.pow_config.use_stratum
796+
if bg.pow_config.use_stratum()
797797
&& elapsed > Duration::from_secs(60)
798798
{
799799
BlockGenerator::send_problem(

changelogs/CHANGELOG-0.6.x.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
# 0.6.2
2+
3+
## Improvement
4+
- Start stratum services automatically if `mining_author` is set.
5+
Use `mining_type` to allow start CPU mining or disable mining manually.
6+
17
# 0.6.0
28

39
## Bug Fixes

changelogs/CHANGELOG-1.0.x.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# 1.0.0
22

3+
## Improvement
4+
- Start stratum services automatically if `mining_author` is set.
5+
Use `mining_type` to allow start CPU mining or disable mining manually.
6+
37
## Bug Fixes
48

59
- Fix bug where users need to restart node before they can use a newly created account to send transactions.

client/src/common/mod.rs

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -414,10 +414,9 @@ pub fn initialize_not_light_node_modules(
414414
);
415415

416416
let maybe_author: Option<Address> =
417-
conf.raw_conf.mining_author.clone().map(|hex_str| {
418-
Address::from_str(hex_str.as_str()).expect(
419-
"mining-author should be 40-digit hex string without 0x prefix",
420-
)
417+
conf.raw_conf.mining_author.as_ref().map(|hex_str| {
418+
parse_hex_string(hex_str)
419+
.expect("mining-author should be 40-digit hex string")
421420
});
422421
let blockgen = Arc::new(BlockGenerator::new(
423422
sync_graph,
@@ -438,21 +437,19 @@ pub fn initialize_not_light_node_modules(
438437
bg.auto_block_generation(interval_ms);
439438
})
440439
.expect("Mining thread spawn error");
441-
} else if conf.raw_conf.start_mining {
442-
if let Some(author) = maybe_author {
443-
if !author.is_valid_address() || author.is_builtin_address() {
444-
panic!("mining-author must starts with 0x1 (user address) or 0x8 (contract address), otherwise you will not get mining rewards!!!");
445-
}
446-
} else {
447-
panic!("mining-author is not set correctly, so you'll not get mining rewards!!!");
440+
} else if let Some(author) = maybe_author {
441+
if !author.is_valid_address() || author.is_builtin_address() {
442+
panic!("mining-author must start with 0x1 (user address) or 0x8 (contract address), otherwise you will not get mining rewards!!!");
443+
}
444+
if blockgen.pow_config.enable_mining() {
445+
let bg = blockgen.clone();
446+
thread::Builder::new()
447+
.name("mining".into())
448+
.spawn(move || {
449+
BlockGenerator::start_mining(bg, 0);
450+
})
451+
.expect("Mining thread spawn error");
448452
}
449-
let bg = blockgen.clone();
450-
thread::Builder::new()
451-
.name("mining".into())
452-
.spawn(move || {
453-
BlockGenerator::start_mining(bg, 0);
454-
})
455-
.expect("Mining thread spawn error");
456453
}
457454

458455
let rpc_impl = Arc::new(RpcImpl::new(
@@ -706,6 +703,7 @@ pub mod delegate_convert {
706703
pub use crate::configuration::Configuration;
707704
use crate::{
708705
accounts::{account_provider, keys_path},
706+
configuration::parse_hex_string,
709707
rpc::{
710708
extractor::RpcExtractor,
711709
impls::{

client/src/configuration.rs

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ build_config! {
7676
// * Open port 12535 for ws rpc if `jsonrpc_ws_port` is not provided.
7777
// * Open port 12536 for tcp rpc if `jsonrpc_tcp_port` is not provided.
7878
// * Open port 12537 for http rpc if `jsonrpc_http_port` is not provided.
79-
// * generate blocks automatically without PoW if `start_mining` is false
79+
// * generate blocks automatically without PoW.
8080
// * Skip catch-up mode even there is no peer
8181
//
8282
(mode, (Option<String>), None)
@@ -85,7 +85,7 @@ build_config! {
8585
(debug_invalid_state_root_epoch, (Option<String>), None)
8686
(debug_dump_dir_invalid_state_root, (String), "./storage_db/debug_dump_invalid_state_root/".to_string())
8787
// Controls block generation speed.
88-
// Only effective in `dev` mode and `start_mining` is false
88+
// Only effective in `dev` mode
8989
(dev_block_interval_ms, (u64), 250)
9090
(enable_state_expose, (bool), false)
9191
(generate_tx, (bool), false)
@@ -124,11 +124,10 @@ build_config! {
124124

125125
// Mining section.
126126
(mining_author, (Option<String>), None)
127-
(start_mining, (bool), false)
127+
(mining_type, (Option<String>), None)
128128
(stratum_listen_address, (String), "127.0.0.1".into())
129129
(stratum_port, (u16), 32525)
130130
(stratum_secret, (Option<String>), None)
131-
(use_stratum, (bool), false)
132131
(use_octopus_in_test_mode, (bool), false)
133132

134133
// Network section.
@@ -313,9 +312,8 @@ impl Configuration {
313312
network_config.config_path = self.raw_conf.netconf_dir.clone();
314313
}
315314
network_config.use_secret =
316-
self.raw_conf.net_key.clone().map(|sec_str| {
317-
sec_str
318-
.parse()
315+
self.raw_conf.net_key.as_ref().map(|sec_str| {
316+
parse_hex_string(sec_str)
319317
.expect("net_key is not a valid secret string")
320318
});
321319
if let Some(addr) = self.raw_conf.public_address.clone() {
@@ -450,16 +448,25 @@ impl Configuration {
450448

451449
pub fn pow_config(&self) -> ProofOfWorkConfig {
452450
let stratum_secret =
453-
self.raw_conf
454-
.stratum_secret
455-
.clone()
456-
.map(|hex_str| H256::from_str(hex_str.as_str())
457-
.expect("Stratum secret should be 64-digit hex string without 0x prefix"));
451+
self.raw_conf.stratum_secret.as_ref().map(|hex_str| {
452+
parse_hex_string(hex_str)
453+
.expect("Stratum secret should be 64-digit hex string")
454+
});
458455

459456
ProofOfWorkConfig::new(
460457
self.is_test_or_dev_mode(),
461458
self.raw_conf.use_octopus_in_test_mode,
462-
self.raw_conf.use_stratum,
459+
self.raw_conf.mining_type.as_ref().map_or_else(
460+
|| {
461+
// Enable stratum implicitly if `mining_author` is set.
462+
if self.raw_conf.mining_author.is_some() {
463+
"stratum"
464+
} else {
465+
"disable"
466+
}
467+
},
468+
|s| s.as_str(),
469+
),
463470
self.raw_conf.initial_difficulty,
464471
self.raw_conf.stratum_listen_address.clone(),
465472
self.raw_conf.stratum_port,
@@ -752,6 +759,8 @@ pub fn to_bootnodes(bootnodes: &Option<String>) -> Result<Vec<String>, String> {
752759
match *bootnodes {
753760
Some(ref x) if !x.is_empty() => x
754761
.split(',')
762+
// ignore empty strings
763+
.filter(|s| !s.is_empty())
755764
.map(|s| match validate_node_url(s).map(Into::into) {
756765
None => Ok(s.to_owned()),
757766
Some(ErrorKind::AddressResolve(_)) => Err(format!(
@@ -768,3 +777,7 @@ pub fn to_bootnodes(bootnodes: &Option<String>) -> Result<Vec<String>, String> {
768777
None => Ok(vec![]),
769778
}
770779
}
780+
781+
pub fn parse_hex_string<F: FromStr>(hex_str: &str) -> Result<F, F::Err> {
782+
hex_str.strip_prefix("0x").unwrap_or(hex_str).parse()
783+
}

client/src/tests/blockgen_tests.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@ fn test_mining_10_epochs() {
8484
conf.raw_conf.tcp_port = 13001;
8585
conf.raw_conf.jsonrpc_http_port = Some(18001);
8686
conf.raw_conf.mining_author =
87-
Some("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".into());
87+
Some("1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".into());
88+
conf.raw_conf.mining_type = Some("cpu".into());
8889

8990
let exit = Arc::new((Mutex::new(false), Condvar::new()));
9091
let handle = ArchiveClient::start(conf, exit).unwrap();

core/src/pow/mod.rs

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use cfx_types::{BigEndianHash, H256, U256, U512};
1616
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
1717
use malloc_size_of_derive::MallocSizeOf as DeriveMallocSizeOf;
1818
use parking_lot::RwLock;
19+
use static_assertions::_core::str::FromStr;
1920
use std::{
2021
collections::{HashMap, VecDeque},
2122
convert::TryFrom,
@@ -60,11 +61,32 @@ pub struct ProofOfWorkSolution {
6061
pub nonce: U256,
6162
}
6263

64+
#[derive(Debug, Clone, DeriveMallocSizeOf)]
65+
pub enum MiningType {
66+
Stratum,
67+
CPU,
68+
Disable,
69+
}
70+
71+
impl FromStr for MiningType {
72+
type Err = String;
73+
74+
fn from_str(s: &str) -> Result<Self, Self::Err> {
75+
let mining_type = match s {
76+
"stratum" => Self::Stratum,
77+
"cpu" => Self::CPU,
78+
"disable" => Self::Disable,
79+
_ => return Err("invalid mining type".into()),
80+
};
81+
Ok(mining_type)
82+
}
83+
}
84+
6385
#[derive(Debug, Clone, DeriveMallocSizeOf)]
6486
pub struct ProofOfWorkConfig {
6587
pub test_mode: bool,
6688
pub use_octopus_in_test_mode: bool,
67-
pub use_stratum: bool,
89+
pub mining_type: MiningType,
6890
pub initial_difficulty: u64,
6991
pub block_generation_period: u64,
7092
pub difficulty_adjustment_epoch_period: u64,
@@ -75,7 +97,7 @@ pub struct ProofOfWorkConfig {
7597

7698
impl ProofOfWorkConfig {
7799
pub fn new(
78-
test_mode: bool, use_octopus_in_test_mode: bool, use_stratum: bool,
100+
test_mode: bool, use_octopus_in_test_mode: bool, mining_type: &str,
79101
initial_difficulty: Option<u64>, stratum_listen_addr: String,
80102
stratum_port: u16, stratum_secret: Option<H256>,
81103
) -> Self
@@ -84,7 +106,7 @@ impl ProofOfWorkConfig {
84106
ProofOfWorkConfig {
85107
test_mode,
86108
use_octopus_in_test_mode,
87-
use_stratum,
109+
mining_type: mining_type.parse().expect("Invalid mining type"),
88110
initial_difficulty: initial_difficulty.unwrap_or(4),
89111
block_generation_period: 1000000,
90112
difficulty_adjustment_epoch_period: 20,
@@ -96,7 +118,7 @@ impl ProofOfWorkConfig {
96118
ProofOfWorkConfig {
97119
test_mode,
98120
use_octopus_in_test_mode,
99-
use_stratum,
121+
mining_type: mining_type.parse().expect("Invalid mining type"),
100122
initial_difficulty: INITIAL_DIFFICULTY,
101123
block_generation_period: TARGET_AVERAGE_BLOCK_GENERATION_PERIOD,
102124
difficulty_adjustment_epoch_period:
@@ -112,6 +134,14 @@ impl ProofOfWorkConfig {
112134
!self.test_mode || self.use_octopus_in_test_mode
113135
}
114136

137+
pub fn use_stratum(&self) -> bool {
138+
matches!(self.mining_type, MiningType::Stratum)
139+
}
140+
141+
pub fn enable_mining(&self) -> bool {
142+
!matches!(self.mining_type, MiningType::Disable)
143+
}
144+
115145
pub fn target_difficulty(
116146
&self, block_count: u64, timespan: u64, cur_difficulty: &U256,
117147
) -> U256 {

core/src/sync/utils.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -174,9 +174,9 @@ pub fn initialize_synchronization_graph_with_data_manager(
174174

175175
let vm = VmFactory::new(1024 * 32);
176176
let pow_config = ProofOfWorkConfig::new(
177-
true, /* test_mode */
178-
false, /* use_octopus_in_test_mode */
179-
false, /* use_stratum */
177+
true, /* test_mode */
178+
false, /* use_octopus_in_test_mode */
179+
"disable", /* mining_type */
180180
Some(10),
181181
String::from(""), /* stratum_listen_addr */
182182
0, /* stratum_port */

network/src/node_table.rs

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -305,17 +305,24 @@ impl FromStr for Node {
305305
type Err = Error;
306306

307307
fn from_str(s: &str) -> Result<Self, Self::Err> {
308-
let (id, endpoint) = if s.len() > 138
309-
&& &s[0..10] == "cfxnode://"
310-
&& &s[138..139] == "@"
311-
{
312-
(
313-
s[10..138].parse().map_err(|_| ErrorKind::InvalidNodeId)?,
314-
NodeEndpoint::from_str(&s[139..])?,
315-
)
316-
} else {
317-
(NodeId::default(), NodeEndpoint::from_str(s)?)
318-
};
308+
let (id, endpoint) =
309+
if let Some(id_and_address_str) = s.strip_prefix("cfxnode://") {
310+
// A node url with format "cfxnode://ID@IP:PORT"
311+
let delimiter_index = id_and_address_str
312+
.find("@")
313+
.ok_or(ErrorKind::AddressParse)?;
314+
(
315+
id_and_address_str[..delimiter_index]
316+
.parse()
317+
.map_err(|_| ErrorKind::InvalidNodeId)?,
318+
NodeEndpoint::from_str(
319+
&id_and_address_str[delimiter_index + 1..],
320+
)?,
321+
)
322+
} else {
323+
// A simple address without node id.
324+
(NodeId::default(), NodeEndpoint::from_str(s)?)
325+
};
319326

320327
Ok(Node {
321328
id,

run/default.toml

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ bootnodes="cfxnode://25265e1aa470d9d8667947820c4830a64e9f9678d6cb23ecde91e044752
2525
# * Open port 12535 for ws rpc if `jsonrpc_ws_port` is not provided.
2626
# * Open port 12536 for tcp rpc if `jsonrpc_tcp_port` is not provided.
2727
# * Open port 12537 for http rpc if `jsonrpc_http_port` is not provided.
28-
# * generate blocks automatically without PoW if `start_mining` is false
28+
# * generate blocks automatically without PoW
2929
# * Skip catch-up mode even there is no peer
3030
#
3131
# mode = ""
@@ -41,21 +41,20 @@ bootnodes="cfxnode://25265e1aa470d9d8667947820c4830a64e9f9678d6cb23ecde91e044752
4141

4242
# ----------------- Mining Configuration -----------------
4343

44-
# `start_mining` controls whether a thread is started to mine new blocks.
45-
# If not set, the node will not start mining blocks.
46-
# If the value is true, `mining_author` must be set.
47-
#
48-
# start_mining=true
49-
5044
# `mining_author` is the address to receive mining rewards.
51-
# The value is a 40-digit hex string without 0x prefix.
45+
# If set, `mining_type` will be "stratum" by default.
46+
# The value is a 40-digit hex string.
5247
# By default, the value is not set.
5348
#
5449
# mining_author="1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
5550

56-
# `use_stratum` controls whether the mining process goes through the
57-
# stratum protocol.
58-
# use_stratum=true
51+
# `mining_type` controls whether the mining process goes through the
52+
# stratum protocol, uses CPU-mining, or disable mining.
53+
# Possible values are "stratum", "cpu", and "disable".
54+
# The default value is "stratum" if `mining_author` is set.
55+
# If the value is set and not "disable", `mining_author` must be set.
56+
#
57+
# mining_type = "stratum"
5958

6059
# Listen address for stratum
6160
#
@@ -66,7 +65,7 @@ bootnodes="cfxnode://25265e1aa470d9d8667947820c4830a64e9f9678d6cb23ecde91e044752
6665
# stratum_port = 32525
6766

6867
# Secret key for stratum.
69-
# The value is 64-digit hex string without 0x prefix.
68+
# The value is 64-digit hex string.
7069
# If not set, the RPC subscription will not check the authorization.
7170
#
7271
# stratum_secret = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
@@ -296,7 +295,7 @@ jsonrpc_local_http_port=12539
296295
# netconf_dir="./net_config"
297296

298297
# `net_key` is the 256-bit private key to generate a unique node id for this node.
299-
# The value is a 64-digit hex string without 0x prefix.
298+
# The value is a 64-digit hex string.
300299
# If not set, the node will try to read from the file "key" under the directory `netconf_dir`.
301300
# If the file is not found, the node will generate a random key.
302301
# By default, the value is not set.

0 commit comments

Comments
 (0)