mirror of
https://github.com/corda/corda.git
synced 2024-12-18 20:47:57 +00:00
Some renaming and moving around (Children's Paper becomes Comedy Paper to make it clearer that it's sort of a joke implementation)
This commit is contained in:
parent
fa626fc5d7
commit
83eb45732f
@ -40,6 +40,7 @@ class InsufficientBalanceException(val amountMissing: Amount) : Exception()
|
||||
|
||||
// Small DSL extension.
|
||||
fun Iterable<ContractState>.sumCashBy(owner: PublicKey) = this.filterIsInstance<CashState>().filter { it.owner == owner }.map { it.amount }.sum()
|
||||
fun Iterable<ContractState>.sumCash() = this.filterIsInstance<CashState>().map { it.amount }.sum()
|
||||
|
||||
/**
|
||||
* A cash transaction may split and merge money represented by a set of (issuer, depositRef) pairs, across multiple
|
||||
|
@ -5,7 +5,7 @@ import java.security.PublicKey
|
||||
import java.time.Instant
|
||||
|
||||
/**
|
||||
* "Children's paper" is basically like commercial paper, but modelled by a non-expert and without any attention paid
|
||||
* "Comedy paper" is basically like commercial paper, but modelled by a non-expert and without any attention paid
|
||||
* to the issuance aspect. It has a weird name to emphasise that it's not a prototype of real CP, as that's currently
|
||||
* waiting for Jo/Ayoub to deliver full CP use case models. This file may be renamed later if it grows up and
|
||||
* becomes real CP.
|
||||
@ -19,48 +19,46 @@ import java.time.Instant
|
||||
|
||||
// TODO: This is very incomplete! Do not attempt to find mistakes in it just yet.
|
||||
|
||||
val CP_PROGRAM_ID = SecureHash.sha256("childrens-paper")
|
||||
|
||||
data class ChildrensPaperState(
|
||||
val issuance: InstitutionReference,
|
||||
val owner: PublicKey,
|
||||
val faceValue: Amount,
|
||||
val maturityDate: Instant
|
||||
) : ContractState {
|
||||
override val programRef = CP_PROGRAM_ID
|
||||
|
||||
fun withoutOwner() = copy(owner = NullPublicKey)
|
||||
}
|
||||
val CP_PROGRAM_ID = SecureHash.sha256("comedy-paper")
|
||||
|
||||
// TODO: Generalise the notion of an owned object into a superclass/supercontract. Consider composition vs inheritance.
|
||||
sealed class CPCommands : Command {
|
||||
class MoveCommand : CPCommands()
|
||||
class RedeemCommand : CPCommands()
|
||||
}
|
||||
object ComedyPaper : Contract {
|
||||
data class State(
|
||||
val issuance: InstitutionReference,
|
||||
val owner: PublicKey,
|
||||
val faceValue: Amount,
|
||||
val maturityDate: Instant
|
||||
) : ContractState {
|
||||
override val programRef = CP_PROGRAM_ID
|
||||
|
||||
fun withoutOwner() = copy(owner = NullPublicKey)
|
||||
}
|
||||
|
||||
sealed class Commands : Command {
|
||||
class Move : Commands()
|
||||
class Redeem : Commands()
|
||||
}
|
||||
|
||||
object ChildrensPaper : Contract {
|
||||
override fun verify(inStates: List<ContractState>, outStates: List<ContractState>, args: List<VerifiedSigned<Command>>, time: Instant) {
|
||||
// There are two possible things that can be done with CP. The first is trading it. The second is redeeming it
|
||||
// for cash on or after the maturity date.
|
||||
val command = args.requireSingleCommand<CPCommands>()
|
||||
val command = args.requireSingleCommand<ComedyPaper.Commands>()
|
||||
|
||||
// For now do not allow multiple pieces of CP to trade in a single transaction. Study this more!
|
||||
val input = inStates.filterIsInstance<ChildrensPaperState>().single()
|
||||
val output = outStates.filterIsInstance<ChildrensPaperState>().single()
|
||||
val input = inStates.filterIsInstance<ComedyPaper.State>().single()
|
||||
|
||||
when (command.value) {
|
||||
is CPCommands.MoveCommand -> requireThat {
|
||||
is Commands.Move -> requireThat {
|
||||
val output = outStates.filterIsInstance<ComedyPaper.State>().single()
|
||||
"the transaction is signed by the owner of the CP" by (command.signer == input.owner)
|
||||
"the output state is the same as the input state except for owner" by (input.withoutOwner() == output.withoutOwner())
|
||||
}
|
||||
|
||||
is CPCommands.RedeemCommand -> {
|
||||
// TODO: Lots more needed here: the CP state must be destroyed by this transaction, command.signer is not really right etc
|
||||
val received = outStates.sumCashBy(command.signer)
|
||||
requireThat {
|
||||
"the paper must have matured" by (input.maturityDate < time)
|
||||
"the received amount equals the face value" by (received == input.faceValue)
|
||||
}
|
||||
is Commands.Redeem -> requireThat {
|
||||
val received = outStates.sumCash()
|
||||
"the paper must have matured" by (input.maturityDate < time)
|
||||
"the received amount equals the face value" by (received == input.faceValue)
|
||||
"the paper must be destroyed" by outStates.filterIsInstance<ComedyPaper.State>().none()
|
||||
}
|
||||
}
|
||||
}
|
@ -5,10 +5,10 @@ import org.junit.Test
|
||||
|
||||
// TODO: Finish this off.
|
||||
|
||||
class ChildrensPaperTests {
|
||||
val contract = ChildrensPaper
|
||||
class ComedyPaperTests {
|
||||
val contract = ComedyPaper
|
||||
|
||||
val PAPER_1 = ChildrensPaperState(
|
||||
val PAPER_1 = ComedyPaper.State(
|
||||
issuance = InstitutionReference(MEGA_CORP, OpaqueBytes.of(123)),
|
||||
owner = DUMMY_PUBKEY_1,
|
||||
faceValue = 1000.DOLLARS,
|
||||
@ -26,12 +26,12 @@ class ChildrensPaperTests {
|
||||
contract.rejects()
|
||||
|
||||
transaction {
|
||||
arg(DUMMY_PUBKEY_2) { CPCommands.MoveCommand() }
|
||||
arg(DUMMY_PUBKEY_2) { ComedyPaper.Commands.Move() }
|
||||
contract `fails requirement` "is signed by the owner"
|
||||
}
|
||||
|
||||
transaction {
|
||||
arg(DUMMY_PUBKEY_1) { CPCommands.MoveCommand() }
|
||||
arg(DUMMY_PUBKEY_1) { ComedyPaper.Commands.Move() }
|
||||
contract.accepts()
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user