Merged in plt-141-moves-only-part-3 (pull request #93)

File and interface moves to core module for scheduler
This commit is contained in:
Rick Parker 2016-05-13 15:17:32 +01:00
commit 539e23a0b1
18 changed files with 65 additions and 110 deletions

View File

@ -1,8 +1,8 @@
package contracts package contracts
import core.* import core.Amount
import core.Tenor
import java.math.BigDecimal import java.math.BigDecimal
import java.security.PublicKey
// Things in here will move to the general utils class when we've hammered out various discussions regarding amounts, dates, oracle etc. // Things in here will move to the general utils class when we've hammered out various discussions regarding amounts, dates, oracle etc.
@ -41,53 +41,6 @@ open class PercentageRatioUnit(percentageAsString: String) : RatioUnit(BigDecima
*/ */
val String.percent: PercentageRatioUnit get() = PercentageRatioUnit(this) val String.percent: PercentageRatioUnit get() = PercentageRatioUnit(this)
/**
* Interface representing an agreement that exposes various attributes that are common. Implementing it simplifies
* implementation of general protocols that manipulate many agreement types.
*/
interface DealState : LinearState {
/** Human readable well known reference (e.g. trade reference) */
val ref: String
/** Exposes the Parties involved in a generic way */
val parties: Array<Party>
// TODO: This works by editing the keys used by a Party which is invalid.
fun withPublicKey(before: Party, after: PublicKey): DealState
/**
* Generate a partial transaction representing an agreement (command) to this deal, allowing a general
* deal/agreement protocol to generate the necessary transaction for potential implementations
*
* TODO: Currently this is the "inception" transaction but in future an offer of some description might be an input state ref
*
* TODO: This should more likely be a method on the Contract (on a common interface) and the changes to reference a
* Contract instance from a ContractState are imminent, at which point we can move this out of here
*/
fun generateAgreement(): TransactionBuilder
}
/**
* Interface adding fixing specific methods
*/
interface FixableDealState : DealState {
/**
* When is the next fixing and what is the fixing for?
*
* TODO: In future we would use this to register for an event to trigger a/the fixing protocol
*/
fun nextFixingOf(): FixOf?
/**
* Generate a fixing command for this deal and fix
*
* TODO: This would also likely move to methods on the Contract once the changes to reference
* the Contract from the ContractState are in
*/
fun generateFix(ptx: TransactionBuilder, oldStateRef: StateRef, fix: Fix)
}
/** /**
* Parent of the Rate family. Used to denote fixed rates, floating rates, reference rates etc * Parent of the Rate family. Used to denote fixed rates, floating rates, reference rates etc
*/ */

View File

@ -59,6 +59,53 @@ interface LinearState : ContractState {
fun isRelevant(ourKeys: Set<PublicKey>): Boolean fun isRelevant(ourKeys: Set<PublicKey>): Boolean
} }
/**
* Interface representing an agreement that exposes various attributes that are common. Implementing it simplifies
* implementation of general protocols that manipulate many agreement types.
*/
interface DealState : LinearState {
/** Human readable well known reference (e.g. trade reference) */
val ref: String
/** Exposes the Parties involved in a generic way */
val parties: Array<Party>
// TODO: This works by editing the keys used by a Party which is invalid.
fun withPublicKey(before: Party, after: PublicKey): DealState
/**
* Generate a partial transaction representing an agreement (command) to this deal, allowing a general
* deal/agreement protocol to generate the necessary transaction for potential implementations
*
* TODO: Currently this is the "inception" transaction but in future an offer of some description might be an input state ref
*
* TODO: This should more likely be a method on the Contract (on a common interface) and the changes to reference a
* Contract instance from a ContractState are imminent, at which point we can move this out of here
*/
fun generateAgreement(): TransactionBuilder
}
/**
* Interface adding fixing specific methods
*/
interface FixableDealState : DealState {
/**
* When is the next fixing and what is the fixing for?
*
* TODO: In future we would use this to register for an event to trigger a/the fixing protocol
*/
fun nextFixingOf(): FixOf?
/**
* Generate a fixing command for this deal and fix
*
* TODO: This would also likely move to methods on the Contract once the changes to reference
* the Contract from the ContractState are in
*/
fun generateFix(ptx: TransactionBuilder, oldStateRef: StateRef, fix: Fix)
}
/** Returns the SHA-256 hash of the serialised contents of this state (not cached!) */ /** Returns the SHA-256 hash of the serialised contents of this state (not cached!) */
fun ContractState.hash(): SecureHash = SecureHash.sha256(serialize().bits) fun ContractState.hash(): SecureHash = SecureHash.sha256(serialize().bits)

View File

@ -1,10 +1,3 @@
/*
* 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 core.node package core.node
import core.Party import core.Party

View File

@ -1,11 +1,3 @@
/*
* 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 core.node package core.node
import java.util.* import java.util.*

View File

@ -4,7 +4,6 @@ import co.paralleluniverse.fibers.Suspendable
import core.NamedByHash import core.NamedByHash
import core.crypto.SecureHash import core.crypto.SecureHash
import core.messaging.SingleMessageRecipient import core.messaging.SingleMessageRecipient
import core.node.subsystems.DataVendingService
import core.protocols.ProtocolLogic import core.protocols.ProtocolLogic
import core.random63BitValue import core.random63BitValue
import core.utilities.UntrustworthyData import core.utilities.UntrustworthyData
@ -34,6 +33,7 @@ abstract class FetchDataProtocol<T : NamedByHash, W : Any>(
class HashNotFound(val requested: SecureHash) : BadAnswer() class HashNotFound(val requested: SecureHash) : BadAnswer()
class DownloadedVsRequestedDataMismatch(val requested: SecureHash, val got: SecureHash) : BadAnswer() class DownloadedVsRequestedDataMismatch(val requested: SecureHash, val got: SecureHash) : BadAnswer()
class Request(val hashes: List<SecureHash>, replyTo: SingleMessageRecipient, sessionID: Long) : AbstractRequestMessage(replyTo, sessionID)
data class Result<T : NamedByHash>(val fromDisk: List<T>, val downloaded: List<T>) data class Result<T : NamedByHash>(val fromDisk: List<T>, val downloaded: List<T>)
protected abstract val queryTopic: String protected abstract val queryTopic: String
@ -49,7 +49,7 @@ abstract class FetchDataProtocol<T : NamedByHash, W : Any>(
logger.trace("Requesting ${toFetch.size} dependency(s) for verification") logger.trace("Requesting ${toFetch.size} dependency(s) for verification")
val sid = random63BitValue() val sid = random63BitValue()
val fetchReq = DataVendingService.Request(toFetch, serviceHub.networkService.myAddress, sid) val fetchReq = Request(toFetch, serviceHub.networkService.myAddress, sid)
// TODO: Support "large message" response streaming so response sizes are not limited by RAM. // TODO: Support "large message" response streaming so response sizes are not limited by RAM.
val maybeItems = sendAndReceive<ArrayList<W?>>(queryTopic, otherSide, 0, sid, fetchReq) val maybeItems = sendAndReceive<ArrayList<W?>>(queryTopic, otherSide, 0, sid, fetchReq)
// Check for a buggy/malicious peer answering with something that we didn't ask for. // Check for a buggy/malicious peer answering with something that we didn't ask for.
@ -98,4 +98,5 @@ abstract class FetchDataProtocol<T : NamedByHash, W : Any>(
answers answers
} }
} }

View File

@ -1,14 +1,10 @@
package protocols package protocols
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import core.Party
import core.WireTransaction import core.WireTransaction
import core.crypto.DigitalSignature import core.crypto.DigitalSignature
import core.messaging.MessageRecipients import core.messaging.MessageRecipients
import core.messaging.StateMachineManager
import core.node.NodeInfo import core.node.NodeInfo
import core.node.services.NodeTimestamperService
import core.node.services.TimestamperService
import core.protocols.ProtocolLogic import core.protocols.ProtocolLogic
import core.random63BitValue import core.random63BitValue
import core.serialization.SerializedBytes import core.serialization.SerializedBytes
@ -27,19 +23,13 @@ class TimestampingProtocol(private val node: NodeInfo,
private val wtxBytes: SerializedBytes<WireTransaction>, private val wtxBytes: SerializedBytes<WireTransaction>,
override val progressTracker: ProgressTracker = TimestampingProtocol.tracker()) : ProtocolLogic<DigitalSignature.LegallyIdentifiable>() { override val progressTracker: ProgressTracker = TimestampingProtocol.tracker()) : ProtocolLogic<DigitalSignature.LegallyIdentifiable>() {
class Client(private val stateMachineManager: StateMachineManager, private val node: NodeInfo) : TimestamperService {
override val identity: Party = node.identity
override fun timestamp(wtxBytes: SerializedBytes<WireTransaction>): DigitalSignature.LegallyIdentifiable {
return stateMachineManager.add("platform.timestamping", TimestampingProtocol(node, wtxBytes)).get()
}
}
companion object { companion object {
object REQUESTING : ProgressTracker.Step("Requesting signature by timestamping service") object REQUESTING : ProgressTracker.Step("Requesting signature by timestamping service")
object VALIDATING : ProgressTracker.Step("Validating received signature from timestamping service") object VALIDATING : ProgressTracker.Step("Validating received signature from timestamping service")
fun tracker() = ProgressTracker(REQUESTING, VALIDATING) fun tracker() = ProgressTracker(REQUESTING, VALIDATING)
val TOPIC = "platform.timestamping.request"
} }
@ -49,8 +39,7 @@ class TimestampingProtocol(private val node: NodeInfo,
val sessionID = random63BitValue() val sessionID = random63BitValue()
val req = Request(wtxBytes, serviceHub.networkService.myAddress, sessionID) val req = Request(wtxBytes, serviceHub.networkService.myAddress, sessionID)
val maybeSignature = sendAndReceive<DigitalSignature.LegallyIdentifiable>( val maybeSignature = sendAndReceive<DigitalSignature.LegallyIdentifiable>(TOPIC, node.address, 0, sessionID, req)
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 // Check that the timestamping authority gave us back a valid signature and didn't break somehow
progressTracker.currentStep = VALIDATING progressTracker.currentStep = VALIDATING

View File

@ -1,8 +1,6 @@
package protocols package protocols
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import contracts.DealState
import contracts.FixableDealState
import core.* import core.*
import core.crypto.DigitalSignature import core.crypto.DigitalSignature
import core.crypto.signWithECDSA import core.crypto.signWithECDSA

View File

@ -1,11 +1,7 @@
package api package api
import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.ListenableFuture
import contracts.DealState import core.*
import core.ContractState
import core.SignedTransaction
import core.StateRef
import core.WireTransaction
import core.crypto.DigitalSignature import core.crypto.DigitalSignature
import core.crypto.SecureHash import core.crypto.SecureHash
import core.node.AbstractNode import core.node.AbstractNode

View File

@ -5,11 +5,9 @@ import core.Party
import core.TimestampCommand import core.TimestampCommand
import core.crypto.DigitalSignature import core.crypto.DigitalSignature
import core.crypto.signWithECDSA import core.crypto.signWithECDSA
import core.messaging.Message
import core.messaging.MessagingService import core.messaging.MessagingService
import core.seconds import core.seconds
import core.serialization.deserialize import core.serialization.deserialize
import core.serialization.serialize
import core.until import core.until
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import protocols.TimestampingProtocol import protocols.TimestampingProtocol
@ -31,14 +29,12 @@ class NodeTimestamperService(net: MessagingService,
val clock: Clock = Clock.systemDefaultZone(), val clock: Clock = Clock.systemDefaultZone(),
val tolerance: Duration = 30.seconds) : AbstractNodeService(net) { val tolerance: Duration = 30.seconds) : AbstractNodeService(net) {
companion object { companion object {
val TIMESTAMPING_PROTOCOL_TOPIC = "platform.timestamping.request"
private val logger = LoggerFactory.getLogger(NodeTimestamperService::class.java) private val logger = LoggerFactory.getLogger(NodeTimestamperService::class.java)
} }
init { init {
require(identity.owningKey == signingKey.public) require(identity.owningKey == signingKey.public)
addMessageHandler(TIMESTAMPING_PROTOCOL_TOPIC, addMessageHandler(TimestampingProtocol.TOPIC,
{ req: TimestampingProtocol.Request -> processRequest(req) }, { req: TimestampingProtocol.Request -> processRequest(req) },
{ message, e -> { message, e ->
if (e is TimestampingError) { if (e is TimestampingError) {

View File

@ -1,17 +1,11 @@
package core.node.subsystems package core.node.subsystems
import core.SignedTransaction import core.SignedTransaction
import core.crypto.SecureHash
import core.messaging.Message
import core.messaging.MessagingService import core.messaging.MessagingService
import core.messaging.SingleMessageRecipient
import core.messaging.send
import core.node.services.AbstractNodeService import core.node.services.AbstractNodeService
import core.node.subsystems.StorageService
import core.serialization.deserialize
import core.utilities.loggerFor import core.utilities.loggerFor
import protocols.AbstractRequestMessage
import protocols.FetchAttachmentsProtocol import protocols.FetchAttachmentsProtocol
import protocols.FetchDataProtocol
import protocols.FetchTransactionsProtocol import protocols.FetchTransactionsProtocol
import java.io.InputStream import java.io.InputStream
import javax.annotation.concurrent.ThreadSafe import javax.annotation.concurrent.ThreadSafe
@ -36,18 +30,16 @@ class DataVendingService(net: MessagingService, private val storage: StorageServ
init { init {
addMessageHandler(FetchTransactionsProtocol.TOPIC, addMessageHandler(FetchTransactionsProtocol.TOPIC,
{ req: Request -> handleTXRequest(req) }, { req: FetchDataProtocol.Request -> handleTXRequest(req) },
{ message, e -> logger.error("Failure processing data vending request.", e) } { message, e -> logger.error("Failure processing data vending request.", e) }
) )
addMessageHandler(FetchAttachmentsProtocol.TOPIC, addMessageHandler(FetchAttachmentsProtocol.TOPIC,
{ req: Request -> handleAttachmentRequest(req) }, { req: FetchDataProtocol.Request -> handleAttachmentRequest(req) },
{ message, e -> logger.error("Failure processing data vending request.", e) } { message, e -> logger.error("Failure processing data vending request.", e) }
) )
} }
class Request(val hashes: List<SecureHash>, replyTo: SingleMessageRecipient, sessionID: Long) : AbstractRequestMessage(replyTo, sessionID) private fun handleTXRequest(req: FetchDataProtocol.Request): List<SignedTransaction?> {
private fun handleTXRequest(req: Request): List<SignedTransaction?> {
require(req.hashes.isNotEmpty()) require(req.hashes.isNotEmpty())
return req.hashes.map { return req.hashes.map {
val tx = storage.validatedTransactions[it] val tx = storage.validatedTransactions[it]
@ -57,7 +49,7 @@ class DataVendingService(net: MessagingService, private val storage: StorageServ
} }
} }
private fun handleAttachmentRequest(req: Request): List<ByteArray?> { private fun handleAttachmentRequest(req: FetchDataProtocol.Request): List<ByteArray?> {
// TODO: Use Artemis message streaming support here, called "large messages". This avoids the need to buffer. // TODO: Use Artemis message streaming support here, called "large messages". This avoids the need to buffer.
require(req.hashes.isNotEmpty()) require(req.hashes.isNotEmpty())
return req.hashes.map { return req.hashes.map {

View File

@ -3,7 +3,7 @@ package demos.protocols
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import com.google.common.util.concurrent.FutureCallback import com.google.common.util.concurrent.FutureCallback
import com.google.common.util.concurrent.Futures import com.google.common.util.concurrent.Futures
import contracts.DealState import core.DealState
import core.Party import core.Party
import core.SignedTransaction import core.SignedTransaction
import core.messaging.SingleMessageRecipient import core.messaging.SingleMessageRecipient

View File

@ -1,8 +1,8 @@
package demos.protocols package demos.protocols
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import contracts.DealState
import contracts.InterestRateSwap import contracts.InterestRateSwap
import core.DealState
import core.StateAndRef import core.StateAndRef
import core.node.Node import core.node.Node
import core.node.NodeInfo import core.node.NodeInfo
@ -15,7 +15,6 @@ import core.utilities.ANSIProgressRenderer
import core.utilities.ProgressTracker import core.utilities.ProgressTracker
import demos.DemoClock import demos.DemoClock
import protocols.TwoPartyDealProtocol import protocols.TwoPartyDealProtocol
import java.security.KeyPair
import java.time.LocalDate import java.time.LocalDate
/** /**

View File

@ -4,7 +4,6 @@ import co.paralleluniverse.fibers.Suspendable
import core.* import core.*
import core.crypto.SecureHash import core.crypto.SecureHash
import core.node.NodeInfo import core.node.NodeInfo
import core.node.services.*
import core.protocols.ProtocolLogic import core.protocols.ProtocolLogic
import core.serialization.serialize import core.serialization.serialize
import core.testing.MockNetwork import core.testing.MockNetwork
@ -57,7 +56,7 @@ class TimestamperNodeServiceTest {
@Test @Test
fun successWithNetwork() { fun successWithNetwork() {
val timestamperNode = network.createNode(null, advertisedServices = TimestamperService.Type) val timestamperNode = network.createNode(null, advertisedServices = TimestamperService.Type)
val logName = NodeTimestamperService.TIMESTAMPING_PROTOCOL_TOPIC val logName = TimestampingProtocol.TOPIC
val psm = TestPSM(timestamperNode.info, clock.instant()) val psm = TestPSM(timestamperNode.info, clock.instant())
val future = timestamperNode.smm.add(logName, psm) val future = timestamperNode.smm.add(logName, psm)