summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mongo/db/logical_clock.cpp4
-rw-r--r--src/mongo/db/logical_clock_test.cpp2
-rw-r--r--src/mongo/db/logical_time_test.cpp6
-rw-r--r--src/mongo/db/signed_logical_time.h11
-rw-r--r--src/mongo/rpc/metadata/logical_time_metadata.cpp33
-rw-r--r--src/mongo/rpc/metadata/logical_time_metadata.h5
-rw-r--r--src/mongo/rpc/metadata/logical_time_metadata_test.cpp58
7 files changed, 103 insertions, 16 deletions
diff --git a/src/mongo/db/logical_clock.cpp b/src/mongo/db/logical_clock.cpp
index 34a11fc163c..32e0b22184e 100644
--- a/src/mongo/db/logical_clock.cpp
+++ b/src/mongo/db/logical_clock.cpp
@@ -93,7 +93,9 @@ SignedLogicalTime LogicalClock::getClusterTime() {
}
SignedLogicalTime LogicalClock::_makeSignedLogicalTime(LogicalTime logicalTime) {
- return SignedLogicalTime(logicalTime, _timeProofService->getProof(logicalTime));
+ // TODO: SERVER-28436 Implement KeysCollectionManager
+ // Replace dummy keyId with real id from key manager.
+ return SignedLogicalTime(logicalTime, _timeProofService->getProof(logicalTime), 0);
}
Status LogicalClock::advanceClusterTime(const SignedLogicalTime& newTime) {
diff --git a/src/mongo/db/logical_clock_test.cpp b/src/mongo/db/logical_clock_test.cpp
index a0b8dbaf30e..156232fc386 100644
--- a/src/mongo/db/logical_clock_test.cpp
+++ b/src/mongo/db/logical_clock_test.cpp
@@ -63,7 +63,7 @@ protected:
}
SignedLogicalTime makeSignedLogicalTime(LogicalTime logicalTime) {
- return SignedLogicalTime(logicalTime, _timeProofService->getProof(logicalTime));
+ return SignedLogicalTime(logicalTime, _timeProofService->getProof(logicalTime), 0);
}
const unsigned currentWallClockSecs() {
diff --git a/src/mongo/db/logical_time_test.cpp b/src/mongo/db/logical_time_test.cpp
index f0f0d7b4477..b55d4fee950 100644
--- a/src/mongo/db/logical_time_test.cpp
+++ b/src/mongo/db/logical_time_test.cpp
@@ -107,15 +107,19 @@ TEST(LogicalTime, toUnsignedArray) {
TEST(SignedLogicalTime, roundtrip) {
Timestamp tX(1);
+
std::array<std::uint8_t, 20> tempKey = {};
TimeProofService::Key key(std::move(tempKey));
TimeProofService tps(std::move(key));
auto time = LogicalTime(tX);
auto proof = tps.getProof(time);
- SignedLogicalTime signedTime(time, proof);
+ long long keyId = 1;
+
+ SignedLogicalTime signedTime(time, proof, keyId);
ASSERT_TRUE(time == signedTime.getTime());
ASSERT_TRUE(proof == signedTime.getProof());
+ ASSERT_TRUE(keyId == signedTime.getKeyId());
}
} // unnamed namespace
diff --git a/src/mongo/db/signed_logical_time.h b/src/mongo/db/signed_logical_time.h
index 7b96e51df79..fde222efb39 100644
--- a/src/mongo/db/signed_logical_time.h
+++ b/src/mongo/db/signed_logical_time.h
@@ -44,8 +44,8 @@ public:
SignedLogicalTime() = default;
- explicit SignedLogicalTime(LogicalTime time, TimeProof proof)
- : _time(std::move(time)), _proof(std::move(proof)) {}
+ explicit SignedLogicalTime(LogicalTime time, TimeProof proof, long long keyId)
+ : _time(std::move(time)), _proof(std::move(proof)), _keyId(keyId) {}
LogicalTime getTime() const {
return _time;
@@ -55,11 +55,18 @@ public:
return _proof;
}
+ long long getKeyId() const {
+ return _keyId;
+ }
+
std::string toString() const;
+ static const SignedLogicalTime kUninitialized;
+
private:
LogicalTime _time;
TimeProof _proof;
+ long long _keyId{0};
};
} // namespace mongo
diff --git a/src/mongo/rpc/metadata/logical_time_metadata.cpp b/src/mongo/rpc/metadata/logical_time_metadata.cpp
index 9d79a892e3a..8abdd91edd4 100644
--- a/src/mongo/rpc/metadata/logical_time_metadata.cpp
+++ b/src/mongo/rpc/metadata/logical_time_metadata.cpp
@@ -40,6 +40,8 @@ namespace {
const char kClusterTimeFieldName[] = "clusterTime";
const char kSignatureFieldName[] = "signature";
+const char kSignatureHashFieldName[] = "hash";
+const char kSignatureKeyIdFieldName[] = "keyId";
} // unnamed namespace
@@ -64,30 +66,49 @@ StatusWith<LogicalTimeMetadata> LogicalTimeMetadata::readFromMetadata(
return status;
}
- // Extract BinData type signature and construct a SHA1Block instance from it.
BSONElement signatureElem;
- status = bsonExtractTypedField(obj, kSignatureFieldName, BinData, &signatureElem);
+ status = bsonExtractTypedField(obj, kSignatureFieldName, Object, &signatureElem);
+ if (!status.isOK()) {
+ return status;
+ }
+
+ const auto& signatureObj = signatureElem.Obj();
+
+ // Extract BinData type signature hash and construct a SHA1Block instance from it.
+ BSONElement hashElem;
+ status = bsonExtractTypedField(signatureObj, kSignatureHashFieldName, BinData, &hashElem);
if (!status.isOK()) {
return status;
}
int hashLength = 0;
- auto rawBinSignature = signatureElem.binData(hashLength);
- BSONBinData proofBinData(rawBinSignature, hashLength, signatureElem.binDataType());
+ auto rawBinSignature = hashElem.binData(hashLength);
+ BSONBinData proofBinData(rawBinSignature, hashLength, hashElem.binDataType());
auto proofStatus = SHA1Block::fromBinData(proofBinData);
if (!proofStatus.isOK()) {
return proofStatus.getStatus();
}
+ long long keyId;
+ status = bsonExtractIntegerField(signatureObj, kSignatureKeyIdFieldName, &keyId);
+ if (!status.isOK()) {
+ return status;
+ }
+
return LogicalTimeMetadata(
- SignedLogicalTime(LogicalTime(ts), std::move(proofStatus.getValue())));
+ SignedLogicalTime(LogicalTime(ts), std::move(proofStatus.getValue()), keyId));
}
void LogicalTimeMetadata::writeToMetadata(BSONObjBuilder* metadataBuilder) const {
BSONObjBuilder subObjBuilder(metadataBuilder->subobjStart(fieldName()));
_clusterTime.getTime().asTimestamp().append(subObjBuilder.bb(), kClusterTimeFieldName);
- _clusterTime.getProof().appendAsBinData(subObjBuilder, kSignatureFieldName);
+
+ BSONObjBuilder signatureObjBuilder(subObjBuilder.subobjStart(kSignatureFieldName));
+ _clusterTime.getProof().appendAsBinData(signatureObjBuilder, kSignatureHashFieldName);
+ signatureObjBuilder.append(kSignatureKeyIdFieldName, _clusterTime.getKeyId());
+ signatureObjBuilder.doneFast();
+
subObjBuilder.doneFast();
}
diff --git a/src/mongo/rpc/metadata/logical_time_metadata.h b/src/mongo/rpc/metadata/logical_time_metadata.h
index 2ff792b58b1..2ec6b7f03b5 100644
--- a/src/mongo/rpc/metadata/logical_time_metadata.h
+++ b/src/mongo/rpc/metadata/logical_time_metadata.h
@@ -42,7 +42,10 @@ namespace rpc {
* Format:
* logicalTime: {
* clusterTime: <Timestamp>,
- * signature: <SHA1 hash of clusterTime as BinData>
+ * signature: {
+ * hash: <SHA1 hash of clusterTime as BinData>,
+ * keyId: <long long>
+ * }
* }
*/
class LogicalTimeMetadata {
diff --git a/src/mongo/rpc/metadata/logical_time_metadata_test.cpp b/src/mongo/rpc/metadata/logical_time_metadata_test.cpp
index 61106f3d469..73e9ad64208 100644
--- a/src/mongo/rpc/metadata/logical_time_metadata_test.cpp
+++ b/src/mongo/rpc/metadata/logical_time_metadata_test.cpp
@@ -48,7 +48,9 @@ TEST(LogicalTimeMetadataTest, Roundtrip) {
proof[19] = 6;
proof[0] = 12;
- SignedLogicalTime signedTs(LogicalTime(ts), proof);
+ long long keyId = 1;
+
+ SignedLogicalTime signedTs(LogicalTime(ts), proof, keyId);
LogicalTimeMetadata origMetadata(signedTs);
BSONObjBuilder builder;
@@ -62,15 +64,34 @@ TEST(LogicalTimeMetadataTest, Roundtrip) {
const auto& parsedTs = parsedMetadata.getSignedTime();
ASSERT_EQ(ts.asTimestamp(), parsedTs.getTime().asTimestamp());
ASSERT_TRUE(SHA1Block(proof) == parsedTs.getProof());
+ ASSERT_TRUE(keyId == parsedTs.getKeyId());
}
TEST(LogicalTimeMetadataTest, MissingClusterTimeShouldFailToParse) {
std::array<uint8_t, 20> proof;
proof.fill(0);
+ long long keyId = 1;
+
+ BSONObjBuilder builder;
+ BSONObjBuilder subObjBuilder(builder.subobjStart("logicalTime"));
+ BSONObjBuilder signatureObjBuilder(subObjBuilder.subobjStart("signature"));
+ signatureObjBuilder.append("hash", BSONBinData(proof.data(), proof.size(), BinDataGeneral));
+ signatureObjBuilder.append("keyId", keyId);
+ signatureObjBuilder.doneFast();
+ subObjBuilder.doneFast();
+
+ auto serializedObj = builder.done();
+ auto status = LogicalTimeMetadata::readFromMetadata(serializedObj).getStatus();
+ ASSERT_EQ(ErrorCodes::NoSuchKey, status);
+}
+
+TEST(LogicalTimeMetadataTest, MissingSignatureShouldFailToParse) {
+ const auto ts = Timestamp(100, 200);
+
BSONObjBuilder builder;
BSONObjBuilder subObjBuilder(builder.subobjStart("logicalTime"));
- subObjBuilder.append("signature", BSONBinData(proof.data(), proof.size(), BinDataGeneral));
+ ts.append(subObjBuilder.bb(), "clusterTime");
subObjBuilder.doneFast();
auto serializedObj = builder.done();
@@ -78,12 +99,36 @@ TEST(LogicalTimeMetadataTest, MissingClusterTimeShouldFailToParse) {
ASSERT_EQ(ErrorCodes::NoSuchKey, status);
}
-TEST(LogicalTimeMetadataTest, MissingProofShouldFailToParse) {
+TEST(LogicalTimeMetadataTest, MissingHashShouldFailToParse) {
const auto ts = Timestamp(100, 200);
+ long long keyId = 1;
+
BSONObjBuilder builder;
BSONObjBuilder subObjBuilder(builder.subobjStart("logicalTime"));
ts.append(subObjBuilder.bb(), "clusterTime");
+ BSONObjBuilder signatureObjBuilder(subObjBuilder.subobjStart("signature"));
+ signatureObjBuilder.append("keyId", keyId);
+ signatureObjBuilder.doneFast();
+ subObjBuilder.doneFast();
+
+ auto serializedObj = builder.done();
+ auto status = LogicalTimeMetadata::readFromMetadata(serializedObj).getStatus();
+ ASSERT_EQ(ErrorCodes::NoSuchKey, status);
+}
+
+TEST(LogicalTimeMetadataTest, MissingKeyIdShouldFailToParse) {
+ const auto ts = Timestamp(100, 200);
+
+ std::array<uint8_t, 20> proof;
+ proof.fill(0);
+
+ BSONObjBuilder builder;
+ BSONObjBuilder subObjBuilder(builder.subobjStart("logicalTime"));
+ ts.append(subObjBuilder.bb(), "clusterTime");
+ BSONObjBuilder signatureObjBuilder(subObjBuilder.subobjStart("signature"));
+ signatureObjBuilder.append("hash", BSONBinData(proof.data(), proof.size(), BinDataGeneral));
+ signatureObjBuilder.doneFast();
subObjBuilder.doneFast();
auto serializedObj = builder.done();
@@ -97,10 +142,15 @@ TEST(LogicalTimeMetadataTest, ProofWithWrongLengthShouldFailToParse) {
std::array<uint8_t, 10> proof;
proof.fill(0);
+ long long keyId = 1;
+
BSONObjBuilder builder;
BSONObjBuilder subObjBuilder(builder.subobjStart("logicalTime"));
ts.append(subObjBuilder.bb(), "clusterTime");
- subObjBuilder.append("signature", BSONBinData(proof.data(), proof.size(), BinDataGeneral));
+ BSONObjBuilder signatureObjBuilder(subObjBuilder.subobjStart("signature"));
+ signatureObjBuilder.append("hash", BSONBinData(proof.data(), proof.size(), BinDataGeneral));
+ signatureObjBuilder.append("keyId", keyId);
+ signatureObjBuilder.doneFast();
subObjBuilder.doneFast();
auto serializedObj = builder.done();