corda/docs/source/key-concepts-contract-constraints.rst
josecoll ef7ccd3147 Merge Open Source to Enterprise (#79)
* Check array size before accessing

* Review fixes

* CORDA-540: Make Verifier work in AMQP mode (#1870)

* reference to finance module via not hardcoded group ID (#1515)

*  generic way to reference to group id when loading finance.jar via cordapp

* Fixed the node shell to work with the DataFeed class

* Attempt to make NodeStatePersistenceTests more stable (#1895)

By ensuring that the nodes are properly started and aware of each other before firing any flows through them.
Also minor refactoring.

* Disable unstable test on Windows (#1899)

* CORDA-530 Don't soft-lock non-fungible states (#1794)

* Don't run unlock query if nothing was locked
* Constructors should not have side-effects

* [CORDA-442] let Driver run without network map (#1890)

* [CORDA-442] let Driver run without network map

- Nodes started by driver run without a networkMapNode.

- Driver does not take a networkMapStartStrategy anymore

- a new parameter in the configuration "noNetworkMapServiceMode" allows for a node not to be a networkMapNode nor to connect to one.

- Driver now waits for each node to write its own NodeInfo file to disk and then copies it into each other node.

- When driver starts a node N, it waits for every node to be have N nodes in their network map.

Note: the code to copy around the NodeInfo files was already in DemoBench, the NodeInfoFilesCopier class was just moved from DemoBench into core (I'm very open to core not being the best place, please advise)

* Added missing cordappPackage dependencies. (#1894)

* Eliminate circular dependency of NodeSchedulerService on ServiceHub. (#1891)

* Update customSchemas documentation. (#1902)

* [CORDA-694] Commands visibility for Oracles (without sacrificing privacy) (#1835)

new checkCommandVisibility feature for Oracles

* CORDA-599 PersistentNetworkMapCache no longer circularly depends on SH (#1652)

* CORDA-725 - Change AMQP identifier to officially assigned value

This does change our header format so pre-cached test files need
regenerating

* CORDA-725 - update changelog

* CORDA-680 Update cordapp packages documentation (#1901)

* Introduce MockNetworkParameters

* Cordformation in Kotlin (#1873)

Cordformation rewritten in kotlin.

* Kotlin migration

* Review Comments

* CORDA-704: Implement `@DoNotImplement` annotation (#1903)

* Enhance the API Scanner plugin to monitor class annotations.
* Implement @DoNotImplement annotation, and apply it.
* Update API definition.
* Update API change detection to handle @DoNotImplement.
* Document the `@DoNotImplement` annotation.

* Experimental support for PostgreSQL (#1525)

* Cash selection refactoring such that 3d party DB providers are only required to implement Coin Selection SQL logic.

* Re-added debug logging statement.

* Updated to include PR review feedback from VK

* Refactoring following rebase from master.

* Fix broken JUnits following rebase.

* Use JDBC ResultSet getBlob() and added custom serializer to address concern raised by tomtau in PR.

* Fix failing JUnits.

* Experimental support for PostgreSQL: CashSelection done using window functions

* Moved postgresql version information into corda/build.gradle

* Using a PreparedStatement in CashSelectionPostgreSQLImpl

* Changed the PostgreSQL Cash Selection implementation to use the new refactored AbstractCashSelection

* * Retire MockServiceHubInternal (#1909)

* Introduce rigorousMock
* Add test-utils and node-driver to generated documentation

* Fix-up: Bank Of Corda sample (#1912)

In the previous version when running with `--role ISSUER` the application failed to start.
The reason was that in spite of `quantity` and `currency` were optional,
un-necessary `requestParams` been constructed regardless.

* move SMM

* Interface changes for multi-threading

* CORDA-351: added dependency check plugin to gradle build script (#1911)

* CORDA-351: added dependency check plugin to gradle build script

* CORDA-351: Added suppression stub file with example

* CORDA-351: added suppresionFile property

* CORDA-435 - Ensure Kryo only tests use Kryo serializatin context

Also correct lambda typos (from lamba)

* Network map service REST API wrapper (#1907)

* Network map client - WIP

* Java doc and doc for doc site

* remove javax.ws dependency

* NetworkParameter -> NetworkParameters

* move network map client to node

* Fix jetty test dependencies

* NetworkParameter -> NetworkParameters

* Address PR issues

* Address PR issues and unit test fix

* Address PR issues

* Fixing Bank-Of-Corda Demo in `master` (#1922)

* Fix-up: Bank Of Corda sample

Use correct CorDapp packages to scan

(cherry picked from commit 2caa134)

* Set adequate permissions for the nodes such that NodeExplorer can connect

(cherry picked from commit ae88242)

* Set adequate permissions for the nodes such that NodeExplorer can connect

(cherry picked from commit ae88242)

* Correct run configuration

* Fix-up port numbers

* CORDA-435 - AMQP serialisation cannot work with private vals

They won't be reported as properties by the introspector and thus we
will fail to find a constructor for them. This makes sense as we will be
unable to serialise an object whose members we cannot read

* CORDA-435 - AMQP enablement fixes

AMQP has different serialization rules than Kryo surrounding the way we
introspect objects to work out how to construct them

* [CORDA-442] make MockNetwork not start a networkmap node (#1908)

* [CORDA-442] make MockNetwork not start a networkmap node

Now MockNetwork will put the appropriate NodeInfos inside each running node networkMapCache.

Tests relating to networkmap node starting and interaction have been removed since they where relaying on MockNetwork

* Minor fix for api checker script to support macOS

* Retrofit changes from Enterprise PR #61 (#1934)

* Introduce MockNodeParameters/Args (#1923)

* CORDA-736 Add some new features to corda.jar via node.conf for testing (#1926)

* CORDA-699 Add injection or modification of memory network messages (#1920)

* Updated API stability changeset to reflect new schema attribute name.
2017-10-25 13:54:34 +01:00

7.4 KiB

Contract Constraints

A basic understanding of contract key concepts, which can be found here </key-concepts-contracts>, is required reading for this page.

Transaction states specify a constraint over the contract that will be used to verify it. For a transaction to be valid, the verify() function associated with each state must run successfully. However, for this to be secure, it is not sufficient to specify the verify() function by name as there may exist multiple different implementations with the same method signature and enclosing class. Contract constraints solve this problem by allowing a contract developer to constrain which verify() functions out of the universe of implementations can be used. (ie the universe is everything that matches the signature and contract constraints restricts this universe to a subset.)

A typical constraint is the hash of the CorDapp JAR that contains the contract and states but will in future releases include constraints that require specific signers of the JAR, or both the signer and the hash. Constraints can be specified when constructing a transaction; if unspecified, an automatic constraint is used.

A TransactionState has a constraint field that represents that state's attachment constraint. When a party constructs a TransactionState without specifying the constraint parameter a default value (AutomaticHashConstraint) is used. This default will be automatically resolved to a specific HashAttachmentConstraint that contains the hash of the attachment which contains the contract of that TransactionState. This automatic resolution occurs when a TransactionBuilder is converted to a WireTransaction. This reduces the boilerplate involved in finding a specific hash constraint when building a transaction.

It is possible to specify the constraint explicitly with any other class that implements the AttachmentConstraint interface. To specify a hash manually the HashAttachmentConstraint can be used and to not provide any constraint the AlwaysAcceptAttachmentConstraint can be used - though this is intended for testing only. An example below shows how to construct a TransactionState with an explicitly specified hash constraint from within a flow;

// Constructing a transaction with a custom hash constraint on a state
TransactionBuilder tx = new TransactionBuilder()

Party notaryParty = ... // a notary party
DummyState contractState = new DummyState()
SecureHash myAttachmentsHash = serviceHub.cordappProvider.getContractAttachmentID(DummyContract.PROGRAM_ID)
TransactionState transactionState = new TransactionState(contractState, DummyContract.Companion.getPROGRAMID(), notaryParty, new AttachmentHashConstraint(myAttachmentsHash))

tx.addOutputState(transactionState)
WireTransaction wtx = tx.toWireTransaction(serviceHub) // This is where an automatic constraint would be resolved
LedgerTransaction ltx = wtx.toLedgerTransaction(serviceHub)
ltx.verify() // Verifies both the attachment constraints and contracts

This mechanism exists both for integrity and security reasons. It is important not to verify against the wrong contract, which could happen if the wrong version of the contract is attached. More importantly when resolving transaction chains there will, in a future release, be attachments loaded from the network into the attachment sandbox that are used to verify the transaction chain. Ensuring the attachment used is the correct one ensures that the verification will not be tamperable by providing a fake contract.

CorDapps as attachments

CorDapp JARs (cordapp-overview) that are installed to the node and contain classes implementing the Contract interface are automatically loaded into the AttachmentStorage of a node at startup.

After CorDapps are loaded into the attachment store the node creates a link between contract classes and the attachment that they were loaded from. This makes it possible to find the attachment for any given contract. This is how the automatic resolution of attachments is done by the TransactionBuilder and how, when verifying the constraints and contracts, attachments are associated with their respective contracts.

Implementations

There are three implementations of AttachmentConstraints with more planned in the future.

AlwaysAcceptAttachmentConstraint: Any attachment (except a missing one) will satisfy this constraint.

AutomaticHashConstraint: This will be resolved to a HashAttachmentConstraint when a TransactionBuilder is converted to a WireTransaction. The HashAttachmentConstraint will include the attachment hash of the CorDapp that contains the ContractState on the TransactionState.contract field.

HashAttachmentConstraint: Will require that the hash of the attachment containing the contract matches the hash stored in the constraint.

We plan to add a future AttachmentConstraint that will only be satisfied by the presence of signatures on the attachment JAR. This allows for trusting of attachments from trusted entities.

Limitations

An AttachmentConstraint is verified by running the AttachmentConstraint.isSatisfiedBy method. When this is called it is provided only the relevant attachment by the transaction that is verifying it.

Testing

Since all tests involving transactions now require attachments it is also required to load the correct attachments for tests. Unit test environments in JVM ecosystems tend to use class directories rather than JARs, and so CorDapp JARs typically aren't built for testing. Requiring this would add significant complexity to the build systems of Corda and CorDapps, so the test suite has a set of convenient functions to generate CorDapps from package names or to specify JAR URLs in the case that the CorDapp(s) involved in testing already exist.

MockNetwork/MockNode

The most simple way to ensure that a vanilla instance of a MockNode generates the correct CorDapps is to use the cordappPackages constructor parameter (Kotlin) or the setCordappPackages method on MockNetworkParameters (Java) when creating the MockNetwork. This will cause the AbstractNode to use the named packages as sources for CorDapps. All files within those packages will be zipped into a JAR and added to the attachment store and loaded as CorDapps by the CordappLoader. An example of this usage would be:

class SomeTestClass {
     MockNetwork network = null

     @Before
     void setup() {
         network = new MockNetwork(new MockNetworkParameters().setCordappPackages(Arrays.asList("com.domain.cordapp")))
     }

     ... // Your tests go here
}

MockServices

If your test uses a MockServices directly you can instantiate it using a constructor that takes a list of packages to use as CorDapps using the cordappPackages parameter.

MockServices mockServices = new MockServices(Arrays.asList("com.domain.cordapp"))

Driver

The driver takes a parameter called extraCordappPackagesToScan which is a list of packages to use as CorDapps.

driver(new DriverParameters().setExtraCordappPackagesToScan(Arrays.asList("com.domain.cordapp"))) ...

Full Nodes

When testing against full nodes simply place your CorDapp into the cordapps directory of the node.