Skip to content

Commit

Permalink
Merge branch 'master' into jcortejoso/test-blockchain-1.8.x-branch
Browse files Browse the repository at this point in the history
  • Loading branch information
lvpeschke authored Nov 10, 2023
2 parents 9ca8c6d + 87647b4 commit be7c8ff
Show file tree
Hide file tree
Showing 21 changed files with 684 additions and 532 deletions.
5 changes: 5 additions & 0 deletions .changeset/breezy-ants-refuse.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@celo/celocli': minor
---

Update of Governance Upvote function
6 changes: 6 additions & 0 deletions .changeset/sixty-squids-warn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@celo/contractkit': minor
'@celo/celocli': minor
---

Add multisig:approve command to CLI, expose MultiSig.confirmTransaction in ContractKit.
13 changes: 5 additions & 8 deletions .github/actions/sync-workspace/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ inputs:
description: "Rebuild package. It also disable fail-on-cache-miss"
required: false
default: 'false'
artifacts_to_cache:
description: "List of artifacts to recover from cache"
required: true
runs:
using: "composite"
steps:
Expand All @@ -19,6 +22,7 @@ runs:
key: node-${{ runner.os }}-${{ runner.arch }}-${{ env.NODE_MODULE_CACHE_VERSION }}-${{ hashFiles('**/yarn.lock') }}
enableCrossOsArchive: true
fail-on-cache-miss: "!${{ fromJSON(env.REBUILD_PACKAGE) }}"

- name: Restore build artifacts cache
uses: actions/cache/restore@v3
id: cache_build_artifacts
Expand All @@ -28,14 +32,7 @@ runs:
# We need to cache all the artifacts generated by yarn install+build
# Update this list also in .github/actions/sync-workspace/action.yml with exactly the same list
path: |
packages/**/lib
packages/**/dist
packages/**/build
packages/protocol/*.js
packages/protocol/*.js.map
packages/protocol/**/*.js
packages/protocol/**/*.js.map
packages/sdk/contractkit/src/generated
${{ inputs.artifacts_to_cache }}
key: code-${{ github.sha }}
restore-keys: |
code-${{ github.sha }}
Expand Down
71 changes: 49 additions & 22 deletions .github/workflows/celo-monorepo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ jobs:
# Propagate more outputs if you need https://github.com/tj-actions/changed-files#outputs
# Adding a initial comma so ',<path>' matches also for the first file
all_modified_files: ',${{ steps.changed-files.outputs.all_modified_files }}'
artifacts_to_cache: ${{ steps.get_artifacts_to_cache.outputs.artifacts_to_cache }}
# runs-on: ubuntu-latest
runs-on: ['self-hosted', 'monorepo-node18']
timeout-minutes: 30
Expand All @@ -68,26 +69,6 @@ jobs:
key: node-${{ runner.os }}-${{ runner.arch }}-${{ env.NODE_MODULE_CACHE_VERSION }}-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
node-${{ runner.os }}-${{ runner.arch }}-${{ env.NODE_MODULE_CACHE_VERSION }}-
# We use cache to share the build artifacts between jobs (gh artifacts are too slow...)
# For more context check https://github.com/actions/upload-artifact/issues/199
- name: Restore build artifacts cache
uses: actions/cache@v3
id: cache_build_artifacts
with:
# We need to cache all the artifacts generated by yarn install+build
# Update this list also in .github/actions/sync-workspace/action.yml with exactly the same list
path: |
packages/**/lib
packages/**/dist
packages/**/build
packages/protocol/*.js
packages/protocol/*.js.map
packages/protocol/**/*.js
packages/protocol/**/*.js.map
packages/sdk/contractkit/src/generated
key: code-${{ github.sha }}
restore-keys: |
code-${{ github.sha }}
- name: Install yarn dependencies
run: git config --global url."https://".insteadOf ssh:// && yarn install
if: steps.cache_node.outputs.cache-hit != 'true'
Expand All @@ -105,6 +86,27 @@ jobs:
if: steps.cache_node.outputs.cache-hit != 'true'
run: |
yarn check-licenses
- name: Get the artifacts to cache
id: get_artifacts_to_cache
run: |
artifacts_to_cache="$(git ls-files --others --ignored --exclude-standard | grep -v node_modules)"
echo "artifacts_to_cache<<EOF" >> $GITHUB_OUTPUT
echo "$artifacts_to_cache" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
# We use cache to share the build artifacts between jobs (gh artifacts are too slow...)
# For more context check https://github.com/actions/upload-artifact/issues/199
- name: Restore build artifacts cache
uses: actions/cache@v3
id: cache_build_artifacts
with:
# We need to cache all the artifacts generated by yarn install+build
# Update this list also in .github/actions/sync-workspace/action.yml with exactly the same list
path: |
${{ steps.get_artifacts_to_cache.outputs.artifacts_to_cache }}
key: code-${{ github.sha }}
restore-keys: |
code-${{ github.sha }}
- name: Detect files changed in PR, and expose as output
id: changed-files
uses: tj-actions/changed-files@v37
Expand All @@ -123,6 +125,8 @@ jobs:
- uses: actions/checkout@v4
- name: Sync workspace
uses: ./.github/actions/sync-workspace
with:
artifacts_to_cache: ${{ needs.install-dependencies.outputs.artifacts_to_cache }}
- run: yarn run prettify:diff
- run: yarn run lint
general_test:
Expand All @@ -133,6 +137,8 @@ jobs:
- uses: actions/checkout@v4
- name: Sync workspace
uses: ./.github/actions/sync-workspace
with:
artifacts_to_cache: ${{ needs.install-dependencies.outputs.artifacts_to_cache }}
- name: Run Jest Tests
run: |
mkdir -p test-results/jest
Expand Down Expand Up @@ -160,6 +166,8 @@ jobs:
- uses: actions/checkout@v4
- name: Sync workspace
uses: ./.github/actions/sync-workspace
with:
artifacts_to_cache: ${{ needs.install-dependencies.outputs.artifacts_to_cache }}
- name: Run Wallet tests
run: |
yarn run lerna --scope '@celo/wallet-*' run test
Expand All @@ -185,6 +193,8 @@ jobs:
submodules: recursive
- name: Sync workspace
uses: ./.github/actions/sync-workspace
with:
artifacts_to_cache: ${{ needs.install-dependencies.outputs.artifacts_to_cache }}
- name: Download protocol devchain artifact
uses: dawidd6/action-download-artifact@v2
with:
Expand All @@ -198,8 +208,6 @@ jobs:
- name: Test against current release
run: |
echo "Comparing against $RELEASE_TAG"
sudo apt-get update
sudo apt-get install vim lsof --yes
BUILD_AND_DEVCHAIN_DIR=$(echo build/$(echo $RELEASE_TAG | sed -e 's/\//_/g'))
yarn --cwd packages/protocol ci:test-make-release -b $RELEASE_TAG -d $BUILD_AND_DEVCHAIN_DIR
Expand Down Expand Up @@ -260,6 +268,7 @@ jobs:
uses: ./.github/actions/sync-workspace
with:
rebuild-package: 'true'
artifacts_to_cache: ${{ needs.install-dependencies.outputs.artifacts_to_cache }}
- name: Execute matrix command for test
uses: nick-fields/retry@v2
with:
Expand All @@ -285,8 +294,12 @@ jobs:
false
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Sync workspace
uses: ./.github/actions/sync-workspace
with:
artifacts_to_cache: ${{ needs.install-dependencies.outputs.artifacts_to_cache }}
- name: Generate DevChain
run: |
cd packages/sdk/contractkit
Expand All @@ -313,8 +326,12 @@ jobs:
false
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Sync workspace
uses: ./.github/actions/sync-workspace
with:
artifacts_to_cache: ${{ needs.install-dependencies.outputs.artifacts_to_cache }}
- name: Generate DevChain
run: |
cd packages/cli
Expand Down Expand Up @@ -350,6 +367,8 @@ jobs:
- uses: actions/checkout@v4
- name: Sync workspace
uses: ./.github/actions/sync-workspace
with:
artifacts_to_cache: ${{ needs.install-dependencies.outputs.artifacts_to_cache }}
- name: Install and test the npm package
run: |
set -euo pipefail
Expand All @@ -375,6 +394,8 @@ jobs:
- uses: actions/checkout@v4
- name: Sync workspace
uses: ./.github/actions/sync-workspace
with:
artifacts_to_cache: ${{ needs.install-dependencies.outputs.artifacts_to_cache }}
- name: Install and test the npm package
run: |
set -euo pipefail
Expand All @@ -400,6 +421,8 @@ jobs:
- uses: actions/checkout@v4
- name: Sync workspace
uses: ./.github/actions/sync-workspace
with:
artifacts_to_cache: ${{ needs.install-dependencies.outputs.artifacts_to_cache }}
- name: Install and test the npm package
run: |
set -euo pipefail
Expand Down Expand Up @@ -488,6 +511,8 @@ jobs:
submodules: recursive
- name: Sync workspace
uses: ./.github/actions/sync-workspace
with:
artifacts_to_cache: ${{ needs.install-dependencies.outputs.artifacts_to_cache }}
- name: Execute matrix command for test
uses: nick-fields/retry@v2
with:
Expand Down Expand Up @@ -543,6 +568,8 @@ jobs:
- uses: actions/checkout@v4
- name: Sync workspace
uses: ./.github/actions/sync-workspace
with:
artifacts_to_cache: ${{ needs.install-dependencies.outputs.artifacts_to_cache }}
- uses: actions/setup-java@v3
with:
distribution: 'zulu'
Expand Down
90 changes: 90 additions & 0 deletions packages/cli/src/commands/governance/upvote.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { Address } from '@celo/connect'
import { newKitFromWeb3 } from '@celo/contractkit'
import { GovernanceWrapper } from '@celo/contractkit/lib/wrappers/Governance'
import { NetworkConfig, testWithGanache, timeTravel } from '@celo/dev-utils/lib/ganache-test'
import BigNumber from 'bignumber.js'
import Web3 from 'web3'
import { testLocally } from '../../test-utils/cliUtils'
import Register from '../account/register'
import Lock from '../lockedgold/lock'
import Dequeue from './dequeue'
import Upvote from './upvote'

process.env.NO_SYNCCHECK = 'true'

const expConfig = NetworkConfig.governance

testWithGanache('governance:upvote cmd', (web3: Web3) => {
const minDeposit = web3.utils.toWei(expConfig.minDeposit.toString(), 'ether')
const kit = newKitFromWeb3(web3)
const proposalID = new BigNumber(1)
const proposalID2 = new BigNumber(2)
const proposalID3 = new BigNumber(3)
const proposalID4 = new BigNumber(4)
const proposalID5 = new BigNumber(5)
const proposalID6 = new BigNumber(6)
const proposalID7 = new BigNumber(7)

let accounts: Address[] = []
let governance: GovernanceWrapper

beforeEach(async () => {
accounts = await web3.eth.getAccounts()
kit.defaultAccount = accounts[0]
governance = await kit.contracts.getGovernance()
const dequeueFrequency = (await governance.dequeueFrequency()).toNumber()

await governance
.propose([], 'URL')
.sendAndWaitForReceipt({ from: accounts[0], value: minDeposit })
// this will reset lastDequeue to now
// there is 5 concurrent proposals possible to be dequeued
await testLocally(Dequeue, ['--from', accounts[0]])
await governance
.propose([], 'URL2')
.sendAndWaitForReceipt({ from: accounts[0], value: minDeposit })
await governance
.propose([], 'URL3')
.sendAndWaitForReceipt({ from: accounts[0], value: minDeposit })
await governance
.propose([], 'URL4')
.sendAndWaitForReceipt({ from: accounts[0], value: minDeposit })
await governance
.propose([], 'URL5')
.sendAndWaitForReceipt({ from: accounts[0], value: minDeposit })
await governance
.propose([], 'URL6')
.sendAndWaitForReceipt({ from: accounts[0], value: minDeposit })
await governance
.propose([], 'URL7')
.sendAndWaitForReceipt({ from: accounts[0], value: minDeposit })

await timeTravel(dequeueFrequency, web3)
await testLocally(Register, ['--from', accounts[0]])
await testLocally(Lock, ['--from', accounts[0], '--value', '100'])
})

test('will dequeue proposal if ready', async () => {
await testLocally(Upvote, ['--proposalID', proposalID2.toString(10), '--from', accounts[0]])

const queue = await governance.getQueue()
expect(queue.map((k) => k.proposalID)).toEqual([proposalID7])

const dequeue = await governance.getDequeue()
expect(dequeue).toEqual([
proposalID,
proposalID2,
proposalID3,
proposalID4,
proposalID5,
proposalID6,
])
})

test('can upvote proposal which cannot be dequeued', async () => {
await testLocally(Upvote, ['--proposalID', proposalID7.toString(10), '--from', accounts[0]])

const queue = await governance.getQueue()
expect(queue).toEqual([{ proposalID: proposalID7, upvotes: new BigNumber(100) }])
})
})
50 changes: 49 additions & 1 deletion packages/cli/src/commands/governance/upvote.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { GovernanceWrapper } from '@celo/contractkit/src/wrappers/Governance'
import { flags } from '@oclif/command'
import chalk from 'chalk'
import { BaseCommand } from '../../base'
import { newCheckBuilder } from '../../utils/checks'
import { displaySendTx } from '../../utils/cli'
Expand Down Expand Up @@ -29,6 +31,52 @@ export default class Upvote extends BaseCommand {
.runChecks()

const account = await (await this.kit.contracts.getAccounts()).voteSignerToAccount(signer)
await displaySendTx('upvoteTx', await governance.upvote(id, account), {}, 'ProposalUpvoted')

const consideredProposals = await this.dequeueAllPossibleProposals(governance as any)

if (!consideredProposals.some((k) => k.id === id)) {
await displaySendTx('upvoteTx', await governance.upvote(id, account), {}, 'ProposalUpvoted')
} else {
console.info(chalk.green('Proposal was dequeued, no need to upvote it.'))
}
}

/**
* Dequeues all possible proposals, returns the ones that were considered to be dequeued.
* This cycle is there only for safety purposes (in 99.9% of times it will not be run more than once).
* The reason behind this cycle is as follows:
* 1. Someone will DDoS our proposals (eg 100+)
* 2. All these proposals will expire
* 3. DequeueProposalsIfReady will always try to dequeue first n proposals but if all of them will be expired it will just remove them from queue.
* 4. Since none of the proposals were actually dequeued, next call will allow to dequeue again
* 5. Upvote function will try to dequeue again and possibly it will hit the proposal and bug that we have
*/
async dequeueAllPossibleProposals(governance: GovernanceWrapper) {
const concurrentProposalCount = (await governance.concurrentProposals()).toNumber()
const queue = await governance.getQueue()
const originalLastDequeue = await governance.lastDequeue()

let consideredProposals

for (let index = 0; index < queue.length / concurrentProposalCount + 1; index++) {
consideredProposals = (
await Promise.all(
queue
.slice(0, concurrentProposalCount)
.map((p) => p.proposalID)
.map(async (id) => {
const expired = await governance.isQueuedProposalExpired(id)
return { id: id.toString(), expired }
})
)
).filter((k) => k.expired === false)

await displaySendTx('dequeue', governance.dequeueProposalsIfReady(), {})
if (originalLastDequeue !== (await governance.lastDequeue())) {
break
}
}

return consideredProposals ?? []
}
}
Loading

0 comments on commit be7c8ff

Please sign in to comment.