rippled
RCLValidations.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012-2017 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/app/consensus/RCLValidations.h>
21 #include <ripple/app/ledger/InboundLedger.h>
22 #include <ripple/app/ledger/InboundLedgers.h>
23 #include <ripple/app/ledger/LedgerMaster.h>
24 #include <ripple/app/main/Application.h>
25 #include <ripple/app/misc/NetworkOPs.h>
26 #include <ripple/app/misc/ValidatorList.h>
27 #include <ripple/basics/Log.h>
28 #include <ripple/basics/StringUtilities.h>
29 #include <ripple/basics/chrono.h>
30 #include <ripple/consensus/LedgerTiming.h>
31 #include <ripple/core/DatabaseCon.h>
32 #include <ripple/core/JobQueue.h>
33 #include <ripple/core/TimeKeeper.h>
34 #include <memory>
35 #include <mutex>
36 #include <thread>
37 
38 namespace ripple {
39 
41  : ledgerID_{0}, ledgerSeq_{0}, j_{beast::Journal::getNullSink()}
42 {
43 }
44 
46  std::shared_ptr<Ledger const> const& ledger,
48  : ledgerID_{ledger->info().hash}, ledgerSeq_{ledger->seq()}, j_{j}
49 {
50  auto const hashIndex = ledger->read(keylet::skip());
51  if (hashIndex)
52  {
53  assert(hashIndex->getFieldU32(sfLastLedgerSequence) == (seq() - 1));
54  ancestors_ = hashIndex->getFieldV256(sfHashes).value();
55  }
56  else
57  JLOG(j_.warn()) << "Ledger " << ledgerSeq_ << ":" << ledgerID_
58  << " missing recent ancestor hashes";
59 }
60 
61 auto
63 {
64  return seq() - std::min(seq(), static_cast<Seq>(ancestors_.size()));
65 }
66 
67 auto
69 {
70  return ledgerSeq_;
71 }
72 auto
74 {
75  return ledgerID_;
76 }
77 
78 auto RCLValidatedLedger::operator[](Seq const& s) const -> ID
79 {
80  if (s >= minSeq() && s <= seq())
81  {
82  if (s == seq())
83  return ledgerID_;
84  Seq const diff = seq() - s;
85  return ancestors_[ancestors_.size() - diff];
86  }
87 
88  JLOG(j_.warn()) << "Unable to determine hash of ancestor seq=" << s
89  << " from ledger hash=" << ledgerID_
90  << " seq=" << ledgerSeq_;
91  // Default ID that is less than all others
92  return ID{0};
93 }
94 
95 // Return the sequence number of the earliest possible mismatching ancestor
98 {
99  using Seq = RCLValidatedLedger::Seq;
100 
101  // Find overlapping interval for known sequence for the ledgers
102  Seq const lower = std::max(a.minSeq(), b.minSeq());
103  Seq const upper = std::min(a.seq(), b.seq());
104 
105  Seq curr = upper;
106  while (curr != Seq{0} && a[curr] != b[curr] && curr >= lower)
107  --curr;
108 
109  // If the searchable interval mismatches entirely, then we have to
110  // assume the ledgers mismatch starting post genesis ledger
111  return (curr < lower) ? Seq{1} : (curr + Seq{1});
112 }
113 
115  : app_(app), j_(j)
116 {
117 }
118 
121 {
122  return app_.timeKeeper().closeTime();
123 }
124 
125 boost::optional<RCLValidatedLedger>
127 {
128  auto ledger = app_.getLedgerMaster().getLedgerByHash(hash);
129  if (!ledger)
130  {
131  JLOG(j_.debug())
132  << "Need validated ledger for preferred ledger analysis " << hash;
133 
134  Application * pApp = &app_;
135 
137  jtADVANCE, "getConsensusLedger", [pApp, hash](Job&) {
138  pApp ->getInboundLedgers().acquire(
140  });
141  return boost::none;
142  }
143 
144  assert(!ledger->open() && ledger->isImmutable());
145  assert(ledger->info().hash == hash);
146 
147  return RCLValidatedLedger(std::move(ledger), j_);
148 }
149 
150 bool
152  STValidation::ref val,
153  std::string const& source)
154 {
155  PublicKey const& signingKey = val->getSignerPublic();
156  uint256 const& hash = val->getLedgerHash();
157 
158  // Ensure validation is marked as trusted if signer currently trusted
159  boost::optional<PublicKey> masterKey =
160  app.validators().getTrustedKey(signingKey);
161  if (!val->isTrusted() && masterKey)
162  val->setTrusted();
163 
164  // If not currently trusted, see if signer is currently listed
165  if (!masterKey)
166  masterKey = app.validators().getListedKey(signingKey);
167 
168  bool shouldRelay = false;
169  RCLValidations& validations = app.getValidations();
170  beast::Journal const j = validations.adaptor().journal();
171 
172  auto dmp = [&](beast::Journal::Stream s, std::string const& msg) {
173  s << "Val for " << hash
174  << (val->isTrusted() ? " trusted/" : " UNtrusted/")
175  << (val->isFull() ? "full" : "partial") << " from "
176  << (masterKey ? toBase58(TokenType::NodePublic, *masterKey)
177  : "unknown")
178  << " signing key "
179  << toBase58(TokenType::NodePublic, signingKey) << " " << msg
180  << " src=" << source;
181  };
182 
183  if(!val->isFieldPresent(sfLedgerSequence))
184  {
185  if(j.error())
186  dmp(j.error(), "missing ledger sequence field");
187  return false;
188  }
189 
190  // masterKey is seated only if validator is trusted or listed
191  if (masterKey)
192  {
193  ValStatus const outcome = validations.add(calcNodeID(*masterKey), val);
194  if(j.debug())
195  dmp(j.debug(), to_string(outcome));
196 
197  if (outcome == ValStatus::badSeq && j.warn())
198  {
199  auto const seq = val->getFieldU32(sfLedgerSequence);
200  dmp(j.warn(),
201  "already validated sequence at or past " + std::to_string(seq));
202  }
203 
204  if (val->isTrusted() && outcome == ValStatus::current)
205  {
207  hash, val->getFieldU32(sfLedgerSequence));
208  shouldRelay = true;
209  }
210  }
211  else
212  {
213  JLOG(j.debug()) << "Val for " << hash << " from "
214  << toBase58(TokenType::NodePublic, signingKey)
215  << " not added UNlisted";
216  }
217 
218  // This currently never forwards untrusted validations, though we may
219  // reconsider in the future. From @JoelKatz:
220  // The idea was that we would have a certain number of validation slots with
221  // priority going to validators we trusted. Remaining slots might be
222  // allocated to validators that were listed by publishers we trusted but
223  // that we didn't choose to trust. The shorter term plan was just to forward
224  // untrusted validations if peers wanted them or if we had the
225  // ability/bandwidth to. None of that was implemented.
226  return shouldRelay;
227 }
228 
229 
230 } // namespace ripple
ripple::ValidatorList::getListedKey
boost::optional< PublicKey > getListedKey(PublicKey const &identity) const
Returns listed master public if public key is included on any lists.
Definition: ValidatorList.cpp:592
ripple::mismatch
RCLValidatedLedger::Seq mismatch(RCLValidatedLedger const &a, RCLValidatedLedger const &b)
Definition: RCLValidations.cpp:97
ripple::Application
Definition: Application.h:85
ripple::keylet::skip
static const skip_t skip
Definition: Indexes.h:139
std::string
STL class.
ripple::InboundLedger::Reason::CONSENSUS
@ CONSENSUS
std::shared_ptr
STL class.
ripple::calcNodeID
NodeID calcNodeID(PublicKey const &pk)
Calculate the 160-bit node ID from a node public key.
Definition: PublicKey.cpp:307
ripple::RCLValidatedLedger::minSeq
Seq minSeq() const
Definition: RCLValidations.cpp:62
ripple::RCLValidatedLedger::MakeGenesis
Definition: RCLValidations.h:152
ripple::RCLValidatedLedger::ledgerID_
ID ledgerID_
Definition: RCLValidations.h:187
ripple::RCLValidatedLedger::ancestors_
std::vector< uint256 > ancestors_
Definition: RCLValidations.h:189
ripple::RCLValidationsAdaptor::acquire
boost::optional< RCLValidatedLedger > acquire(LedgerHash const &id)
Attempt to acquire the ledger with given id from the network.
Definition: RCLValidations.cpp:126
ripple::toBase58
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition: AccountID.cpp:29
beast::Journal::warn
Stream warn() const
Definition: Journal.h:302
ripple::ValStatus
ValStatus
Status of newly received validation.
Definition: Validations.h:164
ripple::SBoxCmp::diff
@ diff
ripple::LedgerMaster::getLedgerByHash
std::shared_ptr< Ledger const > getLedgerByHash(uint256 const &hash)
Definition: LedgerMaster.cpp:1677
ripple::RCLValidationsAdaptor::now
NetClock::time_point now() const
Current time used to determine if validations are stale.
Definition: RCLValidations.cpp:120
ripple::JobQueue::addJob
bool addJob(JobType type, std::string const &name, JobHandler &&jobHandler)
Adds a job to the JobQueue.
Definition: JobQueue.h:156
ripple::RCLValidationsAdaptor::journal
beast::Journal journal() const
Definition: RCLValidations.h:218
ripple::RCLValidatedLedger::id
ID id() const
The ID (hash) of the ledger.
Definition: RCLValidations.cpp:73
ripple::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:41
ripple::Application::timeKeeper
virtual TimeKeeper & timeKeeper()=0
ripple::RCLValidationsAdaptor::RCLValidationsAdaptor
RCLValidationsAdaptor(Application &app, beast::Journal j)
Definition: RCLValidations.cpp:114
beast::Journal::getNullSink
static Sink & getNullSink()
Returns a Sink which does nothing.
Definition: beast_Journal.cpp:67
ripple::RCLValidatedLedger
Wraps a ledger instance for use in generic Validations LedgerTrie.
Definition: RCLValidations.h:147
ripple::handleNewValidation
bool handleNewValidation(Application &app, STValidation::ref val, std::string const &source)
Handle a new validation.
Definition: RCLValidations.cpp:151
ripple::Application::getInboundLedgers
virtual InboundLedgers & getInboundLedgers()=0
ripple::ValStatus::badSeq
@ badSeq
A validation violates the increasing seq requirement.
ripple::RCLValidatedLedger::seq
Seq seq() const
The sequence (index) of the ledger.
Definition: RCLValidations.cpp:68
ripple::ValidatorList::getTrustedKey
boost::optional< PublicKey > getTrustedKey(PublicKey const &identity) const
Returns master public key if public key is trusted.
Definition: ValidatorList.cpp:604
ripple::base_uint< 256 >
ripple::RCLValidatedLedger::RCLValidatedLedger
RCLValidatedLedger(MakeGenesis)
Definition: RCLValidations.cpp:40
ripple::sfLastLedgerSequence
const SF_U32 sfLastLedgerSequence(access, STI_UINT32, 27, "LastLedgerSequence")
Definition: SField.h:364
thread
ripple::Validations::add
ValStatus add(NodeID const &nodeID, Validation const &val)
Add a new validation.
Definition: Validations.h:581
ripple::Application::getLedgerMaster
virtual LedgerMaster & getLedgerMaster()=0
ripple::PublicKey
A public key.
Definition: PublicKey.h:59
ripple::RCLValidationsAdaptor::j_
beast::Journal j_
Definition: RCLValidations.h:225
std::to_string
T to_string(T... args)
ripple::Application::getJobQueue
virtual JobQueue & getJobQueue()=0
beast::Journal::Stream
Provide a light-weight way to check active() before string formatting.
Definition: Journal.h:179
ripple::sfLedgerSequence
const SF_U32 sfLedgerSequence(access, STI_UINT32, 6, "LedgerSequence")
Definition: SField.h:342
beast::Journal::error
Stream error() const
Definition: Journal.h:307
std::chrono::time_point
ripple::RCLValidatedLedger::ledgerSeq_
Seq ledgerSeq_
Definition: RCLValidations.h:188
ripple::RCLValidatedLedger::operator[]
ID operator[](Seq const &s) const
Lookup the ID of the ancestor ledger.
Definition: RCLValidations.cpp:78
ripple::TimeKeeper::closeTime
virtual time_point closeTime() const =0
Returns the close time, in network time.
ripple::ValStatus::current
@ current
This was a new validation and was added.
ripple::Job
Definition: Job.h:83
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:60
ripple::Application::getValidations
virtual RCLValidations & getValidations()=0
std::uint32_t
memory
ripple::LedgerMaster::checkAccept
void checkAccept(std::shared_ptr< Ledger const > const &ledger)
Definition: LedgerMaster.cpp:1000
ripple::Application::validators
virtual ValidatorList & validators()=0
std::min
T min(T... args)
ripple::sfHashes
const SF_Vec256 sfHashes(access, STI_VECTOR256, 2, "Hashes")
Definition: SField.h:474
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::ReadView::seq
LedgerIndex seq() const
Returns the sequence number of the base ledger.
Definition: ReadView.h:258
ripple::RCLValidationsAdaptor::app_
Application & app_
Definition: RCLValidations.h:224
ripple::TokenType::NodePublic
@ NodePublic
ripple::Validations< RCLValidationsAdaptor >
mutex
beast::Journal::debug
Stream debug() const
Definition: Journal.h:292
ripple::jtADVANCE
@ jtADVANCE
Definition: Job.h:54
std::max
T max(T... args)
ripple::Validations::adaptor
Adaptor const & adaptor() const
Return the adaptor instance.
Definition: Validations.h:545
ripple::RCLValidatedLedger::Seq
LedgerIndex Seq
Definition: RCLValidations.h:151