mirror of
https://github.com/corda/corda.git
synced 2024-12-21 13:57:54 +00:00
Docs: fix various issues for C4.
- Delete information about hash->signature constraint migration. That won't work for C4.0 - Rewrite parts of the api-contract-constraints.rst file to fix grammar problems and reduce the weight of the page. Some detail isn't really necessary at this point in the docs. - Mention more things in the upgrade notes.
This commit is contained in:
parent
5f70abfeca
commit
ca49c5e94d
@ -7,52 +7,42 @@ API: Contract Constraints
|
||||
|
||||
.. contents::
|
||||
|
||||
Contract constraints
|
||||
--------------------
|
||||
*Contract constraints* solve two problems faced by any decentralised ledger that supports evolution of data and code:
|
||||
|
||||
Corda separates verification of states from their definition. Whilst you might have expected the ``ContractState``
|
||||
interface to define a verify method, or perhaps to do verification logic in the constructor, instead it is primarily
|
||||
done by a method on a ``Contract`` class. This is because what we're actually checking is the
|
||||
validity of a *transaction*, which is more than just whether the individual states are internally consistent.
|
||||
The transition between two valid states may be invalid, if the rules of the application are not being respected.
|
||||
For instance, two cash states of $100 and $200 may both be internally valid, but replacing the first with the second
|
||||
isn't allowed unless you're a cash issuer - otherwise you could print money for free.
|
||||
1. Controlling and agreeing upon upgrades
|
||||
2. Preventing attacks
|
||||
|
||||
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. This normally will happen as applications
|
||||
evolve, but could also happen maliciously as anyone can create a JAR with a class of that name.
|
||||
Upgrades and security are intimately related because if an attacker can "upgrade" your data to a version of an app that gives them
|
||||
a back door, they would be able to do things like print money or edit states in any way they want. That's why it's important for
|
||||
participants of a state to agree on what kind of upgrades will be allowed.
|
||||
|
||||
Contract constraints solve this problem by allowing a state creator to constrain which ``verify`` functions out of
|
||||
the universe of implementations can be used (i.e. the universe is everything that matches the class name and contract
|
||||
constraints restrict this universe to a subset). Constraints are satisfied by attachments (JARs). You are not allowed to
|
||||
attach two JARs that both define the same application due to the *no overlap rule*. This rule specifies that two
|
||||
attachment JARs may not provide the same file path. If they do, the transaction is considered invalid. Because each
|
||||
state specifies both a constraint over attachments *and* a Contract class name to use, the specified class must appear
|
||||
in only one attachment.
|
||||
Every state on the ledger contains the fully qualified class name of a ``Contract`` implementation, and also a *constraint*.
|
||||
This constraint specifies which versions of an application can be used to provide the named class. There are several types:
|
||||
|
||||
.. note:: With the introduction of signature constraints in Corda 4, a new attachments classloader will verify that
|
||||
both signed and unsigned versions of an associated contract jar contain identical classes. This allows for automatic
|
||||
migration of hash-constrained states (created with pre-Corda 4 unsigned contract jars) to signature constrained states
|
||||
when used as outputs in new transactions using signed Corda 4 contract jars.
|
||||
1. Hash constraint: exactly one version of the app can be used with this state.
|
||||
2. Zone whitelist constraint: the compatibility zone operator lists the hashes of the versions that can be used with this contract class name.
|
||||
3. Signature constraint: any version of the app signed by the given ``CompositeKey`` can be used.
|
||||
4. Always accept constraint: any app can be used at all. This is insecure but convenient for testing.
|
||||
|
||||
Recap: A corda transaction transitions input states to output states. Each state is composed of data, the name of the class that verifies the transition(contract), and
|
||||
the contract constraint. The transaction also contains a list of attachments (normal JARs) from where these classes will be loaded. There must be only one JAR containing each contract.
|
||||
The contract constraints are responsible to ensure the attachment JARs are following the rules set by the creators of the input states (in a continuous chain to the issue).
|
||||
This way, we have both valid data and valid code that checks the transition packed into the transaction.
|
||||
The actual app version used is defined by the attachments on a transaction: the JAR containing the state and contract classes, and optionally
|
||||
its dependencies, are all attached to the transaction. Other nodes will download these JARs from a node if they haven't seen them before,
|
||||
so they can be used for verification. The ``TransactionBuilder`` will manage the details of constraints for you, by selecting both constraints
|
||||
and attachments to ensure they line up correctly. Therefore you only need to have a basic understanding of this topic unless you are
|
||||
doing something sophisticated.
|
||||
|
||||
So who picks the attachment to use? It is chosen by the creator of the transaction but has to satisfy the constraints of the input states.
|
||||
This is because any node doing transaction resolution will actually verify the selected attachment against all constraints,
|
||||
so the transaction will only be valid if it passes those checks.
|
||||
For example, when the input state is constrained by the ``HashAttachmentConstraint``, can only attach the JAR with that hash to the transaction.
|
||||
The best kind of constraint to use is the **signature constraint**. If you sign your application it will be used automatically.
|
||||
We recommend signature constraints because they let you release new versions of your application. Hash and zone
|
||||
whitelist constraints still work, but are left over from earlier Corda versions before signature constraints were
|
||||
implemented. They make it harder to upgrade applications than when using signature constraints, so they're best avoided.
|
||||
Signature constraints can specify flexible policies but if you use the automatic support, then a state will require the attached app
|
||||
to be signed by every key that the first attachment was signed by. Thus if the app that was used to issue the states was signed by
|
||||
Alice and Bob, every transaction must use an attachment signed by Alice and Bob.
|
||||
|
||||
The transaction creator also gets to pick the constraints used by any output states.
|
||||
When building a transaction, the default constraint on output states is ``AutomaticPlaceholderConstraint``, which means that corda will select the appropriate constraint.
|
||||
Unless specified otherwise, attachment constraints will propagate from input to output states. (The rules are described below)
|
||||
Constraint propagation is also enforced during transaction verification, where for normal transactions (not explicit upgrades, or notary changes),
|
||||
the constraints of the output states are required to "inherit" the constraint of the input states. ( See below for details)
|
||||
**Constraint propagation.** Constraints are picked when a state is created for the first time in an issuance transaction. Once created,
|
||||
the constraint used by the equivalent output state must match the input state, so it can't be changed and you can't combine states with
|
||||
incompatible constraints together in the same transaction.
|
||||
|
||||
There are two ways of handling upgrades to a smart contract in Corda:
|
||||
**Implicit vs explicit.** There are two ways of handling upgrades to a smart contract in Corda:
|
||||
|
||||
1. *Implicit:* By allowing multiple implementations of the contract ahead of time, using constraints.
|
||||
2. *Explicit:* By creating a special *contract upgrade transaction* and getting all participants of a state to sign it using the
|
||||
@ -121,135 +111,14 @@ CorDapp is 4 or greater, then transaction verification will fail with a ``Transa
|
||||
the owning ``Contract`` *can* be identified, but the ``ContractState`` has been bundled with a different contract, then
|
||||
transaction verification will fail with a ``TransactionContractConflictException``.
|
||||
|
||||
How constraints work
|
||||
--------------------
|
||||
|
||||
In Corda 4 there are three types of constraint that can be used in production environments: hash, zone whitelist and signature.
|
||||
For development purposes the ``AlwaysAcceptAttachmentConstraint`` allows any attachment to be selected.
|
||||
|
||||
Hash and zone whitelist constraints were available in Corda 3, with hash constraints being used as default.
|
||||
In Corda 4 the default constraint is the signature constraint if the jar is signed. Otherwise,
|
||||
the default constraint type is either a zone constraint, if the network parameters in effect when the
|
||||
transaction is built contain an entry for that contract class, or a hash constraint if not.
|
||||
|
||||
**Hash constraints.** The behaviour provided by public blockchain systems like Bitcoin and Ethereum is that once data is placed on the ledger,
|
||||
the program that controls it is fixed and cannot be changed. There is no support for upgrades at all. This implements a
|
||||
form of "code is law", assuming you trust the community of that blockchain to not release a new version of the platform
|
||||
that invalidates or changes the meaning of your program.
|
||||
|
||||
This is supported by Corda using a hash constraint. This specifies exactly one hash of a CorDapp JAR that contains the
|
||||
contract and states any consuming transaction is allowed to use. Once such a state is created, other nodes will only
|
||||
accept a transaction if it uses that exact JAR file as an attachment. By implication, any bugs in the contract code
|
||||
or state definitions cannot be fixed except by using an explicit upgrade process via ``ContractUpgradeFlow``.
|
||||
|
||||
.. note:: Corda does not support any way to create states that can never be upgraded at all, but the same effect can be
|
||||
obtained by using a hash constraint and then simply refusing to agree to any explicit upgrades. Hash
|
||||
constraints put you in control by requiring an explicit agreement to any upgrade.
|
||||
|
||||
**Zone constraints.** Often a hash constraint will be too restrictive. You do want the ability to upgrade an app,
|
||||
and you don't mind the upgrade taking effect "just in time" when a transaction happens to be required for other business
|
||||
reasons. In this case you can use a zone constraint. This specifies that the network parameters of a compatibility zone
|
||||
(see :doc:`network-map`) is expected to contain a map of class name to hashes of JARs that are allowed to provide that
|
||||
class. The process for upgrading an app then involves asking the zone operator to add the hash of your new JAR to the
|
||||
parameters file, and trigger the network parameters upgrade process. This involves each node operator running a shell
|
||||
command to accept the new parameters file and then restarting the node. Node owners who do not restart their node in
|
||||
time effectively stop being a part of the network.
|
||||
|
||||
**Signature constraints.** These enforce an association between a state and its associated contract JAR which must be
|
||||
signed by a specified identity, via the regular Java ``jarsigner`` tool. This is the most flexible type
|
||||
and the smoothest to deploy: no restarts or contract upgrade transactions are needed.
|
||||
When a CorDapp is build using :ref:`corda-gradle-plugin <cordapp_build_system_signing_cordapp_jar_ref>` the JAR is signed
|
||||
by Corda development key by default, an external keystore can be configured or signing can be disabled.
|
||||
|
||||
.. warning:: CorDapps can only use signature constraints when participating in a Corda network using a minimum platform version of 4.
|
||||
An auto downgrade rule applies to signed CorDapps built and tested with Corda 4 but running on a Corda network of a lower version:
|
||||
if the associated contract class is whitelisted in the network parameters then zone constraints are applied, otherwise hash constraints are used.
|
||||
|
||||
A ``TransactionState`` has a ``constraint`` field that represents that state's attachment constraint. When a party
|
||||
constructs a ``TransactionState``, or adds a state using ``TransactionBuilder.addOutput(ContractState)`` without
|
||||
specifying the constraint parameter, a default value (``AutomaticPlaceholderConstraint``) is used. This default will be
|
||||
automatically resolved to a specific ``HashAttachmentConstraint`` or a ``WhitelistedByZoneAttachmentConstraint``.
|
||||
This automatic resolution occurs when a ``TransactionBuilder`` is converted to a ``WireTransaction``. This reduces
|
||||
the boilerplate that would otherwise be involved.
|
||||
|
||||
Finally, an ``AlwaysAcceptAttachmentConstraint`` can be used which accepts anything, though this is intended for
|
||||
testing only, and a warning will be shown if used by a contract.
|
||||
|
||||
Please note that the ``AttachmentConstraint`` interface is marked as ``@DoNotImplement``. You are not allowed to write
|
||||
new constraint types. Only the platform may implement this interface. If you tried, other nodes would not understand
|
||||
your constraint type and your transaction would not verify.
|
||||
|
||||
.. warning:: An AlwaysAccept constraint is effectively the same as disabling security for those states entirely.
|
||||
Nothing stops you using this constraint in production, but that degrades Corda to being effectively a form
|
||||
of distributed messaging with optional contract logic being useful only to catch mistakes, rather than potentially
|
||||
malicious action. If you are deploying an app for which malicious actors aren't in your threat model, using an
|
||||
AlwaysAccept constraint might simplify things operationally.
|
||||
|
||||
An example below shows how to construct a ``TransactionState`` with an explicitly specified hash constraint from within
|
||||
a flow:
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
// Constructing a transaction with a custom hash constraint on a state
|
||||
TransactionBuilder tx = new TransactionBuilder();
|
||||
|
||||
Party notaryParty = ... // a notary party
|
||||
|
||||
tx.addInputState(...)
|
||||
tx.addInputState(...)
|
||||
|
||||
DummyState contractState = new DummyState();
|
||||
|
||||
TransactionState transactionState = new TransactionState(contractState, DummyContract.Companion.getPROGRAMID(), notaryParty, null, HashAttachmentConstraint(myhash));
|
||||
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
|
||||
|
||||
.. _contract_non-downgrade_rule_ref:
|
||||
|
||||
Contract attachment non-downgrade rule
|
||||
--------------------------------------
|
||||
Contract code is versioned and deployed as an independent JAR that gets imported into a node's database as a contract attachment (either explicitly
|
||||
uploaded via RPC or automatically loaded from disk). When constructing new transaction it is paramount to ensure
|
||||
that the contract version of code associated with new output states is the same or newer than the highest version of any existing input states.
|
||||
This is to prevent the possibility of nodes selecting older, potentially malicious or buggy contract code when creating new states from
|
||||
existing consumed states.
|
||||
|
||||
Transactions contain an attachment for each contract. The version of the output states is the version of this contract attachment.
|
||||
See :doc:`versioning` for more details on how these versions are set. These can be seen as the version of the code that instantiated and
|
||||
serialised those classes.
|
||||
|
||||
The non-downgrade rule specifies that the version of the code used in the transaction that spends a state needs to be greater than or equal to
|
||||
the highest version of the input states (i.e. spending_version >= creation_version)
|
||||
|
||||
The contract attachment non-downgrade rule is enforced in two locations:
|
||||
|
||||
1. Transaction building, upon creation of new output states. During this step, the node also selects the latest available attachment
|
||||
(i.e. the contract code with the latest contract class version).
|
||||
2. Transaction verification, upon resolution of existing transaction chains.
|
||||
|
||||
A version number is stored in the manifest information of the enclosing JAR file. This version identifier should be a whole number starting
|
||||
from 1. This information should be set using the Gradle cordapp plugin, or manually, as described in :doc:`versioning`.
|
||||
|
||||
|
||||
Uniqueness requirement Contract and Version for Signature Constraint
|
||||
--------------------------------------------------------------------
|
||||
|
||||
CorDapps in Corda 4 may be signed (to use new signature constraints functionality) or unsigned, and versioned.
|
||||
The following controls are enforced for these different types of jars within the attachment store of a node:
|
||||
|
||||
- Signed contract JARs must be uniquely versioned per contract class (or group of).
|
||||
At runtime the node will throw a `DuplicateContractClassException`` exception if this condition is violated.
|
||||
|
||||
- Unsigned contract JARs: there should not exist multiple instances of the same contract jar.
|
||||
When a whitelisted JARs is imported and it doesn't contain a version number, the version will be copied from the position (counting from 1)
|
||||
of this JAR in the whilelist. The same JAR can be present in many lists (if it contains many contracts),
|
||||
in such case the version will be equal to the highest position of the JAR in all lists.
|
||||
The new whitelist needs to be distributed to the node before the JAR is imported, otherwise it will receive default version.
|
||||
At run-time the node will warn of duplicates encountered.
|
||||
The most recent version given by insertionDate into the attachment storage will be used upon transaction building/resolution.
|
||||
App versioning with signature constraints
|
||||
-----------------------------------------
|
||||
|
||||
Signed apps require a version number to be provided, see :doc:`versioning`. You can't import two different JARs that claim to be the same
|
||||
version, export the same contract classes and which are both signed. At runtime the node will throw a
|
||||
``DuplicateContractClassException`` exception if this condition is violated.
|
||||
|
||||
Issues when using the HashAttachmentConstraint
|
||||
----------------------------------------------
|
||||
@ -262,16 +131,16 @@ From there it's suspended waiting to be retried on node restart.
|
||||
This gives the node operator the opportunity to recover from those errors, which in the case of constraint violations means
|
||||
adding the right cordapp jar to the ``cordapps`` folder.
|
||||
|
||||
|
||||
CorDapps as attachments
|
||||
-----------------------
|
||||
|
||||
CorDapp JARs (see :doc:`cordapp-overview`) that contain classes implementing the ``Contract`` interface are automatically
|
||||
loaded into the ``AttachmentStorage`` of a node, and made available as ``ContractAttachments``.
|
||||
They are retrievable by hash using ``AttachmentStorage.openAttachment``.
|
||||
These JARs can either be installed on the node or fetched from the network using the ``FetchAttachmentsFlow``.
|
||||
|
||||
.. note:: The obvious way to write a CorDapp is to put all you states, contracts, flows and support code into a single
|
||||
They are retrievable by hash using ``AttachmentStorage.openAttachment``. These JARs can either be installed on the
|
||||
node or will be automatically fetched over the network when receiving a transaction.
|
||||
|
||||
.. warning:: The obvious way to write a CorDapp is to put all you states, contracts, flows and support code into a single
|
||||
Java module. This will work but it will effectively publish your entire app onto the ledger. That has two problems:
|
||||
(1) it is inefficient, and (2) it means changes to your flows or other parts of the app will be seen by the ledger
|
||||
as a "new app", which may end up requiring essentially unnecessary upgrade procedures. It's better to split your
|
||||
@ -282,15 +151,12 @@ These JARs can either be installed on the node or fetched from the network using
|
||||
Constraints propagation
|
||||
-----------------------
|
||||
|
||||
As was mentioned above, the TransactionBuilder API gives the CorDapp developer or even malicious node owner the possibility
|
||||
As was mentioned above, the ``TransactionBuilder`` API gives the CorDapp developer or even malicious node owner the possibility
|
||||
to construct output states with a constraint of his choosing.
|
||||
Also, as listed above, some constraints are more restrictive then others.
|
||||
For example, the ``HashAttachmentConstraint`` is the most restrictive, basically reducing the universe of possible attachments
|
||||
to 1 (see migrating from hash constraints in note below), while the ``AlwaysAcceptAttachmentConstraint`` allows any attachment to be selected.
|
||||
|
||||
For the ledger to remain in a consistent state, the expected behavior is for output state to inherit the constraints of input states.
|
||||
This guarantees that for example, a transaction can't output a state with the ``AlwaysAcceptAttachmentConstraint`` when the
|
||||
corresponding input state was the ``HashAttachmentConstraint``. Translated, this means that if this rule is enforced, it ensures
|
||||
corresponding input state was the ``SignatureAttachmentConstraint``. Translated, this means that if this rule is enforced, it ensures
|
||||
that the output state will be spent under similar conditions as it was created.
|
||||
|
||||
Before version 4, the constraint propagation logic was expected to be enforced in the contract verify code, as it has access to the entire Transaction.
|
||||
@ -298,47 +164,21 @@ Before version 4, the constraint propagation logic was expected to be enforced i
|
||||
Starting with version 4 of Corda, the constraint propagation logic has been implemented and enforced directly by the platform,
|
||||
unless disabled using ``@NoConstraintPropagation`` - which reverts to the previous behavior.
|
||||
|
||||
For Contracts that are not annotated with ``@NoConstraintPropagation``, the platform implements a fairly simple constraint transition policy
|
||||
For contracts that are not annotated with ``@NoConstraintPropagation``, the platform implements a fairly simple constraint transition policy
|
||||
to ensure security and also allow the possibility to transition to the new ``SignatureAttachmentConstraint``.
|
||||
|
||||
.. note:: Migration from hash to signature constraints is automatic if the transaction building node has a signed version of the
|
||||
original contract jar (used in previous transactions generating hash constrained states). Additionally, it is a requirement that
|
||||
the owner of this signed jar register the java package namespace of the encompassing contract classes with the network parameters.
|
||||
See :ref:`package_namespace_ownership` introduced in Corda 4.
|
||||
|
||||
During transaction building the ``AutomaticPlaceholderConstraint`` for output states will be resolved and the best contract attachment versions
|
||||
will be selected based on a variety of factors so that the above holds true.
|
||||
If it can't find attachments in storage or there are no possible constraints, the Transaction Builder will fail early.
|
||||
|
||||
For example:
|
||||
|
||||
- In the simple case, if a ``MyContract`` input state is constrained by the ``HashAttachmentConstraint``, then the constraints of all output states of that type will be resolved
|
||||
to the ``HashAttachmentConstraint`` with the same hash, and the attachment with that hash will be selected.
|
||||
|
||||
- For upgradeable constraints like the ``WhitelistedByZoneAttachmentConstraint``, the output states will inherit the same,
|
||||
and the selected attachment will be the latest version installed on the node.
|
||||
|
||||
- A more complex case is when for ``MyContract``, one input state is constrained by the ``HashAttachmentConstraint``, while another
|
||||
state by the ``WhitelistedByZoneAttachmentConstraint``. To respect the rule from above, if the hash of the ``HashAttachmentConstraint``
|
||||
is whitelisted by the network, then the output states will inherit the ``HashAttachmentConstraint``, as it is more restrictive.
|
||||
If the hash was not whitelisted, then the builder will fail as it is unable to select a correct constraint.
|
||||
|
||||
- The ``SignatureAttachmentConstraint`` is an upgradeable constraint, same as the ``WhitelistedByZoneAttachmentConstraint``.
|
||||
By convention we allow states to transition to the ``SignatureAttachmentConstraint`` from the ``WhitelistedByZoneAttachmentConstraint`` as long as the Signatures
|
||||
from new constraints are all the jarsigners from the whitelisted attachment. We also allow transitioning of states from ``HashAttachmentConstraint`` to
|
||||
``SignatureAttachmentConstraint`` where both the unsigned and signed versions of the associated contract attachment are loaded in a node, and the java
|
||||
package namespace of encompassing contract classes is registered with the network parameters using the same signing key as the signed contract jar.
|
||||
|
||||
For Contracts that are annotated with ``@NoConstraintPropagation``, the platform requires that the Transaction Builder specifies
|
||||
an actual constraint for the output states (the ``AutomaticPlaceholderConstraint`` can't be used) .
|
||||
will be selected based on a variety of factors so that the above holds true. If it can't find attachments in storage or there are no
|
||||
possible constraints, the ``TransactionBuilder`` will throw an exception.
|
||||
|
||||
Debugging
|
||||
---------
|
||||
If an attachment constraint cannot be resolved, a ``MissingContractAttachments`` exception is thrown. There are two
|
||||
common sources of ``MissingContractAttachments`` exceptions:
|
||||
If an attachment constraint cannot be resolved, a ``MissingContractAttachments`` exception is thrown. There are three common sources of
|
||||
``MissingContractAttachments`` exceptions:
|
||||
|
||||
Not setting CorDapp packages in tests
|
||||
*************************************
|
||||
|
||||
You are running a test and have not specified the CorDapp packages to scan.
|
||||
When using ``MockNetwork`` ensure you have provided a package containing the contract class in ``MockNetworkParameters``. See :doc:`api-testing`.
|
||||
|
||||
@ -374,6 +214,7 @@ See :doc:`generating-a-node` for detailed instructions.
|
||||
|
||||
Wrong fully-qualified contract name
|
||||
***********************************
|
||||
|
||||
You are specifying the fully-qualified name of the contract incorrectly. For example, you've defined ``MyContract`` in
|
||||
the package ``com.mycompany.myapp.contracts``, but the fully-qualified contract name you pass to the
|
||||
``TransactionBuilder`` is ``com.mycompany.myapp.MyContract`` (instead of ``com.mycompany.myapp.contracts.MyContract``).
|
@ -17,10 +17,20 @@ However, there are usually new features and other opt-in changes that may improv
|
||||
application that are worth considering for any actively maintained software. This guide shows you how to upgrade your app to benefit
|
||||
from the new features in the latest release.
|
||||
|
||||
.. warning:: The sample apps found in the Corda repository and the Corda samples repository are not intended to be used in production.
|
||||
If you are using them you should re-namespace them to a package namespace you control, and sign/version them yourself.
|
||||
|
||||
.. contents::
|
||||
:depth: 3
|
||||
|
||||
Step 1. Adjust the version numbers in your Gradle build files
|
||||
Step 1. Switch any RPC clients to use the new RPC library
|
||||
----------------------------------------------------------
|
||||
|
||||
Although the RPC API is backwards compatible with Corda 3, the RPC wire protocol isn't. Therefore RPC clients like web servers need to be
|
||||
updated in lockstep with the node to use the new version of the RPC library. Corda 4 delivers RPC wire stability and therefore in future you
|
||||
will be able to update the node and apps without updating RPC clients.
|
||||
|
||||
Step 2. Adjust the version numbers in your Gradle build files
|
||||
-------------------------------------------------------------
|
||||
|
||||
Alter the versions you depend on in your Gradle file like so:
|
||||
@ -43,7 +53,7 @@ You should also ensure you're using Gradle 4.10 (but not 5). If you use the Grad
|
||||
|
||||
Otherwise just upgrade your installed copy in the usual manner for your operating system.
|
||||
|
||||
Step 2. Update your Gradle build file
|
||||
Step 3. Update your Gradle build file
|
||||
-------------------------------------
|
||||
|
||||
There are several adjustments that are beneficial to make to your Gradle build file, beyond simply incrementing the versions
|
||||
@ -110,7 +120,7 @@ starting from 1.
|
||||
If you use the finance demo app, you should adjust your dependencies so you depend on the finance-contracts
|
||||
and finance-workflows artifacts from your own contract and workflow JAR respectively.
|
||||
|
||||
Step 3. Security: Upgrade your use of FinalityFlow
|
||||
Step 4. Security: Upgrade your use of FinalityFlow
|
||||
--------------------------------------------------
|
||||
|
||||
The previous ``FinalityFlow`` API is insecure. It doesn't have a receive flow, so requires counterparty nodes to accept any and
|
||||
@ -224,7 +234,7 @@ You may already be using ``waitForLedgerCommit`` in your responder flow for the
|
||||
Now that it's calling ``ReceiveFinalityFlow``, which effectively does the same thing, this is no longer necessary. The call to
|
||||
``waitForLedgerCommit`` should be removed.
|
||||
|
||||
Step 4. Security: Upgrade your use of SwapIdentitiesFlow
|
||||
Step 5. Security: Upgrade your use of SwapIdentitiesFlow
|
||||
--------------------------------------------------------
|
||||
|
||||
The :ref:`confidential_identities_ref` API is experimental in Corda 3 and remains so in Corda 4. In this release, the ``SwapIdentitiesFlow``
|
||||
@ -232,7 +242,7 @@ has been adjusted in the same way as ``FinalityFlow`` above, to close problems w
|
||||
outside of other flow context. Old code will still work, but it is recommended to adjust your call sites so a session is passed into
|
||||
the ``SwapIdentitiesFlow``.
|
||||
|
||||
Step 5. Possibly, adjust test code
|
||||
Step 6. Possibly, adjust test code
|
||||
----------------------------------
|
||||
|
||||
``MockNodeParameters`` and functions creating it no longer use a lambda expecting a ``NodeConfiguration`` object.
|
||||
@ -283,7 +293,7 @@ For instance, if you have 2 CorDapps containing the packages ``net.corda.example
|
||||
.. note:: If you have any CorDapp code (e.g. flows/contracts/states) that is only used by the tests and located in the same test module, it won't be discovered now.
|
||||
You will need to move them in the main module of one of your CorDapps or create a new, separate CorDapp for them, in case you don't want this code to live inside your production CorDapps.
|
||||
|
||||
Step 6. Security: Add BelongsToContract annotations
|
||||
Step 7. Security: Add BelongsToContract annotations
|
||||
---------------------------------------------------
|
||||
|
||||
In versions of the platform prior to v4, it was the responsibility of contract and flow logic to ensure that ``TransactionState`` objects
|
||||
@ -300,7 +310,7 @@ to be governed by a contract that is either:
|
||||
Learn more by reading ":ref:`implicit_constraint_types`". If an app targets Corda 3 or lower (i.e. does not specify a target version),
|
||||
states that point to contracts outside their package will trigger a log warning but validation will proceed.
|
||||
|
||||
Step 7. Learn about signature constraints and JAR signing
|
||||
Step 8. Learn about signature constraints and JAR signing
|
||||
---------------------------------------------------------
|
||||
|
||||
:doc:`design/data-model-upgrades/signature-constraints` are a new data model feature introduced in Corda 4. They make it much easier to
|
||||
@ -314,7 +324,7 @@ automatically use them if your application JAR is signed. **We recommend all JAR
|
||||
with developer certificates is deployed to a production node, the node will refuse to start. Therefore to deploy apps built for Corda 4
|
||||
to production you will need to generate signing keys and integrate them with the build process.
|
||||
|
||||
Step 8. Security: Package namespace handling
|
||||
Step 9. Security: Package namespace handling
|
||||
--------------------------------------------
|
||||
|
||||
Almost no apps will be affected by these changes, but they're important to know about.
|
||||
@ -331,7 +341,7 @@ In the unlikely event that you were injecting code into ``net.corda.finance.*``
|
||||
into a new package, e.g. ``net/corda/finance/flows/MyClass.java`` can be moved to ``com/company/corda/finance/flows/MyClass.java``.
|
||||
As a consequence your classes are no longer able to access non-public members of finance CorDapp classes.
|
||||
|
||||
When recompiling your JARs for Corda 4, your own apps will also become sealed, meaning other JARs cannot place classes into your own packages.
|
||||
When signing your JARs for Corda 4, your own apps will also become sealed, meaning other JARs cannot place classes into your own packages.
|
||||
This is a security upgrade that ensures package-private visibility in Java code works correctly. If other apps could define classes in your own
|
||||
packages, they could call package-private methods, which may not be expected by the developers.
|
||||
|
||||
@ -342,9 +352,8 @@ Whilst this feature is optional and not strictly required, it may be helpful to
|
||||
where type names may be taken "as read". You can learn more about this feature and the motivation for it by reading
|
||||
":doc:`design/data-model-upgrades/package-namespace-ownership`".
|
||||
|
||||
|
||||
Step 9. Consider adding extension points to your flows
|
||||
------------------------------------------------------
|
||||
Step 10. Consider adding extension points to your flows
|
||||
-------------------------------------------------------
|
||||
|
||||
In Corda 4 it is possible for flows in one app to subclass and take over flows from another. This allows you to create generic, shared
|
||||
flow logic that individual users can customise at pre-agreed points (protected methods). For example, a site-specific app could be developed
|
||||
@ -353,16 +362,15 @@ into shared business logic, but it makes perfect sense to put into a user-specif
|
||||
|
||||
If your flows could benefit from being extended in this way, read ":doc:`flow-overriding`" to learn more.
|
||||
|
||||
Step 10. Possibly update Vault state queries
|
||||
Step 11. Possibly update vault state queries
|
||||
--------------------------------------------
|
||||
|
||||
Queries made on a node's vault can filter by the relevancy of those states to the node in Corda 4. As this functionality does not exist in
|
||||
Corda 3, apps targeting that release will continue to receive all states in any vault queries. In Corda 4, the default is to return all
|
||||
states in the vault, to maintain backwards compatibility. However, it may make sense to migrate queries expecting just those states relevant
|
||||
In Corda 4 queries made on a node's vault can filter by the relevancy of those states to the node. As this functionality does not exist in
|
||||
Corda 3, apps will continue to receive all states in any vault queries. However, it may make sense to migrate queries expecting just those states relevant
|
||||
to the node in question to query for only relevant states. See :doc:`api-vault-query.rst` for more details on how to do this. Not doing this
|
||||
may result in queries returning more states than expected if the node is using Observer node functionality (see ":doc:`tutorial-observer-nodes.rst`").
|
||||
may result in queries returning more states than expected if the node is using observer functionality (see ":doc:`tutorial-observer-nodes.rst`").
|
||||
|
||||
Step 10. Explore other new features that may be useful
|
||||
Step 12. Explore other new features that may be useful
|
||||
------------------------------------------------------
|
||||
|
||||
Corda 4 adds several new APIs that help you build applications. Why not explore:
|
||||
|
Loading…
Reference in New Issue
Block a user