Skip to content

Commit

Permalink
Merge pull request #896 from EYBlockchain/daveroga/implement-pos
Browse files Browse the repository at this point in the history
Implement PoS for proposers
  • Loading branch information
druiz0992 authored Sep 30, 2022
2 parents b8ae9a5 + ca12bc9 commit e943197
Show file tree
Hide file tree
Showing 22 changed files with 861 additions and 305 deletions.
106 changes: 53 additions & 53 deletions .github/workflows/check-PRs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -180,59 +180,59 @@ jobs:
name: optimist-sync-test-logs
path: ./optimist-sync-test.log

# adversary-test:
# runs-on: ubuntu-20.04
# env:
# TRANSACTIONS_PER_BLOCK: 32
# CONFIRMATIONS: 1
# steps:
# - uses: actions/checkout@v3
# - uses: actions/setup-node@v1
# with:
# node-version: '16.17.0'
#
# - name: Build adversary
# run: npm run build-adversary
#
# - name: Start Containers with geth
# run: |
# ./setup-nightfall
# ./geth-standalone -s
# sleep 300
# ./start-nightfall -l -d -a &> adversary-test.log &disown
#
# - name: Wait for images to be ready
# uses: Wandalen/[email protected]
# with:
# command: |
# docker wait nightfall_3_deployer_1
# attempt_limit: 100
# attempt_delay: 20000
#
# - name: debug logs - after container startup
# if: always()
# run: cat adversary-test.log
#
# - name: Run integration test
# run: |
# VERBOSE=true npm run test-adversary
#
# - name: debug logs - after integration test run
# if: always()
# run: cat adversary-test.log
#
# - name: If integration test failed, shutdown the Containers
# if: failure()
# run: |
# npm run nightfall-down
# ./geth-standalone -d
#
# - name: If integration test failed, upload logs files as artifacts
# if: failure()
# uses: actions/upload-artifact@v3
# with:
# name: adversary-test-logs
# path: ./adversary-test.log
# adversary-test:
# runs-on: ubuntu-20.04
# env:
# TRANSACTIONS_PER_BLOCK: 32
# CONFIRMATIONS: 1
# steps:
# - uses: actions/checkout@v3
# - uses: actions/setup-node@v1
# with:
# node-version: '16.17.0'
#
# - name: Build adversary
# run: npm run build-adversary
#
# - name: Start Containers with geth
# run: |
# ./setup-nightfall
# ./geth-standalone -s
# sleep 300
# ./start-nightfall -l -d -a &> adversary-test.log &disown
#
# - name: Wait for images to be ready
# uses: Wandalen/[email protected]
# with:
# command: |
# docker wait nightfall_3_deployer_1
# attempt_limit: 100
# attempt_delay: 20000
#
# - name: debug logs - after container startup
# if: always()
# run: cat adversary-test.log
#
# - name: Run integration test
# run: |
# VERBOSE=true npm run test-adversary
#
# - name: debug logs - after integration test run
# if: always()
# run: cat adversary-test.log
#
# - name: If integration test failed, shutdown the Containers
# if: failure()
# run: |
# npm run nightfall-down
# ./geth-standalone -d
#
# - name: If integration test failed, upload logs files as artifacts
# if: failure()
# uses: actions/upload-artifact@v3
# with:
# name: adversary-test-logs
# path: ./adversary-test.log

ping-pong-test:
runs-on: ubuntu-20.04
Expand Down
3 changes: 2 additions & 1 deletion apps/proposer/config/default.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module.exports = {
OPTIMIST_PORT: process.env.OPTIMIST_PORT || 8081,
OPTIMIST_WS_PORT: process.env.OPTIMIST_WS_PORT || 8082,
BLOCKCHAIN_WS_HOST: process.env.BLOCKCHAIN_WS_HOST || 'localhost',
BLOCKCHAIN_PATH: process.env.BLOCKCHAIN_PATH || '',
BLOCKCHAIN_PORT: process.env.BLOCKCHAIN_PORT || 8546,
BLOCKCHAIN_PATH: process.env.BLOCKCHAIN_PATH || '',
MINIMUM_STAKE: process.env.MINIMUM_STAKE || 100,
};
4 changes: 3 additions & 1 deletion apps/proposer/src/proposer.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
/**
Module that runs up as a proposer
*/
import config from 'config';
import logger from '../common-files/utils/logger.mjs';

const { MINIMUM_STAKE } = config.TEST_OPTIONS;
/**
Does the preliminary setup and starts listening on the websocket
*/
Expand All @@ -17,7 +19,7 @@ export default async function startProposer(nf3, proposerBaseUrl) {
else throw new Error('Healthcheck failed');
logger.info('Attempting to register proposer');

await nf3.registerProposer(proposerBaseUrl);
await nf3.registerProposer(proposerBaseUrl, MINIMUM_STAKE);
logger.debug('Proposer healthcheck up');

// TODO subscribe to layer 1 blocks and call change proposer
Expand Down
71 changes: 51 additions & 20 deletions cli/lib/nf3.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -326,29 +326,29 @@ class Nf3 {
}

/**
Returns the address of a Nightfall_3 contract calling the client.
Returns the abi of a Nightfall_3 contract calling the client.
@method
@async
@param {string} contractName - the name of the smart contract in question. Possible
values are 'Shield', 'State', 'Proposers', 'Challengers'.
@returns {Promise} Resolves into the Ethereum address of the contract
*/
async getContractAddress(contractName) {
const res = await axios.get(`${this.clientBaseUrl}/contract-address/${contractName}`);
return res.data.address.toLowerCase();
async getContractAbi(contractName) {
const res = await axios.get(`${this.clientBaseUrl}/contract-abi/${contractName}`);
return res.data.abi;
}

/**
Returns the abi of a Nightfall_3 contract calling the client.
Returns the address of a Nightfall_3 contract calling the client.
@method
@async
@param {string} contractName - the name of the smart contract in question. Possible
values are 'Shield', 'State', 'Proposers', 'Challengers'.
@returns {Promise} Resolves into the Ethereum abi of the contract
@returns {Promise} Resolves into the Ethereum address of the contract
*/
async getContractAbi(contractName) {
const res = await axios.get(`${this.clientBaseUrl}/contract-abi/${contractName}`);
return res.data.abi;
async getContractAddress(contractName) {
const res = await axios.get(`${this.clientBaseUrl}/contract-address/${contractName}`);
return res.data.address.toLowerCase();
}

/**
Expand Down Expand Up @@ -700,15 +700,16 @@ class Nf3 {
}

/**
Registers a new proposer and pays the Bond required to register.
Registers a new proposer and pays the stake required to register.
It will use the address of the Ethereum Signing key that is holds to register
the proposer.
@method
@async
@param {string} Proposer REST API URL with format https://xxxx.xxx.xx
@param {string} url REST API URL with format https://xxxx.xxx.xx
@param {number} stake - amount to stake
@returns {Promise} A promise that resolves to the Ethereum transaction receipt.
*/
async registerProposer(url) {
async registerProposer(url, stake) {
const res = await axios.post(`${this.optimistBaseUrl}/proposer/register`, {
address: this.ethereumAddress,
url,
Expand All @@ -720,7 +721,7 @@ class Nf3 {
const receipt = await this.submitTransaction(
res.data.txDataToSign,
this.proposersContractAddress,
this.PROPOSER_BOND,
stake,
);
resolve(receipt);
} catch (err) {
Expand Down Expand Up @@ -775,7 +776,7 @@ class Nf3 {
try {
const receipt = await this.submitTransaction(
res.data.txDataToSign,
this.proposersContractAddress,
this.stateContractAddress,
0,
);
resolve(receipt);
Expand All @@ -787,14 +788,14 @@ class Nf3 {
}

/**
Withdraw the bond left by the proposer.
It will use the address of the Ethereum Signing key that is holds to withdraw the bond.
Withdraw the stake left by the proposer.
It will use the address of the Ethereum Signing key that is holds to withdraw the stake.
@method
@async
@returns {Promise} A promise that resolves to the Ethereum transaction receipt.
*/
async withdrawBond() {
const res = await axios.post(`${this.optimistBaseUrl}/proposer/withdrawBond`, {
async withdrawStake() {
const res = await axios.post(`${this.optimistBaseUrl}/proposer/withdrawStake`, {
address: this.ethereumAddress,
});
return new Promise((resolve, reject) => {
Expand All @@ -813,6 +814,35 @@ class Nf3 {
});
}

/**
Get all the proposer pending payments.
@method
@async
@returns {array} A promise that resolves to the Ethereum transaction receipt.
*/
async getProposerPendingPayments() {
const res = await axios.get(`${this.optimistBaseUrl}/proposer/pending-payments`, {
params: {
proposer: this.ethereumAddress,
},
});
return res.data;
}

/**
Request block payment.
@method
@async
@return {Promise} A promise that resolves to an axios response.
*/
async requestBlockPayment(blockHash) {
const res = await axios.post(`${this.optimistBaseUrl}/proposer/payment`, {
address: this.ethereumAddress,
blockHash,
});
return this.submitTransaction(res.data.txDataToSign, this.shieldContractAddress, 0);
}

/**
Get current proposer
@method
Expand Down Expand Up @@ -840,9 +870,10 @@ class Nf3 {
@method
@async
@param {string} Proposer REST API URL with format https://xxxx.xxx.xx
@param {number} stake - amount to stake
@returns {array} A promise that resolves to the Ethereum transaction receipt.
*/
async updateProposer(url) {
async updateProposer(url, stake) {
const res = await axios.post(`${this.optimistBaseUrl}/proposer/update`, {
address: this.ethereumAddress,
url,
Expand All @@ -854,7 +885,7 @@ class Nf3 {
const receipt = await this.submitTransaction(
res.data.txDataToSign,
this.proposersContractAddress,
0,
stake,
);
resolve(receipt);
} catch (err) {
Expand Down
3 changes: 2 additions & 1 deletion config/default.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,8 @@ module.exports = {
gasCosts: 80000000000000000,
fee: 1,
BLOCK_STAKE: 1, // 1 wei
bond: 10, // 10 wei
MINIMUM_STAKE: 100, // 100 wei
ROTATE_PROPOSER_BLOCKS: 20,
txPerBlock: process.env.TRANSACTIONS_PER_BLOCK || 2,
signingKeys: {
walletTest:
Expand Down
9 changes: 6 additions & 3 deletions nightfall-deployer/contracts/Config.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@ import './Ownable.sol';
import './Structures.sol';

contract Config is Ownable, Structures {
uint256 constant REGISTRATION_BOND = 10 wei; // TODO owner can update
uint256 constant MINIMUM_STAKE = 100 wei; // TODO owner can update
uint256 constant BLOCK_STAKE = 1 wei;
uint256 constant ROTATE_PROPOSER_BLOCKS = 4;
uint256 constant COOLING_OFF_PERIOD = 1 weeks;
uint256 constant ROTATE_PROPOSER_BLOCKS = 20;
uint256 constant CHALLENGE_PERIOD = 1 weeks;
bytes32 constant ZERO = bytes32(0);
uint256 constant TRANSACTIONS_PER_BLOCK = 32;
uint256 constant BLOCK_STRUCTURE_SLOTS = 7;
uint256 constant TRANSACTION_STRUCTURE_SLOTS = 24;
uint256 constant VALUE_PER_SLOT = 10; // amount of value of a slot
uint256 constant PROPOSER_SET_COUNT = 5; // number of slots to pop after shuffling slots that will build the proposer set
uint256 constant SPRINTS_IN_SPAN = 5; // number of sprints of a span

address bootProposer;
address bootChallenger;
Expand Down
Loading

0 comments on commit e943197

Please sign in to comment.