Skip to content

Commit 611c7f1

Browse files
Set constitution during recovery (#7155)
Co-authored-by: Eddy Ashton <[email protected]>
1 parent 4409c50 commit 611c7f1

File tree

15 files changed

+121
-6
lines changed

15 files changed

+121
-6
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
99

1010
[7.0.0-dev2]: https://github.com/microsoft/CCF/releases/tag/ccf-7.0.0-dev2
1111

12+
### Added
13+
14+
- Allow changing the constitution during disaster recovery via the `command.recover.constitution_files` entry in cchost. (#7155)
15+
1216
### Changed
1317

1418
- `cchost` is removed, and each application now provides its own executable:

doc/host_config_schema/cchost_config.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,13 @@
417417
"previous_sealed_ledger_secret_location": {
418418
"type": ["string"],
419419
"description": "Path to the sealed ledger secret folder, the ledger secrets for the recovered service will be unsealed from here instead of reconstructed from recovery shares."
420+
},
421+
"constitution_files": {
422+
"type": "array",
423+
"items": {
424+
"type": "string"
425+
},
426+
"description": "List of constitution files. These typically include actions.js, validate.js, resolve.js and apply.js"
420427
}
421428
},
422429
"required": ["previous_service_identity_file"],

include/ccf/node/startup_config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ namespace ccf
146146
std::nullopt;
147147
std::optional<std::string> previous_sealed_ledger_secret_location =
148148
std::nullopt;
149+
std::optional<std::string> constitution = std::nullopt;
149150
};
150151
Recover recover = {};
151152
};

src/common/configuration.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include "ccf/crypto/curve.h"
77
#include "ccf/crypto/pem.h"
8+
#include "ccf/ds/json.h"
89
#include "ccf/ds/logger.h"
910
#include "ccf/ds/unit_strings.h"
1011
#include "ccf/node/startup_config.h"
@@ -125,11 +126,12 @@ namespace ccf
125126
service_cert,
126127
follow_redirect);
127128

128-
DECLARE_JSON_TYPE(StartupConfig::Recover);
129+
DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(StartupConfig::Recover);
129130
DECLARE_JSON_REQUIRED_FIELDS(
130131
StartupConfig::Recover,
131132
previous_service_identity,
132133
previous_sealed_ledger_secret_location);
134+
DECLARE_JSON_OPTIONAL_FIELDS(StartupConfig::Recover, constitution);
133135

134136
DECLARE_JSON_TYPE_WITH_BASE(StartupConfig, CCFConfig);
135137
DECLARE_JSON_REQUIRED_FIELDS(

src/host/configuration.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ namespace host
118118
std::string previous_service_identity_file;
119119
std::optional<std::string> previous_sealed_ledger_secret_location =
120120
std::nullopt;
121+
std::vector<std::string> constitution_files = {};
121122
bool operator==(const Recover&) const = default;
122123
};
123124
Recover recover = {};
@@ -168,7 +169,8 @@ namespace host
168169
CCHostConfig::Command::Recover,
169170
initial_service_certificate_validity_days,
170171
previous_service_identity_file,
171-
previous_sealed_ledger_secret_location);
172+
previous_sealed_ledger_secret_location,
173+
constitution_files);
172174

173175
DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(CCHostConfig::Command);
174176
DECLARE_JSON_REQUIRED_FIELDS(CCHostConfig::Command, type);

src/host/run.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,26 @@ namespace ccf
799799
LOG_INFO_FMT("Reading previous service identity from {}", idf);
800800
startup_config.recover.previous_service_identity = files::slurp(idf);
801801

802+
if (!config.command.recover.constitution_files.empty())
803+
{
804+
LOG_INFO_FMT(
805+
"Reading [{}] constitution file(s) for recovery",
806+
fmt::join(config.command.recover.constitution_files, ", "));
807+
startup_config.recover.constitution = "";
808+
for (const auto& constitution_path :
809+
config.command.recover.constitution_files)
810+
{
811+
// Separate with single newlines
812+
if (!startup_config.recover.constitution->empty())
813+
{
814+
startup_config.recover.constitution.value() += '\n';
815+
}
816+
817+
startup_config.recover.constitution.value() +=
818+
files::slurp_string(constitution_path);
819+
}
820+
}
821+
802822
if (config.command.recover.previous_sealed_ledger_secret_location
803823
.has_value())
804824
{

src/node/node_state.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,7 @@ namespace ccf
392392
{
393393
case StartType::Start:
394394
{
395+
LOG_INFO_FMT("Creating boot request");
395396
create_and_send_boot_request(
396397
aft::starting_view_change, true /* Create new consortium */);
397398
return;
@@ -2127,6 +2128,16 @@ namespace ccf
21272128
{
21282129
create_params.genesis_info = config.start;
21292130
}
2131+
create_params.recovery_constitution = config.recover.constitution;
2132+
LOG_INFO_FMT("serialise_create_request, set recovery_constitution to:");
2133+
if (create_params.recovery_constitution.has_value())
2134+
{
2135+
LOG_INFO_FMT("{}", create_params.recovery_constitution.value());
2136+
}
2137+
else
2138+
{
2139+
LOG_INFO_FMT("No recovery constitution provided");
2140+
}
21302141

21312142
create_params.node_id = self;
21322143
create_params.certificate_signing_request = node_sign_kp->create_csr(

src/node/rpc/node_call_types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ namespace ccf
7474

7575
// Only set on genesis transaction, but not on recovery
7676
std::optional<ccf::StartupConfig::Start> genesis_info = std::nullopt;
77+
// Constitution to set on recovery
78+
std::optional<std::string> recovery_constitution = std::nullopt;
7779
};
7880
};
7981

src/node/rpc/node_frontend.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1568,6 +1568,11 @@ namespace ccf
15681568
}
15691569
else
15701570
{
1571+
if (in.recovery_constitution.has_value())
1572+
{
1573+
InternalTablesAccess::set_constitution(
1574+
ctx.tx, in.recovery_constitution.value());
1575+
}
15711576
// On recovery, force a new ledger chunk
15721577
auto tx_ = static_cast<ccf::kv::CommittableTx*>(&ctx.tx);
15731578
if (tx_ == nullptr)

src/node/rpc/serialization.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ namespace ccf
7373
DECLARE_JSON_OPTIONAL_FIELDS(
7474
CreateNetworkNodeToNode::In,
7575
genesis_info,
76+
recovery_constitution,
7677
node_data,
7778
service_data,
7879
snp_security_policy,

0 commit comments

Comments
 (0)