# 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`

is`INPUT`

,`OUTPUT`

or`REFERENCE`

.`statesClass`

is the required type of the additional states.`requiredNumberOfStates`

defines how many AdditionalStates of this type are allowed using a`MultiplicityConstraint`

.

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)
))
```