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:
parent
a31f8d4424
commit
4dd5eea11f
35 changed files with 753 additions and 144 deletions
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue