mirror of
https://github.com/corda/corda.git
synced 2025-04-10 12:50:37 +00:00
Minor: more code motion ... TimestampingProtocol now split to top level class and moved to same location as the other protocols. Few other timestamping related classes reorganised.
This commit is contained in:
parent
2c4475b0d9
commit
dc6ef73b6b
@ -21,7 +21,7 @@ import core.messaging.SingleMessageRecipient
|
||||
import core.node.services.ArtemisMessagingService
|
||||
import core.node.services.NodeAttachmentStorage
|
||||
import core.node.services.NodeWalletService
|
||||
import core.node.services.TimestampingProtocol
|
||||
import protocols.TimestampingProtocol
|
||||
import core.protocols.ProtocolLogic
|
||||
import core.serialization.deserialize
|
||||
import core.utilities.ANSIProgressRenderer
|
||||
|
@ -9,29 +9,22 @@
|
||||
package core.node.services
|
||||
|
||||
import co.paralleluniverse.common.util.VisibleForTesting
|
||||
import co.paralleluniverse.fibers.Suspendable
|
||||
import core.*
|
||||
import core.Party
|
||||
import core.TimestampCommand
|
||||
import core.crypto.DigitalSignature
|
||||
import core.crypto.signWithECDSA
|
||||
import core.messaging.LegallyIdentifiableNode
|
||||
import core.messaging.MessageRecipients
|
||||
import core.messaging.MessagingService
|
||||
import core.messaging.StateMachineManager
|
||||
import core.protocols.ProtocolLogic
|
||||
import core.serialization.SerializedBytes
|
||||
import core.seconds
|
||||
import core.serialization.deserialize
|
||||
import core.serialization.serialize
|
||||
import core.until
|
||||
import org.slf4j.LoggerFactory
|
||||
import protocols.TimestampingProtocol
|
||||
import java.security.KeyPair
|
||||
import java.time.Clock
|
||||
import java.time.Duration
|
||||
import javax.annotation.concurrent.ThreadSafe
|
||||
|
||||
class TimestampingMessages {
|
||||
// TODO: Improve the messaging api to have a notion of sender+replyTo topic (optional?)
|
||||
data class Request(val tx: SerializedBytes<WireTransaction>, val replyTo: MessageRecipients, val replyToTopic: String)
|
||||
}
|
||||
|
||||
/**
|
||||
* This class implements the server side of the timestamping protocol, using the local clock. A future version might
|
||||
* add features like checking against other NTP servers to make sure the clock hasn't drifted by too much.
|
||||
@ -54,7 +47,7 @@ class NodeTimestamperService(private val net: MessagingService,
|
||||
require(identity.owningKey == signingKey.public)
|
||||
net.addMessageHandler(TIMESTAMPING_PROTOCOL_TOPIC + ".0", null) { message, r ->
|
||||
try {
|
||||
val req = message.data.deserialize<TimestampingMessages.Request>()
|
||||
val req = message.data.deserialize<TimestampingProtocol.Request>()
|
||||
val signature = processRequest(req)
|
||||
val msg = net.createMessage(req.replyToTopic, signature.serialize().bits)
|
||||
net.send(msg, req.replyTo)
|
||||
@ -67,7 +60,7 @@ class NodeTimestamperService(private val net: MessagingService,
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
fun processRequest(req: TimestampingMessages.Request): DigitalSignature.LegallyIdentifiable {
|
||||
fun processRequest(req: TimestampingProtocol.Request): DigitalSignature.LegallyIdentifiable {
|
||||
// We don't bother verifying signatures anything about the transaction here: we simply don't need to see anything
|
||||
// except the relevant command, and a future privacy upgrade should ensure we only get a torn-off command
|
||||
// rather than the full transaction.
|
||||
@ -96,41 +89,3 @@ class NodeTimestamperService(private val net: MessagingService,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The TimestampingProtocol class is the client code that talks to a [NodeTimestamperService] on some remote node. It is a
|
||||
* [ProtocolLogic], meaning it can either be a sub-protocol of some other protocol, or be driven independently.
|
||||
*
|
||||
* If you are not yourself authoring a protocol and want to timestamp something, the [TimestampingProtocol.Client] class
|
||||
* implements the [TimestamperService] interface, meaning it can be passed to [TransactionBuilder.timestamp] to timestamp
|
||||
* the built transaction. Please be aware that this will block, meaning it should not be used on a thread that is handling
|
||||
* a network message: use it only from spare application threads that don't have to respond to anything.
|
||||
*/
|
||||
class TimestampingProtocol(private val node: LegallyIdentifiableNode,
|
||||
private val wtxBytes: SerializedBytes<WireTransaction>) : ProtocolLogic<DigitalSignature.LegallyIdentifiable>() {
|
||||
|
||||
class Client(private val stateMachineManager: StateMachineManager, private val node: LegallyIdentifiableNode) : TimestamperService {
|
||||
override val identity: Party = node.identity
|
||||
|
||||
override fun timestamp(wtxBytes: SerializedBytes<WireTransaction>): DigitalSignature.LegallyIdentifiable {
|
||||
return stateMachineManager.add("platform.timestamping", TimestampingProtocol(node, wtxBytes)).get()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Suspendable
|
||||
override fun call(): DigitalSignature.LegallyIdentifiable {
|
||||
val sessionID = random63BitValue()
|
||||
val replyTopic = "${NodeTimestamperService.TIMESTAMPING_PROTOCOL_TOPIC}.$sessionID"
|
||||
val req = TimestampingMessages.Request(wtxBytes, serviceHub.networkService.myAddress, replyTopic)
|
||||
|
||||
val maybeSignature = sendAndReceive<DigitalSignature.LegallyIdentifiable>(
|
||||
NodeTimestamperService.TIMESTAMPING_PROTOCOL_TOPIC, node.address, 0, sessionID, req)
|
||||
|
||||
// Check that the timestamping authority gave us back a valid signature and didn't break somehow
|
||||
maybeSignature.validate { sig ->
|
||||
sig.verifyWithECDSA(wtxBytes)
|
||||
return sig
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
63
src/main/kotlin/protocols/TimestampingProtocol.kt
Normal file
63
src/main/kotlin/protocols/TimestampingProtocol.kt
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
|
||||
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
|
||||
* set forth therein.
|
||||
*
|
||||
* All other rights reserved.
|
||||
*/
|
||||
|
||||
package protocols
|
||||
|
||||
import co.paralleluniverse.fibers.Suspendable
|
||||
import core.Party
|
||||
import core.WireTransaction
|
||||
import core.crypto.DigitalSignature
|
||||
import core.messaging.LegallyIdentifiableNode
|
||||
import core.messaging.MessageRecipients
|
||||
import core.messaging.StateMachineManager
|
||||
import core.node.services.NodeTimestamperService
|
||||
import core.node.services.TimestamperService
|
||||
import core.protocols.ProtocolLogic
|
||||
import core.random63BitValue
|
||||
import core.serialization.SerializedBytes
|
||||
|
||||
/**
|
||||
* The TimestampingProtocol class is the client code that talks to a [NodeTimestamperService] on some remote node. It is a
|
||||
* [ProtocolLogic], meaning it can either be a sub-protocol of some other protocol, or be driven independently.
|
||||
*
|
||||
* If you are not yourself authoring a protocol and want to timestamp something, the [TimestampingProtocol.Client] class
|
||||
* implements the [TimestamperService] interface, meaning it can be passed to [TransactionBuilder.timestamp] to timestamp
|
||||
* the built transaction. Please be aware that this will block, meaning it should not be used on a thread that is handling
|
||||
* a network message: use it only from spare application threads that don't have to respond to anything.
|
||||
*/
|
||||
class TimestampingProtocol(private val node: LegallyIdentifiableNode,
|
||||
private val wtxBytes: SerializedBytes<WireTransaction>) : ProtocolLogic<DigitalSignature.LegallyIdentifiable>() {
|
||||
|
||||
class Client(private val stateMachineManager: StateMachineManager, private val node: LegallyIdentifiableNode) : TimestamperService {
|
||||
override val identity: Party = node.identity
|
||||
|
||||
override fun timestamp(wtxBytes: SerializedBytes<WireTransaction>): DigitalSignature.LegallyIdentifiable {
|
||||
return stateMachineManager.add("platform.timestamping", TimestampingProtocol(node, wtxBytes)).get()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Suspendable
|
||||
override fun call(): DigitalSignature.LegallyIdentifiable {
|
||||
val sessionID = random63BitValue()
|
||||
val replyTopic = "${NodeTimestamperService.TIMESTAMPING_PROTOCOL_TOPIC}.$sessionID"
|
||||
val req = Request(wtxBytes, serviceHub.networkService.myAddress, replyTopic)
|
||||
|
||||
val maybeSignature = sendAndReceive<DigitalSignature.LegallyIdentifiable>(
|
||||
NodeTimestamperService.TIMESTAMPING_PROTOCOL_TOPIC, node.address, 0, sessionID, req)
|
||||
|
||||
// Check that the timestamping authority gave us back a valid signature and didn't break somehow
|
||||
maybeSignature.validate { sig ->
|
||||
sig.verifyWithECDSA(wtxBytes)
|
||||
return sig
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Improve the messaging api to have a notion of sender+replyTo topic (optional?)
|
||||
data class Request(val tx: SerializedBytes<WireTransaction>, val replyTo: MessageRecipients, val replyToTopic: String)
|
||||
}
|
@ -18,7 +18,7 @@ import core.crypto.signWithECDSA
|
||||
import core.messaging.LegallyIdentifiableNode
|
||||
import core.messaging.SingleMessageRecipient
|
||||
import core.messaging.StateMachineManager
|
||||
import core.node.services.TimestampingProtocol
|
||||
import protocols.TimestampingProtocol
|
||||
import core.protocols.ProtocolLogic
|
||||
import core.utilities.ProgressTracker
|
||||
import core.utilities.trace
|
||||
|
@ -12,7 +12,9 @@ import co.paralleluniverse.fibers.Suspendable
|
||||
import core.*
|
||||
import core.crypto.SecureHash
|
||||
import core.messaging.*
|
||||
import core.node.services.*
|
||||
import core.node.services.NodeTimestamperService
|
||||
import core.node.services.ServiceHub
|
||||
import core.node.services.TimestampingError
|
||||
import core.protocols.ProtocolLogic
|
||||
import core.serialization.serialize
|
||||
import core.testutils.ALICE
|
||||
@ -21,6 +23,7 @@ import core.testutils.CASH
|
||||
import core.utilities.BriefLogFormatter
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import protocols.TimestampingProtocol
|
||||
import java.security.PublicKey
|
||||
import java.time.Clock
|
||||
import java.time.Instant
|
||||
@ -94,14 +97,14 @@ class TimestamperNodeServiceTest : TestWithInMemoryNetwork() {
|
||||
// Zero commands is not OK.
|
||||
assertFailsWith(TimestampingError.RequiresExactlyOneCommand::class) {
|
||||
val wtx = ptx.toWireTransaction()
|
||||
service.processRequest(TimestampingMessages.Request(wtx.serialize(), myMessaging.first, "ignored"))
|
||||
service.processRequest(TimestampingProtocol.Request(wtx.serialize(), myMessaging.first, "ignored"))
|
||||
}
|
||||
// More than one command is not OK.
|
||||
assertFailsWith(TimestampingError.RequiresExactlyOneCommand::class) {
|
||||
ptx.addCommand(TimestampCommand(clock.instant(), 30.seconds), ALICE)
|
||||
ptx.addCommand(TimestampCommand(clock.instant(), 40.seconds), ALICE)
|
||||
val wtx = ptx.toWireTransaction()
|
||||
service.processRequest(TimestampingMessages.Request(wtx.serialize(), myMessaging.first, "ignored"))
|
||||
service.processRequest(TimestampingProtocol.Request(wtx.serialize(), myMessaging.first, "ignored"))
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,7 +114,7 @@ class TimestamperNodeServiceTest : TestWithInMemoryNetwork() {
|
||||
val now = clock.instant()
|
||||
ptx.addCommand(TimestampCommand(now - 60.seconds, now - 40.seconds), ALICE)
|
||||
val wtx = ptx.toWireTransaction()
|
||||
service.processRequest(TimestampingMessages.Request(wtx.serialize(), myMessaging.first, "ignored"))
|
||||
service.processRequest(TimestampingProtocol.Request(wtx.serialize(), myMessaging.first, "ignored"))
|
||||
}
|
||||
}
|
||||
|
||||
@ -121,7 +124,7 @@ class TimestamperNodeServiceTest : TestWithInMemoryNetwork() {
|
||||
val now = clock.instant()
|
||||
ptx.addCommand(TimestampCommand(now - 60.seconds, now - 40.seconds), ALICE)
|
||||
val wtx = ptx.toWireTransaction()
|
||||
service.processRequest(TimestampingMessages.Request(wtx.serialize(), myMessaging.first, "ignored"))
|
||||
service.processRequest(TimestampingProtocol.Request(wtx.serialize(), myMessaging.first, "ignored"))
|
||||
}
|
||||
}
|
||||
|
||||
@ -130,7 +133,7 @@ class TimestamperNodeServiceTest : TestWithInMemoryNetwork() {
|
||||
val now = clock.instant()
|
||||
ptx.addCommand(TimestampCommand(now - 20.seconds, now + 20.seconds), ALICE)
|
||||
val wtx = ptx.toWireTransaction()
|
||||
val sig = service.processRequest(TimestampingMessages.Request(wtx.serialize(), myMessaging.first, "ignored"))
|
||||
val sig = service.processRequest(TimestampingProtocol.Request(wtx.serialize(), myMessaging.first, "ignored"))
|
||||
ptx.checkAndAddSignature(sig)
|
||||
ptx.toSignedTransaction(false).verifySignatures()
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user