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:
Mike Hearn 2019-02-11 20:02:06 +01:00
parent 5f70abfeca
commit ca49c5e94d
2 changed files with 72 additions and 223 deletions

View File

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

View File

@ -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: