Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix elect validators migration, deploy integration #1847

Merged
merged 12 commits into from
Nov 25, 2019
4 changes: 2 additions & 2 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ BLOCKSCOUT_DB_SUFFIX=

ETHSTATS_DOCKER_IMAGE_REPOSITORY="gcr.io/celo-testnet/ethstats"
ETHSTATS_DOCKER_IMAGE_TAG="cd037ea1e18848466452ba9890c1f1bcd3f61009"
ETHSTATS_TRUSTED_ADDRESSES="0x480b0e0A641AE45521377d4984d085a003934561,0xF523976B9FB2160e9a43D8Aee016b98ea8f57837"
ETHSTATS_BANNED_ADDRESSES="0xFd24A0699288E141A855bC8c0dd0400C5E89D5e5"
ETHSTATS_TRUSTED_ADDRESSES=""
ETHSTATS_BANNED_ADDRESSES=""

FAUCET_GENESIS_ACCOUNTS=2

Expand Down
25 changes: 14 additions & 11 deletions .env.integration
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
ENV_TYPE="integration"

GETH_VERBOSITY=3
GETH_VERBOSITY=4
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we move back to 3?


VM_BASED=false

Expand All @@ -11,31 +11,36 @@ CLUSTER_DOMAIN_NAME="celo-testnet"
TESTNET_PROJECT_NAME="celo-testnet"

BLOCKSCOUT_DOCKER_IMAGE_REPOSITORY="gcr.io/celo-testnet/blockscout"
BLOCKSCOUT_DOCKER_IMAGE_TAG="ad86714d629c01272e0651dec1fb6a968c3cec71"
BLOCKSCOUT_DOCKER_IMAGE_TAG="5fba4843b3e78b5ab75d01766214cb24c6a40649"
BLOCKSCOUT_WEB_REPLICAS=3
BLOCKSCOUT_DB_SUFFIX="25"
BLOCKSCOUT_DB_SUFFIX="29"
BLOCKSCOUT_SUBNETWORK_NAME="Integration"

ETHSTATS_DOCKER_IMAGE_REPOSITORY="gcr.io/celo-testnet/ethstats"
ETHSTATS_DOCKER_IMAGE_TAG="cd037ea1e18848466452ba9890c1f1bcd3f61009"
ETHSTATS_TRUSTED_ADDRESSES=""
ETHSTATS_BANNED_ADDRESSES=""

FAUCET_GENESIS_ACCOUNTS=2

GETH_NODE_DOCKER_IMAGE_REPOSITORY="us.gcr.io/celo-testnet/geth"
# When upgrading change this to latest commit hash from the master of the geth repo
# `geth $ git show | head -n 1`
GETH_NODE_DOCKER_IMAGE_TAG="c1ae452c707f8bee91a9a0bf49193e78e9c8512e"
GETH_NODE_DOCKER_IMAGE_TAG="09a217ff58a95214cbc5189c933359707f4fdaf2"

GETH_BOOTNODE_DOCKER_IMAGE_REPOSITORY="gcr.io/celo-testnet/geth-all"
# When upgrading change this to latest commit hash from the master of the geth repo
# `geth $ git show | head -n 1`
GETH_BOOTNODE_DOCKER_IMAGE_TAG="c1ae452c707f8bee91a9a0bf49193e78e9c8512e"
GETH_BOOTNODE_DOCKER_IMAGE_TAG="09a217ff58a95214cbc5189c933359707f4fdaf2"

CELOTOOL_DOCKER_IMAGE_REPOSITORY="gcr.io/celo-testnet/celo-monorepo"
CELOTOOL_DOCKER_IMAGE_TAG="celotool-2cb725c36b69e7ae608875610af080f4f3fa79bd"
CELOTOOL_DOCKER_IMAGE_TAG="celotool-5bea6d30cbe6aa4272b32a4d2cfed5567f422ea9"

TRANSACTION_METRICS_EXPORTER_DOCKER_IMAGE_REPOSITORY="gcr.io/celo-testnet/celo-monorepo"
TRANSACTION_METRICS_EXPORTER_DOCKER_IMAGE_TAG="transaction-metrics-exporter-2cb725c36b69e7ae608875610af080f4f3fa79bd"
TRANSACTION_METRICS_EXPORTER_DOCKER_IMAGE_TAG="transaction-metrics-exporter-5bea6d30cbe6aa4272b32a4d2cfed5567f422ea9"

ATTESTATION_SERVICE_DOCKER_IMAGE_REPOSITORY="gcr.io/celo-testnet/celo-monorepo"
ATTESTATION_SERVICE_DOCKER_IMAGE_TAG="attestation-service-2cb725c36b69e7ae608875610af080f4f3fa79bd"
ATTESTATION_SERVICE_DOCKER_IMAGE_REPOSITORY="us.gcr.io/celo-testnet/celo-monorepo"
ATTESTATION_SERVICE_DOCKER_IMAGE_TAG="attestation-service-c8e3392aa2ca44ff83b4035700ece5fd12ed2b84"

GETH_EXPORTER_DOCKER_IMAGE_REPOSITORY="gcr.io/celo-testnet-production/geth-exporter"
GETH_EXPORTER_DOCKER_IMAGE_TAG="ed7d21bd50592709173368cd697ef73c1774a261"
Expand All @@ -47,7 +52,6 @@ BLOCK_TIME=3
EPOCH=1000
ISTANBUL_REQUEST_TIMEOUT_MS=3000

# "og" -> our original 4 tx nodes, "${n}" -> for deriving n tx nodes from the MNEMONIC
# NOTE: we only create static IPs when TX_NODES is set to "og"
VALIDATORS=20
TX_NODES=2
Expand All @@ -61,7 +65,6 @@ GETH_NODES_BACKUP_CRONJOB_ENABLED=true
CONTRACT_CRONJOBS_ENABLED=true
CLUSTER_CREATION_FLAGS="--enable-autoscaling --min-nodes 3 --max-nodes 8 --machine-type=n1-standard-4"


GETH_NODE_CPU_REQUEST=400m
GETH_NODE_MEMORY_REQUEST=2.5G

Expand Down
3 changes: 0 additions & 3 deletions packages/celotool/src/e2e-tests/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -362,9 +362,6 @@ export async function migrateContracts(
election: {
minElectableValidators: '1',
},
reserve: {
goldBalance: 100000,
},
stableToken: {
initialBalances: {
addresses: validators.map(ensure0x),
Expand Down
4 changes: 2 additions & 2 deletions packages/celotool/src/lib/ethstats.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { installGenericHelmChart, removeGenericHelmChart } from 'src/lib/helm_deploy'
import { execCmdWithExitOnFailure } from 'src/lib/utils'
import { envVar, fetchEnv } from './env-utils'
import { envVar, fetchEnv, fetchEnvOrFallback } from './env-utils'
import { AccountType, getAddressesFor } from './generate_utils'

const helmChartPath = '../helm-charts/ethstats'
Expand Down Expand Up @@ -50,6 +50,6 @@ function generateAuthorizedAddresses() {
publicKeys.push(getAddressesFor(AccountType.TX_NODE, mnemonic, txNodes))
publicKeys.push(getAddressesFor(AccountType.VALIDATOR, mnemonic, validatorNodes))

publicKeys.push(fetchEnv(envVar.ETHSTATS_TRUSTED_ADDRESSES).split(','))
publicKeys.push(fetchEnvOrFallback(envVar.ETHSTATS_TRUSTED_ADDRESSES, '').split(','))
return publicKeys.reduce((accumulator, value) => accumulator.concat(value), [])
}
6 changes: 3 additions & 3 deletions packages/celotool/src/lib/generate_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export const privateKeyToStrippedAddress = (privateKey: string) =>

const validatorZeroBalance = fetchEnvOrFallback(
envVar.VALIDATOR_ZERO_GENESIS_BALANCE,
'100010011000000000000000000'
'103010030000000000000000000'
) // 100,010,011 CG
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this comment still valid then?

const validatorBalance = fetchEnvOrFallback(
envVar.VALIDATOR_GENESIS_BALANCE,
Expand All @@ -109,12 +109,12 @@ export const getStrippedAddressesFor = (accountType: AccountType, mnemonic: stri
getAddressesFor(accountType, mnemonic, n).map(strip0x)

export const getValidators = (mnemonic: string, n: number) => {
return getPrivateKeysFor(AccountType.VALIDATOR, mnemonic, n).map((key) => {
return getPrivateKeysFor(AccountType.VALIDATOR, mnemonic, n).map((key, i) => {
const blsKeyBytes = blsPrivateKeyToProcessedPrivateKey(key)
return {
address: strip0x(privateKeyToAddress(key)),
blsPublicKey: bls12377js.BLS.privateToPublicBytes(blsKeyBytes).toString('hex'),
balance: n === 0 ? validatorZeroBalance : validatorBalance,
balance: i === 0 ? validatorZeroBalance : validatorBalance,
}
})
}
Expand Down
18 changes: 1 addition & 17 deletions packages/protocol/contracts/governance/Election.sol
Original file line number Diff line number Diff line change
Expand Up @@ -752,8 +752,7 @@ contract Election is
totalNumMembersElected = totalNumMembersElected.add(1);
}
}
// Shuffle the validator set using validator-supplied entropy
return shuffleArray(electedValidators);
return electedValidators;
}

/**
Expand Down Expand Up @@ -789,21 +788,6 @@ contract Election is
return (groupIndex, memberElected);
}

/**
* @notice Randomly permutes an array of addresses.
* @param array The array to permute.
* @return The permuted array.
*/
function shuffleArray(address[] memory array) private view returns (address[] memory) {
bytes32 r = getRandom().getBlockRandomness(block.number);
for (uint256 i = array.length - 1; i > 0; i = i.sub(1)) {
uint256 j = uint256(r) % (i + 1);
(array[i], array[j]) = (array[j], array[i]);
r = keccak256(abi.encodePacked(r));
}
return array;
}

/**
* @notice Returns get current validator signers using the precompiles.
* @return List of current validator signers.
Expand Down
2 changes: 2 additions & 0 deletions packages/protocol/migrations/19_governance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,11 @@ module.exports = deploymentForCoreContract<GovernanceInstance>(
)

const proxyAndImplementationOwnedByGovernance = [
'Accounts',
'Attestations',
'BlockchainParameters',
'Election',
'EpochRewards',
'Escrow',
'Exchange',
'FeeCurrencyWhitelist',
Expand Down
73 changes: 43 additions & 30 deletions packages/protocol/migrations/20_elect_validators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,19 +64,26 @@ async function registerValidatorGroup(
numMembers
)

// Add a premium to cover tx fees
const v = lockedGoldValue.times(1.01).toFixed()

console.info(` - send funds ${v} to group address ${account.address}`)
await sendTransactionWithPrivateKey(web3, null, privateKey, {
to: account.address,
value: lockedGoldValue.times(1.01).toFixed(), // Add a premium to cover tx fees
value: v,
})

console.info(` - lock gold`)
await lockGold(accounts, lockedGold, lockedGoldValue, account.privateKey)

console.info(` - setName`)
// @ts-ignore
const setNameTx = accounts.contract.methods.setName(`${name} ${encodedKey}`)
await sendTransactionWithPrivateKey(web3, setNameTx, account.privateKey, {
to: accounts.address,
})

console.info(` - registerValidatorGroup`)
// @ts-ignore
const tx = validators.contract.methods.registerValidatorGroup(
toFixed(config.validators.commission).toString()
Expand All @@ -86,7 +93,7 @@ async function registerValidatorGroup(
to: validators.address,
})

return account
return [account, lockedGoldValue]
}

async function registerValidator(
Expand All @@ -99,19 +106,25 @@ async function registerValidator(
index: number,
networkName: string
) {
const valName = `CLabs Validator #${index} on ${networkName}`

console.info(` - lockGold ${valName}`)
await lockGold(
accounts,
lockedGold,
config.validators.validatorLockedGoldRequirements.value,
validatorPrivateKey
)

console.info(` - setName ${valName}`)

// @ts-ignore
const setNameTx = accounts.contract.methods.setName(`CLabs Validator #${index} on ${networkName}`)
const setNameTx = accounts.contract.methods.setName(valName)
await sendTransactionWithPrivateKey(web3, setNameTx, validatorPrivateKey, {
to: accounts.address,
})

console.info(` - registerValidator ${valName}`)
const publicKey = privateKeyToPublicKey(validatorPrivateKey)
const blsPublicKey = getBlsPublicKey(validatorPrivateKey)
const blsPoP = getBlsPoP(privateKeyToAddress(validatorPrivateKey), validatorPrivateKey)
Expand All @@ -123,13 +136,17 @@ async function registerValidator(
to: validators.address,
})

console.info(` - affiliate ${valName}`)

// @ts-ignore
const affiliateTx = validators.contract.methods.affiliate(groupAddress)

await sendTransactionWithPrivateKey(web3, affiliateTx, validatorPrivateKey, {
to: validators.address,
})

console.info(` - setAccountDataEncryptionKey ${valName}`)

// @ts-ignore
const registerDataEncryptionKeyTx = accounts.contract.methods.setAccountDataEncryptionKey(
privateKeyToPublicKey(validatorPrivateKey)
Expand All @@ -141,6 +158,7 @@ async function registerValidator(

// Authorize the attestation signer
const attestationKeyAddress = privateKeyToAddress(attestationKey)
console.info(` - authorizeAttestationSigner ${valName}->${attestationKeyAddress}`)
const message = web3.utils.soliditySha3({
type: 'address',
value: privateKeyToAddress(validatorPrivateKey),
Expand All @@ -159,6 +177,7 @@ async function registerValidator(
to: accounts.address,
})

console.info(` - done ${valName}`)
return
}

Expand Down Expand Up @@ -195,6 +214,11 @@ module.exports = async (_deployer: any, networkName: string) => {
return
}

// Assumptions about where funds are located:
// * Validator 0 holds funds for all groups' stakes
// * Validator 1-n holds funds needed for their own stake
const validator0Key = valKeys[0]

if (valKeys.length < config.validators.minElectableValidators) {
console.warn(
` Warning: Have ${valKeys.length} Validator keys but require a minimum of ${
Expand All @@ -219,32 +243,32 @@ module.exports = async (_deployer: any, networkName: string) => {
}

console.info(` Registering validator group: ${groupName} ...`)
const account = await registerValidatorGroup(
const [groupAccount, groupLockedGoldValue] = await registerValidatorGroup(
groupName,
accounts,
lockedGold,
validators,
groupKeys[0],
validator0Key,
groupKeys.length
)

console.info(` * Registering ${groupKeys.length} validators ...`)
await Promise.all(
groupKeys.map((key, index) =>
registerValidator(
groupKeys.map((key, i) => {
const index = idx * config.validators.maxGroupSize + i
return registerValidator(
accounts,
lockedGold,
validators,
key,
attestationKeys[index],
account.address,
groupAccount.address,
index,
networkName
)
)
})
)

console.info(' * Adding Validators to Validator Group ...')
console.info(` * Adding Validators to ${groupName} ...`)
for (const [i, key] of groupKeys.entries()) {
const address = privateKeyToAddress(key)
console.info(` - Adding ${address} ...`)
Expand All @@ -255,41 +279,30 @@ module.exports = async (_deployer: any, networkName: string) => {
NULL_ADDRESS,
prevGroupAddress
)
await sendTransactionWithPrivateKey(web3, addTx, account.privateKey, {
await sendTransactionWithPrivateKey(web3, addTx, groupAccount.privateKey, {
to: validators.address,
})
} else {
// @ts-ignore
const addTx = validators.contract.methods.addMember(address)
await sendTransactionWithPrivateKey(web3, addTx, account.privateKey, {
await sendTransactionWithPrivateKey(web3, addTx, groupAccount.privateKey, {
to: validators.address,
})
}
}

console.info(' * Voting for the group ...')
// Make another deposit so our vote has more weight.
const minLockedGoldVotePerValidator = 10000
const value = new BigNumber(groupKeys.length)
.times(minLockedGoldVotePerValidator)
.times(web3.utils.toWei('1'))
// @ts-ignore
const bondTx = lockedGold.contract.methods.lock()
await sendTransactionWithPrivateKey(web3, bondTx, groupKeys[0], {
to: lockedGold.address,
value,
})

console.info(' * Group voting for itself ...')
// @ts-ignore
const voteTx = election.contract.methods.vote(
account.address,
'0x' + value.toString(16),
groupAccount.address,
'0x' + groupLockedGoldValue.toString(16),
NULL_ADDRESS,
prevGroupAddress
)
await sendTransactionWithPrivateKey(web3, voteTx, groupKeys[0], {
await sendTransactionWithPrivateKey(web3, voteTx, groupAccount.privateKey, {
to: election.address,
})
prevGroupAddress = account.address

prevGroupAddress = groupAccount.address
}
}
4 changes: 2 additions & 2 deletions packages/protocol/migrationsConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,11 @@ const DefaultConfig = {
},
validators: {
groupLockedGoldRequirements: {
value: '10000000000000000000000', // 10k gold
value: '10000000000000000000000', // 10k gold per validator
duration: 60 * 24 * 60 * 60, // 60 days
},
validatorLockedGoldRequirements: {
value: '10000000000000000000000', // 1 gold
value: '10000000000000000000000', // 10k gold
duration: 60 * 24 * 60 * 60, // 60 days
},
validatorScoreParameters: {
Expand Down