From 994abb3edb27f88ab79a4d3c061693e949b781b8 Mon Sep 17 00:00:00 2001 From: Sofus Mortensen Date: Tue, 16 Feb 2016 15:10:51 +0100 Subject: [PATCH] Added new project core. Project Contracts depends only on core. --- .gitignore | 5 +- build.gradle | 2 + contracts/build.gradle | 2 +- .../java/contracts/ICommercialPaperState.java | 0 .../src/main/kotlin}/Cash.kt | 0 .../src/main/kotlin}/CommercialPaper.kt | 0 .../main/kotlin/contracts/CommercialPaper.kt | 160 ------------------ core/build.gradle | 23 +++ .../core/crypto/AddressFormatException.java | 0 .../src}/main/java/core/crypto/Base58.java | 0 .../src}/main/kotlin/core/ContractsDSL.kt | 0 core/src/main/kotlin/core/IndentityService.kt | 13 ++ .../src}/main/kotlin/core/Structures.kt | 0 .../main/kotlin/core/TimestamperService.kt | 29 ++++ .../kotlin/core/TransactionVerification.kt | 139 +++++++++++++++ .../src}/main/kotlin/core/Transactions.kt | 0 {src => core/src}/main/kotlin/core/Utils.kt | 0 .../kotlin}/core/crypto/CryptoUtilities.kt | 0 .../kotlin/core/node/TimestampingError.kt | 15 ++ .../kotlin/core/serialization/ByteArrays.kt | 0 .../main/kotlin/core/serialization/Kryo.kt | 0 .../src}/main/kotlin/core/utilities/Emoji.kt | 0 settings.gradle | 3 +- src/main/kotlin/core/Services.kt | 24 --- .../core/node/TimestamperNodeService.kt | 13 -- 25 files changed, 227 insertions(+), 201 deletions(-) rename {src => contracts/src}/main/java/contracts/ICommercialPaperState.java (100%) rename {src/main/kotlin/contracts => contracts/src/main/kotlin}/Cash.kt (100%) rename {src/main/kotlin/contracts => contracts/src/main/kotlin}/CommercialPaper.kt (100%) delete mode 100644 contracts/src/main/kotlin/contracts/CommercialPaper.kt create mode 100644 core/build.gradle rename {src => core/src}/main/java/core/crypto/AddressFormatException.java (100%) rename {src => core/src}/main/java/core/crypto/Base58.java (100%) rename {src => core/src}/main/kotlin/core/ContractsDSL.kt (100%) create mode 100644 core/src/main/kotlin/core/IndentityService.kt rename {src => core/src}/main/kotlin/core/Structures.kt (100%) create mode 100644 core/src/main/kotlin/core/TimestamperService.kt create mode 100644 core/src/main/kotlin/core/TransactionVerification.kt rename {src => core/src}/main/kotlin/core/Transactions.kt (100%) rename {src => core/src}/main/kotlin/core/Utils.kt (100%) rename {src/main/java => core/src/main/kotlin}/core/crypto/CryptoUtilities.kt (100%) create mode 100644 core/src/main/kotlin/core/node/TimestampingError.kt rename {src => core/src}/main/kotlin/core/serialization/ByteArrays.kt (100%) rename {src => core/src}/main/kotlin/core/serialization/Kryo.kt (100%) rename {src => core/src}/main/kotlin/core/utilities/Emoji.kt (100%) diff --git a/.gitignore b/.gitignore index d97c406cb6..697a6bef4a 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,8 @@ TODO .gradle /build/ +/contracts/build +/core/build /docs/build/doctrees buyer @@ -62,5 +64,4 @@ atlassian-ide-plugin.xml # Crashlytics plugin (for Android Studio and IntelliJ) com_crashlytics_export_strings.xml crashlytics.properties -crashlytics-build.properties - +crashlytics-build.properties \ No newline at end of file diff --git a/build.gradle b/build.gradle index b6d2960bcc..299c497aea 100644 --- a/build.gradle +++ b/build.gradle @@ -55,6 +55,8 @@ configurations.all() { dependencies { testCompile 'junit:junit:4.12' + compile project(':contracts') + compile "com.google.code.findbugs:jsr305:3.0.1" compile "org.slf4j:slf4j-jdk14:1.7.13" diff --git a/contracts/build.gradle b/contracts/build.gradle index 7eb8280f27..0fb7b5696b 100644 --- a/contracts/build.gradle +++ b/contracts/build.gradle @@ -70,5 +70,5 @@ repositories { } dependencies { - compile rootProject + compile project(':core') } \ No newline at end of file diff --git a/src/main/java/contracts/ICommercialPaperState.java b/contracts/src/main/java/contracts/ICommercialPaperState.java similarity index 100% rename from src/main/java/contracts/ICommercialPaperState.java rename to contracts/src/main/java/contracts/ICommercialPaperState.java diff --git a/src/main/kotlin/contracts/Cash.kt b/contracts/src/main/kotlin/Cash.kt similarity index 100% rename from src/main/kotlin/contracts/Cash.kt rename to contracts/src/main/kotlin/Cash.kt diff --git a/src/main/kotlin/contracts/CommercialPaper.kt b/contracts/src/main/kotlin/CommercialPaper.kt similarity index 100% rename from src/main/kotlin/contracts/CommercialPaper.kt rename to contracts/src/main/kotlin/CommercialPaper.kt diff --git a/contracts/src/main/kotlin/contracts/CommercialPaper.kt b/contracts/src/main/kotlin/contracts/CommercialPaper.kt deleted file mode 100644 index 3773d9a32b..0000000000 --- a/contracts/src/main/kotlin/contracts/CommercialPaper.kt +++ /dev/null @@ -1,160 +0,0 @@ -/* - * 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 contracts - -import core.* -import core.crypto.NullPublicKey -import core.crypto.SecureHash -import core.crypto.toStringShort -import core.utilities.Emoji -import java.security.PublicKey -import java.time.Instant - -/** - * This is an ultra-trivial implementation of commercial paper, which is essentially a simpler version of a corporate - * bond. It can be seen as a company-specific currency. A company issues CP with a particular face value, say $100, - * but sells it for less, say $90. The paper can be redeemed for cash at a given date in the future. Thus this example - * would have a 10% interest rate with a single repayment. Commercial paper is often rolled over (the maturity date - * is adjusted as if the paper was redeemed and immediately repurchased, but without having to front the cash). - * - * This contract is not intended to realistically model CP. It is here only to act as a next step up above cash in - * the prototyping phase. It is thus very incomplete. - * - * Open issues: - * - In this model, you cannot merge or split CP. Can you do this normally? We could model CP as a specialised form - * of cash, or reuse some of the cash code? Waiting on response from Ayoub and Rajar about whether CP can always - * be split/merged or only in secondary markets. Even if current systems can't do this, would it be a desirable - * feature to have anyway? - * - The funding steps of CP is totally ignored in this model. - * - No attention is paid to the existing roles of custodians, funding banks, etc. - * - There are regional variations on the CP concept, for instance, American CP requires a special "CUSIP number" - * which may need to be tracked. That, in turn, requires validation logic (there is a bean validator that knows how - * to do this in the Apache BVal project). - */ - -val CP_PROGRAM_ID = SecureHash.sha256("replace-me-later-with-bytecode-hash") - -// TODO: Generalise the notion of an owned instrument into a superclass/supercontract. Consider composition vs inheritance. -class CommercialPaper : Contract { - // TODO: should reference the content of the legal agreement, not its URI - override val legalContractReference: SecureHash = SecureHash.sha256("https://en.wikipedia.org/wiki/Commercial_paper") - - data class State( - val issuance: PartyReference, - override val owner: PublicKey, - val faceValue: Amount, - val maturityDate: Instant - ) : OwnableState, ICommercialPaperState { - override val programRef = CP_PROGRAM_ID - - fun withoutOwner() = copy(owner = NullPublicKey) - override fun withNewOwner(newOwner: PublicKey) = Pair(Commands.Move(), copy(owner = newOwner)) - override fun toString() = "${Emoji.newspaper}CommercialPaper(of $faceValue redeemable on $maturityDate by '$issuance', owned by ${owner.toStringShort()})" - - // Although kotlin is smart enough not to need these, as we are using the ICommercialPaperState, we need to declare them explicitly for use later, - override fun withOwner(newOwner: PublicKey): ICommercialPaperState = copy(owner = newOwner) - override fun withIssuance(newIssuance: PartyReference): ICommercialPaperState = copy(issuance = newIssuance) - override fun withFaceValue(newFaceValue: Amount): ICommercialPaperState = copy(faceValue = newFaceValue) - override fun withMaturityDate(newMaturityDate: Instant): ICommercialPaperState = copy(maturityDate = newMaturityDate) - } - - interface Commands : CommandData { - class Move : TypeOnlyCommandData(), Commands - class Redeem : TypeOnlyCommandData(), Commands - // We don't need a nonce in the issue command, because the issuance.reference field should already be unique per CP. - // However, nothing in the platform enforces that uniqueness: it's up to the issuer. - class Issue : TypeOnlyCommandData(), Commands - } - - override fun verify(tx: TransactionForVerification) { - // Group by everything except owner: any modification to the CP at all is considered changing it fundamentally. - val groups = tx.groupStates() { it.withoutOwner() } - - // There are two possible things that can be done with this CP. The first is trading it. The second is redeeming - // it for cash on or after the maturity date. - val command = tx.commands.requireSingleCommand() - val timestamp: TimestampCommand? = tx.getTimestampBy(DummyTimestampingAuthority.identity) - - for (group in groups) { - when (command.value) { - is Commands.Move -> { - val input = group.inputs.single() - requireThat { - "the transaction is signed by the owner of the CP" by (command.signers.contains(input.owner)) - "the state is propagated" by (group.outputs.size == 1) - } - } - - is Commands.Redeem -> { - val input = group.inputs.single() - val received = tx.outStates.sumCashBy(input.owner) - val time = timestamp?.after ?: throw IllegalArgumentException("Redemptions must be timestamped") - requireThat { - "the paper must have matured" by (time > input.maturityDate) - "the received amount equals the face value" by (received == input.faceValue) - "the paper must be destroyed" by group.outputs.isEmpty() - "the transaction is signed by the owner of the CP" by (command.signers.contains(input.owner)) - } - } - - is Commands.Issue -> { - val output = group.outputs.single() - val time = timestamp?.before ?: throw IllegalArgumentException("Issuances must be timestamped") - requireThat { - // Don't allow people to issue commercial paper under other entities identities. - "the issuance is signed by the claimed issuer of the paper" by - (command.signers.contains(output.issuance.party.owningKey)) - "the face value is not zero" by (output.faceValue.pennies > 0) - "the maturity date is not in the past" by (time < output.maturityDate) - // Don't allow an existing CP state to be replaced by this issuance. - "there is no input state" by group.inputs.isEmpty() - } - } - - // TODO: Think about how to evolve contracts over time with new commands. - else -> throw IllegalArgumentException("Unrecognised command") - } - } - } - - /** - * Returns a transaction that issues commercial paper, owned by the issuing parties key. Does not update - * an existing transaction because you aren't able to issue multiple pieces of CP in a single transaction - * at the moment: this restriction is not fundamental and may be lifted later. - */ - fun generateIssue(issuance: PartyReference, faceValue: Amount, maturityDate: Instant): TransactionBuilder { - val state = State(issuance, issuance.party.owningKey, faceValue, maturityDate) - return TransactionBuilder().withItems(state, Command(Commands.Issue(), issuance.party.owningKey)) - } - - /** - * Updates the given partial transaction with an input/output/command to reassign ownership of the paper. - */ - fun generateMove(tx: TransactionBuilder, paper: StateAndRef, newOwner: PublicKey) { - tx.addInputState(paper.ref) - tx.addOutputState(paper.state.copy(owner = newOwner)) - tx.addCommand(Commands.Move(), paper.state.owner) - } - - /** - * Intended to be called by the issuer of some commercial paper, when an owner has notified us that they wish - * to redeem the paper. We must therefore send enough money to the key that owns the paper to satisfy the face - * value, and then ensure the paper is removed from the ledger. - * - * @throws InsufficientBalanceException if the wallet doesn't contain enough money to pay the redeemer - */ - @Throws(InsufficientBalanceException::class) - fun generateRedeem(tx: TransactionBuilder, paper: StateAndRef, wallet: List>) { - // Add the cash movement using the states in our wallet. - Cash().generateSpend(tx, paper.state.faceValue, paper.state.owner, wallet) - tx.addInputState(paper.ref) - tx.addCommand(CommercialPaper.Commands.Redeem(), paper.state.owner) - } -} - diff --git a/core/build.gradle b/core/build.gradle new file mode 100644 index 0000000000..c5dd2d101e --- /dev/null +++ b/core/build.gradle @@ -0,0 +1,23 @@ +group 'com.r3cev.prototyping' +version '1.0-SNAPSHOT' + +apply plugin: 'java' +apply plugin: 'kotlin' + +repositories { + mavenCentral() +} + +dependencies { + compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" + compile "org.jetbrains.kotlin:kotlin-test:$kotlin_version" + + compile "org.slf4j:slf4j-jdk14:1.7.13" + + compile("com.google.guava:guava:19.0") + + // Quasar: for the bytecode rewriting for state machines. + compile("co.paralleluniverse:quasar-core:${quasar_version}:jdk8") +// quasar("co.paralleluniverse:quasar-core:${quasar_version}:jdk8@jar") +} diff --git a/src/main/java/core/crypto/AddressFormatException.java b/core/src/main/java/core/crypto/AddressFormatException.java similarity index 100% rename from src/main/java/core/crypto/AddressFormatException.java rename to core/src/main/java/core/crypto/AddressFormatException.java diff --git a/src/main/java/core/crypto/Base58.java b/core/src/main/java/core/crypto/Base58.java similarity index 100% rename from src/main/java/core/crypto/Base58.java rename to core/src/main/java/core/crypto/Base58.java diff --git a/src/main/kotlin/core/ContractsDSL.kt b/core/src/main/kotlin/core/ContractsDSL.kt similarity index 100% rename from src/main/kotlin/core/ContractsDSL.kt rename to core/src/main/kotlin/core/ContractsDSL.kt diff --git a/core/src/main/kotlin/core/IndentityService.kt b/core/src/main/kotlin/core/IndentityService.kt new file mode 100644 index 0000000000..d4793fb3b0 --- /dev/null +++ b/core/src/main/kotlin/core/IndentityService.kt @@ -0,0 +1,13 @@ +package core + +import core.Party +import java.security.PublicKey + +/** + * An identity service maintains an bidirectional map of [Party]s to their associated public keys and thus supports + * lookup of a party given its key. This is obviously very incomplete and does not reflect everything a real identity + * service would provide. + */ +interface IdentityService { + fun partyFromKey(key: PublicKey): Party? +} diff --git a/src/main/kotlin/core/Structures.kt b/core/src/main/kotlin/core/Structures.kt similarity index 100% rename from src/main/kotlin/core/Structures.kt rename to core/src/main/kotlin/core/Structures.kt diff --git a/core/src/main/kotlin/core/TimestamperService.kt b/core/src/main/kotlin/core/TimestamperService.kt new file mode 100644 index 0000000000..4d7b92fb6e --- /dev/null +++ b/core/src/main/kotlin/core/TimestamperService.kt @@ -0,0 +1,29 @@ +package core + +import co.paralleluniverse.fibers.Suspendable +import core.crypto.DigitalSignature +import core.crypto.generateKeyPair +import core.serialization.SerializedBytes + +/** + * Simple interface (for testing) to an abstract timestamping service. Note that this is not "timestamping" in the + * blockchain sense of a total ordering of transactions, but rather, a signature from a well known/trusted timestamping + * service over a transaction that indicates the timestamp in it is accurate. Such a signature may not always be + * necessary: if there are multiple parties involved in a transaction then they can cross-check the timestamp + * themselves. + */ +interface TimestamperService { + @Suspendable + fun timestamp(wtxBytes: SerializedBytes): DigitalSignature.LegallyIdentifiable + + /** The name+pubkey that this timestamper will sign with. */ + val identity: Party +} + +// Smart contracts may wish to specify explicitly which timestamping authorities are trusted to assert the time. +// We define a dummy authority here to allow to us to develop prototype contracts in the absence of a real authority. +// The timestamper itself is implemented in the unit test part of the code (in TestUtils.kt). +object DummyTimestampingAuthority { + val key = generateKeyPair() + val identity = Party("The dummy timestamper", key.public) +} diff --git a/core/src/main/kotlin/core/TransactionVerification.kt b/core/src/main/kotlin/core/TransactionVerification.kt new file mode 100644 index 0000000000..69e5f4079a --- /dev/null +++ b/core/src/main/kotlin/core/TransactionVerification.kt @@ -0,0 +1,139 @@ +/* + * 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 + +import core.crypto.SecureHash +import java.util.* + +class TransactionResolutionException(val hash: SecureHash) : Exception() +class TransactionConflictException(val conflictRef: StateRef, val tx1: LedgerTransaction, val tx2: LedgerTransaction) : Exception() + +/** + * A TransactionGroup defines a directed acyclic graph of transactions that can be resolved with each other and then + * verified. Successful verification does not imply the non-existence of other conflicting transactions: simply that + * this subgraph does not contain conflicts and is accepted by the involved contracts. + * + * The inputs of the provided transactions must be resolvable either within the [transactions] set, or from the + * [nonVerifiedRoots] set. Transactions in the non-verified set are ignored other than for looking up input states. + */ +class TransactionGroup(val transactions: Set, val nonVerifiedRoots: Set) { + + /** + * Verifies the group and returns the set of resolved transactions. + */ + fun verify(programMap: ContractFactory): Set { + // Check that every input can be resolved to an output. + // Check that no output is referenced by more than one input. + // Cycles should be impossible due to the use of hashes as pointers. + check(transactions.intersect(nonVerifiedRoots).isEmpty()) + + val hashToTXMap: Map> = (transactions + nonVerifiedRoots).groupBy { it.hash } + val refToConsumingTXMap = hashMapOf() + + val resolved = HashSet(transactions.size) + for (tx in transactions) { + val inputs = ArrayList(tx.inputs.size) + for (ref in tx.inputs) { + val conflict = refToConsumingTXMap[ref] + if (conflict != null) + throw TransactionConflictException(ref, tx, conflict) + refToConsumingTXMap[ref] = tx + + // Look up the connecting transaction. + val ltx = hashToTXMap[ref.txhash]?.single() ?: throw TransactionResolutionException(ref.txhash) + // Look up the output in that transaction by index. + inputs.add(ltx.outputs[ref.index]) + } + resolved.add(TransactionForVerification(inputs, tx.outputs, tx.commands, tx.hash)) + } + + for (tx in resolved) + tx.verify(programMap) + return resolved + } + +} + +/** A transaction in fully resolved and sig-checked form, ready for passing as input to a verification function. */ +data class TransactionForVerification(val inStates: List, + val outStates: List, + val commands: List>, + val origHash: SecureHash) { + override fun hashCode() = origHash.hashCode() + override fun equals(other: Any?) = other is TransactionForVerification && other.origHash == origHash + + /** + * @throws TransactionVerificationException if a contract throws an exception, the original is in the cause field + * @throws IllegalStateException if a state refers to an unknown contract. + */ + @Throws(TransactionVerificationException::class, IllegalStateException::class) + fun verify(programMap: ContractFactory) { + // For each input and output state, locate the program to run. Then execute the verification function. If any + // throws an exception, the entire transaction is invalid. + val programHashes = (inStates.map { it.programRef } + outStates.map { it.programRef }).toSet() + for (hash in programHashes) { + val program: Contract = programMap[hash] + try { + program.verify(this) + } catch(e: Throwable) { + throw TransactionVerificationException(this, program, e) + } + } + } + + /** + * Utilities for contract writers to incorporate into their logic. + */ + + data class InOutGroup(val inputs: List, val outputs: List) + + // A shortcut to make IDE auto-completion more intuitive for Java users. + fun getTimestampBy(timestampingAuthority: Party): TimestampCommand? = commands.getTimestampBy(timestampingAuthority) + + // For Java users. + fun groupStates(ofType: Class, selector: (T) -> Any): List> { + val inputs = inStates.filterIsInstance(ofType) + val outputs = outStates.filterIsInstance(ofType) + + val inGroups = inputs.groupBy(selector) + val outGroups = outputs.groupBy(selector) + + @Suppress("DEPRECATION") + return groupStatesInternal(inGroups, outGroups) + } + + // For Kotlin users: this version has nicer syntax and avoids reflection/object creation for the lambda. + inline fun groupStates(selector: (T) -> Any): List> { + val inputs = inStates.filterIsInstance() + val outputs = outStates.filterIsInstance() + + val inGroups = inputs.groupBy(selector) + val outGroups = outputs.groupBy(selector) + + @Suppress("DEPRECATION") + return groupStatesInternal(inGroups, outGroups) + } + + @Deprecated("Do not use this directly: exposed as public only due to function inlining") + fun groupStatesInternal(inGroups: Map>, outGroups: Map>): List> { + val result = ArrayList>() + + for ((k, v) in inGroups.entries) + result.add(InOutGroup(v, outGroups[k] ?: emptyList())) + for ((k, v) in outGroups.entries) { + if (inGroups[k] == null) + result.add(InOutGroup(emptyList(), v)) + } + + return result + } +} + +/** Thrown if a verification fails due to a contract rejection. */ +class TransactionVerificationException(val tx: TransactionForVerification, val contract: Contract, cause: Throwable?) : Exception(cause) \ No newline at end of file diff --git a/src/main/kotlin/core/Transactions.kt b/core/src/main/kotlin/core/Transactions.kt similarity index 100% rename from src/main/kotlin/core/Transactions.kt rename to core/src/main/kotlin/core/Transactions.kt diff --git a/src/main/kotlin/core/Utils.kt b/core/src/main/kotlin/core/Utils.kt similarity index 100% rename from src/main/kotlin/core/Utils.kt rename to core/src/main/kotlin/core/Utils.kt diff --git a/src/main/java/core/crypto/CryptoUtilities.kt b/core/src/main/kotlin/core/crypto/CryptoUtilities.kt similarity index 100% rename from src/main/java/core/crypto/CryptoUtilities.kt rename to core/src/main/kotlin/core/crypto/CryptoUtilities.kt diff --git a/core/src/main/kotlin/core/node/TimestampingError.kt b/core/src/main/kotlin/core/node/TimestampingError.kt new file mode 100644 index 0000000000..97a772f6cc --- /dev/null +++ b/core/src/main/kotlin/core/node/TimestampingError.kt @@ -0,0 +1,15 @@ +package core.node + +sealed class TimestampingError : Exception() { + class RequiresExactlyOneCommand : TimestampingError() + /** + * Thrown if an attempt is made to timestamp a transaction using a trusted timestamper, but the time on the + * transaction is too far in the past or future relative to the local clock and thus the timestamper would reject + * it. + */ + class NotOnTimeException : TimestampingError() + + /** Thrown if the command in the transaction doesn't list this timestamping authorities public key as a signer */ + class NotForMe : TimestampingError() +} + diff --git a/src/main/kotlin/core/serialization/ByteArrays.kt b/core/src/main/kotlin/core/serialization/ByteArrays.kt similarity index 100% rename from src/main/kotlin/core/serialization/ByteArrays.kt rename to core/src/main/kotlin/core/serialization/ByteArrays.kt diff --git a/src/main/kotlin/core/serialization/Kryo.kt b/core/src/main/kotlin/core/serialization/Kryo.kt similarity index 100% rename from src/main/kotlin/core/serialization/Kryo.kt rename to core/src/main/kotlin/core/serialization/Kryo.kt diff --git a/src/main/kotlin/core/utilities/Emoji.kt b/core/src/main/kotlin/core/utilities/Emoji.kt similarity index 100% rename from src/main/kotlin/core/utilities/Emoji.kt rename to core/src/main/kotlin/core/utilities/Emoji.kt diff --git a/settings.gradle b/settings.gradle index a8566e818b..3be1a9b166 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1,3 @@ rootProject.name = 'r3prototyping' -include 'contracts' \ No newline at end of file +include 'contracts' +include 'core' \ No newline at end of file diff --git a/src/main/kotlin/core/Services.kt b/src/main/kotlin/core/Services.kt index d9dd1e6f68..e6593f327b 100644 --- a/src/main/kotlin/core/Services.kt +++ b/src/main/kotlin/core/Services.kt @@ -64,30 +64,6 @@ interface KeyManagementService { fun freshKey(): KeyPair } -/** - * An identity service maintains an bidirectional map of [Party]s to their associated public keys and thus supports - * lookup of a party given its key. This is obviously very incomplete and does not reflect everything a real identity - * service would provide. - */ -interface IdentityService { - fun partyFromKey(key: PublicKey): Party? -} - -/** - * Simple interface (for testing) to an abstract timestamping service. Note that this is not "timestamping" in the - * blockchain sense of a total ordering of transactions, but rather, a signature from a well known/trusted timestamping - * service over a transaction that indicates the timestamp in it is accurate. Such a signature may not always be - * necessary: if there are multiple parties involved in a transaction then they can cross-check the timestamp - * themselves. - */ -interface TimestamperService { - @Suspendable - fun timestamp(wtxBytes: SerializedBytes): DigitalSignature.LegallyIdentifiable - - /** The name+pubkey that this timestamper will sign with. */ - val identity: Party -} - // Smart contracts may wish to specify explicitly which timestamping authorities are trusted to assert the time. // We define a dummy authority here to allow to us to develop prototype contracts in the absence of a real authority. // The timestamper itself is implemented in the unit test part of the code (in TestUtils.kt). diff --git a/src/main/kotlin/core/node/TimestamperNodeService.kt b/src/main/kotlin/core/node/TimestamperNodeService.kt index 433cc7a480..a4cf3f080a 100644 --- a/src/main/kotlin/core/node/TimestamperNodeService.kt +++ b/src/main/kotlin/core/node/TimestamperNodeService.kt @@ -31,19 +31,6 @@ class TimestampingMessages { data class Request(val tx: SerializedBytes, val replyTo: MessageRecipients, val replyToTopic: String) } -sealed class TimestampingError : Exception() { - class RequiresExactlyOneCommand : TimestampingError() - /** - * Thrown if an attempt is made to timestamp a transaction using a trusted timestamper, but the time on the - * transaction is too far in the past or future relative to the local clock and thus the timestamper would reject - * it. - */ - class NotOnTimeException : TimestampingError() - - /** Thrown if the command in the transaction doesn't list this timestamping authorities public key as a signer */ - class NotForMe : TimestampingError() -} - /** * 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.