Coder Social home page Coder Social logo

codex-contracts-eth's People

Contributors

0x-r4bbit avatar auhau avatar benbierens avatar elcritch avatar emizzle avatar gmega avatar gravityblast avatar markspanbroek avatar veaceslavdoina avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

codex-contracts-eth's Issues

Deploy on L2 testnet

Deploy the smart contracts on an L2 testnet, to support the Codex testnet and allow for performance measurements.

Payout based on actual time filling the slot

Currently, if a node fills a slot and the request successfully finishes, it gets paid for the entire request duration regardless of when the node actually filled the slot.

In the context of Slot Reservations, we proposed that changing this behavior to payment based on the actual time of slot filling would create a small incentive to fill the slot as soon as possible.

Certora verification

During writing Application Properties for Certora integration, I am slowly discovering a lot of small things that should be fixed, but maybe not necessarily need a whole issue. I will dump them here and afterwards fix them.

alias bytes32 types

Create RequestId, SlotId, LockId, ProofId, EndId types to avoid confusion and enforce compiler restrictions.

deployment on status-im/infra-codex

Per our team call on Thursday, I started working out the details for deploying the contracts in this repo to our POA test network.

I'm familiar with all the concepts; but if it seems like there's something obvious I missed, please point it out because it probably isn't obvious to me. To date, I haven't spent much time with contracts, deployments, etc.

My first goal is to "get it right". After that I can tie into ansible/terraform automation, if that's the thing to do; or maybe it will be a one-off deployment for now, i.e. for the sake of the demo.

Outline of my approach:

  1. Setup a local POA network. I found a helpful tutorial and followed it, starting with the linked Create Validator Accounts section (I had already downloaded geth v1.10.17 on my mac and put it in PATH).

  2. Deploy dagger-contracts to my local POA network. Hardhat's docs were helpful for this step. It works!

  3. Run nim-dagger's testContracts against my local POA network. I don't think we want/need to run those tests against the infra-codex network, but getting them to pass locally with geth seems like a good way to gain confidence things will work as intended. I'm currently stuck on this step.

  4. Prep to deploy on the infra-codex POA network.


For step 2 I have this in a clone of status-im/dagger-contracts:

hardhat.config_poa.js

require("@nomiclabs/hardhat-waffle")
require("hardhat-deploy")
require("hardhat-deploy-ethers")

// keys for two funded accounts that are unlocked on both nodes in my local POA network
const LOCALPOA_PRIVATE_KEYS = [
    ...,
    ...
]

module.exports = {
  solidity: "0.8.4",
  networks: {
    "2337": {
      url: "http://127.0.0.1:8545",
      accounts: LOCALPOA_PRIVATE_KEYS
    }
  }
}

scripts/deploy.js

async function main() {
  const [deployer] = await ethers.getSigners();

  console.log("Deploying contracts with the account:", deployer.address);
  console.log("Account balance:", (await deployer.getBalance()).toString());

  const TestToken = await ethers.getContractFactory("TestToken");
  const testToken = await TestToken.deploy();
  console.log("TestToken address:", testToken.address);

  const token = testToken.address;
  const proofPeriod = 10;
  const proofTimeout = 5;
  const proofDowntime = 64;
  const collateralAmount = 100;
  const slashMisses = 3;
  const slashPercentage = 10;

  const Storage = await ethers.getContractFactory("Storage");
  const storage = await Storage.deploy(token, proofPeriod, proofTimeout,
    proofDowntime, collateralAmount, slashMisses, slashPercentage);
  console.log("Storage address:", storage.address);

  const file = "./deployment-localhost.json";
  const fs = require("fs/promises");
  let deployment = JSON.parse((await fs.readFile(file)).toString());
  deployment.name = "localpoa";
  deployment.chainId = "2337";
  deployment.contracts.TestToken.address = testToken.address;
  deployment.contracts.Storage.address = storage.address;
  await fs.writeFile(file, JSON.stringify(deployment, null, 2));
}

main()
  .then(() => process.exit(0))
  .catch((error) => {
    console.error(error);
    process.exit(1);
  });

First I run npm start so that deployment-localhost.json gets written to disk. After stopping the Hardhat process and firing up my geth nodes, I run:

$ ./node_modules/.bin/hardhat run scripts/deploy.js --config ./hardhat.config_poa.js --network 2337

For step 3, I copy the updated deployment-localhost.json to e.g. ~/repos/nim-dagger/vendor/dagger-contracts/

I have these changes in nim-dagger:

modified   tests/contracts/ethertest.nim
@@ -37,11 +37,12 @@ template ethersuite*(name, body) =
 
     setup:
       provider = JsonRpcProvider.new("ws://localhost:8545")
-      snapshot = await send(provider, "evm_snapshot")
+      # snapshot = await send(provider, "evm_snapshot")
       accounts = await provider.listAccounts()
 
     teardown:
-      discard await send(provider, "evm_revert", @[snapshot])
+      # discard await send(provider, "evm_revert", @[snapshot])
+      discard
 
     body

At the moment I'm stuck. For many (though not all) contract calls in testContracts I'm getting this error:

{"code": -32602, "message": "missing value for required argument 1"}

I did not encounter that error when running testContracts against a local Hardhat environment, and haven't seen it in CI, which also uses Hardhat.

I'm wondering if it's related to this:

ethereum/go-ethereum#2472
ethereum/go-ethereum#2473

My theory is that nim-ethers isn't passing the default block parameter for some methods, and while that's not a problem for Hardhat it is a problem for Go Ethereum.

I'll attempt to modify nim-ethers and check if my theory holds up.

Any thoughts on whether the error is being caused by something else?


For the deployment on infra-codex, I could simply run scripts/deploy.js (with appropriate changes) from within vendor/dagger-contracts of one of the codex nodes and make note of the contract addresses.

Would that be sufficient for now, or do we want to automate the process somehow? Please let me know your ideas and suggestions.

We also need to think about how to supply the addresses to the codex nodes. Would it be better to supply them in a CLI parameter/s when starting a node, or should they be baked into the builds?

cc: @markspanbroek @Menduist @emizzle

Certora integration

  • Write Application Properties document
  • Write Certora tests
  • Integrate Certora with tests into CI

Implement relational rules for mappings

This issue is about implementing the relational rules for various mappings that live in MarketPlace and Proofs.

Exact details of this issue will be worked out with the smart contracts team and certora.

Port existing fuzz tests to certora rules

Once #113 has landed we can start taking existing fuzz tests and move them over to certora rules.
We need to check how many tests there are. If it's too many we'll break this issue down into smaller chunks.

Deploy Marketplace smart contract on Testnet

This should be considered as a part of codex-storage/infra-codex/issues/186 and quick workaround for #112.

We would need to deploy an updated version of the Marketplace smart contract on existing Testnet before the EthCC, without changing anything around.

Plan is the following

  1. Use a separate branch devnet-testnet until we will finish #112
  2. Use an existing codexdisttestnetwork because it was used for previous deployment on Testnet
  3. Copy previous deployment (2024-04-03) /hardhat/deployments/codexdisttestnetwork folder content, excluding Marketplace.json
  4. Build a Docker image from the branch
  5. Deploy Marketplace smart contract using new Docker image
  6. Save and push Marketplace.json from the new deployment to the branch

Partial payouts for cancelled Requests

Currently, as described in #43 the money put into a Request by the Client is paid out to Hosts when the Request is canceled because of timeout. Instead, the money should be split between Hosts and Client based on the time for how long Hosts stored the content before the Request was pronounced to be timed out and the rest paid out to the Client.

Extend proof expectations once all slots are filled

The current logic for expecting proofs (in expectProofs) starts when a slot is filled and ends at the block.timestamp + duration. This ending will be different for each slot, as each slot will likely be filled at different times, and all slots except the last will not be expected to provide proofs up until the point that the contract is finished. The ending should likely instead be contractStartTime + duration. Currently, we don't track contractStartTime, so proof expectations will need to be extended (like lock expiry) once all slots are filled.

Canceled request's slots payouts money to Hosts

When a Request is canceled because of time out (after the Client calls the withdrawFunction, which returns him all the money for the original Request), then hosts that have already filled some slots can call freeSlot which pays them out the money for the slot. This makes the contract's money pool out of balance as the money is already returned to the Client in the withdrawFunction.

There is a plan in the future to take into consideration the time for how long was the content hosted and return only a partial reward to the client and a partial reward for the hosts, but until then this needs to be fixed.

The probably easiest solution is to payout filled slots to host for now.

Reward address

As Ethereum 2 validators have several addresses, maybe the Codex node could have a "reward address"?

[Certora feedback] `_getPointer` only needs one `% 256`

The _getPointer function can reduce the number of % 256's to reduce gas consumption:

Proofs.sol
- function _getPointer(SlotId id, Period period) internal view returns (uint8) {
-   uint256 blockNumber = block.number % 256;
-   // To ensure the pointer does not remain in downtime for many consecutive
-   // periods, for each period increase, move the pointer 67 blocks. We've
-   // chosen a prime number to ensure that we don't get cycles.
-   uint256 periodNumber = (Period.unwrap(period) * 67) % 256;
-   uint256 idOffset = uint256(SlotId.unwrap(id)) % 256;
-   uint256 pointer = (blockNumber + periodNumber + idOffset) % 256;
-   return uint8(pointer);
- }
+ function _getPointer(SlotId id, Period period) internal view returns (uint8) {
+   uint256 blockNumber = block.number;
+   // To ensure the pointer does not remain in downtime for many consecutive
+   // periods, for each period increase, move the pointer 67 blocks. We've
+   // chosen a prime number to ensure that we don't get cycles.
+   uint256 periodNumber = (Period.unwrap(period) * 67);
+   uint256 idOffset = uint256(SlotId.unwrap(id));
+   uint256 pointer = (blockNumber + periodNumber + idOffset) % 256;
+   return uint8(pointer);
+ }

Handling emergency scenarios of smart contracts

In case of an emergency, eg an exploit, admins should be able to freeze a contract, allowing only withdrawing of funds from the contract.

Freezing a contract will be the only functionality of an admin.

Once a contract is frozen, only withdrawal functionality would be enabled. This includes:

  • freeSlot
  • withdrawFunds

We should keep in mind that in normal operation, withdrawal txs (eg freeSlot, withdrawFunds) are only allowed when a request is cancelled or finished. Therefore, freezing a contract should disable these checks.

These additions should be done pre-audit.

Remove unneeded `_probabilities`?

When a slot is filled, the proof probability is stored in a private mapping _probabilities. However, this is likely not needed as the proof probability for a Request is already stored in Request.Ask.

This may require passing in the request Id.

Reward for validators that correctly mark proof as missing

Currently in the markProofAsMissing there is no reward for the node that calls this function correctly.

It is a question when and whom should get paid the reward as not every call to markProofAsMissing leads to slashing (from which the funds for reward could be deducted) and in the same time if only those calls that leads to slashing will yield the reward, then there is no incentive to really call this function for the other cases...

Repair reward percentage, number of slashing and linearity

Currently, the minimum required collateral is defined on the smart-contract level as an absolute value. Repair reward is currently not defined. And the slashing is logarithmic.

We have agreed to replace the minimumAmount with number of slashing. There needs to be a check for numberOfSlashing*slashingPercentage<=100, though. Also we have decided to move from logarithmic to linear slashing, which goes in hand with the previous change.

Period multiplicator as part of the Proof's configuration

https://github.com/codex-storage/codex-contracts-eth/blob/master/contracts/Proofs.sol#L48

The Period multiplicator (67) in getPointer() function should be configurable as it is coupled with the downtime parameter.

We should also better understand what configuration values we will use in real deployment, because then maybe we would not even need the multiplication? I would assume that the Period should be quite long, but Mark pointed out that it should not be longer than the 256 blocks window.

Maximum Request's duration

When we want to migrate our smart contracts, we need the ability to deprecate the old contract but it needs to be alive until the last Request finishes/fails/cancelles. We should hence prevent somebody from creating very long contracts which would hinder this process and hence have an upper limit for the Request's duration.

What would be a reasonable limit? 6 months? 3 months?

Proportional payout for repaired slots

Currently, when a slot is freed and another host repairs it, they receive the repair reward. Upon successfully completing the slot, they will receive the reward for the entire storage contract duration, not just a portion based on how long they filled the slot (e.g., from the time of slot repair).

Is this desirable? Could it pose a problem?

Add Marketplace test suite with real proof verifier

A marketplace test suite should be created that uses the real proof verifier contract, instead of the test contract. This will serve two purposes:

  1. Test the real verifier contract
  2. Allow more realistic gas reports to be generated with hardhat-gas-reporter when running the tests with REPORT_GAS

Simplify `Request`'s client address tracking

Currently the Request object has client property which is now enforced that it must be the msg.sender (here and is not allowed to be specified to some different address, hence it would be simpler to drop the Request.client property and instead use the msg.sender which could be stored in the RequestContext object.

Fixing `npm install` failure when using python 3.12+

I got a new machine recently and have been setting up my dev environment again. When I run npm install on the codex master branch with node 18.15.0 I'm getting build errors. I've added the errors below for others to find.

It appears to be due to my Python version which is Python 3.12 which doesn't bundle distutils by default anymore.

I was able to resolve the issue by running brew install python-setuptools. You can see stackoverflow for more info.

Unfortunately I'm not aware of how to resolve this for all users. Possibly updating some node deps would use updated python dependencies (gotta love rabbit trails ;)). Otherwise it might make sense to add a note in Codex or here.

npm ERR! code 1
npm ERR! path /Users/elcritch/projs/status/nim-codex/vendor/codex-contracts-eth/node_modules/ganache-core/node_modules/utf-8-validate
npm ERR! command failed
npm ERR! command sh -c node-gyp-build
npm ERR! gyp info it worked if it ends with ok
npm ERR! gyp info using [email protected]
npm ERR! gyp info using [email protected] | darwin | arm64
npm ERR! gyp info find Python using Python version 3.12.2 found at "/opt/homebrew/opt/[email protected]/bin/python3.12"
npm ERR! gyp info spawn /opt/homebrew/opt/[email protected]/bin/python3.12
npm ERR! gyp info spawn args [
npm ERR! gyp info spawn args   '/Users/elcritch/.asdf/installs/nodejs/18.15.0/lib/node_modules/npm/node_modules/node-gyp/gyp/gyp_main.py',
npm ERR! gyp info spawn args   'binding.gyp',
npm ERR! gyp info spawn args   '-f',
npm ERR! gyp info spawn args   'make',
npm ERR! gyp info spawn args   '-I',
npm ERR! gyp info spawn args   '/Users/elcritch/projs/status/nim-codex/vendor/codex-contracts-eth/node_modules/ganache-core/node_modules/utf-8-validate/build/config.gypi',
npm ERR! gyp info spawn args   '-I',
npm ERR! gyp info spawn args   '/Users/elcritch/.asdf/installs/nodejs/18.15.0/lib/node_modules/npm/node_modules/node-gyp/addon.gypi',
npm ERR! gyp info spawn args   '-I',
npm ERR! gyp info spawn args   '/Users/elcritch/Library/Caches/node-gyp/18.15.0/include/node/common.gypi',
npm ERR! gyp info spawn args   '-Dlibrary=shared_library',
npm ERR! gyp info spawn args   '-Dvisibility=default',
npm ERR! gyp info spawn args   '-Dnode_root_dir=/Users/elcritch/Library/Caches/node-gyp/18.15.0',
npm ERR! gyp info spawn args   '-Dnode_gyp_dir=/Users/elcritch/.asdf/installs/nodejs/18.15.0/lib/node_modules/npm/node_modules/node-gyp',
npm ERR! gyp info spawn args   '-Dnode_lib_file=/Users/elcritch/Library/Caches/node-gyp/18.15.0/<(target_arch)/node.lib',
npm ERR! gyp info spawn args   '-Dmodule_root_dir=/Users/elcritch/projs/status/nim-codex/vendor/codex-contracts-eth/node_modules/ganache-core/node_modules/utf-8-validate',
npm ERR! gyp info spawn args   '-Dnode_engine=v8',
npm ERR! gyp info spawn args   '--depth=.',
npm ERR! gyp info spawn args   '--no-parallel',
npm ERR! gyp info spawn args   '--generator-output',
npm ERR! gyp info spawn args   'build',
npm ERR! gyp info spawn args   '-Goutput_dir=.'
npm ERR! gyp info spawn args ]
npm ERR! Traceback (most recent call last):
npm ERR!   File "/Users/elcritch/.asdf/installs/nodejs/18.15.0/lib/node_modules/npm/node_modules/node-gyp/gyp/gyp_main.py", line 42, in <module>
npm ERR!     import gyp  # noqa: E402
npm ERR!     ^^^^^^^^^^
npm ERR!   File "/Users/elcritch/.asdf/installs/nodejs/18.15.0/lib/node_modules/npm/node_modules/node-gyp/gyp/pylib/gyp/__init__.py", line 9, in <module>
npm ERR!     import gyp.input
npm ERR!   File "/Users/elcritch/.asdf/installs/nodejs/18.15.0/lib/node_modules/npm/node_modules/node-gyp/gyp/pylib/gyp/input.py", line 19, in <module>
npm ERR!     from distutils.version import StrictVersion
npm ERR! ModuleNotFoundError: No module named 'distutils'
npm ERR! gyp ERR! configure error 
npm ERR! gyp ERR! stack Error: `gyp` failed with exit code: 1
npm ERR! gyp ERR! stack     at ChildProcess.onCpExit (/Users/elcritch/.asdf/installs/nodejs/18.15.0/lib/node_modules/npm/node_modules/node-gyp/lib/configure.js:325:16)
npm ERR! gyp ERR! stack     at ChildProcess.emit (node:events:513:28)
npm ERR! gyp ERR! stack     at ChildProcess._handle.onexit (node:internal/child_process:291:12)
npm ERR! gyp ERR! System Darwin 23.3.0
npm ERR! gyp ERR! command "/Users/elcritch/.asdf/installs/nodejs/18.15.0/bin/node" "/Users/elcritch/.asdf/installs/nodejs/18.15.0/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
npm ERR! gyp ERR! cwd /Users/elcritch/projs/status/nim-codex/vendor/codex-contracts-eth/node_modules/ganache-core/node_modules/utf-8-validate
npm ERR! gyp ERR! node -v v18.15.0
npm ERR! gyp ERR! node-gyp -v v9.3.1
npm ERR! gyp ERR! not ok

Environment details:

OS: macOS 14.3.1 m3
python: 3.12
node: 18.15.0

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.