Created
April 3, 2019 14:41
-
-
Save alikon/279e509bb62d8e7a8f6fe090791be402 to your computer and use it in GitHub Desktop.
draft ordine di pagamento state e contract
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// TO DO da cambiare | |
package com.r3.businessnetworks.ordine.states | |
// TO DO da cambiare | |
import com.r3.businessnetworks.ordine.states.OrdineStatus.* | |
import net.corda.core.contracts.* | |
import net.corda.core.contracts.Requirements.using | |
import net.corda.core.identity.Party | |
import net.corda.core.schemas.MappedSchema | |
import net.corda.core.schemas.PersistentState | |
import net.corda.core.schemas.QueryableState | |
import net.corda.core.serialization.CordaSerializable | |
import net.corda.core.transactions.LedgerTransaction | |
import java.time.Instant | |
/** | |
* Contracts that verifies an evolution of [MembershipState]s. Only an evolution of [MembershipState]s is verified, not of their metadata. | |
* To verify evolution of a membership metadata, users can: | |
* 1. override responding flows at the BNO's side and put a custom verification logic in there (off-ledger verification) | |
* 2. override [MembershipContract] and add a custom verification logic into a new contract (on-ledger verification), for example: | |
* | |
* class MyMembershipContract : MembershipContract { | |
* // ........ | |
* | |
* override fun verifyAmend(tx : LedgerTransaction, command : CommandWithParties<Commands>, outputMembership : MembershipState<*>, inputMembership : MembershipState<*>) { | |
* super.verifyAmend(tx, command, outputMembership, inputMembership) | |
* // custom logic goes in here | |
* } | |
* } | |
*/ | |
open class OrdineContract : Contract { | |
companion object { | |
// TO DO da cambiare | |
const val CONTRACT_NAME = "com.r3.businessnetworks.ordine.states.OrdineContract" | |
} | |
open class Commands : CommandData, TypeOnlyCommandData() { | |
class Immesso : Commands() | |
class Rifiutato : Commands() | |
class Autorizzato : Commands() | |
} | |
override fun verify(tx : LedgerTransaction) { | |
val command = tx.commands.requireSingleCommand<Commands>() | |
val output = tx.outputs.single { it.data is OrdineState<*> } | |
val outputOrdine = output.data as OrdineState<*> | |
requireThat { | |
"Timestamp modifica deve essere maggiore o uguale Timestamp inserimento" using (outputOrdine.modificato >= outputOrdine.inserito) | |
"Autorizzatore e Ordinante devono essere participants" using (outputOrdine.participants.toSet() == setOf(outputOrdine.ordinante, outputOrdine.autorizzatore)) | |
"Output state deve essere validato con ${contractName()}" using (output.contract == contractName()) | |
if (!tx.inputs.isEmpty()) { | |
val input = tx.inputs.single() | |
val inputState = input.state.data as OrdineState<*> | |
"Participants of input and output states devono essere gli stessi" using (outputOrdine.participants.toSet() == input.state.data.participants.toSet()) | |
"Input state hdeve essere validato con ${contractName()}" using (input.state.contract == contractName()) | |
"Input and output states devono avere lo stessa timestamp di inserimento" using (inputState.inserito == outputOrdine.inserito) | |
"Input and output states devono avere la stessa linear IDs" using (inputState.linearId == outputOrdine.linearId) | |
"Output state's modificato timestamp deve essere maggiore del input's" using (outputOrdine.modificato > inputState.modificato) | |
} | |
} | |
when (command.value) { | |
is Commands.Immesso -> verifyImmesso(tx, command, outputOrdine) | |
is Commands.Rifiutato -> verifyRifiutato(tx, command, outputOrdine, tx.inputsOfType<OrdineState<*>>().single()) | |
is Commands.Autorizzato -> verifyAutorizzato(tx, command, outputOrdine, tx.inputsOfType<OrdineState<*>>().single()) | |
else -> throw IllegalArgumentException("Unsupported command ${command.value}") | |
} | |
} | |
// custom implementations should be able to specify their own contract names | |
open fun contractName() = CONTRACT_NAME | |
open fun verifyImmesso(tx : LedgerTransaction, command : CommandWithParties<Commands>, outputOrdine : OrdineState<*>) = requireThat { | |
"Entrambi Autorizzatore e ordinante devono firmare la transazione di ordine Immesso" using (command.signers.toSet() == outputOrdine.participants.map { it.owningKey }.toSet() ) | |
"La transazione di ordine Immesso non deve contenrere inputs" using (tx.inputs.isEmpty()) | |
"La transazione di ordine Immesso deve contenere un output state in stato IMMESSO" using (outputOrdine.isImmesso()) | |
} | |
open fun verifyRifiutato(tx : LedgerTransaction, command : CommandWithParties<Commands>, outputOrdine : OrdineState<*>, inputOrdine : OrdineState<*>) = requireThat { | |
"Solo l'Autorizzatore deve firmare la transaction RIFIUTATO" using (command.signers.toSet() == setOf(outputOrdine.autorizzatore.owningKey)) | |
"Input state della transaction RIFIUTATO non deve essere RIFIUTATO" using (!inputOrdine.isRifiutato()) | |
"Output state di una transaction RIFIUTATO deve essere RIFIUTATO" using (outputOrdine.isRifiutato()) | |
"Input and output states della transaction RIFIUTATO devono avere lo stesso Blobdata" using (inputOrdine.ordineBlobdata == outputOrdine.ordineBlobdata) | |
} | |
open fun verifyAutorizzato(tx : LedgerTransaction, command : CommandWithParties<Commands>, outputOrdine : OrdineState<*>, inputOrdine : OrdineState<*>) = requireThat { | |
"Solo Autorizzatore deve firmare la transaction AUTORIZZATO" using (command.signers.toSet() == setOf(outputOrdine.autorizzatore.owningKey)) | |
"Input state di transaction AUTORIZZATO non deve essere già AUTORIZZATO" using (!inputOrdine.isAutorizzato()) | |
"Output state di transaction AUTORIZZATO deve essere AUTORIZZATO" using (outputOrdine.isAutorizzato()) | |
"Input and output states di transaction AUTORIZZATO deve avere gli stessi Blobdata" using (inputOrdine.ordineBlobdata == outputOrdine.ordineBlobdata) | |
} | |
} | |
/** | |
* Rappresenta un ordine di pagamento sul ledger. [ordineBlobdata] al momento è un blob di dati da definire/gestire. | |
* | |
* @param ordinante identity dell'ordinante | |
* @param autorizzatore identity di colui che autorizza | |
* @param inserito timestamp quando l'ordine di pagamento è stato immesso | |
* @param modificato timestamp quando lo stato è stato modificato l'ultima volta | |
* @param status status of the state, i.e. AUTORIZZATO, RIFIUTATO, IMMESSO etc. | |
*/ | |
@BelongsToContract(OrdineContract::class) | |
data class OrdineState<out T : Any>(val ordinante : Party, | |
val autorizzatore : Party, | |
val ordineBlobdata : T, | |
val inserito : Instant = Instant.now(), | |
val modificato : Instant = inserito, | |
val status : OrdineStatus = OrdineStatus.IMMESSO, | |
override val linearId : UniqueIdentifier = UniqueIdentifier()) : LinearState, QueryableState { | |
override fun generateMappedObject(schema : MappedSchema) : PersistentState { | |
return when (schema) { | |
is OrdineStateSchemaV1 -> OrdineStateSchemaV1.PersistentOrdineState( | |
ordinante = this.ordinante, | |
autorizzatore = this.autorizzatore, | |
status = this.status | |
) | |
else -> throw IllegalArgumentException("Unrecognised schema $schema") | |
} | |
} | |
override fun supportedSchemas() = listOf(OrdineStateSchemaV1) | |
override val participants = listOf(autorizzatore, ordinante) | |
fun isRifiutato() = status == OrdineStatus.RIFIUTATO | |
fun isImmesso() = status == OrdineStatus.IMMESSO | |
fun isAutorizzato() = status == OrdineStatus.AUTORIZZATO | |
} | |
@CordaSerializable | |
object OrdineStateSchemaV1 : MappedSchema(schemaFamily = OrdineState::class.java, version = 1, mappedTypes = listOf(PersistentOrdineState::class.java)) { | |
@Entity | |
@Table(name = "ordine_states") | |
class PersistentOrdineState ( | |
@Column(name = "ordinante_name") | |
var ordinante: Party, | |
@Column(name = "autorizzatore_name") | |
var autorizzatore: Party, | |
@Column(name = "status") | |
var status: OrdineStatus) : PersistentState() | |
} | |
/** | |
* Stati di un Ordine di Pagamento. | |
* | |
* [IMMESSO] - l'ordinante ha IMMESSO l'ordine di pagamento, ed è in attesa di autorizzazione. | |
* [AUTORIZZATO] - l'ordine di pagamento è stato AUTORIZZATO | |
* [RIFIUTATO] - l'ordine di pagamento è stato RIFIUTATO | |
*/ | |
@CordaSerializable | |
enum class OrdineStatus { | |
IMMESSO, AUTORIZZATO, RIFIUTATO | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment