Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(*): state management of contract instances #709

Conversation

sanketshevkar
Copy link
Member

@sanketshevkar sanketshevkar commented Dec 8, 2021

Changes

  • added to new utility function added to cicero-core to add history of a contract instance to the slc file.
  • A new history.json file stores all the history/states of that contract instance.
  • New api endpoints added to cicero-server to handle contract instances.

Author Checklist

  • Ensure you provide a DCO sign-off for your commits using the --signoff option of git commit.
  • Vital features and changes captured in unit and/or integration tests
  • Commits messages follow AP format
  • Extend the documentation, if necessary
  • Merging to master from fork:branchname

jeromesimeon and others added 30 commits August 24, 2021 13:33
Signed-off-by: sanket shevkar <[email protected]>
@coveralls
Copy link

Coverage Status

Coverage decreased (-1.08%) to 96.198% when pulling b5fae6f on sanketshevkar:sanketshevkar/state-management-slc into 719594c on accordproject:master.

Copy link
Contributor

@dselman dselman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought this was VERY impressive, but I have reservations about how maintainable it will be, in particular about how we have grafted instances into the code base for templates. I think it would be useful to take a step back and potentially to move the instance management code outside of core into a new cicero-contract package that uses cicero-core rather than extends and duplicates some of its logic. This will no doubt lead to some duplication in other areas (e.g. an instance zip file may have to be a zip of zip files (for the templates)) but I think the benefits in terms of modularity probably outweighs the costs. Let's discuss on a call.

We also need to work on the docs, which may also lead to some code improvements in terms of naming and conceptual clarity.

instance,
instance.instantiator,
'instantiate',
'Instantiated Succesfully',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Localization?

Copy link
Member

@martinhalford martinhalford Dec 10, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I understand the question. Are we talking about not having hard-coded strings in English? TBD.

if (this.contractSignatures.length !== 0 ) {
this.verifySignatures();
}
const timestamp = Date.now();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should allow the caller to pass in the timestamp, only using Date.now if not specified. E.g. to ensure determinism if this is running inside a blockchain node.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sanketshevkar to fix.

'Signing in Progress'
);

return await this.toArchive('ergo');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you need to await the Promise as you are returning it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sanketshevkar to fix.

sign(p12File, passphrase, timestamp, signatory) {
if (typeof(p12File) !== 'string') {throw new Error('p12File should be of type String!');}
if (typeof(passphrase) !== 'string') {throw new Error('passphrase should be of type String!');}
if (typeof(timestamp) !== 'number') {throw new Error('timeStamp should be of type Number!');}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in timeStamp

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/**
* signs a string made up of contract hash and time stamp using private key derived
* from the keystore
* @param {String} p12File - encoded string of p12 keystore file
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Encoded how?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sanketshevkar to elaborate.

content.signatures = instance.contractSignatures;

const hasher = crypto.createHash('sha256');
hasher.update(stringify(content));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use template hash

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move to some shared class/package. TBD.

currentState: currentState,
currentHash: currentHash
};
instance.history.push(state);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How large do we expect history to get? It is ok that it lives in memory and just gets bigger and bigger?

Copy link
Member

@martinhalford martinhalford Dec 10, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good question. We may need a couple of different options here for large histories and/or some way to store on immutable blockchains. TBD.

try {
const clause = await initTemplateInstance(req);
const instance = req.params.type === 'clause' ? await initTemplateInstance(req) : req.params.type === 'contract' ? await loadInstance(req) : null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does the caller have to specify the type? We know the type from the template....

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TBD.

);
const archive = await instance.toArchive('ergo');
const file = !req.body.output ? `${process.env.CICERO_CONTRACTS}/${req.params.instanceName}.slc` : `${process.env.CICERO_CONTRACTS}/${req.body.output}.slc`;
fs.writeFileSync(file, archive);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assumes we have write access to the mounted file system - which may not be true in Docker or Cloud.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Let's go with this for the time being and fix in subsequent PR(s). TBD.

* An object containing the data, instatiator's name, author's signatures, party signatures and the history
*
*/
app.post('/instantiate/:instanceName', async function (req, httpResponse, next) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm finding these "polymorphic" rest routes confusing. Would it not be easier to have something like:

/templates/foo/contract/bar/trigger to trigger a specific contract, or /contracts/bar/trigger if we don't want to nest contracts under templates?

Copy link
Member

@martinhalford martinhalford Dec 10, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Would be good to have different end points for templates vs. contract instances. TBD.

@jeromesimeon jeromesimeon self-requested a review December 8, 2021 16:34
Copy link
Member

@jeromesimeon jeromesimeon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is great work but this shouldn't be merged into master at this stage. I would suggest instead to merge into the slc branch where we can address the general question around "what is the slc format" along with all the questions that Dan already asked.

@jeromesimeon
Copy link
Member

jeromesimeon commented Dec 8, 2021

this is great work but this shouldn't be merged into master at this stage. I would suggest instead to merge into the slc branch where we can address the general question around "what is the slc format" along with all the questions that Dan already asked.

Another option is to: make a push for a proper "slc" format in the slc branch and first merge that, then integrate the additional work which is in this PR. (instead of trying to merge both at the same time).

Also, it would be useful to know how this PR relates to #698 (is it just an extension, a rewrite, etc). The merge conflicts makes me wonder if it is based on a slightly outdated version of #698.

@sanketshevkar sanketshevkar changed the base branch from master to poc-slc December 9, 2021 09:24
@sanketshevkar sanketshevkar changed the base branch from poc-slc to master December 9, 2021 09:24
Signed-off-by: sanketshevkar <[email protected]>
@sanketshevkar sanketshevkar changed the base branch from master to poc-slc December 9, 2021 09:56
@jeromesimeon
Copy link
Member

@martinhalford my suggestions to get Sanket's work available for further fixes in a short amount of time:

  1. push the branch "as is" to the repo. I believe Sanket should have the permissions to do that?
  2. have someone rebase Sanket's branch on top of poc-slc
  3. do additional PRs as needed to address Dan's comments

Let me know what you think. The benefit of this is that after 1. anyone can contribute to the work.

@jeromesimeon
Copy link
Member

I believe all of those commits are already in the poc-slc branch which seems to indicate that this PR hasn't been properly based on the latest poc-slc.

Screen Shot 2021-12-15 at 2 28 12 PM

@martinhalford
Copy link
Member

Hi @jeromesimeon, Ok. I'm in agreement if you and @dselman are happy to accept the PR "as is".

(Cc: @sanketshevkar - see above)

Copy link
Member

@jeromesimeon jeromesimeon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are three major blocking issues with this PR:

  1. Not properly based on the poc-slc branch
  2. deletes the whole cicero-transform package, instead importing a fixed version (why?!)
  3. tests are not passing (not sure why they aren't triggered on this PR). Below is a log
  1) ContractInstance
       #sign
         should sign the content hash and timestamp string using the keystore:
     Error: Failed to find history.json in archive file.
      at Function.loadZipFileContents (/Users/jerome.simeon/git/accordproject/cicero/node_modules/@accordproject/ergo-compiler/lib/fileloader.js:47:19)
      at /Users/jerome.simeon/git/accordproject/cicero/packages/cicero-core/lib/instanceloader.js:1417:69
      at Generator.next (<anonymous>)
      at asyncGeneratorStep (lib/instanceloader.js:1305:103)
      at _next (lib/instanceloader.js:1307:194)

  2) ContractInstance
       #verify
         should verify a contract signature:
     Error: Failed to find history.json in archive file.
      at Function.loadZipFileContents (/Users/jerome.simeon/git/accordproject/cicero/node_modules/@accordproject/ergo-compiler/lib/fileloader.js:47:19)
      at /Users/jerome.simeon/git/accordproject/cicero/packages/cicero-core/lib/instanceloader.js:1417:69
      at Generator.next (<anonymous>)
      at asyncGeneratorStep (lib/instanceloader.js:1305:103)
      at _next (lib/instanceloader.js:1307:194)

  3) ContractInstance
       #verify
         should throw error for failed signature verification:
     Error: Failed to find history.json in archive file.
      at Function.loadZipFileContents (/Users/jerome.simeon/git/accordproject/cicero/node_modules/@accordproject/ergo-compiler/lib/fileloader.js:47:19)
      at /Users/jerome.simeon/git/accordproject/cicero/packages/cicero-core/lib/instanceloader.js:1417:69
      at Generator.next (<anonymous>)
      at asyncGeneratorStep (lib/instanceloader.js:1305:103)
      at _next (lib/instanceloader.js:1307:194)

  4) ContractInstance
       #verifySignatures
         should verify all contract signatures:
     Error: Failed to find history.json in archive file.
      at Function.loadZipFileContents (/Users/jerome.simeon/git/accordproject/cicero/node_modules/@accordproject/ergo-compiler/lib/fileloader.js:47:19)
      at /Users/jerome.simeon/git/accordproject/cicero/packages/cicero-core/lib/instanceloader.js:1417:69
      at Generator.next (<anonymous>)
      at asyncGeneratorStep (lib/instanceloader.js:1305:103)
      at _next (lib/instanceloader.js:1307:194)

  5) ContractInstance
       #verifySignatures
         should throw error while verifying the contract signatures:
     Error: Failed to find history.json in archive file.
      at Function.loadZipFileContents (/Users/jerome.simeon/git/accordproject/cicero/node_modules/@accordproject/ergo-compiler/lib/fileloader.js:47:19)
      at /Users/jerome.simeon/git/accordproject/cicero/packages/cicero-core/lib/instanceloader.js:1417:69
      at Generator.next (<anonymous>)
      at asyncGeneratorStep (lib/instanceloader.js:1305:103)
      at _next (lib/instanceloader.js:1307:194)

  6) ContractInstance
       #signContract
         should verify all contract signatures:
     Error: Failed to find history.json in archive file.
      at Function.loadZipFileContents (/Users/jerome.simeon/git/accordproject/cicero/node_modules/@accordproject/ergo-compiler/lib/fileloader.js:47:19)
      at /Users/jerome.simeon/git/accordproject/cicero/packages/cicero-core/lib/instanceloader.js:1417:69
      at Generator.next (<anonymous>)
      at asyncGeneratorStep (lib/instanceloader.js:1305:103)
      at _next (lib/instanceloader.js:1307:194)

As discussed during the last Tech WG call, I'm looking into recreating this PR properly.

@jeromesimeon
Copy link
Member

@martinhalford @sanketshevkar A new PR has been open which replaces this PR at #713 . It would need review to make sure this properly reflect the original work.

@jeromesimeon
Copy link
Member

This work is now included in #713

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants