Skip to content

Commit

Permalink
Merge pull request #2051 from MonsieurNicolas/scpSignedValues
Browse files Browse the repository at this point in the history
Scp signed values during nomination

Reviewed-by: MonsieurNicolas
  • Loading branch information
latobarita authored Apr 15, 2019
2 parents 3d5972d + b0aa767 commit d18ad68
Show file tree
Hide file tree
Showing 25 changed files with 338 additions and 105 deletions.
45 changes: 44 additions & 1 deletion src/herder/HerderImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ HerderImpl::HerderImpl(Application& app)
, mHerderSCPDriver(app, *this, mUpgrades, mPendingEnvelopes)
, mLastSlotSaved(0)
, mTrackingTimer(app)
, mLastExternalize(app.getClock().now())
, mTriggerTimer(app)
, mRebroadcastTimer(app)
, mApp(app)
Expand Down Expand Up @@ -130,9 +131,27 @@ HerderImpl::bootstrap()
void
HerderImpl::valueExternalized(uint64 slotIndex, StellarValue const& value)
{
const int DUMP_SCP_TIMEOUT_SECONDS = 20;

// record metrics
getHerderSCPDriver().recordSCPExecutionMetrics(slotIndex);

// dump SCP information if this ledger took a long time
auto now = mApp.getClock().now();
auto gap =
std::chrono::duration_cast<std::chrono::seconds>(now - mLastExternalize)
.count();
if (gap > DUMP_SCP_TIMEOUT_SECONDS)
{
auto slotInfo = getJsonQuorumInfo(getSCP().getLocalNodeID(), false,
false, slotIndex);
Json::FastWriter fw;
CLOG(WARNING, "Herder")
<< fmt::format("Ledger took {} seconds, SCP information:{}", gap,
fw.write(slotInfo));
}
mLastExternalize = now;

// called both here and at the end (this one is in case of an exception)
trackingHeartBeat();

Expand Down Expand Up @@ -630,7 +649,7 @@ HerderImpl::triggerNextLedger(uint32_t ledgerSeqToTrigger)
}

StellarValue newProposedValue(txSetHash, nextCloseTime, emptyUpgradeSteps,
0);
STELLAR_VALUE_BASIC);

// see if we need to include some upgrades
auto upgrades = mUpgrades.createUpgradesFor(lcl.header);
Expand All @@ -651,6 +670,11 @@ HerderImpl::triggerNextLedger(uint32_t ledgerSeqToTrigger)
}
}

if (lcl.header.ledgerVersion >= 11)
{
// version 11 and above require values to be signed during nomination
signStellarValue(mApp.getConfig().NODE_SEED, newProposedValue);
}
getHerderSCPDriver().recordSCPEvent(slotIndex, true);
mHerderSCPDriver.nominate(slotIndex, newProposedValue, proposedSet,
lcl.header.scpValue);
Expand Down Expand Up @@ -996,4 +1020,23 @@ HerderImpl::signEnvelope(SecretKey const& s, SCPEnvelope& envelope)
envelope.signature = s.sign(xdr::xdr_to_opaque(
mApp.getNetworkID(), ENVELOPE_TYPE_SCP, envelope.statement));
}
bool
HerderImpl::verifyStellarValueSignature(StellarValue const& sv)
{
auto b = PubKeyUtils::verifySig(
sv.ext.lcValueSignature().nodeID, sv.ext.lcValueSignature().signature,
xdr::xdr_to_opaque(mApp.getNetworkID(), ENVELOPE_TYPE_SCPVALUE,
sv.txSetHash, sv.closeTime));
return b;
}

void
HerderImpl::signStellarValue(SecretKey const& s, StellarValue& sv)
{
sv.ext.v(STELLAR_VALUE_SIGNED);
sv.ext.lcValueSignature().nodeID = s.getPublicKey();
sv.ext.lcValueSignature().signature =
s.sign(xdr::xdr_to_opaque(mApp.getNetworkID(), ENVELOPE_TYPE_SCPVALUE,
sv.txSetHash, sv.closeTime));
}
}
8 changes: 8 additions & 0 deletions src/herder/HerderImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,11 @@ class HerderImpl : public Herder
// helper function to sign envelopes
void signEnvelope(SecretKey const& s, SCPEnvelope& envelope);

// helper function to verify SCPValues are signed
bool verifyStellarValueSignature(StellarValue const& sv);
// helper function to sign SCPValues
void signStellarValue(SecretKey const& s, StellarValue& sv);

private:
void ledgerClosed();

Expand Down Expand Up @@ -133,6 +138,9 @@ class HerderImpl : public Herder
// timer that detects that we're stuck on an SCP slot
VirtualTimer mTrackingTimer;

// tracks the last time externalize was called
VirtualClock::time_point mLastExternalize;

// saves the SCP messages that the instance sent out last
void persistSCPState(uint64 slot);
// restores SCP state based on the last messages saved on disk
Expand Down
52 changes: 46 additions & 6 deletions src/herder/HerderSCPDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,11 +149,27 @@ HerderSCPDriver::checkCloseTime(uint64_t slotIndex, uint64_t lastCloseTime,
}

SCPDriver::ValidationLevel
HerderSCPDriver::validateValueHelper(uint64_t slotIndex,
StellarValue const& b) const
HerderSCPDriver::validateValueHelper(uint64_t slotIndex, StellarValue const& b,
bool nomination) const
{
uint64_t lastCloseTime;

if (b.ext.v() == STELLAR_VALUE_SIGNED)
{
if (nomination)
{
if (!mHerder.verifyStellarValueSignature(b))
{
return SCPDriver::kInvalidValue;
}
}
else
{
// don't use signed values in ballot protocol
return SCPDriver::kInvalidValue;
}
}

bool compat = isSlotCompatibleWithCurrentState(slotIndex);

auto const& lcl = mLedgerManager.getLastClosedLedgerHeader().header;
Expand Down Expand Up @@ -258,6 +274,26 @@ HerderSCPDriver::validateValueHelper(uint64_t slotIndex,

// we are fully synced up

if ((!nomination || lcl.ledgerVersion < 11) &&
b.ext.v() != STELLAR_VALUE_BASIC)
{
// ballot protocol or
// pre version 11 only supports BASIC
CLOG(TRACE, "Herder")
<< "HerderSCPDriver::validateValue"
<< " i: " << slotIndex << " invalid value type - expected BASIC";
return SCPDriver::kInvalidValue;
}
if (nomination &&
(lcl.ledgerVersion >= 11 && b.ext.v() != STELLAR_VALUE_SIGNED))
{
// v11 and above use SIGNED for nomination
CLOG(TRACE, "Herder")
<< "HerderSCPDriver::validateValue"
<< " i: " << slotIndex << " invalid value type - expected SIGNED";
return SCPDriver::kInvalidValue;
}

TxSetFramePtr txSet = mPendingEnvelopes.getTxSet(txSetHash);

SCPDriver::ValidationLevel res;
Expand Down Expand Up @@ -304,7 +340,8 @@ HerderSCPDriver::validateValue(uint64_t slotIndex, Value const& value,
return SCPDriver::kInvalidValue;
}

SCPDriver::ValidationLevel res = validateValueHelper(slotIndex, b);
SCPDriver::ValidationLevel res =
validateValueHelper(slotIndex, b, nomination);
if (res != SCPDriver::kInvalidValue)
{
auto const& lcl = mLedgerManager.getLastClosedLedgerHeader();
Expand Down Expand Up @@ -360,7 +397,8 @@ HerderSCPDriver::extractValidValue(uint64_t slotIndex, Value const& value)
return Value();
}
Value res;
if (validateValueHelper(slotIndex, b) == SCPDriver::kFullyValidatedValue)
if (validateValueHelper(slotIndex, b, true) ==
SCPDriver::kFullyValidatedValue)
{
auto const& lcl = mLedgerManager.getLastClosedLedgerHeader();

Expand Down Expand Up @@ -406,7 +444,7 @@ HerderSCPDriver::getValueString(Value const& v) const
{
xdr::xdr_from_opaque(v, b);

return stellarValueToString(b);
return stellarValueToString(mApp.getConfig(), b);
}
catch (...)
{
Expand Down Expand Up @@ -515,7 +553,7 @@ HerderSCPDriver::combineCandidates(uint64_t slotIndex,

Hash h;

StellarValue comp(h, 0, emptyUpgradeSteps, 0);
StellarValue comp(h, 0, emptyUpgradeSteps, STELLAR_VALUE_BASIC);

std::map<LedgerUpgradeType, LedgerUpgrade> upgrades;

Expand Down Expand Up @@ -632,6 +670,8 @@ HerderSCPDriver::combineCandidates(uint64_t slotIndex,
"HerderSCPDriver: combineCandidates posts recvTxSet");
}

// Ballot Protocol uses BASIC values
comp.ext.v(STELLAR_VALUE_BASIC);
return xdr::xdr_to_opaque(comp);
}

Expand Down
5 changes: 3 additions & 2 deletions src/herder/HerderSCPDriver.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,9 @@ class HerderSCPDriver : public SCPDriver
bool checkCloseTime(uint64_t slotIndex, uint64_t lastCloseTime,
StellarValue const& b) const;

SCPDriver::ValidationLevel
validateValueHelper(uint64_t slotIndex, StellarValue const& sv) const;
SCPDriver::ValidationLevel validateValueHelper(uint64_t slotIndex,
StellarValue const& sv,
bool nomination) const;

// returns true if the local instance is in a state compatible with
// this slot
Expand Down
10 changes: 7 additions & 3 deletions src/herder/LedgerCloseData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,16 @@ LedgerCloseData::LedgerCloseData(uint32_t ledgerSeq, TxSetFramePtr txSet,
}

std::string
stellarValueToString(StellarValue const& sv)
stellarValueToString(Config const& c, StellarValue const& sv)
{
std::stringstream res;

res << "[ "
<< " txH: " << hexAbbrev(sv.txSetHash) << ", ct: " << sv.closeTime
res << "[";
if (sv.ext.v() == STELLAR_VALUE_SIGNED)
{
res << " SIGNED@" << c.toShortString(sv.ext.lcValueSignature().nodeID);
}
res << " txH: " << hexAbbrev(sv.txSetHash) << ", ct: " << sv.closeTime
<< ", upgrades: [";
for (auto const& upgrade : sv.upgrades)
{
Expand Down
3 changes: 2 additions & 1 deletion src/herder/LedgerCloseData.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// of this distribution or at http://www.apache.org/licenses/LICENSE-2.0

#include "TxSetFrame.h"
#include "main/Config.h"
#include "overlay/StellarXDR.h"
#include <string>

Expand Down Expand Up @@ -46,7 +47,7 @@ class LedgerCloseData
StellarValue mValue;
};

std::string stellarValueToString(StellarValue const& sv);
std::string stellarValueToString(Config const& c, StellarValue const& sv);

#define emptyUpgradeSteps (xdr::xvector<UpgradeType, 6>(0))
}
Loading

0 comments on commit d18ad68

Please sign in to comment.