13
13
// You should have received a copy of the GNU General Public License
14
14
// along with this program. If not, see <http://www.gnu.org/licenses/>.
15
15
16
+ use std:: str:: FromStr ;
16
17
use std:: sync:: atomic:: Ordering ;
17
18
use std:: time:: { Duration , Instant } ;
18
19
use std:: { env, thread} ;
@@ -28,7 +29,7 @@ use stacks::chainstate::stacks::db::{StacksChainState, StacksHeaderInfo};
28
29
use stacks:: codec:: StacksMessageCodec ;
29
30
use stacks:: libstackerdb:: StackerDBChunkData ;
30
31
use stacks:: net:: api:: postblock_proposal:: TEST_VALIDATE_STALL ;
31
- use stacks:: types:: chainstate:: { StacksAddress , StacksPrivateKey } ;
32
+ use stacks:: types:: chainstate:: { StacksAddress , StacksPrivateKey , StacksPublicKey } ;
32
33
use stacks:: types:: PublicKey ;
33
34
use stacks:: util:: secp256k1:: { Secp256k1PrivateKey , Secp256k1PublicKey } ;
34
35
use stacks:: util_lib:: boot:: boot_code_id;
@@ -44,6 +45,7 @@ use super::SignerTest;
44
45
use crate :: event_dispatcher:: MinedNakamotoBlockEvent ;
45
46
use crate :: nakamoto_node:: miner:: TEST_BROADCAST_STALL ;
46
47
use crate :: nakamoto_node:: relayer:: TEST_SKIP_COMMIT_OP ;
48
+ use crate :: run_loop:: boot_nakamoto;
47
49
use crate :: tests:: nakamoto_integrations:: { boot_to_epoch_3_reward_set, next_block_and} ;
48
50
use crate :: tests:: neon_integrations:: {
49
51
get_account, get_chain_info, next_block_and_wait, submit_tx, test_observer,
@@ -611,6 +613,8 @@ fn forked_tenure_testing(
611
613
// make the duration long enough that the reorg attempt will definitely be accepted
612
614
config. first_proposal_burn_block_timing = proposal_limit;
613
615
} ,
616
+ |_| { } ,
617
+ & [ ] ,
614
618
) ;
615
619
let http_origin = format ! ( "http://{}" , & signer_test. running_nodes. conf. node. rpc_bind) ;
616
620
@@ -799,11 +803,10 @@ fn bitcoind_forking_test() {
799
803
let sender_addr = tests:: to_addr ( & sender_sk) ;
800
804
let send_amt = 100 ;
801
805
let send_fee = 180 ;
802
- let mut signer_test: SignerTest < SpawnedSigner > = SignerTest :: new_with_config_modifications (
806
+ let mut signer_test: SignerTest < SpawnedSigner > = SignerTest :: new (
803
807
num_signers,
804
808
vec ! [ ( sender_addr. clone( ) , send_amt + send_fee) ] ,
805
809
Some ( Duration :: from_secs ( 15 ) ) ,
806
- |_config| { } ,
807
810
) ;
808
811
let conf = signer_test. running_nodes . conf . clone ( ) ;
809
812
let http_origin = format ! ( "http://{}" , & conf. node. rpc_bind) ;
@@ -936,6 +939,134 @@ fn bitcoind_forking_test() {
936
939
signer_test. shutdown ( ) ;
937
940
}
938
941
942
+ #[ test]
943
+ #[ ignore]
944
+ fn multiple_miners ( ) {
945
+ if env:: var ( "BITCOIND_TEST" ) != Ok ( "1" . into ( ) ) {
946
+ return ;
947
+ }
948
+
949
+ let num_signers = 5 ;
950
+ let sender_sk = Secp256k1PrivateKey :: new ( ) ;
951
+ let sender_addr = tests:: to_addr ( & sender_sk) ;
952
+ let send_amt = 100 ;
953
+ let send_fee = 180 ;
954
+
955
+ let btc_miner_1_seed = vec ! [ 1 , 1 , 1 , 1 ] ;
956
+ let btc_miner_2_seed = vec ! [ 2 , 2 , 2 , 2 ] ;
957
+ let btc_miner_1_pk = Keychain :: default ( btc_miner_1_seed. clone ( ) ) . get_pub_key ( ) ;
958
+ let btc_miner_2_pk = Keychain :: default ( btc_miner_2_seed. clone ( ) ) . get_pub_key ( ) ;
959
+
960
+ let node_1_rpc = 51024 ;
961
+ let node_1_p2p = 51023 ;
962
+ let node_2_rpc = 51026 ;
963
+ let node_2_p2p = 51025 ;
964
+
965
+ let node_1_rpc_bind = format ! ( "127.0.0.1:{}" , node_1_rpc) ;
966
+ let node_2_rpc_bind = format ! ( "127.0.0.1:{}" , node_2_rpc) ;
967
+ let mut node_2_listeners = Vec :: new ( ) ;
968
+
969
+ // partition the signer set so that ~half are listening and using node 1 for RPC and events,
970
+ // and the rest are using node 2
971
+
972
+ let mut signer_test: SignerTest < SpawnedSigner > = SignerTest :: new_with_config_modifications (
973
+ num_signers,
974
+ vec ! [ ( sender_addr. clone( ) , send_amt + send_fee) ] ,
975
+ Some ( Duration :: from_secs ( 15 ) ) ,
976
+ |signer_config| {
977
+ let node_host = if signer_config. endpoint . port ( ) % 2 == 0 {
978
+ & node_1_rpc_bind
979
+ } else {
980
+ & node_2_rpc_bind
981
+ } ;
982
+ signer_config. node_host = node_host. to_string ( ) ;
983
+ } ,
984
+ |config| {
985
+ let localhost = "127.0.0.1" ;
986
+ config. node . rpc_bind = format ! ( "{}:{}" , localhost, node_1_rpc) ;
987
+ config. node . p2p_bind = format ! ( "{}:{}" , localhost, node_1_p2p) ;
988
+ config. node . data_url = format ! ( "http://{}:{}" , localhost, node_1_rpc) ;
989
+ config. node . p2p_address = format ! ( "{}:{}" , localhost, node_1_p2p) ;
990
+
991
+ config. node . seed = btc_miner_1_seed. clone ( ) ;
992
+ config. node . local_peer_seed = btc_miner_1_seed. clone ( ) ;
993
+ config. burnchain . local_mining_public_key = Some ( btc_miner_1_pk. to_hex ( ) ) ;
994
+
995
+ config. events_observers . retain ( |listener| {
996
+ let Ok ( addr) = std:: net:: SocketAddr :: from_str ( & listener. endpoint ) else {
997
+ warn ! (
998
+ "Cannot parse {} to a socket, assuming it isn't a signer-listener binding" ,
999
+ listener. endpoint
1000
+ ) ;
1001
+ return true ;
1002
+ } ;
1003
+ if addr. port ( ) % 2 == 0 || addr. port ( ) == test_observer:: EVENT_OBSERVER_PORT {
1004
+ return true ;
1005
+ }
1006
+ node_2_listeners. push ( listener. clone ( ) ) ;
1007
+ false
1008
+ } )
1009
+ } ,
1010
+ & [ btc_miner_1_pk. clone ( ) , btc_miner_2_pk. clone ( ) ] ,
1011
+ ) ;
1012
+ let conf = signer_test. running_nodes . conf . clone ( ) ;
1013
+ let mut conf_node_2 = conf. clone ( ) ;
1014
+ let localhost = "127.0.0.1" ;
1015
+ conf_node_2. node . rpc_bind = format ! ( "{}:{}" , localhost, node_2_rpc) ;
1016
+ conf_node_2. node . p2p_bind = format ! ( "{}:{}" , localhost, node_2_p2p) ;
1017
+ conf_node_2. node . data_url = format ! ( "http://{}:{}" , localhost, node_2_rpc) ;
1018
+ conf_node_2. node . p2p_address = format ! ( "{}:{}" , localhost, node_2_p2p) ;
1019
+ conf_node_2. node . seed = btc_miner_2_seed. clone ( ) ;
1020
+ conf_node_2. burnchain . local_mining_public_key = Some ( btc_miner_2_pk. to_hex ( ) ) ;
1021
+ conf_node_2. node . local_peer_seed = btc_miner_2_seed. clone ( ) ;
1022
+ conf_node_2. node . miner = true ;
1023
+ conf_node_2. events_observers . clear ( ) ;
1024
+ conf_node_2. events_observers . extend ( node_2_listeners) ;
1025
+ assert ! ( !conf_node_2. events_observers. is_empty( ) ) ;
1026
+
1027
+ let node_1_sk = Secp256k1PrivateKey :: from_seed ( & conf. node . local_peer_seed ) ;
1028
+ let node_1_pk = StacksPublicKey :: from_private ( & node_1_sk) ;
1029
+
1030
+ conf_node_2. node . working_dir = format ! ( "{}-{}" , conf_node_2. node. working_dir, "1" ) ;
1031
+
1032
+ conf_node_2. node . set_bootstrap_nodes (
1033
+ format ! ( "{}@{}" , & node_1_pk. to_hex( ) , conf. node. p2p_bind) ,
1034
+ conf. burnchain . chain_id ,
1035
+ conf. burnchain . peer_version ,
1036
+ ) ;
1037
+
1038
+ let mut run_loop_2 = boot_nakamoto:: BootRunLoop :: new ( conf_node_2. clone ( ) ) . unwrap ( ) ;
1039
+ let _run_loop_2_thread = thread:: Builder :: new ( )
1040
+ . name ( "run_loop_2" . into ( ) )
1041
+ . spawn ( move || run_loop_2. start ( None , 0 ) )
1042
+ . unwrap ( ) ;
1043
+
1044
+ signer_test. boot_to_epoch_3 ( ) ;
1045
+ let pre_nakamoto_peer_1_height = get_chain_info ( & conf) . stacks_tip_height ;
1046
+
1047
+ info ! ( "------------------------- Reached Epoch 3.0 -------------------------" ) ;
1048
+
1049
+ let nakamoto_tenures = 20 ;
1050
+ for _i in 0 ..nakamoto_tenures {
1051
+ let _mined_block = signer_test. mine_block_wait_on_processing ( Duration :: from_secs ( 30 ) ) ;
1052
+ }
1053
+
1054
+ info ! (
1055
+ "New chain info: {:?}" ,
1056
+ get_chain_info( & signer_test. running_nodes. conf)
1057
+ ) ;
1058
+
1059
+ info ! ( "New chain info: {:?}" , get_chain_info( & conf_node_2) ) ;
1060
+
1061
+ let peer_1_height = get_chain_info ( & conf) . stacks_tip_height ;
1062
+ let peer_2_height = get_chain_info ( & conf_node_2) . stacks_tip_height ;
1063
+ info ! ( "Peer height information" ; "peer_1" => peer_1_height, "peer_2" => peer_2_height, "pre_naka_height" => pre_nakamoto_peer_1_height) ;
1064
+ assert_eq ! ( peer_1_height, peer_2_height) ;
1065
+ assert_eq ! ( peer_1_height, pre_nakamoto_peer_1_height + nakamoto_tenures) ;
1066
+
1067
+ signer_test. shutdown ( ) ;
1068
+ }
1069
+
939
1070
#[ test]
940
1071
#[ ignore]
941
1072
/// This test checks the behavior at the end of a tenure. Specifically:
0 commit comments