Browse Source

Merge pull request #3249 from Joystream/olympia-playground

Olympia: update from playground
Mokhtar Naamani 3 years ago
parent
commit
60f78e78f8
57 changed files with 1299 additions and 1175 deletions
  1. 9 3
      .github/workflows/create-ami.yml
  2. 48 15
      .github/workflows/deploy-node-network.yml
  3. 3 3
      .github/workflows/deploy-playground.yml
  4. 1 1
      .github/workflows/joystream-node-docker.yml
  5. 19 3
      .pipelines/deploy-node-network-inputs.json
  6. 2 2
      Cargo.lock
  7. 5 1
      build-node-docker.sh
  8. 0 0
      chain-metadata.json
  9. 1 1
      cli/package.json
  10. 0 37
      devops/aws/chain-spec-pioneer.yml
  11. 29 63
      devops/aws/cloudformation/infrastructure.yml
  12. 27 0
      devops/aws/configure-network.yml
  13. 1 1
      devops/aws/create-joystream-node-ami-playbook.yml
  14. 4 1
      devops/aws/deploy-infra.sample.cfg
  15. 20 11
      devops/aws/deploy-infra.sh
  16. 1 1
      devops/aws/deploy-playground-playbook.yml
  17. 0 6
      devops/aws/destroy-infra.sh
  18. 0 3
      devops/aws/group_vars/all
  19. 0 38
      devops/aws/roles/admin/tasks/deploy-pioneer.yml
  20. 1 1
      devops/aws/roles/build-server/tasks/main.yml
  21. 15 15
      devops/aws/roles/common/tasks/chain-spec-node-keys.yml
  22. 4 9
      devops/aws/roles/common/tasks/get-code-git.yml
  23. 3 1
      devops/aws/roles/common/tasks/run-setup-build.yml
  24. 38 9
      devops/aws/roles/rpc/tasks/main.yml
  25. 40 2
      devops/aws/roles/rpc/templates/Caddyfile.j2
  26. 1 1
      devops/aws/roles/rpc/templates/joystream-node.service.j2
  27. 1 2
      devops/aws/setup-build-server.yml
  28. 1 1
      distributor-node/package.json
  29. 2 1
      joystream-node.Dockerfile
  30. 1 1
      node/Cargo.toml
  31. 0 3
      query-node/manifest.yml
  32. 1 1
      query-node/mappings/package.json
  33. 1 1
      runtime/Cargo.toml
  34. 6 6
      runtime/src/lib.rs
  35. 55 54
      runtime/src/proposals_configuration/defaults.rs
  36. 12 9
      runtime/src/proposals_configuration/mod.rs
  37. 3 237
      runtime/src/proposals_configuration/tests.rs
  38. 109 43
      runtime/src/tests/mod.rs
  39. 232 234
      runtime/src/tests/proposals_integration/mod.rs
  40. 20 29
      runtime/src/tests/proposals_integration/working_group_proposals.rs
  41. 2 0
      scripts/cargo-build.sh
  42. 19 14
      start.sh
  43. 1 1
      storage-node/package.json
  44. 17 0
      tests/network-tests/src/Api.ts
  45. 5 1
      tests/network-tests/src/Scenario.ts
  46. 4 3
      tests/network-tests/src/fixtures/membership/TransferInvitesHappyCaseFixture.ts
  47. 1 1
      tests/network-tests/src/fixtures/proposals/DecideOnProposalStatusFixture.ts
  48. 41 0
      tests/network-tests/src/fixtures/workingGroups/SetLeaderInvitationQuotaFixture.ts
  49. 57 0
      tests/network-tests/src/flows/faucet/initFaucet.ts
  50. 1 1
      tests/network-tests/src/graphql/generated/queries.ts
  51. 418 294
      tests/network-tests/src/graphql/generated/schema.ts
  52. 1 1
      tests/network-tests/src/graphql/queries/proposalsEvents.graphql
  53. 7 6
      tests/network-tests/src/scenarios/setupNewChain.ts
  54. 6 0
      tests/network-tests/src/types.ts
  55. 1 1
      types/package.json
  56. 1 1
      utils/api-scripts/package.json
  57. 1 1
      utils/migration-scripts/package.json

+ 9 - 3
.github/workflows/create-ami.yml

@@ -4,6 +4,10 @@ name: Create AWS AMI
 
 on:
   workflow_dispatch:
+    inputs:
+      proposalParameters:
+        description: 'Proposal Parameters (refer to runtime/src/proposals_configuration/sample_proposal_parameters.json for sample)'
+        required: false
 
 jobs:
   build:
@@ -11,7 +15,7 @@ jobs:
     runs-on: ubuntu-latest
     env:
       STACK_NAME: create-joystream-node-ami-ga-${{ github.run_number }}
-      KEY_NAME: joystream-github-action-key
+      KEY_NAME: joystream-github-action-key-new
     steps:
       - name: Extract branch name
         shell: bash
@@ -57,8 +61,10 @@ jobs:
             ${{ steps.deploy_stack.outputs.PublicIp }}
           options: |
             --extra-vars "git_repo=https://github.com/${{ github.repository }} \
-                          branch_name=${{ steps.extract_branch.outputs.branch }} instance_id=${{ steps.deploy_stack.outputs.InstanceId }}
-                          ami_name=${{ env.ami_name }}"
+                          branch_name=${{ steps.extract_branch.outputs.branch }} \
+                          instance_id=${{ steps.deploy_stack.outputs.InstanceId }} \
+                          ami_name=${{ env.ami_name }} \
+                          proposal_parameters=${{ github.event.inputs.proposalParameters }}"
 
       - name: Delete CloudFormation Stack
         if: always()

+ 48 - 15
.github/workflows/deploy-node-network.yml

@@ -39,8 +39,20 @@ jobs:
           echo ::set-output name=ec2AMI::$(echo $jsonInput | jq -r '.ec2AMI.value')
           echo ::set-output name=networkSuffix::$(echo $jsonInput | jq -r '.networkSuffix.value')
           echo ::set-output name=deploymentType::$(echo $jsonInput | jq -r '.deploymentType.value')
+          echo ::set-output name=volumeSize::$(echo $jsonInput | jq -r '.volumeSize.value')
+          echo ::set-output name=rpcVolumeSize::$(echo $jsonInput | jq -r '.rpcVolumeSize.value')
+          echo ::set-output name=skipChainSetup::$(echo $jsonInput | jq -r '.skipChainSetup.value')
           initialBalancesFile=$(echo $jsonInput | jq -r '.initialBalancesFile.value')
           initialMembersFile=$(echo $jsonInput | jq -r '.initialMembersFile.value')
+          proposalParametersInput=$(echo $jsonInput | jq -r '.proposalParameters.value')
+
+          if [ $proposalParametersInput = "{}" ]
+          then
+            echo ::set-output name=proposalParameters::''
+          else
+            echo ::set-output name=proposalParameters::$proposalParametersInput
+          fi
+
           if [ -z "$initialBalancesFile" ]
           then
             echo ::set-output name=initialBalancesFilePath::''
@@ -48,6 +60,7 @@ jobs:
             wget $initialBalancesFile -O initial-balances.json
             echo ::set-output name=initialBalancesFilePath::'initial-balances.json'
           fi
+
           if [ -z "$initialMembersFile" ]
           then
             echo ::set-output name=initialMembersFilePath::''
@@ -66,6 +79,16 @@ jobs:
           aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
           aws-region: us-east-1
 
+      - name: Check if CloudFormation stack exists
+        id: stack_exists
+        run: |
+          if aws cloudformation describe-stacks --stack-name ${{ env.STACK_NAME }} >/dev/null 2>/dev/null; then
+            echo "Stack already exists"
+            exit 1
+          else
+            echo "Stack does not exist"
+          fi
+
       - name: Deploy to AWS CloudFormation
         uses: aws-actions/aws-cloudformation-github-deploy@v1
         id: deploy_stack
@@ -79,7 +102,9 @@ jobs:
             RPCEC2InstanceType=${{ steps.myoutputs.outputs.rpcInstanceType }},
             BuildEC2InstanceType=${{ steps.myoutputs.outputs.buildInstanceType }},
             EC2AMI=${{ steps.myoutputs.outputs.ec2AMI }},
-            NumberOfValidators=${{ steps.myoutputs.outputs.numberOfValidators }}
+            NumberOfValidators=${{ steps.myoutputs.outputs.numberOfValidators }},
+            VolumeSize=${{ steps.myoutputs.outputs.volumeSize }},
+            RPCVolumeSize=${{ steps.myoutputs.outputs.rpcVolumeSize }}
 
       - name: Prepare inventory for Ansible
         run: |
@@ -103,7 +128,8 @@ jobs:
 
       - name: Run playbook to compile joystream-node on build server
         uses: dawidd6/action-ansible-playbook@v2
-        if: steps.myoutputs.outputs.ec2AMI == ''
+        # Build binaries if AMI not specified or a custom proposals parameter is passed
+        if: steps.myoutputs.outputs.ec2AMI == '' || steps.myoutputs.outputs.proposalParameters != ''
         with:
           playbook: build-code.yml
           directory: devops/aws
@@ -112,23 +138,24 @@ jobs:
           options: |
             --inventory inventory
             --extra-vars "branch_name=${{ steps.myoutputs.outputs.branchName }} \
-                          git_repo=${{ steps.myoutputs.outputs.gitRepo }} data_path=mydata"
+                          git_repo=${{ steps.myoutputs.outputs.gitRepo }} data_path=mydata \
+                          proposal_parameters=${{ steps.myoutputs.outputs.proposalParameters }}"
 
       - name: Run playbook to install additional utils on build server
         uses: dawidd6/action-ansible-playbook@v2
         if: steps.myoutputs.outputs.ec2AMI == ''
         with:
-          playbook: setup-admin.yml
+          playbook: setup-build-server.yml
           directory: devops/aws
           requirements: requirements.yml
           key: ${{ secrets.SSH_PRIVATE_KEY }}
           options: |
             --inventory inventory
 
-      - name: Run playbook to configure chain-spec and pioneer
+      - name: Run playbook to configure chain-spec
         uses: dawidd6/action-ansible-playbook@v2
         with:
-          playbook: chain-spec-pioneer.yml
+          playbook: configure-network.yml
           directory: devops/aws
           requirements: requirements.yml
           key: ${{ secrets.SSH_PRIVATE_KEY }}
@@ -138,10 +165,16 @@ jobs:
                           number_of_validators=${{ steps.myoutputs.outputs.numberOfValidators }} \
                           git_repo=${{ steps.myoutputs.outputs.gitRepo }} \
                           deployment_type=${{ steps.myoutputs.outputs.deploymentType }} \
-                          bucket_name=${{ steps.deploy_stack.outputs.S3BucketName }} \
                           branch_name=${{ steps.myoutputs.outputs.branchName }} \
                           initial_members_file=${{ steps.myoutputs.outputs.initialMembersFilePath }} \
-                          initial_balances_file=${{ steps.myoutputs.outputs.initialBalancesFilePath }}"
+                          initial_balances_file=${{ steps.myoutputs.outputs.initialBalancesFilePath }} \
+                          skip_chain_setup=${{ steps.myoutputs.outputs.skipChainSetup }}"
+
+      - name: Terminate Build instance
+        continue-on-error: true
+        run: |
+          echo "Deleting build instance with id ${{ steps.deploy_stack.outputs.BuildInstanceId }}"
+          aws ec2 terminate-instances --instance-ids ${{ steps.deploy_stack.outputs.BuildInstanceId }}
 
       - name: Encrpyt the artifacts
         run: |
@@ -153,16 +186,16 @@ jobs:
           name: data-chainspec-auth
           path: devops/aws/chain-data.7z
 
-      - name: Print output URL's
-        run: |
-          echo -e "Pioneer URL: https://${{ steps.deploy_stack.outputs.DomainName }}"
-          echo -e "RPC: wss://${{ steps.deploy_stack.outputs.RPCPublicIp }}.nip.io/ws-rpc"
+      - name: Save the endpoints file as an artifact
+        uses: actions/upload-artifact@v2
+        with:
+          name: endpoints
+          path: devops/aws/endpoints.json
 
       - name: Delete CloudFormation Stack if any step failed
-        if: failure()
+        # Skip only if stack already existed or all steps passed succesfully
+        if: ( failure() || cancelled() ) && steps.stack_exists.outcome != 'failure'
         run: |
-          echo "Empty the bucket"
-          aws s3 rm s3://${{ steps.deploy_stack.outputs.S3BucketName }} --recursive || echo "No bucket"
           echo "Deleting ${{ env.STACK_NAME }} stack"
           aws cloudformation delete-stack --stack-name ${{ env.STACK_NAME }}
           echo "Waiting for ${{ env.STACK_NAME }} to be deleted..."

+ 3 - 3
.github/workflows/deploy-playground.yml

@@ -14,7 +14,7 @@ on:
       keyName:
         description: 'SSH key pair on AWS'
         required: false
-        default: 'joystream-github-action-key'
+        default: 'joystream-github-action-key-new'
       instanceType:
         description: 'AWS EC2 instance type (t2.micro, t2.large)'
         required: false
@@ -92,8 +92,8 @@ jobs:
             --extra-vars "git_repo=${{ github.event.inputs.gitRepo }} \
                           branch_name=${{ github.event.inputs.branchName }} \
                           skip_chain_setup=${{ github.event.inputs.skipChainSetup }} \
-                          proposal_parameters='${{ github.event.inputs.proposalParameters }}' \
-                          stack_name=${{ env.STACK_NAME }}"
+                          stack_name=${{ env.STACK_NAME }} \
+                          proposal_parameters=${{ github.event.inputs.proposalParameters }}"
 
       - name: Save the endpoints file as an artifact
         uses: actions/upload-artifact@v2

+ 1 - 1
.github/workflows/joystream-node-docker.yml

@@ -4,7 +4,7 @@ on: push
 
 env:
   REPOSITORY: joystream/node
-  KEY_NAME: joystream-github-action-key
+  KEY_NAME: joystream-github-action-key-new
 
 jobs:
   push-amd64:

+ 19 - 3
.pipelines/deploy-node-network-inputs.json

@@ -9,7 +9,7 @@
   },
   "keyName": {
     "description": "SSH key pair on AWS",
-    "value": "joystream-github-action-key"
+    "value": "joystream-github-action-key-new"
   },
   "numberOfValidators": {
     "description": "Number of validators to deploy",
@@ -28,8 +28,16 @@
     "value": "t2.micro"
   },
   "ec2AMI": {
-    "description": "Pre-built AMI ID (ami-095792100b6e43a67)",
-    "value": "ami-095792100b6e43a67"
+    "description": "Pre-built AMI ID",
+    "value": "ami-0ce5f13e91397239a"
+  },
+  "volumeSize": {
+    "description": "Validator and Build instance volume size in GB",
+    "value": "120"
+  },
+  "rpcVolumeSize": {
+    "description": "RPC Instance volume size in GB",
+    "value": "120"
   },
   "networkSuffix": {
     "description": "Network suffix that will be added to the network name",
@@ -50,5 +58,13 @@
   "encryptionKey": {
     "description": "Password to encrypt the artifacts",
     "value": "password"
+  },
+  "proposalParameters": {
+    "description": "Proposal Parameters",
+    "value": {}
+  },
+  "skipChainSetup": {
+    "description": "Set to true to skip running setup new chain scenario",
+    "value": true
   }
 }

+ 2 - 2
Cargo.lock

@@ -2278,7 +2278,7 @@ dependencies = [
 
 [[package]]
 name = "joystream-node"
-version = "6.0.0"
+version = "6.1.0"
 dependencies = [
  "frame-benchmarking",
  "frame-benchmarking-cli",
@@ -2339,7 +2339,7 @@ dependencies = [
 
 [[package]]
 name = "joystream-node-runtime"
-version = "10.0.0"
+version = "10.1.0"
 dependencies = [
  "frame-benchmarking",
  "frame-executive",

+ 5 - 1
build-node-docker.sh

@@ -8,6 +8,8 @@ set -e
 CODE_HASH=`scripts/runtime-code-shasum.sh`
 IMAGE=joystream/node:${CODE_HASH}
 
+# TODO: Check for valid JSON in ALL_PROPOSALS_PARAMETERS_JSON ?
+
 # Look for image locally
 if ! docker inspect ${IMAGE} > /dev/null;
 then
@@ -19,7 +21,9 @@ then
   if ! docker inspect ${IMAGE} > /dev/null;
   then
     echo "Building ${IMAGE}.."
-    docker build . --file joystream-node.Dockerfile --tag ${IMAGE} --build-arg TEST_NODE=${TEST_NODE}
+    docker build . --file joystream-node.Dockerfile --tag ${IMAGE} \
+	    --build-arg TEST_NODE=${TEST_NODE} \
+	    --build-arg ALL_PROPOSALS_PARAMETERS_JSON=${ALL_PROPOSALS_PARAMETERS_JSON}
   fi
 else
   echo "Found ${IMAGE} in local repo"

File diff suppressed because it is too large
+ 0 - 0
chain-metadata.json


+ 1 - 1
cli/package.json

@@ -13,7 +13,7 @@
     "@apidevtools/json-schema-ref-parser": "^9.0.6",
     "@ffprobe-installer/ffprobe": "^1.1.0",
     "@joystream/metadata-protobuf": "^2.0.0",
-    "@joystream/types": "^0.18.0",
+    "@joystream/types": "^0.18.1",
     "@oclif/command": "^1.5.19",
     "@oclif/config": "^1.14.0",
     "@oclif/plugin-autocomplete": "^0.2.0",

+ 0 - 37
devops/aws/chain-spec-pioneer.yml

@@ -1,37 +0,0 @@
----
-# Configure chain spec, start joystream-node service on the servers and build Pioneer
-
-- name: Create and copy the chain-spec file
-  hosts: all
-
-  tasks:
-    - name: Generate chain-spec file and data keys either on localhost or admin server
-      include_role:
-        name: common
-        tasks_from: chain-spec-node-keys
-      vars:
-        local_or_admin: "{{ groups['build'][0] if run_on_admin_server|bool else 'localhost' }}"
-        admin_code_dir: "{{ remote_code_path if run_on_admin_server|bool else local_dir }}"
-
-- name: Copy secret, auth and start joystream-node service for validators
-  hosts: validators
-  gather_facts: no
-
-  roles:
-    - validators
-
-- name: Configure RPC service and start it
-  hosts: rpc
-  gather_facts: no
-
-  roles:
-    - rpc
-
-- name: Build Pioneer and copy artifacts to S3
-  hosts: build
-  gather_facts: no
-
-  tasks:
-    - include_role:
-        name: admin
-        tasks_from: deploy-pioneer

+ 29 - 63
devops/aws/cloudformation/infrastructure.yml

@@ -2,7 +2,7 @@
 # This is comprised of:
 #   - N validators
 #   - One RPC node
-#   - s3 bucket with a build of Pionner
+#   - One Build instance
 
 AWSTemplateFormatVersion: 2010-09-09
 
@@ -34,16 +34,23 @@ Parameters:
     Description: Number of validator instances to launch
     Type: Number
     Default: 2
+  VolumeSize:
+    Description: Validator and Build instance volume size in GB
+    Type: Number
+    Default: 120
+  RPCVolumeSize:
+    Description: RPC Instance volume size in GB
+    Type: Number
+    Default: 120
 
 Conditions:
-  HasAMIId: !Not [!Equals [!Ref EC2AMI, ""]]
+  HasAMIId: !Not [!Equals [!Ref EC2AMI, '']]
 
 Resources:
   SecurityGroup:
     Type: AWS::EC2::SecurityGroup
     Properties:
-      GroupDescription:
-        !Sub 'Internal Security group for validator nodes ${AWS::StackName}'
+      GroupDescription: !Sub 'Internal Security group for validator nodes ${AWS::StackName}'
       SecurityGroupIngress:
         - IpProtocol: tcp
           FromPort: 30333
@@ -60,8 +67,7 @@ Resources:
   RPCSecurityGroup:
     Type: AWS::EC2::SecurityGroup
     Properties:
-      GroupDescription:
-        !Sub 'Internal Security group for RPC nodes ${AWS::StackName}'
+      GroupDescription: !Sub 'Internal Security group for RPC nodes ${AWS::StackName}'
       SecurityGroupIngress:
         - IpProtocol: tcp
           FromPort: 9933
@@ -111,7 +117,7 @@ Resources:
         BlockDeviceMappings:
           - DeviceName: /dev/sda1
             Ebs:
-              VolumeSize: '120'
+              VolumeSize: !Ref VolumeSize
         UserData:
           Fn::Base64: !Sub |
             #!/bin/bash -xe
@@ -161,7 +167,7 @@ Resources:
       DesiredCapacity: !Ref NumberOfValidators
       AvailabilityZones:
         Fn::GetAZs:
-          Ref: "AWS::Region"
+          Ref: 'AWS::Region'
       MixedInstancesPolicy:
         LaunchTemplate:
           LaunchTemplateSpecification:
@@ -172,7 +178,7 @@ Resources:
       Tags:
         - Key: Name
           Value: !Sub '${AWS::StackName}'
-          PropagateAtLaunch: "true"
+          PropagateAtLaunch: 'true'
 
   RPCInstance:
     Type: AWS::EC2::Instance
@@ -183,6 +189,10 @@ Resources:
       LaunchTemplate:
         LaunchTemplateId: !Ref InstanceLaunchTemplate
         Version: !GetAtt InstanceLaunchTemplate.LatestVersionNumber
+      BlockDeviceMappings:
+        - DeviceName: /dev/sda1
+          Ebs:
+            VolumeSize: !Ref RPCVolumeSize
       Tags:
         - Key: Name
           Value: !Sub '${AWS::StackName}_rpc'
@@ -208,71 +218,27 @@ Resources:
       Timeout: '600'
       Count: !Ref NumberOfValidators
 
-  S3Bucket:
-    Type: AWS::S3::Bucket
-    Properties:
-      AccessControl: PublicRead
-      WebsiteConfiguration:
-        IndexDocument: index.html
-
-  BucketPolicy:
-    Type: AWS::S3::BucketPolicy
-    Properties:
-      PolicyDocument:
-        Id: PublicPolicy
-        Version: 2012-10-17
-        Statement:
-          - Sid: PublicReadForGetBucketObjects
-            Effect: Allow
-            Principal: '*'
-            Action: 's3:GetObject'
-            Resource: !Sub "arn:aws:s3:::${S3Bucket}/*"
-      Bucket: !Ref S3Bucket
-
-  CloudFrontDistribution:
-    Type: AWS::CloudFront::Distribution
-    Properties:
-      DistributionConfig:
-        Origins:
-        - DomainName: !Select [1, !Split ["//", !GetAtt S3Bucket.WebsiteURL]]
-          Id: pioneer-origin-s3
-          CustomOriginConfig:
-            OriginProtocolPolicy: http-only
-        DefaultCacheBehavior:
-          TargetOriginId: pioneer-origin-s3
-          ViewerProtocolPolicy: redirect-to-https
-          ForwardedValues:
-            QueryString: true
-        Enabled: true
-        HttpVersion: http2
-
 Outputs:
   AutoScalingId:
     Description: The Auto Scaling ID
-    Value:  !Ref AutoScalingGroup
+    Value: !Ref AutoScalingGroup
     Export:
-      Name: !Sub "${AWS::StackName}AutoScalingGroup"
+      Name: !Sub '${AWS::StackName}AutoScalingGroup'
 
   RPCPublicIp:
     Description: The DNS name for the created instance
-    Value:  !Sub "${RPCInstance.PublicIp}"
+    Value: !Sub '${RPCInstance.PublicIp}'
     Export:
-      Name: !Sub "${AWS::StackName}RPCPublicIp"
+      Name: !Sub '${AWS::StackName}RPCPublicIp'
 
   BuildPublicIp:
     Description: The DNS name for the created instance
-    Value:  !Sub "${BuildInstance.PublicIp}"
-    Export:
-      Name: !Sub "${AWS::StackName}BuildPublicIp"
-
-  S3BucketName:
-    Value: !Ref S3Bucket
-    Description: Name of S3 bucket to hold website content
+    Value: !Sub '${BuildInstance.PublicIp}'
     Export:
-      Name: !Sub "${AWS::StackName}S3BucketName"
+      Name: !Sub '${AWS::StackName}BuildPublicIp'
 
-  DomainName:
-    Description: CloudFront Domain Name
-    Value:  !Sub "${CloudFrontDistribution.DomainName}"
+  BuildInstanceId:
+    Description: Build instance ID
+    Value: !Ref BuildInstance
     Export:
-      Name: !Sub "${AWS::StackName}DomainName"
+      Name: !Sub '${AWS::StackName}BuildInstanceId'

+ 27 - 0
devops/aws/configure-network.yml

@@ -0,0 +1,27 @@
+---
+# Configure chain spec, start joystream-node and other services on the servers
+
+- name: Create and copy the chain-spec file
+  hosts: all
+
+  tasks:
+    - name: Generate chain-spec file and data keys on build server
+      include_role:
+        name: common
+        tasks_from: chain-spec-node-keys
+      vars:
+        build_instance: "{{ groups['build'][0] }}"
+
+- name: Copy secret, auth and start joystream-node service for validators
+  hosts: validators
+  gather_facts: no
+
+  roles:
+    - validators
+
+- name: Configure RPC service and start it
+  hosts: rpc
+  gather_facts: no
+
+  roles:
+    - rpc

+ 1 - 1
devops/aws/create-joystream-node-ami-playbook.yml

@@ -17,7 +17,7 @@
 
     - name: Install subkey
       include_role:
-        name: admin
+        name: build-server
         tasks_from: main
 
     - name: Basic AMI Creation

+ 4 - 1
devops/aws/deploy-infra.sample.cfg

@@ -11,7 +11,7 @@ BUILD_EC2_INSTANCE_TYPE=t2.large
 RPC_EC2_INSTANCE_TYPE=t2.medium
 
 # prebuilt AMI with joystream-node, chain-spec and subkey already built
-EC2_AMI_ID="ami-095792100b6e43a67"
+EC2_AMI_ID="ami-0ce5f13e91397239a"
 
 ACCOUNT_ID=$(aws sts get-caller-identity --profile $CLI_PROFILE --query Account --output text)
 
@@ -35,5 +35,8 @@ INITIAL_BALANCES_PATH=""
 GIT_REPO="https://github.com/Joystream/joystream.git"
 BRANCH_NAME=master
 
+ALL_PROPOSALS_PARAMETERS_JSON=""
+SKIP_CHAIN_SETUP="true"
+
 # If true will build LOCAL_CODE_PATH otherwise will pull from GIT_REPO:BRANCH_NAME
 BUILD_LOCAL_CODE=false

+ 20 - 11
devops/aws/deploy-infra.sh

@@ -63,29 +63,38 @@ if [ $? -eq 0 ]; then
 
   BUILD_SERVER=$(get_aws_export $NEW_STACK_NAME "BuildPublicIp")
 
-  BUCKET_NAME=$(get_aws_export $NEW_STACK_NAME "S3BucketName")
-
-  DOMAIN_NAME=$(get_aws_export $NEW_STACK_NAME "DomainName")
+  BUILD_INSTANCE_ID=$(get_aws_export $NEW_STACK_NAME "BuildInstanceId")
 
   mkdir -p $DATA_PATH
 
   echo -e "[build]\n$BUILD_SERVER\n\n[validators]\n$VALIDATORS\n[rpc]\n$RPC_NODES" > $INVENTORY_PATH
 
-  if [ -z "$EC2_AMI_ID" ]
+  # Build binaries if AMI not specified or a custom proposals parameter is passed
+  if [ -z "$EC2_AMI_ID" ] || [ -n "$ALL_PROPOSALS_PARAMETERS_JSON" ]
   then
     echo -e "\n\n=========== Compile joystream-node on build server ==========="
     ansible-playbook -i $INVENTORY_PATH --private-key $KEY_PATH build-code.yml \
-      --extra-vars "branch_name=$BRANCH_NAME git_repo=$GIT_REPO build_local_code=$BUILD_LOCAL_CODE data_path=$DATA_PATH"
+      --extra-vars "branch_name=$BRANCH_NAME git_repo=$GIT_REPO build_local_code=$BUILD_LOCAL_CODE
+                    data_path=$DATA_PATH proposal_parameters=$ALL_PROPOSALS_PARAMETERS_JSON"
+  fi
 
+  if [ -z "$EC2_AMI_ID" ]
+  then
     echo -e "\n\n=========== Install additional utils on build server ==========="
-    ansible-playbook -i $INVENTORY_PATH --private-key $KEY_PATH setup-admin.yml
+    ansible-playbook -i $INVENTORY_PATH --private-key $KEY_PATH setup-build-server.yml
   fi
 
-  echo -e "\n\n=========== Configure and start new validators, rpc node and pioneer ==========="
-  ansible-playbook -i $INVENTORY_PATH --private-key $KEY_PATH chain-spec-pioneer.yml \
+  echo -e "\n\n=========== Configure and start new validators and rpc node ==========="
+  ansible-playbook -i $INVENTORY_PATH --private-key $KEY_PATH configure-network.yml \
     --extra-vars "local_dir=$LOCAL_CODE_PATH network_suffix=$NETWORK_SUFFIX
-                  data_path=$DATA_PATH bucket_name=$BUCKET_NAME number_of_validators=$NUMBER_OF_VALIDATORS
-                  deployment_type=$DEPLOYMENT_TYPE initial_balances_file=$INITIAL_BALANCES_PATH initial_members_file=$INITIAL_MEMBERS_PATH"
+                  data_path=$DATA_PATH number_of_validators=$NUMBER_OF_VALIDATORS
+                  deployment_type=$DEPLOYMENT_TYPE
+                  initial_balances_file=$INITIAL_BALANCES_PATH
+                  initial_members_file=$INITIAL_MEMBERS_PATH
+                  skip_chain_setup=$SKIP_CHAIN_SETUP"
+
+  echo -e "\n\n=========== Delete Build instance ==========="
+  DELETE_RESULT=$(aws ec2 terminate-instances --instance-ids $BUILD_INSTANCE_ID --profile $CLI_PROFILE)
+  echo $DELETE_RESULT
 
-  echo -e "\n\n Pioneer URL: https://$DOMAIN_NAME"
 fi

+ 1 - 1
devops/aws/deploy-playground-playbook.yml

@@ -11,7 +11,7 @@
         name: common
         tasks_from: get-code-git
 
-    - name: Creat bash profile file
+    - name: Create bash profile file
       command: 'touch /home/ubuntu/.bash_profile'
 
     - name: Run setup script

+ 0 - 6
devops/aws/destroy-infra.sh

@@ -13,14 +13,8 @@ else
   source $1
 fi
 
-BUCKET_NAME=$(get_aws_export $NEW_STACK_NAME "S3BucketName")
-
 # Delete the CloudFormation stack
 
-echo -e "\n\n=========== Emptying bucket $BUCKET_NAME ==========="
-
-aws s3 rm s3://$BUCKET_NAME --recursive --profile $CLI_PROFILE || echo "No bucket"
-
 echo -e "\n\n=========== Deleting stack $NEW_STACK_NAME ==========="
 
 aws cloudformation delete-stack --stack-name $NEW_STACK_NAME --profile $CLI_PROFILE

+ 0 - 3
devops/aws/group_vars/all

@@ -15,8 +15,5 @@ raw_chain_spec_path: "{{ remote_data_path }}/chainspec-raw.json"
 local_raw_chain_spec_path: "{{ data_path }}/chainspec-raw.json"
 remote_code_path: "/home/ubuntu/joystream"
 remote_chain_spec_path: "{{ remote_code_path }}/chainspec.json"
-run_on_admin_server: true
 build_local_code: false
 number_of_validators: 2
-
-bucket_name: s3-bucket-joystream

+ 0 - 38
devops/aws/roles/admin/tasks/deploy-pioneer.yml

@@ -1,38 +0,0 @@
----
-# Build Pioneer, copy build artifacts and sync to S3
-
-- name: Set ws_rpc for build node
-  set_fact:
-    ws_rpc: "{{ hostvars[groups['rpc'][0]].ws_rpc }}"
-
-- name: Build Pioneer code
-  shell: "WS_URL=wss://{{ ws_rpc }} yarn && yarn workspace @joystream/types build && yarn workspace pioneer build"
-  args:
-    chdir: "{{ remote_code_path }}"
-  async: 3600
-  poll: 0
-  register: build_result
-
-- name: Check on build async task
-  async_status:
-    jid: '{{ build_result.ansible_job_id }}'
-  register: job_result
-  until: job_result.finished
-  # Max number of times to check for status
-  retries: 36
-  # Check for the status every 100s
-  delay: 100
-
-- name: Copying build files to local
-  synchronize:
-    src: "{{ remote_code_path }}/pioneer/packages/apps/build"
-    dest: "{{ data_path }}"
-    mode: pull
-  run_once: true
-
-- name: Run S3 Sync to upload build files to bucket
-  community.aws.s3_sync:
-    bucket: "{{ bucket_name }}"
-    file_root: "{{ data_path }}/build"
-    region: us-east-1
-  delegate_to: localhost

+ 1 - 1
devops/aws/roles/admin/tasks/main.yml → devops/aws/roles/build-server/tasks/main.yml

@@ -1,5 +1,5 @@
 ---
-# Configure admin server to be able to create chain-spec file and subkey commands
+# Configure build server to be able to create chain-spec file and subkey commands
 
 - name: Copy bash_profile content
   shell: cat ~/.bash_profile

+ 15 - 15
devops/aws/roles/common/tasks/chain-spec-node-keys.yml

@@ -9,32 +9,34 @@
 - name: Copying initial members file to the server
   copy:
     src: '{{ initial_members_file }}'
-    dest: '{{ admin_code_dir }}/initial-members.json'
+    dest: '{{ remote_code_path }}/query-node/mappings/src/bootstrap-data/data/members.json'
   when: initial_members_file is defined and initial_members_file|length > 0
   run_once: true
 
 - name: Copying initial balances file to the server
   copy:
     src: '{{ initial_balances_file }}'
-    dest: '{{ admin_code_dir }}/initial-balances.json'
+    dest: '{{ remote_code_path }}/initial-balances.json'
   when: initial_balances_file is defined and initial_balances_file|length > 0
   run_once: true
 
 - name: Run chain-spec-builder to generate chainspec.json file (with initial data)
   shell: >
-    {{ admin_code_dir }}/target/release/chain-spec-builder generate -a {{ number_of_validators }}
+    {{ remote_code_path }}/target/release/chain-spec-builder generate -a {{ number_of_validators }}
     --chain-spec-path {{ chain_spec_path }}
     --endowed 1 --keystore-path {{ remote_data_path }}
     {% if deployment_type is defined and deployment_type|length > 0 %}--deployment {{ deployment_type }}{% endif %}
-    {% if initial_members_file is defined and initial_members_file|length > 0 %}--initial-balances-path {{ admin_code_dir }}/initial-balances.json{% endif %}
-    {% if initial_balances_file is defined and initial_balances_file|length > 0 %}--initial-members-path {{ admin_code_dir }}/initial-members.json{% endif %}
+    {% if initial_members_file is defined and initial_members_file|length > 0 %}--initial-balances-path {{ remote_code_path }}/initial-balances.json{% endif %}
+    {% if initial_balances_file is defined and initial_balances_file|length > 0 %}
+    --initial-members-path {{ remote_code_path }}/query-node/mappings/src/bootstrap-data/data/members.json
+    {% endif %}
   register: chain_spec_output
-  delegate_to: '{{ local_or_admin }}'
+  delegate_to: '{{ build_instance }}'
   run_once: true
 
 - name: Run subkey to generate node keys
   shell: subkey generate-node-key
-  delegate_to: '{{ local_or_admin }}'
+  delegate_to: '{{ build_instance }}'
   register: subkey_output
 
 - name: Print to stdout
@@ -51,7 +53,7 @@
   copy:
     content: '{{ chain_spec_output.stdout | regex_replace("\x1B\[([0-9]{1,3}(;[0-9]{1,2})?)?[mGK]", "") }}'
     dest: '{{ remote_data_path }}/chain_spec_output.txt'
-  delegate_to: '{{ local_or_admin }}'
+  delegate_to: '{{ build_instance }}'
   run_once: true
 
 - name: Change chain spec name, id, protocolId
@@ -59,7 +61,7 @@
     chain_spec_path: '{{ chain_spec_path }}'
     prefix: '{{ network_suffix }}'
     all_nodes: '{{ hostvars }}'
-  delegate_to: '{{ local_or_admin }}'
+  delegate_to: '{{ build_instance }}'
   register: result
   run_once: true
 
@@ -69,8 +71,8 @@
   run_once: true
 
 - name: Run build-spec to generate raw chainspec file
-  shell: '{{ admin_code_dir }}/target/release/joystream-node build-spec --chain {{ chain_spec_path }} --raw > {{ raw_chain_spec_path }}'
-  delegate_to: '{{ local_or_admin }}'
+  shell: '{{ remote_code_path }}/target/release/joystream-node build-spec --chain {{ chain_spec_path }} --raw > {{ raw_chain_spec_path }}'
+  delegate_to: '{{ build_instance }}'
   run_once: true
 
 - name: Copying chain spec files to localhost
@@ -79,16 +81,14 @@
     dest: '{{ data_path }}'
     mode: pull
   run_once: true
-  when: run_on_admin_server|bool
 
 - name: Copy joystream-node binary to localhost
   fetch:
-    src: '{{ admin_code_dir }}/target/release/joystream-node'
+    src: '{{ remote_code_path }}/target/release/joystream-node'
     dest: '{{ data_path }}/joystream-node'
     flat: yes
-  delegate_to: '{{ local_or_admin }}'
+  delegate_to: '{{ build_instance }}'
   run_once: true
-  when: run_on_admin_server|bool
 
 - name: Copying raw chain spec file to all servers
   copy:

+ 4 - 9
devops/aws/roles/common/tasks/get-code-git.yml

@@ -1,14 +1,9 @@
 ---
 # Get the latest code
 
-- name: Delete remote code directory if exists
-  file:
-    state: absent
-    path: "{{ remote_code_path }}"
-  become: yes
-
 - name: Git checkout
   git:
-    repo: "{{ git_repo }}"
-    dest: "{{ remote_code_path }}"
-    version: "{{ branch_name }}"
+    repo: '{{ git_repo }}'
+    dest: '{{ remote_code_path }}'
+    version: '{{ branch_name }}'
+    force: yes

+ 3 - 1
devops/aws/roles/common/tasks/run-setup-build.yml

@@ -1,7 +1,7 @@
 ---
 # Run setup and build code
 
-- name: Creat bash profile file
+- name: Create bash profile file
   command: 'touch /home/ubuntu/.bash_profile'
 
 - name: Run setup script
@@ -13,6 +13,8 @@
   shell: . ~/.bash_profile && yarn cargo-build
   args:
     chdir: '{{ remote_code_path }}'
+  environment:
+    ALL_PROPOSALS_PARAMETERS_JSON: '{{ proposal_parameters }}'
   # Run in async fashion for max duration of 1 hr
   async: 3600
   poll: 0

+ 38 - 9
devops/aws/roles/rpc/tasks/main.yml

@@ -11,8 +11,8 @@
     src: joystream-node.service.j2
     dest: /etc/systemd/system/joystream-node.service
   vars:
-    template_remote_chain_spec_path: "{{ remote_chain_spec_path }}"
-    boot_nodes: "{{ result.result.bootNodes }}"
+    template_remote_chain_spec_path: '{{ remote_chain_spec_path }}'
+    boot_nodes: '{{ result.result.bootNodes }}'
   become: yes
 
 - name: Start service joystream-node, if not started
@@ -41,10 +41,15 @@
   # Check for the status every 100s
   delay: 100
 
-- name: Run query node containers
-  command: yarn workspace query-node-root start:dev
+- name: Run service containers
+  command: yarn start
   environment:
+    PERSIST: 'true'
     JOYSTREAM_NODE_WS: 'ws://{{ inventory_hostname }}:9944/'
+    COLOSSUS_1_URL: 'https://{{ inventory_hostname }}.nip.io/colossus-1/'
+    DISTRIBUTOR_1_URL: 'https://{{ inventory_hostname }}.nip.io/distributor-1/'
+    SKIP_NODE: 'true'
+    SKIP_CHAIN_SETUP: '{{ skip_chain_setup }}'
   args:
     chdir: '{{ remote_code_path }}'
   async: 1800
@@ -63,9 +68,7 @@
 
 - name: Set websocket and http endpoint variables
   set_fact:
-    ws_rpc: "{{ inventory_hostname }}.nip.io/ws-rpc"
-    http_rpc: "{{ inventory_hostname }}.nip.io/http-rpc"
-    nip_domain: "{{ inventory_hostname }}.nip.io"
+    nip_domain: '{{ inventory_hostname }}.nip.io'
   run_once: yes
 
 - name: Install and configure Caddy
@@ -78,6 +81,32 @@
     caddy_systemd_capabilities_enabled: true
     caddy_update: false
 
-- name: Print RPC node DNS
+- name: Set endpoints
+  set_fact:
+    all_services: |
+      websocket_rpc: wss://{{ nip_domain }}/ws-rpc
+      http_rpc: https://{{ nip_domain }}/http-rpc
+      colossus: https://{{ nip_domain }}/colossus-1
+      distributor: https://{{ nip_domain }}/distributor-1
+      graphql_server: https://{{ nip_domain }}/query-node/server/graphql
+      graphql_server_websocket: wss://{{ nip_domain }}/query-node/server/graphql
+      indexer: https://{{ nip_domain }}/query-node/indexer/graphql
+      member_faucet: https://{{ nip_domain }}/member-faucet/register
+      config: https://{{ nip_domain }}/network/config.json
+  run_once: yes
+
+- name: Print endpoints
   debug:
-    msg: "RPC Endpoint: wss://{{ ws_rpc }}"
+    msg: '{{ all_services | from_yaml }}'
+  run_once: yes
+
+- name: Create config.json to serve as Caddy endpoint
+  copy:
+    content: '{{ all_services | from_yaml | to_json }}'
+    dest: '/home/ubuntu/config.json'
+
+- name: Save output as file on local
+  copy:
+    content: '{{ all_services | from_yaml | to_json }}'
+    dest: 'endpoints.json'
+  delegate_to: localhost

+ 40 - 2
devops/aws/roles/rpc/templates/Caddyfile.j2

@@ -1,11 +1,24 @@
-{{ ws_rpc }} {
+{{ nip_domain }}/ws-rpc* {
+    uri strip_prefix /ws-rpc
     reverse_proxy localhost:9944
 }
 
-{{ http_rpc }} {
+{{ nip_domain }}/http-rpc* {
+    uri strip_prefix /http-rpc
     reverse_proxy localhost:9933
 }
 
+{{ nip_domain }}/colossus-1* {
+    uri strip_prefix /colossus-1
+    reverse_proxy localhost:3333
+}
+
+{{ nip_domain }}/distributor-1* {
+    uri strip_prefix /distributor-1
+    reverse_proxy localhost:3334
+}
+
+# newer versions of graphql-server seems to expect this url also
 {{ nip_domain }}/@apollographql/* {
     reverse_proxy localhost:8081
 }
@@ -15,7 +28,32 @@
     reverse_proxy localhost:8081
 }
 
+wss://{{ nip_domain }}/query-node/server* {
+    uri strip_prefix /query-node/server
+    reverse_proxy localhost:8081
+}
+
 {{ nip_domain }}/query-node/indexer* {
     uri strip_prefix /query-node/indexer
     reverse_proxy localhost:4000
 }
+
+{{ nip_domain }}/orion* {
+    uri strip_prefix /orion
+    reverse_proxy localhost:6116
+}
+
+{{ nip_domain }}/member-faucet* {
+    uri strip_prefix /member-faucet
+    reverse_proxy localhost:3002
+}
+
+{{ nip_domain }}/network/config.json {
+    header /* {
+      Access-Control-Allow-Origin *
+      Cache-Control: no-cache
+    }
+    root * /home/ubuntu
+    rewrite * /config.json
+    file_server
+}

+ 1 - 1
devops/aws/roles/rpc/templates/joystream-node.service.j2

@@ -13,7 +13,7 @@ ExecStart=/home/ubuntu/joystream/target/release/joystream-node \
         --pruning archive \
         --ws-max-connections 512 \
         --telemetry-url "wss://telemetry.joystream.org/submit/ 0" \
-        --telemetry-url "wss://telemetry.polkadot.io/submit/ 0"
+        --telemetry-url "wss://telemetry.polkadot.io/submit/ 0" \
         --reserved-nodes \
                 {{ boot_nodes|join(" ") }}
 

+ 1 - 2
devops/aws/setup-admin.yml → devops/aws/setup-build-server.yml

@@ -5,5 +5,4 @@
   hosts: build
 
   roles:
-    - role: admin
-      when: run_on_admin_server|bool
+    - role: build-server

+ 1 - 1
distributor-node/package.json

@@ -11,7 +11,7 @@
     "@apollo/client": "^3.2.5",
     "@elastic/ecs-winston-format": "^1.1.0",
     "@joystream/metadata-protobuf": "^2.0.0",
-    "@joystream/types": "^0.18.0",
+    "@joystream/types": "^0.18.1",
     "@oclif/command": "^1",
     "@oclif/config": "^1",
     "@oclif/plugin-help": "^3",

+ 2 - 1
joystream-node.Dockerfile

@@ -14,13 +14,14 @@ COPY . /joystream
 
 # Build all cargo crates
 # Ensure our tests and linter pass before actual build
-ENV WASM_BUILD_TOOLCHAIN=nightly-2021-02-20
+ARG ALL_PROPOSALS_PARAMETERS_JSON
 ARG TEST_NODE
 RUN echo "TEST_NODE=$TEST_NODE"
 RUN test -n "$TEST_NODE" && sed -i 's/MILLISECS_PER_BLOCK: Moment = 6000/MILLISECS_PER_BLOCK: Moment = 1000/' ./runtime/src/constants.rs; exit 0
 RUN test -n "$TEST_NODE" && sed -i 's/SLOT_DURATION: Moment = 6000/SLOT_DURATION: Moment = 1000/' ./runtime/src/constants.rs; exit 0
 RUN test -n "$TEST_NODE" && export ALL_PROPOSALS_PARAMETERS_JSON="$(cat ./tests/network-tests/proposal-parameters.json)";\
     echo "ALL_PROPOSALS_PARAMETERS_JSON=$ALL_PROPOSALS_PARAMETERS_JSON" && \
+    export WASM_BUILD_TOOLCHAIN=nightly-2021-02-20 && \
     BUILD_DUMMY_WASM_BINARY=1 cargo clippy --release --all -- -D warnings && \
     cargo test --release --all && \
     cargo build --release

+ 1 - 1
node/Cargo.toml

@@ -3,7 +3,7 @@ authors = ['Joystream contributors']
 build = 'build.rs'
 edition = '2018'
 name = 'joystream-node'
-version = '6.0.0'
+version = '6.1.0'
 default-run = "joystream-node"
 
 [[bin]]

+ 0 - 3
query-node/manifest.yml

@@ -897,7 +897,6 @@ mappings:
       handler: referendum_VoteRevealed
     - event: referendum.StakeReleased
       handler: referendum_StakeReleased
-
     # Bounty
     - event: bounty.BountyCreated
       handler: bounty_BountyCreated
@@ -927,13 +926,11 @@ mappings:
       handler: bounty_OracleJudgmentSubmitted
     - event: bounty.WorkEntrantFundsWithdrawn
       handler: bounty_WorkEntrantFundsWithdrawn
-
     # ExtrinsicSuccess event handler - we're using an empty handler just for the purpose of triggering
     # preBlock/postBlock hooks for each block (instead of "catching-up" after some event/tx recognized by processor is fired)
     # ExtrinsicSuccess is emitted at least once per block due to timestamp.set extrinsic
     - event: system.ExtrinsicSuccess
       handler: system_ExtrinsicSuccess
-
   extrinsicHandlers:
     # infer defaults here
     #- extrinsic: Balances.Transfer

+ 1 - 1
query-node/mappings/package.json

@@ -21,7 +21,7 @@
     "@joystream/hydra-common": "3.1.0-alpha.16",
     "@joystream/hydra-db-utils": "3.1.0-alpha.16",
     "@joystream/metadata-protobuf": "^2.0.0",
-    "@joystream/types": "^0.18.0",
+    "@joystream/types": "^0.18.1",
     "@joystream/warthog": "2.41.2",
     "@apollo/client": "^3.2.5"
   },

+ 1 - 1
runtime/Cargo.toml

@@ -4,7 +4,7 @@ edition = '2018'
 name = 'joystream-node-runtime'
 # Follow convention: https://github.com/Joystream/substrate-runtime-joystream/issues/1
 # {Authoring}.{Spec}.{Impl} of the RuntimeVersion
-version = '10.0.0'
+version = '10.1.0'
 
 [dependencies]
 # Third-party dependencies

+ 6 - 6
runtime/src/lib.rs

@@ -95,7 +95,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
     spec_name: create_runtime_str!("joystream-node"),
     impl_name: create_runtime_str!("joystream-node"),
     authoring_version: 10,
-    spec_version: 0,
+    spec_version: 1,
     impl_version: 0,
     apis: crate::runtime_api::EXPORTED_RUNTIME_API_VERSIONS,
     transaction_version: 1,
@@ -507,15 +507,15 @@ pub type CouncilModule = council::Module<Runtime>;
 parameter_types! {
     // referendum parameters
     pub const MaxSaltLength: u64 = 32;
-    pub const VoteStageDuration: BlockNumber = 5;
-    pub const RevealStageDuration: BlockNumber = 7;
+    pub const VoteStageDuration: BlockNumber = 100;
+    pub const RevealStageDuration: BlockNumber = 50;
     pub const MinimumVotingStake: u64 = 10000;
 
     // council parameteres
     pub const MinNumberOfExtraCandidates: u64 = 1;
-    pub const AnnouncingPeriodDuration: BlockNumber = 15;
-    pub const IdlePeriodDuration: BlockNumber = 27;
-    pub const CouncilSize: u64 = 3;
+    pub const AnnouncingPeriodDuration: BlockNumber = 200;
+    pub const IdlePeriodDuration: BlockNumber = 400;
+    pub const CouncilSize: u64 = 5;
     pub const MinCandidateStake: u64 = 11000;
     pub const ElectedMemberRewardPeriod: BlockNumber = 10;
     pub const DefaultBudgetIncrement: u64 = 1000;

+ 55 - 54
runtime/src/proposals_configuration/defaults.rs

@@ -5,7 +5,7 @@ use crate::{Balance, BlockNumber, ProposalParameters};
 // Proposal parameters for the 'Set Max Validator Count' proposal
 pub(crate) fn set_max_validator_count_proposal() -> ProposalParameters<BlockNumber, Balance> {
     ProposalParameters {
-        voting_period: 43200,
+        voting_period: 200,
         grace_period: 0,
         approval_quorum_percentage: 66,
         approval_threshold_percentage: 80,
@@ -19,8 +19,8 @@ pub(crate) fn set_max_validator_count_proposal() -> ProposalParameters<BlockNumb
 // Proposal parameters for the 'Runtime Upgrade' proposal
 pub(crate) fn runtime_upgrade_proposal() -> ProposalParameters<BlockNumber, Balance> {
     ProposalParameters {
-        voting_period: 72000,
-        grace_period: 72000,
+        voting_period: 200,
+        grace_period: 200,
         approval_quorum_percentage: 80,
         approval_threshold_percentage: 100,
         slashing_quorum_percentage: 60,
@@ -33,13 +33,13 @@ pub(crate) fn runtime_upgrade_proposal() -> ProposalParameters<BlockNumber, Bala
 // Proposal parameters for the 'Signal' proposal
 pub(crate) fn signal_proposal() -> ProposalParameters<BlockNumber, Balance> {
     ProposalParameters {
-        voting_period: 72000,
+        voting_period: 200,
         grace_period: 0,
         approval_quorum_percentage: 60,
         approval_threshold_percentage: 80,
         slashing_quorum_percentage: 60,
         slashing_threshold_percentage: 80,
-        required_stake: Some(25000),
+        required_stake: Some(25_000),
         constitutionality: 1,
     }
 }
@@ -47,13 +47,13 @@ pub(crate) fn signal_proposal() -> ProposalParameters<BlockNumber, Balance> {
 // Proposal parameters for the 'Funding Request' proposal
 pub(crate) fn funding_request_proposal() -> ProposalParameters<BlockNumber, Balance> {
     ProposalParameters {
-        voting_period: 72000,
-        grace_period: 14400,
+        voting_period: 200,
+        grace_period: 100,
         approval_quorum_percentage: 60,
         approval_threshold_percentage: 80,
         slashing_quorum_percentage: 60,
         slashing_threshold_percentage: 80,
-        required_stake: Some(25000),
+        required_stake: Some(25_000),
         constitutionality: 1,
     }
 }
@@ -61,7 +61,7 @@ pub(crate) fn funding_request_proposal() -> ProposalParameters<BlockNumber, Bala
 pub(crate) fn create_working_group_lead_opening_proposal(
 ) -> ProposalParameters<BlockNumber, Balance> {
     ProposalParameters {
-        voting_period: 72000,
+        voting_period: 200,
         grace_period: 0,
         approval_quorum_percentage: 60,
         approval_threshold_percentage: 80,
@@ -76,13 +76,13 @@ pub(crate) fn create_working_group_lead_opening_proposal(
 pub(crate) fn fill_working_group_lead_opening_proposal() -> ProposalParameters<BlockNumber, Balance>
 {
     ProposalParameters {
-        voting_period: 43200,
+        voting_period: 200,
         grace_period: 0,
         approval_quorum_percentage: 60,
         approval_threshold_percentage: 75,
         slashing_quorum_percentage: 60,
         slashing_threshold_percentage: 80,
-        required_stake: Some(50000),
+        required_stake: Some(50_000),
         constitutionality: 1,
     }
 }
@@ -90,13 +90,13 @@ pub(crate) fn fill_working_group_lead_opening_proposal() -> ProposalParameters<B
 // Proposal parameters for the 'Update Working Group Budget' proposal
 pub(crate) fn update_working_group_budget_proposal() -> ProposalParameters<BlockNumber, Balance> {
     ProposalParameters {
-        voting_period: 43200,
+        voting_period: 200,
         grace_period: 0,
         approval_quorum_percentage: 60,
         approval_threshold_percentage: 75,
         slashing_quorum_percentage: 60,
         slashing_threshold_percentage: 80,
-        required_stake: Some(50000),
+        required_stake: Some(50_000),
         constitutionality: 1,
     }
 }
@@ -105,13 +105,13 @@ pub(crate) fn update_working_group_budget_proposal() -> ProposalParameters<Block
 pub(crate) fn decrease_working_group_lead_stake_proposal(
 ) -> ProposalParameters<BlockNumber, Balance> {
     ProposalParameters {
-        voting_period: 43200,
+        voting_period: 200,
         grace_period: 0,
         approval_quorum_percentage: 60,
         approval_threshold_percentage: 75,
         slashing_quorum_percentage: 60,
         slashing_threshold_percentage: 80,
-        required_stake: Some(50000),
+        required_stake: Some(50_000),
         constitutionality: 1,
     }
 }
@@ -119,13 +119,13 @@ pub(crate) fn decrease_working_group_lead_stake_proposal(
 // Proposal parameters for the 'Slash Working Group Lead' proposal
 pub fn slash_working_group_lead_proposal() -> ProposalParameters<BlockNumber, Balance> {
     ProposalParameters {
-        voting_period: 43200,
+        voting_period: 200,
         grace_period: 0,
         approval_quorum_percentage: 60,
         approval_threshold_percentage: 75,
         slashing_quorum_percentage: 60,
         slashing_threshold_percentage: 80,
-        required_stake: Some(50000),
+        required_stake: Some(50_000),
         constitutionality: 1,
     }
 }
@@ -133,13 +133,13 @@ pub fn slash_working_group_lead_proposal() -> ProposalParameters<BlockNumber, Ba
 // Proposal parameters for the 'Set Working Group Lead Reward' proposal
 pub(crate) fn set_working_group_lead_reward_proposal() -> ProposalParameters<BlockNumber, Balance> {
     ProposalParameters {
-        voting_period: 43200,
+        voting_period: 200,
         grace_period: 0,
         approval_quorum_percentage: 60,
         approval_threshold_percentage: 75,
         slashing_quorum_percentage: 60,
         slashing_threshold_percentage: 80,
-        required_stake: Some(50000),
+        required_stake: Some(50_000),
         constitutionality: 1,
     }
 }
@@ -147,7 +147,7 @@ pub(crate) fn set_working_group_lead_reward_proposal() -> ProposalParameters<Blo
 // Proposal parameters for the 'Terminate Working Group Lead' proposal
 pub(crate) fn terminate_working_group_lead_proposal() -> ProposalParameters<BlockNumber, Balance> {
     ProposalParameters {
-        voting_period: 72200,
+        voting_period: 200,
         grace_period: 0,
         approval_quorum_percentage: 66,
         approval_threshold_percentage: 80,
@@ -161,14 +161,14 @@ pub(crate) fn terminate_working_group_lead_proposal() -> ProposalParameters<Bloc
 // Proposal parameters for the 'Amend Constitution' proposal
 pub(crate) fn amend_constitution_proposal() -> ProposalParameters<BlockNumber, Balance> {
     ProposalParameters {
-        voting_period: 72200,
-        grace_period: 72200,
+        voting_period: 200,
+        grace_period: 100,
         approval_quorum_percentage: 80,
         approval_threshold_percentage: 100,
         slashing_quorum_percentage: 60,
         slashing_threshold_percentage: 80,
         required_stake: Some(1_000_000),
-        constitutionality: 1,
+        constitutionality: 2,
     }
 }
 
@@ -176,13 +176,13 @@ pub(crate) fn amend_constitution_proposal() -> ProposalParameters<BlockNumber, B
 pub(crate) fn cancel_working_group_lead_opening_proposal(
 ) -> ProposalParameters<BlockNumber, Balance> {
     ProposalParameters {
-        voting_period: 43200,
+        voting_period: 200,
         grace_period: 0,
         approval_quorum_percentage: 60,
         approval_threshold_percentage: 75,
         slashing_quorum_percentage: 60,
         slashing_threshold_percentage: 80,
-        required_stake: Some(50000),
+        required_stake: Some(50_000),
         constitutionality: 1,
     }
 }
@@ -190,13 +190,13 @@ pub(crate) fn cancel_working_group_lead_opening_proposal(
 // Proposal parameters for the 'Set Membership Price' proposal
 pub(crate) fn set_membership_price_proposal() -> ProposalParameters<BlockNumber, Balance> {
     ProposalParameters {
-        voting_period: 43200,
-        grace_period: 14400,
+        voting_period: 200,
+        grace_period: 100,
         approval_quorum_percentage: 60,
         approval_threshold_percentage: 75,
         slashing_quorum_percentage: 60,
         slashing_threshold_percentage: 80,
-        required_stake: Some(50000),
+        required_stake: Some(50_000),
         constitutionality: 1,
     }
 }
@@ -204,8 +204,8 @@ pub(crate) fn set_membership_price_proposal() -> ProposalParameters<BlockNumber,
 // Proposal parameters for the 'Set Council Budget Increment' proposal
 pub(crate) fn set_council_budget_increment_proposal() -> ProposalParameters<BlockNumber, Balance> {
     ProposalParameters {
-        voting_period: 72000,
-        grace_period: 43200,
+        voting_period: 200,
+        grace_period: 100,
         approval_quorum_percentage: 66,
         approval_threshold_percentage: 80,
         slashing_quorum_percentage: 60,
@@ -218,14 +218,14 @@ pub(crate) fn set_council_budget_increment_proposal() -> ProposalParameters<Bloc
 // Proposal parameters for the 'Set Councilor Reward' proposal
 pub(crate) fn set_councilor_reward_proposal() -> ProposalParameters<BlockNumber, Balance> {
     ProposalParameters {
-        voting_period: 72000,
-        grace_period: 201600, // A council term
+        voting_period: 200,
+        grace_period: 100, // A council term
         approval_quorum_percentage: 66,
         approval_threshold_percentage: 80,
         slashing_quorum_percentage: 60,
         slashing_threshold_percentage: 80,
         required_stake: Some(200_000),
-        constitutionality: 1,
+        constitutionality: 2,
     }
 }
 
@@ -233,8 +233,8 @@ pub(crate) fn set_councilor_reward_proposal() -> ProposalParameters<BlockNumber,
 pub(crate) fn set_initial_invitation_balance_proposal() -> ProposalParameters<BlockNumber, Balance>
 {
     ProposalParameters {
-        voting_period: 72000,
-        grace_period: 43200,
+        voting_period: 200,
+        grace_period: 100,
         approval_quorum_percentage: 60,
         approval_threshold_percentage: 75,
         slashing_quorum_percentage: 60,
@@ -249,8 +249,8 @@ pub(crate) fn set_initial_invitation_balance_proposal() -> ProposalParameters<Bl
 pub(crate) fn set_membership_lead_invitation_quota_proposal(
 ) -> ProposalParameters<BlockNumber, Balance> {
     ProposalParameters {
-        voting_period: 72000,
-        grace_period: 43200,
+        voting_period: 200,
+        grace_period: 100,
         approval_quorum_percentage: 60,
         approval_threshold_percentage: 75,
         slashing_quorum_percentage: 60,
@@ -263,8 +263,8 @@ pub(crate) fn set_membership_lead_invitation_quota_proposal(
 // Proposal parameters for the 'Set Referral Cut' proposal
 pub(crate) fn set_referral_cut_proposal() -> ProposalParameters<BlockNumber, Balance> {
     ProposalParameters {
-        voting_period: 43200,
-        grace_period: 14400,
+        voting_period: 200,
+        grace_period: 100,
         approval_quorum_percentage: 60,
         approval_threshold_percentage: 75,
         slashing_quorum_percentage: 60,
@@ -277,8 +277,8 @@ pub(crate) fn set_referral_cut_proposal() -> ProposalParameters<BlockNumber, Bal
 // Proposal parameters for the 'Set Initial Invitation Count' proposal
 pub(crate) fn set_invitation_count_proposal() -> ProposalParameters<BlockNumber, Balance> {
     ProposalParameters {
-        voting_period: 72000,
-        grace_period: 43200,
+        voting_period: 200,
+        grace_period: 100,
         approval_quorum_percentage: 60,
         approval_threshold_percentage: 75,
         slashing_quorum_percentage: 60,
@@ -291,13 +291,13 @@ pub(crate) fn set_invitation_count_proposal() -> ProposalParameters<BlockNumber,
 // Proposal parameters for the 'Create Blog Post' proposal
 pub(crate) fn create_blog_post_proposal() -> ProposalParameters<BlockNumber, Balance> {
     ProposalParameters {
-        voting_period: 72000,
-        grace_period: 14400,
+        voting_period: 200,
+        grace_period: 100,
         approval_quorum_percentage: 60,
         approval_threshold_percentage: 80,
         slashing_quorum_percentage: 60,
         slashing_threshold_percentage: 80,
-        required_stake: Some(25000),
+        required_stake: Some(25_000),
         constitutionality: 1,
     }
 }
@@ -305,13 +305,13 @@ pub(crate) fn create_blog_post_proposal() -> ProposalParameters<BlockNumber, Bal
 // Proposal parameters for the 'Edit Blog Post' proposal
 pub(crate) fn edit_blog_post_proposal() -> ProposalParameters<BlockNumber, Balance> {
     ProposalParameters {
-        voting_period: 72000,
-        grace_period: 14400,
+        voting_period: 200,
+        grace_period: 100,
         approval_quorum_percentage: 60,
         approval_threshold_percentage: 80,
         slashing_quorum_percentage: 60,
         slashing_threshold_percentage: 80,
-        required_stake: Some(25000),
+        required_stake: Some(25_000),
         constitutionality: 1,
     }
 }
@@ -319,13 +319,13 @@ pub(crate) fn edit_blog_post_proposal() -> ProposalParameters<BlockNumber, Balan
 // Proposal parameters for the 'Lock Blog Post' proposal
 pub(crate) fn lock_blog_post_proposal() -> ProposalParameters<BlockNumber, Balance> {
     ProposalParameters {
-        voting_period: 72000,
-        grace_period: 14400,
+        voting_period: 200,
+        grace_period: 100,
         approval_quorum_percentage: 60,
         approval_threshold_percentage: 80,
         slashing_quorum_percentage: 60,
         slashing_threshold_percentage: 80,
-        required_stake: Some(25000),
+        required_stake: Some(25_000),
         constitutionality: 1,
     }
 }
@@ -333,13 +333,13 @@ pub(crate) fn lock_blog_post_proposal() -> ProposalParameters<BlockNumber, Balan
 // Proposal parameters for the 'Unlock Blog Post' proposal
 pub(crate) fn unlock_blog_post_proposal() -> ProposalParameters<BlockNumber, Balance> {
     ProposalParameters {
-        voting_period: 72000,
-        grace_period: 14400,
+        voting_period: 200,
+        grace_period: 100,
         approval_quorum_percentage: 60,
         approval_threshold_percentage: 80,
         slashing_quorum_percentage: 60,
         slashing_threshold_percentage: 80,
-        required_stake: Some(25000),
+        required_stake: Some(25_000),
         constitutionality: 1,
     }
 }
@@ -347,7 +347,8 @@ pub(crate) fn unlock_blog_post_proposal() -> ProposalParameters<BlockNumber, Bal
 // Proposal parameters for the 'Veto Proposal' proposal
 pub(crate) fn veto_proposal_proposal() -> ProposalParameters<BlockNumber, Balance> {
     ProposalParameters {
-        voting_period: 72200, // The longest grace period
+        // Doesn't make sense to be longer than longest grace period of all other proposals?
+        voting_period: 200,
         grace_period: 0,
         approval_quorum_percentage: 75,
         approval_threshold_percentage: 80,

+ 12 - 9
runtime/src/proposals_configuration/mod.rs

@@ -4,10 +4,10 @@
 //! to be the integration tests.
 //!
 //! The whole parameter set is initialized only once by deserializing JSON from the environment variable
-//! "ALL_PROPOSALS_PARAMETERS_JSON". If it doesn't exists or contains invalid or empty JSON then
-//! the default parameters are returned. If some proposal section of the JSON file contains only
-//! partial object definition - default values are returned as missing fields.
-//!
+//! "ALL_PROPOSALS_PARAMETERS_JSON". If it doesn't exists the default parameters are returned.
+//! If some proposal section of the JSON file contains only
+//! partial object definition - default values are returned for missing fields.
+//! If passed JSON is invalid or expected numeric value is not a number it will panic!
 
 use crate::{Balance, BlockNumber, ProposalParameters};
 use frame_support::dispatch::Vec;
@@ -105,17 +105,20 @@ lazy_static! {
 #[allow(clippy::match_wild_err_arm)]
 // Composes AllProposalsParameters object from the JSON string.
 // It gets the JSON string from the environment variable and tries to parse it.
-// On error and any missing values it gets default values.
+// On error it will panic!
 fn get_all_proposals_parameters_objects() -> AllProposalsParameters {
     let json_str: Option<&'static str> = option_env!("ALL_PROPOSALS_PARAMETERS_JSON");
 
+    // Handle undefined variable (null) and variable set to empty string the same to work cross platform.
+    if json_str.map_or(true, str::is_empty) {
+        return default_parameters();
+    }
+
     json_str
         .map(lite_json::parse_json)
         .map(|res| match res {
             Ok(json) => Some(json),
-            Err(_) => {
-                panic!("Invalid JSON with proposals parameters provided.");
-            }
+            Err(_) => panic!("Invalid JSON with proposals parameters provided."),
         })
         .flatten()
         .map(convert_json_object_to_proposal_parameters)
@@ -278,7 +281,7 @@ fn extract_proposal_parameters(
     params
 }
 
-// Extracts a specific numeric parameter from the parsed JSON object.
+// Extracts a specific numeric parameter from the parsed JSON object. Will panic if expected value is not numeric.
 fn extract_numeric_parameter(
     json_object: &JsonValue,
     parameter_name: &'static str,

+ 3 - 237
runtime/src/proposals_configuration/tests.rs

@@ -1,239 +1,5 @@
-use crate::{Balance, BlockNumber, ProposalParameters};
-
-fn default_proposal_parameters() -> ProposalParameters<BlockNumber, Balance> {
-    ProposalParameters {
-        voting_period: 1,
-        grace_period: 2,
-        approval_quorum_percentage: 3,
-        approval_threshold_percentage: 4,
-        slashing_quorum_percentage: 5,
-        slashing_threshold_percentage: 6,
-        required_stake: Some(7),
-        constitutionality: 8,
-    }
-}
-
-// Enable during the conditional compilation tests.
-#[test]
-#[ignore]
-fn proposal_parameters_are_initialized_max_validators() {
-    let actual_params = super::SetMaxValidatorCountProposalParameters::get();
-
-    assert_eq!(default_proposal_parameters(), actual_params);
-}
-
-// Enable during the conditional compilation tests.
-#[test]
-#[ignore]
-fn proposal_parameters_are_initialized_runtime_upgrade() {
-    let actual_params = super::RuntimeUpgradeProposalParameters::get();
-
-    assert_eq!(default_proposal_parameters(), actual_params);
-}
-
-// Enable during the conditional compilation tests.
-#[test]
-#[ignore]
-fn proposal_parameters_are_initialized_signal() {
-    let actual_params = super::SignalProposalParameters::get();
-
-    assert_eq!(default_proposal_parameters(), actual_params);
-}
-
-// Enable during the conditional compilation tests.
-#[test]
-#[ignore]
-fn proposal_parameters_are_initialized_funding_request() {
-    let actual_params = super::FundingRequestProposalParameters::get();
-
-    assert_eq!(default_proposal_parameters(), actual_params);
-}
-
-// Enable during the conditional compilation tests.
-#[test]
-#[ignore]
-fn proposal_parameters_are_initialized_create_wg_lead_opening() {
-    let actual_params = super::CreateWorkingGroupLeadOpeningProposalParameters::get();
-
-    assert_eq!(default_proposal_parameters(), actual_params);
-}
-
-// Enable during the conditional compilation tests.
-#[test]
-#[ignore]
-fn proposal_parameters_are_initialized_wg_fill_lead_opening() {
-    let actual_params = super::FillWorkingGroupLeadOpeningProposalParameters::get();
-
-    assert_eq!(default_proposal_parameters(), actual_params);
-}
-
-// Enable during the conditional compilation tests.
-#[test]
-#[ignore]
-fn proposal_parameters_are_initialized_update_budget() {
-    let actual_params = super::UpdateWorkingGroupBudgetProposalParameters::get();
-
-    assert_eq!(default_proposal_parameters(), actual_params);
-}
-
-// Enable during the conditional compilation tests.
-#[test]
-#[ignore]
-fn proposal_parameters_are_initialized_decrease_wg_lead_stake() {
-    let actual_params = super::DecreaseWorkingGroupLeadStakeProposalParameters::get();
-
-    assert_eq!(default_proposal_parameters(), actual_params);
-}
-
-// Enable during the conditional compilation tests.
-#[test]
-#[ignore]
-fn proposal_parameters_are_initialized_slash_wg_lead() {
-    let actual_params = super::SlashWorkingGroupLeadProposalParameters::get();
-
-    assert_eq!(default_proposal_parameters(), actual_params);
-}
-
-// Enable during the conditional compilation tests.
-#[test]
-#[ignore]
-fn proposal_parameters_are_initialized_set_wg_lead_reward() {
-    let actual_params = super::SetWorkingGroupLeadRewardProposalParameters::get();
-
-    assert_eq!(default_proposal_parameters(), actual_params);
-}
-
-// Enable during the conditional compilation tests.
-#[test]
-#[ignore]
-fn proposal_parameters_are_initialized_terminate_wg_lead() {
-    let actual_params = super::TerminateWorkingGroupLeadProposalParameters::get();
-
-    assert_eq!(default_proposal_parameters(), actual_params);
-}
-
-// Enable during the conditional compilation tests.
-#[test]
-#[ignore]
-fn proposal_parameters_are_initialized_amend_constitution() {
-    let actual_params = super::AmendConstitutionProposalParameters::get();
-
-    assert_eq!(default_proposal_parameters(), actual_params);
-}
-
-// Enable during the conditional compilation tests.
-#[test]
-#[ignore]
-fn proposal_parameters_are_initialized_cancel_wg_lead_opening() {
-    let actual_params = super::CancelWorkingGroupLeadOpeningProposalParameters::get();
-
-    assert_eq!(default_proposal_parameters(), actual_params);
-}
-
-// Enable during the conditional compilation tests.
-#[test]
-#[ignore]
-fn proposal_parameters_are_initialized_set_membership_price() {
-    let actual_params = super::SetMembershipPriceProposalParameters::get();
-
-    assert_eq!(default_proposal_parameters(), actual_params);
-}
-
-// Enable during the conditional compilation tests.
-#[test]
-#[ignore]
-fn proposal_parameters_are_initialized_set_council_budget_increment() {
-    let actual_params = super::SetCouncilBudgetIncrementProposalParameters::get();
-
-    assert_eq!(default_proposal_parameters(), actual_params);
-}
-
-// Enable during the conditional compilation tests.
-#[test]
-#[ignore]
-fn proposal_parameters_are_initialized_set_councilor_reward() {
-    let actual_params = super::SetCouncilorRewardProposalParameters::get();
-
-    assert_eq!(default_proposal_parameters(), actual_params);
-}
-
-// Enable during the conditional compilation tests.
-#[test]
-#[ignore]
-fn proposal_parameters_are_initialized_set_initial_invitation_balance() {
-    let actual_params = super::SetInitialInvitationBalanceProposalParameters::get();
-
-    assert_eq!(default_proposal_parameters(), actual_params);
-}
-
-// Enable during the conditional compilation tests.
-#[test]
-#[ignore]
-fn proposal_parameters_are_initialized_set_membership_invitaiton_quota() {
-    let actual_params = super::SetMembershipLeadInvitationQuotaProposalParameters::get();
-
-    assert_eq!(default_proposal_parameters(), actual_params);
-}
-
-// Enable during the conditional compilation tests.
-#[test]
-#[ignore]
-fn proposal_parameters_are_initialized_set_referral_cut() {
-    let actual_params = super::SetReferralCutProposalParameters::get();
-
-    assert_eq!(default_proposal_parameters(), actual_params);
-}
-
-// Enable during the conditional compilation tests.
-#[test]
-#[ignore]
-fn proposal_parameters_are_initialized_set_invitation_count() {
-    let actual_params = super::SetInvitationCountProposalParameters::get();
-
-    assert_eq!(default_proposal_parameters(), actual_params);
-}
-
-// Enable during the conditional compilation tests.
-#[test]
-#[ignore]
-fn proposal_parameters_are_initialized_create_blog_post_proposal() {
-    let actual_params = super::CreateBlogPostProposalParameters::get();
-
-    assert_eq!(default_proposal_parameters(), actual_params);
-}
-
-// Enable during the conditional compilation tests.
-#[test]
-#[ignore]
-fn proposal_parameters_are_initialized_edit_blog_post_proposal() {
-    let actual_params = super::EditBlogPostProoposalParamters::get();
-
-    assert_eq!(default_proposal_parameters(), actual_params);
-}
-
-// Enable during the conditional compilation tests.
-#[test]
-#[ignore]
-fn proposal_parameters_are_initialized_lock_blog_post_proposal() {
-    let actual_params = super::LockBlogPostProposalParameters::get();
-
-    assert_eq!(default_proposal_parameters(), actual_params);
-}
-
-// Enable during the conditional compilation tests.
-#[test]
-#[ignore]
-fn proposal_parameters_are_initialized_unlock_blog_post_proposal() {
-    let actual_params = super::UnlockBlogPostProposalParameters::get();
-
-    assert_eq!(default_proposal_parameters(), actual_params);
-}
-
-// Enable during the conditional compilation tests.
 #[test]
-#[ignore]
-fn proposal_parameters_are_initialized_veto_proposal_proposal() {
-    let actual_params = super::VetoProposalProposalParameters::get();
-
-    assert_eq!(default_proposal_parameters(), actual_params);
+fn proposal_parameters() {
+    // Reading all proposal parameters and look for invalid JSON
+    super::get_all_proposals_parameters_objects();
 }

+ 109 - 43
runtime/src/tests/mod.rs

@@ -1,15 +1,16 @@
 //! The Joystream Substrate Node runtime integration tests.
-
 #![cfg(test)]
-#[macro_use]
 
+#[macro_use]
 mod proposals_integration;
+
 mod locks;
 
 // Temporary commented for Olympia: https://github.com/Joystream/joystream/issues/3237
 // TODO: Restore after the Olympia release
 //mod fee_tests;
 
+use crate::primitives::MemberId;
 use crate::{BlockNumber, ReferendumInstance, Runtime};
 use frame_support::traits::{Currency, OnFinalize, OnInitialize};
 use frame_system::RawOrigin;
@@ -37,31 +38,52 @@ pub(crate) fn initial_test_ext() -> sp_io::TestExternalities {
     t.into()
 }
 
-fn get_account_membership(account: AccountId32, i: usize) -> u64 {
-    let member_id = i as u64;
-    if Membership::membership(member_id).controller_account != account {
-        insert_member(account.clone());
-        set_staking_account(account.clone(), account, member_id);
-    }
-
-    member_id
+// Simple unique account derived from member id
+pub(crate) fn account_from_member_id(member_id: MemberId) -> AccountId32 {
+    let b1: u8 = ((member_id >> 24) & 0xff) as u8;
+    let b2: u8 = ((member_id >> 16) & 0xff) as u8;
+    let b3: u8 = ((member_id >> 8) & 0xff) as u8;
+    let b4: u8 = (member_id & 0xff) as u8;
+    let mut account: [u8; 32] = AccountId32::default().into();
+    account[0] = b1;
+    account[1] = b2;
+    account[2] = b3;
+    account[3] = b4;
+    account.into()
 }
 
-// council = Vec<(ID - membership handle helper, ACCOUNT_ID)>
-pub(crate) fn elect_council(council: Vec<(u8, AccountId32)>, cycle_id: u64) {
-    let mut voters = Vec::<AccountId32>::new();
+// Create a new set of members
+pub(crate) fn create_new_members(count: u64) -> Vec<MemberId> {
+    // get next member id (u64)
+    let first_member_id = Membership::members_created();
+
+    (0..count)
+        .map(|i| {
+            let member_id = first_member_id + i as u64;
+            let account_id = account_from_member_id(member_id);
+            insert_member(account_id.clone());
+            set_staking_account(account_id.clone(), account_id, member_id);
+            member_id
+        })
+        .collect()
+}
 
+pub(crate) fn setup_new_council(cycle_id: u64) {
+    let council_size = <Runtime as council::Trait>::CouncilSize::get();
+    let num_extra_candidates = <Runtime as council::Trait>::MinNumberOfExtraCandidates::get() + 1;
     let councilor_stake: u128 = <Runtime as council::Trait>::MinCandidateStake::get().into();
-    let extra_candidates = <Runtime as council::Trait>::MinNumberOfExtraCandidates::get() + 1;
-    let mut council_member_ids = Vec::new();
 
-    for (i, councilor) in council.iter() {
-        increase_total_balance_issuance_using_account_id(
-            councilor.clone().into(),
-            councilor_stake + 1,
-        );
+    // council members that will be elected
+    let council_member_ids = create_new_members(council_size);
+    // one new voter for each candidate that will be elected
+    let voter_ids = create_new_members(council_size);
+    // additional candidates that will receive no votes
+    let extra_candidate_ids = create_new_members(num_extra_candidates);
+
+    for member_id in council_member_ids.clone() {
+        let councilor = account_from_member_id(member_id);
+        increase_total_balance_issuance_using_account_id(councilor.clone(), councilor_stake + 1);
 
-        let member_id = get_account_membership(councilor.clone(), *i as usize);
         Council::announce_candidacy(
             RawOrigin::Signed(councilor.clone()).into(),
             member_id,
@@ -70,26 +92,13 @@ pub(crate) fn elect_council(council: Vec<(u8, AccountId32)>, cycle_id: u64) {
             councilor_stake,
         )
         .unwrap();
-        // Make sure to use different voters in each election cycle to prevent problems with
-        // staking
-        voters.push(
-            [(council.len() as u8 + extra_candidates as u8) * (cycle_id as u8 + 1) + *i; 32].into(),
-        );
-        council_member_ids.push(member_id);
     }
 
-    let council_index = (council.clone().last().unwrap().0 + 10) as usize;
-    for i in council_index..(council_index + extra_candidates as usize) {
-        let extra_councilor: AccountId32 = [i as u8; 32].into();
+    for member_id in extra_candidate_ids.clone() {
+        let extra_councilor = account_from_member_id(member_id);
 
-        let member_id = get_account_membership(extra_councilor.clone(), i);
-        Council::release_candidacy_stake(
-            RawOrigin::Signed(extra_councilor.clone()).into(),
-            member_id,
-        )
-        .unwrap_or_else(|err| assert_eq!(err, council::Error::NoStake));
         increase_total_balance_issuance_using_account_id(
-            extra_councilor.clone().into(),
+            extra_councilor.clone(),
             councilor_stake + 1,
         );
         Council::announce_candidacy(
@@ -107,14 +116,16 @@ pub(crate) fn elect_council(council: Vec<(u8, AccountId32)>, cycle_id: u64) {
 
     let voter_stake: u128 =
         <Runtime as referendum::Trait<ReferendumInstance>>::MinimumStake::get().into();
-    for (i, voter) in voters.iter().enumerate() {
-        increase_total_balance_issuance_using_account_id(voter.clone().into(), voter_stake + 1);
+
+    for (i, member_id) in voter_ids.clone().iter().enumerate() {
+        let voter = account_from_member_id(*member_id);
+        increase_total_balance_issuance_using_account_id(voter.clone(), voter_stake + 1);
 
         let commitment = Referendum::calculate_commitment(
-            voter.into(),
+            &voter,
             &[0u8],
             &cycle_id,
-            &council_member_ids[i],
+            &council_member_ids[i as usize],
         );
 
         Referendum::vote(
@@ -131,11 +142,12 @@ pub(crate) fn elect_council(council: Vec<(u8, AccountId32)>, cycle_id: u64) {
             + <Runtime as referendum::Trait<ReferendumInstance>>::VoteStageDuration::get(),
     );
 
-    for (i, voter) in voters.iter().enumerate() {
+    for (i, member_id) in voter_ids.iter().enumerate() {
+        let voter = account_from_member_id(*member_id);
         Referendum::reveal_vote(
             RawOrigin::Signed(voter.clone()).into(),
             vec![0u8],
-            council_member_ids[i].clone(),
+            council_member_ids[i as usize].clone(),
         )
         .unwrap();
     }
@@ -237,3 +249,57 @@ pub(crate) fn increase_total_balance_issuance_using_account_id(
     }
     assert_eq!(Balances::total_issuance(), initial_balance + balance);
 }
+
+pub(crate) fn max_proposal_stake() -> u128 {
+    let mut stakes = vec![];
+    stakes.push(<Runtime as proposals_codex::Trait>::SetMaxValidatorCountProposalParameters::get());
+    stakes.push(<Runtime as proposals_codex::Trait>::RuntimeUpgradeProposalParameters::get());
+    stakes.push(<Runtime as proposals_codex::Trait>::SignalProposalParameters::get());
+    stakes.push(<Runtime as proposals_codex::Trait>::FundingRequestProposalParameters::get());
+    stakes.push(
+        <Runtime as proposals_codex::Trait>::CreateWorkingGroupLeadOpeningProposalParameters::get(),
+    );
+    stakes.push(
+        <Runtime as proposals_codex::Trait>::FillWorkingGroupLeadOpeningProposalParameters::get(),
+    );
+    stakes.push(
+        <Runtime as proposals_codex::Trait>::UpdateWorkingGroupBudgetProposalParameters::get(),
+    );
+    stakes.push(
+        <Runtime as proposals_codex::Trait>::DecreaseWorkingGroupLeadStakeProposalParameters::get(),
+    );
+    stakes
+        .push(<Runtime as proposals_codex::Trait>::SlashWorkingGroupLeadProposalParameters::get());
+    stakes.push(
+        <Runtime as proposals_codex::Trait>::SetWorkingGroupLeadRewardProposalParameters::get(),
+    );
+    stakes.push(
+        <Runtime as proposals_codex::Trait>::TerminateWorkingGroupLeadProposalParameters::get(),
+    );
+    stakes.push(<Runtime as proposals_codex::Trait>::AmendConstitutionProposalParameters::get());
+    stakes.push(
+        <Runtime as proposals_codex::Trait>::CancelWorkingGroupLeadOpeningProposalParameters::get(),
+    );
+    stakes.push(<Runtime as proposals_codex::Trait>::SetMembershipPriceProposalParameters::get());
+    stakes.push(
+        <Runtime as proposals_codex::Trait>::SetCouncilBudgetIncrementProposalParameters::get(),
+    );
+    stakes.push(<Runtime as proposals_codex::Trait>::SetCouncilorRewardProposalParameters::get());
+    stakes.push(
+        <Runtime as proposals_codex::Trait>::SetInitialInvitationBalanceProposalParameters::get(),
+    );
+    stakes.push(<Runtime as proposals_codex::Trait>::SetInvitationCountProposalParameters::get());
+    stakes.push(<Runtime as proposals_codex::Trait>::SetMembershipLeadInvitationQuotaProposalParameters::get());
+    stakes.push(<Runtime as proposals_codex::Trait>::SetReferralCutProposalParameters::get());
+    stakes.push(<Runtime as proposals_codex::Trait>::CreateBlogPostProposalParameters::get());
+    stakes.push(<Runtime as proposals_codex::Trait>::EditBlogPostProoposalParamters::get());
+    stakes.push(<Runtime as proposals_codex::Trait>::LockBlogPostProposalParameters::get());
+    stakes.push(<Runtime as proposals_codex::Trait>::UnlockBlogPostProposalParameters::get());
+    stakes.push(<Runtime as proposals_codex::Trait>::VetoProposalProposalParameters::get());
+
+    stakes
+        .iter()
+        .map(|p| p.required_stake.unwrap_or(0))
+        .max_by(|s1, s2| s1.cmp(s2))
+        .unwrap()
+}

File diff suppressed because it is too large
+ 232 - 234
runtime/src/tests/proposals_integration/mod.rs


+ 20 - 29
runtime/src/tests/proposals_integration/working_group_proposals.rs

@@ -490,8 +490,8 @@ fn run_create_add_working_group_leader_opening_proposal_execution_succeeds<
     <T as common::membership::MembershipTypes>::MemberId: From<u64>,
 {
     initial_test_ext().execute_with(|| {
-        let member_id: MemberId = 1;
-        let account_id: [u8; 32] = [member_id as u8; 32];
+        let member_id: MemberId = create_new_members(1)[0];
+        let account_id: [u8; 32] = account_from_member_id(member_id).into();
 
         let next_opening_id = WorkingGroupInstance::<T, I>::next_opening_id();
 
@@ -596,8 +596,8 @@ fn run_create_fill_working_group_leader_opening_proposal_execution_succeeds<
     common::MemberId<T>: From<u64>,
 {
     initial_test_ext().execute_with(|| {
-        let member_id: u64 = 14;
-        let account_id: [u8; 32] = [member_id as u8; 32];
+        let member_id: u64 = create_new_members(1)[0];
+        let account_id: [u8; 32] = account_from_member_id(member_id).into();
 
         increase_total_balance_issuance_using_account_id(account_id.clone().into(), 1_500_000);
 
@@ -755,10 +755,8 @@ fn run_create_decrease_group_leader_stake_proposal_execution_succeeds<
     <T as pallet_balances::Trait>::Balance: From<u128>,
 {
     initial_test_ext().execute_with(|| {
-        // Don't use the same member id as a councilor, can lead to conflicting stakes
-        let member_id: MemberId = 14;
-
-        let account_id: [u8; 32] = [member_id as u8; 32];
+        let member_id: u64 = create_new_members(1)[0];
+        let account_id: [u8; 32] = account_from_member_id(member_id).into();
         let stake_amount: Balance = 10_000;
 
         increase_total_balance_issuance_using_account_id(account_id.into(), 1_500_000);
@@ -937,10 +935,8 @@ fn run_create_slash_group_leader_stake_proposal_execution_succeeds<
     <T as pallet_balances::Trait>::Balance: From<u128>,
 {
     initial_test_ext().execute_with(|| {
-        // Don't use the same member id as a councilor, can lead to conflicting stakes
-        let member_id: MemberId = 14;
-
-        let account_id: [u8; 32] = [member_id as u8; 32];
+        let member_id: u64 = create_new_members(1)[0];
+        let account_id: [u8; 32] = account_from_member_id(member_id).into();
         let stake_amount: Balance = 10_000;
 
         let stake_policy = working_group::StakePolicy {
@@ -1107,13 +1103,12 @@ fn run_create_set_working_group_mint_capacity_proposal_execution_succeeds<
     working_group::BalanceOf<T>: From<u128>,
 {
     initial_test_ext().execute_with(|| {
-        let member_id: MemberId = 1;
-        let account_id: [u8; 32] = [member_id as u8; 32];
+        setup_new_council(0);
 
-        let mint_capacity = 999999;
+        let member_id: MemberId = create_new_members(1)[0];
+        let account_id: [u8; 32] = account_from_member_id(member_id).into();
 
-        setup_members(15);
-        setup_council(0);
+        let mint_capacity = 999999;
 
         increase_total_balance_issuance_using_account_id(account_id.clone().into(), 1_500_000);
 
@@ -1147,8 +1142,8 @@ fn run_create_syphon_working_group_mint_capacity_proposal_execution_succeeds<
     working_group::BalanceOf<T>: From<u128>,
 {
     initial_test_ext().execute_with(|| {
-        let member_id: MemberId = 14;
-        let account_id: [u8; 32] = [member_id as u8; 32];
+        let member_id: u64 = create_new_members(1)[0];
+        let account_id: [u8; 32] = account_from_member_id(member_id).into();
 
         increase_total_balance_issuance_using_account_id(account_id.clone().into(), 1_500_000);
 
@@ -1355,8 +1350,8 @@ fn run_create_set_group_leader_reward_proposal_execution_succeeds<
     working_group::BalanceOf<T>: From<u128>,
 {
     initial_test_ext().execute_with(|| {
-        let member_id: MemberId = 14;
-        let account_id: [u8; 32] = [member_id as u8; 32];
+        let member_id: u64 = create_new_members(1)[0];
+        let account_id: [u8; 32] = account_from_member_id(member_id).into();
 
         increase_total_balance_issuance_using_account_id(account_id.clone().into(), 1_500_000);
 
@@ -1531,10 +1526,8 @@ fn run_create_terminate_group_leader_role_proposal_execution_succeeds<
     <T as pallet_balances::Trait>::Balance: From<u128>,
 {
     initial_test_ext().execute_with(|| {
-        // Don't use the same member id as a councilor, can lead to conflicting stakes
-        let member_id: MemberId = 14;
-
-        let account_id: [u8; 32] = [member_id as u8; 32];
+        let member_id: u64 = create_new_members(1)[0];
+        let account_id: [u8; 32] = account_from_member_id(member_id).into();
         let stake_amount = 100_000_u128;
 
         let stake_policy = working_group::StakePolicy {
@@ -1708,10 +1701,8 @@ fn run_create_terminate_group_leader_role_proposal_with_slashing_execution_succe
     <T as pallet_balances::Trait>::Balance: From<u128>,
 {
     initial_test_ext().execute_with(|| {
-        // Don't use the same member id as a councilor, can lead to conflicting stakes
-        let member_id: MemberId = 14;
-
-        let account_id: [u8; 32] = [member_id as u8; 32];
+        let member_id: u64 = create_new_members(1)[0];
+        let account_id: [u8; 32] = account_from_member_id(member_id).into();
         let stake_amount = 100_000_u128;
 
         let stake_policy = working_group::StakePolicy {

+ 2 - 0
scripts/cargo-build.sh

@@ -1,5 +1,7 @@
 #!/usr/bin/env bash
 
+# TODO: Check for valid JSON in ALL_PROPOSALS_PARAMETERS_JSON ?
+
 export WASM_BUILD_TOOLCHAIN=nightly-2021-02-20
 
 cargo +nightly-2021-02-20 build --release

+ 19 - 14
start.sh

@@ -22,8 +22,17 @@ else
   trap down EXIT
 fi
 
-## Run a local development chain
-docker-compose up -d joystream-node
+if [ "${SKIP_NODE}" != true ]
+then
+  ## Run a local development chain
+  docker-compose up -d joystream-node
+fi
+
+## Query Node Infrastructure
+./query-node/start.sh
+
+## Orion
+docker-compose up -d orion
 
 ## Init the chain with some state
 if [[ $SKIP_CHAIN_SETUP != 'true' ]]; then
@@ -37,20 +46,16 @@ if [[ $SKIP_CHAIN_SETUP != 'true' ]]; then
   export COLOSSUS_1_URL=${COLOSSUS_1_URL:="http://${HOST_IP}:3333"}
   export DISTRIBUTOR_1_URL=${DISTRIBUTOR_1_URL:="http://${HOST_IP}:3334"}
   ./tests/network-tests/run-test-scenario.sh ${INIT_CHAIN_SCENARIO}
-fi
-
-## Member faucet
-docker-compose up -d faucet
-
-## Query Node Infrastructure
-./query-node/start.sh
 
-## Storage Infrastructure Nodes
-docker-compose up -d colossus-1
-docker-compose up -d distributor-1
+  ## Member faucet
+  export SCREENING_AUTHORITY_SEED=$(cat ./tests/network-tests/output.json | jq -r .faucet.suri)
+  export INVITING_MEMBER_ID=$(cat ./tests/network-tests/output.json | jq -r .faucet.memberId)
+  docker-compose up -d faucet
 
-## Orion
-docker-compose up -d orion
+  ## Storage Infrastructure Nodes
+  docker-compose up -d colossus-1
+  docker-compose up -d distributor-1
+fi
 
 if [ "${PERSIST}" == true ]
 then

+ 1 - 1
storage-node/package.json

@@ -11,7 +11,7 @@
     "@apollo/client": "^3.3.21",
     "@elastic/ecs-winston-format": "^1.3.1",
     "@joystream/metadata-protobuf": "^2.0.0",
-    "@joystream/types": "^0.18.0",
+    "@joystream/types": "^0.18.1",
     "@oclif/command": "^1",
     "@oclif/config": "^1",
     "@oclif/plugin-help": "^3",

+ 17 - 0
tests/network-tests/src/Api.ts

@@ -24,6 +24,7 @@ import {
   KeyGenInfo,
   WorkingGroupModuleName,
   ProposalType,
+  FaucetInfo,
 } from './types'
 
 import { ProposalParameters } from '@joystream/types/proposals'
@@ -57,6 +58,9 @@ export class ApiFactory {
   // source of funds for all new accounts
   private readonly treasuryAccount: string
 
+  // faucet details
+  public faucetInfo: FaucetInfo
+
   public static async create(
     provider: WsProvider,
     treasuryAccountUri: string,
@@ -97,12 +101,17 @@ export class ApiFactory {
     this.addressesToKeyId = new Map()
     this.addressesToSuri = new Map()
     this.keyId = 0
+    this.faucetInfo = { suri: '', memberId: 0 }
   }
 
   public getApi(label: string): Api {
     return new Api(this, this.api, this.treasuryAccount, this.keyring, label)
   }
 
+  public setFaucetInfo(info: FaucetInfo): void {
+    this.faucetInfo = info
+  }
+
   public createKeyPairs(n: number): { key: KeyringPair; id: number }[] {
     const keys: { key: KeyringPair; id: number }[] = []
     for (let i = 0; i < n; i++) {
@@ -1013,4 +1022,12 @@ export class Api {
       accountFrom
     )
   }
+
+  public setFaucetInfo(info: FaucetInfo): void {
+    this.factory.setFaucetInfo(info)
+  }
+
+  public getFaucetInfo(): FaucetInfo {
+    return this.factory.faucetInfo
+  }
 }

+ 5 - 1
tests/network-tests/src/Scenario.ts

@@ -10,7 +10,7 @@ import { JobManager } from './JobManager'
 import { ResourceManager } from './Resources'
 import fetch from 'cross-fetch'
 import fs, { existsSync, readFileSync } from 'fs'
-import { KeyGenInfo } from './types'
+import { KeyGenInfo, FaucetInfo } from './types'
 
 export type ScenarioProps = {
   env: NodeJS.ProcessEnv
@@ -24,6 +24,7 @@ type TestsOutput = {
   accounts: { [k: string]: number }
   keyIds: KeyGenInfo
   miniSecret: string
+  faucet: FaucetInfo
 }
 
 function writeOutput(api: Api, miniSecret: string) {
@@ -34,10 +35,13 @@ function writeOutput(api: Api, miniSecret: string) {
   // first and last key id used to generate keys in this scenario
   const keyIds = api.keyGenInfo()
 
+  const faucet = api.getFaucetInfo()
+
   const output: TestsOutput = {
     accounts,
     keyIds,
     miniSecret,
+    faucet,
   }
 
   fs.writeFileSync(OUTPUT_FILE_PATH, JSON.stringify(output, undefined, 2))

+ 4 - 3
tests/network-tests/src/fixtures/membership/TransferInvitesHappyCaseFixture.ts

@@ -47,9 +47,6 @@ export class TransferInvitesHappyCaseFixture extends BaseQueryNodeFixture {
 
   async execute(): Promise<void> {
     const { fromContext, toContext, invitesToTransfer } = this
-    this.tx = this.api.tx.members.transferInvites(fromContext.memberId, toContext.memberId, invitesToTransfer)
-    const txFee = await this.api.estimateTxFee(this.tx, fromContext.account)
-    await this.api.treasuryTransferBalance(fromContext.account, txFee)
 
     const [fromMember, toMember] = await this.api.query.members.membershipById.multi<Membership>([
       fromContext.memberId,
@@ -59,6 +56,10 @@ export class TransferInvitesHappyCaseFixture extends BaseQueryNodeFixture {
     this.fromMemberInitialInvites = fromMember.invites.toNumber()
     this.toMemberInitialInvites = toMember.invites.toNumber()
 
+    this.tx = this.api.tx.members.transferInvites(fromContext.memberId, toContext.memberId, invitesToTransfer)
+    const txFee = await this.api.estimateTxFee(this.tx, fromContext.account)
+    await this.api.treasuryTransferBalance(fromContext.account, txFee)
+
     // Send transfer invites extrinsic
     const txRes = await this.api.signAndSend(this.tx, fromContext.account)
     this.event = await this.api.getEventDetails(txRes, 'members', 'InvitesTransferred')

+ 1 - 1
tests/network-tests/src/fixtures/proposals/DecideOnProposalStatusFixture.ts

@@ -78,7 +78,7 @@ export class DecideOnProposalStatusFixture extends BaseQueryNodeFixture {
         approvalThresholdPercentage.toNumber(),
         slashingThresholdPercentage.toNumber()
       )
-      const minRejectOrAbstainVotesN = Math.ceil((councilSize * (100 - otherResultMinThreshold)) / 100)
+      const minRejectOrAbstainVotesN = Math.floor((councilSize * (100 - otherResultMinThreshold)) / 100) + 1
       return Array.from({ length: minRejectOrAbstainVotesN }, (v, i) => vote('Reject', i))
     }
   }

+ 41 - 0
tests/network-tests/src/fixtures/workingGroups/SetLeaderInvitationQuotaFixture.ts

@@ -0,0 +1,41 @@
+import { Api } from '../../Api'
+import { QueryNodeApi } from '../../QueryNodeApi'
+import { EventDetails, WorkingGroupModuleName } from '../../types'
+import { BaseWorkingGroupFixture } from './BaseWorkingGroupFixture'
+import { SubmittableExtrinsic } from '@polkadot/api/types'
+import { ISubmittableResult } from '@polkadot/types/types/'
+
+export class SetLeaderInvitationQuotaFixture extends BaseWorkingGroupFixture {
+  protected group: WorkingGroupModuleName
+  protected quota: number
+
+  public constructor(api: Api, query: QueryNodeApi, group: WorkingGroupModuleName, quota: number) {
+    super(api, query, group)
+    this.group = group
+    this.quota = quota
+  }
+
+  protected async getSignerAccountOrAccounts(): Promise<string> {
+    return (await this.api.query.sudo.key()).toString()
+  }
+
+  protected async getExtrinsics(): Promise<SubmittableExtrinsic<'promise'>[]> {
+    const extrinsics = [this.api.tx.members.setLeaderInvitationQuota(this.quota)]
+    return extrinsics.map((tx) => this.api.tx.sudo.sudo(tx))
+  }
+
+  protected async getEventFromResult(result: ISubmittableResult): Promise<EventDetails> {
+    return await this.api.getEventDetails(result, 'members', 'LeaderInvitationQuotaUpdated')
+  }
+
+  protected assertQueryNodeEventIsValid(qEvent: unknown, i: number): void {
+    // TODO: implement
+  }
+
+  async runQueryNodeChecks(): Promise<void> {
+    await super.runQueryNodeChecks()
+
+    // Query and check the events
+    // TODO: implement
+  }
+}

+ 57 - 0
tests/network-tests/src/flows/faucet/initFaucet.ts

@@ -0,0 +1,57 @@
+import { FlowProps } from '../../Flow'
+import { extendDebug } from '../../Debugger'
+import { FixtureRunner } from '../../Fixture'
+import { BuyMembershipHappyCaseFixture, TransferInvitesHappyCaseFixture } from '../../fixtures/membership'
+import { SetBudgetFixture } from '../../fixtures/workingGroups/SetBudgetFixture'
+import { SetLeaderInvitationQuotaFixture } from '../../fixtures/workingGroups/SetLeaderInvitationQuotaFixture'
+import _ from 'lodash'
+import BN from 'bn.js'
+
+export default async function initFaucet({ api, env, query }: FlowProps): Promise<void> {
+  const debug = extendDebug('flow:initFaucet')
+  debug('Started')
+
+  const invitesToTransfer = 100
+  // Get membership working group leader
+  const membershipWorkingGroup = 'membershipWorkingGroup'
+  const [, membershipLeader] = await api.getLeader(membershipWorkingGroup)
+
+  // Grant lead invitation quota
+  const setLeaderInvitationQuotaFixture = new SetLeaderInvitationQuotaFixture(
+    api,
+    query,
+    membershipWorkingGroup,
+    invitesToTransfer + 10
+  )
+  await new FixtureRunner(setLeaderInvitationQuotaFixture).runWithQueryNodeChecks()
+
+  // The membership working group should have a budget allocated
+  const budgets: BN[] = [new BN(1000000)]
+  const setGroupBudgetFixture = new SetBudgetFixture(api, query, membershipWorkingGroup, budgets)
+  await new FixtureRunner(setGroupBudgetFixture).runWithQueryNodeChecks()
+
+  // Create a membership account for faucet
+  const faucetSuri = env.SCREENING_AUTHORITY_SEED || '//Faucet'
+  const faucetAccount = api.createCustomKeyPair(faucetSuri, true).address
+  const happyCaseFixture = new BuyMembershipHappyCaseFixture(api, query, [faucetAccount])
+  await new FixtureRunner(happyCaseFixture).runWithQueryNodeChecks()
+  const [faucetMemberId] = happyCaseFixture.getCreatedMembers()
+
+  // Give the faucet member accounts some funds (they need some funds for extrinsics)
+  await api.treasuryTransferBalanceToAccounts([faucetAccount], new BN(200))
+
+  // Send lead invites to faucet member account
+  const [leadMemberControllerAccount] = await api.getMemberSigners([{ asMember: membershipLeader.member_id }])
+  const transferInvitesHappyCaseFixture = new TransferInvitesHappyCaseFixture(
+    api,
+    query,
+    { memberId: membershipLeader.member_id, account: leadMemberControllerAccount },
+    { memberId: faucetMemberId, account: faucetAccount },
+    invitesToTransfer
+  )
+  await new FixtureRunner(transferInvitesHappyCaseFixture).runWithQueryNodeChecks()
+
+  api.setFaucetInfo({ suri: faucetSuri, memberId: faucetMemberId.toNumber() })
+
+  debug('Done')
+}

+ 1 - 1
tests/network-tests/src/graphql/generated/queries.ts

@@ -4320,7 +4320,7 @@ export const GetProposalExecutedEventsByEventIds = gql`
 `
 export const GetProposalVotedEventsByEventIds = gql`
   query getProposalVotedEventsByEventIds($eventIds: [ID!]) {
-    proposalVotedEvents(where: { id_in: $eventIds }) {
+    proposalVotedEvents(where: { id_in: $eventIds }, limit: 200) {
       ...ProposalVotedEventFields
     }
   }

File diff suppressed because it is too large
+ 418 - 294
tests/network-tests/src/graphql/generated/schema.ts


+ 1 - 1
tests/network-tests/src/graphql/queries/proposalsEvents.graphql

@@ -100,7 +100,7 @@ fragment ProposalVotedEventFields on ProposalVotedEvent {
 }
 
 query getProposalVotedEventsByEventIds($eventIds: [ID!]) {
-  proposalVotedEvents(where: { id_in: $eventIds }) {
+  proposalVotedEvents(where: { id_in: $eventIds }, limit: 200) {
     ...ProposalVotedEventFields
   }
 }

+ 7 - 6
tests/network-tests/src/scenarios/setupNewChain.ts

@@ -1,23 +1,24 @@
-import electCouncil from '../flows/council/elect'
 import leaderSetup from '../flows/working-groups/leadOpening'
 import mockContentFlow from '../misc/mockContentFlow'
 import updateAccountsFlow from '../misc/updateAllWorkerRoleAccountsFlow'
+import initFaucet from '../flows/faucet/initFaucet'
 import initStorage, { singleBucketConfig as defaultStorageConfig } from '../flows/storage/initStorage'
 import initDistribution, { singleBucketConfig as defaultDistributionConfig } from '../flows/storage/initDistribution'
 import { scenario } from '../Scenario'
 
 scenario('Setup new chain', async ({ job }) => {
-  job('Elect Council', electCouncil)
   const leads = job('Set WorkingGroup Leads', leaderSetup())
-  const updateWorkerAccounts = job('Update worker accounts', updateAccountsFlow).after(leads)
+  const updateAccounts = job('Update Worker Accounts', updateAccountsFlow).requires(leads)
+
+  job('Initialize Faucet', initFaucet).requires(updateAccounts)
 
   if (!process.env.SKIP_STORAGE_AND_DISTRIBUTION) {
-    job('initialize storage system', initStorage(defaultStorageConfig)).requires(updateWorkerAccounts)
-    job('initialize distribution system', initDistribution(defaultDistributionConfig)).requires(updateWorkerAccounts)
+    job('initialize storage system', initStorage(defaultStorageConfig)).requires(updateAccounts)
+    job('initialize distribution system', initDistribution(defaultDistributionConfig)).requires(updateAccounts)
   }
 
   // Create some mock content in content directory - without assets or any real metadata
-  job('Create Mock Content', mockContentFlow).after(updateWorkerAccounts)
+  job('Create Mock Content', mockContentFlow).after(updateAccounts)
 
   // assign members known accounts?
   // assign council known accounts?

+ 6 - 0
tests/network-tests/src/types.ts

@@ -78,3 +78,9 @@ export type PostPath = {
   threadId: ThreadId
   postId: PostId
 }
+
+// Forum init
+export type FaucetInfo = {
+  suri: string
+  memberId: number
+}

+ 1 - 1
types/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@joystream/types",
-  "version": "0.18.0",
+  "version": "0.18.1",
   "description": "Types for Joystream Substrate Runtime - Olympia release",
   "main": "index.js",
   "types": "index.d.ts",

+ 1 - 1
utils/api-scripts/package.json

@@ -12,7 +12,7 @@
     "storage-dev-init": "./dev-init-storage.sh"
   },
   "dependencies": {
-    "@joystream/types": "^0.18.0",
+    "@joystream/types": "^0.18.1",
     "@polkadot/api": "5.9.1",
     "@polkadot/types": "5.9.1",
     "@polkadot/keyring": "7.3.1",

+ 1 - 1
utils/migration-scripts/package.json

@@ -12,7 +12,7 @@
     "@oclif/config": "^1",
     "@oclif/plugin-help": "^3.2.3",
     "tslib": "^1",
-    "@joystream/types": "^0.18.0",
+    "@joystream/types": "^0.18.1",
     "@polkadot/api": "5.9.1",
     "@polkadot/types": "5.9.1",
     "@polkadot/keyring": "7.3.1",

Some files were not shown because too many files changed in this diff