@@ -221,38 +221,76 @@ int main(int argc, char** argv)
221221 " On start, ledger directory should not exist ({})" ,
222222 config.ledger .directory ));
223223 }
224+
224225 // Count members with public encryption key as only these members will be
225226 // handed a recovery share.
226- // Note that it is acceptable to start a network without any member having
227- // a recovery share. The service will check that at least one recovery
228- // member is added before the service can be opened.
229- size_t members_with_pubk_count = 0 ;
227+ // Note that it is acceptable to start a network without any member
228+ // having a recovery share. The service will check that at least one
229+ // recovery member (participant or owner) is added before the
230+ // service can be opened.
231+ size_t recovery_participants_count = 0 ;
232+ size_t recovery_owners_count = 0 ;
230233 for (auto const & m : config.command .start .members )
231234 {
232235 if (m.encryption_public_key_file .has_value ())
233236 {
234- members_with_pubk_count++;
237+ auto role =
238+ m.recovery_role .value_or (ccf::MemberRecoveryRole::Participant);
239+ if (role == ccf::MemberRecoveryRole::Participant)
240+ {
241+ recovery_participants_count++;
242+ }
243+ else if (role == ccf::MemberRecoveryRole::Owner)
244+ {
245+ recovery_owners_count++;
246+ }
235247 }
236248 }
237249
238250 recovery_threshold =
239251 config.command .start .service_configuration .recovery_threshold ;
240252 if (recovery_threshold == 0 )
241253 {
242- LOG_INFO_FMT (
243- " Recovery threshold unset. Defaulting to number of initial "
244- " consortium members with a public encryption key ({})." ,
245- members_with_pubk_count);
246- recovery_threshold = members_with_pubk_count;
254+ if (recovery_participants_count == 0 && recovery_owners_count != 0 )
255+ {
256+ LOG_INFO_FMT (
257+ " Recovery threshold unset. Defaulting to 1 as only consortium "
258+ " members that are recovery owners ({}) are specified." ,
259+ recovery_owners_count);
260+ recovery_threshold = 1 ;
261+ }
262+ else
263+ {
264+ LOG_INFO_FMT (
265+ " Recovery threshold unset. Defaulting to number of initial "
266+ " consortium members with a public encryption key ({})." ,
267+ recovery_participants_count);
268+ recovery_threshold = recovery_participants_count;
269+ }
247270 }
248- else if (recovery_threshold > members_with_pubk_count)
271+ else
249272 {
250- throw std::logic_error (fmt::format (
251- " Recovery threshold ({}) cannot be greater than total number ({})"
252- " of initial consortium members with a public encryption "
253- " key (specified via --member-info options)" ,
254- recovery_threshold,
255- members_with_pubk_count));
273+ if (recovery_participants_count == 0 && recovery_owners_count != 0 )
274+ {
275+ if (recovery_threshold > 1 )
276+ {
277+ throw std::logic_error (fmt::format (
278+ " Recovery threshold ({}) cannot be greater than 1 when all "
279+ " initial consortium members ({}) are of type recovery owner "
280+ " (specified via --member-info options)" ,
281+ recovery_threshold,
282+ recovery_participants_count));
283+ }
284+ }
285+ else if (recovery_threshold > recovery_participants_count)
286+ {
287+ throw std::logic_error (fmt::format (
288+ " Recovery threshold ({}) cannot be greater than total number ({})"
289+ " of initial consortium members with a public encryption "
290+ " key (specified via --member-info options)" ,
291+ recovery_threshold,
292+ recovery_participants_count));
293+ }
256294 }
257295 }
258296 }
@@ -612,12 +650,17 @@ int main(int argc, char** argv)
612650 for (auto const & m : config.command .start .members )
613651 {
614652 std::optional<ccf::crypto::Pem> public_encryption_key = std::nullopt ;
653+ std::optional<ccf::MemberRecoveryRole> recovery_role = std::nullopt ;
615654 if (
616655 m.encryption_public_key_file .has_value () &&
617656 !m.encryption_public_key_file .value ().empty ())
618657 {
619658 public_encryption_key = ccf::crypto::Pem (
620659 files::slurp (m.encryption_public_key_file .value ()));
660+ if (m.recovery_role .has_value ())
661+ {
662+ recovery_role = m.recovery_role .value ();
663+ }
621664 }
622665
623666 nlohmann::json md = nullptr ;
@@ -629,7 +672,8 @@ int main(int argc, char** argv)
629672 startup_config.start .members .emplace_back (
630673 ccf::crypto::Pem (files::slurp (m.certificate_file )),
631674 public_encryption_key,
632- md);
675+ md,
676+ recovery_role);
633677 }
634678 startup_config.start .constitution = " " ;
635679 for (const auto & constitution_path :
0 commit comments