Path constraints
You can use PathConstraints
to restrict the Path
that is allowed in a transaction. The smart contract defines a set of PathConstraints
for each Primary state status, for example when in status X you can follow PathConstraint
A or B, but when you are in state Y you can only follow PathConstraint
C.
In order to pass verification, the Path in the transaction must comply with at least one of the allowed PathConstraints
for the status
of the Primary input state.
PathConstraints are implemented as follows:
ContractUtils.kt:
class PathConstraint<T: StatusState>(val command: CommandData,
val outputStatus: Status?,
val inputMultiplicityConstraint: MultiplicityConstraint = MultiplicityConstraint(),
val outputMultiplicityConstraint: MultiplicityConstraint = MultiplicityConstraint(),
val additionalStatesConstraints: Set<AdditionalStatesConstraint> = setOf()){
infix fun allows(p: Path<T>): Boolean { ... }
infix fun doesNotAllow(p: Path<T>): Boolean = !this.allows(p)
private fun additionalStatesCheck(constraints: Set<AdditionalStatesConstraint>, additionalStates: Set<AdditionalStates>) :Boolean{ ... }
}
Where:
command
is the class of the command required.outputStatus
is the outputStatus of the Primary state that is required.inputMultiplicityConstraint
defines the range of number of inputs of Primary type that is required.outputMultiplicityConstraint
defines the range of number of outputs of Primary type that is required.additionalStatesConstraint
defines which additional states must be present in the transaction.
A Path in a transaction will only be allowed by the PathConstraint if it passes all these requirements.
additionalStatesConstraint
are implemented as follows:
ContractUtils.kt:
class AdditionalStatesConstraint(val type: AdditionalStatesType ,
val statesClass: Class<out ContractState>,
val requiredNumberOfStates: MultiplicityConstraint = MultiplicityConstraint()) {
infix fun isSatisfiedBy(additionalStates: AdditionalStates ):Boolean {...}
infix fun isNotSatisfiedBy (additionalStates: AdditionalStates): Boolean = !isSatisfiedBy(additionalStates)
}
Where:
type
isINPUT
,OUTPUT
orREFERENCE
.statesClass
is the required type of the additional states.requiredNumberOfStates
defines how many AdditionalStates of this type are allowed using aMultiplicityConstraint
.
MultiplicityConstraint are defined as follows:
ContractUtils.kt:
class MultiplicityConstraint(val from: Int = 1,
val bounded: Boolean = true,
val upperBound: Int = from){
infix fun allows(numberOfStates: Int): Boolean { ... }
infix fun doesNotAllow(numberOfStates: Int): Boolean = !this.allows(numberOfStates)
}
Where:
from
is the minimum number of states.bounded
specifies if there is an upper limit.upperbound
specifies the upper bound, which is only applied if bounded is true.
Note, the structure above allows for quite complex definition of what is allowed, in most cases these won’t be needed. To simplify the use of PathConstraints most properties are defaulted. So for example you can specify a Path constraint simply as:
PathConstraint(Commands.Reject(), REJECTED)
Which would default to:
- 1 Input of Primary State type.
- 1 output Primary State type.
- No additional states required.
Or they could get much more complicated as in this example from the ContractUtils
test scripts:
PathConstraint(Commands.Command2(), TestState2A.TestStatus.STATUSA2, additionalStatesConstraints = setOf(
AdditionalStatesConstraint(AdditionalStatesType.INPUT, TestState2B::class.java, MultiplicityConstraint(2, false)),
AdditionalStatesConstraint(AdditionalStatesType.REFERENCE, TestState2C::class.java),
AdditionalStatesConstraint(AdditionalStatesType.OUTPUT, TestState2D::class.java)
))
Was this page helpful?
Thanks for your feedback!
Chat with us
Chat with us on our #docs channel on slack. You can also join a lot of other slack channels there and have access to 1-on-1 communication with members of the R3 team and the online community.
Propose documentation improvements directly
Help us to improve the docs by contributing directly. It's simple - just fork this repository and raise a PR of your own - R3's Technical Writers will review it and apply the relevant suggestions.
We're sorry this page wasn't helpful. Let us know how we can make it better!
Chat with us
Chat with us on our #docs channel on slack. You can also join a lot of other slack channels there and have access to 1-on-1 communication with members of the R3 team and the online community.
Create an issue
Create a new GitHub issue in this repository - submit technical feedback, draw attention to a potential documentation bug, or share ideas for improvement and general feedback.
Propose documentation improvements directly
Help us to improve the docs by contributing directly. It's simple - just fork this repository and raise a PR of your own - R3's Technical Writers will review it and apply the relevant suggestions.