Renames AuthenticatedObject to CommandWithParties for clarity.

This commit is contained in:
joeldudleyr3 2017-09-01 14:10:35 +01:00
parent 6bc44b96f1
commit d1ee84044d
18 changed files with 51 additions and 51 deletions

View File

@ -32,33 +32,33 @@ inline fun <R> requireThat(body: Requirements.() -> R) = Requirements.body()
// TODO: Provide a version of select that interops with Java
/** Filters the command list by type, party and public key all at once. */
inline fun <reified T : CommandData> Collection<AuthenticatedObject<CommandData>>.select(signer: PublicKey? = null,
inline fun <reified T : CommandData> Collection<CommandWithParties<CommandData>>.select(signer: PublicKey? = null,
party: AbstractParty? = null) =
filter { it.value is T }.
filter { if (signer == null) true else signer in it.signers }.
filter { if (party == null) true else party in it.signingParties }.
map { AuthenticatedObject(it.signers, it.signingParties, it.value as T) }
map { CommandWithParties(it.signers, it.signingParties, it.value as T) }
// TODO: Provide a version of select that interops with Java
/** Filters the command list by type, parties and public keys all at once. */
inline fun <reified T : CommandData> Collection<AuthenticatedObject<CommandData>>.select(signers: Collection<PublicKey>?,
inline fun <reified T : CommandData> Collection<CommandWithParties<CommandData>>.select(signers: Collection<PublicKey>?,
parties: Collection<Party>?) =
filter { it.value is T }.
filter { if (signers == null) true else it.signers.containsAll(signers) }.
filter { if (parties == null) true else it.signingParties.containsAll(parties) }.
map { AuthenticatedObject(it.signers, it.signingParties, it.value as T) }
map { CommandWithParties(it.signers, it.signingParties, it.value as T) }
/** Ensures that a transaction has only one command that is of the given type, otherwise throws an exception. */
inline fun <reified T : CommandData> Collection<AuthenticatedObject<CommandData>>.requireSingleCommand() = try {
inline fun <reified T : CommandData> Collection<CommandWithParties<CommandData>>.requireSingleCommand() = try {
select<T>().single()
} catch (e: NoSuchElementException) {
throw IllegalStateException("Required ${T::class.qualifiedName} command") // Better error message.
}
/** Ensures that a transaction has only one command that is of the given type, otherwise throws an exception. */
fun <C : CommandData> Collection<AuthenticatedObject<CommandData>>.requireSingleCommand(klass: Class<C>) =
mapNotNull { @Suppress("UNCHECKED_CAST") if (klass.isInstance(it.value)) it as AuthenticatedObject<C> else null }.single()
fun <C : CommandData> Collection<CommandWithParties<CommandData>>.requireSingleCommand(klass: Class<C>) =
mapNotNull { @Suppress("UNCHECKED_CAST") if (klass.isInstance(it.value)) it as CommandWithParties<C> else null }.single()
/**
* Simple functionality for verifying a move command. Verifies that each input has a signature from its owning key.
@ -67,7 +67,7 @@ fun <C : CommandData> Collection<AuthenticatedObject<CommandData>>.requireSingle
*/
@Throws(IllegalArgumentException::class)
inline fun <reified T : MoveCommand> verifyMoveCommand(inputs: List<OwnableState>,
commands: List<AuthenticatedObject<CommandData>>)
commands: List<CommandWithParties<CommandData>>)
: MoveCommand {
// Now check the digital signatures on the move command. Every input has an owning public key, and we must
// see a signature from each of those keys. The actual signatures have been verified against the transaction

View File

@ -307,9 +307,9 @@ interface MoveCommand : CommandData {
data class UpgradeCommand(val upgradedContractClass: Class<out UpgradedContract<*, *>>) : CommandData
// DOCSTART 6
/** Wraps an object that was signed by a public key, which may be a well known/recognised institutional key. */
/** A [Command] where the signing parties have been looked up if they have a well known/recognised institutional key. */
@CordaSerializable
data class AuthenticatedObject<out T : Any>(
data class CommandWithParties<out T : CommandData>(
val signers: List<PublicKey>,
/** If any public keys were recognised, the looked up institutions are available here */
val signingParties: List<Party>,

View File

@ -14,7 +14,7 @@ import java.util.function.Predicate
* - Downloading and locally storing all the dependencies of the transaction.
* - Resolving the input states and loading them into memory.
* - Doing some basic key lookups on the [Command]s to see if any keys are from a recognised party, thus converting the
* [Command] objects into [AuthenticatedObject].
* [Command] objects into [CommandWithParties].
* - Deserialising the output states.
*
* All the above refer to inputs using a (txhash, output index) pair.
@ -28,7 +28,7 @@ data class LedgerTransaction(
override val inputs: List<StateAndRef<ContractState>>,
override val outputs: List<TransactionState<ContractState>>,
/** Arbitrary data passed to the program of each input state. */
val commands: List<AuthenticatedObject<CommandData>>,
val commands: List<CommandWithParties<CommandData>>,
/** A list of [Attachment] objects identified by the transaction that are needed for this transaction to verify. */
val attachments: List<Attachment>,
/** The hash of the original serialised WireTransaction. */

View File

@ -84,7 +84,7 @@ data class WireTransaction(
// Look up public keys to authenticated identities. This is just a stub placeholder and will all change in future.
val authenticatedArgs = commands.map {
val parties = it.signers.mapNotNull { pk -> resolveIdentity(pk) }
AuthenticatedObject(it.signers, parties, it.value)
CommandWithParties(it.signers, parties, it.value)
}
// Open attachments specified in this transaction. If we haven't downloaded them, we fail.
val attachments = attachments.map { resolveAttachment(it) ?: throw AttachmentResolutionException(it) }

View File

@ -96,7 +96,7 @@ class TransactionTests : TestDependencyInjectionBase() {
val baseOutState = TransactionState(DummyContract.SingleOwnerState(0, ALICE), DUMMY_NOTARY)
val inputs = emptyList<StateAndRef<*>>()
val outputs = listOf(baseOutState, baseOutState.copy(notary = ALICE), baseOutState.copy(notary = BOB))
val commands = emptyList<AuthenticatedObject<CommandData>>()
val commands = emptyList<CommandWithParties<CommandData>>()
val attachments = emptyList<Attachment>()
val id = SecureHash.randomSHA256()
val timeWindow: TimeWindow? = null
@ -137,7 +137,7 @@ class TransactionTests : TestDependencyInjectionBase() {
val outState = inState.copy(notary = ALICE)
val inputs = listOf(StateAndRef(inState, StateRef(SecureHash.randomSHA256(), 0)))
val outputs = listOf(outState)
val commands = emptyList<AuthenticatedObject<CommandData>>()
val commands = emptyList<CommandWithParties<CommandData>>()
val attachments = emptyList<Attachment>()
val id = SecureHash.randomSHA256()
val timeWindow: TimeWindow? = null

View File

@ -132,9 +132,9 @@ exception will cause the transaction to be rejected.
Commands
^^^^^^^^
``LedgerTransaction`` contains the commands as a list of ``AuthenticatedObject`` instances.
``AuthenticatedObject`` pairs an object with a list of signers. In this case, ``AuthenticatedObject`` pairs a command
with a list of the entities that are required to sign a transaction where this command is present:
``LedgerTransaction`` contains the commands as a list of ``CommandWithParties`` instances.
``CommandWithParties`` pairs a command with a list of the entities that are required to sign a transaction
where this command is present:
.. container:: codeset
@ -153,7 +153,7 @@ Extracting commands
~~~~~~~~~~~~~~~~~~~
You can use the ``requireSingleCommand()`` helper method to extract commands.
``<C : CommandData> Collection<AuthenticatedObject<CommandData>>.requireSingleCommand(klass: Class<C>)`` asserts that
``<C : CommandData> Collection<CommandWithParties<CommandData>>.requireSingleCommand(klass: Class<C>)`` asserts that
the transaction contains exactly one command of type ``T``, and returns it. If there is not exactly one command of this
type in the transaction, an exception is thrown, rejecting the transaction.
@ -197,7 +197,7 @@ execution of ``verify()``:
@Override
public void verify(LedgerTransaction tx) {
final AuthenticatedObject<Commands> command = requireSingleCommand(tx.getCommands(), Commands.class);
final CommandWithParties<Commands> command = requireSingleCommand(tx.getCommands(), Commands.class);
if (command.getValue() instanceof Commands.Issue) {
// Issuance verification logic.

View File

@ -40,9 +40,9 @@ anonymous parties to full parties.
.. note:: These types are provisional and will change significantly in future as the identity framework becomes more
fleshed out.
AuthenticatedObject
-------------------
An ``AuthenticatedObject`` represents an object (like a command) and the list of associated signers.
CommandWithParties
------------------
A ``CommandWithParties`` represents a command and the list of associated signers.
Multi-signature support
-----------------------

View File

@ -21,7 +21,7 @@ Let's take a look at a simplified structure of the ``Clause`` class:
abstract fun verify(tx: LedgerTransaction,
inputs: List<S>,
outputs: List<S>,
commands: List<AuthenticatedObject<C>>,
commands: List<CommandWithParties<C>>,
groupingKey: K?): Set<C>
...
}
@ -235,7 +235,7 @@ Example from ``CommercialPaper.kt``:
override fun verify(tx: LedgerTransaction,
inputs: List<State>,
outputs: List<State>,
commands: List<AuthenticatedObject<Commands>>,
commands: List<CommandWithParties<Commands>>,
groupingKey: Issued<Terms>?): Set<Commands> {
val consumedCommands = super.verify(tx, inputs, outputs, commands, groupingKey)
...

View File

@ -114,7 +114,7 @@ Let's write a contract that enforces these constraints. We'll do this by modifyi
package com.template.contract;
import com.template.state.IOUState;
import net.corda.core.contracts.AuthenticatedObject;
import net.corda.core.contracts.CommandWithParties;
import net.corda.core.contracts.CommandData;
import net.corda.core.contracts.Contract;
import net.corda.core.transactions.LedgerTransaction;
@ -130,7 +130,7 @@ Let's write a contract that enforces these constraints. We'll do this by modifyi
@Override
public void verify(LedgerTransaction tx) {
final AuthenticatedObject<Create> command = requireSingleCommand(tx.getCommands(), Create.class);
final CommandWithParties<Create> command = requireSingleCommand(tx.getCommands(), Create.class);
requireThat(check -> {
// Constraints on the shape of the transaction.

View File

@ -124,7 +124,7 @@ and is included in the ``CommercialPaper.kt`` code.
override fun verify(tx: LedgerTransaction,
inputs: List<State>,
outputs: List<State>,
commands: List<AuthenticatedObject<Commands>>,
commands: List<CommandWithParties<Commands>>,
groupingKey: Issued<Terms>?): Set<Commands> {
val command = commands.requireSingleCommand<Commands.Move>()
val input = inputs.single()
@ -154,9 +154,9 @@ and is included in the ``CommercialPaper.kt`` code.
public Set<Commands> verify(@NotNull LedgerTransaction tx,
@NotNull List<? extends State> inputs,
@NotNull List<? extends State> outputs,
@NotNull List<? extends AuthenticatedObject<? extends Commands>> commands,
@NotNull List<? extends CommandWithParties<? extends Commands>> commands,
@NotNull State groupingKey) {
AuthenticatedObject<Commands.Move> cmd = requireSingleCommand(tx.getCommands(), Commands.Move.class);
CommandWithParties<Commands.Move> cmd = requireSingleCommand(tx.getCommands(), Commands.Move.class);
// There should be only a single input due to aggregation above
State input = single(inputs);

View File

@ -303,7 +303,7 @@ run two contracts one time each: Cash and CommercialPaper.
@Override
public void verify(LedgerTransaction tx) {
List<InOutGroup<State, State>> groups = tx.groupStates(State.class, State::withoutOwner);
AuthenticatedObject<Command> cmd = requireSingleCommand(tx.getCommands(), Commands.class);
CommandWithParties<Command> cmd = requireSingleCommand(tx.getCommands(), Commands.class);
We start by using the ``groupStates`` method, which takes a type and a function. State grouping is a way of ensuring
your contract can handle multiple unrelated states of the same type in the same transaction, which is needed for

View File

@ -155,11 +155,11 @@ public class JavaCommercialPaper implements Contract {
}
@NotNull
private List<AuthenticatedObject<Commands>> extractCommands(@NotNull LedgerTransaction tx) {
private List<CommandWithParties<Commands>> extractCommands(@NotNull LedgerTransaction tx) {
return tx.getCommands()
.stream()
.filter((AuthenticatedObject<CommandData> command) -> command.getValue() instanceof Commands)
.map((AuthenticatedObject<CommandData> command) -> new AuthenticatedObject<>(command.getSigners(), command.getSigningParties(), (Commands) command.getValue()))
.filter((CommandWithParties<CommandData> command) -> command.getValue() instanceof Commands)
.map((CommandWithParties<CommandData> command) -> new CommandWithParties<>(command.getSigners(), command.getSigningParties(), (Commands) command.getValue()))
.collect(Collectors.toList());
}
@ -171,17 +171,17 @@ public class JavaCommercialPaper implements Contract {
// 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.
final List<AuthenticatedObject<CommandData>> commands = tx.getCommands().stream().filter(
final List<CommandWithParties<CommandData>> commands = tx.getCommands().stream().filter(
it -> it.getValue() instanceof Commands
).collect(Collectors.toList());
final AuthenticatedObject<CommandData> command = onlyElementOf(commands);
final CommandWithParties<CommandData> command = onlyElementOf(commands);
final TimeWindow timeWindow = tx.getTimeWindow();
for (final LedgerTransaction.InOutGroup<State, State> group : groups) {
final List<State> inputs = group.getInputs();
final List<State> outputs = group.getOutputs();
if (command.getValue() instanceof Commands.Move) {
final AuthenticatedObject<Commands.Move> cmd = requireSingleCommand(tx.getCommands(), Commands.Move.class);
final CommandWithParties<Commands.Move> cmd = requireSingleCommand(tx.getCommands(), Commands.Move.class);
// There should be only a single input due to aggregation above
final State input = onlyElementOf(inputs);
@ -193,7 +193,7 @@ public class JavaCommercialPaper implements Contract {
throw new IllegalStateException("the state is propagated");
}
} else if (command.getValue() instanceof Commands.Redeem) {
final AuthenticatedObject<Commands.Redeem> cmd = requireSingleCommand(tx.getCommands(), Commands.Redeem.class);
final CommandWithParties<Commands.Redeem> cmd = requireSingleCommand(tx.getCommands(), Commands.Redeem.class);
// There should be only a single input due to aggregation above
final State input = onlyElementOf(inputs);
@ -216,7 +216,7 @@ public class JavaCommercialPaper implements Contract {
return Unit.INSTANCE;
});
} else if (command.getValue() instanceof Commands.Issue) {
final AuthenticatedObject<Commands.Issue> cmd = requireSingleCommand(tx.getCommands(), Commands.Issue.class);
final CommandWithParties<Commands.Issue> cmd = requireSingleCommand(tx.getCommands(), Commands.Issue.class);
final State output = onlyElementOf(outputs);
final Instant time = null == timeWindow
? null

View File

@ -106,7 +106,7 @@ interface CashSelection {
* vaults can ignore the issuer/depositRefs and just examine the amount fields.
*/
class Cash : OnLedgerAsset<Currency, Cash.Commands, Cash.State>() {
override fun extractCommands(commands: Collection<AuthenticatedObject<CommandData>>): List<AuthenticatedObject<Cash.Commands>>
override fun extractCommands(commands: Collection<CommandWithParties<CommandData>>): List<CommandWithParties<Cash.Commands>>
= commands.select<Cash.Commands>()
// DOCSTART 1
@ -238,7 +238,7 @@ class Cash : OnLedgerAsset<Currency, Cash.Commands, Cash.State>() {
private fun verifyIssueCommand(inputs: List<State>,
outputs: List<State>,
tx: LedgerTransaction,
issueCommand: AuthenticatedObject<Commands.Issue>,
issueCommand: CommandWithParties<Commands.Issue>,
currency: Currency,
issuer: PartyAndReference) {
// If we have an issue command, perform special processing: the group is allowed to have no inputs,

View File

@ -123,7 +123,7 @@ class CommodityContract : OnLedgerAsset<Commodity, CommodityContract.Commands, C
private fun verifyIssueCommand(inputs: List<State>,
outputs: List<State>,
tx: LedgerTransaction,
issueCommand: AuthenticatedObject<Commands.Issue>,
issueCommand: CommandWithParties<Commands.Issue>,
commodity: Commodity,
issuer: PartyAndReference) {
// If we have an issue command, perform special processing: the group is allowed to have no inputs,
@ -147,7 +147,7 @@ class CommodityContract : OnLedgerAsset<Commodity, CommodityContract.Commands, C
}
}
override fun extractCommands(commands: Collection<AuthenticatedObject<CommandData>>): List<AuthenticatedObject<Commands>>
override fun extractCommands(commands: Collection<CommandWithParties<CommandData>>): List<CommandWithParties<Commands>>
= commands.select<CommodityContract.Commands>()
/**

View File

@ -283,7 +283,7 @@ class Obligation<P : Any> : Contract {
private fun verifyIssueCommand(tx: LedgerTransaction,
inputs: List<FungibleAsset<Terms<P>>>,
outputs: List<FungibleAsset<Terms<P>>>,
issueCommand: AuthenticatedObject<Commands.Issue>,
issueCommand: CommandWithParties<Commands.Issue>,
key: Issued<Terms<P>>) {
// If we have an issue command, perform special processing: the group is allowed to have no inputs,
// and the output states must have a deposit reference owned by the signer.
@ -311,7 +311,7 @@ class Obligation<P : Any> : Contract {
private fun verifySettleCommand(tx: LedgerTransaction,
inputs: List<FungibleAsset<Terms<P>>>,
outputs: List<FungibleAsset<Terms<P>>>,
command: AuthenticatedObject<Commands.Settle<P>>,
command: CommandWithParties<Commands.Settle<P>>,
groupingKey: Issued<Terms<P>>) {
val obligor = groupingKey.issuer.party
val template = groupingKey.product
@ -394,7 +394,7 @@ class Obligation<P : Any> : Contract {
}
}
private fun verifyNetCommand(tx: LedgerTransaction, command: AuthenticatedObject<NetCommand>) {
private fun verifyNetCommand(tx: LedgerTransaction, command: CommandWithParties<NetCommand>) {
val groups = when (command.value.type) {
NetType.CLOSE_OUT -> tx.groupStates { it: Obligation.State<P> -> it.bilateralNetState }
NetType.PAYMENT -> tx.groupStates { it: Obligation.State<P> -> it.multilateralNetState }
@ -434,7 +434,7 @@ class Obligation<P : Any> : Contract {
private fun verifySetLifecycleCommand(inputs: List<FungibleAsset<Terms<P>>>,
outputs: List<FungibleAsset<Terms<P>>>,
tx: LedgerTransaction,
setLifecycleCommand: AuthenticatedObject<Commands.SetLifecycle>) {
setLifecycleCommand: CommandWithParties<Commands.SetLifecycle>) {
// Default must not change anything except lifecycle, so number of inputs and outputs must match
// exactly.
require(inputs.size == outputs.size) { "Number of inputs and outputs must match" }

View File

@ -282,7 +282,7 @@ abstract class OnLedgerAsset<T : Any, C : CommandData, S : FungibleAsset<T>> : C
}
}
abstract fun extractCommands(commands: Collection<AuthenticatedObject<CommandData>>): Collection<AuthenticatedObject<C>>
abstract fun extractCommands(commands: Collection<CommandWithParties<CommandData>>): Collection<CommandWithParties<C>>
/**
* Generate an transaction exiting assets from the ledger.

View File

@ -18,7 +18,7 @@ import java.security.PublicKey
import java.util.*
class DummyFungibleContract : OnLedgerAsset<Currency, DummyFungibleContract.Commands, DummyFungibleContract.State>() {
override fun extractCommands(commands: Collection<AuthenticatedObject<CommandData>>): List<AuthenticatedObject<DummyFungibleContract.Commands>>
override fun extractCommands(commands: Collection<CommandWithParties<CommandData>>): List<CommandWithParties<DummyFungibleContract.Commands>>
= commands.select<DummyFungibleContract.Commands>()
data class State(
@ -127,7 +127,7 @@ class DummyFungibleContract : OnLedgerAsset<Currency, DummyFungibleContract.Comm
private fun verifyIssueCommand(inputs: List<State>,
outputs: List<State>,
tx: LedgerTransaction,
issueCommand: AuthenticatedObject<Commands.Issue>,
issueCommand: CommandWithParties<Commands.Issue>,
currency: Currency,
issuer: PartyAndReference) {
// If we have an issue command, perform special processing: the group is allowed to have no inputs,

View File

@ -511,7 +511,7 @@ class InterestRateSwap : Contract {
checkLegDates(listOf(irs.fixedLeg, irs.floatingLeg))
}
private fun verifyFixCommand(inputs: List<State>, outputs: List<State>, command: AuthenticatedObject<Commands.Refix>) {
private fun verifyFixCommand(inputs: List<State>, outputs: List<State>, command: CommandWithParties<Commands.Refix>) {
val irs = outputs.filterIsInstance<State>().single()
val prevIrs = inputs.filterIsInstance<State>().single()
val paymentDifferences = getFloatingLegPaymentsDifferences(prevIrs.calculation.floatingLegPaymentSchedule, irs.calculation.floatingLegPaymentSchedule)