0
votes

I am trying to implement an Validator class in Contract-States library of CordApp, which have several validation methods that are inherited by Model classes in their init() fun, so that each time a Model class is called/initialized the validation happens on the spot.

Now I'm stuck at a point, where I need to validate whether the incoming member name(through a Model class) matches with Organisation name of the node, I need to access the NetworkMap for that. How can I do that?

In Work-Flow library each flow extends FlowLogic class that implements ServiceHub interface and through that we can access the NetworkMap, but how to do that in Contract-States library?

P.S. - I'm trying to avoid any circular dependency (Contract-States lib should not depend on Work-Flow lib)

1
Just a Note: I'm using Corda Enterprise 4.2dexter111

1 Answers

2
votes

The short answer, you can't.

The long answer:

  • The difference between flow validations and contract validation is that the latter (contracts) must be deterministic meaning for the same input they must always give the same output whether it's now or after 100 years, in the current node or any other node.
  • The reason for that is because any time (even in the future) when a node receives a transaction it must validate that transaction which includes validating the inputs which in return requires validating the transaction that created those inputs and so on, until you get a fully validated graph of all the inputs that lead to the outputs that were used as inputs and so on.
  • That's why the contract should return the same result any time, and that's why it should be deterministic, and that's why contracts (unlike flows) don't have access to external resources (like HTTP calls, or even the node's database).
  • Imagine if the contract was relying on the node's database for some validation rule, as you know, states are distributed on a need to know basis (i.e. only to participants of the state); so one node might have the state that you're using as validation source and another node won't, so the contract's output (transaction valid/invalid) will differ between nodes, and that breaks the deterministic concept.
  • Contracts only have access to the transaction components: inputs, outputs, attachments, signatures, time-windows, reference states.

Good news, there are other ways to implement your requirement:

  • Using an attachment that has the list of nodes that are allowed to be part of the transaction, this method should be used if the blacklist is not updated frequently and you can see the example here.
  • Using reference states, where you can create a state that has the allowed parties and require the existence of that reference state in your transaction; this method should be used when the blacklist is more frequently updated. You can read about reference states here.
  • Using Oracles, this option is in case there is a world organization (or for instance Ministry of Trade of some country) that provides an Oracle which returns the list of blacklisted parties; and you use that Oracle in your transaction. You can read about Oracles here.