1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-03-09 15:40:10 +00:00

added support for config change proposals

- added some fift scripts for the config change proposal voting
- added validator-engine-console support for the config change proposal voting
- additional sanity checks in catchain
- unsafe slow catchain resync method
This commit is contained in:
ton 2020-03-30 17:20:45 +04:00
parent a31f8d4424
commit 4dd5eea11f
35 changed files with 753 additions and 144 deletions

View file

@ -841,6 +841,131 @@ class ValidatorElectionBidCreator : public td::actor::Actor {
td::BufferSlice result_;
};
class ValidatorProposalVoteCreator : public td::actor::Actor {
public:
ValidatorProposalVoteCreator(td::BufferSlice proposal, std::string dir, td::actor::ActorId<ValidatorEngine> engine,
td::actor::ActorId<ton::keyring::Keyring> keyring, td::Promise<td::BufferSlice> promise)
: proposal_(std::move(proposal))
, dir_(std::move(dir))
, engine_(engine)
, keyring_(keyring)
, promise_(std::move(promise)) {
}
void start_up() override {
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<std::pair<ton::PublicKey, size_t>> R) {
if (R.is_error()) {
td::actor::send_closure(SelfId, &ValidatorProposalVoteCreator::abort_query,
R.move_as_error_prefix("failed to find self permanent key: "));
} else {
auto v = R.move_as_ok();
td::actor::send_closure(SelfId, &ValidatorProposalVoteCreator::got_id, v.first, v.second);
}
});
td::actor::send_closure(engine_, &ValidatorEngine::get_current_validator_perm_key, std::move(P));
}
void got_id(ton::PublicKey pubkey, size_t idx) {
pubkey_ = std::move(pubkey);
idx_ = idx;
auto codeR = td::read_file_str(dir_ + "/config-proposal-vote-req.fif");
if (codeR.is_error()) {
abort_query(codeR.move_as_error_prefix("fif not found (validator-elect-req.fif)"));
return;
}
auto data = proposal_.as_slice().str();
auto R = fift::mem_run_fift(codeR.move_as_ok(), {"config-proposal-vote-req.fif", "-i", td::to_string(idx_), data},
dir_ + "/");
if (R.is_error()) {
abort_query(R.move_as_error_prefix("fift fail (cofig-proposal-vote-req.fif)"));
return;
}
auto res = R.move_as_ok();
auto to_signR = res.source_lookup.read_file("validator-to-sign.req");
if (to_signR.is_error()) {
abort_query(td::Status::Error(PSTRING() << "strange error: no to sign file. Output: " << res.output));
return;
}
auto to_sign = td::BufferSlice{to_signR.move_as_ok().data};
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::BufferSlice> R) {
if (R.is_error()) {
td::actor::send_closure(SelfId, &ValidatorProposalVoteCreator::abort_query,
R.move_as_error_prefix("sign fail: "));
} else {
td::actor::send_closure(SelfId, &ValidatorProposalVoteCreator::signed_vote, R.move_as_ok());
}
});
td::actor::send_closure(keyring_, &ton::keyring::Keyring::sign_message, pubkey_.compute_short_id(),
std::move(to_sign), std::move(P));
}
void signed_vote(td::BufferSlice signature) {
signature_ = std::move(signature);
auto codeR = td::read_file_str(dir_ + "/config-proposal-vote-signed.fif");
if (codeR.is_error()) {
abort_query(codeR.move_as_error_prefix("fif not found (config-proposal-vote-signed.fif)"));
return;
}
auto key = td::base64_encode(pubkey_.export_as_slice().as_slice());
auto sig = td::base64_encode(signature_.as_slice());
auto data = proposal_.as_slice().str();
auto R = fift::mem_run_fift(
codeR.move_as_ok(), {"config-proposal-vote-signed.fif", "-i", td::to_string(idx_), data, key, sig}, dir_ + "/");
if (R.is_error()) {
abort_query(R.move_as_error_prefix("fift fail (config-proposal-vote-signed.fif)"));
return;
}
auto res = R.move_as_ok();
auto dataR = res.source_lookup.read_file("vote-msg-body.boc");
if (dataR.is_error()) {
abort_query(td::Status::Error("strage error: no result boc"));
return;
}
result_ = td::BufferSlice(dataR.move_as_ok().data);
finish_query();
}
void abort_query(td::Status error) {
promise_.set_value(ValidatorEngine::create_control_query_error(std::move(error)));
stop();
}
void finish_query() {
promise_.set_value(ton::create_serialize_tl_object<ton::ton_api::engine_validator_proposalVote>(
pubkey_.compute_short_id().bits256_value(), std::move(result_)));
stop();
}
private:
td::BufferSlice proposal_;
std::string dir_;
ton::PublicKey pubkey_;
size_t idx_;
td::BufferSlice signature_;
td::BufferSlice result_;
td::actor::ActorId<ValidatorEngine> engine_;
td::actor::ActorId<ton::keyring::Keyring> keyring_;
td::Promise<td::BufferSlice> promise_;
td::uint32 ttl_;
AdnlCategory cat_ = 2;
double frac = 2.7;
ton::PublicKeyHash perm_key_;
ton::PublicKey perm_key_full_;
ton::adnl::AdnlNodeIdShort adnl_addr_;
ton::adnl::AdnlNodeIdFull adnl_key_full_;
};
class CheckDhtServerStatusQuery : public td::actor::Actor {
public:
void start_up() override {
@ -1064,6 +1189,9 @@ td::Status ValidatorEngine::load_global_config() {
if (db_depth_ <= 32) {
validator_options_.write().set_filedb_depth(db_depth_);
}
for (auto seq : unsafe_catchains_) {
validator_options_.write().add_unsafe_resync_catchain(seq);
}
std::vector<ton::BlockIdExt> h;
for (auto &x : conf.validator_->hardforks_) {
@ -2822,6 +2950,32 @@ void ValidatorEngine::run_control_query(ton::ton_api::engine_validator_checkDhtS
.release();
}
void ValidatorEngine::run_control_query(ton::ton_api::engine_validator_createProposalVote &query, td::BufferSlice data,
ton::PublicKeyHash src, td::uint32 perm, td::Promise<td::BufferSlice> promise) {
if (!(perm & ValidatorEnginePermissions::vep_modify)) {
promise.set_value(create_control_query_error(td::Status::Error(ton::ErrorCode::error, "not authorized")));
return;
}
if (keyring_.empty()) {
promise.set_value(create_control_query_error(td::Status::Error(ton::ErrorCode::notready, "keyring not started")));
return;
}
if (!started_) {
promise.set_value(create_control_query_error(td::Status::Error(ton::ErrorCode::notready, "not started")));
return;
}
if (fift_dir_.empty()) {
promise.set_value(create_control_query_error(td::Status::Error(ton::ErrorCode::notready, "no fift dir")));
return;
}
td::actor::create_actor<ValidatorProposalVoteCreator>("votecreate", std::move(query.vote_), fift_dir_, actor_id(this),
keyring_.get(), std::move(promise))
.release();
}
void ValidatorEngine::process_control_query(td::uint16 port, ton::adnl::AdnlNodeIdShort src,
ton::adnl::AdnlNodeIdShort dst, td::BufferSlice data,
td::Promise<td::BufferSlice> promise) {
@ -2885,6 +3039,29 @@ void ValidatorEngine::run() {
load_config(std::move(P));
}
void ValidatorEngine::get_current_validator_perm_key(td::Promise<std::pair<ton::PublicKey, size_t>> promise) {
if (state_.is_null()) {
promise.set_error(td::Status::Error(ton::ErrorCode::notready, "not started"));
return;
}
auto val_set = state_->get_total_validator_set(0);
CHECK(val_set.not_null());
auto vec = val_set->export_vector();
for (size_t idx = 0; idx < vec.size(); idx++) {
auto &el = vec[idx];
ton::PublicKey pub{ton::pubkeys::Ed25519{el.key.as_bits256()}};
auto pubkey_hash = pub.compute_short_id();
auto it = config_.validators.find(pubkey_hash);
if (it != config_.validators.end()) {
promise.set_value(std::make_pair(pub, idx));
return;
}
}
promise.set_error(td::Status::Error(ton::ErrorCode::notready, "not a validator"));
}
std::atomic<bool> need_stats_flag{false};
void need_stats(int sig) {
need_stats_flag.store(true);
@ -3029,6 +3206,11 @@ int main(int argc, char *argv[]) {
acts.push_back([&x, v]() { td::actor::send_closure(x, &ValidatorEngine::set_sync_ttl, v); });
return td::Status::OK();
});
p.add_option('U', "unsafe-catchain-restore", "use SLOW and DANGEROUS catchain recover method", [&](td::Slice id) {
TRY_RESULT(seq, td::to_integer_safe<ton::CatchainSeqno>(id));
acts.push_back([&x, seq]() { td::actor::send_closure(x, &ValidatorEngine::add_unsafe_catchain, seq); });
return td::Status::OK();
});
td::uint32 threads = 7;
p.add_option('t', "threads", PSTRING() << "number of threads (default=" << threads << ")", [&](td::Slice fname) {
td::int32 v;