mirror of
https://github.com/corda/corda.git
synced 2025-01-30 16:14:39 +00:00
Small cleanup of commands.
1. Rename Command -> CommandData, WireCommand -> Command, PartialTransaction.addArg -> addCommand 2. Add some helper functions to PartialTransaction to make creation of transactions simpler.
This commit is contained in:
parent
4cec5dac02
commit
6144ccc2c7
@ -66,8 +66,8 @@ class Cash : Contract {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Just for grouping
|
// Just for grouping
|
||||||
interface Commands : Command {
|
interface Commands : CommandData {
|
||||||
class Move() : TypeOnlyCommand(), Commands
|
class Move() : TypeOnlyCommandData(), Commands
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows new cash states to be issued into existence: the nonce ("number used once") ensures the transaction
|
* Allows new cash states to be issued into existence: the nonce ("number used once") ensures the transaction
|
||||||
@ -155,7 +155,7 @@ class Cash : Contract {
|
|||||||
check(tx.inputStates().isEmpty())
|
check(tx.inputStates().isEmpty())
|
||||||
check(tx.outputStates().sumCashOrNull() == null)
|
check(tx.outputStates().sumCashOrNull() == null)
|
||||||
tx.addOutputState(Cash.State(at, amount, owner))
|
tx.addOutputState(Cash.State(at, amount, owner))
|
||||||
tx.addArg(WireCommand(Cash.Commands.Issue(), listOf(at.party.owningKey)))
|
tx.addCommand(Cash.Commands.Issue(), at.party.owningKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -233,7 +233,7 @@ class Cash : Contract {
|
|||||||
for (state in outputs) tx.addOutputState(state)
|
for (state in outputs) tx.addOutputState(state)
|
||||||
// What if we already have a move command with the right keys? Filter it out here or in platform code?
|
// What if we already have a move command with the right keys? Filter it out here or in platform code?
|
||||||
val keysList = keysUsed.toList()
|
val keysList = keysUsed.toList()
|
||||||
tx.addArg(WireCommand(Commands.Move(), keysList))
|
tx.addCommand(Commands.Move(), keysList)
|
||||||
return keysList
|
return keysList
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,12 +53,12 @@ class CommercialPaper : Contract {
|
|||||||
override fun withNewOwner(newOwner: PublicKey) = Pair(Commands.Move(), copy(owner = newOwner))
|
override fun withNewOwner(newOwner: PublicKey) = Pair(Commands.Move(), copy(owner = newOwner))
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Commands : Command {
|
interface Commands : CommandData {
|
||||||
class Move : TypeOnlyCommand(), Commands
|
class Move : TypeOnlyCommandData(), Commands
|
||||||
class Redeem : TypeOnlyCommand(), 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.
|
// 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.
|
// However, nothing in the platform enforces that uniqueness: it's up to the issuer.
|
||||||
class Issue : TypeOnlyCommand(), Commands
|
class Issue : TypeOnlyCommandData(), Commands
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun verify(tx: TransactionForVerification) {
|
override fun verify(tx: TransactionForVerification) {
|
||||||
@ -119,7 +119,7 @@ class CommercialPaper : Contract {
|
|||||||
*/
|
*/
|
||||||
fun craftIssue(issuance: PartyReference, faceValue: Amount, maturityDate: Instant): PartialTransaction {
|
fun craftIssue(issuance: PartyReference, faceValue: Amount, maturityDate: Instant): PartialTransaction {
|
||||||
val state = State(issuance, issuance.party.owningKey, faceValue, maturityDate)
|
val state = State(issuance, issuance.party.owningKey, faceValue, maturityDate)
|
||||||
return PartialTransaction().withItems(state, WireCommand(Commands.Issue(), issuance.party.owningKey))
|
return PartialTransaction().withItems(state, Command(Commands.Issue(), issuance.party.owningKey))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -128,7 +128,7 @@ class CommercialPaper : Contract {
|
|||||||
fun craftMove(tx: PartialTransaction, paper: StateAndRef<State>, newOwner: PublicKey) {
|
fun craftMove(tx: PartialTransaction, paper: StateAndRef<State>, newOwner: PublicKey) {
|
||||||
tx.addInputState(paper.ref)
|
tx.addInputState(paper.ref)
|
||||||
tx.addOutputState(paper.state.copy(owner = newOwner))
|
tx.addOutputState(paper.state.copy(owner = newOwner))
|
||||||
tx.addArg(WireCommand(Commands.Move(), paper.state.owner))
|
tx.addCommand(Commands.Move(), paper.state.owner)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -143,7 +143,7 @@ class CommercialPaper : Contract {
|
|||||||
// Add the cash movement using the states in our wallet.
|
// Add the cash movement using the states in our wallet.
|
||||||
Cash().craftSpend(tx, paper.state.faceValue, paper.state.owner, wallet)
|
Cash().craftSpend(tx, paper.state.faceValue, paper.state.owner, wallet)
|
||||||
tx.addInputState(paper.ref)
|
tx.addInputState(paper.ref)
|
||||||
tx.addArg(WireCommand(CommercialPaper.Commands.Redeem(), paper.state.owner))
|
tx.addCommand(CommercialPaper.Commands.Redeem(), paper.state.owner)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,10 +66,10 @@ class CrowdFund : Contract {
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
interface Commands : Command {
|
interface Commands : CommandData {
|
||||||
class Register : TypeOnlyCommand(), Commands
|
class Register : TypeOnlyCommandData(), Commands
|
||||||
class Pledge : TypeOnlyCommand(), Commands
|
class Pledge : TypeOnlyCommandData(), Commands
|
||||||
class Close : TypeOnlyCommand(), Commands
|
class Close : TypeOnlyCommandData(), Commands
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun verify(tx: TransactionForVerification) {
|
override fun verify(tx: TransactionForVerification) {
|
||||||
@ -146,7 +146,7 @@ class CrowdFund : Contract {
|
|||||||
fun craftRegister(owner: PartyReference, fundingTarget: Amount, fundingName: String, closingTime: Instant): PartialTransaction {
|
fun craftRegister(owner: PartyReference, fundingTarget: Amount, fundingName: String, closingTime: Instant): PartialTransaction {
|
||||||
val campaign = Campaign(owner = owner.party.owningKey, name = fundingName, target = fundingTarget, closingTime = closingTime)
|
val campaign = Campaign(owner = owner.party.owningKey, name = fundingName, target = fundingTarget, closingTime = closingTime)
|
||||||
val state = State(campaign)
|
val state = State(campaign)
|
||||||
return PartialTransaction().withItems(state, WireCommand(Commands.Register(), owner.party.owningKey))
|
return PartialTransaction().withItems(state, Command(Commands.Register(), owner.party.owningKey))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -157,13 +157,13 @@ class CrowdFund : Contract {
|
|||||||
tx.addOutputState(campaign.state.copy(
|
tx.addOutputState(campaign.state.copy(
|
||||||
pledges = campaign.state.pledges + CrowdFund.Pledge(subscriber, 1000.DOLLARS)
|
pledges = campaign.state.pledges + CrowdFund.Pledge(subscriber, 1000.DOLLARS)
|
||||||
))
|
))
|
||||||
tx.addArg(WireCommand(Commands.Pledge(), subscriber))
|
tx.addCommand(Commands.Pledge(), subscriber)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun craftClose(tx: PartialTransaction, campaign: StateAndRef<State>, wallet: List<StateAndRef<Cash.State>>) {
|
fun craftClose(tx: PartialTransaction, campaign: StateAndRef<State>, wallet: List<StateAndRef<Cash.State>>) {
|
||||||
tx.addInputState(campaign.ref)
|
tx.addInputState(campaign.ref)
|
||||||
tx.addOutputState(campaign.state.copy(closed = true))
|
tx.addOutputState(campaign.state.copy(closed = true))
|
||||||
tx.addArg(WireCommand(Commands.Close(), campaign.state.campaign.owner))
|
tx.addCommand(Commands.Close(), campaign.state.campaign.owner)
|
||||||
// If campaign target has not been met, compose cash returns
|
// If campaign target has not been met, compose cash returns
|
||||||
if (campaign.state.pledgedAmount < campaign.state.campaign.target) {
|
if (campaign.state.pledgedAmount < campaign.state.campaign.target) {
|
||||||
for (pledge in campaign.state.pledges) {
|
for (pledge in campaign.state.pledges) {
|
||||||
|
@ -91,7 +91,7 @@ public class JavaCommercialPaper implements Contract {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Commands implements core.Command {
|
public static class Commands implements core.CommandData {
|
||||||
public static class Move extends Commands {
|
public static class Move extends Commands {
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
@ -114,7 +114,7 @@ public class JavaCommercialPaper implements Contract {
|
|||||||
List<InOutGroup<State>> groups = tx.groupStates(State.class, State::withoutOwner);
|
List<InOutGroup<State>> groups = tx.groupStates(State.class, State::withoutOwner);
|
||||||
|
|
||||||
// Find the command that instructs us what to do and check there's exactly one.
|
// Find the command that instructs us what to do and check there's exactly one.
|
||||||
AuthenticatedObject<Command> cmd = requireSingleCommand(tx.getCommands(), Commands.class);
|
AuthenticatedObject<CommandData> cmd = requireSingleCommand(tx.getCommands(), Commands.class);
|
||||||
|
|
||||||
Instant time = tx.getTime(); // Can be null/missing.
|
Instant time = tx.getTime(); // Can be null/missing.
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ private class TwoPartyTradeProtocolImpl(private val smm: StateMachineManager) :
|
|||||||
val freshKey = serviceHub.keyManagementService.freshKey()
|
val freshKey = serviceHub.keyManagementService.freshKey()
|
||||||
val (command, state) = tradeRequest.assetForSale.state.withNewOwner(freshKey.public)
|
val (command, state) = tradeRequest.assetForSale.state.withNewOwner(freshKey.public)
|
||||||
ptx.addOutputState(state)
|
ptx.addOutputState(state)
|
||||||
ptx.addArg(WireCommand(command, tradeRequest.assetForSale.state.owner))
|
ptx.addCommand(command, tradeRequest.assetForSale.state.owner)
|
||||||
|
|
||||||
// Now sign the transaction with whatever keys we need to move the cash.
|
// Now sign the transaction with whatever keys we need to move the cash.
|
||||||
for (k in cashSigningPubKeys) {
|
for (k in cashSigningPubKeys) {
|
||||||
|
@ -106,17 +106,17 @@ fun Iterable<Amount>.sumOrZero(currency: Currency) = if (iterator().hasNext()) s
|
|||||||
//// Authenticated commands ///////////////////////////////////////////////////////////////////////////////////////////
|
//// Authenticated commands ///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/** Filters the command list by type, party and public key all at once. */
|
/** Filters the command list by type, party and public key all at once. */
|
||||||
inline fun <reified T : Command> List<AuthenticatedObject<Command>>.select(signer: PublicKey? = null, party: Party? = null) =
|
inline fun <reified T : CommandData> List<AuthenticatedObject<CommandData>>.select(signer: PublicKey? = null, party: Party? = null) =
|
||||||
filter { it.value is T }.
|
filter { it.value is T }.
|
||||||
filter { if (signer == null) true else it.signers.contains(signer) }.
|
filter { if (signer == null) true else it.signers.contains(signer) }.
|
||||||
filter { if (party == null) true else it.signingParties.contains(party) }.
|
filter { if (party == null) true else it.signingParties.contains(party) }.
|
||||||
map { AuthenticatedObject<T>(it.signers, it.signingParties, it.value as T) }
|
map { AuthenticatedObject<T>(it.signers, it.signingParties, it.value as T) }
|
||||||
|
|
||||||
inline fun <reified T : Command> List<AuthenticatedObject<Command>>.requireSingleCommand() = try {
|
inline fun <reified T : CommandData> List<AuthenticatedObject<CommandData>>.requireSingleCommand() = try {
|
||||||
select<T>().single()
|
select<T>().single()
|
||||||
} catch (e: NoSuchElementException) {
|
} catch (e: NoSuchElementException) {
|
||||||
throw IllegalStateException("Required ${T::class.qualifiedName} command") // Better error message.
|
throw IllegalStateException("Required ${T::class.qualifiedName} command") // Better error message.
|
||||||
}
|
}
|
||||||
|
|
||||||
// For Java
|
// For Java
|
||||||
fun List<AuthenticatedObject<Command>>.requireSingleCommand(klass: Class<out Command>) = filter { klass.isInstance(it) }.single()
|
fun List<AuthenticatedObject<CommandData>>.requireSingleCommand(klass: Class<out CommandData>) = filter { klass.isInstance(it) }.single()
|
||||||
|
@ -31,7 +31,7 @@ interface OwnableState : ContractState {
|
|||||||
val owner: PublicKey
|
val owner: PublicKey
|
||||||
|
|
||||||
/** Copies the underlying data structure, replacing the owner field with this new value and leaving the rest alone */
|
/** Copies the underlying data structure, replacing the owner field with this new value and leaving the rest alone */
|
||||||
fun withNewOwner(newOwner: PublicKey): Pair<Command, OwnableState>
|
fun withNewOwner(newOwner: PublicKey): Pair<CommandData, OwnableState>
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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!) */
|
||||||
@ -63,14 +63,19 @@ data class PartyReference(val party: Party, val reference: OpaqueBytes) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Marker interface for classes that represent commands */
|
/** Marker interface for classes that represent commands */
|
||||||
interface Command
|
interface CommandData
|
||||||
|
|
||||||
/** Commands that inherit from this are intended to have no data items: it's only their presence that matters. */
|
/** Commands that inherit from this are intended to have no data items: it's only their presence that matters. */
|
||||||
abstract class TypeOnlyCommand : Command {
|
abstract class TypeOnlyCommandData : CommandData {
|
||||||
override fun equals(other: Any?) = other?.javaClass == javaClass
|
override fun equals(other: Any?) = other?.javaClass == javaClass
|
||||||
override fun hashCode() = javaClass.name.hashCode()
|
override fun hashCode() = javaClass.name.hashCode()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Command data/content plus pubkey pair: the signature is stored at the end of the serialized bytes */
|
||||||
|
data class Command(val data: CommandData, val pubkeys: List<PublicKey>) {
|
||||||
|
constructor(data: CommandData, key: PublicKey) : this(data, listOf(key))
|
||||||
|
}
|
||||||
|
|
||||||
/** Wraps an object that was signed by a public key, which may be a well known/recognised institutional key. */
|
/** Wraps an object that was signed by a public key, which may be a well known/recognised institutional key. */
|
||||||
data class AuthenticatedObject<out T : Any>(
|
data class AuthenticatedObject<out T : Any>(
|
||||||
val signers: List<PublicKey>,
|
val signers: List<PublicKey>,
|
||||||
|
@ -46,19 +46,14 @@ import java.util.*
|
|||||||
* database and replaced with the real objects. TFV is the form that is finally fed into the contracts.
|
* database and replaced with the real objects. TFV is the form that is finally fed into the contracts.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** Serialized command plus pubkey pair: the signature is stored at the end of the serialized bytes */
|
|
||||||
data class WireCommand(val command: Command, val pubkeys: List<PublicKey>) {
|
|
||||||
constructor(command: Command, key: PublicKey) : this(command, listOf(key))
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Transaction ready for serialisation, without any signatures attached. */
|
/** Transaction ready for serialisation, without any signatures attached. */
|
||||||
data class WireTransaction(val inputStates: List<ContractStateRef>,
|
data class WireTransaction(val inputStates: List<ContractStateRef>,
|
||||||
val outputStates: List<ContractState>,
|
val outputStates: List<ContractState>,
|
||||||
val commands: List<WireCommand>) {
|
val commands: List<Command>) {
|
||||||
fun toLedgerTransaction(timestamp: Instant?, identityService: IdentityService, originalHash: SecureHash): LedgerTransaction {
|
fun toLedgerTransaction(timestamp: Instant?, identityService: IdentityService, originalHash: SecureHash): LedgerTransaction {
|
||||||
val authenticatedArgs = commands.map {
|
val authenticatedArgs = commands.map {
|
||||||
val institutions = it.pubkeys.mapNotNull { pk -> identityService.partyFromKey(pk) }
|
val institutions = it.pubkeys.mapNotNull { pk -> identityService.partyFromKey(pk) }
|
||||||
AuthenticatedObject(it.pubkeys, institutions, it.command)
|
AuthenticatedObject(it.pubkeys, institutions, it.data)
|
||||||
}
|
}
|
||||||
return LedgerTransaction(inputStates, outputStates, authenticatedArgs, timestamp, originalHash)
|
return LedgerTransaction(inputStates, outputStates, authenticatedArgs, timestamp, originalHash)
|
||||||
}
|
}
|
||||||
@ -67,14 +62,14 @@ data class WireTransaction(val inputStates: List<ContractStateRef>,
|
|||||||
/** A mutable transaction that's in the process of being built, before all signatures are present. */
|
/** A mutable transaction that's in the process of being built, before all signatures are present. */
|
||||||
class PartialTransaction(private val inputStates: MutableList<ContractStateRef> = arrayListOf(),
|
class PartialTransaction(private val inputStates: MutableList<ContractStateRef> = arrayListOf(),
|
||||||
private val outputStates: MutableList<ContractState> = arrayListOf(),
|
private val outputStates: MutableList<ContractState> = arrayListOf(),
|
||||||
private val commands: MutableList<WireCommand> = arrayListOf()) {
|
private val commands: MutableList<Command> = arrayListOf()) {
|
||||||
/** A more convenient way to add items to this transaction that calls the add* methods for you based on type */
|
/** A more convenient way to add items to this transaction that calls the add* methods for you based on type */
|
||||||
public fun withItems(vararg items: Any): PartialTransaction {
|
public fun withItems(vararg items: Any): PartialTransaction {
|
||||||
for (t in items) {
|
for (t in items) {
|
||||||
when (t) {
|
when (t) {
|
||||||
is ContractStateRef -> inputStates.add(t)
|
is ContractStateRef -> inputStates.add(t)
|
||||||
is ContractState -> outputStates.add(t)
|
is ContractState -> outputStates.add(t)
|
||||||
is WireCommand -> commands.add(t)
|
is Command -> commands.add(t)
|
||||||
else -> throw IllegalArgumentException("Wrong argument type: ${t.javaClass}")
|
else -> throw IllegalArgumentException("Wrong argument type: ${t.javaClass}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -112,17 +107,20 @@ class PartialTransaction(private val inputStates: MutableList<ContractStateRef>
|
|||||||
outputStates.add(state)
|
outputStates.add(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addArg(arg: WireCommand) {
|
fun addCommand(arg: Command) {
|
||||||
check(currentSigs.isEmpty())
|
check(currentSigs.isEmpty())
|
||||||
|
|
||||||
// We should probably merge the lists of pubkeys for identical commands here.
|
// We should probably merge the lists of pubkeys for identical commands here.
|
||||||
commands.add(arg)
|
commands.add(arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun addCommand(data: CommandData, vararg keys: PublicKey) = addCommand(Command(data, listOf(*keys)))
|
||||||
|
fun addCommand(data: CommandData, keys: List<PublicKey>) = addCommand(Command(data, keys))
|
||||||
|
|
||||||
// Accessors that yield immutable snapshots.
|
// Accessors that yield immutable snapshots.
|
||||||
fun inputStates(): List<ContractStateRef> = ArrayList(inputStates)
|
fun inputStates(): List<ContractStateRef> = ArrayList(inputStates)
|
||||||
fun outputStates(): List<ContractState> = ArrayList(outputStates)
|
fun outputStates(): List<ContractState> = ArrayList(outputStates)
|
||||||
fun commands(): List<WireCommand> = ArrayList(commands)
|
fun commands(): List<Command> = ArrayList(commands)
|
||||||
}
|
}
|
||||||
|
|
||||||
data class SignedWireTransaction(val txBits: SerializedBytes<WireTransaction>, val sigs: List<DigitalSignature.WithKey>) {
|
data class SignedWireTransaction(val txBits: SerializedBytes<WireTransaction>, val sigs: List<DigitalSignature.WithKey>) {
|
||||||
@ -206,7 +204,7 @@ data class LedgerTransaction(
|
|||||||
/** The states that will be generated by the execution of this transaction. */
|
/** The states that will be generated by the execution of this transaction. */
|
||||||
val outStates: List<ContractState>,
|
val outStates: List<ContractState>,
|
||||||
/** Arbitrary data passed to the program of each input state. */
|
/** Arbitrary data passed to the program of each input state. */
|
||||||
val commands: List<AuthenticatedObject<Command>>,
|
val commands: List<AuthenticatedObject<CommandData>>,
|
||||||
/** The moment the transaction was timestamped for, if a timestamp was present. */
|
/** The moment the transaction was timestamped for, if a timestamp was present. */
|
||||||
val time: Instant?,
|
val time: Instant?,
|
||||||
/** The hash of the original serialised TimestampedWireTransaction or SignedTransaction */
|
/** The hash of the original serialised TimestampedWireTransaction or SignedTransaction */
|
||||||
@ -227,7 +225,7 @@ data class LedgerTransaction(
|
|||||||
/** A transaction in fully resolved and sig-checked form, ready for passing as input to a verification function. */
|
/** A transaction in fully resolved and sig-checked form, ready for passing as input to a verification function. */
|
||||||
data class TransactionForVerification(val inStates: List<ContractState>,
|
data class TransactionForVerification(val inStates: List<ContractState>,
|
||||||
val outStates: List<ContractState>,
|
val outStates: List<ContractState>,
|
||||||
val commands: List<AuthenticatedObject<Command>>,
|
val commands: List<AuthenticatedObject<CommandData>>,
|
||||||
val time: Instant?,
|
val time: Instant?,
|
||||||
val origHash: SecureHash) {
|
val origHash: SecureHash) {
|
||||||
override fun hashCode() = origHash.hashCode()
|
override fun hashCode() = origHash.hashCode()
|
||||||
|
@ -110,7 +110,7 @@ class CashTests {
|
|||||||
assertEquals(100.DOLLARS, s.amount)
|
assertEquals(100.DOLLARS, s.amount)
|
||||||
assertEquals(MINI_CORP, s.deposit.party)
|
assertEquals(MINI_CORP, s.deposit.party)
|
||||||
assertEquals(DUMMY_PUBKEY_1, s.owner)
|
assertEquals(DUMMY_PUBKEY_1, s.owner)
|
||||||
assertTrue(ptx.commands()[0].command is Cash.Commands.Issue)
|
assertTrue(ptx.commands()[0].data is Cash.Commands.Issue)
|
||||||
assertEquals(MINI_CORP_PUBKEY, ptx.commands()[0].pubkeys[0])
|
assertEquals(MINI_CORP_PUBKEY, ptx.commands()[0].pubkeys[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ class TransactionSerializationTests {
|
|||||||
@Before
|
@Before
|
||||||
fun setup() {
|
fun setup() {
|
||||||
tx = PartialTransaction().withItems(
|
tx = PartialTransaction().withItems(
|
||||||
fakeStateRef, outputState, changeState, WireCommand(Cash.Commands.Move(), arrayListOf(TestUtils.keypair.public))
|
fakeStateRef, outputState, changeState, Command(Cash.Commands.Move(), arrayListOf(TestUtils.keypair.public))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ class TransactionSerializationTests {
|
|||||||
// If the signature was replaced in transit, we don't like it.
|
// If the signature was replaced in transit, we don't like it.
|
||||||
assertFailsWith(SignatureException::class) {
|
assertFailsWith(SignatureException::class) {
|
||||||
val tx2 = PartialTransaction().withItems(fakeStateRef, outputState, changeState,
|
val tx2 = PartialTransaction().withItems(fakeStateRef, outputState, changeState,
|
||||||
WireCommand(Cash.Commands.Move(), arrayListOf(TestUtils.keypair2.public)))
|
Command(Cash.Commands.Move(), TestUtils.keypair2.public))
|
||||||
tx2.signWith(TestUtils.keypair2)
|
tx2.signWith(TestUtils.keypair2)
|
||||||
|
|
||||||
signedTX.copy(sigs = tx2.toSignedTransaction().sigs).verify()
|
signedTX.copy(sigs = tx2.toSignedTransaction().sigs).verify()
|
||||||
@ -89,7 +89,7 @@ class TransactionSerializationTests {
|
|||||||
tx.signWith(TestUtils.keypair)
|
tx.signWith(TestUtils.keypair)
|
||||||
val ttx = tx.toSignedTransaction().toTimestampedTransactionWithoutTime()
|
val ttx = tx.toSignedTransaction().toTimestampedTransactionWithoutTime()
|
||||||
val ltx = ttx.verifyToLedgerTransaction(DUMMY_TIMESTAMPER, MockIdentityService)
|
val ltx = ttx.verifyToLedgerTransaction(DUMMY_TIMESTAMPER, MockIdentityService)
|
||||||
assertEquals(tx.commands().map { it.command }, ltx.commands.map { it.value })
|
assertEquals(tx.commands().map { it.data }, ltx.commands.map { it.value })
|
||||||
assertEquals(tx.inputStates(), ltx.inStateRefs)
|
assertEquals(tx.inputStates(), ltx.inStateRefs)
|
||||||
assertEquals(tx.outputStates(), ltx.outStates)
|
assertEquals(tx.outputStates(), ltx.outStates)
|
||||||
assertNull(ltx.time)
|
assertNull(ltx.time)
|
||||||
|
@ -176,13 +176,17 @@ infix fun ContractState.label(label: String) = LabeledOutput(label, this)
|
|||||||
|
|
||||||
abstract class AbstractTransactionForTest {
|
abstract class AbstractTransactionForTest {
|
||||||
protected val outStates = ArrayList<LabeledOutput>()
|
protected val outStates = ArrayList<LabeledOutput>()
|
||||||
protected val commands = ArrayList<AuthenticatedObject<Command>>()
|
protected val commands = ArrayList<Command>()
|
||||||
|
|
||||||
open fun output(label: String? = null, s: () -> ContractState) = LabeledOutput(label, s()).apply { outStates.add(this) }
|
open fun output(label: String? = null, s: () -> ContractState) = LabeledOutput(label, s()).apply { outStates.add(this) }
|
||||||
|
|
||||||
fun arg(vararg key: PublicKey, c: () -> Command) {
|
protected fun commandsToAuthenticatedObjects(): List<AuthenticatedObject<CommandData>> {
|
||||||
|
return commands.map { AuthenticatedObject(it.pubkeys, it.pubkeys.mapNotNull { TEST_KEYS_TO_CORP_MAP[it] }, it.data) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun arg(vararg key: PublicKey, c: () -> CommandData) {
|
||||||
val keys = listOf(*key)
|
val keys = listOf(*key)
|
||||||
commands.add(AuthenticatedObject(keys, keys.mapNotNull { TEST_KEYS_TO_CORP_MAP[it] }, c()))
|
commands.add(Command(c(), keys))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Forbid patterns like: transaction { ... transaction { ... } }
|
// Forbid patterns like: transaction { ... transaction { ... } }
|
||||||
@ -196,7 +200,8 @@ open class TransactionForTest : AbstractTransactionForTest() {
|
|||||||
fun input(s: () -> ContractState) = inStates.add(s())
|
fun input(s: () -> ContractState) = inStates.add(s())
|
||||||
|
|
||||||
protected fun run(time: Instant) {
|
protected fun run(time: Instant) {
|
||||||
val tx = TransactionForVerification(inStates, outStates.map { it.state }, commands, time, SecureHash.randomSHA256())
|
val tx = TransactionForVerification(inStates, outStates.map { it.state }, commandsToAuthenticatedObjects(),
|
||||||
|
time, SecureHash.randomSHA256())
|
||||||
tx.verify(TEST_PROGRAM_MAP)
|
tx.verify(TEST_PROGRAM_MAP)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,8 +285,8 @@ class TransactionGroupDSL<T : ContractState>(private val stateType: Class<T>) {
|
|||||||
* hash (i.e. pretend it was signed)
|
* hash (i.e. pretend it was signed)
|
||||||
*/
|
*/
|
||||||
fun toLedgerTransaction(time: Instant): LedgerTransaction {
|
fun toLedgerTransaction(time: Instant): LedgerTransaction {
|
||||||
val wireCmds = commands.map { WireCommand(it.value, it.signers) }
|
val wtx = WireTransaction(inStates, outStates.map { it.state }, commands)
|
||||||
return WireTransaction(inStates, outStates.map { it.state }, wireCmds).toLedgerTransaction(time, MockIdentityService, SecureHash.randomSHA256())
|
return wtx.toLedgerTransaction(time, MockIdentityService, SecureHash.randomSHA256())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
package core.visualiser
|
package core.visualiser
|
||||||
|
|
||||||
import core.Command
|
import core.CommandData
|
||||||
import core.ContractState
|
import core.ContractState
|
||||||
import core.SecureHash
|
import core.SecureHash
|
||||||
import core.testutils.TransactionGroupDSL
|
import core.testutils.TransactionGroupDSL
|
||||||
@ -67,7 +67,7 @@ class GraphVisualiser(val dsl: TransactionGroupDSL<in ContractState>) {
|
|||||||
return dsl.labelForState(state) ?: stateToTypeName(state)
|
return dsl.labelForState(state) ?: stateToTypeName(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun commandToTypeName(state: Command) = state.javaClass.canonicalName.removePrefix("contracts.").replace('$', '.')
|
private fun commandToTypeName(state: CommandData) = state.javaClass.canonicalName.removePrefix("contracts.").replace('$', '.')
|
||||||
private fun stateToTypeName(state: ContractState) = state.javaClass.canonicalName.removePrefix("contracts.").removeSuffix(".State")
|
private fun stateToTypeName(state: ContractState) = state.javaClass.canonicalName.removePrefix("contracts.").removeSuffix(".State")
|
||||||
private fun stateToCSSClass(state: ContractState) = stateToTypeName(state).replace('.', '_').toLowerCase()
|
private fun stateToCSSClass(state: ContractState) = stateToTypeName(state).replace('.', '_').toLowerCase()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user