@@ -47,7 +47,119 @@ BOOST_AUTO_TEST_CASE(block_with_invalid_tx_test)
47
47
[] (const fc::exception &e)->bool {
48
48
return e.code () == account_name_exists_exception::code_value ;
49
49
}) ;
50
-
50
+
51
+ }
52
+
53
+ std::pair<signed_block_ptr, signed_block_ptr> corrupt_trx_in_block (validating_tester& main, account_name act_name) {
54
+ // First we create a valid block with valid transaction
55
+ main.create_account (act_name);
56
+ signed_block_ptr b = main.produce_block_no_validation ();
57
+
58
+ // Make a copy of the valid block and corrupt the transaction
59
+ auto copy_b = std::make_shared<signed_block>(*b);
60
+ auto signed_tx = copy_b->transactions .back ().trx .get <packed_transaction>().get_signed_transaction ();
61
+ // Corrupt one signature
62
+ signed_tx.signatures .clear ();
63
+ signed_tx.sign (main.get_private_key (act_name, " active" ), main.control ->get_chain_id ());
64
+
65
+ // Replace the valid transaction with the invalid transaction
66
+ auto invalid_packed_tx = packed_transaction (signed_tx);
67
+ copy_b->transactions .back ().trx = invalid_packed_tx;
68
+
69
+ // Re-calculate the transaction merkle
70
+ vector<digest_type> trx_digests;
71
+ const auto & trxs = copy_b->transactions ;
72
+ trx_digests.reserve ( trxs.size () );
73
+ for ( const auto & a : trxs )
74
+ trx_digests.emplace_back ( a.digest () );
75
+ copy_b->transaction_mroot = merkle ( move (trx_digests) );
76
+
77
+ // Re-sign the block
78
+ auto header_bmroot = digest_type::hash ( std::make_pair ( copy_b->digest (), main.control ->head_block_state ()->blockroot_merkle .get_root () ) );
79
+ auto sig_digest = digest_type::hash ( std::make_pair (header_bmroot, main.control ->head_block_state ()->pending_schedule_hash ) );
80
+ copy_b->producer_signature = main.get_private_key (b->producer , " active" ).sign (sig_digest);
81
+ return std::pair<signed_block_ptr, signed_block_ptr>(b, copy_b);
82
+ }
83
+
84
+ // verify that a block with a transaction with an incorrect signature, is blindly accepted from a trusted producer
85
+ BOOST_AUTO_TEST_CASE (trusted_producer_test)
86
+ {
87
+ flat_set<account_name> trusted_producers = { N (defproducera), N (defproducerc) };
88
+ validating_tester main (trusted_producers);
89
+ // only using validating_tester to keep the 2 chains in sync, not to validate that the validating_node matches the main node,
90
+ // since it won't be
91
+ main.skip_validate = true ;
92
+
93
+ // First we create a valid block with valid transaction
94
+ std::set<account_name> producers = { N (defproducera), N (defproducerb), N (defproducerc), N (defproducerd) };
95
+ for (auto prod : producers)
96
+ main.create_account (prod);
97
+ auto b = main.produce_block ();
98
+
99
+ std::vector<account_name> schedule (producers.cbegin (), producers.cend ());
100
+ auto trace = main.set_producers (schedule);
101
+
102
+ while (b->producer != N (defproducera)) {
103
+ b = main.produce_block ();
104
+ }
105
+
106
+ auto blocks = corrupt_trx_in_block (main, N (tstproducera));
107
+ main.validate_push_block ( blocks.second );
108
+ }
109
+
110
+ // like trusted_producer_test, except verify that any entry in the trusted_producer list is accepted
111
+ BOOST_AUTO_TEST_CASE (trusted_producer_verify_2nd_test)
112
+ {
113
+ flat_set<account_name> trusted_producers = { N (defproducera), N (defproducerc) };
114
+ validating_tester main (trusted_producers);
115
+ // only using validating_tester to keep the 2 chains in sync, not to validate that the validating_node matches the main node,
116
+ // since it won't be
117
+ main.skip_validate = true ;
118
+
119
+ // First we create a valid block with valid transaction
120
+ std::set<account_name> producers = { N (defproducera), N (defproducerb), N (defproducerc), N (defproducerd) };
121
+ for (auto prod : producers)
122
+ main.create_account (prod);
123
+ auto b = main.produce_block ();
124
+
125
+ std::vector<account_name> schedule (producers.cbegin (), producers.cend ());
126
+ auto trace = main.set_producers (schedule);
127
+
128
+ while (b->producer != N (defproducerc)) {
129
+ b = main.produce_block ();
130
+ }
131
+
132
+ auto blocks = corrupt_trx_in_block (main, N (tstproducera));
133
+ main.validate_push_block ( blocks.second );
134
+ }
135
+
136
+ // verify that a block with a transaction with an incorrect signature, is rejected if it is not from a trusted producer
137
+ BOOST_AUTO_TEST_CASE (untrusted_producer_test)
138
+ {
139
+ flat_set<account_name> trusted_producers = { N (defproducera), N (defproducerc) };
140
+ validating_tester main (trusted_producers);
141
+ // only using validating_tester to keep the 2 chains in sync, not to validate that the validating_node matches the main node,
142
+ // since it won't be
143
+ main.skip_validate = true ;
144
+
145
+ // First we create a valid block with valid transaction
146
+ std::set<account_name> producers = { N (defproducera), N (defproducerb), N (defproducerc), N (defproducerd) };
147
+ for (auto prod : producers)
148
+ main.create_account (prod);
149
+ auto b = main.produce_block ();
150
+
151
+ std::vector<account_name> schedule (producers.cbegin (), producers.cend ());
152
+ auto trace = main.set_producers (schedule);
153
+
154
+ while (b->producer != N (defproducerb)) {
155
+ b = main.produce_block ();
156
+ }
157
+
158
+ auto blocks = corrupt_trx_in_block (main, N (tstproducera));
159
+ BOOST_REQUIRE_EXCEPTION (main.validate_push_block ( blocks.second ), fc::exception ,
160
+ [] (const fc::exception &e)->bool {
161
+ return e.code () == unsatisfied_authorization::code_value ;
162
+ }) ;
51
163
}
52
164
53
165
BOOST_AUTO_TEST_SUITE_END ()
0 commit comments