How Do I Store Extra Private Information Related To A State? - corda

I have a simple flow that creates a state between a buyer and seller and obviously each side can see everything on the state.
However, I now have a requirement that the buyer wants to store the user that processed the transaction for auditing and reporting purposes.
The user in this case is not a node or an account but a user that has logged in to the application and been authorised via Active Directory.
I could just add the user name to the state as a String but that would expose private data to the seller.
An alternative would be to obfuscate the name in some way but I would rather store the information in a separate table outside the state and only in the buyers vault.
How do I do this and is there a sample that demonstrates it?

You can create a second output state, which is used in the same transaction, but has only the token issuer as participant. Then of course, it is up to you to make the link between the "issued state" and the "recorder state", it depends on what you will store inside the latter.
Let's make an example of a fungible token issuance from Node1 to Node2. You could create a "issuance recorder state" that aims at recording something on Node1's vault only, like so (note the list of participants):
// the "recorder" state visible only in Node1's vault
#BelongsToContract(IssuanceRecordContract::class)
class IssuanceRecord(
val holder: AbstractParty,
val amount: Amount<IssuedTokenType>
) : ContractState {
override val participants: List<AbstractParty>
get() = listOf(amount.token.issuer)
}
and then you could pass it to the same TransactionBuilder that you are using to issue the fungible token (which instead has both parties in the list of participants), like so:
// This is from the Issuanflow launched from Node1
#Suspendable
override fun call(): String {
...
...
// Create the FungibleToken (issuedToken is an IssuedTokenType created before)
val tokenCoin = FungibleToken(Amount(volume.toLong(), issuedToken), holderAnonymousParty)
// create the "recorder" output state visible only to Node1
val issuanceRecord = IssuanceRecord(holderAnonymousParty, tokenCoin.amount)
// create the Transaction Builder passing the "recorder" output state
val transactionBuilder = TransactionBuilder(notary).apply {
addOutputState(issuanceRecord, IssuanceRecordContract.ID)
addCommand(Command(IssuanceRecordContract.Commands.Issue(), ourIdentity.owningKey))
}
// Issue the token passing the transactionBuilder and the fungible token
addIssueTokens(transactionBuilder, tokenCoin)
// collect signatures
// verify transaction
// FinalityFlow (fundamental to make this work in Node1)
}
This way, I think, the recorder states will be atomically stored in Node1's vault. If something happens, the transaction will be not successful for both output states.

Related

How to transfer an asset which isn't money from one party to another in corda

Basically i have two parties in my state and i want to transfer an asset say a house or a car from one party to another or issue the same asset to a party so how can i manage that?
I tried searching the docs but couldn't find anything substantial
If your modeling or defining your own states then you decide. Some attribute of your state is set to the owning party. Transfer of the asset is a transaction that changes the party on this attribute, presumably initiated by only the owner or a party delegated that power.
Let's use the example of your House State
Your house state might look something like this:
#BelongsToContract(HouseContract::class)
data class HouseState (
val address: String,
val appraisal: Amount<USD>,
val owner: Party,
val participants: List<Party>,
override val linearId: UniqueIdentifier = UniqueIdentifier()
): ContractState, LinearState {
fun withNewOwner(party: Party): HouseState {
return this.copy(owner = party)
}
override val participants: List<AbstractParty> get() = players
}
}
In Corda, states are immutable. You would change the owner of a House by marking the input state as consumed and issuing a new houseState onto the ledger with the owner field updated.
Some states even have convenience methods (see the HouseState above) That return a copy of the input state with a field updated (in this case the owner) to be included in the transaction as the output state.

How should we upgrade a state which is owned by one DL participant but has a participant list which includes more than one participant?

I am looking for the correct contract upgrade process. Consider the following example:
SimpleContract : Contract {
data class State(override val owner: AbstractParty, val relevantParticipant: AbstractParty) : OwnableState {
override val participants: List<AbstractParty> = listOf(owner, relevantParticipant)
override fun withNewOwner(newOwner: AbstractParty): CommandAndState
= CommandAndState(Commands.Move(), copy(owner = newOwner))
}
}
As I understand, this state is only stored in the owner's vault, but the relevantParticipant also has (in it's transaction storage) the transaction where the SimpleContract.State is one of the outputs. If the owner were to (authorize and) initiate the upgrade, the flow fails as the relevantParticipant does not have the authorized contract upgrade for it. What is the right approach here?
One solution is for the owner to send the StateRef to the relevantParticipant. The relevantParticipant can then retrieve the StateAndRef using ServiceHub.loadState, and choose to authorise the contract upgrade using ContractUpgradeFlow.Authorise.
This is better than sending the StateAndRef directly, since the relevantParticipant can then verify that the state being sent hasn't been tampered with (since they retrieve the actual state from their storage, not the counterparty's).

Transaction between 3 participants with Corda

Do you have any example how to execute multiple transactions between participants A, B, C. I can do it ease between 2 parties A and B. Have fount the same discussion on the official Corda forum without result
Sharing transaction among multiple nodes
Is it possible? Do you have any example?
If you are issuing a new state, you can simply alter the participants of this state to ensure all parties receive the new state. Here is an example I have created with KYC data. This is example is updating a state (not issuing a new state), but the same principle applies - simply alter the participants list to control who will see that state. The KYC State is as follows:
#CordaSerializable
data class State(val firstName: String, val lastName: String, val accountNum: String, val owner: AbstractParty,
override val linearId: UniqueIdentifier = UniqueIdentifier(), val banksInvolved: List<AbstractParty> = emptyList()) : QueryableState, ContractState, LinearState {
//Each time a TD is issued with this KYC data, the bank it is issued to is added to this banks involved list, meaning the data is now stored in that banks vault
override val participants: List<AbstractParty> get() = banksInvolved.plus(owner)
This participants variable is the list of all nodes that will store this state in their vault (i.e will be notified about the states creation, update, etc). This is where you would add new nodes too for them to be able to view the state in their vault.
Then within a flow, to notify a new bank that they have received KYC data, we simply add the state as output with a new bank added to the banksInvolved list. This will make this new bank a participant with this state:
builder.addOutputState(KYCData.first().state.copy(data = KYCData.first().state.data.copy(
banksInvolved = KYCData.first().state.data.banksInvolved.plus(issuingInstitue)))) //Same state but with a new bank involved - i.e able to view this KYC data
check your state, there you can mention the List of participants for transaction.

In Corda, can persisted ContractStates encode commands?

I have some ContractState, and there are two commands that can 'delete' the state (mark it as historic, with no new state to replace it) - let's say 'Delete' and 'Revoke', which have different real-world consequences.
I can still see the historic states in the vault, right? How can I determine which command deleted the state? I suppose I could add some enum to the state: 'Active|Deleted|Revoked', and then move the state from S(Active) -> S(Deleted|Revoked) -> Historic. But that seems clunky.
In theory, you could determine which command was used to consume the state by checking the transaction that consumed the state.
However, there is currently no non-deprecated API for viewing the contents of the node's transaction storage as a node owner. This is because in a future version of Corda, we expect transaction resolution to occur within a secure guard extension (SGX). This will affect which transactions are visible, and Corda therefore cannot commit to a stable API for viewing the contents of the node's transaction storage.
If you're willing to use the deprecated internalVerifiedTransactionsSnapshot/internalVerifiedTransactionsFeed API, you could do something like:
val (_, vaultUpdates) = proxy.vaultTrackBy<ContractState>()
vaultUpdates.toBlocking().subscribe { update ->
update.produced.forEach { stateAndRef ->
val newStateTxId = stateAndRef.ref.txhash
val transactions = proxy.internalVerifiedTransactionsSnapshot()
val transaction = transactions.find { transaction -> transaction.id == newStateTxId }!!
val commands = transaction.tx.commands
}
}
An alternative would be to add a status field to the state, and updating the status field instead of marking it as consumed when "deleting" it. For example:
class MyState(val expired: Boolean): ContractState {
override val participants = TODO()
}

How to access state scoped to current behaviour from postStop

I have an online game, with an actor that represents a user's state. State updates via recursive become calls:
private PartialFunction<Object, BoxedUnit> updatedUser(final User user) {
return ReceiveBuilder.
...
matchEquals("update", s -> {
context().become(updatedUser(new User(...)));
}).build();
}
Now when the user leaves the game (actor stops), I need to save its state to a database. I think the ideal place for this would be sending a message from postStop. But user's state is out of scope.
public void postStop() throws Exception {
//user state out of scope
Database.tell(user, self());
}
I don't want to have state as an actor field. What would be the best way to solve this problem?
There's no way to access the user value outside of the updatedUser function.
Just make your user state an instance variable of the actor.

Resources