Signing constraints

Signing constraints are implement using a switch on the command.

The slight modification to be added to signing constraints in this example is that the check being performed is always of the same form - does the command.signers contain the required signer per the CDL diagram?

To make the code more efficient you can define a checkSigners() function for which you use a switch on command.value to send different arguments based on the CDL required signers for each command.

There is also a similar guard to verifyLinearIDConstraints() to ensure there is only one primary input and primary output state, which allows you to simplify the implementation.

AgreementContract.kt:


    fun verifySigningConstraints(tx: LedgerTransaction){

        // This implementation assumes there is a maximum of one Primary input state and a maximum one Primary output state.
        // For Contracts which assume multiple Primary inputs or Output a different approach will be required

        val command = tx.commands.requireSingleCommand<AgreementContract.Commands>()
        val inputStates = tx.inputsOfType<AgreementState>()
        val outputStates = tx.outputsOfType<AgreementState>()

        // This is a guard which shouldn't be triggered because the Path constraints should have already ensured there is
        // a maximum of one Primary input state and a maximum one Primary output state
        requireThat{
            "when checking signing constraints there should be a maximum of one Primary input state." using (inputStates.size <= 1)
            "When checking signing constraints there should be a maximum of one Primary output state." using (outputStates.size <= 1)
        }

        val inputState = inputStates.singleOrNull()
        val outputState = outputStates.singleOrNull()

        val commandName = command.value::class.java.simpleName

        fun checkSigner(signerDescription: String, signer: Party?){
            requireThat { "When the Command is $commandName the $signerDescription must sign." using (command.signers.contains(signer?.owningKey))}

        }

        when (command.value){
            is Commands.Propose -> {
                checkSigner("output.proposer", outputState?.proposer)   // Can add multiple signing check against each Command
            }
            is Commands.Reject -> {
                checkSigner("output.rejectedBy", outputState?.rejectedBy)
            }
            is Commands.Repropose -> {
                checkSigner("output.proposer", outputState?.proposer)
            }
            is Commands.Agree -> {
                checkSigner("input.consenter", inputState?.consenter )
            }
            is Commands.Complete -> {
                checkSigner("input.seller", inputState?.seller)
            }
        }
    }

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.