Add manifests subscriptions

Add verify method to manifest script to check signature
This commit is contained in:
wilsonianb
2016-01-13 15:44:47 -08:00
committed by Edward Hennis
parent a67e4ab9f1
commit 749b4adc7c
13 changed files with 155 additions and 8 deletions

View File

@@ -436,6 +436,10 @@ public:
bool subBook (InfoSub::ref ispListener, Book const&) override;
bool unsubBook (std::uint64_t uListener, Book const&) override;
bool subManifests (InfoSub::ref ispListener) override;
bool unsubManifests (std::uint64_t uListener) override;
void pubManifest (Manifest const&) override;
bool subTransactions (InfoSub::ref ispListener) override;
bool unsubTransactions (std::uint64_t uListener) override;
@@ -526,6 +530,7 @@ private:
subRpcMapType mRpcSubMap;
SubMapType mSubLedger; // Accepted ledgers.
SubMapType mSubManifests; // Received validator manifests.
SubMapType mSubServer; // When server changes connectivity state.
SubMapType mSubTransactions; // All accepted transactions.
SubMapType mSubRTTransactions; // All proposed and accepted transactions.
@@ -1507,6 +1512,36 @@ void NetworkOPsImp::consensusViewChange ()
setMode (omCONNECTED);
}
void NetworkOPsImp::pubManifest (Manifest const& mo)
{
// VFALCO consider std::shared_mutex
ScopedLockType sl (mSubLock);
if (!mSubManifests.empty ())
{
Json::Value jvObj (Json::objectValue);
jvObj [jss::type] = "manifestReceived";
jvObj [jss::master_key] = toBase58(TokenType::TOKEN_NODE_PUBLIC, mo.masterKey);
jvObj [jss::signing_key] = toBase58(TokenType::TOKEN_NODE_PUBLIC, mo.signingKey);
jvObj [jss::seq] = Json::UInt (mo.sequence);
jvObj [jss::signature] = strHex (mo.getSignature ());
for (auto i = mSubManifests.begin (); i != mSubManifests.end (); )
{
if (auto p = i->second.lock())
{
p->send (jvObj, true);
++i;
}
else
{
i = mSubManifests.erase (i);
}
}
}
}
void NetworkOPsImp::pubServer ()
{
// VFALCO TODO Don't hold the lock across calls to send...make a copy of the
@@ -1568,9 +1603,7 @@ void NetworkOPsImp::pubValidation (STValidation::ref val)
for (auto i = mSubValidations.begin (); i != mSubValidations.end (); )
{
InfoSub::pointer p = i->second.lock ();
if (p)
if (auto p = i->second.lock())
{
p->send (jvObj, true);
++i;
@@ -2538,6 +2571,20 @@ bool NetworkOPsImp::unsubLedger (std::uint64_t uSeq)
return mSubLedger.erase (uSeq);
}
// <-- bool: true=added, false=already there
bool NetworkOPsImp::subManifests (InfoSub::ref isrListener)
{
ScopedLockType sl (mSubLock);
return mSubManifests.emplace (isrListener->getSeq (), isrListener).second;
}
// <-- bool: true=erased, false=was not there
bool NetworkOPsImp::unsubManifests (std::uint64_t uSeq)
{
ScopedLockType sl (mSubLock);
return mSubManifests.erase (uSeq);
}
// <-- bool: true=added, false=already there
bool NetworkOPsImp::subServer (InfoSub::ref isrListener, Json::Value& jvResult,
bool admin)

View File

@@ -22,6 +22,7 @@
#include <ripple/basics/CountedObject.h>
#include <ripple/json/json_value.h>
#include <ripple/overlay/impl/Manifest.h>
#include <ripple/resource/Consumer.h>
#include <ripple/protocol/Book.h>
#include <beast/threads/Stoppable.h>
@@ -84,6 +85,10 @@ public:
virtual bool subLedger (ref ispListener, Json::Value& jvResult) = 0;
virtual bool unsubLedger (std::uint64_t uListener) = 0;
virtual bool subManifests (ref ispListener) = 0;
virtual bool unsubManifests (std::uint64_t uListener) = 0;
virtual void pubManifest (Manifest const&) = 0;
virtual bool subServer (ref ispListener, Json::Value& jvResult,
bool admin) = 0;
virtual bool unsubServer (std::uint64_t uListener) = 0;

View File

@@ -56,6 +56,7 @@ InfoSub::~InfoSub ()
m_source.unsubTransactions (mSeq);
m_source.unsubRTTransactions (mSeq);
m_source.unsubLedger (mSeq);
m_source.unsubManifests (mSeq);
m_source.unsubServer (mSeq);
m_source.unsubValidations (mSeq);
m_source.unsubPeerStatus (mSeq);

View File

@@ -119,6 +119,14 @@ bool Manifest::revoked () const
return sequence == std::numeric_limits<std::uint32_t>::max ();
}
Blob Manifest::getSignature () const
{
STObject st (sfGeneric);
SerialIter sit (serialized.data (), serialized.size ());
st.set (sit);
return st.getFieldVL (sfSignature);
}
void
ManifestCache::configValidatorKey(
std::string const& line, beast::Journal journal)

View File

@@ -98,6 +98,7 @@ struct Manifest
bool verify () const;
uint256 hash () const;
bool revoked () const;
Blob getSignature () const;
};
boost::optional<Manifest> make_Manifest(std::string s);

View File

@@ -19,6 +19,7 @@
#include <BeastConfig.h>
#include <ripple/app/misc/HashRouter.h>
#include <ripple/app/misc/NetworkOPs.h>
#include <ripple/core/DatabaseCon.h>
#include <ripple/basics/contract.h>
#include <ripple/basics/Log.h>
@@ -695,6 +696,10 @@ OverlayImpl::onManifests (
app_.validators(),
journal);
if (result == ManifestDisposition::accepted ||
result == ManifestDisposition::untrusted)
app_.getOPs().pubManifest (*make_Manifest(serialized));
if (result == ManifestDisposition::accepted)
{
auto db = app_.getWalletDB ().checkoutDb ();

View File

@@ -19,6 +19,7 @@
#include <BeastConfig.h>
#include <ripple/basics/contract.h>
#include <ripple/basics/StringUtilities.h>
#include <ripple/basics/TestSuite.h>
#include <ripple/overlay/impl/Manifest.h>
#include <ripple/core/DatabaseCon.h>
@@ -93,9 +94,9 @@ public:
auto const pk = derivePublicKey(type, sk);
STObject st(sfGeneric);
set(st, sfSequence, seq);
set(st, sfPublicKey, pk);
set(st, sfSigningPubKey, spk);
st[sfSequence] = seq;
st[sfPublicKey] = pk;
st[sfSigningPubKey] = spk;
sign(st, HashPrefix::manifest, type, sk);
expect(verify(st, HashPrefix::manifest, pk, true));
@@ -179,6 +180,26 @@ public:
boost::filesystem::path (dbName));
}
void testGetSignature()
{
testcase ("getSignature");
auto const sk = randomSecretKey();
auto const pk = derivePublicKey(KeyType::ed25519, sk);
auto const kp = randomKeyPair(KeyType::secp256k1);
auto const m = make_Manifest (KeyType::ed25519, sk, kp.first, 0);
STObject st(sfGeneric);
st[sfSequence] = 0;
st[sfPublicKey] = pk;
st[sfSigningPubKey] = kp.first;
Serializer ss;
ss.add32(HashPrefix::manifest);
st.addWithoutSigningFields(ss);
auto const sig = sign(KeyType::ed25519, sk, ss.slice());
expect (strHex(sig) == strHex(m.getSignature()));
}
void
run() override
{
@@ -227,6 +248,7 @@ public:
expect (cache.applyManifest (clone (s_b2), *unl, journal) == invalid);
}
testLoadStore (cache, *unl);
testGetSignature ();
}
};

View File

@@ -341,6 +341,7 @@ JSS ( server_state ); // out: NetworkOPs
JSS ( server_status ); // out: NetworkOPs
JSS ( severity ); // in: LogLevel
JSS ( signature ); // out: NetworkOPs
JSS ( signing_key ); // out: NetworkOPs
JSS ( signer_list ); // in: AccountObjects
JSS ( snapshot ); // in: Subscribe
JSS ( source_account ); // in: PathRequest, RipplePathFind

View File

@@ -124,6 +124,10 @@ Json::Value doSubscribe (RPC::Context& context)
{
context.netOps.subLedger (ispSub, jvResult);
}
else if (streamName == "manifests")
{
context.netOps.subManifests (ispSub);
}
else if (streamName == "transactions")
{
context.netOps.subTransactions (ispSub);

View File

@@ -77,6 +77,10 @@ Json::Value doUnsubscribe (RPC::Context& context)
{
context.netOps.unsubLedger (ispSub->getSeq ());
}
else if (streamName == "manifests")
{
context.netOps.unsubManifests (ispSub->getSeq ());
}
else if (streamName == "transactions")
{
context.netOps.unsubTransactions (ispSub->getSeq ());