Skip to content

Commit f997d4a

Browse files
authored
Merge pull request #1553 from DanShaders/validator-set
Use check_for_each for iterating over validator set
2 parents 86e6726 + 92f865b commit f997d4a

File tree

1 file changed

+28
-12
lines changed

1 file changed

+28
-12
lines changed

crypto/block/mc-config.cpp

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -576,34 +576,50 @@ td::Result<std::shared_ptr<ValidatorSet>> Config::unpack_validator_set(Ref<vm::C
576576
"maximal index in a validator set dictionary must be one less than the total number of validators");
577577
}
578578
auto ptr = std::make_shared<ValidatorSet>(rec.utime_since, rec.utime_until, rec.total, rec.main);
579-
for (int i = 0; i < rec.total; i++) {
580-
key_buffer.store_ulong(i);
581-
auto descr_cs = dict.lookup(key_buffer.bits(), 16);
582-
if (descr_cs.is_null()) {
583-
return td::Status::Error("indices in a validator set dictionary must be integers 0..total-1");
584-
}
579+
580+
std::vector<bool> seen_keys(rec.total);
581+
td::Status error;
582+
583+
auto validator_set_check_fn = [&](Ref<vm::CellSlice> descr_cs, td::ConstBitPtr key, int n) -> bool {
584+
int i = static_cast<int>(key.get_uint(n));
585+
CHECK(i >= 0 && i < rec.total && !seen_keys[i]);
586+
seen_keys[i] = true;
587+
585588
gen::ValidatorDescr::Record_validator_addr descr;
586589
if (!tlb::csr_unpack(descr_cs, descr)) {
587590
descr.adnl_addr.set_zero();
588591
if (!(gen::t_ValidatorDescr.unpack_validator(descr_cs.write(), descr.public_key, descr.weight) &&
589592
descr_cs->empty_ext())) {
590-
return td::Status::Error(PSLICE() << "validator #" << i
591-
<< " has an invalid ValidatorDescr record in the validator set dictionary");
593+
error = td::Status::Error(PSLICE() << "validator #" << i
594+
<< " has an invalid ValidatorDescr record in the validator set dictionary");
595+
return false;
592596
}
593597
}
594598
gen::SigPubKey::Record sig_pubkey;
595599
if (!tlb::csr_unpack(std::move(descr.public_key), sig_pubkey)) {
596-
return td::Status::Error(PSLICE() << "validator #" << i
597-
<< " has no public key or its public key is in unsupported format");
600+
error = td::Status::Error(PSLICE() << "validator #" << i
601+
<< " has no public key or its public key is in unsupported format");
602+
return false;
598603
}
599604
if (!descr.weight) {
600-
return td::Status::Error(PSLICE() << "validator #" << i << " has zero weight");
605+
error = td::Status::Error(PSLICE() << "validator #" << i << " has zero weight");
606+
return false;
601607
}
602608
if (descr.weight > ~(ptr->total_weight)) {
603-
return td::Status::Error("total weight of all validators in validator set exceeds 2^64");
609+
error = td::Status::Error("total weight of all validators in validator set exceeds 2^64");
610+
return false;
604611
}
605612
ptr->list.emplace_back(sig_pubkey.pubkey, descr.weight, ptr->total_weight, descr.adnl_addr);
606613
ptr->total_weight += descr.weight;
614+
return true;
615+
};
616+
617+
if (!dict.check_for_each(validator_set_check_fn)) {
618+
CHECK(error.is_error());
619+
return error;
620+
}
621+
if (std::find(seen_keys.begin(), seen_keys.end(), false) != seen_keys.end()) {
622+
return td::Status::Error("indices in a validator set dictionary must be integers 0..total-1");
607623
}
608624
if (rec.total_weight && rec.total_weight != ptr->total_weight) {
609625
return td::Status::Error("validator set declares incorrect total weight");

0 commit comments

Comments
 (0)