Corda - Validating notaries and custom objects in states - corda

In relation to this post: Corda - java.lang.IllegalArgumentException being thrown from a validating notary
I've identified a case in Corda where states sometimes need to store a custom data type, however validating transactions using these states fails when using a validating notary.
Consider the following types to be implemented in the same package, in the same jar file:
Example Custom Type
package com.example.statescontracts
#CordaSerializable
data class Foo(
val bar: Int,
val baz: String
)
Example State
package com.example.statescontracts
data class FooState(
override val linearId: UniqueIdentifier,
val obligor: AbstractParty,
val obligee: AbstractParty,
val foos: Set<Foo>
) : LinearState {
override val participants get() = listOf(obligor, obligee)
}
Issuing a new FooState instance to the ledger probably isn't affected as it's not consuming a previous FooState instance, but subsequent consumption of FooState instances seem to fail for validating notaries.
Exception
java.lang.IllegalArgumentException: Not a valid Java name:
java.util.Set<com.example.statescontracts.Foo>
Assumptions
Validation can occur for all participants of the state who have the states/contracts JAR file, and therefore can access the Foo type, however this doesn't work for the notary because it doesn't have a copy of the states/contracts JAR file locally.
As I understand it, the states/contracts JAR file should be kept small as it's attached to the transaction when proposed, therefore validating notaries should be able to validate using classes found in the JAR attached to the transaction.
Question
Can anyone verify whether my assumptions are correct, and if so, why this issue occurs for validating notaries, and how to correct this issue?

As described in the tech white paper, the intended end design is that the contract JARs are taken from attachments and run inside the deterministic JVM, where they're sandboxed and resource monitored.
A standalone DJVM preview is shipping in Corda 4, but is not integrated. We will continue to work on this over time, which will allow nodes that don't have the contracts JAR to validate transactions. For now, validating notaries do need to have every version of every app they may encounter installed. Non-validating notaries don't suffer this problem.

As of Corda 3, validating notaries need the states/contracts JAR file for each transaction they are notarising.

Related

corda 4 - Can a State belong to more than one Contract class

We are building a POC using Corda 4 and Springboot web server.
The POC is running in DEV MODE in our local network using PostgreSQL as database
The CorDapp developed for POC has four nodes -
Provider Node (Node 1)
Consumer 1 Node (Node 2)
Consumer 2 Node (Node 3)
Notary Node
All the above nodes participate in a deal. A deal consists of three worflows -
Flow 1 : data flows from Node 1 to Node 2
Flow 2 : data flows from Node 2 to Node 1 and Node 3
Flow 3 : data flows from Node 3 to Node 1 and Node 2
When all the three flows are executed the deal is FINISHED.
Suppose "DEAL 1" is started and "Flow 1" and 'Flow 2" are executed. Also for "DEAL 1" assuming "IOUContract.class" is used.
Due to new requirements, contract changed and a new contract class file "IOUContractv2.class" was created.
Now the application has two contracts -
"IOUContract.class" --- Used by "DEAL 1"
"IOUContractv2.class" --- Will be used by new deals
When I am linking above contract classes to the "State" using "BelongsToContract" annotation, the compiler does not allow repeated use of the same annotation.
#BelongsToContract(IOUContract::class)
#BelongsToContract(IOUContractv2::class)
data class State(val iou: IOU,
val sender: Party,
val recipient: Party,
var recipient2: Party,
val state: WorkflowState = WorkflowState.NEW,
override val linearId: UniqueIdentifier = UniqueIdentifier(iou.bndId.toString())) : LinearState, QueryableState {
Questions:
How can I make both contracts use the same state?
Is my method to use two contracts wrong?
Can an aplication have only one Contract?
How to finish the execution of old "Deals" that used old contracts?
To make sure "What you see is what I see", we have "states" in Corda. States evolve over time. This evolution is governed by a set of rules. These rules are written in a "contract". A state transition is always associated with one contract at any point of time. As you have mentioned, you may wish to change these rules. In this case, you have to do a contract upgrade as Alessandro rightly pointed out. Since you are using Corda 4, you can use implicit Signature Constraints to do the contract upgrade. Follow below steps to upgrade your contract.
Stop your node.
Sign the jar. By default, if you do not disable signing in Corda
version 4, the jar is signed when you run the deployNodes task. Stop your node.
Sign the jar. To externally sign the jar use the jarsigner. By default, if you do not disable signing in Corda version 4, the jar is signed when you run the deployNodes task.
Replace the old jar with this newly signed jar.
Replace the old jar with this newly signed jar.

Spring cloud stream kafka transactions in producer side

We have a spring cloud stream app using Kafka. The requirement is that on the producer side the list of messages needs to be put in a topic in a transaction. There is no consumer for the messages in the same app. When i initiated the transaction using spring.cloud.stream.kafka.binder.transaction.transaction-id prefix, I am facing the error that there is no subscriber for the dispatcher and a total number of partitions obtained from the topic is less than the transaction configured. The app is not able to obtain the partitions for the topic in transaction mode. Could you please tell if I am missing anything. I will post detailed logs tomorrow.
Thanks
You need to show your code and configuration as well as the versions you are using.
Producer-only transactions are discussed in the documentation.
Enable transactions by setting spring.cloud.stream.kafka.binder.transaction.transactionIdPrefix to a non-empty value, e.g. tx-. When used in a processor application, the consumer starts the transaction; any records sent on the consumer thread participate in the same transaction. When the listener exits normally, the listener container will send the offset to the transaction and commit it. A common producer factory is used for all producer bindings configured using spring.cloud.stream.kafka.binder.transaction.producer.* properties; individual binding Kafka producer properties are ignored.
If you wish to use transactions in a source application, or from some arbitrary thread for producer-only transaction (e.g. #Scheduled method), you must get a reference to the transactional producer factory and define a KafkaTransactionManager bean using it.
#Bean
public PlatformTransactionManager transactionManager(BinderFactory binders) {
ProducerFactory<byte[], byte[]> pf = ((KafkaMessageChannelBinder) binders.getBinder(null,
MessageChannel.class)).getTransactionalProducerFactory();
return new KafkaTransactionManager<>(pf);
}
Notice that we get a reference to the binder using the BinderFactory; use null in the first argument when there is only one binder configured. If more than one binder is configured, use the binder name to get the reference. Once we have a reference to the binder, we can obtain a reference to the ProducerFactory and create a transaction manager.
Then you would just normal Spring transaction support, e.g. TransactionTemplate or #Transactional, for example:
public static class Sender {
#Transactional
public void doInTransaction(MessageChannel output, List<String> stuffToSend) {
stuffToSend.forEach(stuff -> output.send(new GenericMessage<>(stuff)));
}
}
If you wish to synchronize producer-only transactions with those from some other transaction manager, use a ChainedTransactionManager.

Corda 4 - Querying vault by specific transactionid

We are building a POC using Corda 4 and Springboot web server.
We are currently using the following code to retrieve all the states from the vault via RPC -
val vaultStatesAndRefs = services.proxy.vaultQueryBy<State>().states
val vaultStates = vaultStatesAndRefs.map { it.state.data }
We want - to retrieve a state from the vault via RPC using the transactionId.
Kindly guide in achieving this.
Please note that Corda doesn't guarantee the set of transactions retrieved via any method would remain consistent across future versions of Corda. This is because the future version of Corda would use SGX-encrypted format to exchange transaction chain between nodes. Thus the transactions can only be decrypted in a secure SGX enclave.
Having said that there is no direct API exposed which could be used to obtain state based on transactionId via RPC. The one you could use (internalFindVerifiedTransaction) have been deprecated and would likely be removed in the future versions of Corda.
The way to do this I suppose would be to use flow. You could retrieve the output states based on the transactionId.
SignedTransaction tx = getServiceHub().getValidatedTransactions().getTransaction(
SecureHash.parse(txId));
tx.toLedgerTransaction(getServiceHub()).getOutputStates();
You could then trigger the flow from your client using RPC and get the result from the FlowHandle object returned.
FlowHandle<List<ContractState>> flowHandle =
proxy.startFlowDynamic(GetStateFlow.class, txId);
List<ContractState> list = flowHandle.getReturnValue().get();

How is contract code distributed

Is the contract handling code essentially just Java and run by the server ?.
If I want to edit a contract's functionality do I have to release code to be installed across the network ?.
Great question. The Corda technical whitepaper talks about this. See e.g. section 5.9: https://docs.corda.net/_static/corda-technical-whitepaper.pdf
The short answer is that some of this infrastructure still needs to be built out but the key idea is that a State doesn't just say "the Java class with this name governs my evolution"; it says: "the Java class with this name, living in a JAR with this hash governs my evolution". So there will be no room for games caused by people trying to substitute malicious/compromised implementations.
As for how the code gets distributed: today, it is installed in each node locally. Very soon, it will be able to migrate around the network using the Attachments functionality.
And I should add: the contract verification logic will run in a very strict sandbox: both to limit what it can do and to ensure it is 100% deterministic... we can't have one node thinking a transaction is valid and another one thinking it is invalid!
As Richard notes, states reference contracts. Indeed, there is a contract property in the base ContractState interface:
#CordaSerializable
interface ContractState {
val contract: Contract
val participants: List<AbstractParty>
}
A Corda transaction is required to change any state property. Therefore, if one party wishes to novate/update the contract code then they must propose a transaction which changes the contract reference then ask all required participants to assent to this change.

How to add another regulatory node and add some functionality to it in corda DLT?

I would like to add a new Notary/Regulatory node in my Cordapp application ,
which should perform some extra validation checks when transaction
is completed between two parties.
so that notary/regulatory will be finally checks for some things and stamp the transaction.
There are two options here:
Instead of using the default FinalityFlow to notarise, broadcast and record transactions, you can implement your own flow that performs some additional validation before the notarisation step. The limitation here is that the checks are not part of the notary service.
Create your own custom notary. Here, the custom validation checks happen within the notary service. The ability to do this is a recent change to the codebase, as such the documentation has not been updated to reflect the changes, however the source docs can be found on github:
Instructions for creating a custom notary service: https://github.com/corda/corda/blob/9e563f9b98b79a308d68ecb01c80ce61df048310/docs/source/tutorial-custom-notary.rst
Sample custom notary service code: https://github.com/corda/corda/blob/9e563f9b98b79a308d68ecb01c80ce61df048310/docs/source/example-code/src/main/kotlin/net/corda/docs/CustomNotaryTutorial.kt
As Roger notes, you could customise FinalityFlow/implement your own notary.
An alternative would be:
Add a new node to the network representing some regulator
Write the contract rules so that the regulator is a required signer on transactions
Have the regulator do additional checking of the transaction in their flow before signing

Resources