diff --git a/scripts/README.md b/scripts/README.md index 3dad84ec..3b847f04 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -9,7 +9,7 @@ Also, check the [config file](./sdk/src/config/index.js), to ensure that you are The [examples](./examples/) folder contains scripts that demonstrate how to properly send transacrions to DDC Bucket contracts using the [@polkadot/api](https://polkadot.js.org/docs/api/) library. These simple scenarious should help other team members to clarify the business logic flow, and quickly detect issues related to various business constraints and infrastructue constraints (i.e. gas price, attached tokens, method signature, etc.). Scripts should be updated while the contract is evolving to reflect the actual logic. -#### DDC Bucket scenario +#### DDC Contract demo scenario Run the script as: ``` @@ -18,7 +18,7 @@ ENV=devnet yarn run demo-ddc-bucket The execution progress will be displayed in the console along with links to explorer that will help you to investigate the details of each transaction -#### Display DDC Bucket state +#### Display DDC Contract state Run the script as: ``` @@ -26,14 +26,14 @@ ENV=devnet yarn run print-ddc-bucket ``` -## Deployment using script +## Deployment DDC Contract using script The [deployment](./deployment/) folder contains scripts that allow you to deploy artifacts to a local or remote network. Typically, these scripts are used for EDC, Devnet and QAnet environments during development. For Testnet and Mainnet environments, it is recomended to upload the contract code manually and assert all the required keys, attached tokens, gas limits, etc. during deployment and contract instantianating. -#### DDC Bucket deployment +#### DDC Contract deployment Run the script as: ``` @@ -42,6 +42,15 @@ yarn run deploy-ddc-bucket Optionally, the command can accept a code hash as the first parameter, and constructor name as the second parameter. In order to use these options, your contract artifacts [must be registered](./sdk/src/deploymentRegistry.js) to retrieve the required metadata from artifacts. +#### DDC Contract setup + +Run the script as: +``` +DDC_CONTRACT='6PZ6ndAdULxsnzLjyNmPuWonS9jSxTRgXN1EtVMnbi41VZZg' SUPERADMIN='//Alice' ENV='devnet' yarn run setup-ddc-bucket +``` +Use the DDC Contract address in place of the `DDC_CONTRACT` variable that you want to configure, the admin of DDC Contract from the deployment step in place of `SUPERADMIN` variable, and DDC environment that you are targeting in place of the `ENV` variable + + #### Build and Deploy all contracts To run both building and deployment for all contracts, you can use the [build-and-deploy.sh](./../build-and-deploy.sh) script. diff --git a/scripts/ddc-setup/ddcBucketSetup.js b/scripts/ddc-setup/ddcBucketSetup.js index 4d6db103..773079e6 100644 --- a/scripts/ddc-setup/ddcBucketSetup.js +++ b/scripts/ddc-setup/ddcBucketSetup.js @@ -7,22 +7,20 @@ const { CERE, MGAS, ddcBucket, - randomAccount, deploymentRegistry, config } = require("../sdk/src"); const ddcConfig = require('./ddcConfig.js'); const log = console.log; -const DDC_BUCKET_CONTRACT_NAME = config.DDC_BUCKET_CONTRACT_NAME; const ENV = process.env.ENV; +const ddcEnvConfig = ddcConfig[ENV]; const SUPERADMIN_MNEMONIC = process.env.SUPERADMIN; +const DDC_CONTRACT_ADDRESS = process.env.DDC_CONTRACT; - -const ddcEnvConfig = ddcConfig[ENV]; if (!ddcEnvConfig) { - console.error("Please provide ENV as one of ", Object.keys(ddcConfig)); - process.exit(-1); + console.error("Please provide ENV as one of ", Object.keys(ddcConfig)); + process.exit(-1); } console.log(ddcEnvConfig); @@ -31,41 +29,42 @@ if (!SUPERADMIN_MNEMONIC) { process.exit(-1); } -deploymentRegistry.initContract( - DDC_BUCKET_CONTRACT_NAME, - ENV, - ddcEnvConfig.contract_address -); +if (!DDC_CONTRACT_ADDRESS) { + console.error("Please provide DDC_CONTRACT address"); + process.exit(-1); +} +deploymentRegistry.initContract(config.DDC_BUCKET_CONTRACT_NAME, ENV, DDC_CONTRACT_ADDRESS); async function main() { - const {api, chainName, getExplorerUrl} = await connect(ddcEnvConfig.ws_provider); + const {api, chainName, getExplorerUrl} = await connect(ddcEnvConfig.blockchainUrl); log("Connected to blockchain:", chainName); const sadmin = accountFromUri(SUPERADMIN_MNEMONIC); console.log(`Superadmin: ${sadmin.address}`); - const bucketContract = getContract(DDC_BUCKET_CONTRACT_NAME, ENV, api); - log("Using bucket contract", DDC_BUCKET_CONTRACT_NAME, "at", bucketContract.address.toString()); + const bucketContract = getContract(config.DDC_BUCKET_CONTRACT_NAME, ENV, api); + log("Using bucket contract", config.DDC_BUCKET_CONTRACT_NAME, "at", bucketContract.address.toString()); const txOptions = { storageDepositLimit: null, gasLimit: 100_000_000_000n, }; + console.log( "\n", `Setup Started`, "\n"); + { - log("1. accountSetUsdPerCere"); + log(`Setting USD per CERE rate ...`); const tx = bucketContract.tx.accountSetUsdPerCere( txOptions, 1000n * CERE ); - const result = await sendTx(sadmin, tx); log(getExplorerUrl(result), "\n"); } { - log("2. grantTrustedManagerPermission"); + log(`Granting trusted managers permissions ...`); const tx = bucketContract.tx.grantTrustedManagerPermission( txOptions, sadmin.address @@ -74,70 +73,100 @@ async function main() { log(getExplorerUrl(result), "\n"); } - const cdnNodesKeys = [] - { - console.log("3. cdnNodeCreate"); - for (let i = 0; i < ddcEnvConfig.cdn_node_params.length; i++) { - const cdnNodeKey = ddcEnvConfig.cdn_node_params[i].publicKey; - cdnNodesKeys.push(cdnNodeKey); - - const tx = bucketContract.tx.cdnNodeCreate( - txOptions, - cdnNodeKey, - JSON.stringify(ddcEnvConfig.cdn_node_params[i]) - ); - - const result = await sendTx(sadmin, tx); - log(getExplorerUrl(result), "\n"); - } - } - - const storageNodesKeys = [] - { - console.log("4. nodeCreate"); - for (let i = 0; i < ddcEnvConfig.storage_node_params.length; i++) { - const param = JSON.stringify(ddcEnvConfig.storage_node_params[i]); - const user = randomAccount(); - - fs.appendFileSync('secrets.txt', `${user.address}: ${user.mnemonic} -- ${ENV} storage ${i}\n`); - console.log(` node ${i}: address ${user.address}, param ${param}`); - - const storageNodeKey = user.address; - storageNodesKeys.push(storageNodeKey); + for (let i = 0; i < ddcEnvConfig.clusters.length; i++) { + const cluster = ddcEnvConfig.clusters[i]; + const clusterParams = JSON.stringify(cluster.params); + const resourcePerVNode = 100000n; - const tx = bucketContract.tx.nodeCreate( + console.log(`Creating Cluster ${i} ...`); + const clusterCreateTx = bucketContract.tx.clusterCreate( + txOptions, + clusterParams, + resourcePerVNode + ); + const result = await sendTx(sadmin, clusterCreateTx); + log(getExplorerUrl(result), "\n"); + let { clusterId } = ddcBucket.findClusterCreatedEvent(result.contractEvents || []); + console.log(`Cluster ${clusterId} created`); + + for (let j = 0; j < cluster.storageNodes.length; j++) { + const storageNode = cluster.storageNodes[j]; + const storageNodeKey = storageNode.pubKey; + const storageNodeParams = JSON.stringify(storageNode.params); + const vNodes = storageNode.vNodes; + const storageNodeCapacity = 100000n; + const rentVNodePerMonth = 1n * CERE; + + console.log(`Creating Storage node ${storageNodeKey} ...`); + const nodeCreateTx = bucketContract.tx.nodeCreate( txOptions, storageNodeKey, - param, - 100000n, - 1n * CERE + storageNodeParams, + storageNodeCapacity, + rentVNodePerMonth, ); + const result1 = await sendTx(sadmin, nodeCreateTx); + log(getExplorerUrl(result1), "\n"); - const result = await sendTx(sadmin, tx); - log(getExplorerUrl(result), "\n"); + console.log(`Adding Storage node ${storageNodeKey} to Cluster ${clusterId} ...`); + const clusterAddNodeTx = bucketContract.tx.clusterAddNode( + txOptions, + clusterId, + storageNodeKey, + vNodes + ) + const result2 = await sendTx(sadmin, clusterAddNodeTx); + log(getExplorerUrl(result2), "\n"); + + const storageNodeStatus = 'ACTIVE'; + console.log(`Setting '${storageNodeStatus}' status ${storageNodeKey} in Cluster ${clusterId} ...`); + const clusterSetNodeStatusTx = bucketContract.tx.clusterSetNodeStatus( + txOptions, + clusterId, + storageNodeKey, + storageNodeStatus, + ) + const result3 = await sendTx(sadmin, clusterSetNodeStatusTx); + log(getExplorerUrl(result3), "\n"); } - } - - const clustersIds = []; - { - for (let key in ddcEnvConfig.cluster) { - console.log("5. clusterCreate "); - const tx1 = bucketContract.tx.clusterCreate( - txOptions, - JSON.stringify(ddcEnvConfig.cluster[key].param), - 100000n - ); + for (let j = 0; j < cluster.cdnNodes.length; j++) { + const cdnNode = cluster.cdnNodes[j]; + const cdnNodeKey = cdnNode.pubKey; + const cdnNodeParams = JSON.stringify(cdnNode.params); - const result1 = await sendTx(sadmin, tx1); + console.log(`Creating CDN node ${cdnNodeKey} ...`); + const cdnNodeCreateTx = bucketContract.tx.cdnNodeCreate( + txOptions, + cdnNodeKey, + cdnNodeParams + ); + const result1 = await sendTx(sadmin, cdnNodeCreateTx); log(getExplorerUrl(result1), "\n"); - let { clusterId } = ddcBucket.findClusterCreatedEvent(result1.contractEvents || []); - clustersIds.push(clusterId); + + console.log(`Adding CDN node ${cdnNodeKey} to Cluster ${clusterId} ...`); + const clusterAddCdnNodeTx = bucketContract.tx.clusterAddCdnNode( + txOptions, + clusterId, + cdnNodeKey, + ) + const result2 = await sendTx(sadmin, clusterAddCdnNodeTx); + log(getExplorerUrl(result2), "\n"); + + const cdnNodeStatus = 'ACTIVE'; + console.log(`Setting '${cdnNodeStatus}' status ${cdnNodeKey} in Cluster ${clusterId} ...`); + const clusterSetCdnNodeStatusTx = bucketContract.tx.clusterSetCdnNodeStatus( + txOptions, + clusterId, + cdnNodeKey, + cdnNodeStatus, + ) + const result3 = await sendTx(sadmin, clusterSetCdnNodeStatusTx); + log(getExplorerUrl(result3), "\n"); } } - // TODO: Add Storage nodes and CDN nodes to clusters - + console.log( "\n", `Setup Finished`, "\n"); process.exit(0); } diff --git a/scripts/ddc-setup/ddcConfig.js b/scripts/ddc-setup/ddcConfig.js index 0517238f..387eb7af 100644 --- a/scripts/ddc-setup/ddcConfig.js +++ b/scripts/ddc-setup/ddcConfig.js @@ -1,139 +1,156 @@ const GEN = 0x10000000000000000n; // UINT64_MAX module.exports = { + devnet: { - ws_provider: "wss://archive.devnet.cere.network/ws", - contract_address: "6SfBsKbfPUTN35GCcqAHSMY4MemedK2A73VeJ34Z2FV6PB4r", - cluster: { - 1n: { - param: { replicationFactor: 3 }, - vnodes: [ [0n], [GEN / 4n], [GEN * 2n / 4n], [GEN * 3n / 4n] ], - storage_nodes: [1n, 2n, 3n, 4n], - }, - }, - storage_node_params: [ - { url: `https://node-0.v2.storage.devnet.cere.network` }, - { url: `https://node-1.v2.storage.devnet.cere.network` }, - { url: `https://node-2.v2.storage.devnet.cere.network` }, - { url: `https://node-3.v2.storage.devnet.cere.network` }, - ], - cdn_cluster: { - 0n: { - cdn_nodes: [1n, 2n, 3n, 4n], - }, - }, - cdn_node_params: [ + blockchainUrl: "wss://archive.devnet.cere.network/ws", + clusters: [ { - url: `https://node-0.v2.cdn.devnet.cere.network`, - publicKey: "0x1c4a1b081af8dd09096ebb6e7ad61dd549ac2931cdb2b1216589094ad71ca90b", + params: { replicationFactor: 3 }, + storageNodes: [ + { + pubKey: "0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d", + vNodes: [0n], + params: { url: `https://node-0.v2.storage.devnet.cere.network` }, + }, + { + pubKey: "0x8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48", + vNodes: [GEN / 4n], + params: { url: `https://node-1.v2.storage.devnet.cere.network` }, + }, + { + pubKey: "0x90b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22", + vNodes: [GEN * 2n / 4n], + params: { url: `https://node-2.v2.storage.devnet.cere.network` }, + }, + { + pubKey: "0x306721211d5404bd9da88e0204360a1a9ab8b87c66c1bc2fcdd37f3c2222cc20", + vNodes: [GEN * 3n / 4n], + params: { url: `https://node-3.v2.storage.devnet.cere.network` }, + } + ], + cdnNodes: [ + { + pubKey: "0xfe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e", + params: { url: `https://node-0.v2.cdn.devnet.cere.network` }, + }, + { + pubKey: "0x1e07379407fecc4b89eb7dbd287c2c781cfb1907a96947a3eb18e4f8e7198625", + params: { url: `https://node-1.v2.cdn.devnet.cere.network` }, + }, + { + pubKey: "0xe860f1b1c7227f7c22602f53f15af80747814dffd839719731ee3bba6edc126c", + params: { url: `https://node-2.v2.cdn.devnet.cere.network` }, + }, + { + pubKey: "0x8ac59e11963af19174d0b94d5d78041c233f55d2e19324665bafdfb62925af2d", + params: { url: `https://node-3.v2.cdn.devnet.cere.network` }, + } + ] }, - { - url: `https://node-1.v2.cdn.devnet.cere.network`, - publicKey: "0x3ec2ec407053acdfe8137d7105e90294f2e0e5f5fe5420fd3172142671dbc25f", - }, - { - url: `https://node-2.v2.cdn.devnet.cere.network`, - publicKey: "0x20e448c403d3f009ec309394d3aab828c3dbf0d2cc8047f01dded984ec992b41", - }, - { - url: `https://node-3.v2.cdn.devnet.cere.network`, - publicKey: "0xd2f93cea79e37cfc9e5f78cd3e51b989afb1e257adcbbae00b8cd081539e9f13", - } ], }, testnet: { - ws_provider: "wss://archive.devnet.cere.network/ws", - // contract_address: "6R2PF5gzKYbNkNLymTr8YNeQgWqNkE6azspwaMLZF2UHc1sg", - contract_address: "6UWDf6rEgSDFRr1h2pMdCbifowTDK64yRkDR6nc3C1cjL82e", - cluster: { - 1n: { - storage_nodes: [1n, 2n, 3n], - vnodes: [ [0n], [GEN / 3n], [GEN * 2n / 3n] ], - param: { replicationFactor: 3 }, - }, - 2n: { - storage_nodes: [4n, 5n, 6n], - vnodes: [ [0n], [GEN / 3n], [GEN * 2n / 3n] ], - param: { replicationFactor: 3 }, - }, - }, - storage_node_params: [ - { url: `https://node-0.v2.us.storage.testnet.cere.network` }, - { url: `https://node-1.v2.us.storage.testnet.cere.network` }, - { url: `https://node-2.v2.us.storage.testnet.cere.network` }, - { url: `https://node-0.v2.eu.storage.testnet.cere.network` }, - { url: `https://node-1.v2.eu.storage.testnet.cere.network` }, - { url: `https://node-2.v2.eu.storage.testnet.cere.network` }, - ], - cdn_cluster: { - 0n: { - cdn_nodes: [1n, 2n], - }, - 1n: { - cdn_nodes: [3n, 4n], - }, - 2n: { - cdn_nodes: [5n, 6n], - }, - }, - cdn_node_params: [ - { - url: `https://node-0.v2.us.cdn.testnet.cere.network`, - publicKey: "0x089522cee0567ff8e072c9efbd5cb4e05fe47cdab8340816be9d6f60538e8645", - }, - { - url: `https://node-1.v2.us.cdn.testnet.cere.network`, - publicKey: "0x7693cbc6a6f3fff67d4eb29bb07bc018e1eee43618d03e6c0a91b0b3e79f272d", - }, - { - url: `https://node-0.v2.eu.cdn.testnet.cere.network`, - publicKey: "0xdce47cdd1da69c19261b72e3c58e93d78e49d1ac20a566b535cb9bcf9d197958", - }, + blockchainUrl: "wss://archive.testnet.cere.network/ws", + clusters: [ { - url: `https://node-1.v2.eu.cdn.testnet.cere.network`, - publicKey: "0xb8541743735ffba6877b214925a9ec07c813369bb36b49ee5849b1fea0f9dd55", + params: { replicationFactor: 3 }, + storageNodes: [ + { + pubKey: "0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d", + vNodes: [0n], + params: { url: `https://node-0.v2.us.storage.testnet.cere.network` }, + }, + { + pubKey: "0x8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48", + vNodes: [GEN / 3n], + params: { url: `https://node-1.v2.us.storage.testnet.cere.network` }, + }, + { + pubKey: "0x90b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22", + vNodes: [GEN * 2n / 3n], + params: { url: `https://node-2.v2.us.storage.testnet.cere.network` }, + } + ], + cdnNodes: [ + { + pubKey: "0xfe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e", + params: { url: `https://node-0.v2.us.cdn.testnet.cere.network` }, + }, + { + pubKey: "0x1e07379407fecc4b89eb7dbd287c2c781cfb1907a96947a3eb18e4f8e7198625", + params: { url: `https://node-1.v2.us.cdn.testnet.cere.network` }, + } + ] }, { - url: `https://node-0.unmarshal.v2.us.cdn.testnet.cere.network`, - publicKey: "0x685168b78deb42eebf01e38d18c9302f032c50e544d56c1c4f86b13b0a2ad40a", - }, - { - url: `https://node-1.unmarshal.v2.us.cdn.testnet.cere.network`, - publicKey: "0xeeb3683dcd43e9c7f8759b1dce2440d767ae1c51dec05b584d785e24997cb947", - }, + params: { replicationFactor: 3 }, + storageNodes: [ + { + pubKey: "0x306721211d5404bd9da88e0204360a1a9ab8b87c66c1bc2fcdd37f3c2222cc20", + vNodes: [0n], + params: { url: `https://node-0.v2.eu.storage.testnet.cere.network` }, + }, + { + pubKey: "0xe659a7a1628cdd93febc04a4e0646ea20e9f5f0ce097d9a05290d4a9e054df4e", + vNodes: [GEN / 3n], + params: { url: `https://node-1.v2.eu.storage.testnet.cere.network` }, + }, + { + pubKey: "0x1cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c", + vNodes: [GEN * 2n / 3n], + params: { url: `https://node-2.v2.eu.storage.testnet.cere.network` }, + } + ], + cdnNodes: [ + { + pubKey: "0xe860f1b1c7227f7c22602f53f15af80747814dffd839719731ee3bba6edc126c", + params: { url: `https://node-0.v2.eu.cdn.testnet.cere.network` }, + }, + { + pubKey: "0x8ac59e11963af19174d0b94d5d78041c233f55d2e19324665bafdfb62925af2d", + params: { url: `https://node-1.v2.eu.cdn.testnet.cere.network` }, + } + ] + } ], }, mainnet: { - ws_provider: "wss://archive.testnet.cere.network/ws", - contract_address: "6So8eqxMyWAxJ4ZZ2wCcJym7Cy6BYkc4V8GZZD9wgdCqWMQB", - cluster: { - 1n: { - param: { replicationFactor: 3 }, - vnodes: [ [0n], [GEN / 3n], [GEN * 2n / 3n] ], - storage_nodes: [1n, 2n, 3n], - }, - }, - storage_node_params: [ - { url: `https://node-0.v2.us.storage.mainnet.cere.network` }, - { url: `https://node-1.v2.us.storage.mainnet.cere.network` }, - { url: `https://node-2.v2.us.storage.mainnet.cere.network` }, - ], - cdn_cluster: { - 0n: { - cdn_nodes: [1n, 2n], - }, - }, - cdn_node_params: [ - { - url: `https://node-0.v2.us.cdn.mainnet.cere.network`, - publicKey: "0x86af4db1e433ad221b6fa3c1a9fc4de694ab59408ca57584e50d8fd420e7b45b", - }, + blockchainUrl: "wss://archive.qanet.cere.network/ws", + clusters: [ { - url: `https://node-1.v2.us.cdn.mainnet.cere.network`, - publicKey: "0x9a9fb6c479ef7c8f3af54dc0720f08a73d532815d525aa8d69d965e56512440e", - }, + params: { replicationFactor: 3 }, + storageNodes: [ + { + pubKey: "0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d", + vNodes: [0n], + params: { url: `https://node-0.v2.us.storage.mainnet.cere.network` }, + }, + { + pubKey: "0x8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48", + vNodes: [GEN / 3n], + params: { url: `https://node-1.v2.us.storage.mainnet.cere.network` } + }, + { + pubKey: "0x90b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22", + vNodes: [GEN * 2n / 3n], + params: { url: `https://node-2.v2.us.storage.mainnet.cere.network` } + } + ], + cdnNodes: [ + { + pubKey: "0xfe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e", + params: { url: `https://node-0.v2.us.cdn.mainnet.cere.network` }, + }, + { + pubKey: "0x1e07379407fecc4b89eb7dbd287c2c781cfb1907a96947a3eb18e4f8e7198625", + params: { url: `https://node-1.v2.us.cdn.mainnet.cere.network` }, + } + ] + } ], }, + };