diff --git a/AmendmentTable_8cpp_source.html b/AmendmentTable_8cpp_source.html index d742f7f5a4..5ed84cc687 100644 --- a/AmendmentTable_8cpp_source.html +++ b/AmendmentTable_8cpp_source.html @@ -422,602 +422,609 @@ $(function() {
388  Json::Value& v,
389  uint256 const& amendment,
390  AmendmentState const& state,
-
391  std::lock_guard<std::mutex> const& lock) const;
-
392 
-
393  void
-
394  persistVote(
-
395  uint256 const& amendment,
-
396  std::string const& name,
-
397  AmendmentVote vote) const;
-
398 
-
399 public:
-
400  AmendmentTableImpl(
-
401  Application& app,
-
402  std::chrono::seconds majorityTime,
-
403  std::vector<FeatureInfo> const& supported,
-
404  Section const& enabled,
-
405  Section const& vetoed,
-
406  beast::Journal journal);
-
407 
-
408  uint256
-
409  find(std::string const& name) const override;
-
410 
-
411  bool
-
412  veto(uint256 const& amendment) override;
-
413  bool
-
414  unVeto(uint256 const& amendment) override;
-
415 
-
416  bool
-
417  enable(uint256 const& amendment) override;
-
418 
-
419  bool
-
420  isEnabled(uint256 const& amendment) const override;
-
421  bool
-
422  isSupported(uint256 const& amendment) const override;
-
423 
-
424  bool
-
425  hasUnsupportedEnabled() const override;
-
426 
-
427  std::optional<NetClock::time_point>
-
428  firstUnsupportedExpected() const override;
-
429 
-
430  Json::Value
-
431  getJson() const override;
-
432  Json::Value
-
433  getJson(uint256 const&) const override;
-
434 
-
435  bool
-
436  needValidatedLedger(LedgerIndex seq) const override;
-
437 
-
438  void
-
439  doValidatedLedger(
-
440  LedgerIndex seq,
-
441  std::set<uint256> const& enabled,
-
442  majorityAmendments_t const& majority) override;
-
443 
-
444  void
-
445  trustChanged(hash_set<PublicKey> const& allTrusted) override;
-
446 
-
447  std::vector<uint256>
-
448  doValidation(std::set<uint256> const& enabledAmendments) const override;
-
449 
-
450  std::vector<uint256>
-
451  getDesired() const override;
-
452 
-
453  std::map<uint256, std::uint32_t>
-
454  doVoting(
-
455  Rules const& rules,
-
456  NetClock::time_point closeTime,
-
457  std::set<uint256> const& enabledAmendments,
-
458  majorityAmendments_t const& majorityAmendments,
-
459  std::vector<std::shared_ptr<STValidation>> const& validations) override;
-
460 };
-
461 
-
462 //------------------------------------------------------------------------------
-
463 
-
464 AmendmentTableImpl::AmendmentTableImpl(
-
465  Application& app,
-
466  std::chrono::seconds majorityTime,
-
467  std::vector<FeatureInfo> const& supported,
-
468  Section const& enabled,
-
469  Section const& vetoed,
-
470  beast::Journal journal)
-
471  : lastUpdateSeq_(0)
-
472  , majorityTime_(majorityTime)
-
473  , unsupportedEnabled_(false)
-
474  , j_(journal)
-
475  , db_(app.getWalletDB())
-
476 {
-
477  std::lock_guard lock(mutex_);
-
478 
-
479  // Find out if the FeatureVotes table exists in WalletDB
-
480  bool const featureVotesExist = [this]() {
-
481  auto db = db_.checkoutDb();
-
482  return createFeatureVotes(*db);
-
483  }();
-
484 
-
485  // Parse supported amendments
-
486  for (auto const& [name, amendment, votebehavior] : supported)
-
487  {
-
488  AmendmentState& s = add(amendment, lock);
-
489 
-
490  s.name = name;
-
491  s.supported = true;
-
492  switch (votebehavior)
-
493  {
-
494  case VoteBehavior::DefaultYes:
-
495  s.vote = AmendmentVote::up;
-
496  break;
-
497 
-
498  case VoteBehavior::DefaultNo:
-
499  s.vote = AmendmentVote::down;
-
500  break;
-
501 
-
502  case VoteBehavior::Obsolete:
-
503  s.vote = AmendmentVote::obsolete;
-
504  break;
-
505  }
-
506 
-
507  JLOG(j_.debug()) << "Amendment " << amendment << " (" << s.name
-
508  << ") is supported and will be "
-
509  << (s.vote == AmendmentVote::up ? "up" : "down")
-
510  << " voted by default if not enabled on the ledger.";
-
511  }
-
512 
-
513  hash_set<uint256> detect_conflict;
-
514  // Parse enabled amendments from config
-
515  for (std::pair<uint256, std::string> const& a : parseSection(enabled))
-
516  {
-
517  if (featureVotesExist)
-
518  { // If the table existed, warn about duplicate config info
-
519  JLOG(j_.warn()) << "[amendments] section in config file ignored"
-
520  " in favor of data in db/wallet.db.";
-
521  break;
-
522  }
-
523  else
-
524  { // Otherwise transfer config data into the table
-
525  detect_conflict.insert(a.first);
-
526  persistVote(a.first, a.second, AmendmentVote::up);
-
527  }
-
528  }
-
529 
-
530  // Parse vetoed amendments from config
-
531  for (auto const& a : parseSection(vetoed))
-
532  {
-
533  if (featureVotesExist)
-
534  { // If the table existed, warn about duplicate config info
-
535  JLOG(j_.warn())
-
536  << "[veto_amendments] section in config file ignored"
-
537  " in favor of data in db/wallet.db.";
-
538  break;
-
539  }
-
540  else
-
541  { // Otherwise transfer config data into the table
-
542  if (detect_conflict.count(a.first) == 0)
-
543  {
-
544  persistVote(a.first, a.second, AmendmentVote::down);
-
545  }
-
546  else
-
547  {
-
548  JLOG(j_.warn())
-
549  << "[veto_amendments] section in config has amendment "
-
550  << '(' << a.first << ", " << a.second
-
551  << ") both [veto_amendments] and [amendments].";
-
552  }
-
553  }
-
554  }
-
555 
-
556  // Read amendment votes from wallet.db
-
557  auto db = db_.checkoutDb();
-
558  readAmendments(
-
559  *db,
-
560  [&](boost::optional<std::string> amendment_hash,
-
561  boost::optional<std::string> amendment_name,
-
562  boost::optional<AmendmentVote> vote) {
-
563  uint256 amend_hash;
-
564  if (!amendment_hash || !amendment_name || !vote)
-
565  {
-
566  // These fields should never have nulls, but check
-
567  Throw<std::runtime_error>(
-
568  "Invalid FeatureVotes row in wallet.db");
-
569  }
-
570  if (!amend_hash.parseHex(*amendment_hash))
-
571  {
-
572  Throw<std::runtime_error>(
-
573  "Invalid amendment ID '" + *amendment_hash +
-
574  " in wallet.db");
-
575  }
-
576  if (*vote == AmendmentVote::down)
-
577  {
-
578  // Unknown amendments are effectively vetoed already
-
579  if (auto s = get(amend_hash, lock))
-
580  {
-
581  JLOG(j_.info()) << "Amendment {" << *amendment_name << ", "
-
582  << amend_hash << "} is downvoted.";
-
583  if (!amendment_name->empty())
-
584  s->name = *amendment_name;
-
585  // An obsolete amendment's vote can never be changed
-
586  if (s->vote != AmendmentVote::obsolete)
-
587  s->vote = *vote;
-
588  }
-
589  }
-
590  else // up-vote
-
591  {
-
592  AmendmentState& s = add(amend_hash, lock);
-
593 
-
594  JLOG(j_.debug()) << "Amendment {" << *amendment_name << ", "
-
595  << amend_hash << "} is upvoted.";
-
596  if (!amendment_name->empty())
-
597  s.name = *amendment_name;
-
598  // An obsolete amendment's vote can never be changed
-
599  if (s.vote != AmendmentVote::obsolete)
-
600  s.vote = *vote;
-
601  }
-
602  });
-
603 }
-
604 
-
605 AmendmentState&
-
606 AmendmentTableImpl::add(
-
607  uint256 const& amendmentHash,
-
608  std::lock_guard<std::mutex> const&)
-
609 {
-
610  // call with the mutex held
-
611  return amendmentMap_[amendmentHash];
-
612 }
-
613 
-
614 AmendmentState*
-
615 AmendmentTableImpl::get(
-
616  uint256 const& amendmentHash,
-
617  std::lock_guard<std::mutex> const& lock)
-
618 {
-
619  // Forward to the const version of get.
-
620  return const_cast<AmendmentState*>(
-
621  std::as_const(*this).get(amendmentHash, lock));
-
622 }
-
623 
-
624 AmendmentState const*
-
625 AmendmentTableImpl::get(
-
626  uint256 const& amendmentHash,
-
627  std::lock_guard<std::mutex> const&) const
-
628 {
-
629  // call with the mutex held
-
630  auto ret = amendmentMap_.find(amendmentHash);
-
631 
-
632  if (ret == amendmentMap_.end())
-
633  return nullptr;
-
634 
-
635  return &ret->second;
-
636 }
-
637 
-
638 uint256
-
639 AmendmentTableImpl::find(std::string const& name) const
-
640 {
-
641  std::lock_guard lock(mutex_);
-
642 
-
643  for (auto const& e : amendmentMap_)
-
644  {
-
645  if (name == e.second.name)
-
646  return e.first;
-
647  }
-
648 
-
649  return {};
-
650 }
-
651 
-
652 void
-
653 AmendmentTableImpl::persistVote(
-
654  uint256 const& amendment,
-
655  std::string const& name,
-
656  AmendmentVote vote) const
-
657 {
-
658  assert(vote != AmendmentVote::obsolete);
-
659  auto db = db_.checkoutDb();
-
660  voteAmendment(*db, amendment, name, vote);
-
661 }
-
662 
-
663 bool
-
664 AmendmentTableImpl::veto(uint256 const& amendment)
-
665 {
-
666  std::lock_guard lock(mutex_);
-
667  AmendmentState& s = add(amendment, lock);
-
668 
-
669  if (s.vote != AmendmentVote::up)
-
670  return false;
-
671  s.vote = AmendmentVote::down;
-
672  persistVote(amendment, s.name, s.vote);
-
673  return true;
-
674 }
-
675 
-
676 bool
-
677 AmendmentTableImpl::unVeto(uint256 const& amendment)
-
678 {
-
679  std::lock_guard lock(mutex_);
-
680  AmendmentState* const s = get(amendment, lock);
-
681 
-
682  if (!s || s->vote != AmendmentVote::down)
-
683  return false;
-
684  s->vote = AmendmentVote::up;
-
685  persistVote(amendment, s->name, s->vote);
-
686  return true;
-
687 }
-
688 
-
689 bool
-
690 AmendmentTableImpl::enable(uint256 const& amendment)
-
691 {
-
692  std::lock_guard lock(mutex_);
-
693  AmendmentState& s = add(amendment, lock);
-
694 
-
695  if (s.enabled)
-
696  return false;
-
697 
-
698  s.enabled = true;
-
699 
-
700  if (!s.supported)
-
701  {
-
702  JLOG(j_.error()) << "Unsupported amendment " << amendment
-
703  << " activated.";
-
704  unsupportedEnabled_ = true;
-
705  }
-
706 
-
707  return true;
-
708 }
-
709 
-
710 bool
-
711 AmendmentTableImpl::isEnabled(uint256 const& amendment) const
-
712 {
-
713  std::lock_guard lock(mutex_);
-
714  AmendmentState const* s = get(amendment, lock);
-
715  return s && s->enabled;
-
716 }
-
717 
-
718 bool
-
719 AmendmentTableImpl::isSupported(uint256 const& amendment) const
-
720 {
-
721  std::lock_guard lock(mutex_);
-
722  AmendmentState const* s = get(amendment, lock);
-
723  return s && s->supported;
-
724 }
-
725 
-
726 bool
-
727 AmendmentTableImpl::hasUnsupportedEnabled() const
-
728 {
-
729  std::lock_guard lock(mutex_);
-
730  return unsupportedEnabled_;
-
731 }
-
732 
-
733 std::optional<NetClock::time_point>
-
734 AmendmentTableImpl::firstUnsupportedExpected() const
-
735 {
-
736  std::lock_guard lock(mutex_);
-
737  return firstUnsupportedExpected_;
-
738 }
-
739 
-
740 std::vector<uint256>
-
741 AmendmentTableImpl::doValidation(std::set<uint256> const& enabled) const
-
742 {
-
743  // Get the list of amendments we support and do not
-
744  // veto, but that are not already enabled
-
745  std::vector<uint256> amendments;
-
746 
-
747  {
-
748  std::lock_guard lock(mutex_);
-
749  amendments.reserve(amendmentMap_.size());
-
750  for (auto const& e : amendmentMap_)
-
751  {
-
752  if (e.second.supported && e.second.vote == AmendmentVote::up &&
-
753  (enabled.count(e.first) == 0))
-
754  {
-
755  amendments.push_back(e.first);
-
756  JLOG(j_.info()) << "Voting for amendment " << e.second.name;
-
757  }
-
758  }
-
759  }
-
760 
-
761  if (!amendments.empty())
-
762  std::sort(amendments.begin(), amendments.end());
-
763 
-
764  return amendments;
-
765 }
-
766 
-
767 std::vector<uint256>
-
768 AmendmentTableImpl::getDesired() const
-
769 {
-
770  // Get the list of amendments we support and do not veto
-
771  return doValidation({});
-
772 }
-
773 
-
774 std::map<uint256, std::uint32_t>
-
775 AmendmentTableImpl::doVoting(
-
776  Rules const& rules,
-
777  NetClock::time_point closeTime,
-
778  std::set<uint256> const& enabledAmendments,
-
779  majorityAmendments_t const& majorityAmendments,
-
780  std::vector<std::shared_ptr<STValidation>> const& valSet)
-
781 {
-
782  JLOG(j_.trace()) << "voting at " << closeTime.time_since_epoch().count()
-
783  << ": " << enabledAmendments.size() << ", "
-
784  << majorityAmendments.size() << ", " << valSet.size();
-
785 
-
786  std::lock_guard lock(mutex_);
-
787 
-
788  // Keep a record of the votes we received.
-
789  previousTrustedVotes_.recordVotes(rules, valSet, closeTime, lock);
-
790 
-
791  // Tally the most recent votes.
-
792  auto vote =
-
793  std::make_unique<AmendmentSet>(rules, previousTrustedVotes_, lock);
-
794  JLOG(j_.debug()) << "Received " << vote->trustedValidations()
-
795  << " trusted validations, threshold is: "
-
796  << vote->threshold();
-
797 
-
798  // Map of amendments to the action to be taken for each one. The action is
-
799  // the value of the flags in the pseudo-transaction
-
800  std::map<uint256, std::uint32_t> actions;
-
801 
-
802  // process all amendments we know of
-
803  for (auto const& entry : amendmentMap_)
-
804  {
-
805  NetClock::time_point majorityTime = {};
-
806 
-
807  bool const hasValMajority = vote->passes(entry.first);
-
808 
-
809  {
-
810  auto const it = majorityAmendments.find(entry.first);
-
811  if (it != majorityAmendments.end())
-
812  majorityTime = it->second;
-
813  }
-
814 
-
815  if (enabledAmendments.count(entry.first) != 0)
-
816  {
-
817  JLOG(j_.debug()) << entry.first << ": amendment already enabled";
-
818  }
-
819  else if (
-
820  hasValMajority && (majorityTime == NetClock::time_point{}) &&
-
821  entry.second.vote == AmendmentVote::up)
-
822  {
-
823  // Ledger says no majority, validators say yes
-
824  JLOG(j_.debug()) << entry.first << ": amendment got majority";
-
825  actions[entry.first] = tfGotMajority;
-
826  }
-
827  else if (!hasValMajority && (majorityTime != NetClock::time_point{}))
-
828  {
-
829  // Ledger says majority, validators say no
-
830  JLOG(j_.debug()) << entry.first << ": amendment lost majority";
-
831  actions[entry.first] = tfLostMajority;
-
832  }
-
833  else if (
-
834  (majorityTime != NetClock::time_point{}) &&
-
835  ((majorityTime + majorityTime_) <= closeTime) &&
-
836  entry.second.vote == AmendmentVote::up)
-
837  {
-
838  // Ledger says majority held
-
839  JLOG(j_.debug()) << entry.first << ": amendment majority held";
-
840  actions[entry.first] = 0;
-
841  }
-
842  }
-
843 
-
844  // Stash for reporting
-
845  lastVote_ = std::move(vote);
-
846  return actions;
-
847 }
-
848 
-
849 bool
-
850 AmendmentTableImpl::needValidatedLedger(LedgerIndex ledgerSeq) const
-
851 {
-
852  std::lock_guard lock(mutex_);
-
853 
-
854  // Is there a ledger in which an amendment could have been enabled
-
855  // between these two ledger sequences?
-
856 
-
857  return ((ledgerSeq - 1) / 256) != ((lastUpdateSeq_ - 1) / 256);
-
858 }
-
859 
-
860 void
-
861 AmendmentTableImpl::doValidatedLedger(
-
862  LedgerIndex ledgerSeq,
-
863  std::set<uint256> const& enabled,
-
864  majorityAmendments_t const& majority)
-
865 {
-
866  for (auto& e : enabled)
-
867  enable(e);
-
868 
-
869  std::lock_guard lock(mutex_);
-
870 
-
871  // Remember the ledger sequence of this update.
-
872  lastUpdateSeq_ = ledgerSeq;
-
873 
-
874  // Since we have the whole list in `majority`, reset the time flag, even
-
875  // if it's currently set. If it's not set when the loop is done, then any
-
876  // prior unknown amendments have lost majority.
-
877  firstUnsupportedExpected_.reset();
-
878  for (auto const& [hash, time] : majority)
-
879  {
-
880  AmendmentState& s = add(hash, lock);
-
881 
-
882  if (s.enabled)
-
883  continue;
-
884 
-
885  if (!s.supported)
-
886  {
-
887  JLOG(j_.info()) << "Unsupported amendment " << hash
-
888  << " reached majority at " << to_string(time);
-
889  if (!firstUnsupportedExpected_ || firstUnsupportedExpected_ > time)
-
890  firstUnsupportedExpected_ = time;
-
891  }
-
892  }
-
893  if (firstUnsupportedExpected_)
-
894  firstUnsupportedExpected_ = *firstUnsupportedExpected_ + majorityTime_;
-
895 }
-
896 
-
897 void
-
898 AmendmentTableImpl::trustChanged(hash_set<PublicKey> const& allTrusted)
-
899 {
-
900  std::lock_guard lock(mutex_);
-
901  previousTrustedVotes_.trustChanged(allTrusted, lock);
-
902 }
-
903 
-
904 void
-
905 AmendmentTableImpl::injectJson(
-
906  Json::Value& v,
-
907  const uint256& id,
-
908  const AmendmentState& fs,
-
909  std::lock_guard<std::mutex> const&) const
-
910 {
-
911  if (!fs.name.empty())
-
912  v[jss::name] = fs.name;
-
913 
-
914  v[jss::supported] = fs.supported;
-
915  if (!fs.enabled)
-
916  {
-
917  if (fs.vote == AmendmentVote::obsolete)
-
918  v[jss::vetoed] = "Obsolete";
-
919  else
-
920  v[jss::vetoed] = fs.vote == AmendmentVote::down;
-
921  }
-
922  v[jss::enabled] = fs.enabled;
-
923 
-
924  if (!fs.enabled && lastVote_)
-
925  {
-
926  auto const votesTotal = lastVote_->trustedValidations();
-
927  auto const votesNeeded = lastVote_->threshold();
-
928  auto const votesFor = lastVote_->votes(id);
-
929 
-
930  v[jss::count] = votesFor;
-
931  v[jss::validations] = votesTotal;
-
932 
-
933  if (votesNeeded)
-
934  v[jss::threshold] = votesNeeded;
-
935  }
-
936 }
-
937 
-
938 Json::Value
-
939 AmendmentTableImpl::getJson() const
-
940 {
-
941  Json::Value ret(Json::objectValue);
-
942  {
-
943  std::lock_guard lock(mutex_);
-
944  for (auto const& e : amendmentMap_)
-
945  {
-
946  injectJson(
-
947  ret[to_string(e.first)] = Json::objectValue,
-
948  e.first,
-
949  e.second,
-
950  lock);
-
951  }
-
952  }
-
953  return ret;
-
954 }
-
955 
-
956 Json::Value
-
957 AmendmentTableImpl::getJson(uint256 const& amendmentID) const
-
958 {
-
959  Json::Value ret = Json::objectValue;
-
960  Json::Value& jAmendment = (ret[to_string(amendmentID)] = Json::objectValue);
-
961 
-
962  {
-
963  std::lock_guard lock(mutex_);
-
964  AmendmentState const* a = get(amendmentID, lock);
-
965  if (a)
-
966  injectJson(jAmendment, amendmentID, *a, lock);
-
967  }
-
968 
-
969  return ret;
-
970 }
-
971 
-
972 std::unique_ptr<AmendmentTable>
-
973 make_AmendmentTable(
-
974  Application& app,
-
975  std::chrono::seconds majorityTime,
-
976  std::vector<AmendmentTable::FeatureInfo> const& supported,
-
977  Section const& enabled,
-
978  Section const& vetoed,
-
979  beast::Journal journal)
-
980 {
-
981  return std::make_unique<AmendmentTableImpl>(
-
982  app, majorityTime, supported, enabled, vetoed, journal);
-
983 }
-
984 
-
985 } // namespace ripple
+
391  bool isAdmin,
+
392  std::lock_guard<std::mutex> const& lock) const;
+
393 
+
394  void
+
395  persistVote(
+
396  uint256 const& amendment,
+
397  std::string const& name,
+
398  AmendmentVote vote) const;
+
399 
+
400 public:
+
401  AmendmentTableImpl(
+
402  Application& app,
+
403  std::chrono::seconds majorityTime,
+
404  std::vector<FeatureInfo> const& supported,
+
405  Section const& enabled,
+
406  Section const& vetoed,
+
407  beast::Journal journal);
+
408 
+
409  uint256
+
410  find(std::string const& name) const override;
+
411 
+
412  bool
+
413  veto(uint256 const& amendment) override;
+
414  bool
+
415  unVeto(uint256 const& amendment) override;
+
416 
+
417  bool
+
418  enable(uint256 const& amendment) override;
+
419 
+
420  bool
+
421  isEnabled(uint256 const& amendment) const override;
+
422  bool
+
423  isSupported(uint256 const& amendment) const override;
+
424 
+
425  bool
+
426  hasUnsupportedEnabled() const override;
+
427 
+
428  std::optional<NetClock::time_point>
+
429  firstUnsupportedExpected() const override;
+
430 
+
431  Json::Value
+
432  getJson(bool isAdmin) const override;
+
433  Json::Value
+
434  getJson(uint256 const&, bool isAdmin) const override;
+
435 
+
436  bool
+
437  needValidatedLedger(LedgerIndex seq) const override;
+
438 
+
439  void
+
440  doValidatedLedger(
+
441  LedgerIndex seq,
+
442  std::set<uint256> const& enabled,
+
443  majorityAmendments_t const& majority) override;
+
444 
+
445  void
+
446  trustChanged(hash_set<PublicKey> const& allTrusted) override;
+
447 
+
448  std::vector<uint256>
+
449  doValidation(std::set<uint256> const& enabledAmendments) const override;
+
450 
+
451  std::vector<uint256>
+
452  getDesired() const override;
+
453 
+
454  std::map<uint256, std::uint32_t>
+
455  doVoting(
+
456  Rules const& rules,
+
457  NetClock::time_point closeTime,
+
458  std::set<uint256> const& enabledAmendments,
+
459  majorityAmendments_t const& majorityAmendments,
+
460  std::vector<std::shared_ptr<STValidation>> const& validations) override;
+
461 };
+
462 
+
463 //------------------------------------------------------------------------------
+
464 
+
465 AmendmentTableImpl::AmendmentTableImpl(
+
466  Application& app,
+
467  std::chrono::seconds majorityTime,
+
468  std::vector<FeatureInfo> const& supported,
+
469  Section const& enabled,
+
470  Section const& vetoed,
+
471  beast::Journal journal)
+
472  : lastUpdateSeq_(0)
+
473  , majorityTime_(majorityTime)
+
474  , unsupportedEnabled_(false)
+
475  , j_(journal)
+
476  , db_(app.getWalletDB())
+
477 {
+
478  std::lock_guard lock(mutex_);
+
479 
+
480  // Find out if the FeatureVotes table exists in WalletDB
+
481  bool const featureVotesExist = [this]() {
+
482  auto db = db_.checkoutDb();
+
483  return createFeatureVotes(*db);
+
484  }();
+
485 
+
486  // Parse supported amendments
+
487  for (auto const& [name, amendment, votebehavior] : supported)
+
488  {
+
489  AmendmentState& s = add(amendment, lock);
+
490 
+
491  s.name = name;
+
492  s.supported = true;
+
493  switch (votebehavior)
+
494  {
+
495  case VoteBehavior::DefaultYes:
+
496  s.vote = AmendmentVote::up;
+
497  break;
+
498 
+
499  case VoteBehavior::DefaultNo:
+
500  s.vote = AmendmentVote::down;
+
501  break;
+
502 
+
503  case VoteBehavior::Obsolete:
+
504  s.vote = AmendmentVote::obsolete;
+
505  break;
+
506  }
+
507 
+
508  JLOG(j_.debug()) << "Amendment " << amendment << " (" << s.name
+
509  << ") is supported and will be "
+
510  << (s.vote == AmendmentVote::up ? "up" : "down")
+
511  << " voted by default if not enabled on the ledger.";
+
512  }
+
513 
+
514  hash_set<uint256> detect_conflict;
+
515  // Parse enabled amendments from config
+
516  for (std::pair<uint256, std::string> const& a : parseSection(enabled))
+
517  {
+
518  if (featureVotesExist)
+
519  { // If the table existed, warn about duplicate config info
+
520  JLOG(j_.warn()) << "[amendments] section in config file ignored"
+
521  " in favor of data in db/wallet.db.";
+
522  break;
+
523  }
+
524  else
+
525  { // Otherwise transfer config data into the table
+
526  detect_conflict.insert(a.first);
+
527  persistVote(a.first, a.second, AmendmentVote::up);
+
528  }
+
529  }
+
530 
+
531  // Parse vetoed amendments from config
+
532  for (auto const& a : parseSection(vetoed))
+
533  {
+
534  if (featureVotesExist)
+
535  { // If the table existed, warn about duplicate config info
+
536  JLOG(j_.warn())
+
537  << "[veto_amendments] section in config file ignored"
+
538  " in favor of data in db/wallet.db.";
+
539  break;
+
540  }
+
541  else
+
542  { // Otherwise transfer config data into the table
+
543  if (detect_conflict.count(a.first) == 0)
+
544  {
+
545  persistVote(a.first, a.second, AmendmentVote::down);
+
546  }
+
547  else
+
548  {
+
549  JLOG(j_.warn())
+
550  << "[veto_amendments] section in config has amendment "
+
551  << '(' << a.first << ", " << a.second
+
552  << ") both [veto_amendments] and [amendments].";
+
553  }
+
554  }
+
555  }
+
556 
+
557  // Read amendment votes from wallet.db
+
558  auto db = db_.checkoutDb();
+
559  readAmendments(
+
560  *db,
+
561  [&](boost::optional<std::string> amendment_hash,
+
562  boost::optional<std::string> amendment_name,
+
563  boost::optional<AmendmentVote> vote) {
+
564  uint256 amend_hash;
+
565  if (!amendment_hash || !amendment_name || !vote)
+
566  {
+
567  // These fields should never have nulls, but check
+
568  Throw<std::runtime_error>(
+
569  "Invalid FeatureVotes row in wallet.db");
+
570  }
+
571  if (!amend_hash.parseHex(*amendment_hash))
+
572  {
+
573  Throw<std::runtime_error>(
+
574  "Invalid amendment ID '" + *amendment_hash +
+
575  " in wallet.db");
+
576  }
+
577  if (*vote == AmendmentVote::down)
+
578  {
+
579  // Unknown amendments are effectively vetoed already
+
580  if (auto s = get(amend_hash, lock))
+
581  {
+
582  JLOG(j_.info()) << "Amendment {" << *amendment_name << ", "
+
583  << amend_hash << "} is downvoted.";
+
584  if (!amendment_name->empty())
+
585  s->name = *amendment_name;
+
586  // An obsolete amendment's vote can never be changed
+
587  if (s->vote != AmendmentVote::obsolete)
+
588  s->vote = *vote;
+
589  }
+
590  }
+
591  else // up-vote
+
592  {
+
593  AmendmentState& s = add(amend_hash, lock);
+
594 
+
595  JLOG(j_.debug()) << "Amendment {" << *amendment_name << ", "
+
596  << amend_hash << "} is upvoted.";
+
597  if (!amendment_name->empty())
+
598  s.name = *amendment_name;
+
599  // An obsolete amendment's vote can never be changed
+
600  if (s.vote != AmendmentVote::obsolete)
+
601  s.vote = *vote;
+
602  }
+
603  });
+
604 }
+
605 
+
606 AmendmentState&
+
607 AmendmentTableImpl::add(
+
608  uint256 const& amendmentHash,
+
609  std::lock_guard<std::mutex> const&)
+
610 {
+
611  // call with the mutex held
+
612  return amendmentMap_[amendmentHash];
+
613 }
+
614 
+
615 AmendmentState*
+
616 AmendmentTableImpl::get(
+
617  uint256 const& amendmentHash,
+
618  std::lock_guard<std::mutex> const& lock)
+
619 {
+
620  // Forward to the const version of get.
+
621  return const_cast<AmendmentState*>(
+
622  std::as_const(*this).get(amendmentHash, lock));
+
623 }
+
624 
+
625 AmendmentState const*
+
626 AmendmentTableImpl::get(
+
627  uint256 const& amendmentHash,
+
628  std::lock_guard<std::mutex> const&) const
+
629 {
+
630  // call with the mutex held
+
631  auto ret = amendmentMap_.find(amendmentHash);
+
632 
+
633  if (ret == amendmentMap_.end())
+
634  return nullptr;
+
635 
+
636  return &ret->second;
+
637 }
+
638 
+
639 uint256
+
640 AmendmentTableImpl::find(std::string const& name) const
+
641 {
+
642  std::lock_guard lock(mutex_);
+
643 
+
644  for (auto const& e : amendmentMap_)
+
645  {
+
646  if (name == e.second.name)
+
647  return e.first;
+
648  }
+
649 
+
650  return {};
+
651 }
+
652 
+
653 void
+
654 AmendmentTableImpl::persistVote(
+
655  uint256 const& amendment,
+
656  std::string const& name,
+
657  AmendmentVote vote) const
+
658 {
+
659  assert(vote != AmendmentVote::obsolete);
+
660  auto db = db_.checkoutDb();
+
661  voteAmendment(*db, amendment, name, vote);
+
662 }
+
663 
+
664 bool
+
665 AmendmentTableImpl::veto(uint256 const& amendment)
+
666 {
+
667  std::lock_guard lock(mutex_);
+
668  AmendmentState& s = add(amendment, lock);
+
669 
+
670  if (s.vote != AmendmentVote::up)
+
671  return false;
+
672  s.vote = AmendmentVote::down;
+
673  persistVote(amendment, s.name, s.vote);
+
674  return true;
+
675 }
+
676 
+
677 bool
+
678 AmendmentTableImpl::unVeto(uint256 const& amendment)
+
679 {
+
680  std::lock_guard lock(mutex_);
+
681  AmendmentState* const s = get(amendment, lock);
+
682 
+
683  if (!s || s->vote != AmendmentVote::down)
+
684  return false;
+
685  s->vote = AmendmentVote::up;
+
686  persistVote(amendment, s->name, s->vote);
+
687  return true;
+
688 }
+
689 
+
690 bool
+
691 AmendmentTableImpl::enable(uint256 const& amendment)
+
692 {
+
693  std::lock_guard lock(mutex_);
+
694  AmendmentState& s = add(amendment, lock);
+
695 
+
696  if (s.enabled)
+
697  return false;
+
698 
+
699  s.enabled = true;
+
700 
+
701  if (!s.supported)
+
702  {
+
703  JLOG(j_.error()) << "Unsupported amendment " << amendment
+
704  << " activated.";
+
705  unsupportedEnabled_ = true;
+
706  }
+
707 
+
708  return true;
+
709 }
+
710 
+
711 bool
+
712 AmendmentTableImpl::isEnabled(uint256 const& amendment) const
+
713 {
+
714  std::lock_guard lock(mutex_);
+
715  AmendmentState const* s = get(amendment, lock);
+
716  return s && s->enabled;
+
717 }
+
718 
+
719 bool
+
720 AmendmentTableImpl::isSupported(uint256 const& amendment) const
+
721 {
+
722  std::lock_guard lock(mutex_);
+
723  AmendmentState const* s = get(amendment, lock);
+
724  return s && s->supported;
+
725 }
+
726 
+
727 bool
+
728 AmendmentTableImpl::hasUnsupportedEnabled() const
+
729 {
+
730  std::lock_guard lock(mutex_);
+
731  return unsupportedEnabled_;
+
732 }
+
733 
+
734 std::optional<NetClock::time_point>
+
735 AmendmentTableImpl::firstUnsupportedExpected() const
+
736 {
+
737  std::lock_guard lock(mutex_);
+
738  return firstUnsupportedExpected_;
+
739 }
+
740 
+
741 std::vector<uint256>
+
742 AmendmentTableImpl::doValidation(std::set<uint256> const& enabled) const
+
743 {
+
744  // Get the list of amendments we support and do not
+
745  // veto, but that are not already enabled
+
746  std::vector<uint256> amendments;
+
747 
+
748  {
+
749  std::lock_guard lock(mutex_);
+
750  amendments.reserve(amendmentMap_.size());
+
751  for (auto const& e : amendmentMap_)
+
752  {
+
753  if (e.second.supported && e.second.vote == AmendmentVote::up &&
+
754  (enabled.count(e.first) == 0))
+
755  {
+
756  amendments.push_back(e.first);
+
757  JLOG(j_.info()) << "Voting for amendment " << e.second.name;
+
758  }
+
759  }
+
760  }
+
761 
+
762  if (!amendments.empty())
+
763  std::sort(amendments.begin(), amendments.end());
+
764 
+
765  return amendments;
+
766 }
+
767 
+
768 std::vector<uint256>
+
769 AmendmentTableImpl::getDesired() const
+
770 {
+
771  // Get the list of amendments we support and do not veto
+
772  return doValidation({});
+
773 }
+
774 
+
775 std::map<uint256, std::uint32_t>
+
776 AmendmentTableImpl::doVoting(
+
777  Rules const& rules,
+
778  NetClock::time_point closeTime,
+
779  std::set<uint256> const& enabledAmendments,
+
780  majorityAmendments_t const& majorityAmendments,
+
781  std::vector<std::shared_ptr<STValidation>> const& valSet)
+
782 {
+
783  JLOG(j_.trace()) << "voting at " << closeTime.time_since_epoch().count()
+
784  << ": " << enabledAmendments.size() << ", "
+
785  << majorityAmendments.size() << ", " << valSet.size();
+
786 
+
787  std::lock_guard lock(mutex_);
+
788 
+
789  // Keep a record of the votes we received.
+
790  previousTrustedVotes_.recordVotes(rules, valSet, closeTime, lock);
+
791 
+
792  // Tally the most recent votes.
+
793  auto vote =
+
794  std::make_unique<AmendmentSet>(rules, previousTrustedVotes_, lock);
+
795  JLOG(j_.debug()) << "Received " << vote->trustedValidations()
+
796  << " trusted validations, threshold is: "
+
797  << vote->threshold();
+
798 
+
799  // Map of amendments to the action to be taken for each one. The action is
+
800  // the value of the flags in the pseudo-transaction
+
801  std::map<uint256, std::uint32_t> actions;
+
802 
+
803  // process all amendments we know of
+
804  for (auto const& entry : amendmentMap_)
+
805  {
+
806  NetClock::time_point majorityTime = {};
+
807 
+
808  bool const hasValMajority = vote->passes(entry.first);
+
809 
+
810  {
+
811  auto const it = majorityAmendments.find(entry.first);
+
812  if (it != majorityAmendments.end())
+
813  majorityTime = it->second;
+
814  }
+
815 
+
816  if (enabledAmendments.count(entry.first) != 0)
+
817  {
+
818  JLOG(j_.debug()) << entry.first << ": amendment already enabled";
+
819  }
+
820  else if (
+
821  hasValMajority && (majorityTime == NetClock::time_point{}) &&
+
822  entry.second.vote == AmendmentVote::up)
+
823  {
+
824  // Ledger says no majority, validators say yes
+
825  JLOG(j_.debug()) << entry.first << ": amendment got majority";
+
826  actions[entry.first] = tfGotMajority;
+
827  }
+
828  else if (!hasValMajority && (majorityTime != NetClock::time_point{}))
+
829  {
+
830  // Ledger says majority, validators say no
+
831  JLOG(j_.debug()) << entry.first << ": amendment lost majority";
+
832  actions[entry.first] = tfLostMajority;
+
833  }
+
834  else if (
+
835  (majorityTime != NetClock::time_point{}) &&
+
836  ((majorityTime + majorityTime_) <= closeTime) &&
+
837  entry.second.vote == AmendmentVote::up)
+
838  {
+
839  // Ledger says majority held
+
840  JLOG(j_.debug()) << entry.first << ": amendment majority held";
+
841  actions[entry.first] = 0;
+
842  }
+
843  }
+
844 
+
845  // Stash for reporting
+
846  lastVote_ = std::move(vote);
+
847  return actions;
+
848 }
+
849 
+
850 bool
+
851 AmendmentTableImpl::needValidatedLedger(LedgerIndex ledgerSeq) const
+
852 {
+
853  std::lock_guard lock(mutex_);
+
854 
+
855  // Is there a ledger in which an amendment could have been enabled
+
856  // between these two ledger sequences?
+
857 
+
858  return ((ledgerSeq - 1) / 256) != ((lastUpdateSeq_ - 1) / 256);
+
859 }
+
860 
+
861 void
+
862 AmendmentTableImpl::doValidatedLedger(
+
863  LedgerIndex ledgerSeq,
+
864  std::set<uint256> const& enabled,
+
865  majorityAmendments_t const& majority)
+
866 {
+
867  for (auto& e : enabled)
+
868  enable(e);
+
869 
+
870  std::lock_guard lock(mutex_);
+
871 
+
872  // Remember the ledger sequence of this update.
+
873  lastUpdateSeq_ = ledgerSeq;
+
874 
+
875  // Since we have the whole list in `majority`, reset the time flag, even
+
876  // if it's currently set. If it's not set when the loop is done, then any
+
877  // prior unknown amendments have lost majority.
+
878  firstUnsupportedExpected_.reset();
+
879  for (auto const& [hash, time] : majority)
+
880  {
+
881  AmendmentState& s = add(hash, lock);
+
882 
+
883  if (s.enabled)
+
884  continue;
+
885 
+
886  if (!s.supported)
+
887  {
+
888  JLOG(j_.info()) << "Unsupported amendment " << hash
+
889  << " reached majority at " << to_string(time);
+
890  if (!firstUnsupportedExpected_ || firstUnsupportedExpected_ > time)
+
891  firstUnsupportedExpected_ = time;
+
892  }
+
893  }
+
894  if (firstUnsupportedExpected_)
+
895  firstUnsupportedExpected_ = *firstUnsupportedExpected_ + majorityTime_;
+
896 }
+
897 
+
898 void
+
899 AmendmentTableImpl::trustChanged(hash_set<PublicKey> const& allTrusted)
+
900 {
+
901  std::lock_guard lock(mutex_);
+
902  previousTrustedVotes_.trustChanged(allTrusted, lock);
+
903 }
+
904 
+
905 void
+
906 AmendmentTableImpl::injectJson(
+
907  Json::Value& v,
+
908  const uint256& id,
+
909  const AmendmentState& fs,
+
910  bool isAdmin,
+
911  std::lock_guard<std::mutex> const&) const
+
912 {
+
913  if (!fs.name.empty())
+
914  v[jss::name] = fs.name;
+
915 
+
916  v[jss::supported] = fs.supported;
+
917  if (!fs.enabled && isAdmin)
+
918  {
+
919  if (fs.vote == AmendmentVote::obsolete)
+
920  v[jss::vetoed] = "Obsolete";
+
921  else
+
922  v[jss::vetoed] = fs.vote == AmendmentVote::down;
+
923  }
+
924  v[jss::enabled] = fs.enabled;
+
925 
+
926  if (!fs.enabled && lastVote_ && isAdmin)
+
927  {
+
928  auto const votesTotal = lastVote_->trustedValidations();
+
929  auto const votesNeeded = lastVote_->threshold();
+
930  auto const votesFor = lastVote_->votes(id);
+
931 
+
932  v[jss::count] = votesFor;
+
933  v[jss::validations] = votesTotal;
+
934 
+
935  if (votesNeeded)
+
936  v[jss::threshold] = votesNeeded;
+
937  }
+
938 }
+
939 
+
940 Json::Value
+
941 AmendmentTableImpl::getJson(bool isAdmin) const
+
942 {
+
943  Json::Value ret(Json::objectValue);
+
944  {
+
945  std::lock_guard lock(mutex_);
+
946  for (auto const& e : amendmentMap_)
+
947  {
+
948  injectJson(
+
949  ret[to_string(e.first)] = Json::objectValue,
+
950  e.first,
+
951  e.second,
+
952  isAdmin,
+
953  lock);
+
954  }
+
955  }
+
956  return ret;
+
957 }
+
958 
+
959 Json::Value
+
960 AmendmentTableImpl::getJson(uint256 const& amendmentID, bool isAdmin) const
+
961 {
+
962  Json::Value ret = Json::objectValue;
+
963 
+
964  {
+
965  std::lock_guard lock(mutex_);
+
966  AmendmentState const* a = get(amendmentID, lock);
+
967  if (a)
+
968  {
+
969  Json::Value& jAmendment =
+
970  (ret[to_string(amendmentID)] = Json::objectValue);
+
971  injectJson(jAmendment, amendmentID, *a, isAdmin, lock);
+
972  }
+
973  }
+
974 
+
975  return ret;
+
976 }
+
977 
+
978 std::unique_ptr<AmendmentTable>
+
979 make_AmendmentTable(
+
980  Application& app,
+
981  std::chrono::seconds majorityTime,
+
982  std::vector<AmendmentTable::FeatureInfo> const& supported,
+
983  Section const& enabled,
+
984  Section const& vetoed,
+
985  beast::Journal journal)
+
986 {
+
987  return std::make_unique<AmendmentTableImpl>(
+
988  app, majorityTime, supported, enabled, vetoed, journal);
+
989 }
+
990 
+
991 } // namespace ripple
+
ripple::isAdmin
bool isAdmin(Port const &port, Json::Value const &params, beast::IP::Address const &remoteIp)
Definition: Role.cpp:84
ripple::tfGotMajority
constexpr std::uint32_t tfGotMajority
Definition: TxFlags.h:119
ripple::Section
Holds a collection of configuration values.
Definition: BasicConfig.h:42
ripple::Application
Definition: Application.h:116
@@ -1036,24 +1043,25 @@ $(function() {
ripple::AmendmentVote::obsolete
@ obsolete
ripple::AmendmentTableImpl::firstUnsupportedExpected_
std::optional< NetClock::time_point > firstUnsupportedExpected_
Definition: AmendmentTable.cpp:366
std::unordered_set
STL class.
-
ripple::AmendmentTableImpl::getDesired
std::vector< uint256 > getDesired() const override
Definition: AmendmentTable.cpp:768
+
ripple::AmendmentTableImpl::getDesired
std::vector< uint256 > getDesired() const override
Definition: AmendmentTable.cpp:769
std::pair
ripple::AmendmentTableImpl::mutex_
std::mutex mutex_
Definition: AmendmentTable.cpp:345
ripple::AmendmentTableImpl::unsupportedEnabled_
bool unsupportedEnabled_
Definition: AmendmentTable.cpp:361
-
ripple::AmendmentTableImpl::doValidation
std::vector< uint256 > doValidation(std::set< uint256 > const &enabledAmendments) const override
Definition: AmendmentTable.cpp:741
+
ripple::AmendmentTableImpl::doValidation
std::vector< uint256 > doValidation(std::set< uint256 > const &enabledAmendments) const override
Definition: AmendmentTable.cpp:742
ripple::createFeatureVotes
bool createFeatureVotes(soci::session &session)
createFeatureVotes Creates the FeatureVote table if it does not exist.
Definition: Wallet.cpp:225
std::vector
STL class.
std::unordered_map::find
T find(T... args)
std::unordered_set::size
T size(T... args)
ripple::VoteBehavior::DefaultNo
@ DefaultNo
std::chrono::duration
-
ripple::AmendmentTableImpl::find
uint256 find(std::string const &name) const override
Definition: AmendmentTable.cpp:639
+
ripple::AmendmentTableImpl::find
uint256 find(std::string const &name) const override
Definition: AmendmentTable.cpp:640
beast::Journal::warn
Stream warn() const
Definition: Journal.h:326
ripple::AmendmentSet::votes_
hash_map< uint256, int > votes_
Definition: AmendmentTable.cpp:249
std::lock_guard
STL class.
-
ripple::AmendmentTableImpl::unVeto
bool unVeto(uint256 const &amendment) override
Definition: AmendmentTable.cpp:677
+
ripple::AmendmentTableImpl::unVeto
bool unVeto(uint256 const &amendment) override
Definition: AmendmentTable.cpp:678
ripple::AmendmentState::vote
AmendmentVote vote
If an amendment is down-voted, a server will not vote to enable it.
Definition: AmendmentTable.cpp:226
ripple::AmendmentSet
The status of all amendments requested in a given window.
Definition: AmendmentTable.cpp:245
+
ripple::AmendmentTableImpl::getJson
Json::Value getJson(bool isAdmin) const override
Definition: AmendmentTable.cpp:941
ripple::TrustedVotes::recordedVotes_
hash_map< PublicKey, UpvotesAndTimeout > recordedVotes_
Definition: AmendmentTable.cpp:101
std::as_const
T as_const(T... args)
ripple::AmendmentTableImpl
Track the list of "amendments".
Definition: AmendmentTable.cpp:342
@@ -1066,20 +1074,21 @@ $(function() {
ripple::AmendmentVote::down
@ down
ripple::base_uint< 256 >
ripple::Section::name
std::string const & name() const
Returns the name of this section.
Definition: BasicConfig.h:59
+
ripple::AmendmentTableImpl::injectJson
void injectJson(Json::Value &v, uint256 const &amendment, AmendmentState const &state, bool isAdmin, std::lock_guard< std::mutex > const &lock) const
Definition: AmendmentTable.cpp:906
std::chrono::time_point::time_since_epoch
T time_since_epoch(T... args)
ripple::AmendmentSet::threshold
int threshold() const
Definition: AmendmentTable.cpp:328
ripple::DatabaseCon::checkoutDb
LockedSociSession checkoutDb()
Definition: DatabaseCon.h:178
Json::objectValue
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:43
-
ripple::AmendmentTableImpl::firstUnsupportedExpected
std::optional< NetClock::time_point > firstUnsupportedExpected() const override
Definition: AmendmentTable.cpp:734
+
ripple::AmendmentTableImpl::firstUnsupportedExpected
std::optional< NetClock::time_point > firstUnsupportedExpected() const override
Definition: AmendmentTable.cpp:735
ripple::preFixAmendmentMajorityCalcThreshold
constexpr std::ratio< 204, 256 > preFixAmendmentMajorityCalcThreshold
The minimum amount of support an amendment should have.
Definition: SystemParameters.h:83
ripple::fixAmendmentMajorityCalc
const uint256 fixAmendmentMajorityCalc
-
ripple::AmendmentTableImpl::AmendmentTableImpl
AmendmentTableImpl(Application &app, std::chrono::seconds majorityTime, std::vector< FeatureInfo > const &supported, Section const &enabled, Section const &vetoed, beast::Journal journal)
Definition: AmendmentTable.cpp:464
+
ripple::AmendmentTableImpl::AmendmentTableImpl
AmendmentTableImpl(Application &app, std::chrono::seconds majorityTime, std::vector< FeatureInfo > const &supported, Section const &enabled, Section const &vetoed, beast::Journal journal)
Definition: AmendmentTable.cpp:465
ripple::TrustedVotes::maxTimeout
static constexpr NetClock::time_point maxTimeout
Definition: AmendmentTable.cpp:91
-
ripple::AmendmentTableImpl::doVoting
std::map< uint256, std::uint32_t > doVoting(Rules const &rules, NetClock::time_point closeTime, std::set< uint256 > const &enabledAmendments, majorityAmendments_t const &majorityAmendments, std::vector< std::shared_ptr< STValidation >> const &validations) override
Definition: AmendmentTable.cpp:775
+
ripple::AmendmentTableImpl::doVoting
std::map< uint256, std::uint32_t > doVoting(Rules const &rules, NetClock::time_point closeTime, std::set< uint256 > const &enabledAmendments, majorityAmendments_t const &majorityAmendments, std::vector< std::shared_ptr< STValidation >> const &validations) override
Definition: AmendmentTable.cpp:776
ripple::readAmendments
void readAmendments(soci::session &session, std::function< void(boost::optional< std::string > amendment_hash, boost::optional< std::string > amendment_name, boost::optional< AmendmentVote > vote)> const &callback)
readAmendments Reads all amendments from the FeatureVotes table.
Definition: Wallet.cpp:249
ripple::AmendmentSet::rules_
Rules const & rules_
Definition: AmendmentTable.cpp:250
-
ripple::AmendmentTableImpl::get
AmendmentState * get(uint256 const &amendment, std::lock_guard< std::mutex > const &lock)
Definition: AmendmentTable.cpp:615
-
ripple::AmendmentTableImpl::isSupported
bool isSupported(uint256 const &amendment) const override
Definition: AmendmentTable.cpp:719
+
ripple::AmendmentTableImpl::get
AmendmentState * get(uint256 const &amendment, std::lock_guard< std::mutex > const &lock)
Definition: AmendmentTable.cpp:616
+
ripple::AmendmentTableImpl::isSupported
bool isSupported(uint256 const &amendment) const override
Definition: AmendmentTable.cpp:720
beast::Journal::error
Stream error() const
Definition: Journal.h:332
beast::Journal::info
Stream info() const
Definition: Journal.h:320
std::chrono::time_point
@@ -1092,14 +1101,13 @@ $(function() {
ripple::TrustedVotes::UpvotesAndTimeout
Definition: AmendmentTable.cpp:96
ripple::TrustedVotes::operator=
TrustedVotes & operator=(TrustedVotes const &rhs)=delete
ripple::AmendmentTableImpl::previousTrustedVotes_
TrustedVotes previousTrustedVotes_
Definition: AmendmentTable.cpp:351
-
ripple::AmendmentTableImpl::veto
bool veto(uint256 const &amendment) override
Definition: AmendmentTable.cpp:664
+
ripple::AmendmentTableImpl::veto
bool veto(uint256 const &amendment) override
Definition: AmendmentTable.cpp:665
ripple::TrustedVotes::UpvotesAndTimeout::upVotes
std::vector< uint256 > upVotes
Definition: AmendmentTable.cpp:98
std::unordered_map::swap
T swap(T... args)
ripple::getJson
Json::Value getJson(LedgerFill const &fill)
Return a new Json::Value representing the ledger with given options.
Definition: LedgerToJson.cpp:357
ripple::TrustedVotes::recordVotes
void recordVotes(Rules const &rules, std::vector< std::shared_ptr< STValidation >> const &valSet, NetClock::time_point const closeTime, std::lock_guard< std::mutex > const &lock)
Definition: AmendmentTable.cpp:146
ripple::TrustedVotes::UpvotesAndTimeout::timeout
NetClock::time_point timeout
Definition: AmendmentTable.cpp:99
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
-
ripple::AmendmentTableImpl::injectJson
void injectJson(Json::Value &v, uint256 const &amendment, AmendmentState const &state, std::lock_guard< std::mutex > const &lock) const
Definition: AmendmentTable.cpp:905
ripple::AmendmentSet::computeThreshold
void computeThreshold(int trustedValidations, Rules const &rules)
Definition: AmendmentTable.cpp:257
ripple::AmendmentTableImpl::amendmentMap_
hash_map< uint256, AmendmentState > amendmentMap_
Definition: AmendmentTable.cpp:347
ripple::AmendmentTableImpl::lastVote_
std::unique_ptr< AmendmentSet > lastVote_
Definition: AmendmentTable.cpp:358
@@ -1107,7 +1115,6 @@ $(function() {
ripple::AmendmentTableImpl::majorityTime_
const std::chrono::seconds majorityTime_
Definition: AmendmentTable.cpp:354
ripple::voteAmendment
void voteAmendment(soci::session &session, uint256 const &amendment, std::string const &name, AmendmentVote vote)
voteAmendment Set the veto value for a particular amendment.
Definition: Wallet.cpp:285
ripple::AmendmentState::enabled
bool enabled
Indicates that the amendment has been enabled.
Definition: AmendmentTable.cpp:233
-
ripple::AmendmentTableImpl::getJson
Json::Value getJson() const override
Definition: AmendmentTable.cpp:939
ripple::DatabaseCon
Definition: DatabaseCon.h:81
ripple::AmendmentState::name
std::string name
The name of this amendment, possibly empty.
Definition: AmendmentTable.cpp:239
std::unordered_set::count
T count(T... args)
@@ -1119,31 +1126,31 @@ $(function() {
beast::Journal::debug
Stream debug() const
Definition: Journal.h:314
ripple::TrustedVotes::TrustedVotes
TrustedVotes()=default
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:38
-
ripple::make_AmendmentTable
std::unique_ptr< AmendmentTable > make_AmendmentTable(Application &app, std::chrono::seconds majorityTime, std::vector< AmendmentTable::FeatureInfo > const &supported, Section const &enabled, Section const &vetoed, beast::Journal journal)
Definition: AmendmentTable.cpp:973
+
ripple::make_AmendmentTable
std::unique_ptr< AmendmentTable > make_AmendmentTable(Application &app, std::chrono::seconds majorityTime, std::vector< AmendmentTable::FeatureInfo > const &supported, Section const &enabled, Section const &vetoed, beast::Journal journal)
Definition: AmendmentTable.cpp:979
std::make_pair
T make_pair(T... args)
std::unordered_map::end
T end(T... args)
-
ripple::AmendmentTableImpl::add
AmendmentState & add(uint256 const &amendment, std::lock_guard< std::mutex > const &lock)
Definition: AmendmentTable.cpp:606
+
ripple::AmendmentTableImpl::add
AmendmentState & add(uint256 const &amendment, std::lock_guard< std::mutex > const &lock)
Definition: AmendmentTable.cpp:607
ripple::AmendmentSet::trustedValidations
int trustedValidations() const
Definition: AmendmentTable.cpp:322
-
ripple::AmendmentTableImpl::isEnabled
bool isEnabled(uint256 const &amendment) const override
Definition: AmendmentTable.cpp:711
+
ripple::AmendmentTableImpl::isEnabled
bool isEnabled(uint256 const &amendment) const override
Definition: AmendmentTable.cpp:712
std::chrono::time_point::max
T max(T... args)
ripple::base_uint::parseHex
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition: base_uint.h:496
ripple::AmendmentTableImpl::j_
const beast::Journal j_
Definition: AmendmentTable.cpp:368
ripple::AmendmentTable
The amendment table stores the list of enabled and potential amendments.
Definition: AmendmentTable.h:37
-
ripple::AmendmentTableImpl::needValidatedLedger
bool needValidatedLedger(LedgerIndex seq) const override
Called to determine whether the amendment logic needs to process a new validated ledger.
Definition: AmendmentTable.cpp:850
+
ripple::AmendmentTableImpl::needValidatedLedger
bool needValidatedLedger(LedgerIndex seq) const override
Called to determine whether the amendment logic needs to process a new validated ledger.
Definition: AmendmentTable.cpp:851
ripple::AmendmentSet::votes
int votes(uint256 const &amendment) const
Definition: AmendmentTable.cpp:311
std::unique_ptr
STL class.
ripple::TrustedVotes
TrustedVotes records the most recent votes from trusted validators.
Definition: AmendmentTable.cpp:88
std::unordered_map
STL class.
-
ripple::AmendmentTableImpl::trustChanged
void trustChanged(hash_set< PublicKey > const &allTrusted) override
Definition: AmendmentTable.cpp:898
-
ripple::AmendmentTableImpl::persistVote
void persistVote(uint256 const &amendment, std::string const &name, AmendmentVote vote) const
Definition: AmendmentTable.cpp:653
+
ripple::AmendmentTableImpl::trustChanged
void trustChanged(hash_set< PublicKey > const &allTrusted) override
Definition: AmendmentTable.cpp:899
+
ripple::AmendmentTableImpl::persistVote
void persistVote(uint256 const &amendment, std::string const &name, AmendmentVote vote) const
Definition: AmendmentTable.cpp:654
std::set
STL class.
ripple::postFixAmendmentMajorityCalcThreshold
constexpr std::ratio< 80, 100 > postFixAmendmentMajorityCalcThreshold
Definition: SystemParameters.h:85
-
ripple::AmendmentTableImpl::doValidatedLedger
void doValidatedLedger(LedgerIndex seq, std::set< uint256 > const &enabled, majorityAmendments_t const &majority) override
Definition: AmendmentTable.cpp:861
-
ripple::AmendmentTableImpl::enable
bool enable(uint256 const &amendment) override
Definition: AmendmentTable.cpp:690
+
ripple::AmendmentTableImpl::doValidatedLedger
void doValidatedLedger(LedgerIndex seq, std::set< uint256 > const &enabled, majorityAmendments_t const &majority) override
Definition: AmendmentTable.cpp:862
+
ripple::AmendmentTableImpl::enable
bool enable(uint256 const &amendment) override
Definition: AmendmentTable.cpp:691
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::sfAmendments
const SF_VECTOR256 sfAmendments
ripple::get
T & get(EitherAmount &amt)
Definition: AmountSpec.h:118
-
ripple::AmendmentTableImpl::hasUnsupportedEnabled
bool hasUnsupportedEnabled() const override
returns true if one or more amendments on the network have been enabled that this server does not sup...
Definition: AmendmentTable.cpp:727
+
ripple::AmendmentTableImpl::hasUnsupportedEnabled
bool hasUnsupportedEnabled() const override
returns true if one or more amendments on the network have been enabled that this server does not sup...
Definition: AmendmentTable.cpp:728
ripple::VoteBehavior::DefaultYes
@ DefaultYes