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

[SC] Contract libraries (proposal) #506

Merged
merged 14 commits into from
Apr 13, 2021

Conversation

rowandh
Copy link
Contributor

@rowandh rowandh commented Apr 8, 2021

There's an architectural flaw in the original smart contracts design. Functionality such as hashing, serialization and now ecrecover are exposed via methods on the base SmartContract class.

This is not easily extensible as the SmartContracts class must be updated every time new functionality is added. Additionally it pollutes the SmartContracts class with unnecessary functionality.

This PR adds the beginning of a Smart Contract Library Stratis.SCL. The library is whitelisted for use in contracts. To add additional functionality, only the library module needs to be updated.

I've added EcRecover to demonstrate the proposed idea.

@rowandh
Copy link
Contributor Author

rowandh commented Apr 8, 2021

@mrtpain would be great to hear your thoughts on this!

@rowandh
Copy link
Contributor Author

rowandh commented Apr 8, 2021

If this is accepted then I will update #414 and stratisproject/Stratis.SmartContracts#14 and revert stratisproject/Stratis.SmartContracts#13

@rowandh rowandh force-pushed the contract-libraries branch from ee1a467 to 09c54d2 Compare April 8, 2021 13:18
@YakupIpek
Copy link
Member

It is possible to implement these features inside main library without modifying SmartContract class like you do with static classes. Also sometimes modification is unavoidable like we supported uint128/uint256 types and we needed to modify persistent state and other classes.

In some cases we may need to update both library if we add another library. IMO it would be better to go with single library dependency because i don't see clear benefits.

I am open to hear other ideas .

@rowandh
Copy link
Contributor Author

rowandh commented Apr 8, 2021

Thanks @YakupIpek. Definitely some modification is unavoidable. The goal of this is mainly so we can add additional "library-style" functionality more easily in the future. Eg. if we need more support for manipulating byte arrays or converting an enum to a byte 😃

Are you just suggesting that this functionality be moved to Stratis.SmartContracts? The original goal of the Stratis.SmartContracts package was just to be a very basic contract interface that rarely needed updating. It contains almost no logic.

My preference is therefore to separate concerns and create a new namespace for this and add it to the whitelist.

@mrtpain
Copy link

mrtpain commented Apr 9, 2021

I think this is a good idea, it'll help keep the SmartContract class clean and let developers choose which added functionality they want to bring into their contracts or keep out entirely.

@YakupIpek
Copy link
Member

The goal of this is mainly so we can add additional "library-style" functionality more easily in the future.
How this can make it easier to add new functionality compared to add it to Stratis.SmartContracts ?

I only see separation concerns on this.

Adding another library bring more work. If i update Stratis.SCL library then i have to update Stratis.SmartContracts references again and create pr for it. Already at the moment we have to update Fullnode, SCT tool, Local-Chain project, visual studio template project, sometimes wallet UI..etc and this bring one more project to update process so for this reason i am favor of single library IMHO. We can add another folder for the libraries as namespace in Stratis.SmartContracts library.

I would like to know @quantumagi idea on this.

This is just my suggestion and it is still up to you @rowandh

@rowandh
Copy link
Contributor Author

rowandh commented Apr 9, 2021

One of the goals with this is that we don't have to update Stratis.SmartContracts every time we want to expose new functionality to a contract.

For example the EcRecover functionality can be exposed through this library, meaning we don't need a SmartContract.EcRecover method.

@@ -17,6 +17,7 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Stratis.SCL\Stratis.SCL.csproj" />
Copy link
Contributor

@quantumagi quantumagi Apr 9, 2021

Choose a reason for hiding this comment

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

This reference should be removed as Stratis.SCL should only ever be referenced by SCs (see #506 (comment)). Here it should be dynamically loaded, perhaps into a custom AssemblyLoadContext. Also, it would be very robust if SCs are always provided with the version of the library that they were originally validated with (if possible).

Stratis.SCL (Package)
  <- Stratis.SmartContracts.CLR (Package)
     <- Stratis.Bitcoin.Features.Interop (Package)
     <- Stratis.Bitcoin.Features.SmartContracts (Package)
        <- Stratis.Benchmark (Package)
        <- Stratis.Bitcoin.Networks (Package)
        <- Stratis.Features.Collateral (Package)
        <- Stratis.Features.FederatedPeg (Package)
        <- Stratis.SmartContracts.Networks (Package)
        <- Stratis.StraxD

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unused reference, I have removed it

Copy link
Contributor

@quantumagi quantumagi Apr 9, 2021

Choose a reason for hiding this comment

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

The reference still exists implicitly. See #506 (comment).

@quantumagi
Copy link
Contributor

quantumagi commented Apr 9, 2021

The main benefit of this library is that, if done in a certain way, it could avoid scenarios such as: Package A uses B which is not a package, and Stratis.SCL is used by B, then we may have to bump the version of A if Stratis.SCL changes.

The guaranteed way to accomplish this is to only ever reference the Stratis.SCL library from smart contracts.

@stratisproject stratisproject deleted a comment from rowandh Apr 9, 2021
@@ -23,7 +23,8 @@ public static class FormatPolicy
Core,
typeof(SmartContract).Assembly,
typeof(Enumerable).Assembly,
typeof(IStandardToken).Assembly
typeof(IStandardToken).Assembly,
typeof(SCL.Base.Operations).Assembly
Copy link
Contributor

@quantumagi quantumagi Apr 9, 2021

Choose a reason for hiding this comment

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

Should SCL.Crypto.ECRecover be added here? Ah wait it's the same assembly as Base right? It probably won't hurt adding it anyway if the list is made distinct as well (if required). Actually the SCL typeof references here may be problematic.

@@ -23,7 +23,8 @@ public static class ReferencedAssemblyResolver
Core,
typeof(SmartContract).Assembly,
typeof(Enumerable).Assembly,
typeof(IStandardToken).Assembly
typeof(IStandardToken).Assembly,
typeof(SCL.Base.Operations).Assembly
Copy link
Contributor

Choose a reason for hiding this comment

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

See previous comment.

@quantumagi quantumagi self-requested a review April 9, 2021 04:05
quantumagi
quantumagi previously approved these changes Apr 9, 2021
Copy link
Contributor

@quantumagi quantumagi left a comment

Choose a reason for hiding this comment

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

LGTM. Just a few minor comments.

@quantumagi quantumagi self-requested a review April 9, 2021 04:25
@quantumagi quantumagi dismissed their stale review April 9, 2021 04:25

Reference still exists

@quantumagi
Copy link
Contributor

quantumagi commented Apr 9, 2021

image

@@ -13,4 +13,8 @@
<PackageReference Include="Stratis.SmartContracts.Standards" Version="2.0.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Stratis.SCL\Stratis.SCL.csproj" />
Copy link
Contributor

Choose a reason for hiding this comment

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

Should not have this reference.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The validator needs to access types from it.

Copy link
Contributor

@quantumagi quantumagi Apr 9, 2021

Choose a reason for hiding this comment

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

Yes, I noticed that. Could it access types by name (instead of typeof) or is there some other workaround? Otherwise we will have an avalanche of version updates each time Stratis.SCL is changed as shown here: #506 (comment). That would defeat the purpose of this library. I think that is what @YakupIpek's concern is. We need to handle this library in a special way to see any undeniable benefits,

@quantumagi
Copy link
Contributor

quantumagi commented Apr 9, 2021

Please ensure that all packages that have been changed or that have project reference to other packages that have updated versions have their versions bumped iff their versions are still the same as the latest package release. The new EnsureVersionsBumpedWhenChangingPublishedPackages test case (currently passing) should check this but it may still be worth double-checking.

@quantumagi quantumagi self-requested a review April 12, 2021 08:22
@rowandh rowandh changed the base branch from master to infracontracts April 12, 2021 11:15
@rowandh
Copy link
Contributor Author

rowandh commented Apr 12, 2021

To avoid the various versioning issues noted by @quantumagi, I've moved everything into the Stratis.SmartContracts.CLR project. This also guarantees that SCL will always be loaded in the assembly load context.

I have also moved validation policy definitions out of Stratis.SmartContracts.CLR.Validation and into Stratis.SmartContracts.CLR which is where they should have been, and bumped both packages a full version as these are significant API changes.

Lastly I will note that this does not solve the 'library upgradeability problem', which is also present with #414. This just makes it possible to add new library functionality without lumping it on the base SmartContract class.

@quantumagi quantumagi self-requested a review April 12, 2021 12:14
Copy link
Contributor

@quantumagi quantumagi left a comment

Choose a reason for hiding this comment

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

This PR shows 58 files changed. That does not seem right.

Can you resubmit your changes on top of the latest "infracontracts" branch or after first merging with it?

@rowandh rowandh force-pushed the contract-libraries branch from aee15c5 to c0e45cf Compare April 12, 2021 12:18
@rowandh rowandh changed the base branch from infracontracts to master April 12, 2021 12:20
@rowandh rowandh changed the base branch from master to infracontracts April 12, 2021 12:20
@rowandh rowandh force-pushed the contract-libraries branch from c0e45cf to b4393f9 Compare April 12, 2021 12:29
@rowandh
Copy link
Contributor Author

rowandh commented Apr 12, 2021

Retargeted to infracontracts

@rowandh rowandh merged commit ff8ae49 into stratisproject:infracontracts Apr 13, 2021
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.

4 participants